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",