[es6] Super call in arrows and eval

This splits the SuperReference AST node into SuperPropertyReference and
SuperCallReference. The super call reference node consists of three
unresolved vars to this, new.target and this_function. These gets
declared when the right function is entered and if it is in use. The
variables gets assigned in FullCodeGenerator::Generate.

BUG=v8:3768
LOG=N
R=wingo@igalia.com, adamk@chromium.org

Review URL: https://codereview.chromium.org/1146863007

Cr-Commit-Position: refs/heads/master@{#28731}
This commit is contained in:
arv 2015-06-01 08:02:31 -07:00 committed by Commit bot
parent f2eb98b900
commit 673c0516ab
26 changed files with 743 additions and 342 deletions

View File

@ -242,6 +242,24 @@ void FullCodeGenerator::Generate() {
} }
} }
// Possibly set up a local binding to the this function which is used in
// derived constructors with super calls.
Variable* this_function_var = scope()->this_function_var();
if (this_function_var != nullptr) {
Comment cmnt(masm_, "[ This function");
SetVar(this_function_var, r1, r0, r2);
}
Variable* new_target_var = scope()->new_target_var();
if (new_target_var != nullptr) {
Comment cmnt(masm_, "[ new.target");
// new.target is parameter -2.
int offset = 2 * kPointerSize +
(info_->scope()->num_parameters() + 1) * kPointerSize;
__ ldr(r0, MemOperand(fp, offset));
SetVar(new_target_var, r0, r2, r3);
}
Variable* home_object_var = scope()->home_object_var(); Variable* home_object_var = scope()->home_object_var();
if (home_object_var != nullptr) { if (home_object_var != nullptr) {
__ Push(r1); __ Push(r1);
@ -2002,9 +2020,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
} }
break; break;
case NAMED_SUPER_PROPERTY: case NAMED_SUPER_PROPERTY:
VisitForStackValue(property->obj()->AsSuperReference()->this_var()); VisitForStackValue(
property->obj()->AsSuperPropertyReference()->this_var());
VisitForAccumulatorValue( VisitForAccumulatorValue(
property->obj()->AsSuperReference()->home_object_var()); property->obj()->AsSuperPropertyReference()->home_object_var());
__ Push(result_register()); __ Push(result_register());
if (expr->is_compound()) { if (expr->is_compound()) {
const Register scratch = r1; const Register scratch = r1;
@ -2014,9 +2033,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
} }
break; break;
case KEYED_SUPER_PROPERTY: case KEYED_SUPER_PROPERTY:
VisitForStackValue(property->obj()->AsSuperReference()->this_var());
VisitForStackValue( VisitForStackValue(
property->obj()->AsSuperReference()->home_object_var()); property->obj()->AsSuperPropertyReference()->this_var());
VisitForStackValue(
property->obj()->AsSuperPropertyReference()->home_object_var());
VisitForAccumulatorValue(property->key()); VisitForAccumulatorValue(property->key());
__ Push(result_register()); __ Push(result_register());
if (expr->is_compound()) { if (expr->is_compound()) {
@ -2659,9 +2679,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr,
} }
case NAMED_SUPER_PROPERTY: { case NAMED_SUPER_PROPERTY: {
__ Push(r0); __ Push(r0);
VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
VisitForAccumulatorValue( VisitForAccumulatorValue(
prop->obj()->AsSuperReference()->home_object_var()); prop->obj()->AsSuperPropertyReference()->home_object_var());
// stack: value, this; r0: home_object // stack: value, this; r0: home_object
Register scratch = r2; Register scratch = r2;
Register scratch2 = r3; Register scratch2 = r3;
@ -2676,8 +2696,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr,
} }
case KEYED_SUPER_PROPERTY: { case KEYED_SUPER_PROPERTY: {
__ Push(r0); __ Push(r0);
VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var()); VisitForStackValue(
prop->obj()->AsSuperPropertyReference()->home_object_var());
VisitForAccumulatorValue(prop->key()); VisitForAccumulatorValue(prop->key());
Register scratch = r2; Register scratch = r2;
Register scratch2 = r3; Register scratch2 = r3;
@ -2901,8 +2922,9 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
__ Move(LoadDescriptor::ReceiverRegister(), r0); __ Move(LoadDescriptor::ReceiverRegister(), r0);
EmitNamedPropertyLoad(expr); EmitNamedPropertyLoad(expr);
} else { } else {
VisitForStackValue(expr->obj()->AsSuperReference()->this_var()); VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var()); VisitForStackValue(
expr->obj()->AsSuperPropertyReference()->home_object_var());
EmitNamedSuperPropertyLoad(expr); EmitNamedSuperPropertyLoad(expr);
} }
} else { } else {
@ -2913,8 +2935,9 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
__ pop(LoadDescriptor::ReceiverRegister()); __ pop(LoadDescriptor::ReceiverRegister());
EmitKeyedPropertyLoad(expr); EmitKeyedPropertyLoad(expr);
} else { } else {
VisitForStackValue(expr->obj()->AsSuperReference()->this_var()); VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var()); VisitForStackValue(
expr->obj()->AsSuperPropertyReference()->home_object_var());
VisitForStackValue(expr->key()); VisitForStackValue(expr->key());
EmitKeyedSuperPropertyLoad(expr); EmitKeyedSuperPropertyLoad(expr);
} }
@ -2979,7 +3002,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
DCHECK(!key->value()->IsSmi()); DCHECK(!key->value()->IsSmi());
// Load the function from the receiver. // Load the function from the receiver.
const Register scratch = r1; const Register scratch = r1;
SuperReference* super_ref = prop->obj()->AsSuperReference(); SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
VisitForStackValue(super_ref->home_object_var()); VisitForStackValue(super_ref->home_object_var());
VisitForAccumulatorValue(super_ref->this_var()); VisitForAccumulatorValue(super_ref->this_var());
__ Push(r0); __ Push(r0);
@ -3039,7 +3062,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
SetSourcePosition(prop->position()); SetSourcePosition(prop->position());
// Load the function from the receiver. // Load the function from the receiver.
const Register scratch = r1; const Register scratch = r1;
SuperReference* super_ref = prop->obj()->AsSuperReference(); SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
VisitForStackValue(super_ref->home_object_var()); VisitForStackValue(super_ref->home_object_var());
VisitForAccumulatorValue(super_ref->this_var()); VisitForAccumulatorValue(super_ref->this_var());
__ Push(r0); __ Push(r0);
@ -3121,15 +3144,8 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
} }
void FullCodeGenerator::EmitLoadSuperConstructor() {
__ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
__ Push(r0);
__ CallRuntime(Runtime::kGetPrototype, 1);
}
void FullCodeGenerator::EmitInitializeThisAfterSuper( void FullCodeGenerator::EmitInitializeThisAfterSuper(
SuperReference* super_ref, FeedbackVectorICSlot slot) { SuperCallReference* super_ref, FeedbackVectorICSlot slot) {
Variable* this_var = super_ref->this_var()->var(); Variable* this_var = super_ref->this_var()->var();
GetVar(r1, this_var); GetVar(r1, this_var);
__ CompareRoot(r1, Heap::kTheHoleValueRootIndex); __ CompareRoot(r1, Heap::kTheHoleValueRootIndex);
@ -3289,7 +3305,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
// Push constructor on the stack. If it's not a function it's used as // Push constructor on the stack. If it's not a function it's used as
// receiver for CALL_NON_FUNCTION, otherwise the value on the stack is // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
// ignored. // ignored.
DCHECK(!expr->expression()->IsSuperReference()); DCHECK(!expr->expression()->IsSuperPropertyReference());
VisitForStackValue(expr->expression()); VisitForStackValue(expr->expression());
// Push the arguments ("left-to-right") on the stack. // Push the arguments ("left-to-right") on the stack.
@ -3325,11 +3341,14 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) { void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
Variable* new_target_var = scope()->DeclarationScope()->new_target_var(); SuperCallReference* super_call_ref =
GetVar(result_register(), new_target_var); expr->expression()->AsSuperCallReference();
__ Push(result_register()); DCHECK_NOT_NULL(super_call_ref);
EmitLoadSuperConstructor(); VariableProxy* new_target_proxy = super_call_ref->new_target_var();
VisitForStackValue(new_target_proxy);
EmitLoadSuperConstructor(super_call_ref);
__ push(result_register()); __ push(result_register());
// Push the arguments ("left-to-right") on the stack. // Push the arguments ("left-to-right") on the stack.
@ -3367,8 +3386,7 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
RecordJSReturnSite(expr); RecordJSReturnSite(expr);
EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(), EmitInitializeThisAfterSuper(super_call_ref, expr->CallFeedbackICSlot());
expr->CallFeedbackICSlot());
context()->Plug(r0); context()->Plug(r0);
} }
@ -4229,11 +4247,15 @@ void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
void FullCodeGenerator::EmitDefaultConstructorCallSuper(CallRuntime* expr) { void FullCodeGenerator::EmitDefaultConstructorCallSuper(CallRuntime* expr) {
Variable* new_target_var = scope()->DeclarationScope()->new_target_var(); ZoneList<Expression*>* args = expr->arguments();
GetVar(result_register(), new_target_var); DCHECK(args->length() == 2);
__ Push(result_register());
EmitLoadSuperConstructor(); // new.target
VisitForStackValue(args->at(0));
// .this_function
VisitForStackValue(args->at(1));
__ CallRuntime(Runtime::kGetPrototype, 1);
__ Push(result_register()); __ Push(result_register());
// Check if the calling frame is an arguments adaptor frame. // Check if the calling frame is an arguments adaptor frame.
@ -4626,11 +4648,14 @@ void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) { void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
// Assert: expr === CallRuntime("ReflectConstruct") // Assert: expr === CallRuntime("ReflectConstruct")
DCHECK_EQ(1, expr->arguments()->length());
CallRuntime* call = expr->arguments()->at(0)->AsCallRuntime(); CallRuntime* call = expr->arguments()->at(0)->AsCallRuntime();
ZoneList<Expression*>* args = call->arguments(); ZoneList<Expression*>* args = call->arguments();
DCHECK_EQ(3, args->length()); DCHECK_EQ(3, args->length());
SuperReference* super_reference = args->at(0)->AsSuperReference(); SuperCallReference* super_call_ref = args->at(0)->AsSuperCallReference();
DCHECK_NOT_NULL(super_call_ref);
// Load ReflectConstruct function // Load ReflectConstruct function
EmitLoadJSRuntimeFunction(call); EmitLoadJSRuntimeFunction(call);
@ -4640,8 +4665,8 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
__ push(ip); __ push(ip);
__ str(r0, MemOperand(sp, kPointerSize)); __ str(r0, MemOperand(sp, kPointerSize));
// Push super // Push super constructor
EmitLoadSuperConstructor(); EmitLoadSuperConstructor(super_call_ref);
__ Push(result_register()); __ Push(result_register());
// Push arguments array // Push arguments array
@ -4658,7 +4683,7 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
context()->DropAndPlug(1, r0); context()->DropAndPlug(1, r0);
// TODO(mvstanton): with FLAG_vector_stores this needs a slot id. // TODO(mvstanton): with FLAG_vector_stores this needs a slot id.
EmitInitializeThisAfterSuper(super_reference); EmitInitializeThisAfterSuper(super_call_ref);
} }
@ -4883,9 +4908,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
} }
case NAMED_SUPER_PROPERTY: { case NAMED_SUPER_PROPERTY: {
VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
VisitForAccumulatorValue( VisitForAccumulatorValue(
prop->obj()->AsSuperReference()->home_object_var()); prop->obj()->AsSuperPropertyReference()->home_object_var());
__ Push(result_register()); __ Push(result_register());
const Register scratch = r1; const Register scratch = r1;
__ ldr(scratch, MemOperand(sp, kPointerSize)); __ ldr(scratch, MemOperand(sp, kPointerSize));
@ -4896,8 +4921,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
} }
case KEYED_SUPER_PROPERTY: { case KEYED_SUPER_PROPERTY: {
VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var()); VisitForStackValue(
prop->obj()->AsSuperPropertyReference()->home_object_var());
VisitForAccumulatorValue(prop->key()); VisitForAccumulatorValue(prop->key());
__ Push(result_register()); __ Push(result_register());
const Register scratch = r1; const Register scratch = r1;

View File

@ -243,6 +243,24 @@ void FullCodeGenerator::Generate() {
} }
} }
// Possibly set up a local binding to the this function which is used in
// derived constructors with super calls.
Variable* this_function_var = scope()->this_function_var();
if (this_function_var != nullptr) {
Comment cmnt(masm_, "[ This function");
SetVar(this_function_var, x1, x0, x2);
}
Variable* new_target_var = scope()->new_target_var();
if (new_target_var != nullptr) {
Comment cmnt(masm_, "[ new.target");
// new.target is parameter -2.
int offset =
2 * kXRegSize + (info_->scope()->num_parameters() + 1) * kPointerSize;
__ Ldr(x0, MemOperand(fp, offset));
SetVar(new_target_var, x0, x2, x3);
}
Variable* home_object_var = scope()->home_object_var(); Variable* home_object_var = scope()->home_object_var();
if (home_object_var != nullptr) { if (home_object_var != nullptr) {
__ Push(x1); __ Push(x1);
@ -1970,9 +1988,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
} }
break; break;
case NAMED_SUPER_PROPERTY: case NAMED_SUPER_PROPERTY:
VisitForStackValue(property->obj()->AsSuperReference()->this_var()); VisitForStackValue(
property->obj()->AsSuperPropertyReference()->this_var());
VisitForAccumulatorValue( VisitForAccumulatorValue(
property->obj()->AsSuperReference()->home_object_var()); property->obj()->AsSuperPropertyReference()->home_object_var());
__ Push(result_register()); __ Push(result_register());
if (expr->is_compound()) { if (expr->is_compound()) {
const Register scratch = x10; const Register scratch = x10;
@ -1981,9 +2000,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
} }
break; break;
case KEYED_SUPER_PROPERTY: case KEYED_SUPER_PROPERTY:
VisitForStackValue(property->obj()->AsSuperReference()->this_var());
VisitForStackValue( VisitForStackValue(
property->obj()->AsSuperReference()->home_object_var()); property->obj()->AsSuperPropertyReference()->this_var());
VisitForStackValue(
property->obj()->AsSuperPropertyReference()->home_object_var());
VisitForAccumulatorValue(property->key()); VisitForAccumulatorValue(property->key());
__ Push(result_register()); __ Push(result_register());
if (expr->is_compound()) { if (expr->is_compound()) {
@ -2340,9 +2360,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr,
} }
case NAMED_SUPER_PROPERTY: { case NAMED_SUPER_PROPERTY: {
__ Push(x0); __ Push(x0);
VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
VisitForAccumulatorValue( VisitForAccumulatorValue(
prop->obj()->AsSuperReference()->home_object_var()); prop->obj()->AsSuperPropertyReference()->home_object_var());
// stack: value, this; x0: home_object // stack: value, this; x0: home_object
Register scratch = x10; Register scratch = x10;
Register scratch2 = x11; Register scratch2 = x11;
@ -2357,8 +2377,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr,
} }
case KEYED_SUPER_PROPERTY: { case KEYED_SUPER_PROPERTY: {
__ Push(x0); __ Push(x0);
VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var()); VisitForStackValue(
prop->obj()->AsSuperPropertyReference()->home_object_var());
VisitForAccumulatorValue(prop->key()); VisitForAccumulatorValue(prop->key());
Register scratch = x10; Register scratch = x10;
Register scratch2 = x11; Register scratch2 = x11;
@ -2584,8 +2605,9 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
__ Move(LoadDescriptor::ReceiverRegister(), x0); __ Move(LoadDescriptor::ReceiverRegister(), x0);
EmitNamedPropertyLoad(expr); EmitNamedPropertyLoad(expr);
} else { } else {
VisitForStackValue(expr->obj()->AsSuperReference()->this_var()); VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var()); VisitForStackValue(
expr->obj()->AsSuperPropertyReference()->home_object_var());
EmitNamedSuperPropertyLoad(expr); EmitNamedSuperPropertyLoad(expr);
} }
} else { } else {
@ -2596,8 +2618,9 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
__ Pop(LoadDescriptor::ReceiverRegister()); __ Pop(LoadDescriptor::ReceiverRegister());
EmitKeyedPropertyLoad(expr); EmitKeyedPropertyLoad(expr);
} else { } else {
VisitForStackValue(expr->obj()->AsSuperReference()->this_var()); VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var()); VisitForStackValue(
expr->obj()->AsSuperPropertyReference()->home_object_var());
VisitForStackValue(expr->key()); VisitForStackValue(expr->key());
EmitKeyedSuperPropertyLoad(expr); EmitKeyedSuperPropertyLoad(expr);
} }
@ -2665,7 +2688,8 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
// Load the function from the receiver. // Load the function from the receiver.
const Register scratch = x10; const Register scratch = x10;
SuperReference* super_ref = callee->AsProperty()->obj()->AsSuperReference(); SuperPropertyReference* super_ref =
callee->AsProperty()->obj()->AsSuperPropertyReference();
VisitForStackValue(super_ref->home_object_var()); VisitForStackValue(super_ref->home_object_var());
VisitForAccumulatorValue(super_ref->this_var()); VisitForAccumulatorValue(super_ref->this_var());
__ Push(x0); __ Push(x0);
@ -2724,7 +2748,8 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
// Load the function from the receiver. // Load the function from the receiver.
const Register scratch = x10; const Register scratch = x10;
SuperReference* super_ref = callee->AsProperty()->obj()->AsSuperReference(); SuperPropertyReference* super_ref =
callee->AsProperty()->obj()->AsSuperPropertyReference();
VisitForStackValue(super_ref->home_object_var()); VisitForStackValue(super_ref->home_object_var());
VisitForAccumulatorValue(super_ref->this_var()); VisitForAccumulatorValue(super_ref->this_var());
__ Push(x0); __ Push(x0);
@ -2805,15 +2830,8 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
} }
void FullCodeGenerator::EmitLoadSuperConstructor() {
__ ldr(x0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
__ Push(x0);
__ CallRuntime(Runtime::kGetPrototype, 1);
}
void FullCodeGenerator::EmitInitializeThisAfterSuper( void FullCodeGenerator::EmitInitializeThisAfterSuper(
SuperReference* super_ref, FeedbackVectorICSlot slot) { SuperCallReference* super_ref, FeedbackVectorICSlot slot) {
Variable* this_var = super_ref->this_var()->var(); Variable* this_var = super_ref->this_var()->var();
GetVar(x1, this_var); GetVar(x1, this_var);
Label uninitialized_this; Label uninitialized_this;
@ -2973,7 +2991,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
// Push constructor on the stack. If it's not a function it's used as // Push constructor on the stack. If it's not a function it's used as
// receiver for CALL_NON_FUNCTION, otherwise the value on the stack is // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
// ignored. // ignored.
DCHECK(!expr->expression()->IsSuperReference()); DCHECK(!expr->expression()->IsSuperPropertyReference());
VisitForStackValue(expr->expression()); VisitForStackValue(expr->expression());
// Push the arguments ("left-to-right") on the stack. // Push the arguments ("left-to-right") on the stack.
@ -3009,11 +3027,14 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) { void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
Variable* new_target_var = scope()->DeclarationScope()->new_target_var(); SuperCallReference* super_call_ref =
GetVar(result_register(), new_target_var); expr->expression()->AsSuperCallReference();
__ Push(result_register()); DCHECK_NOT_NULL(super_call_ref);
EmitLoadSuperConstructor(); VariableProxy* new_target_proxy = super_call_ref->new_target_var();
VisitForStackValue(new_target_proxy);
EmitLoadSuperConstructor(super_call_ref);
__ push(result_register()); __ push(result_register());
// Push the arguments ("left-to-right") on the stack. // Push the arguments ("left-to-right") on the stack.
@ -3051,8 +3072,7 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
RecordJSReturnSite(expr); RecordJSReturnSite(expr);
EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(), EmitInitializeThisAfterSuper(super_call_ref, expr->CallFeedbackICSlot());
expr->CallFeedbackICSlot());
context()->Plug(x0); context()->Plug(x0);
} }
@ -3932,11 +3952,15 @@ void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
void FullCodeGenerator::EmitDefaultConstructorCallSuper(CallRuntime* expr) { void FullCodeGenerator::EmitDefaultConstructorCallSuper(CallRuntime* expr) {
Variable* new_target_var = scope()->DeclarationScope()->new_target_var(); ZoneList<Expression*>* args = expr->arguments();
GetVar(result_register(), new_target_var); DCHECK(args->length() == 2);
__ Push(result_register());
EmitLoadSuperConstructor(); // new.target
VisitForStackValue(args->at(0));
// .this_function
VisitForStackValue(args->at(1));
__ CallRuntime(Runtime::kGetPrototype, 1);
__ Push(result_register()); __ Push(result_register());
// Check if the calling frame is an arguments adaptor frame. // Check if the calling frame is an arguments adaptor frame.
@ -4309,11 +4333,14 @@ void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) { void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
// Assert: expr === CallRuntime("ReflectConstruct") // Assert: expr === CallRuntime("ReflectConstruct")
DCHECK_EQ(1, expr->arguments()->length());
CallRuntime* call = expr->arguments()->at(0)->AsCallRuntime(); CallRuntime* call = expr->arguments()->at(0)->AsCallRuntime();
ZoneList<Expression*>* args = call->arguments(); ZoneList<Expression*>* args = call->arguments();
DCHECK_EQ(3, args->length()); DCHECK_EQ(3, args->length());
SuperReference* super_reference = args->at(0)->AsSuperReference(); SuperCallReference* super_call_ref = args->at(0)->AsSuperCallReference();
DCHECK_NOT_NULL(super_call_ref);
// Load ReflectConstruct function // Load ReflectConstruct function
EmitLoadJSRuntimeFunction(call); EmitLoadJSRuntimeFunction(call);
@ -4322,8 +4349,8 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
__ Pop(x10); __ Pop(x10);
__ Push(x0, x10); __ Push(x0, x10);
// Push super // Push super constructor
EmitLoadSuperConstructor(); EmitLoadSuperConstructor(super_call_ref);
__ Push(result_register()); __ Push(result_register());
// Push arguments array // Push arguments array
@ -4340,7 +4367,7 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
context()->DropAndPlug(1, x0); context()->DropAndPlug(1, x0);
// TODO(mvstanton): with FLAG_vector_stores this needs a slot id. // TODO(mvstanton): with FLAG_vector_stores this needs a slot id.
EmitInitializeThisAfterSuper(super_reference); EmitInitializeThisAfterSuper(super_call_ref);
} }
@ -4562,9 +4589,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
} }
case NAMED_SUPER_PROPERTY: { case NAMED_SUPER_PROPERTY: {
VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
VisitForAccumulatorValue( VisitForAccumulatorValue(
prop->obj()->AsSuperReference()->home_object_var()); prop->obj()->AsSuperPropertyReference()->home_object_var());
__ Push(result_register()); __ Push(result_register());
const Register scratch = x10; const Register scratch = x10;
__ Peek(scratch, kPointerSize); __ Peek(scratch, kPointerSize);
@ -4574,8 +4601,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
} }
case KEYED_SUPER_PROPERTY: { case KEYED_SUPER_PROPERTY: {
VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var()); VisitForStackValue(
prop->obj()->AsSuperPropertyReference()->home_object_var());
VisitForAccumulatorValue(prop->key()); VisitForAccumulatorValue(prop->key());
__ Push(result_register()); __ Push(result_register());
const Register scratch1 = x10; const Register scratch1 = x10;

View File

@ -168,15 +168,26 @@ void AstNumberingVisitor::VisitThisFunction(ThisFunction* node) {
} }
void AstNumberingVisitor::VisitSuperReference(SuperReference* node) { void AstNumberingVisitor::VisitSuperPropertyReference(
SuperPropertyReference* node) {
IncrementNodeCount(); IncrementNodeCount();
DisableOptimization(kSuperReference); DisableOptimization(kSuperReference);
node->set_base_id(ReserveIdRange(SuperReference::num_ids())); node->set_base_id(ReserveIdRange(SuperPropertyReference::num_ids()));
Visit(node->this_var()); Visit(node->this_var());
Visit(node->home_object_var()); Visit(node->home_object_var());
} }
void AstNumberingVisitor::VisitSuperCallReference(SuperCallReference* node) {
IncrementNodeCount();
DisableOptimization(kSuperReference);
node->set_base_id(ReserveIdRange(SuperCallReference::num_ids()));
Visit(node->this_var());
Visit(node->new_target_var());
Visit(node->this_function_var());
}
void AstNumberingVisitor::VisitImportDeclaration(ImportDeclaration* node) { void AstNumberingVisitor::VisitImportDeclaration(ImportDeclaration* node) {
IncrementNodeCount(); IncrementNodeCount();
DisableOptimization(kImportDeclaration); DisableOptimization(kImportDeclaration);

View File

@ -267,6 +267,7 @@ class AstValue : public ZoneObject {
F(spread_arguments, "$spreadArguments") \ F(spread_arguments, "$spreadArguments") \
F(spread_iterable, "$spreadIterable") \ F(spread_iterable, "$spreadIterable") \
F(this, "this") \ F(this, "this") \
F(this_function, ".this_function") \
F(throw_iterator_result_not_an_object, "ThrowIteratorResultNotAnObject") \ F(throw_iterator_result_not_an_object, "ThrowIteratorResultNotAnObject") \
F(to_string, "$toString") \ F(to_string, "$toString") \
F(undefined, "undefined") \ F(undefined, "undefined") \

View File

@ -734,7 +734,7 @@ Call::CallType Call::GetCallType(Isolate* isolate) const {
} }
} }
if (expression()->AsSuperReference() != NULL) return SUPER_CALL; if (expression()->IsSuperCallReference()) return SUPER_CALL;
Property* property = expression()->AsProperty(); Property* property = expression()->AsProperty();
return property != NULL ? PROPERTY_CALL : OTHER_CALL; return property != NULL ? PROPERTY_CALL : OTHER_CALL;

