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

ruby-changes:47056

From: nobu <ko1@a...>
Date: Sun, 25 Jun 2017 17:55:30 +0900 (JST)
Subject: [ruby-changes:47056] nobu:r59171 (trunk): compile.c: fix_sp_depth

nobu	2017-06-25 17:55:23 +0900 (Sun, 25 Jun 2017)

  New Revision: 59171

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

  Log:
    compile.c: fix_sp_depth
    
    * compile.c (fix_sp_depth): separate fix-up of sp depth from code
      generation.

  Modified files:
    trunk/compile.c
Index: compile.c
===================================================================
--- compile.c	(revision 59170)
+++ compile.c	(revision 59171)
@@ -1571,6 +1571,112 @@ get_ivar_ic_value(rb_iseq_t *iseq,ID id) https://github.com/ruby/ruby/blob/trunk/compile.c#L1571
      BADINSN_DUMP(anchor, list, NULL), \
      COMPILE_ERROR)
 
+static int
+fix_sp_depth(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
+{
+    int stack_max = 0, sp = 0, line = 0;
+    LINK_ELEMENT *list;
+
+    for (list = FIRST_ELEMENT(anchor); list; list = list->next) {
+	if (list->type == ISEQ_ELEMENT_LABEL) {
+	    LABEL *lobj = (LABEL *)list;
+	    lobj->set = TRUE;
+	}
+    }
+
+    for (list = FIRST_ELEMENT(anchor); list; list = list->next) {
+	switch (list->type) {
+	  case ISEQ_ELEMENT_INSN:
+	    {
+		int j, len, insn;
+		const char *types;
+		VALUE *operands;
+		INSN *iobj = (INSN *)list;
+
+		/* update sp */
+		sp = calc_sp_depth(sp, iobj);
+		if (sp < 0) {
+		    BADINSN_DUMP(anchor, list, NULL);
+		    COMPILE_ERROR(iseq, iobj->line_no,
+				  "argument stack underflow (%d)", sp);
+		    return -1;
+		}
+		if (sp > stack_max) {
+		    stack_max = sp;
+		}
+
+		line = iobj->line_no;
+		/* fprintf(stderr, "insn: %-16s, sp: %d\n", insn_name(iobj->insn_id), sp); */
+		operands = iobj->operands;
+		insn = iobj->insn_id;
+		types = insn_op_types(insn);
+		len = insn_len(insn);
+
+		/* operand check */
+		if (iobj->operand_size != len - 1) {
+		    /* printf("operand size miss! (%d, %d)\n", iobj->operand_size, len); */
+		    BADINSN_DUMP(anchor, list, NULL);
+		    COMPILE_ERROR(iseq, iobj->line_no,
+				  "operand size miss! (%d for %d)",
+				  iobj->operand_size, len - 1);
+		    return -1;
+		}
+
+		for (j = 0; types[j]; j++) {
+		    if (types[j] == TS_OFFSET) {
+			/* label(destination position) */
+			LABEL *lobj = (LABEL *)operands[j];
+			if (!lobj->set) {
+			    BADINSN_DUMP(anchor, list, NULL);
+			    COMPILE_ERROR(iseq, iobj->line_no,
+					  "unknown label: "LABEL_FORMAT, lobj->label_no);
+			    return -1;
+			}
+			if (lobj->sp == -1) {
+			    lobj->sp = sp;
+			}
+		    }
+		}
+		break;
+	    }
+	  case ISEQ_ELEMENT_LABEL:
+	    {
+		LABEL *lobj = (LABEL *)list;
+		if (lobj->sp == -1) {
+		    lobj->sp = sp;
+		}
+		else {
+		    sp = lobj->sp;
+		}
+		break;
+	    }
+	  case ISEQ_ELEMENT_NONE:
+	    {
+		/* ignore */
+		break;
+	    }
+	  case ISEQ_ELEMENT_ADJUST:
+	    {
+		ADJUST *adjust = (ADJUST *)list;
+		int orig_sp = sp;
+
+		sp = adjust->label ? adjust->label->sp : 0;
+		if (adjust->line_no != -1 && orig_sp - sp < 0) {
+		    compile_bug(iseq, adjust->line_no,
+				"iseq_set_sequence: adjust bug %d < %d",
+				orig_sp, sp);
+		}
+		break;
+	    }
+	  default:
+	    BADINSN_DUMP(anchor, list, NULL);
+	    COMPILE_ERROR(iseq, line, "unknown list type: %d", list->type);
+	    return -1;
+	}
+    }
+    return stack_max;
+}
+
 /**
   ruby insn object list -> raw instruction sequence
  */
@@ -1582,7 +1688,10 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ https://github.com/ruby/ruby/blob/trunk/compile.c#L1688
     LINK_ELEMENT *list;
     VALUE *generated_iseq;
 
-    int insn_num, code_index, line_info_index, sp, stack_max = 0, line = 0;
+    int insn_num, code_index, line_info_index, sp = 0;
+    int stack_max = fix_sp_depth(iseq, anchor);
+
+    if (stack_max < 0) return COMPILE_NG;
 
     /* fix label position */
     list = FIRST_ELEMENT(anchor);
@@ -1592,7 +1701,6 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ https://github.com/ruby/ruby/blob/trunk/compile.c#L1701
 	  case ISEQ_ELEMENT_INSN:
 	    {
 		INSN *iobj = (INSN *)list;
-		line = iobj->line_no;
 		code_index += insn_data_length(iobj);
 		insn_num++;
 		break;
@@ -1601,7 +1709,6 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ https://github.com/ruby/ruby/blob/trunk/compile.c#L1709
 	    {
 		LABEL *lobj = (LABEL *)list;
 		lobj->position = code_index;
-		lobj->set = TRUE;
 		break;
 	    }
 	  case ISEQ_ELEMENT_NONE:
@@ -1618,10 +1725,6 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ https://github.com/ruby/ruby/blob/trunk/compile.c#L1725
 		}
 		break;
 	    }
