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

ruby-changes:69819

From: Koichi <ko1@a...>
Date: Fri, 19 Nov 2021 08:32:49 +0900 (JST)
Subject: [ruby-changes:69819] 82ea287018 (master): optimize `Struct` getter/setter

https://git.ruby-lang.org/ruby.git/commit/?id=82ea287018

From 82ea2870188d66aa75a99f03b4e7fdd1750aa196 Mon Sep 17 00:00:00 2001
From: Koichi Sasada <ko1@a...>
Date: Thu, 18 Nov 2021 11:01:31 +0900
Subject: optimize `Struct` getter/setter

Introduce new optimized method type
`OPTIMIZED_METHOD_TYPE_STRUCT_AREF/ASET` with index information.
---
 common.mk              |   1 +
 compile.c              |  95 ------------------------
 debug_counter.h        |   2 +
 method.h               |   3 +
 proc.c                 |   6 ++
 struct.c               |  70 ++----------------
 test/ruby/test_yjit.rb |   2 +
 vm_eval.c              |  39 ++++++----
 vm_insnhelper.c        | 196 ++++++++++++++++++++++++++++++++++---------------
 vm_method.c            |   5 +-
 10 files changed, 181 insertions(+), 238 deletions(-)

diff --git a/common.mk b/common.mk
index ebf98993f64..7ba32ac6e8f 100644
--- a/common.mk
+++ b/common.mk
@@ -16068,6 +16068,7 @@ vm.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h https://github.com/ruby/ruby/blob/trunk/common.mk#L16068
 vm.$(OBJEXT): $(top_srcdir)/internal/serial.h
 vm.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
 vm.$(OBJEXT): $(top_srcdir)/internal/string.h
+vm.$(OBJEXT): $(top_srcdir)/internal/struct.h
 vm.$(OBJEXT): $(top_srcdir)/internal/symbol.h
 vm.$(OBJEXT): $(top_srcdir)/internal/thread.h
 vm.$(OBJEXT): $(top_srcdir)/internal/variable.h
diff --git a/compile.c b/compile.c
index 2b92893d801..a6505f82d6d 100644
--- a/compile.c
+++ b/compile.c
@@ -10588,101 +10588,6 @@ rb_local_defined(ID id, const rb_iseq_t *iseq) https://github.com/ruby/ruby/blob/trunk/compile.c#L10588
     return 0;
 }
 
-static int
-caller_location(VALUE *path, VALUE *realpath)
-{
-    const rb_execution_context_t *ec = GET_EC();
-    const rb_control_frame_t *const cfp =
-        rb_vm_get_ruby_level_next_cfp(ec, ec->cfp);
-
-    if (cfp) {
-	int line = rb_vm_get_sourceline(cfp);
-	*path = rb_iseq_path(cfp->iseq);
-	*realpath = rb_iseq_realpath(cfp->iseq);
-	return line;
-    }
-    else {
-	*path = rb_fstring_lit("<compiled>");
-	*realpath = *path;
-	return 1;
-    }
-}
-
-typedef struct {
-    VALUE arg;
-    VALUE func;
-    int line;
-} accessor_args;
-
-static const rb_iseq_t *
-method_for_self(VALUE name, VALUE arg, const struct rb_builtin_function *func,
-                void (*build)(rb_iseq_t *, LINK_ANCHOR *, const void *))
-{
-    VALUE path, realpath;
-    accessor_args acc;
-
-    acc.arg = arg;
-    acc.func = (VALUE)func;
-    acc.line = caller_location(&path, &realpath);
-    struct rb_iseq_new_with_callback_callback_func *ifunc =
-        rb_iseq_new_with_callback_new_callback(build, &acc);
-    return rb_iseq_new_with_callback(ifunc,
-			     rb_sym2str(name), path, realpath,
-			     INT2FIX(acc.line), 0, ISEQ_TYPE_METHOD, 0);
-}
-
-static void
-for_self_aref(rb_iseq_t *iseq, LINK_ANCHOR *ret, const void *a)
-{
-    const accessor_args *const args = (void *)a;
-    const int line = args->line;
-    struct rb_iseq_constant_body *const body = iseq->body;
-
-    iseq_set_local_table(iseq, 0);
-    body->param.lead_num = 0;
-    body->param.size = 0;
-
-    NODE dummy_line_node = generate_dummy_line_node(line, -1);
-    ADD_INSN1(ret, &dummy_line_node, putobject, args->arg);
-    ADD_INSN1(ret, &dummy_line_node, invokebuiltin, args->func);
-}
-
-static void
-for_self_aset(rb_iseq_t *iseq, LINK_ANCHOR *ret, const void *a)
-{
-    const accessor_args *const args = (void *)a;
-    const int line = args->line;
-    struct rb_iseq_constant_body *const body = iseq->body;
-    static const ID vars[] = {1, idUScore};
-
-    iseq_set_local_table(iseq, vars);
-    body->param.lead_num = 1;
-    body->param.size = 1;
-
-    NODE dummy_line_node = generate_dummy_line_node(line, -1);
-    ADD_GETLOCAL(ret, &dummy_line_node, numberof(vars)-1, 0);
-    ADD_INSN1(ret, &dummy_line_node, putobject, args->arg);
-    ADD_INSN1(ret, &dummy_line_node, invokebuiltin, args->func);
-}
-
-/*
- * func (index) -> (value)
- */
-const rb_iseq_t *
-rb_method_for_self_aref(VALUE name, VALUE arg, const struct rb_builtin_function *func)
-{
-    return method_for_self(name, arg, func, for_self_aref);
-}
-
-/*
- * func (index, value) -> (value)
- */
-const rb_iseq_t *
-rb_method_for_self_aset(VALUE name, VALUE arg, const struct rb_builtin_function *func)
-{
-    return method_for_self(name, arg, func, for_self_aset);
-}
-
 /* ISeq binary format */
 
 #ifndef IBF_ISEQ_DEBUG
