Skip to content

Commit 55f5d07

Browse files
Move finalizer flag from FL_FINALIZE to object metadata
This commit moves the finalizer flag from using the FL_FINALIZE object flag to using a dedicated bit in the object metadata structure. This change frees up the FL_FINALIZE flag bit (bit 7) for potential reuse in the future.
1 parent 6f7e61b commit 55f5d07

3 files changed

Lines changed: 41 additions & 32 deletions

File tree

gc.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,7 @@ typedef struct gc_function_map {
657657
void (*each_objects)(void *objspace_ptr, int (*callback)(void *, void *, size_t, void *), void *data);
658658
void (*each_object)(void *objspace_ptr, void (*func)(VALUE obj, void *data), void *data);
659659
// Finalizers
660+
bool (*has_finalizer)(VALUE obj);
660661
void (*make_zombie)(void *objspace_ptr, VALUE obj, void (*dfree)(void *), void *data);
661662
VALUE (*define_finalizer)(void *objspace_ptr, VALUE obj, VALUE block);
662663
void (*undefine_finalizer)(void *objspace_ptr, VALUE obj);
@@ -875,6 +876,7 @@ ruby_modular_gc_init(void)
875876
# define rb_gc_impl_set_params rb_gc_functions.set_params
876877
# define rb_gc_impl_init rb_gc_functions.init
877878
# define rb_gc_impl_heap_sizes rb_gc_functions.heap_sizes
879+
# define rb_gc_impl_has_finalizer rb_gc_functions.has_finalizer
878880
// Shutdown
879881
# define rb_gc_impl_shutdown_free_objects rb_gc_functions.shutdown_free_objects
880882
# define rb_gc_impl_objspace_free rb_gc_functions.objspace_free
@@ -1457,7 +1459,7 @@ rb_gc_obj_free(void *objspace, VALUE obj)
14571459
BUILTIN_TYPE(obj), (void*)obj, RBASIC(obj)->flags);
14581460
}
14591461

1460-
if (FL_TEST(obj, FL_FINALIZE)) {
1462+
if (rb_gc_impl_has_finalizer(obj)) {
14611463
rb_gc_impl_make_zombie(objspace, obj, 0, 0);
14621464
return FALSE;
14631465
}

gc/default/default.c

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -712,6 +712,7 @@ struct free_slot {
712712
struct object_metadata {
713713
unsigned char age : RVALUE_AGE_BIT_COUNT;
714714
unsigned char seen_obj_id : 1;
715+
unsigned char has_finalizer : 1;
715716
};
716717
STATIC_ASSERT(SIZEOF_OBJECT_METADATA, sizeof(struct object_metadata) == 1);
717718

@@ -2629,15 +2630,13 @@ rb_gc_impl_pointer_to_heap_p(void *objspace_ptr, const void *ptr)
26292630
return is_pointer_to_heap(objspace_ptr, ptr);
26302631
}
26312632

2632-
#define ZOMBIE_OBJ_KEPT_FLAGS (FL_FINALIZE)
2633-
26342633
void
26352634
rb_gc_impl_make_zombie(void *objspace_ptr, VALUE obj, void (*dfree)(void *), void *data)
26362635
{
26372636
rb_objspace_t *objspace = objspace_ptr;
26382637

26392638
struct RZombie *zombie = RZOMBIE(obj);
2640-
zombie->basic.flags = T_ZOMBIE | (zombie->basic.flags & ZOMBIE_OBJ_KEPT_FLAGS);
2639+
zombie->basic.flags = T_ZOMBIE;
26412640
zombie->dfree = dfree;
26422641
zombie->data = data;
26432642
VALUE prev, next = heap_pages_deferred_final;
@@ -2827,7 +2826,7 @@ rb_gc_impl_define_finalizer(void *objspace_ptr, VALUE obj, VALUE block)
28272826

28282827
GC_ASSERT(!OBJ_FROZEN(obj));
28292828

2830-
RBASIC(obj)->flags |= FL_FINALIZE;
2829+
RVALUE_METADATA(obj)->has_finalizer = 1;
28312830

28322831
if (st_lookup(finalizer_table, obj, &data)) {
28332832
table = (VALUE)data;
@@ -2865,7 +2864,7 @@ rb_gc_impl_undefine_finalizer(void *objspace_ptr, VALUE obj)
28652864

28662865
st_data_t data = obj;
28672866
st_delete(finalizer_table, &data, 0);
2868-
FL_UNSET(obj, FL_FINALIZE);
2867+
RVALUE_METADATA(obj)->has_finalizer = 0;
28692868
}
28702869

28712870
void
@@ -2875,15 +2874,15 @@ rb_gc_impl_copy_finalizer(void *objspace_ptr, VALUE dest, VALUE obj)
28752874
VALUE table;
28762875
st_data_t data;
28772876

2878-
if (!FL_TEST(obj, FL_FINALIZE)) return;
2877+
if (!RVALUE_METADATA(obj)->has_finalizer) return;
28792878

28802879
if (RB_LIKELY(st_lookup(finalizer_table, obj, &data))) {
28812880
table = (VALUE)data;
28822881
st_insert(finalizer_table, dest, table);
2883-
FL_SET(dest, FL_FINALIZE);
2882+
RVALUE_METADATA(dest)->has_finalizer = 1;
28842883
}
28852884
else {
2886-
rb_bug("rb_gc_copy_finalizer: FL_FINALIZE set but not found in finalizer_table: %s", rb_obj_info(obj));
2885+
rb_bug("rb_gc_copy_finalizer: has_finalizer set but not found in finalizer_table: %s", rb_obj_info(obj));
28872886
}
28882887
}
28892888

@@ -2916,18 +2915,25 @@ run_final(rb_objspace_t *objspace, VALUE zombie)
29162915
}
29172916

