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

ruby-changes:54908

From: ko1 <ko1@a...>
Date: Fri, 22 Feb 2019 05:59:13 +0900 (JST)
Subject: [ruby-changes:54908] ko1:r67113 (trunk): refactoring compile.c.

ko1	2019-02-22 05:59:08 +0900 (Fri, 22 Feb 2019)

  New Revision: 67113

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=67113

  Log:
    refactoring compile.c.
    
    * compile.c: refacetoring:
      * initialize `branches` with Qfalse intead of 0.
      * make compile_call* functions from `iseq_compile_each0()`
        to make modifying them easy.

  Modified files:
    trunk/compile.c
Index: compile.c
===================================================================
--- compile.c	(revision 67112)
+++ compile.c	(revision 67113)
@@ -4982,7 +4982,7 @@ compile_if(rb_iseq_t *iseq, LINK_ANCHOR https://github.com/ruby/ruby/blob/trunk/compile.c#L4982
     DECL_ANCHOR(then_seq);
     DECL_ANCHOR(else_seq);
     LABEL *then_label, *else_label, *end_label;
-    VALUE branches = 0;
+    VALUE branches = Qfalse;
     int ci_size, ci_kw_size;
 
     INIT_ANCHOR(cond_seq);
@@ -5069,7 +5069,7 @@ compile_case(rb_iseq_t *iseq, LINK_ANCHO https://github.com/ruby/ruby/blob/trunk/compile.c#L5069
     VALUE literals = rb_hash_new();
     int line, lineno, column, last_lineno, last_column;
     enum node_type type;
-    VALUE branches = 0;
+    VALUE branches = Qfalse;
 
     INIT_ANCHOR(head);
     INIT_ANCHOR(body_seq);
@@ -5185,7 +5185,7 @@ compile_case2(rb_iseq_t *iseq, LINK_ANCH https://github.com/ruby/ruby/blob/trunk/compile.c#L5185
     const NODE *node = orig_node->nd_body;
     LABEL *endlabel;
     DECL_ANCHOR(body_seq);
-    VALUE branches = 0;
+    VALUE branches = Qfalse;
 
     DECL_BRANCH_BASE(branches, nd_first_lineno(orig_node), nd_first_column(orig_node), nd_last_lineno(orig_node), nd_last_column(orig_node), "case");
 
@@ -5270,7 +5270,7 @@ compile_loop(rb_iseq_t *iseq, LINK_ANCHO https://github.com/ruby/ruby/blob/trunk/compile.c#L5270
     LABEL *prev_end_label = ISEQ_COMPILE_DATA(iseq)->end_label;
     LABEL *prev_redo_label = ISEQ_COMPILE_DATA(iseq)->redo_label;
     int prev_loopval_popped = ISEQ_COMPILE_DATA(iseq)->loopval_popped;
-    VALUE branches = 0;
+    VALUE branches = Qfalse;
 
     struct iseq_compile_data_ensure_node_stack enl;
 
@@ -5869,29 +5869,6 @@ compile_evstr(rb_iseq_t *iseq, LINK_ANCH https://github.com/ruby/ruby/blob/trunk/compile.c#L5869
     return COMPILE_OK;
 }
 
-static int iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int popped);
-/**
-  compile each node
-
-  self:  InstructionSequence
-  node:  Ruby compiled node
-  popped: This node will be popped
- */
-static int
-iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, const NODE *node, int popped)
-{
-    if (node == 0) {
-	if (!popped) {
-	    int lineno = ISEQ_COMPILE_DATA(iseq)->last_line;
-	    if (lineno == 0) lineno = FIX2INT(rb_iseq_first_lineno(iseq));
-	    debugs("node: NODE_NIL(implicit)\n");
-	    ADD_INSN(ret, lineno, putnil);
-	}
-	return COMPILE_OK;
-    }
-    return iseq_compile_each0(iseq, ret, node, popped);
-}
-
 static LABEL *
 qcall_branch_start(rb_iseq_t *iseq, LINK_ANCHOR *const recv, VALUE *branches, const NODE *node, int line)
 {
@@ -5922,6 +5899,218 @@ qcall_branch_end(rb_iseq_t *iseq, LINK_A https://github.com/ruby/ruby/blob/trunk/compile.c#L5899
 }
 
 static int
+compile_call_precheck_freeze(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int line, int popped)
+{
+    /* optimization shortcut
+     *   "literal".freeze -> opt_str_freeze("literal")
+     */
+    if (node->nd_recv && nd_type(node->nd_recv) == NODE_STR &&
+        (node->nd_mid == idFreeze || node->nd_mid == idUMinus) &&
+        node->nd_args == NULL &&
+        ISEQ_COMPILE_DATA(iseq)->current_block == NULL &&
+        ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) {
+        VALUE str = freeze_literal(iseq, node->nd_recv->nd_lit);
+        if (node->nd_mid == idUMinus) {
+            ADD_INSN3(ret, line, opt_str_uminus, str,
+                      new_callinfo(iseq, idUMinus, 0, 0, NULL, FALSE),
+                      Qundef /* CALL_CACHE */);
+        }
+        else {
+            ADD_INSN3(ret, line, opt_str_freeze, str,
+                      new_callinfo(iseq, idFreeze, 0, 0, NULL, FALSE),
+                      Qundef /* CALL_CACHE */);
+        }
+        if (popped) {
+            ADD_INSN(ret, line, pop);
+        }
+        return TRUE;
+    }
+    /* optimization shortcut
+     *   obj["literal"] -> opt_aref_with(obj, "literal")
+     */
+    if (node->nd_mid == idAREF && !private_recv_p(node) && node->nd_args &&
+        nd_type(node->nd_args) == NODE_ARRAY && node->nd_args->nd_alen == 1 &&
+        nd_type(node->nd_args->nd_head) == NODE_STR &&
+        ISEQ_COMPILE_DATA(iseq)->current_block == NULL &&
+        !ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal &&
+        ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) {
+        VALUE str = freeze_literal(iseq, node->nd_args->nd_head->nd_lit);
+        CHECK(COMPILE(ret, "recv", node->nd_recv));
+        ADD_INSN3(ret, line, opt_aref_with, str,
+                  new_callinfo(iseq, idAREF, 1, 0, NULL, FALSE),
+                  NULL/* CALL_CACHE */);
+        if (popped) {
+            ADD_INSN(ret, line, pop);
+        }
+        return TRUE;
+    }
+    return FALSE;
+}
+
+static int
+compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int type, int line, int popped)
+{
+    /* call:  obj.method(...)
+     * fcall: func(...)
+     * vcall: func
+     */
+    DECL_ANCHOR(recv);
+    DECL_ANCHOR(args);
+    ID mid = node->nd_mid;
+    VALUE argc;
+    unsigned int flag = 0;
+    struct rb_call_info_kw_arg *keywords = NULL;
+    const rb_iseq_t *parent_block = ISEQ_COMPILE_DATA(iseq)->current_block;
+    LABEL *else_label = NULL;
+    VALUE branches = Qfalse;
+
+    ISEQ_COMPILE_DATA(iseq)->current_block = NULL;
+
+    INIT_ANCHOR(recv);
+    INIT_ANCHOR(args);
+#if SUPPORT_JOKE
+    if (nd_type(node) == NODE_VCALL) {
+        ID id_bitblt;
+        ID id_answer;
+
+        CONST_ID(id_bitblt, "bitblt");
+        CONST_ID(id_answer, "the_answer_to_life_the_universe_and_everything");
+
+        if (mid == id_bitblt) {
+            ADD_INSN(ret, line, bitblt);
+            return COMPILE_OK;
+        }
+        else if (mid == id_answer) {
+            ADD_INSN(ret, line, answer);
+            return COMPILE_OK;
+        }
+    }
+    /* only joke */
+    {
+        ID goto_id;
+        ID label_id;
+
+        CONST_ID(goto_id, "__goto__");
+        CONST_ID(label_id, "__label__");
+
+        if (nd_type(node) == NODE_FCALL &&
+            (mid == goto_id || mid == label_id)) {
+            LABEL *label;
+            st_data_t data;
+            st_table *labels_table = ISEQ_COMPILE_DATA(iseq)->labels_table;
+            VALUE label_name;
+
+            if (!labels_table) {
+                labels_table = st_init_numtable();
+                ISEQ_COMPILE_DATA(iseq)->labels_table = labels_table;
+            }
+            if (nd_type(node->nd_args->nd_head) == NODE_LIT &&
+                SYMBOL_P(node->nd_args->nd_head->nd_lit)) {
+
+                label_name = node->nd_args->nd_head->nd_lit;
+                if (!st_lookup(labels_table, (st_data_t)label_name, &data)) {
+                    label = NEW_LABEL(line);
+                    label->position = line;
+                    st_insert(labels_table, (st_data_t)label_name, (st_data_t)label);
+                }
+                else {
+                    label = (LABEL *)data;
+                }
+            }
+            else {
+                COMPILE_ERROR(ERROR_ARGS "invalid goto/label format");
+                goto ng;
+            }
+
+
+            if (mid == goto_id) {
+                ADD_INSNL(ret, line, jump, label);
+            }
+            else {
+                ADD_LABEL(ret, label);
+            }
+            return COMPILE_OK;
+        }
+    }
+#endif
+    /* receiver */
+    if (type == NODE_CALL || type == NODE_OPCALL || type == NODE_QCALL) {
+        int idx, level;
+
+        if (mid == idCall &&
+            nd_type(node->nd_recv) == NODE_LVAR &&
+            iseq_block_param_id_p(iseq, node->nd_recv->nd_vid, &idx, &level)) {
+            ADD_INSN2(recv, nd_line(node->nd_recv), getblockparamproxy, INT2FIX(idx + VM_ENV_DATA_SIZE - 1), INT2FIX(level));
+        }
+        else {
+            CHECK(COMPILE(recv, "recv", node->nd_recv));
+        }
+
+        if (type == NODE_QCALL) {
+            else_label = qcall_branch_start(iseq, recv, &branches, node, line);
+        }
+    }
+    else if (type == NODE_FCALL || type == NODE_VCALL) {
+        ADD_CALL_RECEIVER(recv, line);
+    }
+
+    /* args */
+    if (type != NODE_VCALL) {
+        argc = setup_args(iseq, args, node->nd_args, &flag, &keywords);
+        CHECK(!NIL_P(argc));
+    }
+    else {
+        argc = INT2FIX(0);
+    }
+
+    ADD_SEQ(ret, recv);
+    ADD_SEQ(ret, args);
+
+    debugp_param("call args argc", argc);
+    debugp_param("call method", ID2SYM(mid));
+
+    switch ((int)type) {
+      case NODE_VCALL:
+        flag |= VM_CALL_VCALL;
+        /* VCALL is funcall, so fall through */
+      case NODE_FCALL:
+        flag |= VM_CALL_FCALL;
+    }
+
+    ADD_SEND_R(ret, line, mid, argc, parent_block, INT2FIX(flag), keywords);
+
+    qcall_branch_end(iseq, ret, else_label, branches, node, line);
+    if (popped) {
+        ADD_INSN(ret, line, pop);
+    }
+    return COMPILE_OK;
+}
+
+
+static int iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int popped);
+/**
+  compile each node
+
+  self:  InstructionSequence
+  node:  Ruby compiled node
+  popped: This node will be popped
+ */
+static int
+iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, const NODE *node, int popped)
+{
+    if (node == 0) {
+	if (!popped) {
+	    int lineno = ISEQ_COMPILE_DATA(iseq)->last_line;
+	    if (lineno == 0) lineno = FIX2INT(rb_iseq_first_lineno(iseq));
+	    debugs("node: NODE_NIL(implicit)\n");
+	    ADD_INSN(ret, lineno, putnil);
+	}
+	return COMPILE_OK;
+    }
+    return iseq_compile_each0(iseq, ret, node, popped);
+}
+
+static int
 check_yield_place(const rb_iseq_t *iseq, int line)
 {
     VALUE file;
@@ -5945,8 +6134,6 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK https://github.com/ruby/ruby/blob/trunk/compile.c#L6134
     const int line = (int)nd_line(node);
     const enum node_type type = nd_type(node);
     struct rb_iseq_constant_body *const body = iseq->body;
-    LABEL *else_label = 0;
-    VALUE branches = 0;
 
     if (ISEQ_COMPILE_DATA(iseq)->last_line == line) {
 	/* ignore */
@@ -6479,187 +6666,16 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK https://github.com/ruby/ruby/blob/trunk/compile.c#L6666
 	}
 	break;
       }
