aboutsummaryrefslogtreecommitdiff
path: root/libphobos/libdruntime/rt/ehalloc.d
blob: 65f92e3d015a5b7f2961589b1342910889665ab9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
/**
 * 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);
    }
}