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

ruby-changes:58034

From: =E5=8D=9C=E9=83=A8=E6=98=8C=E5=B9=B3 <ko1@a...>
Date: Mon, 30 Sep 2019 10:33:15 +0900 (JST)
Subject: [ruby-changes:58034] c11c5e69ac (master): refactor split rb_method_definition_set

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

From c11c5e69ac66ae10255a20a6b84e481f0423703d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=8D=9C=E9=83=A8=E6=98=8C=E5=B9=B3?=
 <shyouhei@r...>
Date: Fri, 20 Sep 2019 17:01:53 +0900
Subject: refactor split rb_method_definition_set

Did you know that C functions can return structs?  That has been
true since the beginning, but not that very useful until C99.  Now
that we can write compound literals, this feature is much easier
to use.  By allowing struct-returning functions, some formerly big
functions can be split into smaller ones, like this changeset.

At least GCC is smart enough to inline the split functions back
into one.  No performance penalty is observed.

diff --git a/vm_method.c b/vm_method.c
index 4abefd5..730ec35 100644
--- a/vm_method.c
+++ b/vm_method.c
@@ -211,98 +211,6 @@ static VALUE https://github.com/ruby/ruby/blob/trunk/vm_method.c#L211
     }
 }
 
-MJIT_FUNC_EXPORTED void
-rb_method_definition_set(const rb_method_entry_t *me, rb_method_definition_t *def, void *opts)
-{
-    *(rb_method_definition_t **)&me->def = def;
-
-    if (opts != NULL) {
-	switch (def->type) {
-	  case VM_METHOD_TYPE_ISEQ:
-	    {
-		rb_method_iseq_t *iseq_body = (rb_method_iseq_t *)opts;
-		rb_cref_t *method_cref, *cref = iseq_body->cref;
-
-		/* setup iseq first (before invoking GC) */
-		RB_OBJ_WRITE(me, &def->body.iseq.iseqptr, iseq_body->iseqptr);
-
-		if (0) vm_cref_dump("rb_method_definition_create", cref);
-
-		if (cref) {
-		    method_cref = cref;
-		}
-		else {
-		    method_cref = vm_cref_new_toplevel(GET_EC()); /* TODO: can we reuse? */
-		}
-
-		RB_OBJ_WRITE(me, &def->body.iseq.cref, method_cref);
-		return;
-	    }
-	  case VM_METHOD_TYPE_CFUNC:
-	    {
-                const rb_method_cfunc_t *p = (const rb_method_cfunc_t *)opts;
-                rb_method_cfunc_t c = {
-                    p->func,
-                    call_cfunc_invoker_func(p->argc),
-                    p->argc,
-                };
-                memcpy((void *)&def->body.cfunc, &c, sizeof c);
-		return;
-	    }
-	  case VM_METHOD_TYPE_ATTRSET:
-	  case VM_METHOD_TYPE_IVAR:
-	    {
-		const rb_execution_context_t *ec = GET_EC();
-		rb_control_frame_t *cfp;
-		int line;
-
-                memcpy((void *)&def->body.attr, &(rb_method_attr_t) { (ID)(VALUE)opts }, sizeof(rb_method_attr_t));
-
-		cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp);
-
-		if (cfp && (line = rb_vm_get_sourceline(cfp))) {
-		    VALUE location = rb_ary_new3(2, rb_iseq_path(cfp->iseq), INT2FIX(line));
-		    RB_OBJ_WRITE(me, &def->body.attr.location, rb_ary_freeze(location));
-		}
-		else {
-		    VM_ASSERT(def->body.attr.location == 0);
-		}
-		return;
-	    }
-	  case VM_METHOD_TYPE_BMETHOD:
-            memcpy((void *)&def->body.bmethod, &(rb_method_bmethod_t) { (VALUE)opts }, sizeof(rb_method_bmethod_t));
-            RB_OBJ_WRITTEN(me, &def->body.bmethod.proc, (VALUE)opts);
-	    return;
-	  case VM_METHOD_TYPE_NOTIMPLEMENTED:
-            {
-                rb_method_cfunc_t f = { rb_f_notimplement, call_cfunc_m1, -1, };
-                memcpy((void *)&def->body.cfunc, &f, sizeof f);
-                return;
-            }
-	  case VM_METHOD_TYPE_OPTIMIZED:
-            {
-                enum method_optimized_type t = (enum method_optimized_type)opts;
-                memcpy((void *)&def->body.optimize_type, &t, sizeof t);
-                return;
-            }
-	  case VM_METHOD_TYPE_REFINED:
-	    {
-		const rb_method_refined_t *refined = (rb_method_refined_t *)opts;
-		RB_OBJ_WRITE(me, &def->body.refined.orig_me, refined->orig_me);
-		RB_OBJ_WRITE(me, &def->body.refined.owner, refined->owner);
-		return;
-	    }
-	  case VM_METHOD_TYPE_ALIAS:
-	    RB_OBJ_WRITE(me, &def->body.alias.original_me, (rb_method_entry_t *)opts);
-	    return;
-	  case VM_METHOD_TYPE_ZSUPER:
-	  case VM_METHOD_TYPE_UNDEF:
-	  case VM_METHOD_TYPE_MISSING:
-	    return;
-	}
-    }
-}
-
 static void
 method_definition_reset(const rb_method_entry_t *me)
 {
@@ -339,6 +247,208 @@ method_definition_reset(const rb_method_entry_t *me) https://github.com/ruby/ruby/blob/trunk/vm_method.c#L247
     }
 }
 