29182917
st_data_t key = (st_data_t)zombie;
2919-
if (FL_TEST_RAW(zombie, FL_FINALIZE)) {
2920-
FL_UNSET(zombie, FL_FINALIZE);
2918+
bool has_finalizer = RVALUE_METADATA(zombie)->has_finalizer;
2919+
2920+
if (has_finalizer) {
2921+
RVALUE_METADATA(zombie)->has_finalizer = 0;
2922+
29212923
st_data_t table;
29222924
if (st_delete(finalizer_table, &key, &table)) {
29232925
rb_gc_run_obj_finalizer(get_object_id_in_finalizer(objspace, zombie), RARRAY_LEN(table), get_final, (void *)table);
29242926
}
29252927
else {
2926-
rb_bug("FL_FINALIZE flag is set, but finalizers are not found");
2928+
rb_bug("Finalizer metadata is set, but finalizers are not found");
29272929
}
29282930
}
29292931
else {
2930-
GC_ASSERT(!st_lookup(finalizer_table, key, NULL));
2932+
if (st_lookup(finalizer_table, key, NULL)) {
2933+
st_data_t ignore;
2934+
st_delete(finalizer_table, &key, &ignore);
2935+
rb_bug("Finalizer table entry exists but metadata is not set");
2936+
}
29312937
}
29322938
}
29332939

