new classes: implement correct check for uninitialized this in 'super()'
R=arv@chromium.org BUG=v8:3834 LOG=N Review URL: https://codereview.chromium.org/918603004 Cr-Commit-Position: refs/heads/master@{#26599}
This commit is contained in:
parent
993a48f8c0
commit
fdcf3e59ba
@ -3270,18 +3270,6 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
|
||||
EmitLoadSuperConstructor();
|
||||
__ push(result_register());
|
||||
|
||||
SuperReference* super_ref = expr->expression()->AsSuperReference();
|
||||
Variable* this_var = super_ref->this_var()->var();
|
||||
|
||||
GetVar(r0, this_var);
|
||||
__ CompareRoot(r0, Heap::kTheHoleValueRootIndex);
|
||||
Label uninitialized_this;
|
||||
__ b(eq, &uninitialized_this);
|
||||
__ mov(r0, Operand(this_var->name()));
|
||||
__ Push(r0);
|
||||
__ CallRuntime(Runtime::kThrowReferenceError, 1);
|
||||
__ bind(&uninitialized_this);
|
||||
|
||||
// Push the arguments ("left-to-right") on the stack.
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
int arg_count = args->length();
|
||||
@ -3317,6 +3305,17 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
|
||||
|
||||
RecordJSReturnSite(expr);
|
||||
|
||||
SuperReference* super_ref = expr->expression()->AsSuperReference();
|
||||
Variable* this_var = super_ref->this_var()->var();
|
||||
GetVar(r1, this_var);
|
||||
__ CompareRoot(r1, Heap::kTheHoleValueRootIndex);
|
||||
Label uninitialized_this;
|
||||
__ b(eq, &uninitialized_this);
|
||||
__ mov(r0, Operand(this_var->name()));
|
||||
__ Push(r0);
|
||||
__ CallRuntime(Runtime::kThrowReferenceError, 1);
|
||||
__ bind(&uninitialized_this);
|
||||
|
||||
EmitVariableAssignment(this_var, Token::INIT_CONST);
|
||||
context()->Plug(r0);
|
||||
}
|
||||
|
@ -2956,20 +2956,9 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
|
||||
GetVar(result_register(), new_target_var);
|
||||
__ Push(result_register());
|
||||
|
||||
SuperReference* super_ref = expr->expression()->AsSuperReference();
|
||||
EmitLoadSuperConstructor();
|
||||
__ push(result_register());
|
||||
|
||||
Variable* this_var = super_ref->this_var()->var();
|
||||
|
||||
GetVar(x0, this_var);
|
||||
Label uninitialized_this;
|
||||
__ JumpIfRoot(x0, Heap::kTheHoleValueRootIndex, &uninitialized_this);
|
||||
__ Mov(x0, Operand(this_var->name()));
|
||||
__ Push(x0);
|
||||
__ CallRuntime(Runtime::kThrowReferenceError, 1);
|
||||
__ bind(&uninitialized_this);
|
||||
|
||||
// Push the arguments ("left-to-right") on the stack.
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
int arg_count = args->length();
|
||||
@ -3005,6 +2994,16 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
|
||||
|
||||
RecordJSReturnSite(expr);
|
||||
|
||||
SuperReference* super_ref = expr->expression()->AsSuperReference();
|
||||
Variable* this_var = super_ref->this_var()->var();
|
||||
GetVar(x1, this_var);
|
||||
Label uninitialized_this;
|
||||
__ JumpIfRoot(x1, Heap::kTheHoleValueRootIndex, &uninitialized_this);
|
||||
__ Mov(x0, Operand(this_var->name()));
|
||||
__ Push(x0);
|
||||
__ CallRuntime(Runtime::kThrowReferenceError, 1);
|
||||
__ bind(&uninitialized_this);
|
||||
|
||||
EmitVariableAssignment(this_var, Token::INIT_CONST);
|
||||
context()->Plug(x0);
|
||||
}
|
||||
|
@ -3146,19 +3146,9 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
|
||||
GetVar(eax, new_target_var);
|
||||
__ push(eax);
|
||||
|
||||
SuperReference* super_ref = expr->expression()->AsSuperReference();
|
||||
EmitLoadSuperConstructor();
|
||||
__ push(result_register());
|
||||
|
||||
Variable* this_var = super_ref->this_var()->var();
|
||||
GetVar(eax, this_var);
|
||||
__ cmp(eax, isolate()->factory()->the_hole_value());
|
||||
Label uninitialized_this;
|
||||
__ j(equal, &uninitialized_this);
|
||||
__ push(Immediate(this_var->name()));
|
||||
__ CallRuntime(Runtime::kThrowReferenceError, 1);
|
||||
__ bind(&uninitialized_this);
|
||||
|
||||
// Push the arguments ("left-to-right") on the stack.
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
int arg_count = args->length();
|
||||
@ -3194,6 +3184,16 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
|
||||
|
||||
RecordJSReturnSite(expr);
|
||||
|
||||
SuperReference* super_ref = expr->expression()->AsSuperReference();
|
||||
Variable* this_var = super_ref->this_var()->var();
|
||||
GetVar(ecx, this_var);
|
||||
__ cmp(ecx, isolate()->factory()->the_hole_value());
|
||||
Label uninitialized_this;
|
||||
__ j(equal, &uninitialized_this);
|
||||
__ push(Immediate(this_var->name()));
|
||||
__ CallRuntime(Runtime::kThrowReferenceError, 1);
|
||||
__ bind(&uninitialized_this);
|
||||
|
||||
EmitVariableAssignment(this_var, Token::INIT_CONST);
|
||||
context()->Plug(eax);
|
||||
}
|
||||
|
@ -3155,18 +3155,6 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
|
||||
EmitLoadSuperConstructor();
|
||||
__ Push(result_register());
|
||||
|
||||
SuperReference* super_ref = expr->expression()->AsSuperReference();
|
||||
Variable* this_var = super_ref->this_var()->var();
|
||||
|
||||
GetVar(rax, this_var);
|
||||
__ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
|
||||
Label uninitialized_this;
|
||||
__ j(equal, &uninitialized_this);
|
||||
__ Push(this_var->name());
|
||||
__ CallRuntime(Runtime::kThrowReferenceError, 1);
|
||||
__ bind(&uninitialized_this);
|
||||
|
||||
|
||||
// Push the arguments ("left-to-right") on the stack.
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
int arg_count = args->length();
|
||||
@ -3195,7 +3183,6 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
|
||||
__ Move(rbx, FeedbackVector());
|
||||
__ Move(rdx, SmiFromSlot(expr->CallFeedbackSlot()));
|
||||
|
||||
// TODO(dslomov): use a different stub and propagate new.target.
|
||||
CallConstructStub stub(isolate(), SUPER_CALL_RECORD_TARGET);
|
||||
__ call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
|
||||
|
||||
@ -3203,6 +3190,15 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
|
||||
|
||||
RecordJSReturnSite(expr);
|
||||
|
||||
SuperReference* super_ref = expr->expression()->AsSuperReference();
|
||||
Variable* this_var = super_ref->this_var()->var();
|
||||
GetVar(rcx, this_var);
|
||||
__ CompareRoot(rcx, Heap::kTheHoleValueRootIndex);
|
||||
Label uninitialized_this;
|
||||
__ j(equal, &uninitialized_this);
|
||||
__ Push(this_var->name());
|
||||
__ CallRuntime(Runtime::kThrowReferenceError, 1);
|
||||
__ bind(&uninitialized_this);
|
||||
|
||||
EmitVariableAssignment(this_var, Token::INIT_CONST);
|
||||
context()->Plug(rax);
|
||||
|
@ -89,8 +89,7 @@
|
||||
super(tmp(),4);
|
||||
} catch (e) { exn = e; }
|
||||
assertTrue(exn instanceof ReferenceError);
|
||||
// TODO(dslomov): should be 'true'.
|
||||
assertFalse(called);
|
||||
assertTrue(called);
|
||||
}
|
||||
}
|
||||
|
||||
@ -110,6 +109,61 @@
|
||||
assertThrows(function() { new BadSubclass(); }, ReferenceError);
|
||||
}());
|
||||
|
||||
(function TestThisCheckOrdering() {
|
||||
let baseCalled = 0;
|
||||
class Base {
|
||||
constructor() { baseCalled++ }
|
||||
}
|
||||
|
||||
let fCalled = 0;
|
||||
function f() { fCalled++; return 3; }
|
||||
|
||||
class Subclass1 extends Base {
|
||||
constructor() {
|
||||
baseCalled = 0;
|
||||
super();
|
||||
assertEquals(1, baseCalled);
|
||||
let obj = this;
|
||||
|
||||
let exn = null;
|
||||
baseCalled = 0;
|
||||
fCalled = 0;
|
||||
try {
|
||||
super(f());
|
||||
} catch (e) { exn = e; }
|
||||
assertTrue(exn instanceof ReferenceError);
|
||||
assertEquals(1, fCalled);
|
||||
assertEquals(1, baseCalled);
|
||||
assertSame(obj, this);
|
||||
|
||||
exn = null;
|
||||
baseCalled = 0;
|
||||
fCalled = 0;
|
||||
try {
|
||||
super(super(), f());
|
||||
} catch (e) { exn = e; }
|
||||
assertTrue(exn instanceof ReferenceError);
|
||||
assertEquals(0, fCalled);
|
||||
assertEquals(1, baseCalled);
|
||||
assertSame(obj, this);
|
||||
|
||||
exn = null;
|
||||
baseCalled = 0;
|
||||
fCalled = 0;
|
||||
try {
|
||||
super(f(), super());
|
||||
} catch (e) { exn = e; }
|
||||
assertTrue(exn instanceof ReferenceError);
|
||||
assertEquals(1, fCalled);
|
||||
assertEquals(1, baseCalled);
|
||||
assertSame(obj, this);
|
||||
}
|
||||
}
|
||||
|
||||
new Subclass1();
|
||||
}());
|
||||
|
||||
|
||||
(function TestPrototypeWiring() {
|
||||
class Base {
|
||||
constructor(x) {
|
||||
|
Loading…
Reference in New Issue
Block a user