Bug 1377051 - Support JSOP_SETELEM_SUPER in Baseline
MozReview-Commit-ID: 5YycYP7J2w0
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -2343,16 +2343,57 @@ BaselineCompiler::emit_JSOP_SETELEM()
}
bool
BaselineCompiler::emit_JSOP_STRICTSETELEM()
{
return emit_JSOP_SETELEM();
}
+typedef bool (*SetObjectElementFn)(JSContext*, HandleObject, HandleValue,
+ HandleValue, HandleValue, bool);
+static const VMFunction SetObjectElementInfo =
+ FunctionInfo<SetObjectElementFn>(js::SetObjectElement, "SetObjectElement");
+
+bool
+BaselineCompiler::emit_JSOP_SETELEM_SUPER()
+{
+ bool strict = IsCheckStrictOp(JSOp(*pc));
+
+ // Incoming stack is |propval, receiver, obj, rval|. We need to shuffle
+ // stack to leave rval when operation is complete.
+
+ // Pop rval into R0, then load propval into R1 and replace with rval.
+ frame.popRegsAndSync(1);
+ masm.loadValue(frame.addressOfStackValue(frame.peek(-3)), R1);
+ masm.storeValue(R0, frame.addressOfStackValue(frame.peek(-3)));
+
+ prepareVMCall();
+
+ pushArg(Imm32(strict));
+ masm.loadValue(frame.addressOfStackValue(frame.peek(-2)), R2);
+ pushArg(R2); // receiver
+ pushArg(R0); // rval
+ pushArg(R1); // propval
+ masm.unboxObject(frame.addressOfStackValue(frame.peek(-1)), R0.scratchReg());
+ pushArg(R0.scratchReg()); // obj
+
+ if (!callVM(SetObjectElementInfo))
+ return false;
+
+ frame.popn(2);
+ return true;
+}
+
+bool
+BaselineCompiler::emit_JSOP_STRICTSETELEM_SUPER()
+{
+ return emit_JSOP_SETELEM_SUPER();
+}
+
typedef bool (*DeleteElementFn)(JSContext*, HandleValue, HandleValue, bool*);
static const VMFunction DeleteElementStrictInfo
= FunctionInfo<DeleteElementFn>(DeleteElementJit<true>, "DeleteElementStrict");
static const VMFunction DeleteElementNonStrictInfo
= FunctionInfo<DeleteElementFn>(DeleteElementJit<false>, "DeleteElementNonStrict");
bool
BaselineCompiler::emit_JSOP_DELELEM()
--- a/js/src/jit/BaselineCompiler.h
+++ b/js/src/jit/BaselineCompiler.h
@@ -118,16 +118,18 @@ namespace jit {
_(JSOP_ARRAYPUSH) \
_(JSOP_GETELEM) \
_(JSOP_SETELEM) \
_(JSOP_STRICTSETELEM) \
_(JSOP_CALLELEM) \
_(JSOP_DELELEM) \
_(JSOP_STRICTDELELEM) \
_(JSOP_GETELEM_SUPER) \
+ _(JSOP_SETELEM_SUPER) \
+ _(JSOP_STRICTSETELEM_SUPER) \
_(JSOP_IN) \
_(JSOP_HASOWN) \
_(JSOP_GETGNAME) \
_(JSOP_BINDGNAME) \
_(JSOP_SETGNAME) \
_(JSOP_STRICTSETGNAME) \
_(JSOP_SETNAME) \
_(JSOP_STRICTSETNAME) \
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -2944,24 +2944,23 @@ CASE(JSOP_STRICTSETELEM)
END_CASE(JSOP_SETELEM)
CASE(JSOP_SETELEM_SUPER)
CASE(JSOP_STRICTSETELEM_SUPER)
{
static_assert(JSOP_SETELEM_SUPER_LENGTH == JSOP_STRICTSETELEM_SUPER_LENGTH,
"setelem-super and strictsetelem-super must be the same size");
- ReservedRooted<jsid> id(&rootId0);
- FETCH_ELEMENT_ID(-4, id);
+ ReservedRooted<Value> index(&rootValue1, REGS.sp[-4]);
ReservedRooted<Value> receiver(&rootValue0, REGS.sp[-3]);
ReservedRooted<JSObject*> obj(&rootObject1, ®S.sp[-2].toObject());
HandleValue value = REGS.stackHandleAt(-1);
bool strict = JSOp(*REGS.pc) == JSOP_STRICTSETELEM_SUPER;
- if (!SetObjectElementOperation(cx, obj, id, value, receiver, strict))
+ if (!SetObjectElement(cx, obj, index, value, receiver, strict))
goto error;
REGS.sp[-4] = value;
REGS.sp -= 3;
}
END_CASE(JSOP_SETELEM_SUPER)
CASE(JSOP_EVAL)
CASE(JSOP_STRICTEVAL)
@@ -4616,16 +4615,26 @@ js::SetObjectElement(JSContext* cx, Hand
if (!ToPropertyKey(cx, index, &id))
return false;
RootedValue receiver(cx, ObjectValue(*obj));
return SetObjectElementOperation(cx, obj, id, value, receiver, strict, script, pc);
}
bool
js::SetObjectElement(JSContext* cx, HandleObject obj, HandleValue index, HandleValue value,
+ HandleValue receiver, bool strict)
+{
+ RootedId id(cx);
+ if (!ToPropertyKey(cx, index, &id))
+ return false;
+ return SetObjectElementOperation(cx, obj, id, value, receiver, strict);
+}
+
+bool
+js::SetObjectElement(JSContext* cx, HandleObject obj, HandleValue index, HandleValue value,
HandleValue receiver, bool strict, HandleScript script, jsbytecode* pc)
{
MOZ_ASSERT(pc);
RootedId id(cx);
if (!ToPropertyKey(cx, index, &id))
return false;
return SetObjectElementOperation(cx, obj, id, value, receiver, strict, script, pc);
}
--- a/js/src/vm/Interpreter.h
+++ b/js/src/vm/Interpreter.h
@@ -434,16 +434,19 @@ bool
SetObjectElement(JSContext* cx, HandleObject obj, HandleValue index, HandleValue value,
bool strict);
bool
SetObjectElement(JSContext* cx, HandleObject obj, HandleValue index, HandleValue value,
bool strict, HandleScript script, jsbytecode* pc);
bool
SetObjectElement(JSContext* cx, HandleObject obj, HandleValue index, HandleValue value,
+ HandleValue receiver, bool strict);
+bool
+SetObjectElement(JSContext* cx, HandleObject obj, HandleValue index, HandleValue value,
HandleValue receiver, bool strict, HandleScript script, jsbytecode* pc);
bool
InitElementArray(JSContext* cx, jsbytecode* pc,
HandleObject obj, uint32_t index, HandleValue value);
bool
AddValues(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res);