-      case NODE_CALL:
-      case NODE_OPCALL:
-	/* optimization shortcut
-	 *   "literal".freeze -> opt_str_freeze("literal")
-	 */
-	if (node->nd_recv && nd_type(node->nd_recv) == NODE_STR &&
-	    (node->nd_mid == idFreeze || node->nd_mid == idUMinus) &&
-	    node->nd_args == NULL &&
-	    ISEQ_COMPILE_DATA(iseq)->current_block == NULL &&
-	    ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) {
-	    VALUE str = freeze_literal(iseq, node->nd_recv->nd_lit);
-	    if (node->nd_mid == idUMinus) {
-		ADD_INSN3(ret, line, opt_str_uminus, str,
-                          new_callinfo(iseq, idUMinus, 0, 0, NULL, FALSE),
-                          Qundef /* CALL_CACHE */);
-	    }
-	    else {
-		ADD_INSN3(ret, line, opt_str_freeze, str,
-                          new_callinfo(iseq, idFreeze, 0, 0, NULL, FALSE),
-                          Qundef /* CALL_CACHE */);
-	    }
-	    if (popped) {
-		ADD_INSN(ret, line, pop);
-	    }
-	    break;
-	}
-	/* optimization shortcut
-	 *   obj["literal"] -> opt_aref_with(obj, "literal")
-	 */
-	if (node->nd_mid == idAREF && !private_recv_p(node) && node->nd_args &&
-	    nd_type(node->nd_args) == NODE_ARRAY && node->nd_args->nd_alen == 1 &&
-	    nd_type(node->nd_args->nd_head) == NODE_STR &&
-	    ISEQ_COMPILE_DATA(iseq)->current_block == NULL &&
-            !ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal &&
-	    ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) {
-	    VALUE str = freeze_literal(iseq, node->nd_args->nd_head->nd_lit);
-	    CHECK(COMPILE(ret, "recv", node->nd_recv));
-	    ADD_INSN3(ret, line, opt_aref_with, str,
-		      new_callinfo(iseq, idAREF, 1, 0, NULL, FALSE),
-		      NULL/* CALL_CACHE */);
-	    if (popped) {
-		ADD_INSN(ret, line, pop);
-	    }
-	    break;
-	}
-      case NODE_QCALL:
-      case NODE_FCALL:
-      case NODE_VCALL:{		/* VCALL: variable or call */
-	/*
-	  call:  obj.method(...)
-	  fcall: func(...)
-	  vcall: func
-	*/
-	DECL_ANCHOR(recv);
-	DECL_ANCHOR(args);
-	ID mid = node->nd_mid;
-	VALUE argc;
-	unsigned int flag = 0;
-	struct rb_call_info_kw_arg *keywords = NULL;
-	const rb_iseq_t *parent_block = ISEQ_COMPILE_DATA(iseq)->current_block;
-	ISEQ_COMPILE_DATA(iseq)->current_block = NULL;
-
-	INIT_ANCHOR(recv);
-	INIT_ANCHOR(args);
-#if SUPPORT_JOKE
-	if (nd_type(node) == NODE_VCALL) {
-            ID id_bitblt;
-	    ID id_answer;
-
-            CONST_ID(id_bitblt, "bitblt");
-	    CONST_ID(id_answer, "the_answer_to_life_the_universe_and_everything");
-
-            if (mid == id_bitblt) {
-                ADD_INSN(ret, line, bitblt);
-                break;
-            }
-            else if (mid == id_answer) {
-		ADD_INSN(ret, line, answer);
-		break;
-	    }
-	}
-	/* only joke */
-	{
-	    ID goto_id;
-	    ID label_id;
-
-	    CONST_ID(goto_id, "__goto__");
-	    CONST_ID(label_id, "__label__");
-
-	    if (nd_type(node) == NODE_FCALL &&
-		(mid == goto_id || mid == label_id)) {
-		LABEL *label;
-		st_data_t data;
-		st_table *labels_table = ISEQ_COMPILE_DATA(iseq)->labels_table;
-		VALUE label_name;
-
-		if (!labels_table) {
-		    labels_table = st_init_numtable();
-		    ISEQ_COMPILE_DATA(iseq)->labels_table = labels_table;
-		}
-		if (nd_type(node->nd_args->nd_head) == NODE_LIT &&
-		    SYMBOL_P(node->nd_args->nd_head->nd_lit)) {
-
-		    label_name = node->nd_args->nd_head->nd_lit;
-		    if (!st_lookup(labels_table, (st_data_t)label_name, &data)) {
-			label = NEW_LABEL(line);
-			label->position = line;
-			st_insert(labels_table, (st_data_t)label_name, (st_data_t)label);
-		    }
-		    else {
-			label = (LABEL *)data;
-		    }
-		}
-		else {
-		    COMPILE_ERROR(ERROR_ARGS "invalid goto/label format");
-		    goto ng;
-		}
-
-
-		if (mid == goto_id) {
-		    ADD_INSNL(ret, line, jump, label);
-		}
-		else {
-		    ADD_LABEL(ret, label);
-		}
-		break;
-	    }
-	}
-#endif
-	/* receiver */
-	if (type == NODE_CALL || type == NODE_OPCALL || type == NODE_QCALL) {
-	    int idx, level;
-
-	    if (mid == idCall &&
-		nd_type(node->nd_recv) == NODE_LVAR &&
-		iseq_block_param_id_p(iseq, node->nd_recv->nd_vid, &idx, &level)) {
-		ADD_INSN2(recv, nd_line(node->nd_recv), getblockparamproxy, INT2FIX(idx + VM_ENV_DATA_SIZE - 1), INT2FIX(level));
-	    }
-	    else {
-		CHECK(COMPILE(recv, "recv", node->nd_recv));
-	    }
-
-	    if (type == NODE_QCALL) {
-                else_label = qcall_branch_start(iseq, recv, &branches, node, line);
-	    }
-	}
-	else if (type == NODE_FCALL || type == NODE_VCALL) {
-	    ADD_CALL_RECEIVER(recv, line);
-	}
-
-	/* args */
-	if (type != NODE_VCALL) {
-	    argc = setup_args(iseq, args, node->nd_args, &flag, &keywords);
-	    CHECK(!NIL_P(argc));
-	}
-	else {
-	    argc = INT2FIX(0);
-	}
-
-	ADD_SEQ(ret, recv);
-	ADD_SEQ(ret, args);
-
-	debugp_param("call args argc", argc);
-	debugp_param("call method", ID2SYM(mid));
-
-	switch ((int)type) {
-	  case NODE_VCALL:
-	    flag |= VM_CALL_VCALL;
-	    /* VCALL is funcall, so fall through */
-	  case NODE_FCALL:
-	    flag |= VM_CALL_FCALL;
-	}
-
-	ADD_SEND_R(ret, line, mid, argc, parent_block, INT2FIX(flag), keywords);
-
-        qcall_branch_end(iseq, ret, else_label, branches, node, line);
-	if (popped) {
-	    ADD_INSN(ret, line, pop);
-	}
-	break;
-      }
+      case NODE_CALL:   /* obj.foo */
+      case NODE_OPCALL: /* foo[] */
+        if (compile_call_precheck_freeze(iseq, ret, node, line, popped) == TRUE) {
+            break;
+        }
+      case NODE_QCALL: /* obj&.foo */
+      case NODE_FCALL: /* foo() */
+      case NODE_VCALL: /* foo (variable or call) */
+        compile_call(iseq, ret, node, type, line, popped);
+        break;
       case NODE_SUPER:
       case NODE_ZSUPER:{
 	DECL_ANCHOR(args);
@@ -7483,6 +7499,8 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK https://github.com/ruby/ruby/blob/trunk/compile.c#L7499
 	unsigned int flag = 0;
 	ID mid = node->nd_mid;
 	VALUE argc;
+        LABEL *else_label = NULL;
+        VALUE branches = Qfalse;
 
 	/* optimization shortcut
 	 *   obj["literal"] = value -> opt_aset_with(obj, "literal", value)

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

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