diff options
Diffstat (limited to 'ext/objspace/object_tracing.c')
| -rw-r--r-- | ext/objspace/object_tracing.c | 49 |
1 files changed, 35 insertions, 14 deletions
diff --git a/ext/objspace/object_tracing.c b/ext/objspace/object_tracing.c index c1c93c51f5..1c18bf02ee 100644 --- a/ext/objspace/object_tracing.c +++ b/ext/objspace/object_tracing.c @@ -53,6 +53,14 @@ make_unique_str(st_table *tbl, const char *str, long len) } } +static int +delete_unique_str_dec(st_data_t *key, st_data_t *value, st_data_t arg, int existing) +{ + assert(existing); + *value = arg; + return ST_CONTINUE; +} + static void delete_unique_str(st_table *tbl, const char *str) { @@ -66,7 +74,7 @@ delete_unique_str(st_table *tbl, const char *str) ruby_xfree((char *)n); } else { - st_insert(tbl, (st_data_t)str, n-1); + st_update(tbl, (st_data_t)str, delete_unique_str_dec, (st_data_t)(n-1)); } } } @@ -83,7 +91,7 @@ newobj_i(VALUE tpval, void *data) VALUE klass = rb_tracearg_defined_class(tparg); struct allocation_info *info; const char *path_cstr = RTEST(path) ? make_unique_str(arg->str_table, RSTRING_PTR(path), RSTRING_LEN(path)) : 0; - VALUE class_path = (RTEST(klass) && !OBJ_FROZEN(klass)) ? rb_class_path_cached(klass) : Qnil; + VALUE class_path = (RTEST(klass) && !OBJ_FROZEN(klass)) ? rb_mod_name(klass) : Qnil; const char *class_path_cstr = RTEST(class_path) ? make_unique_str(arg->str_table, RSTRING_PTR(class_path), RSTRING_LEN(class_path)) : 0; st_data_t v; @@ -190,22 +198,25 @@ allocation_info_tracer_memsize(const void *ptr) } static int -hash_foreach_should_replace_key(st_data_t key, st_data_t value, st_data_t argp, int error) +allocation_info_tracer_compact_update_object_table_i(st_data_t key, st_data_t value, st_data_t data) { - VALUE allocated_object; + st_table *table = (st_table *)data; - allocated_object = (VALUE)value; - if (allocated_object != rb_gc_location(allocated_object)) { - return ST_REPLACE; + if (!rb_gc_pointer_to_heap_p(key)) { + struct allocation_info *info = (struct allocation_info *)value; + xfree(info); + return ST_DELETE; } - return ST_CONTINUE; -} + if (key != rb_gc_location(key)) { + DURING_GC_COULD_MALLOC_REGION_START(); + { + st_insert(table, rb_gc_location(key), value); + } + DURING_GC_COULD_MALLOC_REGION_END(); -static int -hash_replace_key(st_data_t *key, st_data_t *value, st_data_t argp, int existing) -{ - *key = rb_gc_location((VALUE)*key); + return ST_DELETE; + } return ST_CONTINUE; } @@ -216,7 +227,10 @@ allocation_info_tracer_compact(void *ptr) struct traceobj_arg *trace_arg = (struct traceobj_arg *)ptr; if (trace_arg->object_table && - st_foreach_with_replace(trace_arg->object_table, hash_foreach_should_replace_key, hash_replace_key, 0)) { + st_foreach( + trace_arg->object_table, + allocation_info_tracer_compact_update_object_table_i, + (st_data_t)trace_arg->object_table)) { rb_raise(rb_eRuntimeError, "hash modified during iteration"); } } @@ -399,6 +413,13 @@ object_allocations_reporter(FILE *out, void *ptr) fprintf(out, "== object_allocations_reporter: END\n"); } +/* + * call-seq: trace_object_allocations_debug_start + * + * Starts tracing object allocations for GC debugging. + * If you encounter the BUG "... is T_NONE" (and so on) on your + * application, please try this method at the beginning of your app. + */ static VALUE trace_object_allocations_debug_start(VALUE self) { |
