shithub: libmujs

Download patch

ref: 1c52e8b7b403802b11f85ec68a221ab2cd31bdb5
parent: 46b9d8c7e779f9cee7ae636daa8acd320e261aba
author: Tor Andersson <tor@ccxvii.net>
date: Wed Mar 12 11:19:31 EDT 2014

Fix semantics of x++: return ToNumber(x) rather than x.

Remove unused opcodes.

--- a/jscompile.c
+++ b/jscompile.c
@@ -342,12 +342,11 @@
 	}
 }
 
-static void cassignop1(JF, js_Ast *lhs, int dup)
+static void cassignop1(JF, js_Ast *lhs)
 {
 	switch (lhs->type) {
 	case EXP_IDENTIFIER:
 		emitlocal(J, F, OP_GETLOCAL, OP_GETVAR, lhs->string);
-		if (dup) emit(J, F, OP_DUP);
 		break;
 	case EXP_INDEX:
 		cexp(J, F, lhs->a);
@@ -354,13 +353,11 @@
 		cexp(J, F, lhs->b);
 		emit(J, F, OP_DUP2);
 		emit(J, F, OP_GETPROP);
-		if (dup) emit(J, F, OP_DUP1ROT4);
 		break;
 	case EXP_MEMBER:
 		cexp(J, F, lhs->a);
 		emit(J, F, OP_DUP);
 		emitstring(J, F, OP_GETPROP_S, lhs->b->string);
-		if (dup) emit(J, F, OP_DUP1ROT3);
 		break;
 	default:
 		jsC_error(J, lhs, "invalid l-value in assignment");
@@ -367,16 +364,19 @@
 	}
 }
 
