/** * Exception allocation, cloning, and release compiler support routines. * * Copyright: Copyright (c) 2017 by D Language Foundation * License: Distributed under the * $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0). * (See accompanying file LICENSE) * Authors: Walter Bright * Source: $(DRUNTIMESRC rt/_ehalloc.d) */ module rt.ehalloc; //debug = PRINTF; debug(PRINTF) { import core.stdc.stdio; } /******************************************** * Delete exception instance `t` from the exception pool. * Must have been allocated with `_d_newThrowable()`. * This is meant to be called at the close of a catch block. * It's nothrow because otherwise any function with a catch block could * not be nothrow. * Input: * t = Throwable */ nothrow extern (C) void _d_delThrowable(Throwable t) { if (t) { debug(PRINTF) printf("_d_delThrowable(%p)\n", t); /* If allocated by the GC, don't free it. * Let the GC handle it. * Supporting this is necessary while transitioning * to this new scheme for allocating exceptions. */ auto refcount = t.refcount(); if (refcount == 0) return; // it was allocated by the GC if (refcount == 1) assert(0); // no zombie objects t.refcount() = --refcount; if (refcount > 1) return; TypeInfo_Class **pc = cast(TypeInfo_Class **)t; if (*pc) { TypeInfo_Class ci = **pc; if (!(ci.m_flags & TypeInfo_Class.ClassFlags.noPointers)) { // Inform the GC about the pointers in the object instance import core.memory : GC; GC.removeRange(cast(void*) t); } } try { import rt.lifetime : rt_finalize; rt_finalize(cast(void*) t); } catch (Throwable t) { assert(0); // should never happen since Throwable.~this() is nothrow } import core.stdc.stdlib : free; debug(PRINTF) printf("free(%p)\n", t); free(cast(void*) t); } }