diff options
Diffstat (limited to 'libphobos/libdruntime/rt/ehalloc.d')
-rw-r--r-- | libphobos/libdruntime/rt/ehalloc.d | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/libphobos/libdruntime/rt/ehalloc.d b/libphobos/libdruntime/rt/ehalloc.d new file mode 100644 index 0000000..1dcd69a --- /dev/null +++ b/libphobos/libdruntime/rt/ehalloc.d @@ -0,0 +1,125 @@ +/** + * 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; +} + +/********************************************** + * Allocate an exception of type `ci` from the exception pool. + * It has the same interface as `rt.lifetime._d_newclass()`. + * The class type must be Throwable or derived from it, + * and cannot be a COM or C++ class. The compiler must enforce + * this. + * Returns: + * default initialized instance of the type + */ + +extern (C) Throwable _d_newThrowable(const TypeInfo_Class ci) +{ + debug(PRINTF) printf("_d_newThrowable(ci = %p, %s)\n", ci, cast(char *)ci.name); + + assert(!(ci.m_flags & TypeInfo_Class.ClassFlags.isCOMclass)); + assert(!(ci.m_flags & TypeInfo_Class.ClassFlags.isCPPclass)); + + import core.stdc.stdlib : malloc; + auto init = ci.initializer; + void* p = malloc(init.length); + if (!p) + { + import core.exception : onOutOfMemoryError; + onOutOfMemoryError(); + } + + debug(PRINTF) printf(" p = %p\n", p); + + // initialize it + p[0 .. init.length] = init[]; + + if (!(ci.m_flags & TypeInfo_Class.ClassFlags.noPointers)) + { + // Inform the GC about the pointers in the object instance + import core.memory : GC; + + GC.addRange(p, init.length, ci); + } + + debug(PRINTF) printf("initialization done\n"); + Throwable t = cast(Throwable)p; + t.refcount() = 1; + return t; +} + + +/******************************************** + * 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); + } +} |