-static void cassignop2(JF, js_Ast *lhs)
+static void cassignop2(JF, js_Ast *lhs, int postfix)
 {
 	switch (lhs->type) {
 	case EXP_IDENTIFIER:
+		if (postfix) emit(J, F, OP_ROT2);
 		emitlocal(J, F, OP_SETLOCAL, OP_SETVAR, lhs->string);
 		break;
 	case EXP_INDEX:
+		if (postfix) emit(J, F, OP_ROT4);
 		emit(J, F, OP_SETPROP);
 		break;
 	case EXP_MEMBER:
+		if (postfix) emit(J, F, OP_ROT3);
 		emitstring(J, F, OP_SETPROP_S, lhs->b->string);
 		break;
 	default:
@@ -386,10 +386,10 @@
 
 static void cassignop(JF, js_Ast *lhs, js_Ast *rhs, int opcode)
 {
-	cassignop1(J, F, lhs, 0);
+	cassignop1(J, F, lhs);
 	cexp(J, F, rhs);
 	emit(J, F, opcode);
-	cassignop2(J, F, lhs);
+	cassignop2(J, F, lhs, 0);
 }
 
 static void cdelete(JF, js_Ast *exp)
@@ -504,28 +504,28 @@
 		break;
 
 	case EXP_PREINC:
-		cassignop1(J, F, exp->a, 0);
+		cassignop1(J, F, exp->a);
 		emit(J, F, OP_INC);
-		cassignop2(J, F, exp->a);
+		cassignop2(J, F, exp->a, 0);
 		break;
 
 	case EXP_PREDEC:
-		cassignop1(J, F, exp->a, 0);
+		cassignop1(J, F, exp->a);
 		emit(J, F, OP_DEC);
-		cassignop2(J, F, exp->a);
+		cassignop2(J, F, exp->a, 0);
 		break;
 
 	case EXP_POSTINC:
-		cassignop1(J, F, exp->a, 1);
-		emit(J, F, OP_INC);
-		cassignop2(J, F, exp->a);
+		cassignop1(J, F, exp->a);
+		emit(J, F, OP_POSTINC);
+		cassignop2(J, F, exp->a, 1);
 		emit(J, F, OP_POP);
 		break;
 
 	case EXP_POSTDEC:
-		cassignop1(J, F, exp->a, 1);
-		emit(J, F, OP_DEC);
-		cassignop2(J, F, exp->a);
+		cassignop1(J, F, exp->a);
+		emit(J, F, OP_POSTDEC);
+		cassignop2(J, F, exp->a, 1);
 		emit(J, F, OP_POP);
 		break;
 
@@ -717,13 +717,19 @@
 		case STM_FOR_IN_VAR:
 			/* pop the iterator if leaving the loop */
 			if (F->script) {
-				if (T == STM_RETURN || T == STM_BREAK || (T == STM_CONTINUE && target != node))
-					emit(J, F, OP_ROT2POP1); /* pop the iterator, save the return or exp value */
+				if (T == STM_RETURN || T == STM_BREAK || (T == STM_CONTINUE && target != node)) {
+					/* pop the iterator, save the return or exp value */
+					emit(J, F, OP_ROT2);
+					emit(J, F, OP_POP);
+				}
 				if (T == STM_CONTINUE)
 					emit(J, F, OP_ROT2); /* put the iterator back on top */
 			} else {
-				if (T == STM_RETURN)
-					emit(J, F, OP_ROT2POP1); /* pop the iterator, save the return value */
+				if (T == STM_RETURN) {
+					/* pop the iterator, save the return value */
+					emit(J, F, OP_ROT2);
+					emit(J, F, OP_POP);
+				}
 				if (T == STM_BREAK || (T == STM_CONTINUE && target != node))
 					emit(J, F, OP_POP); /* pop the iterator */
 			}
--- a/jscompile.h
+++ b/jscompile.h
@@ -4,15 +4,11 @@
 enum js_OpCode
 {
 	OP_POP,		/* A -- */
-	OP_POP2,	/* A B -- */
 	OP_DUP,		/* A -- A A */
 	OP_DUP2,	/* A B -- A B A B */
 	OP_ROT2,	/* A B -- B A */
 	OP_ROT3,	/* A B C -- C A B */
-	OP_ROT2POP1,	/* A B -- B */
-	OP_ROT3POP2,	/* A B C -- C */
-	OP_DUP1ROT3,	/* A B -- B A B */
-	OP_DUP1ROT4,	/* A B C -- C A B C */
+	OP_ROT4,	/* A B C D -- D A B C */
 
 	OP_NUMBER_0,	/* -- 0 */
 	OP_NUMBER_1,	/* -- 1 */
@@ -74,8 +70,10 @@
 	OP_NEG,
 	OP_BITNOT,
 	OP_LOGNOT,
-	OP_INC,
-	OP_DEC,
+	OP_INC,		/* <x> -- ToNumber(x)+1 */
+	OP_DEC,		/* <x> -- ToNumber(x)-1 */
+	OP_POSTINC,	/* <x> -- ToNumber(x)+1 ToNumber(x) */
+	OP_POSTDEC,	/* <x> -- ToNumber(x)-1 ToNumber(x) */
 
 	OP_MUL,
 	OP_DIV,
--- a/jsrun.c
+++ b/jsrun.c
@@ -366,6 +366,16 @@
 	STACK[TOP-3] = tmp;		/* C A B */
 }
 
+void js_rot4(js_State *J)
+{
+	/* A B C D -> D A B C */
+	js_Value tmp = STACK[TOP-1];	/* A B C D (D) */
+	STACK[TOP-1] = STACK[TOP-2];	/* A B C C */
+	STACK[TOP-2] = STACK[TOP-3];	/* A B B C */
+	STACK[TOP-3] = STACK[TOP-4];	/* A A B C */
+	STACK[TOP-4] = tmp;		/* D A B C */
+}
+
 void js_rot2pop1(js_State *J)
 {
 	/* A B -> B */
@@ -380,27 +390,6 @@
 	TOP -= 2;
 }
 
-void js_dup1rot3(js_State *J)
-{
-	CHECKSTACK(1);
-	/* A B -> B A B */
-	STACK[TOP] = STACK[TOP-1];	/* A B B */
-	STACK[TOP-1] = STACK[TOP-2];	/* A A B */
-	STACK[TOP-2] = STACK[TOP];	/* B A B */
-	++TOP;
-}
-
-void js_dup1rot4(js_State *J)
-{
-	CHECKSTACK(1);
-	/* A B C -> C A B C */
-	STACK[TOP] = STACK[TOP-1];	/* A B C C */
-	STACK[TOP-1] = STACK[TOP-2];	/* A B B C */
-	STACK[TOP-2] = STACK[TOP-3];	/* A A B C */
-	STACK[TOP-3] = STACK[TOP];	/* C A B C */
-	++TOP;
-}
-
 void js_rot(js_State *J, int n)
 {
 	int i;
@@ -1080,15 +1069,11 @@
 		opcode = *pc++;
 		switch (opcode) {
 		case OP_POP: js_pop(J, 1); break;
-		case OP_POP2: js_pop(J, 2); break;
 		case OP_DUP: js_dup(J); break;
 		case OP_DUP2: js_dup2(J); break;
 		case OP_ROT2: js_rot2(J); break;
 		case OP_ROT3: js_rot3(J); break;
-		case OP_ROT2POP1: js_rot2pop1(J); break;
-		case OP_ROT3POP2: js_rot3pop2(J); break;
-		case OP_DUP1ROT3: js_dup1rot3(J); break;
-		case OP_DUP1ROT4: js_dup1rot4(J); break;
+		case OP_ROT4: js_rot4(J); break;
 
 		case OP_NUMBER_0: js_pushnumber(J, 0); break;
 		case OP_NUMBER_1: js_pushnumber(J, 1); break;
@@ -1322,6 +1307,20 @@
 			x = js_tonumber(J, -1);
 			js_pop(J, 1);
 			js_pushnumber(J, x - 1);
+			break;
+
+		case OP_POSTINC:
+			x = js_tonumber(J, -1);
+			js_pop(J, 1);
+			js_pushnumber(J, x + 1);
+			js_pushnumber(J, x);
+			break;
+
+		case OP_POSTDEC:
+			x = js_tonumber(J, -1);
+			js_pop(J, 1);
+			js_pushnumber(J, x - 1);
+			js_pushnumber(J, x);
 			break;
 
 		/* Multiplicative operators */
--- a/opnames.h
+++ b/opnames.h
@@ -1,13 +1,9 @@
 "pop",
-"pop2",
 "dup",
 "dup2",
 "rot2",
 "rot3",
-"rot2pop1",
-"rot3pop2",
-"dup1rot3",
-"dup1rot4",
+"rot4",
 "number_0",
 "number_1",
 "number_n",
@@ -57,6 +53,8 @@
 "lognot",
 "inc",
 "dec",
+"postinc",
+"postdec",
 "mul",
 "div",
 "mod",