-	  default:
-	    BADINSN_DUMP(anchor, list, NULL);
-	    COMPILE_ERROR(iseq, line, "unknown list type: %d", list->type);
-	    return COMPILE_NG;
 	}
 	list = list->next;
     }
@@ -1650,15 +1753,6 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ https://github.com/ruby/ruby/blob/trunk/compile.c#L1753
 
 		/* update sp */
 		sp = calc_sp_depth(sp, iobj);
-		if (sp < 0) {
-		    BADINSN_ERROR(iseq, iobj->line_no,
-				  "argument stack underflow (%d)", sp);
-		    return COMPILE_NG;
-		}
-		if (sp > stack_max) {
-		    stack_max = sp;
-		}
-
 		/* fprintf(stderr, "insn: %-16s, sp: %d\n", insn_name(iobj->insn_id), sp); */
 		operands = iobj->operands;
 		insn = iobj->insn_id;
@@ -1666,15 +1760,6 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ https://github.com/ruby/ruby/blob/trunk/compile.c#L1760
 		types = insn_op_types(insn);
 		len = insn_len(insn);
 
-		/* operand check */
-		if (iobj->operand_size != len - 1) {
-		    /* printf("operand size miss! (%d, %d)\n", iobj->operand_size, len); */
-		    BADINSN_ERROR(iseq, iobj->line_no,
-				  "operand size miss! (%d for %d)",
-				  iobj->operand_size, len - 1);
-		    return COMPILE_NG;
-		}
-
 		for (j = 0; types[j]; j++) {
 		    char type = types[j];
 		    /* printf("--> [%c - (%d-%d)]\n", type, k, j); */
@@ -1683,14 +1768,6 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ https://github.com/ruby/ruby/blob/trunk/compile.c#L1768
 			{
 			    /* label(destination position) */
 			    LABEL *lobj = (LABEL *)operands[j];
-			    if (!lobj->set) {
-				BADINSN_ERROR(iseq, iobj->line_no,
-					      "unknown label: "LABEL_FORMAT, lobj->label_no);
-				return COMPILE_NG;
-			    }
-			    if (lobj->sp == -1) {
-				lobj->sp = sp;
-			    }
 			    generated_iseq[code_index + 1 + j] = lobj->position - (code_index + len);
 			    break;
 			}
@@ -1793,12 +1870,7 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ https://github.com/ruby/ruby/blob/trunk/compile.c#L1870
 	  case ISEQ_ELEMENT_LABEL:
 	    {
 		LABEL *lobj = (LABEL *)list;
-		if (lobj->sp == -1) {
-		    lobj->sp = sp;
-		}
-		else {
-		    sp = lobj->sp;
-		}
+		sp = lobj->sp;
 		break;
 	    }
 	  case ISEQ_ELEMENT_ADJUST:

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

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