2 * Copyright (c) 2011 by Hewlett-Packard Company. All rights reserved.
4 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
5 * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
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.
15 #include "private/gc_priv.h"
17 #ifdef ENABLE_DISCLAIM
19 #include "gc_disclaim.h"
20 #include "gc_inline.h" /* for GC_malloc_kind */
21 #include "private/dbg_mlc.h" /* for oh type */
23 STATIC int GC_finalized_kind = 0;
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
29 # define FINALIZER_CLOSURE_FLAG 0x1
32 STATIC int GC_CALLBACK GC_finalized_disclaim(void *obj)
34 word fc_word = *(word *)obj;
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);
54 GC_API void GC_CALL GC_init_finalized_malloc(void)
58 GC_init(); /* In case it's not already done. */
60 if (GC_finalized_kind != 0) {
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));
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);
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);
84 GC_API void GC_CALL GC_register_disclaim_proc(int kind, GC_disclaim_proc proc,
85 int mark_unconditionally)
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;
96 GC_API GC_ATTR_MALLOC void * GC_CALL GC_finalized_malloc(size_t lb,
97 const struct GC_finalizer_closure *fclos)
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)),
106 if (EXPECT(NULL == op, FALSE))
108 *op = (word)fclos | FINALIZER_CLOSURE_FLAG;
110 REACHABLE_AFTER_DIRTY(fclos);
114 #endif /* ENABLE_DISCLAIM */