View File

@ -87,7 +87,8 @@ namespace internal {
V(CompareOperation) \ V(CompareOperation) \
V(Spread) \ V(Spread) \
V(ThisFunction) \ V(ThisFunction) \
V(SuperReference) \ V(SuperPropertyReference) \
V(SuperCallReference) \
V(CaseClause) V(CaseClause)
#define AST_NODE_LIST(V) \ #define AST_NODE_LIST(V) \
@ -1760,9 +1761,7 @@ class Property final : public Expression {
} }
bool is_for_call() const { return IsForCallField::decode(bit_field_); } bool is_for_call() const { return IsForCallField::decode(bit_field_); }
bool IsSuperAccess() { bool IsSuperAccess() { return obj()->IsSuperPropertyReference(); }
return obj()->IsSuperReference();
}
virtual FeedbackVectorRequirements ComputeFeedbackRequirements( virtual FeedbackVectorRequirements ComputeFeedbackRequirements(
Isolate* isolate, const ICSlotCache* cache) override { Isolate* isolate, const ICSlotCache* cache) override {
@ -2791,16 +2790,16 @@ class ThisFunction final : public Expression {
}; };
class SuperReference final : public Expression { class SuperPropertyReference final : public Expression {
public: public:
DECLARE_NODE_TYPE(SuperReference) DECLARE_NODE_TYPE(SuperPropertyReference)
VariableProxy* this_var() const { return this_var_; } VariableProxy* this_var() const { return this_var_; }
VariableProxy* home_object_var() const { return home_object_var_; } VariableProxy* home_object_var() const { return home_object_var_; }
protected: protected:
SuperReference(Zone* zone, VariableProxy* this_var, SuperPropertyReference(Zone* zone, VariableProxy* this_var,
VariableProxy* home_object_var, int pos) VariableProxy* home_object_var, int pos)
: Expression(zone, pos), : Expression(zone, pos),
this_var_(this_var), this_var_(this_var),
home_object_var_(home_object_var) { home_object_var_(home_object_var) {
@ -2814,6 +2813,34 @@ class SuperReference final : public Expression {
}; };
class SuperCallReference final : public Expression {
public:
DECLARE_NODE_TYPE(SuperCallReference)
VariableProxy* this_var() const { return this_var_; }
VariableProxy* new_target_var() const { return new_target_var_; }
VariableProxy* this_function_var() const { return this_function_var_; }
protected:
SuperCallReference(Zone* zone, VariableProxy* this_var,
VariableProxy* new_target_var,
VariableProxy* this_function_var, int pos)
: Expression(zone, pos),
this_var_(this_var),
new_target_var_(new_target_var),
this_function_var_(this_function_var) {
DCHECK(this_var->is_this());
DCHECK(new_target_var->raw_name()->IsOneByteEqualTo("new.target"));
DCHECK(this_function_var->raw_name()->IsOneByteEqualTo(".this_function"));
}
private:
VariableProxy* this_var_;
VariableProxy* new_target_var_;
VariableProxy* this_function_var_;
};
#undef DECLARE_NODE_TYPE #undef DECLARE_NODE_TYPE
@ -3581,9 +3608,18 @@ class AstNodeFactory final BASE_EMBEDDED {
return new (zone_) ThisFunction(zone_, pos); return new (zone_) ThisFunction(zone_, pos);
} }
SuperReference* NewSuperReference(VariableProxy* this_var, SuperPropertyReference* NewSuperPropertyReference(
VariableProxy* home_object_var, int pos) { VariableProxy* this_var, VariableProxy* home_object_var, int pos) {
return new (zone_) SuperReference(zone_, this_var, home_object_var, pos); return new (zone_)
SuperPropertyReference(zone_, this_var, home_object_var, pos);
}
SuperCallReference* NewSuperCallReference(VariableProxy* this_var,
VariableProxy* new_target_var,
VariableProxy* this_function_var,
int pos) {
return new (zone_) SuperCallReference(zone_, this_var, new_target_var,
this_function_var, pos);
} }
private: private:

View File

@ -2590,7 +2590,15 @@ void AstGraphBuilder::VisitThisFunction(ThisFunction* expr) {
} }
void AstGraphBuilder::VisitSuperReference(SuperReference* expr) { void AstGraphBuilder::VisitSuperPropertyReference(
SuperPropertyReference* expr) {
// TODO(turbofan): Implement super here.
SetStackOverflow();
ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
}
void AstGraphBuilder::VisitSuperCallReference(SuperCallReference* expr) {
// TODO(turbofan): Implement super here. // TODO(turbofan): Implement super here.
SetStackOverflow(); SetStackOverflow();
ast_context()->ProduceValue(jsgraph()->UndefinedConstant()); ast_context()->ProduceValue(jsgraph()->UndefinedConstant());

View File

@ -67,7 +67,8 @@ void ALAA::VisitVariableProxy(VariableProxy* leaf) {}
void ALAA::VisitLiteral(Literal* leaf) {} void ALAA::VisitLiteral(Literal* leaf) {}
void ALAA::VisitRegExpLiteral(RegExpLiteral* leaf) {} void ALAA::VisitRegExpLiteral(RegExpLiteral* leaf) {}
void ALAA::VisitThisFunction(ThisFunction* leaf) {} void ALAA::VisitThisFunction(ThisFunction* leaf) {}
void ALAA::VisitSuperReference(SuperReference* leaf) {} void ALAA::VisitSuperPropertyReference(SuperPropertyReference* leaf) {}
void ALAA::VisitSuperCallReference(SuperCallReference* leaf) {}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------

View File

@ -276,7 +276,12 @@ void BreakableStatementChecker::VisitThisFunction(ThisFunction* expr) {
} }
void BreakableStatementChecker::VisitSuperReference(SuperReference* expr) {} void BreakableStatementChecker::VisitSuperPropertyReference(
SuperPropertyReference* expr) {}
void BreakableStatementChecker::VisitSuperCallReference(
SuperCallReference* expr) {}
#define __ ACCESS_MASM(masm()) #define __ ACCESS_MASM(masm())
@ -668,7 +673,13 @@ void FullCodeGenerator::SetStatementPosition(Statement* stmt) {
} }
void FullCodeGenerator::VisitSuperReference(SuperReference* super) { void FullCodeGenerator::VisitSuperPropertyReference(
SuperPropertyReference* super) {
__ CallRuntime(Runtime::kThrowUnsupportedSuperError, 0);
}
void FullCodeGenerator::VisitSuperCallReference(SuperCallReference* super) {
__ CallRuntime(Runtime::kThrowUnsupportedSuperError, 0); __ CallRuntime(Runtime::kThrowUnsupportedSuperError, 0);
} }
@ -978,6 +989,12 @@ void FullCodeGenerator::EmitPropertyKey(ObjectLiteralProperty* property,
} }
void FullCodeGenerator::EmitLoadSuperConstructor(SuperCallReference* ref) {
VisitForStackValue(ref->this_function_var());
__ CallRuntime(Runtime::kGetPrototype, 1);
}
void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
Comment cmnt(masm_, "[ ReturnStatement"); Comment cmnt(masm_, "[ ReturnStatement");
SetStatementPosition(stmt); SetStatementPosition(stmt);

View File

@ -672,9 +672,9 @@ class FullCodeGenerator: public AstVisitor {
Expression* initializer, int offset, Expression* initializer, int offset,
FeedbackVectorICSlot slot = FeedbackVectorICSlot::Invalid()); FeedbackVectorICSlot slot = FeedbackVectorICSlot::Invalid());
void EmitLoadSuperConstructor(); void EmitLoadSuperConstructor(SuperCallReference* super_call_ref);
void EmitInitializeThisAfterSuper( void EmitInitializeThisAfterSuper(
SuperReference* super_ref, SuperCallReference* super_call_ref,
FeedbackVectorICSlot slot = FeedbackVectorICSlot::Invalid()); FeedbackVectorICSlot slot = FeedbackVectorICSlot::Invalid());
void CallIC(Handle<Code> code, void CallIC(Handle<Code> code,

View File

@ -11568,7 +11568,16 @@ void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) {
} }
void HOptimizedGraphBuilder::VisitSuperReference(SuperReference* expr) { void HOptimizedGraphBuilder::VisitSuperPropertyReference(
SuperPropertyReference* expr) {
DCHECK(!HasStackOverflow());
DCHECK(current_block() != NULL);
DCHECK(current_block()->HasPredecessor());
return Bailout(kSuperReference);
}
void HOptimizedGraphBuilder::VisitSuperCallReference(SuperCallReference* expr) {
DCHECK(!HasStackOverflow()); DCHECK(!HasStackOverflow());
DCHECK(current_block() != NULL); DCHECK(current_block() != NULL);
DCHECK(current_block()->HasPredecessor()); DCHECK(current_block()->HasPredecessor());

View File

@ -238,6 +238,24 @@ void FullCodeGenerator::Generate() {
} }
} }
// Possibly set up a local binding to the this function which is used in
// derived constructors with super calls.
Variable* this_function_var = scope()->this_function_var();
if (this_function_var != nullptr) {
Comment cmnt(masm_, "[ This function");
SetVar(this_function_var, edi, ebx, edx);
}
Variable* new_target_var = scope()->new_target_var();
if (new_target_var != nullptr) {
Comment cmnt(masm_, "[ new.target");
// new.target is parameter -2.
int offset = 2 * kPointerSize + kFPOnStackSize + kPCOnStackSize +
(info_->scope()->num_parameters() - 1) * kPointerSize;
__ mov(eax, Operand(ebp, offset));
SetVar(new_target_var, eax, ebx, edx);
}
Variable* home_object_var = scope()->home_object_var(); Variable* home_object_var = scope()->home_object_var();
if (home_object_var != nullptr) { if (home_object_var != nullptr) {
__ push(edi); __ push(edi);
@ -1920,9 +1938,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
// Nothing to do here. // Nothing to do here.
break; break;
case NAMED_SUPER_PROPERTY: case NAMED_SUPER_PROPERTY:
VisitForStackValue(property->obj()->AsSuperReference()->this_var()); VisitForStackValue(
property->obj()->AsSuperPropertyReference()->this_var());
VisitForAccumulatorValue( VisitForAccumulatorValue(
property->obj()->AsSuperReference()->home_object_var()); property->obj()->AsSuperPropertyReference()->home_object_var());
__ push(result_register()); __ push(result_register());
if (expr->is_compound()) { if (expr->is_compound()) {
__ push(MemOperand(esp, kPointerSize)); __ push(MemOperand(esp, kPointerSize));
@ -1939,9 +1958,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
} }
break; break;
case KEYED_SUPER_PROPERTY: case KEYED_SUPER_PROPERTY:
VisitForStackValue(property->obj()->AsSuperReference()->this_var());
VisitForStackValue( VisitForStackValue(
property->obj()->AsSuperReference()->home_object_var()); property->obj()->AsSuperPropertyReference()->this_var());
VisitForStackValue(
property->obj()->AsSuperPropertyReference()->home_object_var());
VisitForAccumulatorValue(property->key()); VisitForAccumulatorValue(property->key());
__ Push(result_register()); __ Push(result_register());
if (expr->is_compound()) { if (expr->is_compound()) {
@ -2565,9 +2585,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr,
} }
case NAMED_SUPER_PROPERTY: { case NAMED_SUPER_PROPERTY: {
__ push(eax); __ push(eax);
VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
VisitForAccumulatorValue( VisitForAccumulatorValue(
prop->obj()->AsSuperReference()->home_object_var()); prop->obj()->AsSuperPropertyReference()->home_object_var());
// stack: value, this; eax: home_object // stack: value, this; eax: home_object
Register scratch = ecx; Register scratch = ecx;
Register scratch2 = edx; Register scratch2 = edx;
@ -2582,8 +2602,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr,
} }
case KEYED_SUPER_PROPERTY: { case KEYED_SUPER_PROPERTY: {
__ push(eax); __ push(eax);
VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var()); VisitForStackValue(
prop->obj()->AsSuperPropertyReference()->home_object_var());
VisitForAccumulatorValue(prop->key()); VisitForAccumulatorValue(prop->key());
Register scratch = ecx; Register scratch = ecx;
Register scratch2 = edx; Register scratch2 = edx;
@ -2805,8 +2826,9 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
__ Move(LoadDescriptor::ReceiverRegister(), result_register()); __ Move(LoadDescriptor::ReceiverRegister(), result_register());
EmitNamedPropertyLoad(expr); EmitNamedPropertyLoad(expr);
} else { } else {
VisitForStackValue(expr->obj()->AsSuperReference()->this_var()); VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var()); VisitForStackValue(
expr->obj()->AsSuperPropertyReference()->home_object_var());
EmitNamedSuperPropertyLoad(expr); EmitNamedSuperPropertyLoad(expr);
} }
} else { } else {
@ -2817,8 +2839,9 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
__ Move(LoadDescriptor::NameRegister(), result_register()); // Key. __ Move(LoadDescriptor::NameRegister(), result_register()); // Key.
EmitKeyedPropertyLoad(expr); EmitKeyedPropertyLoad(expr);
} else { } else {
VisitForStackValue(expr->obj()->AsSuperReference()->this_var()); VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var()); VisitForStackValue(
expr->obj()->AsSuperPropertyReference()->home_object_var());
VisitForStackValue(expr->key()); VisitForStackValue(expr->key());
EmitKeyedSuperPropertyLoad(expr); EmitKeyedSuperPropertyLoad(expr);
} }
@ -2876,7 +2899,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
Literal* key = prop->key()->AsLiteral(); Literal* key = prop->key()->AsLiteral();
DCHECK(!key->value()->IsSmi()); DCHECK(!key->value()->IsSmi());
// Load the function from the receiver. // Load the function from the receiver.
SuperReference* super_ref = callee->AsProperty()->obj()->AsSuperReference(); SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
VisitForStackValue(super_ref->home_object_var()); VisitForStackValue(super_ref->home_object_var());
VisitForAccumulatorValue(super_ref->this_var()); VisitForAccumulatorValue(super_ref->this_var());
__ push(eax); __ push(eax);
@ -2932,7 +2955,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
SetSourcePosition(prop->position()); SetSourcePosition(prop->position());
// Load the function from the receiver. // Load the function from the receiver.
SuperReference* super_ref = callee->AsProperty()->obj()->AsSuperReference(); SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
VisitForStackValue(super_ref->home_object_var()); VisitForStackValue(super_ref->home_object_var());
VisitForAccumulatorValue(super_ref->this_var()); VisitForAccumulatorValue(super_ref->this_var());
__ push(eax); __ push(eax);
@ -3010,15 +3033,9 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
} }
void FullCodeGenerator::EmitLoadSuperConstructor() {
__ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
__ CallRuntime(Runtime::kGetPrototype, 1);
}
void FullCodeGenerator::EmitInitializeThisAfterSuper( void FullCodeGenerator::EmitInitializeThisAfterSuper(
SuperReference* super_ref, FeedbackVectorICSlot slot) { SuperCallReference* super_call_ref, FeedbackVectorICSlot slot) {
Variable* this_var = super_ref->this_var()->var(); Variable* this_var = super_call_ref->this_var()->var();
GetVar(ecx, this_var); GetVar(ecx, this_var);
__ cmp(ecx, isolate()->factory()->the_hole_value()); __ cmp(ecx, isolate()->factory()->the_hole_value());
Label uninitialized_this; Label uninitialized_this;
@ -3167,7 +3184,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
// Push constructor on the stack. If it's not a function it's used as // Push constructor on the stack. If it's not a function it's used as
// receiver for CALL_NON_FUNCTION, otherwise the value on the stack is // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
// ignored. // ignored.
DCHECK(!expr->expression()->IsSuperReference()); DCHECK(!expr->expression()->IsSuperPropertyReference());
VisitForStackValue(expr->expression()); VisitForStackValue(expr->expression());
// Push the arguments ("left-to-right") on the stack. // Push the arguments ("left-to-right") on the stack.
@ -3203,11 +3220,14 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) { void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
Variable* new_target_var = scope()->DeclarationScope()->new_target_var(); SuperCallReference* super_call_ref =
GetVar(eax, new_target_var); expr->expression()->AsSuperCallReference();
__ push(eax); DCHECK_NOT_NULL(super_call_ref);
EmitLoadSuperConstructor(); VariableProxy* new_target_proxy = super_call_ref->new_target_var();
VisitForStackValue(new_target_proxy);
EmitLoadSuperConstructor(super_call_ref);
__ push(result_register()); __ push(result_register());
// Push the arguments ("left-to-right") on the stack. // Push the arguments ("left-to-right") on the stack.
@ -3245,8 +3265,7 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
RecordJSReturnSite(expr); RecordJSReturnSite(expr);
EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(), EmitInitializeThisAfterSuper(super_call_ref, expr->CallFeedbackICSlot());
expr->CallFeedbackICSlot());
context()->Plug(eax); context()->Plug(eax);
} }
@ -4123,11 +4142,15 @@ void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
void FullCodeGenerator::EmitDefaultConstructorCallSuper(CallRuntime* expr) { void FullCodeGenerator::EmitDefaultConstructorCallSuper(CallRuntime* expr) {
Variable* new_target_var = scope()->DeclarationScope()->new_target_var(); ZoneList<Expression*>* args = expr->arguments();
GetVar(eax, new_target_var); DCHECK(args->length() == 2);
__ push(eax);
EmitLoadSuperConstructor(); // new.target
VisitForStackValue(args->at(0));
// .this_function
VisitForStackValue(args->at(1));
__ CallRuntime(Runtime::kGetPrototype, 1);
__ push(result_register()); __ push(result_register());
// Check if the calling frame is an arguments adaptor frame. // Check if the calling frame is an arguments adaptor frame.
@ -4550,11 +4573,14 @@ void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) { void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
// Assert: expr == CallRuntime("ReflectConstruct") // Assert: expr == CallRuntime("ReflectConstruct")
DCHECK_EQ(1, expr->arguments()->length());
CallRuntime* call = expr->arguments()->at(0)->AsCallRuntime(); CallRuntime* call = expr->arguments()->at(0)->AsCallRuntime();
ZoneList<Expression*>* args = call->arguments(); ZoneList<Expression*>* args = call->arguments();
DCHECK_EQ(3, args->length()); DCHECK_EQ(3, args->length());
SuperReference* super_reference = args->at(0)->AsSuperReference(); SuperCallReference* super_call_ref = args->at(0)->AsSuperCallReference();
DCHECK_NOT_NULL(super_call_ref);
// Load ReflectConstruct function // Load ReflectConstruct function
EmitLoadJSRuntimeFunction(call); EmitLoadJSRuntimeFunction(call);
@ -4563,8 +4589,8 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
__ push(Operand(esp, 0)); __ push(Operand(esp, 0));
__ mov(Operand(esp, kPointerSize), eax); __ mov(Operand(esp, kPointerSize), eax);
// Push super // Push super constructor
EmitLoadSuperConstructor(); EmitLoadSuperConstructor(super_call_ref);
__ Push(result_register()); __ Push(result_register());
// Push arguments array // Push arguments array
@ -4581,7 +4607,7 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
context()->DropAndPlug(1, eax); context()->DropAndPlug(1, eax);
// TODO(mvstanton): with FLAG_vector_stores this needs a slot id. // TODO(mvstanton): with FLAG_vector_stores this needs a slot id.
EmitInitializeThisAfterSuper(super_reference); EmitInitializeThisAfterSuper(super_call_ref);
} }
@ -4806,9 +4832,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
} }
case NAMED_SUPER_PROPERTY: { case NAMED_SUPER_PROPERTY: {
VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
VisitForAccumulatorValue( VisitForAccumulatorValue(
prop->obj()->AsSuperReference()->home_object_var()); prop->obj()->AsSuperPropertyReference()->home_object_var());
__ push(result_register()); __ push(result_register());
__ push(MemOperand(esp, kPointerSize)); __ push(MemOperand(esp, kPointerSize));
__ push(result_register()); __ push(result_register());
@ -4817,8 +4843,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
} }
case KEYED_SUPER_PROPERTY: { case KEYED_SUPER_PROPERTY: {
VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var()); VisitForStackValue(
prop->obj()->AsSuperPropertyReference()->home_object_var());
VisitForAccumulatorValue(prop->key()); VisitForAccumulatorValue(prop->key());
__ push(result_register()); __ push(result_register());
__ push(MemOperand(esp, 2 * kPointerSize)); __ push(MemOperand(esp, 2 * kPointerSize));

View File

@ -251,6 +251,24 @@ void FullCodeGenerator::Generate() {
} }
} }
// Possibly set up a local binding to the this function which is used in
// derived constructors with super calls.
Variable* this_function_var = scope()->this_function_var();
if (this_function_var != nullptr) {
Comment cmnt(masm_, "[ This function");
SetVar(this_function_var, a1, a2, a3);
}
Variable* new_target_var = scope()->new_target_var();
if (new_target_var != nullptr) {
Comment cmnt(masm_, "[ new.target");
// new.target is parameter -2.
int offset = 2 * kPointerSize +
(info_->scope()->num_parameters() + 1) * kPointerSize;
__ lw(v0, MemOperand(fp, offset));
SetVar(new_target_var, v0, a2, a3);
}
Variable* home_object_var = scope()->home_object_var(); Variable* home_object_var = scope()->home_object_var();
if (home_object_var != nullptr) { if (home_object_var != nullptr) {
__ Push(a1); __ Push(a1);
@ -1988,9 +2006,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
} }
break; break;
case NAMED_SUPER_PROPERTY: case NAMED_SUPER_PROPERTY:
VisitForStackValue(property->obj()->AsSuperReference()->this_var()); VisitForStackValue(
property->obj()->AsSuperPropertyReference()->this_var());
VisitForAccumulatorValue( VisitForAccumulatorValue(
property->obj()->AsSuperReference()->home_object_var()); property->obj()->AsSuperPropertyReference()->home_object_var());
__ Push(result_register()); __ Push(result_register());
if (expr->is_compound()) { if (expr->is_compound()) {
const Register scratch = a1; const Register scratch = a1;
@ -2000,9 +2019,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
break; break;
case KEYED_SUPER_PROPERTY: { case KEYED_SUPER_PROPERTY: {
const Register scratch = a1; const Register scratch = a1;
VisitForStackValue(property->obj()->AsSuperReference()->this_var()); VisitForStackValue(
property->obj()->AsSuperPropertyReference()->this_var());
VisitForAccumulatorValue( VisitForAccumulatorValue(
property->obj()->AsSuperReference()->home_object_var()); property->obj()->AsSuperPropertyReference()->home_object_var());
__ Move(scratch, result_register()); __ Move(scratch, result_register());
VisitForAccumulatorValue(property->key()); VisitForAccumulatorValue(property->key());
__ Push(scratch, result_register()); __ Push(scratch, result_register());
@ -2636,9 +2656,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr,
} }
case NAMED_SUPER_PROPERTY: { case NAMED_SUPER_PROPERTY: {
__ Push(v0); __ Push(v0);
VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
VisitForAccumulatorValue( VisitForAccumulatorValue(
prop->obj()->AsSuperReference()->home_object_var()); prop->obj()->AsSuperPropertyReference()->home_object_var());
// stack: value, this; v0: home_object // stack: value, this; v0: home_object
Register scratch = a2; Register scratch = a2;
Register scratch2 = a3; Register scratch2 = a3;
@ -2653,8 +2673,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr,
} }
case KEYED_SUPER_PROPERTY: { case KEYED_SUPER_PROPERTY: {
__ Push(v0); __ Push(v0);
VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var()); VisitForStackValue(
prop->obj()->AsSuperPropertyReference()->home_object_var());
VisitForAccumulatorValue(prop->key()); VisitForAccumulatorValue(prop->key());
Register scratch = a2; Register scratch = a2;
Register scratch2 = a3; Register scratch2 = a3;
@ -2883,8 +2904,9 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
__ Move(LoadDescriptor::ReceiverRegister(), v0); __ Move(LoadDescriptor::ReceiverRegister(), v0);
EmitNamedPropertyLoad(expr); EmitNamedPropertyLoad(expr);
} else { } else {
VisitForStackValue(expr->obj()->AsSuperReference()->this_var()); VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var()); VisitForStackValue(
expr->obj()->AsSuperPropertyReference()->home_object_var());
EmitNamedSuperPropertyLoad(expr); EmitNamedSuperPropertyLoad(expr);
} }
} else { } else {
@ -2895,8 +2917,9 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
__ pop(LoadDescriptor::ReceiverRegister()); __ pop(LoadDescriptor::ReceiverRegister());
EmitKeyedPropertyLoad(expr); EmitKeyedPropertyLoad(expr);
} else { } else {
VisitForStackValue(expr->obj()->AsSuperReference()->this_var()); VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var()); VisitForStackValue(
expr->obj()->AsSuperPropertyReference()->home_object_var());
VisitForStackValue(expr->key()); VisitForStackValue(expr->key());
EmitKeyedSuperPropertyLoad(expr); EmitKeyedSuperPropertyLoad(expr);
} }
@ -2958,7 +2981,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
DCHECK(!key->value()->IsSmi()); DCHECK(!key->value()->IsSmi());
// Load the function from the receiver. // Load the function from the receiver.
const Register scratch = a1; const Register scratch = a1;
SuperReference* super_ref = prop->obj()->AsSuperReference(); SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
VisitForAccumulatorValue(super_ref->home_object_var()); VisitForAccumulatorValue(super_ref->home_object_var());
__ mov(scratch, v0); __ mov(scratch, v0);
VisitForAccumulatorValue(super_ref->this_var()); VisitForAccumulatorValue(super_ref->this_var());
@ -3016,7 +3039,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
SetSourcePosition(prop->position()); SetSourcePosition(prop->position());
// Load the function from the receiver. // Load the function from the receiver.
const Register scratch = a1; const Register scratch = a1;
SuperReference* super_ref = prop->obj()->AsSuperReference(); SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
VisitForAccumulatorValue(super_ref->home_object_var()); VisitForAccumulatorValue(super_ref->home_object_var());
__ Move(scratch, v0); __ Move(scratch, v0);
VisitForAccumulatorValue(super_ref->this_var()); VisitForAccumulatorValue(super_ref->this_var());
@ -3096,15 +3119,8 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
} }
void FullCodeGenerator::EmitLoadSuperConstructor() {
__ lw(a0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
__ Push(a0);
__ CallRuntime(Runtime::kGetPrototype, 1);
}
void FullCodeGenerator::EmitInitializeThisAfterSuper( void FullCodeGenerator::EmitInitializeThisAfterSuper(
SuperReference* super_ref, FeedbackVectorICSlot slot) { SuperCallReference* super_ref, FeedbackVectorICSlot slot) {
Variable* this_var = super_ref->this_var()->var(); Variable* this_var = super_ref->this_var()->var();
GetVar(a1, this_var); GetVar(a1, this_var);
__ LoadRoot(at, Heap::kTheHoleValueRootIndex); __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
@ -3262,7 +3278,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
// Push constructor on the stack. If it's not a function it's used as // Push constructor on the stack. If it's not a function it's used as
// receiver for CALL_NON_FUNCTION, otherwise the value on the stack is // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
// ignored. // ignored.
DCHECK(!expr->expression()->IsSuperReference()); DCHECK(!expr->expression()->IsSuperPropertyReference());
VisitForStackValue(expr->expression()); VisitForStackValue(expr->expression());
// Push the arguments ("left-to-right") on the stack. // Push the arguments ("left-to-right") on the stack.
@ -3298,11 +3314,14 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) { void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
Variable* new_target_var = scope()->DeclarationScope()->new_target_var(); SuperCallReference* super_call_ref =
GetVar(result_register(), new_target_var); expr->expression()->AsSuperCallReference();
__ Push(result_register()); DCHECK_NOT_NULL(super_call_ref);
EmitLoadSuperConstructor(); VariableProxy* new_target_proxy = super_call_ref->new_target_var();
VisitForStackValue(new_target_proxy);
EmitLoadSuperConstructor(super_call_ref);
__ push(result_register()); __ push(result_register());
// Push the arguments ("left-to-right") on the stack. // Push the arguments ("left-to-right") on the stack.
@ -3340,8 +3359,7 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
RecordJSReturnSite(expr); RecordJSReturnSite(expr);
EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(), EmitInitializeThisAfterSuper(super_call_ref, expr->CallFeedbackICSlot());
expr->CallFeedbackICSlot());
context()->Plug(v0); context()->Plug(v0);
} }
@ -4227,11 +4245,15 @@ void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
void FullCodeGenerator::EmitDefaultConstructorCallSuper(CallRuntime* expr) { void FullCodeGenerator::EmitDefaultConstructorCallSuper(CallRuntime* expr) {
Variable* new_target_var = scope()->DeclarationScope()->new_target_var(); ZoneList<Expression*>* args = expr->arguments();
GetVar(result_register(), new_target_var); DCHECK(args->length() == 2);
__ Push(result_register());
EmitLoadSuperConstructor(); // new.target
VisitForStackValue(args->at(0));
// .this_function
VisitForStackValue(args->at(1));
__ CallRuntime(Runtime::kGetPrototype, 1);
__ Push(result_register()); __ Push(result_register());
// Check if the calling frame is an arguments adaptor frame. // Check if the calling frame is an arguments adaptor frame.
@ -4633,11 +4655,14 @@ void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) { void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
// Assert: expr == CallRuntime("ReflectConstruct") // Assert: expr == CallRuntime("ReflectConstruct")
DCHECK_EQ(1, expr->arguments()->length());
CallRuntime* call = expr->arguments()->at(0)->AsCallRuntime(); CallRuntime* call = expr->arguments()->at(0)->AsCallRuntime();
ZoneList<Expression*>* args = call->arguments(); ZoneList<Expression*>* args = call->arguments();
DCHECK_EQ(3, args->length()); DCHECK_EQ(3, args->length());
SuperReference* super_reference = args->at(0)->AsSuperReference(); SuperCallReference* super_call_ref = args->at(0)->AsSuperCallReference();
DCHECK_NOT_NULL(super_call_ref);
// Load ReflectConstruct function // Load ReflectConstruct function
EmitLoadJSRuntimeFunction(call); EmitLoadJSRuntimeFunction(call);
@ -4647,8 +4672,8 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
__ push(at); __ push(at);
__ sw(v0, MemOperand(sp, kPointerSize)); __ sw(v0, MemOperand(sp, kPointerSize));
// Push super // Push super constructor
EmitLoadSuperConstructor(); EmitLoadSuperConstructor(super_call_ref);
__ Push(result_register()); __ Push(result_register());
// Push arguments array // Push arguments array
@ -4665,7 +4690,7 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
context()->DropAndPlug(1, v0); context()->DropAndPlug(1, v0);
// TODO(mvstanton): with FLAG_vector_stores this needs a slot id. // TODO(mvstanton): with FLAG_vector_stores this needs a slot id.
EmitInitializeThisAfterSuper(super_reference); EmitInitializeThisAfterSuper(super_call_ref);
} }
@ -4890,9 +4915,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
} }
case NAMED_SUPER_PROPERTY: { case NAMED_SUPER_PROPERTY: {
VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
VisitForAccumulatorValue( VisitForAccumulatorValue(
prop->obj()->AsSuperReference()->home_object_var()); prop->obj()->AsSuperPropertyReference()->home_object_var());
__ Push(result_register()); __ Push(result_register());
const Register scratch = a1; const Register scratch = a1;
__ lw(scratch, MemOperand(sp, kPointerSize)); __ lw(scratch, MemOperand(sp, kPointerSize));
@ -4902,9 +4927,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
} }
case KEYED_SUPER_PROPERTY: { case KEYED_SUPER_PROPERTY: {
VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
VisitForAccumulatorValue( VisitForAccumulatorValue(
prop->obj()->AsSuperReference()->home_object_var()); prop->obj()->AsSuperPropertyReference()->home_object_var());
const Register scratch = a1; const Register scratch = a1;
const Register scratch1 = t0; const Register scratch1 = t0;
__ Move(scratch, result_register()); __ Move(scratch, result_register());

View File

@ -248,6 +248,24 @@ void FullCodeGenerator::Generate() {
} }
} }
// Possibly set up a local binding to the this function which is used in
// derived constructors with super calls.
Variable* this_function_var = scope()->this_function_var();
if (this_function_var != nullptr) {
Comment cmnt(masm_, "[ This function");
SetVar(this_function_var, a1, a2, a3);
}
Variable* new_target_var = scope()->new_target_var();
if (new_target_var != nullptr) {
Comment cmnt(masm_, "[ new.target");
// new.target is parameter -2.
int offset = 2 * kPointerSize +
(info_->scope()->num_parameters() + 1) * kPointerSize;
__ lw(v0, MemOperand(fp, offset));
SetVar(new_target_var, v0, a2, a3);
}
Variable* home_object_var = scope()->home_object_var(); Variable* home_object_var = scope()->home_object_var();
if (home_object_var != nullptr) { if (home_object_var != nullptr) {
__ Push(a1); __ Push(a1);
@ -1987,9 +2005,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
} }
break; break;
case NAMED_SUPER_PROPERTY: case NAMED_SUPER_PROPERTY:
VisitForStackValue(property->obj()->AsSuperReference()->this_var()); VisitForStackValue(
property->obj()->AsSuperPropertyReference()->this_var());
VisitForAccumulatorValue( VisitForAccumulatorValue(
property->obj()->AsSuperReference()->home_object_var()); property->obj()->AsSuperPropertyReference()->home_object_var());
__ Push(result_register()); __ Push(result_register());
if (expr->is_compound()) { if (expr->is_compound()) {
const Register scratch = a1; const Register scratch = a1;
@ -1999,9 +2018,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
break; break;
case KEYED_SUPER_PROPERTY: { case KEYED_SUPER_PROPERTY: {
const Register scratch = a1; const Register scratch = a1;
VisitForStackValue(property->obj()->AsSuperReference()->this_var()); VisitForStackValue(
property->obj()->AsSuperPropertyReference()->this_var());
VisitForAccumulatorValue( VisitForAccumulatorValue(
property->obj()->AsSuperReference()->home_object_var()); property->obj()->AsSuperPropertyReference()->home_object_var());
__ Move(scratch, result_register()); __ Move(scratch, result_register());
VisitForAccumulatorValue(property->key()); VisitForAccumulatorValue(property->key());
__ Push(scratch, result_register()); __ Push(scratch, result_register());
@ -2635,9 +2655,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr,
} }
case NAMED_SUPER_PROPERTY: { case NAMED_SUPER_PROPERTY: {
__ Push(v0); __ Push(v0);
VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
VisitForAccumulatorValue( VisitForAccumulatorValue(
prop->obj()->AsSuperReference()->home_object_var()); prop->obj()->AsSuperPropertyReference()->home_object_var());
// stack: value, this; v0: home_object // stack: value, this; v0: home_object
Register scratch = a2; Register scratch = a2;
Register scratch2 = a3; Register scratch2 = a3;
@ -2652,8 +2672,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr,
} }
case KEYED_SUPER_PROPERTY: { case KEYED_SUPER_PROPERTY: {
__ Push(v0); __ Push(v0);
VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var()); VisitForStackValue(
prop->obj()->AsSuperPropertyReference()->home_object_var());
VisitForAccumulatorValue(prop->key()); VisitForAccumulatorValue(prop->key());
Register scratch = a2; Register scratch = a2;
Register scratch2 = a3; Register scratch2 = a3;
@ -2886,8 +2907,9 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
__ Move(LoadDescriptor::ReceiverRegister(), v0); __ Move(LoadDescriptor::ReceiverRegister(), v0);
EmitNamedPropertyLoad(expr); EmitNamedPropertyLoad(expr);
} else { } else {
VisitForStackValue(expr->obj()->AsSuperReference()->this_var()); VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var()); VisitForStackValue(
expr->obj()->AsSuperPropertyReference()->home_object_var());
EmitNamedSuperPropertyLoad(expr); EmitNamedSuperPropertyLoad(expr);
} }
} else { } else {
@ -2898,8 +2920,9 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
__ pop(LoadDescriptor::ReceiverRegister()); __ pop(LoadDescriptor::ReceiverRegister());
EmitKeyedPropertyLoad(expr); EmitKeyedPropertyLoad(expr);
} else { } else {
VisitForStackValue(expr->obj()->AsSuperReference()->this_var()); VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var()); VisitForStackValue(
expr->obj()->AsSuperPropertyReference()->home_object_var());
VisitForStackValue(expr->key()); VisitForStackValue(expr->key());
EmitKeyedSuperPropertyLoad(expr); EmitKeyedSuperPropertyLoad(expr);
} }
@ -2961,7 +2984,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
DCHECK(!key->value()->IsSmi()); DCHECK(!key->value()->IsSmi());
// Load the function from the receiver. // Load the function from the receiver.
const Register scratch = a1; const Register scratch = a1;
SuperReference* super_ref = prop->obj()->AsSuperReference(); SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
VisitForAccumulatorValue(super_ref->home_object_var()); VisitForAccumulatorValue(super_ref->home_object_var());
__ mov(scratch, v0); __ mov(scratch, v0);
VisitForAccumulatorValue(super_ref->this_var()); VisitForAccumulatorValue(super_ref->this_var());
@ -3019,7 +3042,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
SetSourcePosition(prop->position()); SetSourcePosition(prop->position());
// Load the function from the receiver. // Load the function from the receiver.
const Register scratch = a1; const Register scratch = a1;
SuperReference* super_ref = prop->obj()->AsSuperReference(); SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
VisitForAccumulatorValue(super_ref->home_object_var()); VisitForAccumulatorValue(super_ref->home_object_var());
__ Move(scratch, v0); __ Move(scratch, v0);
VisitForAccumulatorValue(super_ref->this_var()); VisitForAccumulatorValue(super_ref->this_var());
@ -3098,15 +3121,8 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
} }
void FullCodeGenerator::EmitLoadSuperConstructor() {
__ ld(a0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
__ Push(a0);
__ CallRuntime(Runtime::kGetPrototype, 1);
}
void FullCodeGenerator::EmitInitializeThisAfterSuper( void FullCodeGenerator::EmitInitializeThisAfterSuper(
SuperReference* super_ref, FeedbackVectorICSlot slot) { SuperCallReference* super_ref, FeedbackVectorICSlot slot) {
Variable* this_var = super_ref->this_var()->var(); Variable* this_var = super_ref->this_var()->var();
GetVar(a1, this_var); GetVar(a1, this_var);
__ LoadRoot(at, Heap::kTheHoleValueRootIndex); __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
@ -3264,7 +3280,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
// Push constructor on the stack. If it's not a function it's used as // Push constructor on the stack. If it's not a function it's used as
// receiver for CALL_NON_FUNCTION, otherwise the value on the stack is // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
// ignored. // ignored.
DCHECK(!expr->expression()->IsSuperReference()); DCHECK(!expr->expression()->IsSuperPropertyReference());
VisitForStackValue(expr->expression()); VisitForStackValue(expr->expression());
// Push the arguments ("left-to-right") on the stack. // Push the arguments ("left-to-right") on the stack.
@ -3300,11 +3316,14 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) { void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
Variable* new_target_var = scope()->DeclarationScope()->new_target_var(); SuperCallReference* super_call_ref =
GetVar(result_register(), new_target_var); expr->expression()->AsSuperCallReference();
__ Push(result_register()); DCHECK_NOT_NULL(super_call_ref);
EmitLoadSuperConstructor(); VariableProxy* new_target_proxy = super_call_ref->new_target_var();
VisitForStackValue(new_target_proxy);
EmitLoadSuperConstructor(super_call_ref);
__ push(result_register()); __ push(result_register());
// Push the arguments ("left-to-right") on the stack. // Push the arguments ("left-to-right") on the stack.
@ -3342,8 +3361,7 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
RecordJSReturnSite(expr); RecordJSReturnSite(expr);
EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(), EmitInitializeThisAfterSuper(super_call_ref, expr->CallFeedbackICSlot());
expr->CallFeedbackICSlot());
context()->Plug(v0); context()->Plug(v0);
} }
@ -4231,11 +4249,15 @@ void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
void FullCodeGenerator::EmitDefaultConstructorCallSuper(CallRuntime* expr) { void FullCodeGenerator::EmitDefaultConstructorCallSuper(CallRuntime* expr) {
Variable* new_target_var = scope()->DeclarationScope()->new_target_var(); ZoneList<Expression*>* args = expr->arguments();
GetVar(result_register(), new_target_var); DCHECK(args->length() == 2);
__ Push(result_register());
EmitLoadSuperConstructor(); // new.target
VisitForStackValue(args->at(0));
// .this_function
VisitForStackValue(args->at(1));
__ CallRuntime(Runtime::kGetPrototype, 1);
__ Push(result_register()); __ Push(result_register());
// Check if the calling frame is an arguments adaptor frame. // Check if the calling frame is an arguments adaptor frame.
@ -4637,11 +4659,14 @@ void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) { void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
// Assert: expr === CallRuntime("ReflectConstruct") // Assert: expr === CallRuntime("ReflectConstruct")
DCHECK_EQ(1, expr->arguments()->length());
CallRuntime* call = expr->arguments()->at(0)->AsCallRuntime(); CallRuntime* call = expr->arguments()->at(0)->AsCallRuntime();
ZoneList<Expression*>* args = call->arguments(); ZoneList<Expression*>* args = call->arguments();
DCHECK_EQ(3, args->length()); DCHECK_EQ(3, args->length());
SuperReference* super_reference = args->at(0)->AsSuperReference(); SuperCallReference* super_call_ref = args->at(0)->AsSuperCallReference();
DCHECK_NOT_NULL(super_call_ref);
// Load ReflectConstruct function // Load ReflectConstruct function
EmitLoadJSRuntimeFunction(call); EmitLoadJSRuntimeFunction(call);
@ -4651,8 +4676,8 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
__ push(at); __ push(at);
__ sd(v0, MemOperand(sp, kPointerSize)); __ sd(v0, MemOperand(sp, kPointerSize));
// Push super // Push super constructor
EmitLoadSuperConstructor(); EmitLoadSuperConstructor(super_call_ref);
__ Push(result_register()); __ Push(result_register());
// Push arguments array // Push arguments array
@ -4669,7 +4694,7 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
context()->DropAndPlug(1, v0); context()->DropAndPlug(1, v0);
// TODO(mvstanton): with FLAG_vector_stores this needs a slot id. // TODO(mvstanton): with FLAG_vector_stores this needs a slot id.
EmitInitializeThisAfterSuper(super_reference); EmitInitializeThisAfterSuper(super_call_ref);
} }
@ -4893,9 +4918,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
} }
case NAMED_SUPER_PROPERTY: { case NAMED_SUPER_PROPERTY: {
VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
VisitForAccumulatorValue( VisitForAccumulatorValue(
prop->obj()->AsSuperReference()->home_object_var()); prop->obj()->AsSuperPropertyReference()->home_object_var());
__ Push(result_register()); __ Push(result_register());
const Register scratch = a1; const Register scratch = a1;
__ ld(scratch, MemOperand(sp, kPointerSize)); __ ld(scratch, MemOperand(sp, kPointerSize));
@ -4905,9 +4930,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
} }
case KEYED_SUPER_PROPERTY: { case KEYED_SUPER_PROPERTY: {
VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
VisitForAccumulatorValue( VisitForAccumulatorValue(
prop->obj()->AsSuperReference()->home_object_var()); prop->obj()->AsSuperPropertyReference()->home_object_var());
const Register scratch = a1; const Register scratch = a1;
const Register scratch1 = a4; const Register scratch1 = a4;
__ Move(scratch, result_register()); __ Move(scratch, result_register());

View File

@ -359,8 +359,17 @@ FunctionLiteral* Parser::DefaultConstructor(bool call_super, Scope* scope,
body = new (zone()) ZoneList<Statement*>(call_super ? 2 : 1, zone()); body = new (zone()) ZoneList<Statement*>(call_super ? 2 : 1, zone());
AddAssertIsConstruct(body, pos); AddAssertIsConstruct(body, pos);
if (call_super) { if (call_super) {
// %_DefaultConstructorCallSuper(new.target, .this_function)
ZoneList<Expression*>* args = ZoneList<Expression*>* args =
new (zone()) ZoneList<Expression*>(0, zone()); new (zone()) ZoneList<Expression*>(2, zone());
VariableProxy* new_target_proxy = scope_->NewUnresolved(
factory(), ast_value_factory()->new_target_string(), Variable::NORMAL,
pos);
args->Add(new_target_proxy, zone());
VariableProxy* this_function_proxy = scope_->NewUnresolved(
factory(), ast_value_factory()->this_function_string(),
Variable::NORMAL, pos);
args->Add(this_function_proxy, zone());
CallRuntime* call = factory()->NewCallRuntime( CallRuntime* call = factory()->NewCallRuntime(
ast_value_factory()->empty_string(), ast_value_factory()->empty_string(),
Runtime::FunctionForId(Runtime::kInlineDefaultConstructorCallSuper), Runtime::FunctionForId(Runtime::kInlineDefaultConstructorCallSuper),
@ -747,19 +756,32 @@ Expression* ParserTraits::ThisExpression(Scope* scope, AstNodeFactory* factory,
Variable::THIS, pos, pos + 4); Variable::THIS, pos, pos + 4);
} }
Expression* ParserTraits::SuperReference(Scope* scope, AstNodeFactory* factory, Expression* ParserTraits::SuperPropertyReference(Scope* scope,
int pos) { AstNodeFactory* factory,
// TODO(arv): Split into SuperProperty and SuperCall? int pos) {
VariableProxy* home_object_proxy = scope->NewUnresolved( VariableProxy* home_object_proxy = scope->NewUnresolved(
factory, parser_->ast_value_factory()->home_object_string(), factory, parser_->ast_value_factory()->home_object_string(),
Variable::NORMAL, pos); Variable::NORMAL, pos);
return factory->NewSuperPropertyReference(
return factory->NewSuperReference(
ThisExpression(scope, factory, pos)->AsVariableProxy(), home_object_proxy, ThisExpression(scope, factory, pos)->AsVariableProxy(), home_object_proxy,
pos); pos);
} }
Expression* ParserTraits::SuperCallReference(Scope* scope,
AstNodeFactory* factory, int pos) {
VariableProxy* new_target_proxy = scope->NewUnresolved(
factory, parser_->ast_value_factory()->new_target_string(),
Variable::NORMAL, pos);
VariableProxy* this_function_proxy = scope->NewUnresolved(
factory, parser_->ast_value_factory()->this_function_string(),
Variable::NORMAL, pos);
return factory->NewSuperCallReference(
ThisExpression(scope, factory, pos)->AsVariableProxy(), new_target_proxy,
this_function_proxy, pos);
}
Expression* ParserTraits::DefaultConstructor(bool call_super, Scope* scope, Expression* ParserTraits::DefaultConstructor(bool call_super, Scope* scope,
int pos, int end_pos) { int pos, int end_pos) {
return parser_->DefaultConstructor(call_super, scope, pos, end_pos); return parser_->DefaultConstructor(call_super, scope, pos, end_pos);
@ -5744,13 +5766,14 @@ ZoneList<v8::internal::Expression*>* Parser::PrepareSpreadArguments(
Expression* Parser::SpreadCall(Expression* function, Expression* Parser::SpreadCall(Expression* function,
ZoneList<v8::internal::Expression*>* args, ZoneList<v8::internal::Expression*>* args,
int pos) { int pos) {
if (function->IsSuperReference()) { if (function->IsSuperCallReference()) {
// Super calls // Super calls
// %_CallSuperWithSpread(%ReflectConstruct(<super>, args, new.target))
args->InsertAt(0, function, zone()); args->InsertAt(0, function, zone());
args->Add(factory()->NewVariableProxy(scope_->new_target_var()), zone()); args->Add(function->AsSuperCallReference()->new_target_var(), zone());
Expression* result = factory()->NewCallRuntime( Expression* result = factory()->NewCallRuntime(
ast_value_factory()->reflect_construct_string(), NULL, args, pos); ast_value_factory()->reflect_construct_string(), NULL, args, pos);
args = new (zone()) ZoneList<Expression*>(0, zone()); args = new (zone()) ZoneList<Expression*>(1, zone());
args->Add(result, zone()); args->Add(result, zone());
return factory()->NewCallRuntime( return factory()->NewCallRuntime(
ast_value_factory()->empty_string(), ast_value_factory()->empty_string(),

View File

@ -724,7 +724,10 @@ class ParserTraits {
Expression* ThisExpression(Scope* scope, AstNodeFactory* factory, Expression* ThisExpression(Scope* scope, AstNodeFactory* factory,
int pos = RelocInfo::kNoPosition); int pos = RelocInfo::kNoPosition);
Expression* SuperReference(Scope* scope, AstNodeFactory* factory, int pos); Expression* SuperPropertyReference(Scope* scope, AstNodeFactory* factory,
int pos);
Expression* SuperCallReference(Scope* scope, AstNodeFactory* factory,
int pos);
Expression* DefaultConstructor(bool call_super, Scope* scope, int pos, Expression* DefaultConstructor(bool call_super, Scope* scope, int pos,
int end_pos); int end_pos);
Literal* ExpressionFromLiteral(Token::Value token, int pos, Scanner* scanner, Literal* ExpressionFromLiteral(Token::Value token, int pos, Scanner* scanner,

View File

@ -404,7 +404,8 @@ NOT_A_PATTERN(NativeFunctionLiteral)
NOT_A_PATTERN(Property) NOT_A_PATTERN(Property)
NOT_A_PATTERN(RegExpLiteral) NOT_A_PATTERN(RegExpLiteral)
NOT_A_PATTERN(ReturnStatement) NOT_A_PATTERN(ReturnStatement)
NOT_A_PATTERN(SuperReference) NOT_A_PATTERN(SuperPropertyReference)
NOT_A_PATTERN(SuperCallReference)
NOT_A_PATTERN(SwitchStatement) NOT_A_PATTERN(SwitchStatement)
NOT_A_PATTERN(ThisFunction) NOT_A_PATTERN(ThisFunction)
NOT_A_PATTERN(Throw) NOT_A_PATTERN(Throw)

View File

@ -1715,9 +1715,15 @@ class PreParserTraits {
return PreParserExpression::This(); return PreParserExpression::This();
} }
static PreParserExpression SuperReference(Scope* scope, static PreParserExpression SuperPropertyReference(Scope* scope,
PreParserFactory* factory, PreParserFactory* factory,
int pos) { int pos) {
return PreParserExpression::Default();
}
static PreParserExpression SuperCallReference(Scope* scope,
PreParserFactory* factory,
int pos) {
return PreParserExpression::Default(); return PreParserExpression::Default();
} }
@ -3515,7 +3521,7 @@ ParserBase<Traits>::ParseStrongSuperCallExpression(
Consume(Token::SUPER); Consume(Token::SUPER);
int pos = position(); int pos = position();
Scanner::Location super_loc = scanner()->location(); Scanner::Location super_loc = scanner()->location();
ExpressionT expr = this->SuperReference(scope_, factory(), pos); ExpressionT expr = this->SuperCallReference(scope_, factory(), pos);
if (peek() != Token::LPAREN) { if (peek() != Token::LPAREN) {
ReportMessage(MessageTemplate::kStrongConstructorSuper); ReportMessage(MessageTemplate::kStrongConstructorSuper);
@ -3580,7 +3586,7 @@ ParserBase<Traits>::ParseSuperExpression(bool is_new,
i::IsConstructor(kind)) { i::IsConstructor(kind)) {
if (peek() == Token::PERIOD || peek() == Token::LBRACK) { if (peek() == Token::PERIOD || peek() == Token::LBRACK) {
scope->RecordSuperPropertyUsage(); scope->RecordSuperPropertyUsage();
return this->SuperReference(scope_, factory(), pos); return this->SuperPropertyReference(scope_, factory(), pos);
} }
// new super() is never allowed. // new super() is never allowed.
// super() is only allowed in derived constructor // super() is only allowed in derived constructor
@ -3595,7 +3601,7 @@ ParserBase<Traits>::ParseSuperExpression(bool is_new,
// TODO(rossberg): This might not be the correct FunctionState for the // TODO(rossberg): This might not be the correct FunctionState for the
// method here. // method here.
function_state_->set_super_location(scanner()->location()); function_state_->set_super_location(scanner()->location());
return this->SuperReference(scope_, factory(), pos); return this->SuperCallReference(scope_, factory(), pos);
} }
} }

View File

@ -364,7 +364,10 @@ void CallPrinter::VisitSpread(Spread* node) {
void CallPrinter::VisitThisFunction(ThisFunction* node) {} void CallPrinter::VisitThisFunction(ThisFunction* node) {}
void CallPrinter::VisitSuperReference(SuperReference* node) {} void CallPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) {}
void CallPrinter::VisitSuperCallReference(SuperCallReference* node) {}
void CallPrinter::FindStatements(ZoneList<Statement*>* statements) { void CallPrinter::FindStatements(ZoneList<Statement*>* statements) {
@ -835,8 +838,13 @@ void PrettyPrinter::VisitThisFunction(ThisFunction* node) {
} }
void PrettyPrinter::VisitSuperReference(SuperReference* node) { void PrettyPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) {
Print("<super-reference>"); Print("<super-property-reference>");
}
void PrettyPrinter::VisitSuperCallReference(SuperCallReference* node) {
Print("<super-call-reference>");
} }
@ -1527,10 +1535,16 @@ void AstPrinter::VisitThisFunction(ThisFunction* node) {
} }
void AstPrinter::VisitSuperReference(SuperReference* node) { void AstPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) {
IndentedScope indent(this, "SUPER-REFERENCE"); IndentedScope indent(this, "SUPER-PROPERTY-REFERENCE");
} }
void AstPrinter::VisitSuperCallReference(SuperCallReference* node) {
IndentedScope indent(this, "SUPER-CALL-REFERENCE");
}
#endif // DEBUG #endif // DEBUG
} } // namespace v8::internal } } // namespace v8::internal

View File

@ -72,8 +72,8 @@ namespace internal {
F(StoreKeyedToSuper_Strict, 4, 1) \ F(StoreKeyedToSuper_Strict, 4, 1) \
F(StoreKeyedToSuper_Sloppy, 4, 1) \ F(StoreKeyedToSuper_Sloppy, 4, 1) \
F(HandleStepInForDerivedConstructors, 1, 1) \ F(HandleStepInForDerivedConstructors, 1, 1) \
F(DefaultConstructorCallSuper, 0, 1) \ F(DefaultConstructorCallSuper, 2, 1) \
F(CallSuperWithSpread, 0, 1) F(CallSuperWithSpread, 1, 1)
#define FOR_EACH_INTRINSIC_COLLECTIONS(F) \ #define FOR_EACH_INTRINSIC_COLLECTIONS(F) \

View File

@ -160,6 +160,7 @@ void Scope::SetDefaults(ScopeType scope_type, Scope* outer_scope,
function_ = nullptr; function_ = nullptr;
arguments_ = nullptr; arguments_ = nullptr;
home_object_ = nullptr; home_object_ = nullptr;
this_function_ = nullptr;
illegal_redecl_ = nullptr; illegal_redecl_ = nullptr;
scope_inside_with_ = false; scope_inside_with_ = false;
scope_contains_with_ = false; scope_contains_with_ = false;
@ -308,45 +309,44 @@ void Scope::Initialize() {
} }
// Declare convenience variables and the receiver. // Declare convenience variables and the receiver.
if (is_declaration_scope()) { if (is_declaration_scope() && has_this_declaration()) {
DCHECK(!subclass_constructor || is_function_scope()); Variable* var = variables_.Declare(
if (has_this_declaration()) { this, ast_value_factory_->this_string(),
Variable* var = variables_.Declare( subclass_constructor ? CONST : VAR, Variable::THIS,
this, ast_value_factory_->this_string(), subclass_constructor ? kNeedsInitialization : kCreatedInitialized);
subclass_constructor ? CONST : VAR, Variable::THIS, receiver_ = var;
subclass_constructor ? kNeedsInitialization : kCreatedInitialized); }
receiver_ = var;
if (is_function_scope()) {
if (!is_arrow_scope()) {
// Declare 'arguments' variable which exists in all non arrow functions.
// Note that it might never be accessed, in which case it won't be
// allocated during variable allocation.
variables_.Declare(this, ast_value_factory_->arguments_string(), VAR,
Variable::ARGUMENTS, kCreatedInitialized);
} }
if (subclass_constructor) { if (subclass_constructor) {
new_target_ = DCHECK(!is_arrow_scope());
variables_.Declare(this, ast_value_factory_->new_target_string(), variables_.Declare(this, ast_value_factory_->new_target_string(), CONST,
CONST, Variable::NEW_TARGET, kCreatedInitialized); Variable::NORMAL, kCreatedInitialized);
new_target_->AllocateTo(Variable::PARAMETER, -2);
new_target_->set_is_used();
} }
}
if (is_function_scope() && !is_arrow_scope()) { if (IsConciseMethod(function_kind_) || IsConstructor(function_kind_) ||
// Declare 'arguments' variable which exists in all non arrow functions. IsAccessorFunction(function_kind_)) {
// Note that it might never be accessed, in which case it won't be DCHECK(!is_arrow_scope());
// allocated during variable allocation. // Declare '.home_object' variable which exists in all methods.
variables_.Declare(this, // Note that it might never be accessed, in which case it won't be
ast_value_factory_->arguments_string(), // allocated during variable allocation.
VAR, variables_.Declare(this, ast_value_factory_->home_object_string(), CONST,
Variable::ARGUMENTS, Variable::NORMAL, kCreatedInitialized);
kCreatedInitialized); }
}
if (is_function_scope() && if (IsSubclassConstructor(function_kind_)) {
(IsConciseMethod(function_kind_) || IsConstructor(function_kind_) || DCHECK(!is_arrow_scope());
IsAccessorFunction(function_kind_))) { variables_.Declare(this, ast_value_factory_->this_function_string(),
DCHECK(!is_arrow_scope()); CONST, Variable::NORMAL, kCreatedInitialized);
// Declare '.home_object' variable which exists in all methods. }
// Note that it might never be accessed, in which case it won't be
// allocated during variable allocation.
variables_.Declare(this, ast_value_factory_->home_object_string(), VAR,
Variable::NORMAL, kCreatedInitialized);
} }
} }
@ -1311,7 +1311,7 @@ bool Scope::MustAllocate(Variable* var) {
// Give var a read/write use if there is a chance it might be accessed // Give var a read/write use if there is a chance it might be accessed
// via an eval() call. This is only possible if the variable has a // via an eval() call. This is only possible if the variable has a
// visible name. // visible name.
if ((var->is_this() || var->is_new_target() || !var->raw_name()->IsEmpty()) && if ((var->is_this() || !var->raw_name()->IsEmpty()) &&
(var->has_forced_context_allocation() || scope_calls_eval_ || (var->has_forced_context_allocation() || scope_calls_eval_ ||
inner_scope_calls_eval_ || scope_contains_with_ || is_catch_scope() || inner_scope_calls_eval_ || scope_contains_with_ || is_catch_scope() ||
is_block_scope() || is_module_scope() || is_script_scope())) { is_block_scope() || is_module_scope() || is_script_scope())) {
@ -1403,18 +1403,6 @@ void Scope::AllocateParameterLocals(Isolate* isolate) {
rest_parameter_ = NULL; rest_parameter_ = NULL;
} }
Variable* home_object_var =
LookupLocal(ast_value_factory_->home_object_string());
if (home_object_var != nullptr && uses_super_property() &&
MustAllocate(home_object_var)) {
// TODO(arv): super() uses a SuperReference so it generates a VariableProxy
// for the .home_object which makes it look like we need to allocate the
// home_object_var.
// Consider splitting the AST node into 2 different nodes since the
// semantics is just so different.
home_object_ = home_object_var;
}
// The same parameter may occur multiple times in the parameters_ list. // The same parameter may occur multiple times in the parameters_ list.
// If it does, and if it is not copied into the context object, it must // If it does, and if it is not copied into the context object, it must
// receive the highest parameter index for that parameter; thus iteration // receive the highest parameter index for that parameter; thus iteration
@ -1503,13 +1491,31 @@ void Scope::AllocateNonParameterLocals(Isolate* isolate) {
// allocated in the context, it must be the last slot in the context, // allocated in the context, it must be the last slot in the context,
// because of the current ScopeInfo implementation (see // because of the current ScopeInfo implementation (see
// ScopeInfo::ScopeInfo(FunctionScope* scope) constructor). // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor).
if (function_ != NULL) { if (function_ != nullptr) {
AllocateNonParameterLocal(isolate, function_->proxy()->var()); AllocateNonParameterLocal(isolate, function_->proxy()->var());
} }
if (rest_parameter_) { if (rest_parameter_ != nullptr) {
AllocateNonParameterLocal(isolate, rest_parameter_); AllocateNonParameterLocal(isolate, rest_parameter_);
} }
Variable* home_object_var =
LookupLocal(ast_value_factory_->home_object_string());
if (home_object_var != nullptr && MustAllocate(home_object_var)) {
home_object_ = home_object_var;
}
Variable* new_target_var =
LookupLocal(ast_value_factory_->new_target_string());
if (new_target_var != nullptr && MustAllocate(new_target_var)) {
new_target_ = new_target_var;
}
Variable* this_function_var =
LookupLocal(ast_value_factory_->this_function_string());
if (this_function_var != nullptr && MustAllocate(this_function_var)) {
this_function_ = this_function_var;
}
} }

View File

@ -419,6 +419,13 @@ class Scope: public ZoneObject {
return home_object_; return home_object_;
} }
Variable* this_function_var() const {
// This is only used in derived constructors atm.
DCHECK(this_function_ == nullptr ||
(is_function_scope() && IsSubclassConstructor(function_kind())));
return this_function_;
}
// Declarations list. // Declarations list.
ZoneList<Declaration*>* declarations() { return &decls_; } ZoneList<Declaration*>* declarations() { return &decls_; }
@ -579,6 +586,8 @@ class Scope: public ZoneObject {
Variable* arguments_; Variable* arguments_;
// Convenience variable; method scopes only. // Convenience variable; method scopes only.
Variable* home_object_; Variable* home_object_;
// Convenience variable; Subclass constructor only
Variable* this_function_;
// Module descriptor; module scopes only. // Module descriptor; module scopes only.
ModuleDescriptor* module_descriptor_; ModuleDescriptor* module_descriptor_;

View File

@ -761,7 +761,10 @@ void AstTyper::VisitThisFunction(ThisFunction* expr) {
} }
void AstTyper::VisitSuperReference(SuperReference* expr) {} void AstTyper::VisitSuperPropertyReference(SuperPropertyReference* expr) {}
void AstTyper::VisitSuperCallReference(SuperCallReference* expr) {}
void AstTyper::VisitDeclarations(ZoneList<Declaration*>* decls) { void AstTyper::VisitDeclarations(ZoneList<Declaration*>* decls) {

View File

@ -20,7 +20,7 @@ class ClassVariable;
class Variable: public ZoneObject { class Variable: public ZoneObject {
public: public:
enum Kind { NORMAL, FUNCTION, CLASS, THIS, NEW_TARGET, ARGUMENTS }; enum Kind { NORMAL, FUNCTION, CLASS, THIS, ARGUMENTS };
enum Location { enum Location {
// Before and during variable allocation, a variable whose location is // Before and during variable allocation, a variable whose location is
@ -103,7 +103,6 @@ class Variable: public ZoneObject {
bool is_function() const { return kind_ == FUNCTION; } bool is_function() const { return kind_ == FUNCTION; }
bool is_class() const { return kind_ == CLASS; } bool is_class() const { return kind_ == CLASS; }
bool is_this() const { return kind_ == THIS; } bool is_this() const { return kind_ == THIS; }
bool is_new_target() const { return kind_ == NEW_TARGET; }
bool is_arguments() const { return kind_ == ARGUMENTS; } bool is_arguments() const { return kind_ == ARGUMENTS; }
ClassVariable* AsClassVariable() { ClassVariable* AsClassVariable() {

View File

@ -234,6 +234,24 @@ void FullCodeGenerator::Generate() {
} }
} }
// Possibly set up a local binding to the this function which is used in
// derived constructors with super calls.
Variable* this_function_var = scope()->this_function_var();
if (this_function_var != nullptr) {
Comment cmnt(masm_, "[ This function");
SetVar(this_function_var, rdi, rbx, rdx);
}
Variable* new_target_var = scope()->new_target_var();
if (new_target_var != nullptr) {
Comment cmnt(masm_, "[ new.target");
// new.target is parameter -2.
int offset = 2 * kPointerSize + kFPOnStackSize + kPCOnStackSize +
(info_->scope()->num_parameters() - 1) * kPointerSize;
__ movp(rax, Operand(rbp, offset));
SetVar(new_target_var, rax, rbx, rdx);
}
Variable* home_object_var = scope()->home_object_var(); Variable* home_object_var = scope()->home_object_var();
if (home_object_var != nullptr) { if (home_object_var != nullptr) {
__ Push(rdi); __ Push(rdi);
@ -1959,9 +1977,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
} }
break; break;
case NAMED_SUPER_PROPERTY: case NAMED_SUPER_PROPERTY:
VisitForStackValue(property->obj()->AsSuperReference()->this_var()); VisitForStackValue(
property->obj()->AsSuperPropertyReference()->this_var());
VisitForAccumulatorValue( VisitForAccumulatorValue(
property->obj()->AsSuperReference()->home_object_var()); property->obj()->AsSuperPropertyReference()->home_object_var());
__ Push(result_register()); __ Push(result_register());
if (expr->is_compound()) { if (expr->is_compound()) {
__ Push(MemOperand(rsp, kPointerSize)); __ Push(MemOperand(rsp, kPointerSize));
@ -1969,9 +1988,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
} }
break; break;
case KEYED_SUPER_PROPERTY: case KEYED_SUPER_PROPERTY:
VisitForStackValue(property->obj()->AsSuperReference()->this_var());
VisitForStackValue( VisitForStackValue(
property->obj()->AsSuperReference()->home_object_var()); property->obj()->AsSuperPropertyReference()->this_var());
VisitForStackValue(
property->obj()->AsSuperPropertyReference()->home_object_var());
VisitForAccumulatorValue(property->key()); VisitForAccumulatorValue(property->key());
__ Push(result_register()); __ Push(result_register());
if (expr->is_compound()) { if (expr->is_compound()) {
@ -2563,9 +2583,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr,
} }
case NAMED_SUPER_PROPERTY: { case NAMED_SUPER_PROPERTY: {
__ Push(rax); __ Push(rax);
VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
VisitForAccumulatorValue( VisitForAccumulatorValue(
prop->obj()->AsSuperReference()->home_object_var()); prop->obj()->AsSuperPropertyReference()->home_object_var());
// stack: value, this; rax: home_object // stack: value, this; rax: home_object
Register scratch = rcx; Register scratch = rcx;
Register scratch2 = rdx; Register scratch2 = rdx;
@ -2580,8 +2600,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr,
} }
case KEYED_SUPER_PROPERTY: { case KEYED_SUPER_PROPERTY: {
__ Push(rax); __ Push(rax);
VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var()); VisitForStackValue(
prop->obj()->AsSuperPropertyReference()->home_object_var());
VisitForAccumulatorValue(prop->key()); VisitForAccumulatorValue(prop->key());
Register scratch = rcx; Register scratch = rcx;
Register scratch2 = rdx; Register scratch2 = rdx;
@ -2800,8 +2821,9 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
__ movp(LoadDescriptor::ReceiverRegister(), rax); __ movp(LoadDescriptor::ReceiverRegister(), rax);
EmitNamedPropertyLoad(expr); EmitNamedPropertyLoad(expr);
} else { } else {
VisitForStackValue(expr->obj()->AsSuperReference()->this_var()); VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var()); VisitForStackValue(
expr->obj()->AsSuperPropertyReference()->home_object_var());
EmitNamedSuperPropertyLoad(expr); EmitNamedSuperPropertyLoad(expr);
} }
} else { } else {
@ -2812,8 +2834,9 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
__ Pop(LoadDescriptor::ReceiverRegister()); __ Pop(LoadDescriptor::ReceiverRegister());
EmitKeyedPropertyLoad(expr); EmitKeyedPropertyLoad(expr);
} else { } else {
VisitForStackValue(expr->obj()->AsSuperReference()->this_var()); VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var()); VisitForStackValue(
expr->obj()->AsSuperPropertyReference()->home_object_var());
VisitForStackValue(expr->key()); VisitForStackValue(expr->key());
EmitKeyedSuperPropertyLoad(expr); EmitKeyedSuperPropertyLoad(expr);
} }
@ -2871,7 +2894,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
Literal* key = prop->key()->AsLiteral(); Literal* key = prop->key()->AsLiteral();
DCHECK(!key->value()->IsSmi()); DCHECK(!key->value()->IsSmi());
// Load the function from the receiver. // Load the function from the receiver.
SuperReference* super_ref = prop->obj()->AsSuperReference(); SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
VisitForStackValue(super_ref->home_object_var()); VisitForStackValue(super_ref->home_object_var());
VisitForAccumulatorValue(super_ref->this_var()); VisitForAccumulatorValue(super_ref->this_var());
__ Push(rax); __ Push(rax);
@ -2928,7 +2951,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
SetSourcePosition(prop->position()); SetSourcePosition(prop->position());
// Load the function from the receiver. // Load the function from the receiver.
SuperReference* super_ref = prop->obj()->AsSuperReference(); SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
VisitForStackValue(super_ref->home_object_var()); VisitForStackValue(super_ref->home_object_var());
VisitForAccumulatorValue(super_ref->this_var()); VisitForAccumulatorValue(super_ref->this_var());
__ Push(rax); __ Push(rax);
@ -3009,14 +3032,8 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
} }
void FullCodeGenerator::EmitLoadSuperConstructor() {
__ Push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
__ CallRuntime(Runtime::kGetPrototype, 1);
}
void FullCodeGenerator::EmitInitializeThisAfterSuper( void FullCodeGenerator::EmitInitializeThisAfterSuper(
SuperReference* super_ref, FeedbackVectorICSlot slot) { SuperCallReference* super_ref, FeedbackVectorICSlot slot) {
Variable* this_var = super_ref->this_var()->var(); Variable* this_var = super_ref->this_var()->var();
GetVar(rcx, this_var); GetVar(rcx, this_var);
__ CompareRoot(rcx, Heap::kTheHoleValueRootIndex); __ CompareRoot(rcx, Heap::kTheHoleValueRootIndex);
@ -3166,7 +3183,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
// Push constructor on the stack. If it's not a function it's used as // Push constructor on the stack. If it's not a function it's used as
// receiver for CALL_NON_FUNCTION, otherwise the value on the stack is // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
// ignored. // ignored.
DCHECK(!expr->expression()->IsSuperReference()); DCHECK(!expr->expression()->IsSuperPropertyReference());
VisitForStackValue(expr->expression()); VisitForStackValue(expr->expression());
// Push the arguments ("left-to-right") on the stack. // Push the arguments ("left-to-right") on the stack.
@ -3202,11 +3219,14 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) { void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
Variable* new_target_var = scope()->DeclarationScope()->new_target_var(); SuperCallReference* super_call_ref =
GetVar(result_register(), new_target_var); expr->expression()->AsSuperCallReference();
__ Push(result_register()); DCHECK_NOT_NULL(super_call_ref);
EmitLoadSuperConstructor(); VariableProxy* new_target_proxy = super_call_ref->new_target_var();
VisitForStackValue(new_target_proxy);
EmitLoadSuperConstructor(super_call_ref);
__ Push(result_register()); __ Push(result_register());
// Push the arguments ("left-to-right") on the stack. // Push the arguments ("left-to-right") on the stack.
@ -3244,8 +3264,7 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
RecordJSReturnSite(expr); RecordJSReturnSite(expr);
EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(), EmitInitializeThisAfterSuper(super_call_ref, expr->CallFeedbackICSlot());
expr->CallFeedbackICSlot());
context()->Plug(rax); context()->Plug(rax);
} }
@ -4112,11 +4131,15 @@ void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
void FullCodeGenerator::EmitDefaultConstructorCallSuper(CallRuntime* expr) { void FullCodeGenerator::EmitDefaultConstructorCallSuper(CallRuntime* expr) {
Variable* new_target_var = scope()->DeclarationScope()->new_target_var(); ZoneList<Expression*>* args = expr->arguments();
GetVar(result_register(), new_target_var); DCHECK(args->length() == 2);
__ Push(result_register());
EmitLoadSuperConstructor(); // new.target
VisitForStackValue(args->at(0));
// .this_function
VisitForStackValue(args->at(1));
__ CallRuntime(Runtime::kGetPrototype, 1);
__ Push(result_register()); __ Push(result_register());
// Check if the calling frame is an arguments adaptor frame. // Check if the calling frame is an arguments adaptor frame.
@ -4568,11 +4591,14 @@ void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) { void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
// Assert: expr === CallRuntime("ReflectConstruct") // Assert: expr === CallRuntime("ReflectConstruct")
DCHECK_EQ(1, expr->arguments()->length());
CallRuntime* call = expr->arguments()->at(0)->AsCallRuntime(); CallRuntime* call = expr->arguments()->at(0)->AsCallRuntime();
ZoneList<Expression*>* args = call->arguments(); ZoneList<Expression*>* args = call->arguments();
DCHECK_EQ(3, args->length()); DCHECK_EQ(3, args->length());
SuperReference* super_reference = args->at(0)->AsSuperReference(); SuperCallReference* super_call_ref = args->at(0)->AsSuperCallReference();
DCHECK_NOT_NULL(super_call_ref);
// Load ReflectConstruct function // Load ReflectConstruct function
EmitLoadJSRuntimeFunction(call); EmitLoadJSRuntimeFunction(call);
@ -4581,8 +4607,8 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
__ Push(Operand(rsp, 0)); __ Push(Operand(rsp, 0));
__ movp(Operand(rsp, kPointerSize), rax); __ movp(Operand(rsp, kPointerSize), rax);
// Push super // Push super constructor
EmitLoadSuperConstructor(); EmitLoadSuperConstructor(super_call_ref);
__ Push(result_register()); __ Push(result_register());
// Push arguments array // Push arguments array
@ -4599,7 +4625,7 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
context()->DropAndPlug(1, rax); context()->DropAndPlug(1, rax);
// TODO(mvstanton): with FLAG_vector_stores this needs a slot id. // TODO(mvstanton): with FLAG_vector_stores this needs a slot id.
EmitInitializeThisAfterSuper(super_reference); EmitInitializeThisAfterSuper(super_call_ref);
} }
@ -4824,9 +4850,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
} }
case NAMED_SUPER_PROPERTY: { case NAMED_SUPER_PROPERTY: {
VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
VisitForAccumulatorValue( VisitForAccumulatorValue(
prop->obj()->AsSuperReference()->home_object_var()); prop->obj()->AsSuperPropertyReference()->home_object_var());
__ Push(result_register()); __ Push(result_register());
__ Push(MemOperand(rsp, kPointerSize)); __ Push(MemOperand(rsp, kPointerSize));
__ Push(result_register()); __ Push(result_register());
@ -4835,8 +4861,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
} }
case KEYED_SUPER_PROPERTY: { case KEYED_SUPER_PROPERTY: {
VisitForStackValue(prop->obj()->AsSuperReference()->this_var()); VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var()); VisitForStackValue(
prop->obj()->AsSuperPropertyReference()->home_object_var());
VisitForAccumulatorValue(prop->key()); VisitForAccumulatorValue(prop->key());
__ Push(result_register()); __ Push(result_register());
__ Push(MemOperand(rsp, 2 * kPointerSize)); __ Push(MemOperand(rsp, 2 * kPointerSize));

View File

@ -3,7 +3,7 @@
// found in the LICENSE file. // found in the LICENSE file.
// Flags: --harmony-classes --harmony-arrow-functions --allow-natives-syntax // Flags: --harmony-classes --harmony-arrow-functions --allow-natives-syntax
// Flags: --harmony-spreadcalls
(function TestSuperNamedLoads() { (function TestSuperNamedLoads() {
function Base() { } function Base() { }
@ -2107,3 +2107,99 @@ TestKeyedSetterCreatingOwnPropertiesNonConfigurable(42, 43, 44);
let d = new Derived(); let d = new Derived();
assertSame(1, d.arrow()); assertSame(1, d.arrow());
})(); })();
(function TestSuperCallInEval() {
'use strict';
class Base {
constructor(x) {
this.x = x;
}
}
class Derived extends Base {
constructor(x) {
eval('super(x)');
}
}
let d = new Derived(42);
assertSame(42, d.x);
})();
(function TestSuperCallInArrow() {
'use strict';
class Base {
constructor(x) {
this.x = x;
}
}
class Derived extends Base {
constructor(x) {
(() => super(x))();
}
}
let d = new Derived(42);
assertSame(42, d.x);
})();
(function TestSuperCallEscapes() {
'use strict';
class Base {
constructor(x) {
this.x = x;
}
}
let f;
class Derived extends Base {
constructor() {
f = () => super(2);
}
}
assertThrows(function() {
new Derived();
}, ReferenceError);
let o = f();
assertEquals(2, o.x);
assertInstanceof(o, Derived);
assertThrows(function() {
f();
}, ReferenceError);
})();
(function TestSuperCallSpreadInEval() {
'use strict';
class Base {
constructor(x) {
this.x = x;
}
}
class Derived extends Base {
constructor(x) {
eval('super(...[x])');
}
}
let d = new Derived(42);
assertSame(42, d.x);
})();
(function TestSuperCallSpreadInArrow() {
'use strict';
class Base {
constructor(x) {
this.x = x;
}
}
class Derived extends Base {
constructor(x) {
(() => super(...[x]))();
}
}
let d = new Derived(42);
assertSame(42, d.x);
})();