aboutsummaryrefslogtreecommitdiff
path: root/libphobos/libdruntime/rt/ehalloc.d
diff options
context:
space:
mode:
Diffstat (limited to 'libphobos/libdruntime/rt/ehalloc.d')
-rw-r--r--libphobos/libdruntime/rt/ehalloc.d125
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);
+ }
+}