[前][次][番号順一覧][スレッド一覧]

ruby-changes:59098

From: Aaron <ko1@a...>
Date: Fri, 6 Dec 2019 06:37:32 +0900 (JST)
Subject: [ruby-changes:59098] 2c8d186c6e (master): Introduce an "Inline IVAR cache" struct

https://git.ruby-lang.org/ruby.git/commit/?id=2c8d186c6e

From 2c8d186c6e4fd03ea57466fa6dce6bad40d09401 Mon Sep 17 00:00:00 2001
From: Aaron Patterson <tenderlove@r...>
Date: Fri, 11 Oct 2019 17:06:41 -0700
Subject: Introduce an "Inline IVAR cache" struct

This commit introduces an "inline ivar cache" struct.  The reason we
need this is so compaction can differentiate from an ivar cache and a
regular inline cache.  Regular inline caches contain references to
`VALUE` and ivar caches just contain references to the ivar index.  With
this new struct we can easily update references for inline caches (but
not inline var caches as they just contain an int)

diff --git a/compile.c b/compile.c
index e261a38..aee9672 100644
--- a/compile.c
+++ b/compile.c
@@ -2190,6 +2190,7 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) https://github.com/ruby/ruby/blob/trunk/compile.c#L2190
 			FL_SET(iseq, ISEQ_MARKABLE_ISEQ);
                         /* fall through */
 		      case TS_IC: /* inline cache */
+		      case TS_IVC: /* inline ivar cache */
 			{
 			    unsigned int ic_index = FIX2UINT(operands[j]);
 			    IC ic = (IC)&body->is_entries[ic_index];
@@ -8648,6 +8649,7 @@ insn_data_to_s_detail(INSN *iobj) https://github.com/ruby/ruby/blob/trunk/compile.c#L8649
 		    break;
 		}
 	      case TS_IC:	/* inline cache */
+	      case TS_IVC:	/* inline ivar cache */
 	      case TS_ISE:	/* inline storage entry */
 		rb_str_catf(str, "<ic:%d>", FIX2INT(OPERAND_AT(iobj, j)));
 		break;
@@ -9035,6 +9037,7 @@ iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *const anchor, https://github.com/ruby/ruby/blob/trunk/compile.c#L9037
 			FL_SET(iseq, ISEQ_MARKABLE_ISEQ);
                         /* fall through */
 		      case TS_IC:
