]> granicus.if.org Git - gc/blob - fnlz_mlc.c
Travis CI: Remove building redundant check-cpp target of Makefile.direct
[gc] / fnlz_mlc.c
1 /*
2  * Copyright (c) 2011 by Hewlett-Packard Company.  All rights reserved.
3  *
4  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
5  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
6  *
7  * Permission is hereby granted to use or copy this program
8  * for any purpose,  provided the above notices are retained on all copies.
9  * Permission to modify the code and to distribute modified code is granted,
10  * provided the above notices are retained, and a notice that the code was
11  * modified is included with the above copyright notice.
12  *
13  */
14
15 #include "private/gc_priv.h"
16
17 #ifdef ENABLE_DISCLAIM
18
19 #include "gc_disclaim.h"
20 #include "gc_inline.h" /* for GC_malloc_kind */
21 #include "private/dbg_mlc.h" /* for oh type */
22
23 STATIC int GC_finalized_kind = 0;
24
25 #if defined(KEEP_BACK_PTRS) || defined(MAKE_BACK_GRAPH)
26   /* The first bit is already used for a debug purpose. */
27 # define FINALIZER_CLOSURE_FLAG 0x2
28 #else
29 # define FINALIZER_CLOSURE_FLAG 0x1
30 #endif
31
32 STATIC int GC_CALLBACK GC_finalized_disclaim(void *obj)
33 {
34     word fc_word = *(word *)obj;
35
36     if ((fc_word & FINALIZER_CLOSURE_FLAG) != 0) {
37        /* The disclaim function may be passed fragments from the        */
38        /* free-list, on which it should not run finalization.           */
39        /* To recognize this case, we use the fact that the first word   */
40        /* on such fragments is always multiple of 4 (a link to the next */
41        /* fragment, or NULL).  If it is desirable to have a finalizer   */
42        /* which does not use the first word for storing finalization    */
43        /* info, GC_reclaim_with_finalization must be extended to clear  */
44        /* fragments so that the assumption holds for the selected word. */
45         const struct GC_finalizer_closure *fc
46                         = (struct GC_finalizer_closure *)(fc_word
47                                         & ~(word)FINALIZER_CLOSURE_FLAG);
48         GC_ASSERT(!GC_find_leak);
49         (*fc->proc)((word *)obj + 1, fc->cd);
50     }
51     return 0;
52 }
53
54 GC_API void GC_CALL GC_init_finalized_malloc(void)
55 {
56     DCL_LOCK_STATE;
57
58     GC_init();  /* In case it's not already done.       */
59     LOCK();
60     if (GC_finalized_kind != 0) {
61         UNLOCK();
62         return;
63     }
64
65     /* The finalizer closure is placed in the first word in order to    */
66     /* use the lower bits to distinguish live objects from objects on   */
67     /* the free list.  The downside of this is that we need one-word    */
68     /* offset interior pointers, and that GC_base does not return the   */
69     /* start of the user region.                                        */
70     GC_register_displacement_inner(sizeof(word));
71
72     /* And, the pointer to the finalizer closure object itself is       */
73     /* displaced due to baking in this indicator.                       */
74     GC_register_displacement_inner(FINALIZER_CLOSURE_FLAG);
75     GC_register_displacement_inner(sizeof(oh) + FINALIZER_CLOSURE_FLAG);
76
77     GC_finalized_kind = GC_new_kind_inner(GC_new_free_list_inner(),
78                                           GC_DS_LENGTH, TRUE, TRUE);
79     GC_ASSERT(GC_finalized_kind != 0);
80     GC_register_disclaim_proc(GC_finalized_kind, GC_finalized_disclaim, TRUE);
81     UNLOCK();
82 }
83
84 GC_API void GC_CALL GC_register_disclaim_proc(int kind, GC_disclaim_proc proc,
85                                               int mark_unconditionally)
86 {
87     GC_ASSERT((unsigned)kind < MAXOBJKINDS);
88     GC_ASSERT(NONNULL_ARG_NOT_NULL(proc));
89     if (!EXPECT(GC_find_leak, FALSE)) {
90         GC_obj_kinds[kind].ok_disclaim_proc = proc;
91         GC_obj_kinds[kind].ok_mark_unconditionally =
92                                         (GC_bool)mark_unconditionally;
93     }
94 }
95
96 GC_API GC_ATTR_MALLOC void * GC_CALL GC_finalized_malloc(size_t lb,
97                                 const struct GC_finalizer_closure *fclos)
98 {
99     word *op;
100
101     GC_ASSERT(GC_finalized_kind != 0);
102     GC_ASSERT(NONNULL_ARG_NOT_NULL(fclos));
103     GC_ASSERT(((word)fclos & FINALIZER_CLOSURE_FLAG) == 0);
104     op = (word *)GC_malloc_kind(SIZET_SAT_ADD(lb, sizeof(word)),
105                                 GC_finalized_kind);
106     if (EXPECT(NULL == op, FALSE))
107         return NULL;
108     *op = (word)fclos | FINALIZER_CLOSURE_FLAG;
109     GC_dirty(op);
110     REACHABLE_AFTER_DIRTY(fclos);
111     return op + 1;
112 }
113
114 #endif /* ENABLE_DISCLAIM */