diff --git a/debug_counter.h b/debug_counter.h
index 3cf80cc188b..3f0dec948fa 100644
--- a/debug_counter.h
+++ b/debug_counter.h
@@ -97,6 +97,8 @@ RB_DEBUG_COUNTER(ccf_bmethod) https://github.com/ruby/ruby/blob/trunk/debug_counter.h#L97
 RB_DEBUG_COUNTER(ccf_opt_send)
 RB_DEBUG_COUNTER(ccf_opt_call)
 RB_DEBUG_COUNTER(ccf_opt_block_call)
+RB_DEBUG_COUNTER(ccf_opt_struct_aref)
+RB_DEBUG_COUNTER(ccf_opt_struct_aset)
 RB_DEBUG_COUNTER(ccf_super_method)
 
 /*
diff --git a/method.h b/method.h
index b7c4318f830..031d2ce89f3 100644
--- a/method.h
+++ b/method.h
@@ -167,11 +167,14 @@ enum method_optimized_type { https://github.com/ruby/ruby/blob/trunk/method.h#L167
     OPTIMIZED_METHOD_TYPE_SEND,
     OPTIMIZED_METHOD_TYPE_CALL,
     OPTIMIZED_METHOD_TYPE_BLOCK_CALL,
+    OPTIMIZED_METHOD_TYPE_STRUCT_AREF,
+    OPTIMIZED_METHOD_TYPE_STRUCT_ASET,
     OPTIMIZED_METHOD_TYPE__MAX
 };
 
 typedef struct rb_method_optimized {
     enum method_optimized_type type;
+    unsigned int index;
 } rb_method_optimized_t;
 
 struct rb_method_definition_struct {
diff --git a/proc.c b/proc.c
index 9c62abb0c63..13996b102ad 100644
--- a/proc.c
+++ b/proc.c
@@ -2681,6 +2681,12 @@ rb_method_entry_min_max_arity(const rb_method_entry_t *me, int *max) https://github.com/ruby/ruby/blob/trunk/proc.c#L2681
 	  case OPTIMIZED_METHOD_TYPE_BLOCK_CALL:
 	    *max = UNLIMITED_ARGUMENTS;
 	    return 0;
+          case OPTIMIZED_METHOD_TYPE_STRUCT_AREF:
+            *max = 0;
+            return 0;
+          case OPTIMIZED_METHOD_TYPE_STRUCT_ASET:
+            *max = 1;
+            return 0;
 	  default:
 	    break;
 	}
diff --git a/struct.c b/struct.c
index ad8b480d8d1..2f296b34f62 100644
--- a/struct.c
+++ b/struct.c
@@ -28,9 +28,6 @@ enum { https://github.com/ruby/ruby/blob/trunk/struct.c#L28
     AREF_HASH_THRESHOLD = 10
 };
 
-const rb_iseq_t *rb_method_for_self_aref(VALUE name, VALUE arg, const struct rb_builtin_function *func);
-const rb_iseq_t *rb_method_for_self_aset(VALUE name, VALUE arg, const struct rb_builtin_function *func);
-
 VALUE rb_cStruct;
 static ID id_members, id_back_members, id_keyword_init;
 
@@ -229,32 +226,6 @@ rb_struct_getmember(VALUE obj, ID id) https://github.com/ruby/ruby/blob/trunk/struct.c#L226
     UNREACHABLE_RETURN(Qnil);
 }
 
-static VALUE rb_struct_ref0(VALUE obj) {return RSTRUCT_GET(obj, 0);}
-static VALUE rb_struct_ref1(VALUE obj) {return RSTRUCT_GET(obj, 1);}
-static VALUE rb_struct_ref2(VALUE obj) {return RSTRUCT_GET(obj, 2);}
-static VALUE rb_struct_ref3(VALUE obj) {return RSTRUCT_GET(obj, 3);}
-static VALUE rb_struct_ref4(VALUE obj) {return RSTRUCT_GET(obj, 4);}
-static VALUE rb_struct_ref5(VALUE obj) {return RSTRUCT_GET(obj, 5);}
-static VALUE rb_struct_ref6(VALUE obj) {return RSTRUCT_GET(obj, 6);}
-static VALUE rb_struct_ref7(VALUE obj) {return RSTRUCT_GET(obj, 7);}
-static VALUE rb_struct_ref8(VALUE obj) {return RSTRUCT_GET(obj, 8);}
-static VALUE rb_struct_ref9(VALUE obj) {return RSTRUCT_GET(obj, 9);}
-
-#define N_REF_FUNC numberof(ref_func)
-
-static VALUE (*const ref_func[])(VALUE) = {
-    rb_struct_ref0,
-    rb_struct_ref1,
-    rb_struct_ref2,
-    rb_struct_ref3,
-    rb_struct_ref4,
-    rb_struct_ref5,
-    rb_struct_ref6,
-    rb_struct_ref7,
-    rb_struct_ref8,
-    rb_struct_ref9,
-};
-
 static void
 rb_struct_modify(VALUE s)
 {
@@ -300,42 +271,16 @@ struct_pos_num(VALUE s, VALUE idx) https://github.com/ruby/ruby/blob/trunk/struct.c#L271
     return i;
 }
 
-static VALUE
-opt_struct_aref(rb_execution_context_t *ec, VALUE self, VALUE idx)
-{
-    long i = struct_pos_num(self, idx);
-    return RSTRUCT_GET(self, i);
-}
-
-static VALUE
-opt_struct_aset(rb_execution_context_t *ec, VALUE self, VALUE val, VALUE idx)
-{
-    long i = struct_pos_num(self, idx);
-    rb_struct_modify(self);
-    RSTRUCT_SET(self, i, val);
-    return val;
-}
-
-static const struct rb_builtin_function struct_aref_builtin =
-    RB_BUILTIN_FUNCTION(0, struct_aref, opt_struct_aref, 1, 0);
-static const struct rb_builtin_function struct_aset_builtin =
-    RB_BUILTIN_FUNCTION(1, struct_aref, opt_struct_aset, 2, 0);
-
 static void
 define_aref_method(VALUE nstr, VALUE name, VALUE off)
 {
-    const rb_iseq_t *iseq = rb_method_for_self_aref(name, off, &struct_aref_builtin);
-    iseq->body->builtin_inline_p = true;
-
-    rb_add_method_iseq(nstr, SYM2ID(name), iseq, NULL, METHOD_VISI_PUBLIC);
+    rb_add_method_optimized(nstr, SYM2ID(name), OPTIMIZED_METHOD_TYPE_STRUCT_AREF, FIX2UINT(off), METHOD_VISI_PUBLIC);
 }
 
 static void
 define_aset_method(VALUE nstr, VALUE name, VALUE off)
 {
-    const rb_iseq_t *iseq = rb_method_for_self_aset(name, off, &struct_aset_builtin);
-
-    rb_add_method_iseq(nstr, SYM2ID(name), iseq, NULL, METHOD_VISI_PUBLIC);
+    rb_add_method_optimized(nstr, SYM2ID(name), OPTIMIZED_METHOD_TYPE_STRUCT_ASET, FIX2UINT(off), METHOD_VISI_PUBLIC);
 }
 
 static VALUE
@@ -386,13 +331,8 @@ setup_struct(VALUE nstr, VALUE members) https://github.com/ruby/ruby/blob/trunk/struct.c#L331
         ID id = SYM2ID(sym);
 	VALUE off = LONG2NUM(i);
 
-	if (i < N_REF_FUNC) {
-	    rb_define_method_id(nstr, id, ref_func[i], 0);
-	}
-	else {
-            define_aref_method(nstr, sym, off);
-	}
-	define_aset_method(nstr, ID2SYM(rb_id_attrset(id)), off);
+        define_aref_method(nstr, sym, off);
+        define_aset_method(nstr, ID2SYM(rb_id_attrset(id)), off);
     }
 
     return nstr;
@@ -844,7 +784,7 @@ rb_struct_alloc(VALUE klass, VALUE values) https://github.com/ruby/ruby/blob/trunk/struct.c#L784
 VALUE
 rb_struct_new(VALUE klass, ...)
 {
-    VALUE tmpargs[N_REF_FUNC], *mem = tmpargs;
+    VALUE tmpargs[16], * (... truncated)

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

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