ref: 40572172a5acbbd86fe610d41b6d2195d7b81fb2
parent: 6f4c2143e56d833f9a7705f34d97c48a80a65178
author: Tor Andersson <tor@ccxvii.net>
date: Thu Jan 23 11:50:54 EST 2014
Add 'string' operand versions of get/set/del property opcodes.
--- a/jscompile.c
+++ b/jscompile.c
@@ -197,15 +197,18 @@
if (kv->type == EXP_PROP_VAL) {
js_Ast *prop = kv->a;
emit(J, F, OP_DUP);
- if (prop->type == AST_IDENTIFIER || prop->type == AST_STRING)
- emitstring(J, F, OP_STRING, prop->string);
- else if (prop->type == AST_NUMBER)
+ if (prop->type == AST_IDENTIFIER || prop->type == AST_STRING) {
+ cexp(J, F, kv->b);
+ emitstring(J, F, OP_SETPROPS, prop->string);
+ emit(J, F, OP_POP);
+ } else if (prop->type == AST_NUMBER) {
emitnumber(J, F, prop->number);
- else
+ cexp(J, F, kv->b);
+ emit(J, F, OP_SETPROP);
+ emit(J, F, OP_POP);
+ } else {
jsC_error(J, list, "illegal property name in object initializer");
- cexp(J, F, kv->b);
- emit(J, F, OP_SETPROP);
- emit(J, F, OP_POP);
+ }
} else {
// TODO: set/get
jsC_error(J, kv, "property setters and getters are not implemented");
@@ -240,9 +243,8 @@
break;
case EXP_MEMBER:
cexp(J, F, lhs->a);
- emitstring(J, F, OP_STRING, lhs->b->string);
cexp(J, F, rhs);
- emit(J, F, OP_SETPROP);
+ emitstring(J, F, OP_SETPROPS, lhs->b->string);
break;
default:
jsC_error(J, lhs, "invalid l-value in assignment");
@@ -276,9 +278,8 @@
break;
case EXP_MEMBER:
cexp(J, F, lhs->a);
- emitstring(J, F, OP_STRING, lhs->b->string);
- emit(J, F, OP_ROT3);
- emit(J, F, OP_SETPROP);
+ emit(J, F, OP_ROT2);
+ emitstring(J, F, OP_SETPROPS, lhs->b->string);
emit(J, F, OP_POP);
break;
default:
@@ -303,10 +304,9 @@
break;
case EXP_MEMBER:
cexp(J, F, lhs->a);
- emitstring(J, F, OP_STRING, lhs->b->string);
- emit(J, F, OP_DUP2);
- emit(J, F, OP_GETPROP);
- if (dup) emit(J, F, OP_DUP1ROT4);
+ emit(J, F, OP_DUP);
+ emitstring(J, F, OP_GETPROPS, lhs->b->string);
+ if (dup) emit(J, F, OP_DUP1ROT3);
break;
default:
jsC_error(J, lhs, "invalid l-value in assignment");
@@ -321,9 +321,9 @@
emitstring(J, F, OP_SETVAR, lhs->string);
break;
case EXP_INDEX:
+ break;
case EXP_MEMBER:
- case EXP_CALL:
- emit(J, F, OP_SETPROP);
+ emitstring(J, F, OP_SETPROPS, lhs->b->string);
break;
default:
jsC_error(J, lhs, "invalid l-value in assignment");
@@ -352,8 +352,7 @@
break;
case EXP_MEMBER:
cexp(J, F, exp->a);
- emitstring(J, F, OP_STRING, exp->b->string);
- emit(J, F, OP_DELPROP);
+ emitstring(J, F, OP_DELPROPS, exp->b->string);
break;
default:
jsC_error(J, exp, "invalid l-value in delete expression");
@@ -375,8 +374,7 @@
case EXP_MEMBER:
cexp(J, F, fun->a);
emit(J, F, OP_DUP);
- emitstring(J, F, OP_STRING, fun->b->string);
- emit(J, F, OP_GETPROP);
+ emitstring(J, F, OP_GETPROPS, fun->b->string);
emit(J, F, OP_ROT2);
break;
default:
@@ -429,8 +427,7 @@
case EXP_MEMBER:
cexp(J, F, exp->a);
- emitstring(J, F, OP_STRING, exp->b->string);
- emit(J, F, OP_GETPROP);
+ emitstring(J, F, OP_GETPROPS, exp->b->string);
break;
case EXP_CALL:
--- a/jscompile.h
+++ b/jscompile.h
@@ -13,6 +13,7 @@
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_NUMBER_0, /* -- 0 */
@@ -41,9 +42,13 @@
OP_DELVAR, /* -S- <success> */
OP_IN, /* <name> <obj> -- <exists?> */
+
OP_GETPROP, /* <obj> <name> -- <value> */
+ OP_GETPROPS, /* <obj> -S- <value> */
OP_SETPROP, /* <obj> <name> <value> -- <value> */
+ OP_SETPROPS, /* <obj> <value> -S- <value> */
OP_DELPROP, /* <obj> <name> -- <success> */
+ OP_DELPROPS, /* <obj> -S- <success> */
OP_ITERATOR, /* <obj> -- <iobj> */
OP_NEXTITER, /* <iobj> -- <iobj> <name> true || false */
--- a/jsdump.c
+++ b/jsdump.c
@@ -648,6 +648,9 @@
case OP_GETVAR:
case OP_SETVAR:
case OP_DELVAR:
+ case OP_GETPROPS:
+ case OP_SETPROPS:
+ case OP_DELPROPS:
pc(' ');
ps(F->strtab[*p++]);
break;
--- a/jsrun.c
+++ b/jsrun.c
@@ -215,6 +215,15 @@
TOP -= 2;
}
+void js_dup1rot3(js_State *J)
+{
+ /* 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)
{
/* A B C -> C A B C */
@@ -526,6 +535,7 @@
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_NUMBER_0: js_pushnumber(J, 0); break;
@@ -596,6 +606,19 @@
js_pushundefined(J);
break;
+ case OP_GETPROPS:
+ str = ST[*pc++];
+ js_getproperty(J, -1, str);
+
+ obj = js_toobject(J, -2);
+ ref = jsV_getproperty(J, obj, str);
+ js_pop(J, 2);
+ if (ref)
+ js_pushvalue(J, ref->value);
+ else
+ js_pushundefined(J);
+ break;
+
case OP_SETPROP:
obj = js_toobject(J, -3);
str = js_tostring(J, -2);
@@ -605,7 +628,17 @@
js_rot3pop2(J);
break;
+ case OP_SETPROPS:
+ str = ST[*pc++];
+ obj = js_toobject(J, -2);
+ ref = jsV_setproperty(J, obj, str);
+ if (ref)
+ ref->value = js_tovalue(J, -1);
+ js_rot2pop1(J);
+ break;
+
// OP_DELPROP
+ // OP_DELPROPS
case OP_ITERATOR:
obj = jsV_newiterator(J, js_toobject(J, -1));