Commit fdcf3e59 authored by dslomov's avatar dslomov Committed by Commit bot

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}
parent 993a48f8
......@@ -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) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment