diff options
author | Peter Zhu <[email protected]> | 2025-02-18 12:58:40 -0500 |
---|---|---|
committer | Peter Zhu <[email protected]> | 2025-02-19 09:47:28 -0500 |
commit | 7b6e07ea93cfc42bfb8bdf875555d2c8c7d5e507 (patch) | |
tree | b798642d9ecae2c2355a96339f6f2c6f7b329fa4 | |
parent | 273e35cdcc04c6c68066a963157896472a2d1eb3 (diff) |
Add rb_gc_object_metadata API
This function replaces the internal rb_obj_gc_flags API. rb_gc_object_metadata
returns an array of name and value pairs, with the last element having
0 for the name.
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/12777
-rw-r--r-- | ext/objspace/objspace_dump.c | 29 | ||||
-rw-r--r-- | gc.c | 13 | ||||
-rw-r--r-- | gc/default/default.c | 41 | ||||
-rw-r--r-- | gc/gc_impl.h | 10 | ||||
-rw-r--r-- | internal/gc.h | 10 |
5 files changed, 67 insertions, 36 deletions
diff --git a/ext/objspace/objspace_dump.c b/ext/objspace/objspace_dump.c index 2b98214f69..139612526f 100644 --- a/ext/objspace/objspace_dump.c +++ b/ext/objspace/objspace_dump.c @@ -385,8 +385,6 @@ dump_object(VALUE obj, struct dump_config *dc) size_t memsize; struct allocation_info *ainfo = objspace_lookup_allocation_info(obj); rb_io_t *fptr; - ID flags[RB_OBJ_GC_FLAGS_MAX]; - size_t n, i; ID mid; if (SPECIAL_CONST_P(obj)) { @@ -643,14 +641,24 @@ dump_object(VALUE obj, struct dump_config *dc) dump_append_lu(dc, RB_NUM2ULONG(rb_obj_id(obj))); } - if ((n = rb_obj_gc_flags(obj, flags, sizeof(flags))) > 0) { - dump_append(dc, ", \"flags\":{"); - for (i=0; i<n; i++) { - dump_append(dc, "\""); - dump_append(dc, rb_id2name(flags[i])); - dump_append(dc, "\":true"); - if (i != n-1) dump_append(dc, ", "); + struct rb_gc_object_metadata_entry *gc_metadata = rb_gc_object_metadata(obj); + for (int i = 0; gc_metadata[i].name != 0; i++) { + if (i == 0) { + dump_append(dc, ", \"flags\":{"); + } + else { + dump_append(dc, ", "); } + + dump_append(dc, "\""); + dump_append(dc, rb_id2name(gc_metadata[i].name)); + dump_append(dc, "\":"); + dump_append_special_const(dc, gc_metadata[i].val); + } + + /* If rb_gc_object_metadata had any entries, we need to close the opening + * `"flags":{`. */ + if (gc_metadata[0].name != 0) { dump_append(dc, "}"); } @@ -883,7 +891,4 @@ Init_objspace_dump(VALUE rb_mObjSpace) rb_define_module_function(rb_mObjSpace, "_dump", objspace_dump, 2); rb_define_module_function(rb_mObjSpace, "_dump_all", objspace_dump_all, 4); rb_define_module_function(rb_mObjSpace, "_dump_shapes", objspace_dump_shapes, 2); - - /* force create static IDs */ - rb_obj_gc_flags(rb_mObjSpace, 0, 0); } @@ -678,7 +678,7 @@ typedef struct gc_function_map { VALUE (*stat_heap)(void *objspace_ptr, VALUE heap_name, VALUE hash_or_sym); const char *(*active_gc_name)(void); // Miscellaneous - size_t (*obj_flags)(void *objspace_ptr, VALUE obj, ID* flags, size_t max); + struct rb_gc_object_metadata_entry *(*object_metadata)(void *objspace_ptr, VALUE obj); bool (*pointer_to_heap_p)(void *objspace_ptr, const void *ptr); bool (*garbage_object_p)(void *objspace_ptr, VALUE obj); void (*set_event_hook)(void *objspace_ptr, const rb_event_flag_t event); @@ -855,7 +855,7 @@ ruby_modular_gc_init(void) load_modular_gc_func(stat_heap); load_modular_gc_func(active_gc_name); // Miscellaneous - load_modular_gc_func(obj_flags); + load_modular_gc_func(object_metadata); load_modular_gc_func(pointer_to_heap_p); load_modular_gc_func(garbage_object_p); load_modular_gc_func(set_event_hook); @@ -938,7 +938,7 @@ ruby_modular_gc_init(void) # define rb_gc_impl_stat_heap rb_gc_functions.stat_heap # define rb_gc_impl_active_gc_name rb_gc_functions.active_gc_name // Miscellaneous -# define rb_gc_impl_obj_flags rb_gc_functions.obj_flags +# define rb_gc_impl_object_metadata rb_gc_functions.object_metadata # define rb_gc_impl_pointer_to_heap_p rb_gc_functions.pointer_to_heap_p # define rb_gc_impl_garbage_object_p rb_gc_functions.garbage_object_p # define rb_gc_impl_set_event_hook rb_gc_functions.set_event_hook @@ -2955,11 +2955,10 @@ rb_gc_active_gc_name(void) return gc_name; } -// TODO: rearchitect this function to work for a generic GC -size_t -rb_obj_gc_flags(VALUE obj, ID* flags, size_t max) +struct rb_gc_object_metadata_entry * +rb_gc_object_metadata(VALUE obj) { - return rb_gc_impl_obj_flags(rb_gc_get_objspace(), obj, flags, max); + return rb_gc_impl_object_metadata(rb_gc_get_objspace(), obj); } /* GC */ diff --git a/gc/default/default.c b/gc/default/default.c index 4cf39a0331..03427f51a1 100644 --- a/gc/default/default.c +++ b/gc/default/default.c @@ -6189,33 +6189,46 @@ rb_gc_impl_writebarrier_remember(void *objspace_ptr, VALUE obj) } } -// TODO: rearchitect this function to work for a generic GC -size_t -rb_gc_impl_obj_flags(void *objspace_ptr, VALUE obj, ID* flags, size_t max) +#define RB_GC_OBJECT_METADATA_ENTRY_COUNT 5 +static struct rb_gc_object_metadata_entry object_metadata_entries[RB_GC_OBJECT_METADATA_ENTRY_COUNT + 1]; + +struct rb_gc_object_metadata_entry * +rb_gc_impl_object_metadata(void *objspace_ptr, VALUE obj) { rb_objspace_t *objspace = objspace_ptr; size_t n = 0; - static ID ID_marked; - static ID ID_wb_protected, ID_old, ID_marking, ID_uncollectible, ID_pinned; + static ID ID_wb_protected, ID_old, ID_uncollectible, ID_marking, ID_marked, ID_pinned; if (!ID_marked) { #define I(s) ID_##s = rb_intern(#s); - I(marked); I(wb_protected); I(old); - I(marking); I(uncollectible); + I(marking); + I(marked); I(pinned); #undef I } - if (RVALUE_WB_UNPROTECTED(objspace, obj) == 0 && n < max) flags[n++] = ID_wb_protected; - if (RVALUE_OLD_P(objspace, obj) && n < max) flags[n++] = ID_old; - if (RVALUE_UNCOLLECTIBLE(objspace, obj) && n < max) flags[n++] = ID_uncollectible; - if (RVALUE_MARKING(objspace, obj) && n < max) flags[n++] = ID_marking; - if (RVALUE_MARKED(objspace, obj) && n < max) flags[n++] = ID_marked; - if (RVALUE_PINNED(objspace, obj) && n < max) flags[n++] = ID_pinned; - return n; +#define SET_ENTRY(na, v) do { \ + GC_ASSERT(n <= RB_GC_OBJECT_METADATA_ENTRY_COUNT); \ + object_metadata_entries[n].name = ID_##na; \ + object_metadata_entries[n].val = v; \ + n++; \ +} while (0) + + if (!RVALUE_WB_UNPROTECTED(objspace, obj)) SET_ENTRY(wb_protected, Qtrue); + if (RVALUE_OLD_P(objspace, obj)) SET_ENTRY(old, Qtrue); + if (RVALUE_UNCOLLECTIBLE(objspace, obj)) SET_ENTRY(uncollectible, Qtrue); + if (RVALUE_MARKING(objspace, obj)) SET_ENTRY(marking, Qtrue); + if (RVALUE_MARKED(objspace, obj)) SET_ENTRY(marked, Qtrue); + if (RVALUE_PINNED(objspace, obj)) SET_ENTRY(pinned, Qtrue); + + object_metadata_entries[n].name = 0; + object_metadata_entries[n].val = 0; +#undef SET_ENTRY + + return object_metadata_entries; } void * diff --git a/gc/gc_impl.h b/gc/gc_impl.h index edff242bd0..5e8d209432 100644 --- a/gc/gc_impl.h +++ b/gc/gc_impl.h @@ -10,6 +10,14 @@ */ #include "ruby/ruby.h" +#ifndef RB_GC_OBJECT_METADATA_ENTRY_DEFINED +# define RB_GC_OBJECT_METADATA_ENTRY_DEFINED +struct rb_gc_object_metadata_entry { + ID name; + VALUE val; +}; +#endif + #ifdef BUILDING_MODULAR_GC # define GC_IMPL_FN #else @@ -108,7 +116,7 @@ GC_IMPL_FN VALUE rb_gc_impl_stat(void *objspace_ptr, VALUE hash_or_sym); GC_IMPL_FN VALUE rb_gc_impl_stat_heap(void *objspace_ptr, VALUE heap_name, VALUE hash_or_sym); GC_IMPL_FN const char *rb_gc_impl_active_gc_name(void); // Miscellaneous -GC_IMPL_FN size_t rb_gc_impl_obj_flags(void *objspace_ptr, VALUE obj, ID* flags, size_t max); +GC_IMPL_FN struct rb_gc_object_metadata_entry *rb_gc_impl_object_metadata(void *objspace_ptr, VALUE obj); GC_IMPL_FN bool rb_gc_impl_pointer_to_heap_p(void *objspace_ptr, const void *ptr); GC_IMPL_FN bool rb_gc_impl_garbage_object_p(void *objspace_ptr, VALUE obj); GC_IMPL_FN void rb_gc_impl_set_event_hook(void *objspace_ptr, const rb_event_flag_t event); diff --git a/internal/gc.h b/internal/gc.h index 1407f4b988..4e9b4554e8 100644 --- a/internal/gc.h +++ b/internal/gc.h @@ -127,7 +127,13 @@ struct rb_objspace; /* in vm_core.h */ rb_wb_protected_newobj_of((ec ? ec : GET_EC()), (c), (f) & ~FL_WB_PROTECTED, s) : \ rb_wb_unprotected_newobj_of((c), (f), s)) -#define RB_OBJ_GC_FLAGS_MAX 6 /* used in ext/objspace */ +#ifndef RB_GC_OBJECT_METADATA_ENTRY_DEFINED +# define RB_GC_OBJECT_METADATA_ENTRY_DEFINED +struct rb_gc_object_metadata_entry { + ID name; + VALUE val; +}; +#endif #ifndef USE_UNALIGNED_MEMBER_ACCESS # define UNALIGNED_MEMBER_ACCESS(expr) (expr) @@ -244,7 +250,7 @@ const char *rb_objspace_data_type_name(VALUE obj); VALUE rb_wb_protected_newobj_of(struct rb_execution_context_struct *, VALUE, VALUE, size_t); VALUE rb_wb_unprotected_newobj_of(VALUE, VALUE, size_t); size_t rb_obj_memsize_of(VALUE); -size_t rb_obj_gc_flags(VALUE, ID[], size_t); +struct rb_gc_object_metadata_entry *rb_gc_object_metadata(VALUE obj); void rb_gc_mark_values(long n, const VALUE *values); void rb_gc_mark_vm_stack_values(long n, const VALUE *values); void rb_gc_update_values(long n, VALUE *values); |