From dc9ce32864a99391ef8892946c769c0d5bdf1c41 Mon Sep 17 00:00:00 2001 From: normal Date: Wed, 14 Feb 2018 22:35:08 +0000 Subject: [PATCH 01/20] test/ruby/test_optimization.rb: fix compile kwarg Fixes: r62177 ("compile.c: fix string Range optimization with FSL") git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62406 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- test/ruby/test_optimization.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/ruby/test_optimization.rb b/test/ruby/test_optimization.rb index 6e463e18639a9c..83a3a1191a0c74 100644 --- a/test/ruby/test_optimization.rb +++ b/test/ruby/test_optimization.rb @@ -557,8 +557,9 @@ def test_peephole_string_literal_range when "1.8.0"..."1.8.8" then :bar end end; - [ nil, { frozen_string_literal: true } ].each do |opt| - iseq = RubyVM::InstructionSequence.compile(code, nil, nil, opt) + [ true, false ].each do |opt| + iseq = RubyVM::InstructionSequence.compile(code, + frozen_string_literal: opt) insn = iseq.disasm assert_match %r{putobject\s+#{Regexp.quote('"1.8.0"..."1.8.8"')}}, insn assert_match %r{putobject\s+#{Regexp.quote('"2.0.0".."2.3.2"')}}, insn From 7606806cd9a75cd2a9efc1b17f86a57230bd92a6 Mon Sep 17 00:00:00 2001 From: normal Date: Wed, 14 Feb 2018 22:35:13 +0000 Subject: [PATCH 02/20] compile.c: drop freezestring insn on String#-@ Followup to r62039 and remove the redundant freezestring insn which was preventing deduplication from String#-@ * compile.c (iseq_peephole_optimize): drop freezestring insn on String#-@ [ruby-core:85542] [Bug #14475] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62407 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- compile.c | 6 +++--- test/ruby/test_optimization.rb | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/compile.c b/compile.c index 5bca0dca994129..7d065b25d3f871 100644 --- a/compile.c +++ b/compile.c @@ -2851,11 +2851,11 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal struct rb_call_info *ci = (struct rb_call_info *)OPERAND_AT(niobj, 0); /* * freezestring debug_info - * send <:+@, 0, ARG_SIMPLE> + * send <:+@, 0, ARG_SIMPLE> # :-@, too * => - * send <:+@, 0, ARG_SIMPLE> + * send <:+@, 0, ARG_SIMPLE> # :-@, too */ - if (ci->mid == idUPlus && + if ((ci->mid == idUPlus || ci->mid == idUMinus) && (ci->flag & VM_CALL_ARGS_SIMPLE) && ci->orig_argc == 0) { ELEM_REMOVE(list); diff --git a/test/ruby/test_optimization.rb b/test/ruby/test_optimization.rb index 83a3a1191a0c74..8aa5c39323a9d6 100644 --- a/test/ruby/test_optimization.rb +++ b/test/ruby/test_optimization.rb @@ -568,6 +568,21 @@ def test_peephole_string_literal_range end end + def test_peephole_dstr + code = "#{<<~'begin;'}\n#{<<~'end;'}" + begin; + exp = (-'a').object_id + z = 'a' + exp == (-"#{z}").object_id + end; + [ false, true ].each do |fsl| + iseq = RubyVM::InstructionSequence.compile(code, + frozen_string_literal: fsl) + assert_equal(true, iseq.eval, + "[ruby-core:85542] [Bug #14475] fsl: #{fsl}") + end + end + def test_branch_condition_backquote bug = '[ruby-core:80740] [Bug #13444] redefined backquote should be called' class << self From 8df47f8c8d85399cdbe974d83cc5f488bd8603c0 Mon Sep 17 00:00:00 2001 From: mame Date: Thu, 15 Feb 2018 01:59:15 +0000 Subject: [PATCH 03/20] configure.ac: Use `pthread_create` to determine if pthread is available Instead of `pthread_kill`. This is because emscripten supports `pthread_create` but not `pthread_kill`. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62408 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 800e44ae89d77a..1cd2d581eb631f 100644 --- a/configure.ac +++ b/configure.ac @@ -2256,7 +2256,7 @@ AS_IF([test "${universal_binary-no}" = yes ], [ AS_IF([test x"$enable_pthread" = xyes], [ for pthread_lib in thr pthread pthreads c c_r root; do - AC_CHECK_LIB($pthread_lib, pthread_kill, + AC_CHECK_LIB($pthread_lib, pthread_create, rb_with_pthread=yes, rb_with_pthread=no) AS_IF([test "$rb_with_pthread" = "yes"], [ break; fi done From 50700c4d3ceded853dac685e7c3671a839f9dec3 Mon Sep 17 00:00:00 2001 From: mame Date: Thu, 15 Feb 2018 01:59:16 +0000 Subject: [PATCH 04/20] thread_pthread.c: Use `getpagesize()` when `pthread_attr_getguardsize` is unavailable This is also for emscripten. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62409 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- configure.ac | 2 +- thread_pthread.c | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 1cd2d581eb631f..19b41971165887 100644 --- a/configure.ac +++ b/configure.ac @@ -2290,7 +2290,7 @@ AS_IF([test x"$enable_pthread" = xyes], [ AC_DEFINE(NON_SCALAR_THREAD_ID) ]) AC_CHECK_FUNCS(sched_yield pthread_attr_setinheritsched \ - pthread_attr_get_np pthread_attr_getstack \ + pthread_attr_get_np pthread_attr_getstack pthread_attr_getguardsize \ pthread_get_stackaddr_np pthread_get_stacksize_np \ thr_stksegment pthread_stackseg_np pthread_getthrds_np \ pthread_condattr_setclock \ diff --git a/thread_pthread.c b/thread_pthread.c index 381114d1ce0083..d36c1494830c1b 100644 --- a/thread_pthread.c +++ b/thread_pthread.c @@ -561,8 +561,12 @@ get_stack(void **addr, size_t *size) CHECK_ERR(pthread_attr_getstackaddr(&attr, addr)); CHECK_ERR(pthread_attr_getstacksize(&attr, size)); # endif +# ifdef HAVE_PTHREAD_ATTR_GETGUARDSIZE CHECK_ERR(pthread_attr_getguardsize(&attr, &guard)); *size -= guard; +# else + *size -= getpagesize(); +# endif pthread_attr_destroy(&attr); #elif defined HAVE_PTHREAD_ATTR_GET_NP /* FreeBSD, DragonFly BSD, NetBSD */ pthread_attr_t attr; From b4b4b9436740997a807f59e0c979520ed4d20311 Mon Sep 17 00:00:00 2001 From: mame Date: Thu, 15 Feb 2018 01:59:17 +0000 Subject: [PATCH 05/20] gc.c: force STACK_GROW_DIRECTION for emscripten The configure script fails to guess the direction on emscripten. Perhaps this is because of https://github.com/kripken/emscripten/issues/2093 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62410 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- gc.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/gc.c b/gc.c index a1e6bc4bc23e86..ad4cd55b2a392d 100644 --- a/gc.c +++ b/gc.c @@ -3996,6 +3996,11 @@ init_mark_stack(mark_stack_t *stack) #define STACK_END (ec->machine.stack_end) #define STACK_LEVEL_MAX (ec->machine.stack_maxsize/sizeof(VALUE)) +#ifdef __EMSCRIPTEN__ +#undef STACK_GROW_DIRECTION +#define STACK_GROW_DIRECTION 1 +#endif + #if STACK_GROW_DIRECTION < 0 # define STACK_LENGTH (size_t)(STACK_START - STACK_END) #elif STACK_GROW_DIRECTION > 0 From 0efd8bbd34117437f0e1584fe1c1f2177ed09d0d Mon Sep 17 00:00:00 2001 From: mame Date: Thu, 15 Feb 2018 05:34:20 +0000 Subject: [PATCH 06/20] test/io/console/test_io_console.rb (test_oflush): Avoid race condition Add a ad-hoc wait. Follows test_ioflush2. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62411 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- test/io/console/test_io_console.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/test/io/console/test_io_console.rb b/test/io/console/test_io_console.rb index 764c5e1a61360a..1368502b042d60 100644 --- a/test/io/console/test_io_console.rb +++ b/test/io/console/test_io_console.rb @@ -212,6 +212,7 @@ def test_oflush s.oflush # oflush may be issued after "a" is already sent. s.print "b" s.flush + sleep 0.1 assert_include(["b", "ab"], m.readpartial(10)) } end From 9a9a4e874d2257fcdb6fba0be5fa6fb3c402076d Mon Sep 17 00:00:00 2001 From: nobu Date: Thu, 15 Feb 2018 06:14:42 +0000 Subject: [PATCH 07/20] Benchmarks for Array#values_at git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62412 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- benchmark/bm_array_values_at_int.rb | 2 ++ benchmark/bm_array_values_at_range.rb | 2 ++ 2 files changed, 4 insertions(+) create mode 100644 benchmark/bm_array_values_at_int.rb create mode 100644 benchmark/bm_array_values_at_range.rb diff --git a/benchmark/bm_array_values_at_int.rb b/benchmark/bm_array_values_at_int.rb new file mode 100644 index 00000000000000..6cb394cb9fd8f7 --- /dev/null +++ b/benchmark/bm_array_values_at_int.rb @@ -0,0 +1,2 @@ +ary = Array.new(10000) {|i| i} +100000.times { ary.values_at(500) } diff --git a/benchmark/bm_array_values_at_range.rb b/benchmark/bm_array_values_at_range.rb new file mode 100644 index 00000000000000..5b53806d1ca974 --- /dev/null +++ b/benchmark/bm_array_values_at_range.rb @@ -0,0 +1,2 @@ +ary = Array.new(10000) {|i| i} +100000.times { ary.values_at(1..2000) } From 41e9e19bc6544563e8a5eca3d4d8a7c6df0944e1 Mon Sep 17 00:00:00 2001 From: nobu Date: Thu, 15 Feb 2018 10:00:57 +0000 Subject: [PATCH 08/20] Array#values_at optimization * array.c (rb_ary_values_at): optimization range argument case. bulk concatenation than pushing for each element. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62413 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- array.c | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/array.c b/array.c index 2789acd56f3fe5..a821575676d87e 100644 --- a/array.c +++ b/array.c @@ -2804,6 +2804,34 @@ rb_get_values_at(VALUE obj, long olen, int argc, const VALUE *argv, VALUE (*func return result; } +static VALUE +append_values_at_single(VALUE result, VALUE ary, long olen, VALUE idx) +{ + long beg, len; + if (FIXNUM_P(idx)) { + beg = FIX2LONG(idx); + } + /* check if idx is Range */ + else if (rb_range_beg_len(idx, &beg, &len, olen, 1)) { + if (len > 0) { + const VALUE *const src = RARRAY_CONST_PTR(ary); + const long end = beg + len; + const long prevlen = RARRAY_LEN(result); + if (beg < olen) { + rb_ary_cat(result, src + beg, end > olen ? olen-beg : len); + } + if (end > olen) { + rb_ary_store(result, prevlen + len - 1, Qnil); + } + } + return result; + } + else { + beg = NUM2LONG(idx); + } + return rb_ary_push(result, rb_ary_entry(ary, beg)); +} + /* * call-seq: * ary.values_at(selector, ...) -> new_ary @@ -2825,7 +2853,13 @@ rb_get_values_at(VALUE obj, long olen, int argc, const VALUE *argv, VALUE (*func static VALUE rb_ary_values_at(int argc, VALUE *argv, VALUE ary) { - return rb_get_values_at(ary, RARRAY_LEN(ary), argc, argv, rb_ary_entry); + long i, olen = RARRAY_LEN(ary); + VALUE result = rb_ary_new_capa(argc); + for (i = 0; i < argc; ++i) { + append_values_at_single(result, ary, olen, argv[i]); + } + RB_GC_GUARD(ary); + return result; } From d6db2d952e2c6e65fb95a6cabfc3acd07592178c Mon Sep 17 00:00:00 2001 From: knu Date: Thu, 15 Feb 2018 11:16:51 +0000 Subject: [PATCH 09/20] Avoid using `@` in macro substitution that confuses FreeBSD make ``` making mjit_config.h make: Unknown modifier ' ' make: Unclosed variable specification (expecting ')') for "Q" (value "") modifier /bin/sh: Syntax error: end of file unexpected (expecting "}") *** Error code 2 Stop. ``` The at sign probably conflicts the `:@temp@string@` modifier syntax supported by FreeBSD make. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62414 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.in b/Makefile.in index a55a738fea2452..eeda81b0b373ab 100644 --- a/Makefile.in +++ b/Makefile.in @@ -538,7 +538,7 @@ un-runnable: mjit_config.h: $(ECHO) making $@ @{ \ - $(Q:@=:) set -x; \ + test "$(Q)" = @ || set -x; \ echo '#ifndef RUBY_MJIT_CONFIG_H'; \ echo '#define RUBY_MJIT_CONFIG_H 1'; \ \ From 80c850e2243c6cd290e6393da9b72208e8df6d3f Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 12 Jan 2018 13:17:22 -0800 Subject: [PATCH 10/20] Iterate over the catch table, and mark iseq in the table This commit iterates over the catch table, marking instruction sequences stored in the catch table. This allows us to avoid adding the catch table instruction sequence object to the mark array --- compile.c | 5 ----- iseq.c | 13 +++++++++++++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/compile.c b/compile.c index 7d065b25d3f871..33c3b75507dec8 100644 --- a/compile.c +++ b/compile.c @@ -2209,11 +2209,6 @@ iseq_set_exception_table(rb_iseq_t *iseq) entry->end = label_get_position((LABEL *)(ptr[2] & ~1)); entry->iseq = (rb_iseq_t *)ptr[3]; - /* register iseq as mark object */ - if (entry->iseq != 0) { - iseq_add_mark_object(iseq, (VALUE)entry->iseq); - } - /* stack depth */ if (ptr[4]) { LABEL *lobj = (LABEL *)(ptr[4] & ~1); diff --git a/iseq.c b/iseq.c index b703baa2c4b53d..88e8ac469bc3f9 100644 --- a/iseq.c +++ b/iseq.c @@ -128,8 +128,21 @@ rb_iseq_mark(const rb_iseq_t *iseq) rb_gc_mark(body->location.base_label); rb_gc_mark(body->location.pathobj); RUBY_MARK_UNLESS_NULL((VALUE)body->parent_iseq); + + if (body->catch_table) { + const struct iseq_catch_table *table = body->catch_table; + unsigned int i; + for(i = 0; i < table->size; i++) { + const struct iseq_catch_table_entry *entry; + entry = &table->entries[i]; + if (entry->iseq) { + rb_gc_mark((VALUE)entry->iseq); + } + } + } } + if (FL_TEST(iseq, ISEQ_NOT_LOADED_YET)) { rb_gc_mark(iseq->aux.loader.obj); } From 881ea053c0386690ad3138a7d4caccf1e70172d1 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 12 Jan 2018 13:38:21 -0800 Subject: [PATCH 11/20] Disasm instruction sequences and mark things managed by the GC This commit introduce a function to disassemble instruction sequences and call a callback for each value that should be marked by the GC. --- iseq.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/iseq.c b/iseq.c index 88e8ac469bc3f9..eecaa3d2fa6a91 100644 --- a/iseq.c +++ b/iseq.c @@ -115,6 +115,76 @@ rb_iseq_free(const rb_iseq_t *iseq) RUBY_FREE_LEAVE("iseq"); } +#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE +static int +rb_vm_insn_addr2insn2(const void *addr) /* cold path */ +{ + int insn; + const void * const *table = rb_vm_get_insns_address_table(); + + for (insn = 0; insn < VM_INSTRUCTION_SIZE; insn++) { + if (table[insn] == addr) { + return insn; + } + } + rb_bug("rb_vm_insn_addr2insn: invalid insn address: %p", addr); +} +#endif + +typedef void iseq_value_itr_t(void *ctx, VALUE obj); + +static int +iseq_extract_values(const VALUE *code, size_t pos, iseq_value_itr_t * func, void *data) +{ +#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE + VALUE insn = rb_vm_insn_addr2insn2((void *)code[pos]); +#else + VALUE insn = code[pos]; +#endif + int len = insn_len(insn); + int op_no; + const char *types = insn_op_types(insn); + + for (op_no = 0; types[op_no]; op_no++) { + char type = types[op_no]; + VALUE op = code[pos + op_no + 1]; + switch (type) { + case TS_CDHASH: + case TS_ISEQ: + case TS_VALUE: + if (!SPECIAL_CONST_P(op)) { + func(data, op); + } + break; + default: + break; + } + } + + return len; +} + +void +rb_iseq_each_value(const rb_iseq_t *iseq, iseq_value_itr_t * func, void *data) +{ + unsigned int size; + const VALUE *code; + size_t n; + + size = iseq->body->iseq_size; + code = iseq->body->iseq_encoded; + + for (n = 0; n < size;) { + n += iseq_extract_values(code, n, func, data); + } +} + +static void +each_insn_value(void *ctx, VALUE obj) +{ + return rb_gc_mark(obj); +} + void rb_iseq_mark(const rb_iseq_t *iseq) { @@ -123,6 +193,7 @@ rb_iseq_mark(const rb_iseq_t *iseq) if (iseq->body) { const struct rb_iseq_constant_body *body = iseq->body; + rb_iseq_each_value(iseq, each_insn_value, NULL); RUBY_MARK_UNLESS_NULL(body->mark_ary); rb_gc_mark(body->location.label); rb_gc_mark(body->location.base_label); From 969ccfd5deddf2c318ff3e111ade17dd473d6761 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 12 Jan 2018 15:44:45 -0800 Subject: [PATCH 12/20] Only add objects to the compile time mark array Now that marking is done directly on the iseq, we just need to keep objects alive during compile time via a mark array. This commit switches iseq mark to push on to the compile time mark array, then stops adding the iseq to iseq mark arrays --- compile.c | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/compile.c b/compile.c index 33c3b75507dec8..2ffb6f5578976d 100644 --- a/compile.c +++ b/compile.c @@ -562,15 +562,6 @@ APPEND_ELEM(ISEQ_ARG_DECLARE LINK_ANCHOR *const anchor, LINK_ELEMENT *before, LI #define APPEND_ELEM(anchor, before, elem) APPEND_ELEM(iseq, (anchor), (before), (elem)) #endif -static int -iseq_add_mark_object(const rb_iseq_t *iseq, VALUE v) -{ - if (!SPECIAL_CONST_P(v)) { - rb_iseq_add_mark_object(iseq, v); - } - return COMPILE_OK; -} - static int iseq_add_mark_object_compile_time(const rb_iseq_t *iseq, VALUE v) { @@ -1235,7 +1226,7 @@ new_child_iseq(rb_iseq_t *iseq, const NODE *const node, rb_iseq_path(iseq), rb_iseq_realpath(iseq), INT2FIX(line_no), parent, type, ISEQ_COMPILE_DATA(iseq)->option); debugs("[new_child_iseq]< ---------------------------------------\n"); - iseq_add_mark_object(iseq, (VALUE)ret_iseq); + iseq_add_mark_object_compile_time(iseq, (VALUE)ret_iseq); return ret_iseq; } @@ -1250,7 +1241,7 @@ new_child_iseq_ifunc(rb_iseq_t *iseq, const struct vm_ifunc *ifunc, rb_iseq_path(iseq), rb_iseq_realpath(iseq), INT2FIX(line_no), parent, type, ISEQ_COMPILE_DATA(iseq)->option); debugs("[new_child_iseq_ifunc]< ---------------------------------------\n"); - iseq_add_mark_object(iseq, (VALUE)ret_iseq); + iseq_add_mark_object_compile_time(iseq, (VALUE)ret_iseq); return ret_iseq; } @@ -1501,7 +1492,6 @@ iseq_set_arguments_keywords(rb_iseq_t *iseq, LINK_ANCHOR *const optargs, switch (nd_type(val_node)) { case NODE_LIT: dv = val_node->nd_lit; - iseq_add_mark_object(iseq, dv); break; case NODE_NIL: dv = Qnil; @@ -2044,7 +2034,6 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) VALUE v = operands[j]; generated_iseq[code_index + 1 + j] = v; /* to mark ruby object */ - iseq_add_mark_object(iseq, v); break; } case TS_IC: /* inline cache */ @@ -4822,7 +4811,6 @@ compile_case(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_nod } if (only_special_literals) { - iseq_add_mark_object(iseq, literals); ADD_INSN(ret, nd_line(orig_node), dup); ADD_INSN2(ret, nd_line(orig_node), opt_case_dispatch, literals, elselabel); @@ -7538,7 +7526,6 @@ iseq_build_load_iseq(const rb_iseq_t *iseq, VALUE op) } loaded_iseq = rb_iseqw_to_iseq(iseqw); - iseq_add_mark_object(iseq, (VALUE)loaded_iseq); return loaded_iseq; } @@ -7669,7 +7656,6 @@ iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *const anchor, break; case TS_VALUE: argv[j] = op; - iseq_add_mark_object(iseq, op); break; case TS_ISEQ: { @@ -7716,7 +7702,6 @@ iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *const anchor, } RB_GC_GUARD(op); argv[j] = map; - rb_iseq_add_mark_object(iseq, map); } break; case TS_FUNCPTR: @@ -9320,7 +9305,6 @@ ibf_load_object(const struct ibf_load *load, VALUE object_index) rb_ary_store(load->obj_list, (long)object_index, obj); } - iseq_add_mark_object(load->iseq, obj); return obj; } } @@ -9507,9 +9491,6 @@ ibf_load_iseq(const struct ibf_load *load, const rb_iseq_t *index_iseq) ibf_load_iseq_complete(iseq); #endif /* !USE_LAZY_LOAD */ - if (load->iseq) { - iseq_add_mark_object(load->iseq, (VALUE)iseq); - } return iseq; } } From aaaffa44dc39a986f25d68af0f0705bbb6fd588b Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 17 Jan 2018 11:30:55 -0800 Subject: [PATCH 13/20] Only de-reference when we need to check the object type --- iseq.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/iseq.c b/iseq.c index eecaa3d2fa6a91..b02d5d7638fa18 100644 --- a/iseq.c +++ b/iseq.c @@ -117,7 +117,7 @@ rb_iseq_free(const rb_iseq_t *iseq) #if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE static int -rb_vm_insn_addr2insn2(const void *addr) /* cold path */ +rb_vm_insn_addr2insn2(const void *addr) { int insn; const void * const *table = rb_vm_get_insns_address_table(); @@ -147,15 +147,17 @@ iseq_extract_values(const VALUE *code, size_t pos, iseq_value_itr_t * func, void for (op_no = 0; types[op_no]; op_no++) { char type = types[op_no]; - VALUE op = code[pos + op_no + 1]; switch (type) { case TS_CDHASH: case TS_ISEQ: case TS_VALUE: - if (!SPECIAL_CONST_P(op)) { - func(data, op); + { + VALUE op = code[pos + op_no + 1]; + if (!SPECIAL_CONST_P(op)) { + func(data, op); + } + break; } - break; default: break; } From 5fa17335ce41ed7f98d7473720686b15dae5eb29 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 18 Jan 2018 10:37:22 -0800 Subject: [PATCH 14/20] Private function should be static, no return in `void` --- iseq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/iseq.c b/iseq.c index b02d5d7638fa18..370f0f87497c1d 100644 --- a/iseq.c +++ b/iseq.c @@ -166,7 +166,7 @@ iseq_extract_values(const VALUE *code, size_t pos, iseq_value_itr_t * func, void return len; } -void +static void rb_iseq_each_value(const rb_iseq_t *iseq, iseq_value_itr_t * func, void *data) { unsigned int size; @@ -184,7 +184,7 @@ rb_iseq_each_value(const rb_iseq_t *iseq, iseq_value_itr_t * func, void *data) static void each_insn_value(void *ctx, VALUE obj) { - return rb_gc_mark(obj); + rb_gc_mark(obj); } void From d3f6c51e40b9d525f0a8067ed793b8db7850f332 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 18 Jan 2018 15:39:03 -0800 Subject: [PATCH 15/20] CDHASH needs to stay in the mark array until compilation finishes --- compile.c | 1 + 1 file changed, 1 insertion(+) diff --git a/compile.c b/compile.c index 2ffb6f5578976d..b8176b60372b91 100644 --- a/compile.c +++ b/compile.c @@ -4811,6 +4811,7 @@ compile_case(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_nod } if (only_special_literals) { + iseq_add_mark_object_compile_time(iseq, literals); ADD_INSN(ret, nd_line(orig_node), dup); ADD_INSN2(ret, nd_line(orig_node), opt_case_dispatch, literals, elselabel); From 9bed499f10f3787f85e75b545148acb511f810d3 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 19 Jan 2018 14:02:32 -0800 Subject: [PATCH 16/20] Fix bug when marking iseq before instruction have been translated If an instruction sequence gets marked before instructions have been translated, the we need to *not* translate back instructions in the mark function. --- compile.c | 1 + iseq.c | 28 +++++++++++++++++++++------- iseq.h | 1 + 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/compile.c b/compile.c index b8176b60372b91..123eeafba1973f 100644 --- a/compile.c +++ b/compile.c @@ -740,6 +740,7 @@ rb_iseq_translate_threaded_code(rb_iseq_t *iseq) encoded[i] = (VALUE)table[insn]; i += len; } + FL_SET(iseq, ISEQ_TRANSLATED); #endif return COMPILE_OK; } diff --git a/iseq.c b/iseq.c index 370f0f87497c1d..0d7c2cf061872c 100644 --- a/iseq.c +++ b/iseq.c @@ -131,16 +131,19 @@ rb_vm_insn_addr2insn2(const void *addr) } #endif +static int +rb_vm_insn_null_translator(const void *addr) +{ + return (int)addr; +} + typedef void iseq_value_itr_t(void *ctx, VALUE obj); +typedef int rb_vm_insns_translator_t(const void *addr); static int -iseq_extract_values(const VALUE *code, size_t pos, iseq_value_itr_t * func, void *data) +iseq_extract_values(const VALUE *code, size_t pos, iseq_value_itr_t * func, void *data, rb_vm_insns_translator_t * translator) { -#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE - VALUE insn = rb_vm_insn_addr2insn2((void *)code[pos]); -#else - VALUE insn = code[pos]; -#endif + VALUE insn = translator((void *)code[pos]); int len = insn_len(insn); int op_no; const char *types = insn_op_types(insn); @@ -172,12 +175,23 @@ rb_iseq_each_value(const rb_iseq_t *iseq, iseq_value_itr_t * func, void *data) unsigned int size; const VALUE *code; size_t n; + rb_vm_insns_translator_t * translator; size = iseq->body->iseq_size; code = iseq->body->iseq_encoded; +#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE + if (FL_TEST(iseq, ISEQ_TRANSLATED)) { + translator = rb_vm_insn_addr2insn2; + } else { + translator = rb_vm_insn_null_translator; + } +#else + translator = rb_vm_insn_null_translator; +#endif + for (n = 0; n < size;) { - n += iseq_extract_values(code, n, func, data); + n += iseq_extract_values(code, n, func, data, translator); } } diff --git a/iseq.h b/iseq.h index 0c316e2cb2863c..f8578bf522d6af 100644 --- a/iseq.h +++ b/iseq.h @@ -94,6 +94,7 @@ ISEQ_ORIGINAL_ISEQ_ALLOC(const rb_iseq_t *iseq, long size) #define ISEQ_NOT_LOADED_YET IMEMO_FL_USER1 #define ISEQ_USE_COMPILE_DATA IMEMO_FL_USER2 +#define ISEQ_TRANSLATED IMEMO_FL_USER3 struct iseq_compile_data { /* GC is needed */ From 8aeb2b8c6d2e017338fa47bd038236c277b5e562 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 1 Feb 2018 17:22:35 -0800 Subject: [PATCH 17/20] Directly mark `once` instruction values --- iseq.c | 15 ++++++++------- iseq.h | 1 - vm_insnhelper.c | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/iseq.c b/iseq.c index 0d7c2cf061872c..b69c7c355c0694 100644 --- a/iseq.c +++ b/iseq.c @@ -161,6 +161,14 @@ iseq_extract_values(const VALUE *code, size_t pos, iseq_value_itr_t * func, void } break; } + case TS_IC: + if (BIN(once) == insn || BIN(trace_once) == insn) { + union iseq_inline_storage_entry *const is = (union iseq_inline_storage_entry *)code[pos + op_no + 1]; + if (is->once.value) { + func(data, is->once.value); + } + } + break; default: break; } @@ -399,13 +407,6 @@ set_relation(rb_iseq_t *iseq, const rb_iseq_t *piseq) } } -void -rb_iseq_add_mark_object(const rb_iseq_t *iseq, VALUE obj) -{ - /* TODO: check dedup */ - rb_ary_push(ISEQ_MARK_ARY(iseq), obj); -} - static VALUE prepare_iseq_build(rb_iseq_t *iseq, VALUE name, VALUE path, VALUE realpath, VALUE first_lineno, const rb_code_location_t *code_location, diff --git a/iseq.h b/iseq.h index f8578bf522d6af..0dd0703d207054 100644 --- a/iseq.h +++ b/iseq.h @@ -174,7 +174,6 @@ void rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE exception, VALUE body); /* iseq.c */ -void rb_iseq_add_mark_object(const rb_iseq_t *iseq, VALUE obj); VALUE rb_iseq_load(VALUE data, VALUE parent, VALUE opt); VALUE rb_iseq_parameters(const rb_iseq_t *iseq, int is_proc); struct st_table *ruby_insn_make_insn_table(void); diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 5567c6b20f0d84..7efbf59a7420d2 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -3298,10 +3298,10 @@ vm_once_dispatch(rb_execution_context_t *ec, ISEQ iseq, IC ic) else if (is->once.running_thread == NULL) { VALUE val; is->once.running_thread = th; - val = is->once.value = rb_ensure(vm_once_exec, (VALUE)iseq, vm_once_clear, (VALUE)is); + val = rb_ensure(vm_once_exec, (VALUE)iseq, vm_once_clear, (VALUE)is); + RB_OBJ_WRITE(ec->cfp->iseq, &is->once.value, val); /* is->once.running_thread is cleared by vm_once_clear() */ is->once.running_thread = RUNNING_THREAD_ONCE_DONE; /* success */ - rb_iseq_add_mark_object(ec->cfp->iseq, val); return val; } else if (is->once.running_thread == th) { From 65c9fc93a9cef2f41ccb74e908abe8d543044907 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 2 Feb 2018 11:15:21 -0800 Subject: [PATCH 18/20] stop using a mark array --- compile.c | 5 +++-- iseq.c | 5 +++-- iseq.h | 37 +++++++++++++------------------------ vm_core.h | 6 +++++- 4 files changed, 24 insertions(+), 29 deletions(-) diff --git a/compile.c b/compile.c index 123eeafba1973f..aa60cf374d3cea 100644 --- a/compile.c +++ b/compile.c @@ -8644,7 +8644,8 @@ ibf_dump_iseq_each(struct ibf_dump *dump, const rb_iseq_t *iseq) dump_body.is_entries = NULL; dump_body.ci_entries = ibf_dump_ci_entries(dump, iseq); dump_body.cc_entries = NULL; - dump_body.mark_ary = ISEQ_FLIP_CNT(iseq); + dump_body.variable.coverage = Qnil; + dump_body.variable.original_iseq = Qnil; return ibf_dump_write(dump, &dump_body, sizeof(dump_body)); } @@ -8676,7 +8677,7 @@ ibf_load_iseq_each(const struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t of load_body->ci_kw_size = body->ci_kw_size; load_body->insns_info.size = body->insns_info.size; - RB_OBJ_WRITE(iseq, &load_body->mark_ary, iseq_mark_ary_create((int)body->mark_ary)); + iseq_mark_ary_create(iseq, (int)body->variable.flip_count); { VALUE realpath = Qnil, path = ibf_load_object(load, body->location.pathobj); diff --git a/iseq.c b/iseq.c index b69c7c355c0694..4cef5b8ea0ac77 100644 --- a/iseq.c +++ b/iseq.c @@ -218,7 +218,8 @@ rb_iseq_mark(const rb_iseq_t *iseq) const struct rb_iseq_constant_body *body = iseq->body; rb_iseq_each_value(iseq, each_insn_value, NULL); - RUBY_MARK_UNLESS_NULL(body->mark_ary); + rb_gc_mark(body->variable.coverage); + rb_gc_mark(body->variable.original_iseq); rb_gc_mark(body->location.label); rb_gc_mark(body->location.base_label); rb_gc_mark(body->location.pathobj); @@ -427,7 +428,7 @@ prepare_iseq_build(rb_iseq_t *iseq, if (iseq != iseq->body->local_iseq) { RB_OBJ_WRITE(iseq, &iseq->body->location.base_label, iseq->body->local_iseq->body->location.label); } - RB_OBJ_WRITE(iseq, &iseq->body->mark_ary, iseq_mark_ary_create(0)); + iseq_mark_ary_create(iseq, 0); ISEQ_COMPILE_DATA_ALLOC(iseq); RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->err_info, err_info); diff --git a/iseq.h b/iseq.h index 0dd0703d207054..d238a55fe4d5f8 100644 --- a/iseq.h +++ b/iseq.h @@ -28,44 +28,33 @@ rb_call_info_kw_arg_bytes(int keyword_len) return sizeof(struct rb_call_info_kw_arg) + sizeof(VALUE) * (keyword_len - 1); } -enum iseq_mark_ary_index { - ISEQ_MARK_ARY_COVERAGE, - ISEQ_MARK_ARY_FLIP_CNT, - ISEQ_MARK_ARY_ORIGINAL_ISEQ, - ISEQ_MARK_ARY_INITIAL_SIZE -}; - -static inline VALUE -iseq_mark_ary_create(int flip_cnt) +static inline void +iseq_mark_ary_create(rb_iseq_t *iseq, int flip_cnt) { - VALUE ary = rb_ary_tmp_new(ISEQ_MARK_ARY_INITIAL_SIZE); - rb_ary_push(ary, Qnil); /* ISEQ_MARK_ARY_COVERAGE */ - rb_ary_push(ary, INT2FIX(flip_cnt)); /* ISEQ_MARK_ARY_FLIP_CNT */ - rb_ary_push(ary, Qnil); /* ISEQ_MARK_ARY_ORIGINAL_ISEQ */ - return ary; + RB_OBJ_WRITE(iseq, &iseq->body->variable.coverage, Qnil); + RB_OBJ_WRITE(iseq, &iseq->body->variable.original_iseq, Qnil); + iseq->body->variable.flip_count = flip_cnt; } -#define ISEQ_MARK_ARY(iseq) (iseq)->body->mark_ary - -#define ISEQ_COVERAGE(iseq) RARRAY_AREF(ISEQ_MARK_ARY(iseq), ISEQ_MARK_ARY_COVERAGE) -#define ISEQ_COVERAGE_SET(iseq, cov) RARRAY_ASET(ISEQ_MARK_ARY(iseq), ISEQ_MARK_ARY_COVERAGE, cov) +#define ISEQ_COVERAGE(iseq) iseq->body->variable.coverage +#define ISEQ_COVERAGE_SET(iseq, cov) RB_OBJ_WRITE(iseq, &iseq->body->variable.coverage, cov) #define ISEQ_LINE_COVERAGE(iseq) RARRAY_AREF(ISEQ_COVERAGE(iseq), COVERAGE_INDEX_LINES) #define ISEQ_BRANCH_COVERAGE(iseq) RARRAY_AREF(ISEQ_COVERAGE(iseq), COVERAGE_INDEX_BRANCHES) -#define ISEQ_FLIP_CNT(iseq) FIX2INT(RARRAY_AREF(ISEQ_MARK_ARY(iseq), ISEQ_MARK_ARY_FLIP_CNT)) +#define ISEQ_FLIP_CNT(iseq) (iseq)->body->variable.flip_count static inline int ISEQ_FLIP_CNT_INCREMENT(const rb_iseq_t *iseq) { - int cnt = ISEQ_FLIP_CNT(iseq); - RARRAY_ASET(ISEQ_MARK_ARY(iseq), ISEQ_MARK_ARY_FLIP_CNT, INT2FIX(cnt+1)); + int cnt = iseq->body->variable.flip_count; + iseq->body->variable.flip_count += 1; return cnt; } static inline VALUE * ISEQ_ORIGINAL_ISEQ(const rb_iseq_t *iseq) { - VALUE str = RARRAY_AREF(ISEQ_MARK_ARY(iseq), ISEQ_MARK_ARY_ORIGINAL_ISEQ); + VALUE str = iseq->body->variable.original_iseq; if (RTEST(str)) return (VALUE *)RSTRING_PTR(str); return NULL; } @@ -73,14 +62,14 @@ ISEQ_ORIGINAL_ISEQ(const rb_iseq_t *iseq) static inline void ISEQ_ORIGINAL_ISEQ_CLEAR(const rb_iseq_t *iseq) { - RARRAY_ASET(ISEQ_MARK_ARY(iseq), ISEQ_MARK_ARY_ORIGINAL_ISEQ, Qnil); + RB_OBJ_WRITE(iseq, &iseq->body->variable.original_iseq, Qnil); } static inline VALUE * ISEQ_ORIGINAL_ISEQ_ALLOC(const rb_iseq_t *iseq, long size) { VALUE str = rb_str_tmp_new(size * sizeof(VALUE)); - RARRAY_ASET(ISEQ_MARK_ARY(iseq), ISEQ_MARK_ARY_ORIGINAL_ISEQ, str); + RB_OBJ_WRITE(iseq, &iseq->body->variable.original_iseq, str); return (VALUE *)RSTRING_PTR(str); } diff --git a/vm_core.h b/vm_core.h index 0a62b66db82b1d..98b9513e7e1a92 100644 --- a/vm_core.h +++ b/vm_core.h @@ -411,7 +411,11 @@ struct rb_iseq_constant_body { */ struct rb_call_cache *cc_entries; /* size is ci_size = ci_kw_size */ - VALUE mark_ary; /* Array: includes operands which should be GC marked */ + struct { + rb_num_t flip_count; + VALUE coverage; + VALUE original_iseq; + } variable; unsigned int local_table_size; unsigned int is_size; From 6649dc468f94d218c058a25233a468113204ee74 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 5 Feb 2018 11:49:13 -0800 Subject: [PATCH 19/20] Set a compile time flag so iseq marking knows about markables At compile time, set a flag on the iseq object so that the iseq mark function knows to skip disassembly for iseqs that have no markables. --- compile.c | 10 ++++++++++ iseq.c | 5 ++++- iseq.h | 1 + 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/compile.c b/compile.c index aa60cf374d3cea..ef71ade5dee9a6 100644 --- a/compile.c +++ b/compile.c @@ -2018,6 +2018,7 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) rb_hash_rehash(map); freeze_hide_obj(map); generated_iseq[code_index + 1 + j] = map; + FL_SET(iseq, ISEQ_MARKABLE_ISEQ); break; } case TS_LINDEX: @@ -2028,6 +2029,9 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) { VALUE v = operands[j]; generated_iseq[code_index + 1 + j] = v; + if (!SPECIAL_CONST_P(v)) { + FL_SET(iseq, ISEQ_MARKABLE_ISEQ); + } break; } case TS_VALUE: /* VALUE */ @@ -2035,6 +2039,9 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) VALUE v = operands[j]; generated_iseq[code_index + 1 + j] = v; /* to mark ruby object */ + if (!SPECIAL_CONST_P(v)) { + FL_SET(iseq, ISEQ_MARKABLE_ISEQ); + } break; } case TS_IC: /* inline cache */ @@ -2045,6 +2052,9 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) rb_bug("iseq_set_sequence: ic_index overflow: index: %d, size: %d", ic_index, iseq->body->is_size); } generated_iseq[code_index + 1 + j] = (VALUE)ic; + if (BIN(once) == insn || BIN(trace_once) == insn) { + FL_SET(iseq, ISEQ_MARKABLE_ISEQ); + } break; } case TS_CALLINFO: /* call info */ diff --git a/iseq.c b/iseq.c index 4cef5b8ea0ac77..3bb7b09057de9a 100644 --- a/iseq.c +++ b/iseq.c @@ -217,7 +217,10 @@ rb_iseq_mark(const rb_iseq_t *iseq) if (iseq->body) { const struct rb_iseq_constant_body *body = iseq->body; - rb_iseq_each_value(iseq, each_insn_value, NULL); + if(FL_TEST(iseq, ISEQ_MARKABLE_ISEQ)) { + rb_iseq_each_value(iseq, each_insn_value, NULL); + } + rb_gc_mark(body->variable.coverage); rb_gc_mark(body->variable.original_iseq); rb_gc_mark(body->location.label); diff --git a/iseq.h b/iseq.h index d238a55fe4d5f8..31a3232e3be1f7 100644 --- a/iseq.h +++ b/iseq.h @@ -84,6 +84,7 @@ ISEQ_ORIGINAL_ISEQ_ALLOC(const rb_iseq_t *iseq, long size) #define ISEQ_NOT_LOADED_YET IMEMO_FL_USER1 #define ISEQ_USE_COMPILE_DATA IMEMO_FL_USER2 #define ISEQ_TRANSLATED IMEMO_FL_USER3 +#define ISEQ_MARKABLE_ISEQ IMEMO_FL_USER4 struct iseq_compile_data { /* GC is needed */ From d6ca1ce34321552a73cef70060d51385384a37ed Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 5 Feb 2018 12:16:33 -0800 Subject: [PATCH 20/20] Introduce TS_ISE operand The `once` instruction uses an "inline storage entry". This commit introduces an inline storage entry specific operand. Adding this operand allows us to remove conditionals based on instruction type. --- compile.c | 16 ++++++++++++++-- insns.def | 4 ++-- iseq.c | 8 +++++--- tool/ruby_vm/models/typemap.rb | 1 + vm_core.h | 1 + vm_insnhelper.c | 3 +-- 6 files changed, 24 insertions(+), 9 deletions(-) diff --git a/compile.c b/compile.c index ef71ade5dee9a6..2610836e78b2e7 100644 --- a/compile.c +++ b/compile.c @@ -2052,9 +2052,17 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) rb_bug("iseq_set_sequence: ic_index overflow: index: %d, size: %d", ic_index, iseq->body->is_size); } generated_iseq[code_index + 1 + j] = (VALUE)ic; - if (BIN(once) == insn || BIN(trace_once) == insn) { - FL_SET(iseq, ISEQ_MARKABLE_ISEQ); + break; + } + case TS_ISE: /* inline storage entry */ + { + unsigned int ic_index = FIX2UINT(operands[j]); + IC ic = (IC)&iseq->body->is_entries[ic_index]; + if (UNLIKELY(ic_index >= iseq->body->is_size)) { + rb_bug("iseq_set_sequence: ic_index overflow: index: %d, size: %d", ic_index, iseq->body->is_size); } + generated_iseq[code_index + 1 + j] = (VALUE)ic; + FL_SET(iseq, ISEQ_MARKABLE_ISEQ); break; } case TS_CALLINFO: /* call info */ @@ -7299,6 +7307,7 @@ insn_data_to_s_detail(INSN *iobj) break; } case TS_IC: /* inline cache */ + case TS_ISE: /* inline storage entry */ rb_str_catf(str, "", FIX2INT(OPERAND_AT(iobj, j))); break; case TS_CALLINFO: /* call info */ @@ -7684,6 +7693,7 @@ iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *const anchor, argv[j] = (VALUE)rb_global_entry(SYM2ID(op)); break; case TS_IC: + case TS_ISE: argv[j] = op; if (NUM2UINT(op) >= iseq->body->is_size) { iseq->body->is_size = NUM2INT(op) + 1; @@ -8289,6 +8299,7 @@ ibf_dump_code(struct ibf_dump *dump, const rb_iseq_t *iseq) code[code_index] = (VALUE)ibf_dump_iseq(dump, (const rb_iseq_t *)op); break; case TS_IC: + case TS_ISE: { unsigned int i; for (i=0; ibody->is_size; i++) { @@ -8354,6 +8365,7 @@ ibf_load_code(const struct ibf_load *load, const rb_iseq_t *iseq, const struct r code[code_index] = (VALUE)ibf_load_iseq(load, (const rb_iseq_t *)op); break; case TS_IC: + case TS_ISE: code[code_index] = (VALUE)&is_entries[(int)op]; break; case TS_CALLINFO: diff --git a/insns.def b/insns.def index d06368466ed1db..4f791ed16b801c 100644 --- a/insns.def +++ b/insns.def @@ -971,11 +971,11 @@ setinlinecache /* run iseq only once */ DEFINE_INSN once -(ISEQ iseq, IC ic) +(ISEQ iseq, ISE ise) () (VALUE val) { - val = vm_once_dispatch(ec, iseq, ic); + val = vm_once_dispatch(ec, iseq, ise); } /* case dispatcher, jump by table if possible */ diff --git a/iseq.c b/iseq.c index 3bb7b09057de9a..fcac257fb3701a 100644 --- a/iseq.c +++ b/iseq.c @@ -161,14 +161,14 @@ iseq_extract_values(const VALUE *code, size_t pos, iseq_value_itr_t * func, void } break; } - case TS_IC: - if (BIN(once) == insn || BIN(trace_once) == insn) { + case TS_ISE: + { union iseq_inline_storage_entry *const is = (union iseq_inline_storage_entry *)code[pos + op_no + 1]; if (is->once.value) { func(data, is->once.value); } + break; } - break; default: break; } @@ -1717,6 +1717,7 @@ rb_insn_operand_intern(const rb_iseq_t *iseq, break; case TS_IC: + case TS_ISE: ret = rb_sprintf("", (union iseq_inline_storage_entry *)op - iseq->body->is_entries); break; @@ -2460,6 +2461,7 @@ iseq_data_to_ary(const rb_iseq_t *iseq) } break; case TS_IC: + case TS_ISE: { union iseq_inline_storage_entry *is = (union iseq_inline_storage_entry *)*seq; rb_ary_push(ary, INT2FIX(is - iseq->body->is_entries)); diff --git a/tool/ruby_vm/models/typemap.rb b/tool/ruby_vm/models/typemap.rb index d818ce9878bb30..7c5c872d7cb104 100644 --- a/tool/ruby_vm/models/typemap.rb +++ b/tool/ruby_vm/models/typemap.rb @@ -18,6 +18,7 @@ "GENTRY" => %w[G TS_GENTRY], "IC" => %w[K TS_IC], "ID" => %w[I TS_ID], + "ISE" => %w[T TS_ISE], "ISEQ" => %w[S TS_ISEQ], "OFFSET" => %w[O TS_OFFSET], "VALUE" => %w[V TS_VALUE], diff --git a/vm_core.h b/vm_core.h index 98b9513e7e1a92..4b8f2474f1e2f4 100644 --- a/vm_core.h +++ b/vm_core.h @@ -1013,6 +1013,7 @@ enum vm_svar_index { /* inline cache */ typedef struct iseq_inline_cache_entry *IC; +typedef union iseq_inline_storage_entry *ISE; typedef struct rb_call_info *CALL_INFO; typedef struct rb_call_cache *CALL_CACHE; diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 7efbf59a7420d2..cd17a129c3fe62 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -3285,11 +3285,10 @@ vm_ic_update(IC ic, VALUE val, const VALUE *reg_ep) } static VALUE -vm_once_dispatch(rb_execution_context_t *ec, ISEQ iseq, IC ic) +vm_once_dispatch(rb_execution_context_t *ec, ISEQ iseq, ISE is) { rb_thread_t *th = rb_ec_thread_ptr(ec); rb_thread_t *const RUNNING_THREAD_ONCE_DONE = (rb_thread_t *)(0x1); - union iseq_inline_storage_entry *const is = (union iseq_inline_storage_entry *)ic; again: if (is->once.running_thread == RUNNING_THREAD_ONCE_DONE) { pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy