1 /**
2  * Exception allocation, cloning, and release compiler support routines.
3  *
4  * Copyright: Copyright (c) 2017 by D Language Foundation
5  * License: Distributed under the
6  *      $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
7  *    (See accompanying file LICENSE)
8  * Authors: Walter Bright
9  * Source: $(DRUNTIMESRC rt/_ehalloc.d)
10  */
11 
12 module rt.ehalloc;
13 
14 //debug = PRINTF;
15 
16 debug(PRINTF)
17 {
18     import core.stdc.stdio;
19 }
20 
21 
22 /********************************************
23  * Delete exception instance `t` from the exception pool.
24  * Must have been allocated with `_d_newThrowable()`.
25  * This is meant to be called at the close of a catch block.
26  * It's nothrow because otherwise any function with a catch block could
27  * not be nothrow.
28  * Input:
29  *      t = Throwable
30  */
31 
32 nothrow extern (C) void _d_delThrowable(Throwable t)
33 {
34     if (t)
35     {
36         debug(PRINTF) printf("_d_delThrowable(%p)\n", t);
37 
38         /* If allocated by the GC, don't free it.
39          * Let the GC handle it.
40          * Supporting this is necessary while transitioning
41          * to this new scheme for allocating exceptions.
42          */
43         auto refcount = t.refcount();
44         if (refcount == 0)
45             return;     // it was allocated by the GC
46 
47         if (refcount == 1)
48             assert(0);  // no zombie objects
49 
50         t.refcount() = --refcount;
51         if (refcount > 1)
52             return;
53 
54         TypeInfo_Class **pc = cast(TypeInfo_Class **)t;
55         if (*pc)
56         {
57             TypeInfo_Class ci = **pc;
58 
59             if (!(ci.m_flags & TypeInfo_Class.ClassFlags.noPointers))
60             {
61                 // Inform the GC about the pointers in the object instance
62                 import core.memory : GC;
63                 GC.removeRange(cast(void*) t);
64             }
65         }
66 
67         try
68         {
69             import rt.lifetime : rt_finalize;
70             rt_finalize(cast(void*) t);
71         }
72         catch (Throwable t)
73         {
74             assert(0);  // should never happen since Throwable.~this() is nothrow
75         }
76         import core.stdc.stdlib : free;
77         debug(PRINTF) printf("free(%p)\n", t);
78         free(cast(void*) t);
79     }
80 }