Bug 1377051 - Support JSOP_SETPROP_SUPER in Baseline r=jandem

MozReview-Commit-ID: LNOVCntYDsM

--HG--
extra : rebase_source : 987cd42d72fc3beca649025295a9ac725c31b88b
This commit is contained in:
Ted Campbell 2017-06-29 15:02:53 -04:00
Родитель d4a17dec07
Коммит 3e2612fce6
6 изменённых файлов: 192 добавлений и 7 удалений

Просмотреть файл

@ -0,0 +1,64 @@
var g_foo = "foo";
var g_bar = "bar";
// Define base class with a read-only and a writable data property
class Base
{
}
Object.defineProperty(Base.prototype, "foo", { value: "Base", writable: true });
Object.defineProperty(Base.prototype, "bar", { value: "Base", writable: false });
// Test various cases that should throw during SETPROP_SUPER
class Derived extends Base
{
// ECMA-2018 9.1.9.1, step 4.a
testReadonly() {
super.bar = "Derived";
}
testReadonlyElem() {
super[g_bar] = "Derived";
}
// ECMA-2018 9.1.9.1, step 4.b
testPrimitiveReceiver() {
super.foo = "Derived";
}
testPrimitiveReceiverElem() {
super[g_foo] = "Derived";
}
// ECMA-2018 9.1.9.1, step 4.d.i
testAccessorShadow() {
Object.defineProperty(this, "foo", { get: function() { } });
super.foo = "Derived";
}
testAccessorShadowElem() {
Object.defineProperty(this, "foo", { get: function() { } });
super[g_foo] = "Derived";
}
// ECMA-2018 9.1.9.1, step 4.d.ii
testReadonlyShadow() {
Object.defineProperty(this, "foo", { writable: false });
super.foo = "Derived";
}
testReadonlyShadowElem() {
Object.defineProperty(this, "foo", { writable: false });
super[g_foo] = "Derived";
}
}
for (let i = 0; i < 10; ++i) {
var cnt = 0;
try { new Derived().testReadonly(); } catch(e) { cnt++; }
try { new Derived().testReadonlyElem(); } catch(e) { cnt++; }
try { Derived.prototype.testPrimitiveReceiver.call(null); } catch(e) { cnt++; }
try { Derived.prototype.testPrimitiveReceiverElem.call(null); } catch(e) { cnt++; }
try { new Derived().testAccessorShadow(); } catch(e) { cnt++; }
try { new Derived().testAccessorShadowElem(); } catch(e) { cnt++; }
try { new Derived().testReadonlyShadow(); } catch(e) { cnt++; }
try { new Derived().testReadonlyShadowElem(); } catch(e) { cnt++; }
assertEq(cnt, 8);
}

Просмотреть файл

@ -0,0 +1,67 @@
class Base
{
set setter(val) {
this.set_val = val;
this.set_this = this;
}
}
Base.prototype.prop = "Base";
class Derived extends Base
{
set setter(val) { super.setter = val; }
setelem(pname, val) { super[pname] = val; }
}
// Test SETPROP_SUPER invoke setters correctly
function testSetterChain() {
let d = new Derived();
for (let i = 0; i < 10; ++i)
{
d.setter = i;
assertEq(d.set_val, i);
assertEq(d.set_this, d);
}
}
function testSetterChainElem() {
let d = new Derived();
for (let i = 0; i < 10; ++i)
{
d.setelem("setter", i);
assertEq(d.set_val, i);
assertEq(d.set_this, d);
}
}
// Test that SETPROP_SUPER modifies |this| and not home object
function testSuperSetProp() {
let d = new Derived();
for (let i = 0; i < 10; ++i)
{
d.prop = i;
assertEq(d.prop, i);
assertEq(d.hasOwnProperty("prop"), true);
assertEq(Derived.prototype.prop, "Base");
}
}
function testSuperSetPropElem() {
let d = new Derived();
for (let i = 0; i < 10; ++i)
{
d.setelem("prop", i);
assertEq(d.prop, i);
assertEq(d.hasOwnProperty("prop"), true);
assertEq(Derived.prototype.prop, "Base");
}
}
testSetterChain();
testSetterChainElem();
testSuperSetProp();
testSuperSetPropElem();

Просмотреть файл