@@ -3067,12 +3073,12 @@ rb_gc_impl_shutdown_call_finalizer_i(st_data_t key, st_data_t val, st_data_t dat
30673073
VALUE obj = (VALUE)key;
30683074
VALUE table = (VALUE)val;
30693075

3070-
GC_ASSERT(RB_FL_TEST(obj, FL_FINALIZE));
3076+
GC_ASSERT(RVALUE_METADATA(obj)->has_finalizer);
30713077
GC_ASSERT(RB_BUILTIN_TYPE(val) == T_ARRAY);
30723078

30733079
rb_gc_run_obj_finalizer(rb_gc_impl_object_id(objspace, obj), RARRAY_LEN(table), get_final, (void *)table);
30743080

3075-
FL_UNSET(obj, FL_FINALIZE);
3081+
RVALUE_METADATA(obj)->has_finalizer = 0;
30763082

30773083
return ST_DELETE;
30783084
}
@@ -5061,15 +5067,16 @@ verify_internal_consistency_i(void *page_start, void *page_end, size_t stride,
50615067
if (BUILTIN_TYPE(obj) == T_ZOMBIE) {
50625068
data->zombie_object_count++;
50635069

5064-
if ((RBASIC(obj)->flags & ~ZOMBIE_OBJ_KEPT_FLAGS) != T_ZOMBIE) {
5070+
if (RBASIC(obj)->flags != T_ZOMBIE) {
50655071
fprintf(stderr, "verify_internal_consistency_i: T_ZOMBIE has extra flags set: %s\n",
50665072
rb_obj_info(obj));
50675073
data->err_count++;
50685074
}
50695075

5070-
if (!!FL_TEST(obj, FL_FINALIZE) != !!st_is_member(finalizer_table, obj)) {
5071-
fprintf(stderr, "verify_internal_consistency_i: FL_FINALIZE %s but %s finalizer_table: %s\n",
5072-
FL_TEST(obj, FL_FINALIZE) ? "set" : "not set", st_is_member(finalizer_table, obj) ? "in" : "not in",
5076+
if (!!RVALUE_METADATA(obj)->has_finalizer != !!st_is_member(finalizer_table, obj)) {
5077+
fprintf(stderr, "verify_internal_consistency_i: Finalizer metadata %s but %s finalizer_table: %s\n",
5078+
RVALUE_METADATA(obj)->has_finalizer ? "set" : "not set",
5079+
st_is_member(finalizer_table, obj) ? "in" : "not in",
50735080
rb_obj_info(obj));
50745081
data->err_count++;
50755082
}
@@ -6202,15 +6209,15 @@ rb_gc_impl_writebarrier_remember(void *objspace_ptr, VALUE obj)
62026209
}
62036210
}
62046211

6205-
#define RB_GC_OBJECT_METADATA_ENTRY_COUNT 7
6212+
#define RB_GC_OBJECT_METADATA_ENTRY_COUNT 8
62066213
static struct rb_gc_object_metadata_entry object_metadata_entries[RB_GC_OBJECT_METADATA_ENTRY_COUNT + 1];
62076214

62086215
struct rb_gc_object_metadata_entry *
62096216
rb_gc_impl_object_metadata(void *objspace_ptr, VALUE obj)
62106217
{
62116218
rb_objspace_t *objspace = objspace_ptr;
62126219
size_t n = 0;
6213-
static ID ID_wb_protected, ID_age, ID_old, ID_uncollectible, ID_marking, ID_marked, ID_pinned, ID_object_id;
6220+
static ID ID_wb_protected, ID_age, ID_old, ID_uncollectible, ID_marking, ID_marked, ID_pinned, ID_object_id, ID_has_finalizer;
62146221

62156222
if (!ID_marked) {
62166223
#define I(s) ID_##s = rb_intern(#s);
@@ -6222,6 +6229,7 @@ rb_gc_impl_object_metadata(void *objspace_ptr, VALUE obj)
62226229
I(marked);
62236230
I(pinned);
62246231
I(object_id);
6232+
I(has_finalizer);
62256233
#undef I
62266234
}
62276235

@@ -6240,6 +6248,7 @@ rb_gc_impl_object_metadata(void *objspace_ptr, VALUE obj)
62406248
if (RVALUE_MARKED(objspace, obj)) SET_ENTRY(marked, Qtrue);
62416249
if (RVALUE_PINNED(objspace, obj)) SET_ENTRY(pinned, Qtrue);
62426250
if (rb_gc_impl_object_id_seen_p(obj)) SET_ENTRY(object_id, rb_obj_id(obj));
6251+
if (RVALUE_METADATA(obj)->has_finalizer) SET_ENTRY(has_finalizer, Qtrue);
62436252

62446253
object_metadata_entries[n].name = 0;
62456254
object_metadata_entries[n].val = 0;
@@ -6248,6 +6257,12 @@ rb_gc_impl_object_metadata(void *objspace_ptr, VALUE obj)
62486257
return object_metadata_entries;
62496258
}
62506259

6260+
bool
6261+
rb_gc_impl_has_finalizer(VALUE obj)
6262+
{
6263+
return RVALUE_METADATA(obj)->has_finalizer;
6264+
}
6265+
62516266
void *
62526267
rb_gc_impl_ractor_cache_alloc(void *objspace_ptr, void *ractor)
62536268
{
@@ -6906,7 +6921,7 @@ gc_is_moveable_obj(rb_objspace_t *objspace, VALUE obj)
69066921
case T_RATIONAL:
69076922
case T_NODE:
69086923
case T_CLASS:
6909-
if (FL_TEST_RAW(obj, FL_FINALIZE)) {
6924+
if (RVALUE_METADATA(obj)->has_finalizer) {
69106925
/* The finalizer table is a numtable. It looks up objects by address.
69116926
* We can't mark the keys in the finalizer table because that would
69126927
* prevent the objects from being collected. This check prevents

include/ruby/internal/fl_type.h

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@
5757

5858
#define FL_SINGLETON RBIMPL_CAST((VALUE)RUBY_FL_SINGLETON) /**< @old{RUBY_FL_SINGLETON} */
5959
#define FL_WB_PROTECTED RBIMPL_CAST((VALUE)RUBY_FL_WB_PROTECTED) /**< @old{RUBY_FL_WB_PROTECTED} */
60-
#define FL_FINALIZE RBIMPL_CAST((VALUE)RUBY_FL_FINALIZE) /**< @old{RUBY_FL_FINALIZE} */
6160
#define FL_TAINT RBIMPL_CAST((VALUE)RUBY_FL_TAINT) /**< @old{RUBY_FL_TAINT} */
6261
#define FL_SHAREABLE RBIMPL_CAST((VALUE)RUBY_FL_SHAREABLE) /**< @old{RUBY_FL_SHAREABLE} */
6362
#define FL_UNTRUSTED RBIMPL_CAST((VALUE)RUBY_FL_UNTRUSTED) /**< @old{RUBY_FL_UNTRUSTED} */
@@ -211,18 +210,11 @@ ruby_fl_type {
211210
RUBY_FL_UNUSED6 = (1<<6),
212211

213212
/**
214-
* This flag has something to do with finalisers. A ruby object can have
215-
* its finaliser, which is another object that evaluates when the target
216-
* object is about to die. This flag is used to denote that there is an
217-
* attached finaliser.
213+
* This flag is no longer in use.
218214
*
219215
* @internal
220-
*
221-
* But honestly, @shyouhei doesn't think this flag should be visible from
222-
* 3rd parties. It must be an implementation detail that they should never
223-
* know. Might better be hidden.
224216
*/
225-
RUBY_FL_FINALIZE = (1<<7),
217+
RUBY_FL_UNUSED7 = (1<<7),
226218

227219
/**
228220
* @deprecated This flag once was a thing back in the old days, but makes

0 commit comments

Comments
 (0)