+                      case TS_IVC:  /* inline ivar cache */
 			argv[j] = op;
 			if (NUM2UINT(op) >= iseq->body->is_size) {
 			    iseq->body->is_size = NUM2INT(op) + 1;
@@ -9883,6 +9886,7 @@ ibf_dump_code(struct ibf_dump *dump, const rb_iseq_t *iseq) https://github.com/ruby/ruby/blob/trunk/compile.c#L9886
                 wv = (VALUE)ibf_dump_iseq(dump, (const rb_iseq_t *)op);
                 break;
               case TS_IC:
+              case TS_IVC:
               case TS_ISE:
                 {
                     unsigned int i;
@@ -9974,6 +9978,7 @@ ibf_load_code(const struct ibf_load *load, const rb_iseq_t *iseq, ibf_offset_t b https://github.com/ruby/ruby/blob/trunk/compile.c#L9978
                 FL_SET(iseq, ISEQ_MARKABLE_ISEQ);
                 /* fall through */
               case TS_IC:
+              case TS_IVC:
                 {
                     VALUE op = ibf_load_small_value(load, &reading_pos);
                     code[code_index] = (VALUE)&is_entries[op];
diff --git a/insns.def b/insns.def
index 9bad676..bd1bffb 100644
--- a/insns.def
+++ b/insns.def
@@ -207,7 +207,7 @@ setspecial https://github.com/ruby/ruby/blob/trunk/insns.def#L207
 /* Get value of instance variable id of self. */
 DEFINE_INSN
 getinstancevariable
-(ID id, IC ic)
+(ID id, IVC ic)
 ()
 (VALUE val)
 /* "instance variable not initialized" warning can be hooked. */
@@ -219,7 +219,7 @@ getinstancevariable https://github.com/ruby/ruby/blob/trunk/insns.def#L219
 /* Set value of instance variable id of self to val. */
 DEFINE_INSN
 setinstancevariable
-(ID id, IC ic)
+(ID id, IVC ic)
 (VALUE val)
 ()
 // attr bool leaf = false; /* has rb_check_frozen_internal() */
@@ -1040,7 +1040,7 @@ opt_getinlinecache https://github.com/ruby/ruby/blob/trunk/insns.def#L1040
 (VALUE val)
 {
     if (vm_ic_hit_p(ic, GET_EP())) {
-	val = ic->ic_value.value;
+	val = ic->value;
 	JUMP(dst);
     }
     else {
diff --git a/iseq.c b/iseq.c
index 4277398..7fbb906 100644
--- a/iseq.c
+++ b/iseq.c
@@ -1917,6 +1917,7 @@ rb_insn_operand_intern(const rb_iseq_t *iseq, https://github.com/ruby/ruby/blob/trunk/iseq.c#L1917
 	break;
 
       case TS_IC:
+      case TS_IVC:
       case TS_ISE:
 	ret = rb_sprintf("<is:%"PRIdPTRDIFF">", (union iseq_inline_storage_entry *)op - iseq->body->is_entries);
 	break;
@@ -2741,6 +2742,7 @@ iseq_data_to_ary(const rb_iseq_t *iseq) https://github.com/ruby/ruby/blob/trunk/iseq.c#L2742
 		}
 		break;
 	      case TS_IC:
+              case TS_IVC:
 	      case TS_ISE:
 		{
 		    union iseq_inline_storage_entry *is = (union iseq_inline_storage_entry *)*seq;
diff --git a/tool/ruby_vm/models/typemap.rb b/tool/ruby_vm/models/typemap.rb
index 015aa05..c4b13f6 100644
--- a/tool/ruby_vm/models/typemap.rb
+++ b/tool/ruby_vm/models/typemap.rb
@@ -16,6 +16,7 @@ RubyVM::Typemap = { https://github.com/ruby/ruby/blob/trunk/tool/ruby_vm/models/typemap.rb#L16
   "CDHASH"         => %w[H TS_CDHASH],
   "GENTRY"         => %w[G TS_GENTRY],
   "IC"             => %w[K TS_IC],
+  "IVC"            => %w[A TS_IVC],
   "ID"             => %w[I TS_ID],
   "ISE"            => %w[T TS_ISE],
   "ISEQ"           => %w[S TS_ISEQ],
diff --git a/tool/ruby_vm/views/_mjit_compile_ivar.erb b/tool/ruby_vm/views/_mjit_compile_ivar.erb
index 4b4dcec..57f8d14 100644
--- a/tool/ruby_vm/views/_mjit_compile_ivar.erb
+++ b/tool/ruby_vm/views/_mjit_compile_ivar.erb
@@ -13,8 +13,8 @@ https://github.com/ruby/ruby/blob/trunk/tool/ruby_vm/views/_mjit_compile_ivar.erb#L13
 % insn.opes.each_with_index do |ope, i|
     MAYBE_UNUSED(<%= ope.fetch(:decl) %>) = (<%= ope.fetch(:type) %>)operands[<%= i %>];
 % end
-% # compiler: Use copied IC to avoid race condition
-    IC ic_copy = &(status->is_entries + ((union iseq_inline_storage_entry *)ic - body->is_entries))->cache;
+% # compiler: Use copied IVC to avoid race condition
+    IVC ic_copy = &(status->is_entries + ((union iseq_inline_storage_entry *)ic - body->is_entries))->iv_cache;
 %
 % # compiler: Consider cfp->self as T_OBJECT if ic_copy->ic_serial is set
     if (!status->compile_info->disable_ivar_cache && ic_copy->ic_serial) {
@@ -25,7 +25,7 @@ https://github.com/ruby/ruby/blob/trunk/tool/ruby_vm/views/_mjit_compile_ivar.erb#L25
         fprintf(f, "{\n");
         fprintf(f, "    VALUE obj = GET_SELF();\n");
         fprintf(f, "    const rb_serial_t ic_serial = (rb_serial_t)%"PRI_SERIALT_PREFIX"u;\n", ic_copy->ic_serial);
-        fprintf(f, "    const st_index_t index = %"PRIuSIZE";\n", ic_copy->ic_value.index);
+        fprintf(f, "    const st_index_t index = %"PRIuSIZE";\n", ic_copy->index);
 % # JIT: cache hit path of vm_getivar, or cancel JIT.
 % if insn.name == 'setinstancevariable'
         fprintf(f, "    VALUE val = stack[%d];\n", b->stack_size - 1);
diff --git a/vm_core.h b/vm_core.h
index b0787aa..f7ec156 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -220,10 +220,12 @@ typedef struct rb_compile_option_struct rb_compile_option_t; https://github.com/ruby/ruby/blob/trunk/vm_core.h#L220
 struct iseq_inline_cache_entry {
     rb_serial_t ic_serial;
     const rb_cref_t *ic_cref;
-    union {
-	size_t index;
-	VALUE value;
-    } ic_value;
+    VALUE value;
+};
+
+struct iseq_inline_iv_cache_entry {
+    rb_serial_t ic_serial;
+    size_t index;
 };
 
 union iseq_inline_storage_entry {
@@ -232,6 +234,7 @@ union iseq_inline_storage_entry { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L234
 	VALUE value;
     } once;
     struct iseq_inline_cache_entry cache;
+    struct iseq_inline_iv_cache_entry iv_cache;
 };
 
 struct rb_call_info_kw_arg {
@@ -1122,6 +1125,7 @@ enum vm_svar_index { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L1125
 
 /* inline cache */
 typedef struct iseq_inline_cache_entry *IC;
+typedef struct iseq_inline_iv_cache_entry *IVC;
 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 1c54de6..c8ea3f9 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -1008,9 +1008,9 @@ vm_search_const_defined_class(const VALUE cbase, ID id) https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L1008
     return 0;
 }
 
-ALWAYS_INLINE(static VALUE vm_getivar(VALUE, ID, IC, struct rb_call_cache *, int));
+ALWAYS_INLINE(static VALUE vm_getivar(VALUE, ID, IVC, struct rb_call_cache *, int));
 static inline VALUE
-vm_getivar(VALUE obj, ID id, IC ic, struct rb_call_cache *cc, int is_attr)
+vm_getivar(VALUE obj, ID id, IVC ic, struct rb_call_cache *cc, int is_attr)
 {
 #if OPT_IC_FOR_IVAR
     VALUE val = Qundef;
@@ -1022,7 +1022,7 @@ vm_getivar(VALUE obj, ID id, IC ic, struct rb_call_cache *cc, int is_attr) https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L1022
                     RB_DEBUG_COUNTER_INC_UNLESS(ivar_get_ic_miss_unset, cc->aux.index > 0) :
                     RB_DEBUG_COUNTER_INC_UNLESS(ivar_get_ic_miss_serial,
                                                 ic->ic_serial == RCLASS_SERIAL(RBASIC(obj)->klass)))) {
-        st_index_t index = !is_attr ? ic->ic_value.index : (cc->aux.index - 1);
+        st_index_t index = !is_attr ? ic->index : (cc->aux.index - 1);
 
         RB_DEBUG_COUNTER_INC(ivar_get_ic_hit);
 
@@ -1056,7 +1056,7 @@ vm_getivar(VALUE obj, ID id, IC ic, struct rb_call_cache *cc, int is_attr) https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L1056
 	    if (iv_index_tbl) {
 		if (st_lookup(iv_index_tbl, id, &index)) {
                     if (!is_attr) {
-                        ic->ic_value.index = index;
+                        ic->index = index;
                         ic->ic_serial = RCLASS_SERIAL(RBASIC(obj)->klass);
                     }
                     else { /* call_info */
@@ -1108,7 +1108,7 @@ vm_getivar(VALUE obj, ID id, IC ic, struct rb_call_cache *cc, int is_attr) https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L1108
 }
 
 static inline VALUE
-vm_setivar(VALUE obj, ID id, VALUE val, IC ic, struct rb_call_cache *cc, int is_attr)
+vm_setivar(VALUE obj, ID id, VALUE val, IVC ic, struct rb_call_cache *cc, int is_attr)
 {
 #if OPT_IC_FOR_IVAR
     rb_check_frozen_internal(obj);
@@ -1121,7 +1121,7 @@ vm_setivar(VALUE obj, ID id, VALUE val, IC ic, struct rb_call_cache *cc, int is_ https://github.com/ruby/ruby/blob/trunk/v (... truncated)

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]