@ -2546,6 +2546,46 @@ BaselineCompiler::emit_JSOP_STRICTSETGNAME()
return emit_JSOP_SETPROP();
}
typedef bool (*SetPropertySuperFn)(JSContext*, HandleObject, HandleValue,
HandlePropertyName, HandleValue, bool);
static const VMFunction SetPropertySuperInfo =
FunctionInfo<SetPropertySuperFn>(js::SetPropertySuper, "SetPropertySuper");
bool
BaselineCompiler::emit_JSOP_SETPROP_SUPER()
{
bool strict = IsCheckStrictOp(JSOp(*pc));
// Incoming stack is |receiver, obj, rval|. We need to shuffle stack to
// leave rval when operation is complete.
// Pop rval into R0, then load receiver into R1 and replace with rval.
frame.popRegsAndSync(1);
masm.loadValue(frame.addressOfStackValue(frame.peek(-2)), R1);
masm.storeValue(R0, frame.addressOfStackValue(frame.peek(-2)));
prepareVMCall();
pushArg(Imm32(strict));
pushArg(R0); // rval
pushArg(ImmGCPtr(script->getName(pc)));
pushArg(R1); // receiver
masm.unboxObject(frame.addressOfStackValue(frame.peek(-1)), R0.scratchReg());
pushArg(R0.scratchReg()); // obj
if (!callVM(SetPropertySuperInfo))
return false;
frame.pop();
return true;
}
bool
BaselineCompiler::emit_JSOP_STRICTSETPROP_SUPER()
{
return emit_JSOP_SETPROP_SUPER();
}
bool
BaselineCompiler::emit_JSOP_GETPROP()
{

Просмотреть файл

@ -138,6 +138,8 @@ namespace jit {
_(JSOP_DELPROP) \
_(JSOP_STRICTDELPROP) \
_(JSOP_GETPROP_SUPER) \
_(JSOP_SETPROP_SUPER) \
_(JSOP_STRICTSETPROP_SUPER) \
_(JSOP_LENGTH) \
_(JSOP_GETBOUNDNAME) \
_(JSOP_GETALIASEDVAR) \

Просмотреть файл

@ -2868,18 +2868,14 @@ CASE(JSOP_STRICTSETPROP_SUPER)
static_assert(JSOP_SETPROP_SUPER_LENGTH == JSOP_STRICTSETPROP_SUPER_LENGTH,
"setprop-super and strictsetprop-super must be the same size");
ReservedRooted<Value> receiver(&rootValue0, REGS.sp[-3]);
ReservedRooted<JSObject*> obj(&rootObject0, &REGS.sp[-2].toObject());
ReservedRooted<Value> rval(&rootValue1, REGS.sp[-1]);
ReservedRooted<jsid> id(&rootId0, NameToId(script->getName(REGS.pc)));
ObjectOpResult result;
if (!SetProperty(cx, obj, id, rval, receiver, result))
goto error;
ReservedRooted<PropertyName*> name(&rootName0, script->getName(REGS.pc));
bool strict = JSOp(*REGS.pc) == JSOP_STRICTSETPROP_SUPER;
if (!result.checkStrictErrorOrWarning(cx, obj, id, strict))
if (!SetPropertySuper(cx, obj, receiver, name, rval, strict))
goto error;
REGS.sp[-3] = REGS.sp[-1];
@ -5257,3 +5253,15 @@ js::ThrowInitializedThis(JSContext* cx, AbstractFramePtr frame)
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_REINIT_THIS);
return false;
}
bool
js::SetPropertySuper(JSContext* cx, HandleObject obj, HandleValue receiver,
HandlePropertyName name, HandleValue rval, bool strict)
{
RootedId id(cx, NameToId(name));
ObjectOpResult result;
if (!SetProperty(cx, obj, id, rval, receiver, result))
return false;
return result.checkStrictErrorOrWarning(cx, obj, id, strict);
}

Просмотреть файл

@ -598,6 +598,10 @@ HomeObjectSuperBase(JSContext* cx, HandleObject homeObj);
JSObject*
SuperFunOperation(JSContext* cx, HandleObject callee);
bool
SetPropertySuper(JSContext* cx, HandleObject obj, HandleValue receiver,
HandlePropertyName id, HandleValue rval, bool strict);
} /* namespace js */
#endif /* vm_Interpreter_h */