+static rb_cref_t*
+the_top_cref(void)
+{
+    static rb_cref_t *top = NULL;
+    if (!top) {
+        top = vm_cref_new_toplevel(GET_EC());
+        rb_gc_register_mark_object((VALUE)top); // cref is an IMEMO.
+    }
+    return top;
+}
+
+static rb_method_iseq_t
+the_method_iseq(const rb_method_iseq_t *p)
+{
+    return (rb_method_iseq_t) {
+        .iseqptr = p->iseqptr,
+        .cref    = p->cref ? p->cref : the_top_cref(),
+    };
+}
+
+static rb_method_cfunc_t
+the_method_cfunc(const rb_method_cfunc_t *p)
+{
+    return (rb_method_cfunc_t) {
+        .func    = p->func,
+        .invoker = call_cfunc_invoker_func(p->argc),
+        .argc    = p->argc,
+    };
+}
+
+static VALUE
+the_location(void)
+{
+    const rb_execution_context_t *ec = GET_EC();
+    const rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp);
+    int line;
+
+    if (!cfp) {
+        return Qnil;
+    }
+    else if (! (line = rb_vm_get_sourceline(cfp))) {
+        return Qnil;
+    }
+    else {
+        VALUE loc = rb_ary_new3(2, rb_iseq_path(cfp->iseq), INT2FIX(line));
+        rb_ary_freeze(loc);
+        return loc;
+    }
+}
+
+static rb_method_attr_t
+the_method_attr(const void *p)
+{
+    return (rb_method_attr_t) {
+        .id       = (ID)(VALUE)p,
+        .location = the_location(),
+    };
+}
+
+static rb_method_bmethod_t
+the_method_bmethod(const void *p)
+{
+    return (rb_method_bmethod_t) {
+        .proc  = (VALUE)p,
+        .hooks = NULL,
+    };
+}
+
+static rb_method_cfunc_t
+the_method_notimplemented(void)
+{
+    return (rb_method_cfunc_t) {
+        .func    = rb_f_notimplement,
+        .invoker = call_cfunc_m1,
+        .argc    = -1,
+    };
+}
+
+static enum method_optimized_type
+the_method_optimized(const void *p)
+{
+    return (enum method_optimized_type)p;
+}
+
+static rb_method_refined_t
+the_method_refined(const rb_method_refined_t *p)
+{
+    return (rb_method_refined_t) {
+        .orig_me = p->orig_me,
+        .owner = p->owner,
+    };
+}
+
+static rb_method_alias_t
+the_method_alias(const rb_method_entry_t *p)
+{
+    return (rb_method_alias_t) {
+        .original_me = p,
+    };
+}
+
+static rb_method_definition_t
+rb_method_definition_new(rb_method_type_t type, ID mid, const void *opts)
+{
+    switch (type) {
+      case VM_METHOD_TYPE_ISEQ:
+        return (rb_method_definition_t) {
+            .type        = type,
+            .original_id = mid,
+            .body        = {
+                .iseq    = the_method_iseq(opts),
+            }
+        };
+
+      case VM_METHOD_TYPE_CFUNC:
+        return (rb_method_definition_t) {
+            .type        = type,
+            .original_id = mid,
+            .body        = {
+                .cfunc   = the_method_cfunc(opts),
+            }
+        };
+
+      case VM_METHOD_TYPE_ATTRSET:
+      case VM_METHOD_TYPE_IVAR:
+        return (rb_method_definition_t) {
+            .type        = type,
+            .original_id = mid,
+            .body        = {
+                .attr    = the_method_attr(opts),
+            }
+        };
+
+      case VM_METHOD_TYPE_BMETHOD:
+        return (rb_method_definition_t) {
+            .type        = type,
+            .original_id = mid,
+            .body        = {
+                .bmethod = the_method_bmethod(opts),
+            }
+        };
+
+      case VM_METHOD_TYPE_NOTIMPLEMENTED:
+        return (rb_method_definition_t) {
+            .type        = type,
+            .original_id = mid,
+            .body        = {
+                .cfunc   = the_method_notimplemented(),
+            }
+        };
+
+      case VM_METHOD_TYPE_OPTIMIZED:
+        return (rb_method_definition_t) {
+            .type        = type,
+            .original_id = mid,
+            .body        = {
+                .optimize_type = the_method_optimized(opts),
+            }
+        };
+
+      case VM_METHOD_TYPE_REFINED:
+        return (rb_method_definition_t) {
+            .type        = type,
+            .original_id = mid,
+            .body        = {
+                .refined = the_method_refined(opts),
+            }
+        };
+
+      case VM_METHOD_TYPE_ALIAS:
+        return (rb_method_definition_t) {
+            .type        = type,
+            .original_id = mid,
+            .body        = {
+                .alias   = the_method_alias(opts),
+            }
+        };
+
+      case VM_METHOD_TYPE_ZSUPER:
+      case VM_METHOD_TYPE_UNDEF:
+      case VM_METHOD_TYPE_MISSING:
+        return (rb_method_definition_t) {
+            .type        = type,
+            .original_id = mid,
+        };
+    }
+
+    UNREACHABLE_RETURN((rb_method_definition_t){0});
+}
+
+MJIT_FUNC_EXPORTED void
+rb_method_definition_set(const rb_method_entry_t *me, rb_method_definition_t *def, void *opts)
+{
+    if (opts) {
+        rb_method_definition_t template =
+            rb_method_definition_new(def->type, def->original_id, opts);
+        memcpy(def, &template, sizeof template);
+    }
+    memcpy((void *)&me->def, &def, sizeof def);
+    method_definition_reset(me);
+}
+
 MJIT_FUNC_EXPORTED const rb_method_definition_t *
 rb_method_definition_create(rb_method_type_t type, ID mid)
 {
-- 
cgit v0.10.2


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

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