From ef19e51d907928a7aac220992744f79adbeb0424 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 28 Oct 2019 16:10:48 -0700 Subject: [PATCH] Wrap "call data" with an IMEMO object Currently, compaction will invalidate all inline caches. I would like to update the compactor to fix references in inline caches. Unfortunately this static variable is not reachable from the GC. This commit introduces a "call data" imemo type to wrap the call data. This way the GC can see the static call data variable and update its references. --- ext/objspace/objspace.c | 1 + ext/objspace/objspace_dump.c | 1 + gc.c | 7 +++++++ internal.h | 9 ++++++++- 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/ext/objspace/objspace.c b/ext/objspace/objspace.c index 927c5b543c..3247245efb 100644 --- a/ext/objspace/objspace.c +++ b/ext/objspace/objspace.c @@ -634,6 +634,7 @@ count_imemo_objects(int argc, VALUE *argv, VALUE self) imemo_type_ids[8] = rb_intern("imemo_tmpbuf"); imemo_type_ids[9] = rb_intern("imemo_ast"); imemo_type_ids[10] = rb_intern("imemo_parser_strterm"); + imemo_type_ids[11] = rb_intern("imemo_call_data"); } rb_objspace_each_objects(count_imemo_objects_i, (void *)hash); diff --git a/ext/objspace/objspace_dump.c b/ext/objspace/objspace_dump.c index 5fa9d98e38..dd571600b8 100644 --- a/ext/objspace/objspace_dump.c +++ b/ext/objspace/objspace_dump.c @@ -208,6 +208,7 @@ imemo_name(int imemo) TYPE_STR(tmpbuf); TYPE_STR(ast); TYPE_STR(parser_strterm); + TYPE_STR(call_data); default: return "unknown"; #undef TYPE_STR diff --git a/gc.c b/gc.c index 6fcdf2a53c..75daa7fc4b 100644 --- a/gc.c +++ b/gc.c @@ -2338,6 +2338,7 @@ imemo_memsize(VALUE obj) case imemo_ifunc: case imemo_memo: case imemo_parser_strterm: + case imemo_call_data: break; default: /* unreachable */ @@ -2826,6 +2827,9 @@ obj_free(rb_objspace_t *objspace, VALUE obj) case imemo_parser_strterm: RB_DEBUG_COUNTER_INC(obj_imemo_parser_strterm); break; + case imemo_call_data: + RB_DEBUG_COUNTER_INC(obj_imemo_call_data); + break; default: /* unreachable */ break; @@ -5227,6 +5231,8 @@ gc_mark_imemo(rb_objspace_t *objspace, VALUE obj) case imemo_parser_strterm: rb_strterm_mark(obj); return; + case imemo_call_data: + return; #if VM_CHECK_MODE > 0 default: VM_UNREACHABLE(gc_mark_imemo); @@ -8095,6 +8101,7 @@ gc_ref_update_imemo(rb_objspace_t *objspace, VALUE obj) break; case imemo_parser_strterm: case imemo_tmpbuf: + case imemo_call_data: break; default: rb_bug("not reachable %d", imemo_type(obj)); diff --git a/internal.h b/internal.h index 53091e25f8..36abf56ea8 100644 --- a/internal.h +++ b/internal.h @@ -1109,7 +1109,8 @@ enum imemo_type { imemo_iseq = 7, imemo_tmpbuf = 8, imemo_ast = 9, - imemo_parser_strterm = 10 + imemo_parser_strterm = 10, + imemo_call_data = 11 }; #define IMEMO_MASK 0x0f @@ -2387,12 +2388,18 @@ struct rb_call_data { struct rb_call_cache cc; struct rb_call_info ci; }; + VALUE rb_funcallv_with_cc(struct rb_call_data*, VALUE, ID, int, const VALUE*) #if GCC_VERSION_SINCE(3, 3, 0) && defined(__OPTIMIZE__) __attribute__((__visibility__("default"), __nonnull__(1))) # define rb_funcallv(recv, mid, argc, argv) \ __extension__({ \ static struct rb_call_data rb_funcallv_data = { { 0, }, { 0, }, }; \ + static VALUE wrapper = 0; \ + if (!wrapper) { \ + wrapper = rb_imemo_new(imemo_call_data, 0, 0, 0, (VALUE)&rb_funcallv_data); \ + rb_gc_register_mark_object(wrapper); \ + } \ rb_funcallv_with_cc(&rb_funcallv_data, recv, mid, argc, argv); \ }) #endif -- 2.21.0