shithub: libmujs

Download patch

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));