[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:
parent
f2eb98b900
commit
673c0516ab
@ -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();
|
||||
if (home_object_var != nullptr) {
|
||||
__ Push(r1);
|
||||
@ -2002,9 +2020,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
}
|
||||
break;
|
||||
case NAMED_SUPER_PROPERTY:
|
||||
VisitForStackValue(property->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(
|
||||
property->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForAccumulatorValue(
|
||||
property->obj()->AsSuperReference()->home_object_var());
|
||||
property->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
__ Push(result_register());
|
||||
if (expr->is_compound()) {
|
||||
const Register scratch = r1;
|
||||
@ -2014,9 +2033,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
}
|
||||
break;
|
||||
case KEYED_SUPER_PROPERTY:
|
||||
VisitForStackValue(property->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(
|
||||
property->obj()->AsSuperReference()->home_object_var());
|
||||
property->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForStackValue(
|
||||
property->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
VisitForAccumulatorValue(property->key());
|
||||
__ Push(result_register());
|
||||
if (expr->is_compound()) {
|
||||
@ -2659,9 +2679,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr,
|
||||
}
|
||||
case NAMED_SUPER_PROPERTY: {
|
||||
__ Push(r0);
|
||||
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForAccumulatorValue(
|
||||
prop->obj()->AsSuperReference()->home_object_var());
|
||||
prop->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
// stack: value, this; r0: home_object
|
||||
Register scratch = r2;
|
||||
Register scratch2 = r3;
|
||||
@ -2676,8 +2696,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr,
|
||||
}
|
||||
case KEYED_SUPER_PROPERTY: {
|
||||
__ Push(r0);
|
||||
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
|
||||
VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForStackValue(
|
||||
prop->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
VisitForAccumulatorValue(prop->key());
|
||||
Register scratch = r2;
|
||||
Register scratch2 = r3;
|
||||
@ -2901,8 +2922,9 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
|
||||
__ Move(LoadDescriptor::ReceiverRegister(), r0);
|
||||
EmitNamedPropertyLoad(expr);
|
||||
} else {
|
||||
VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
|
||||
VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForStackValue(
|
||||
expr->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
EmitNamedSuperPropertyLoad(expr);
|
||||
}
|
||||
} else {
|
||||
@ -2913,8 +2935,9 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
|
||||
__ pop(LoadDescriptor::ReceiverRegister());
|
||||
EmitKeyedPropertyLoad(expr);
|
||||
} else {
|
||||
VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
|
||||
VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForStackValue(
|
||||
expr->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
VisitForStackValue(expr->key());
|
||||
EmitKeyedSuperPropertyLoad(expr);
|
||||
}
|
||||
@ -2979,7 +3002,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
|
||||
DCHECK(!key->value()->IsSmi());
|
||||
// Load the function from the receiver.
|
||||
const Register scratch = r1;
|
||||
SuperReference* super_ref = prop->obj()->AsSuperReference();
|
||||
SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
|
||||
VisitForStackValue(super_ref->home_object_var());
|
||||
VisitForAccumulatorValue(super_ref->this_var());
|
||||
__ Push(r0);
|
||||
@ -3039,7 +3062,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
|
||||
SetSourcePosition(prop->position());
|
||||
// Load the function from the receiver.
|
||||
const Register scratch = r1;
|
||||
SuperReference* super_ref = prop->obj()->AsSuperReference();
|
||||
SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
|
||||
VisitForStackValue(super_ref->home_object_var());
|
||||
VisitForAccumulatorValue(super_ref->this_var());
|
||||
__ 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(
|
||||
SuperReference* super_ref, FeedbackVectorICSlot slot) {
|
||||
SuperCallReference* super_ref, FeedbackVectorICSlot slot) {
|
||||
Variable* this_var = super_ref->this_var()->var();
|
||||
GetVar(r1, this_var);
|
||||
__ 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
|
||||
// receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
|
||||
// ignored.
|
||||
DCHECK(!expr->expression()->IsSuperReference());
|
||||
DCHECK(!expr->expression()->IsSuperPropertyReference());
|
||||
VisitForStackValue(expr->expression());
|
||||
|
||||
// Push the arguments ("left-to-right") on the stack.
|
||||
@ -3325,11 +3341,14 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
|
||||
Variable* new_target_var = scope()->DeclarationScope()->new_target_var();
|
||||
GetVar(result_register(), new_target_var);
|
||||
__ Push(result_register());
|
||||
SuperCallReference* super_call_ref =
|
||||
expr->expression()->AsSuperCallReference();
|
||||
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 the arguments ("left-to-right") on the stack.
|
||||
@ -3367,8 +3386,7 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
|
||||
|
||||
RecordJSReturnSite(expr);
|
||||
|
||||
EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(),
|
||||
expr->CallFeedbackICSlot());
|
||||
EmitInitializeThisAfterSuper(super_call_ref, expr->CallFeedbackICSlot());
|
||||
context()->Plug(r0);
|
||||
}
|
||||
|
||||
@ -4229,11 +4247,15 @@ void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitDefaultConstructorCallSuper(CallRuntime* expr) {
|
||||
Variable* new_target_var = scope()->DeclarationScope()->new_target_var();
|
||||
GetVar(result_register(), new_target_var);
|
||||
__ Push(result_register());
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK(args->length() == 2);
|
||||
|
||||
EmitLoadSuperConstructor();
|
||||
// new.target
|
||||
VisitForStackValue(args->at(0));
|
||||
|
||||
// .this_function
|
||||
VisitForStackValue(args->at(1));
|
||||
__ CallRuntime(Runtime::kGetPrototype, 1);
|
||||
__ Push(result_register());
|
||||
|
||||
// Check if the calling frame is an arguments adaptor frame.
|
||||
@ -4626,11 +4648,14 @@ void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
|
||||
|
||||
void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
|
||||
// Assert: expr === CallRuntime("ReflectConstruct")
|
||||
DCHECK_EQ(1, expr->arguments()->length());
|
||||
CallRuntime* call = expr->arguments()->at(0)->AsCallRuntime();
|
||||
|
||||
ZoneList<Expression*>* args = call->arguments();
|
||||
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
|
||||
EmitLoadJSRuntimeFunction(call);
|
||||
@ -4640,8 +4665,8 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
|
||||
__ push(ip);
|
||||
__ str(r0, MemOperand(sp, kPointerSize));
|
||||
|
||||
// Push super
|
||||
EmitLoadSuperConstructor();
|
||||
// Push super constructor
|
||||
EmitLoadSuperConstructor(super_call_ref);
|
||||
__ Push(result_register());
|
||||
|
||||
// Push arguments array
|
||||
@ -4658,7 +4683,7 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
|
||||
context()->DropAndPlug(1, r0);
|
||||
|
||||
// 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: {
|
||||
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForAccumulatorValue(
|
||||
prop->obj()->AsSuperReference()->home_object_var());
|
||||
prop->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
__ Push(result_register());
|
||||
const Register scratch = r1;
|
||||
__ ldr(scratch, MemOperand(sp, kPointerSize));
|
||||
@ -4896,8 +4921,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
}
|
||||
|
||||
case KEYED_SUPER_PROPERTY: {
|
||||
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
|
||||
VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForStackValue(
|
||||
prop->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
VisitForAccumulatorValue(prop->key());
|
||||
__ Push(result_register());
|
||||
const Register scratch = r1;
|
||||
|
@ -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();
|
||||
if (home_object_var != nullptr) {
|
||||
__ Push(x1);
|
||||
@ -1970,9 +1988,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
}
|
||||
break;
|
||||
case NAMED_SUPER_PROPERTY:
|
||||
VisitForStackValue(property->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(
|
||||
property->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForAccumulatorValue(
|
||||
property->obj()->AsSuperReference()->home_object_var());
|
||||
property->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
__ Push(result_register());
|
||||
if (expr->is_compound()) {
|
||||
const Register scratch = x10;
|
||||
@ -1981,9 +2000,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
}
|
||||
break;
|
||||
case KEYED_SUPER_PROPERTY:
|
||||
VisitForStackValue(property->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(
|
||||
property->obj()->AsSuperReference()->home_object_var());
|
||||
property->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForStackValue(
|
||||
property->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
VisitForAccumulatorValue(property->key());
|
||||
__ Push(result_register());
|
||||
if (expr->is_compound()) {
|
||||
@ -2340,9 +2360,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr,
|
||||
}
|
||||
case NAMED_SUPER_PROPERTY: {
|
||||
__ Push(x0);
|
||||
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForAccumulatorValue(
|
||||
prop->obj()->AsSuperReference()->home_object_var());
|
||||
prop->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
// stack: value, this; x0: home_object
|
||||
Register scratch = x10;
|
||||
Register scratch2 = x11;
|
||||
@ -2357,8 +2377,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr,
|
||||
}
|
||||
case KEYED_SUPER_PROPERTY: {
|
||||
__ Push(x0);
|
||||
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
|
||||
VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForStackValue(
|
||||
prop->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
VisitForAccumulatorValue(prop->key());
|
||||
Register scratch = x10;
|
||||
Register scratch2 = x11;
|
||||
@ -2584,8 +2605,9 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
|
||||
__ Move(LoadDescriptor::ReceiverRegister(), x0);
|
||||
EmitNamedPropertyLoad(expr);
|
||||
} else {
|
||||
VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
|
||||
VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForStackValue(
|
||||
expr->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
EmitNamedSuperPropertyLoad(expr);
|
||||
}
|
||||
} else {
|
||||
@ -2596,8 +2618,9 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
|
||||
__ Pop(LoadDescriptor::ReceiverRegister());
|
||||
EmitKeyedPropertyLoad(expr);
|
||||
} else {
|
||||
VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
|
||||
VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForStackValue(
|
||||
expr->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
VisitForStackValue(expr->key());
|
||||
EmitKeyedSuperPropertyLoad(expr);
|
||||
}
|
||||
@ -2665,7 +2688,8 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
|
||||
|
||||
// Load the function from the receiver.
|
||||
const Register scratch = x10;
|
||||
SuperReference* super_ref = callee->AsProperty()->obj()->AsSuperReference();
|
||||
SuperPropertyReference* super_ref =
|
||||
callee->AsProperty()->obj()->AsSuperPropertyReference();
|
||||
VisitForStackValue(super_ref->home_object_var());
|
||||
VisitForAccumulatorValue(super_ref->this_var());
|
||||
__ Push(x0);
|
||||
@ -2724,7 +2748,8 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
|
||||
|
||||
// Load the function from the receiver.
|
||||
const Register scratch = x10;
|
||||
SuperReference* super_ref = callee->AsProperty()->obj()->AsSuperReference();
|
||||
SuperPropertyReference* super_ref =
|
||||
callee->AsProperty()->obj()->AsSuperPropertyReference();
|
||||
VisitForStackValue(super_ref->home_object_var());
|
||||
VisitForAccumulatorValue(super_ref->this_var());
|
||||
__ 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(
|
||||
SuperReference* super_ref, FeedbackVectorICSlot slot) {
|
||||
SuperCallReference* super_ref, FeedbackVectorICSlot slot) {
|
||||
Variable* this_var = super_ref->this_var()->var();
|
||||
GetVar(x1, this_var);
|
||||
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
|
||||
// receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
|
||||
// ignored.
|
||||
DCHECK(!expr->expression()->IsSuperReference());
|
||||
DCHECK(!expr->expression()->IsSuperPropertyReference());
|
||||
VisitForStackValue(expr->expression());
|
||||
|
||||
// Push the arguments ("left-to-right") on the stack.
|
||||
@ -3009,11 +3027,14 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
|
||||
Variable* new_target_var = scope()->DeclarationScope()->new_target_var();
|
||||
GetVar(result_register(), new_target_var);
|
||||
__ Push(result_register());
|
||||
SuperCallReference* super_call_ref =
|
||||
expr->expression()->AsSuperCallReference();
|
||||
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 the arguments ("left-to-right") on the stack.
|
||||
@ -3051,8 +3072,7 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
|
||||
|
||||
RecordJSReturnSite(expr);
|
||||
|
||||
EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(),
|
||||
expr->CallFeedbackICSlot());
|
||||
EmitInitializeThisAfterSuper(super_call_ref, expr->CallFeedbackICSlot());
|
||||
context()->Plug(x0);
|
||||
}
|
||||
|
||||
@ -3932,11 +3952,15 @@ void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitDefaultConstructorCallSuper(CallRuntime* expr) {
|
||||
Variable* new_target_var = scope()->DeclarationScope()->new_target_var();
|
||||
GetVar(result_register(), new_target_var);
|
||||
__ Push(result_register());
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK(args->length() == 2);
|
||||
|
||||
EmitLoadSuperConstructor();
|
||||
// new.target
|
||||
VisitForStackValue(args->at(0));
|
||||
|
||||
// .this_function
|
||||
VisitForStackValue(args->at(1));
|
||||
__ CallRuntime(Runtime::kGetPrototype, 1);
|
||||
__ Push(result_register());
|
||||
|
||||
// Check if the calling frame is an arguments adaptor frame.
|
||||
@ -4309,11 +4333,14 @@ void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
|
||||
|
||||
void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
|
||||
// Assert: expr === CallRuntime("ReflectConstruct")
|
||||
DCHECK_EQ(1, expr->arguments()->length());
|
||||
CallRuntime* call = expr->arguments()->at(0)->AsCallRuntime();
|
||||
|
||||
ZoneList<Expression*>* args = call->arguments();
|
||||
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
|
||||
EmitLoadJSRuntimeFunction(call);
|
||||
@ -4322,8 +4349,8 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
|
||||
__ Pop(x10);
|
||||
__ Push(x0, x10);
|
||||
|
||||
// Push super
|
||||
EmitLoadSuperConstructor();
|
||||
// Push super constructor
|
||||
EmitLoadSuperConstructor(super_call_ref);
|
||||
__ Push(result_register());
|
||||
|
||||
// Push arguments array
|
||||
@ -4340,7 +4367,7 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
|
||||
context()->DropAndPlug(1, x0);
|
||||
|
||||
// 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: {
|
||||
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForAccumulatorValue(
|
||||
prop->obj()->AsSuperReference()->home_object_var());
|
||||
prop->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
__ Push(result_register());
|
||||
const Register scratch = x10;
|
||||
__ Peek(scratch, kPointerSize);
|
||||
@ -4574,8 +4601,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
}
|
||||
|
||||
case KEYED_SUPER_PROPERTY: {
|
||||
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
|
||||
VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForStackValue(
|
||||
prop->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
VisitForAccumulatorValue(prop->key());
|
||||
__ Push(result_register());
|
||||
const Register scratch1 = x10;
|
||||
|
@ -168,15 +168,26 @@ void AstNumberingVisitor::VisitThisFunction(ThisFunction* node) {
|
||||
}
|
||||
|
||||
|
||||
void AstNumberingVisitor::VisitSuperReference(SuperReference* node) {
|
||||
void AstNumberingVisitor::VisitSuperPropertyReference(
|
||||
SuperPropertyReference* node) {
|
||||
IncrementNodeCount();
|
||||
DisableOptimization(kSuperReference);
|
||||
node->set_base_id(ReserveIdRange(SuperReference::num_ids()));
|
||||
node->set_base_id(ReserveIdRange(SuperPropertyReference::num_ids()));
|
||||
Visit(node->this_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) {
|
||||
IncrementNodeCount();
|
||||
DisableOptimization(kImportDeclaration);
|
||||
|
@ -267,6 +267,7 @@ class AstValue : public ZoneObject {
|
||||
F(spread_arguments, "$spreadArguments") \
|
||||
F(spread_iterable, "$spreadIterable") \
|
||||
F(this, "this") \
|
||||
F(this_function, ".this_function") \
|
||||
F(throw_iterator_result_not_an_object, "ThrowIteratorResultNotAnObject") \
|
||||
F(to_string, "$toString") \
|
||||
F(undefined, "undefined") \
|
||||
|
@ -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();
|
||||
return property != NULL ? PROPERTY_CALL : OTHER_CALL;
|
||||
|
58
src/ast.h
58
src/ast.h
@ -87,7 +87,8 @@ namespace internal {
|
||||
V(CompareOperation) \
|
||||
V(Spread) \
|
||||
V(ThisFunction) \
|
||||
V(SuperReference) \
|
||||
V(SuperPropertyReference) \
|
||||
V(SuperCallReference) \
|
||||
V(CaseClause)
|
||||
|
||||
#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 IsSuperAccess() {
|
||||
return obj()->IsSuperReference();
|
||||
}
|
||||
bool IsSuperAccess() { return obj()->IsSuperPropertyReference(); }
|
||||
|
||||
virtual FeedbackVectorRequirements ComputeFeedbackRequirements(
|
||||
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:
|
||||
DECLARE_NODE_TYPE(SuperReference)
|
||||
DECLARE_NODE_TYPE(SuperPropertyReference)
|
||||
|
||||
VariableProxy* this_var() const { return this_var_; }
|
||||
VariableProxy* home_object_var() const { return home_object_var_; }
|
||||
|
||||
protected:
|
||||
SuperReference(Zone* zone, VariableProxy* this_var,
|
||||
VariableProxy* home_object_var, int pos)
|
||||
SuperPropertyReference(Zone* zone, VariableProxy* this_var,
|
||||
VariableProxy* home_object_var, int pos)
|
||||
: Expression(zone, pos),
|
||||
this_var_(this_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
|
||||
|
||||
|
||||
@ -3581,9 +3608,18 @@ class AstNodeFactory final BASE_EMBEDDED {
|
||||
return new (zone_) ThisFunction(zone_, pos);
|
||||
}
|
||||
|
||||
SuperReference* NewSuperReference(VariableProxy* this_var,
|
||||
VariableProxy* home_object_var, int pos) {
|
||||
return new (zone_) SuperReference(zone_, this_var, home_object_var, pos);
|
||||
SuperPropertyReference* NewSuperPropertyReference(
|
||||
VariableProxy* this_var, VariableProxy* home_object_var, int 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:
|
||||
|
@ -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.
|
||||
SetStackOverflow();
|
||||
ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
|
||||
|
@ -67,7 +67,8 @@ void ALAA::VisitVariableProxy(VariableProxy* leaf) {}
|
||||
void ALAA::VisitLiteral(Literal* leaf) {}
|
||||
void ALAA::VisitRegExpLiteral(RegExpLiteral* leaf) {}
|
||||
void ALAA::VisitThisFunction(ThisFunction* leaf) {}
|
||||
void ALAA::VisitSuperReference(SuperReference* leaf) {}
|
||||
void ALAA::VisitSuperPropertyReference(SuperPropertyReference* leaf) {}
|
||||
void ALAA::VisitSuperCallReference(SuperCallReference* leaf) {}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
@ -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())
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
Comment cmnt(masm_, "[ ReturnStatement");
|
||||
SetStatementPosition(stmt);
|
||||
|
@ -672,9 +672,9 @@ class FullCodeGenerator: public AstVisitor {
|
||||
Expression* initializer, int offset,
|
||||
FeedbackVectorICSlot slot = FeedbackVectorICSlot::Invalid());
|
||||
|
||||
void EmitLoadSuperConstructor();
|
||||
void EmitLoadSuperConstructor(SuperCallReference* super_call_ref);
|
||||
void EmitInitializeThisAfterSuper(
|
||||
SuperReference* super_ref,
|
||||
SuperCallReference* super_call_ref,
|
||||
FeedbackVectorICSlot slot = FeedbackVectorICSlot::Invalid());
|
||||
|
||||
void CallIC(Handle<Code> code,
|
||||
|
@ -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(current_block() != NULL);
|
||||
DCHECK(current_block()->HasPredecessor());
|
||||
|
@ -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();
|
||||
if (home_object_var != nullptr) {
|
||||
__ push(edi);
|
||||
@ -1920,9 +1938,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
// Nothing to do here.
|
||||
break;
|
||||
case NAMED_SUPER_PROPERTY:
|
||||
VisitForStackValue(property->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(
|
||||
property->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForAccumulatorValue(
|
||||
property->obj()->AsSuperReference()->home_object_var());
|
||||
property->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
__ push(result_register());
|
||||
if (expr->is_compound()) {
|
||||
__ push(MemOperand(esp, kPointerSize));
|
||||
@ -1939,9 +1958,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
}
|
||||
break;
|
||||
case KEYED_SUPER_PROPERTY:
|
||||
VisitForStackValue(property->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(
|
||||
property->obj()->AsSuperReference()->home_object_var());
|
||||
property->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForStackValue(
|
||||
property->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
VisitForAccumulatorValue(property->key());
|
||||
__ Push(result_register());
|
||||
if (expr->is_compound()) {
|
||||
@ -2565,9 +2585,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr,
|
||||
}
|
||||
case NAMED_SUPER_PROPERTY: {
|
||||
__ push(eax);
|
||||
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForAccumulatorValue(
|
||||
prop->obj()->AsSuperReference()->home_object_var());
|
||||
prop->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
// stack: value, this; eax: home_object
|
||||
Register scratch = ecx;
|
||||
Register scratch2 = edx;
|
||||
@ -2582,8 +2602,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr,
|
||||
}
|
||||
case KEYED_SUPER_PROPERTY: {
|
||||
__ push(eax);
|
||||
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
|
||||
VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForStackValue(
|
||||
prop->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
VisitForAccumulatorValue(prop->key());
|
||||
Register scratch = ecx;
|
||||
Register scratch2 = edx;
|
||||
@ -2805,8 +2826,9 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
|
||||
__ Move(LoadDescriptor::ReceiverRegister(), result_register());
|
||||
EmitNamedPropertyLoad(expr);
|
||||
} else {
|
||||
VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
|
||||
VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForStackValue(
|
||||
expr->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
EmitNamedSuperPropertyLoad(expr);
|
||||
}
|
||||
} else {
|
||||
@ -2817,8 +2839,9 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
|
||||
__ Move(LoadDescriptor::NameRegister(), result_register()); // Key.
|
||||
EmitKeyedPropertyLoad(expr);
|
||||
} else {
|
||||
VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
|
||||
VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForStackValue(
|
||||
expr->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
VisitForStackValue(expr->key());
|
||||
EmitKeyedSuperPropertyLoad(expr);
|
||||
}
|
||||
@ -2876,7 +2899,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
|
||||
Literal* key = prop->key()->AsLiteral();
|
||||
DCHECK(!key->value()->IsSmi());
|
||||
// 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());
|
||||
VisitForAccumulatorValue(super_ref->this_var());
|
||||
__ push(eax);
|
||||
@ -2932,7 +2955,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
|
||||
|
||||
SetSourcePosition(prop->position());
|
||||
// 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());
|
||||
VisitForAccumulatorValue(super_ref->this_var());
|
||||
__ 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(
|
||||
SuperReference* super_ref, FeedbackVectorICSlot slot) {
|
||||
Variable* this_var = super_ref->this_var()->var();
|
||||
SuperCallReference* super_call_ref, FeedbackVectorICSlot slot) {
|
||||
Variable* this_var = super_call_ref->this_var()->var();
|
||||
GetVar(ecx, this_var);
|
||||
__ cmp(ecx, isolate()->factory()->the_hole_value());
|
||||
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
|
||||
// receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
|
||||
// ignored.
|
||||
DCHECK(!expr->expression()->IsSuperReference());
|
||||
DCHECK(!expr->expression()->IsSuperPropertyReference());
|
||||
VisitForStackValue(expr->expression());
|
||||
|
||||
// Push the arguments ("left-to-right") on the stack.
|
||||
@ -3203,11 +3220,14 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
|
||||
Variable* new_target_var = scope()->DeclarationScope()->new_target_var();
|
||||
GetVar(eax, new_target_var);
|
||||
__ push(eax);
|
||||
SuperCallReference* super_call_ref =
|
||||
expr->expression()->AsSuperCallReference();
|
||||
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 the arguments ("left-to-right") on the stack.
|
||||
@ -3245,8 +3265,7 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
|
||||
|
||||
RecordJSReturnSite(expr);
|
||||
|
||||
EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(),
|
||||
expr->CallFeedbackICSlot());
|
||||
EmitInitializeThisAfterSuper(super_call_ref, expr->CallFeedbackICSlot());
|
||||
context()->Plug(eax);
|
||||
}
|
||||
|
||||
@ -4123,11 +4142,15 @@ void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitDefaultConstructorCallSuper(CallRuntime* expr) {
|
||||
Variable* new_target_var = scope()->DeclarationScope()->new_target_var();
|
||||
GetVar(eax, new_target_var);
|
||||
__ push(eax);
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK(args->length() == 2);
|
||||
|
||||
EmitLoadSuperConstructor();
|
||||
// new.target
|
||||
VisitForStackValue(args->at(0));
|
||||
|
||||
// .this_function
|
||||
VisitForStackValue(args->at(1));
|
||||
__ CallRuntime(Runtime::kGetPrototype, 1);
|
||||
__ push(result_register());
|
||||
|
||||
// Check if the calling frame is an arguments adaptor frame.
|
||||
@ -4550,11 +4573,14 @@ void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
|
||||
|
||||
void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
|
||||
// Assert: expr == CallRuntime("ReflectConstruct")
|
||||
DCHECK_EQ(1, expr->arguments()->length());
|
||||
CallRuntime* call = expr->arguments()->at(0)->AsCallRuntime();
|
||||
|
||||
ZoneList<Expression*>* args = call->arguments();
|
||||
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
|
||||
EmitLoadJSRuntimeFunction(call);
|
||||
@ -4563,8 +4589,8 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
|
||||
__ push(Operand(esp, 0));
|
||||
__ mov(Operand(esp, kPointerSize), eax);
|
||||
|
||||
// Push super
|
||||
EmitLoadSuperConstructor();
|
||||
// Push super constructor
|
||||
EmitLoadSuperConstructor(super_call_ref);
|
||||
__ Push(result_register());
|
||||
|
||||
// Push arguments array
|
||||
@ -4581,7 +4607,7 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
|
||||
context()->DropAndPlug(1, eax);
|
||||
|
||||
// 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: {
|
||||
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForAccumulatorValue(
|
||||
prop->obj()->AsSuperReference()->home_object_var());
|
||||
prop->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
__ push(result_register());
|
||||
__ push(MemOperand(esp, kPointerSize));
|
||||
__ push(result_register());
|
||||
@ -4817,8 +4843,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
}
|
||||
|
||||
case KEYED_SUPER_PROPERTY: {
|
||||
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
|
||||
VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForStackValue(
|
||||
prop->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
VisitForAccumulatorValue(prop->key());
|
||||
__ push(result_register());
|
||||
__ push(MemOperand(esp, 2 * kPointerSize));
|
||||
|
@ -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();
|
||||
if (home_object_var != nullptr) {
|
||||
__ Push(a1);
|
||||
@ -1988,9 +2006,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
}
|
||||
break;
|
||||
case NAMED_SUPER_PROPERTY:
|
||||
VisitForStackValue(property->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(
|
||||
property->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForAccumulatorValue(
|
||||
property->obj()->AsSuperReference()->home_object_var());
|
||||
property->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
__ Push(result_register());
|
||||
if (expr->is_compound()) {
|
||||
const Register scratch = a1;
|
||||
@ -2000,9 +2019,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
break;
|
||||
case KEYED_SUPER_PROPERTY: {
|
||||
const Register scratch = a1;
|
||||
VisitForStackValue(property->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(
|
||||
property->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForAccumulatorValue(
|
||||
property->obj()->AsSuperReference()->home_object_var());
|
||||
property->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
__ Move(scratch, result_register());
|
||||
VisitForAccumulatorValue(property->key());
|
||||
__ Push(scratch, result_register());
|
||||
@ -2636,9 +2656,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr,
|
||||
}
|
||||
case NAMED_SUPER_PROPERTY: {
|
||||
__ Push(v0);
|
||||
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForAccumulatorValue(
|
||||
prop->obj()->AsSuperReference()->home_object_var());
|
||||
prop->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
// stack: value, this; v0: home_object
|
||||
Register scratch = a2;
|
||||
Register scratch2 = a3;
|
||||
@ -2653,8 +2673,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr,
|
||||
}
|
||||
case KEYED_SUPER_PROPERTY: {
|
||||
__ Push(v0);
|
||||
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
|
||||
VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForStackValue(
|
||||
prop->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
VisitForAccumulatorValue(prop->key());
|
||||
Register scratch = a2;
|
||||
Register scratch2 = a3;
|
||||
@ -2883,8 +2904,9 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
|
||||
__ Move(LoadDescriptor::ReceiverRegister(), v0);
|
||||
EmitNamedPropertyLoad(expr);
|
||||
} else {
|
||||
VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
|
||||
VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForStackValue(
|
||||
expr->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
EmitNamedSuperPropertyLoad(expr);
|
||||
}
|
||||
} else {
|
||||
@ -2895,8 +2917,9 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
|
||||
__ pop(LoadDescriptor::ReceiverRegister());
|
||||
EmitKeyedPropertyLoad(expr);
|
||||
} else {
|
||||
VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
|
||||
VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForStackValue(
|
||||
expr->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
VisitForStackValue(expr->key());
|
||||
EmitKeyedSuperPropertyLoad(expr);
|
||||
}
|
||||
@ -2958,7 +2981,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
|
||||
DCHECK(!key->value()->IsSmi());
|
||||
// Load the function from the receiver.
|
||||
const Register scratch = a1;
|
||||
SuperReference* super_ref = prop->obj()->AsSuperReference();
|
||||
SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
|
||||
VisitForAccumulatorValue(super_ref->home_object_var());
|
||||
__ mov(scratch, v0);
|
||||
VisitForAccumulatorValue(super_ref->this_var());
|
||||
@ -3016,7 +3039,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
|
||||
SetSourcePosition(prop->position());
|
||||
// Load the function from the receiver.
|
||||
const Register scratch = a1;
|
||||
SuperReference* super_ref = prop->obj()->AsSuperReference();
|
||||
SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
|
||||
VisitForAccumulatorValue(super_ref->home_object_var());
|
||||
__ Move(scratch, v0);
|
||||
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(
|
||||
SuperReference* super_ref, FeedbackVectorICSlot slot) {
|
||||
SuperCallReference* super_ref, FeedbackVectorICSlot slot) {
|
||||
Variable* this_var = super_ref->this_var()->var();
|
||||
GetVar(a1, this_var);
|
||||
__ 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
|
||||
// receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
|
||||
// ignored.
|
||||
DCHECK(!expr->expression()->IsSuperReference());
|
||||
DCHECK(!expr->expression()->IsSuperPropertyReference());
|
||||
VisitForStackValue(expr->expression());
|
||||
|
||||
// Push the arguments ("left-to-right") on the stack.
|
||||
@ -3298,11 +3314,14 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
|
||||
Variable* new_target_var = scope()->DeclarationScope()->new_target_var();
|
||||
GetVar(result_register(), new_target_var);
|
||||
__ Push(result_register());
|
||||
SuperCallReference* super_call_ref =
|
||||
expr->expression()->AsSuperCallReference();
|
||||
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 the arguments ("left-to-right") on the stack.
|
||||
@ -3340,8 +3359,7 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
|
||||
|
||||
RecordJSReturnSite(expr);
|
||||
|
||||
EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(),
|
||||
expr->CallFeedbackICSlot());
|
||||
EmitInitializeThisAfterSuper(super_call_ref, expr->CallFeedbackICSlot());
|
||||
context()->Plug(v0);
|
||||
}
|
||||
|
||||
@ -4227,11 +4245,15 @@ void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitDefaultConstructorCallSuper(CallRuntime* expr) {
|
||||
Variable* new_target_var = scope()->DeclarationScope()->new_target_var();
|
||||
GetVar(result_register(), new_target_var);
|
||||
__ Push(result_register());
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK(args->length() == 2);
|
||||
|
||||
EmitLoadSuperConstructor();
|
||||
// new.target
|
||||
VisitForStackValue(args->at(0));
|
||||
|
||||
// .this_function
|
||||
VisitForStackValue(args->at(1));
|
||||
__ CallRuntime(Runtime::kGetPrototype, 1);
|
||||
__ Push(result_register());
|
||||
|
||||
// Check if the calling frame is an arguments adaptor frame.
|
||||
@ -4633,11 +4655,14 @@ void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
|
||||
|
||||
void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
|
||||
// Assert: expr == CallRuntime("ReflectConstruct")
|
||||
DCHECK_EQ(1, expr->arguments()->length());
|
||||
CallRuntime* call = expr->arguments()->at(0)->AsCallRuntime();
|
||||
|
||||
ZoneList<Expression*>* args = call->arguments();
|
||||
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
|
||||
EmitLoadJSRuntimeFunction(call);
|
||||
@ -4647,8 +4672,8 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
|
||||
__ push(at);
|
||||
__ sw(v0, MemOperand(sp, kPointerSize));
|
||||
|
||||
// Push super
|
||||
EmitLoadSuperConstructor();
|
||||
// Push super constructor
|
||||
EmitLoadSuperConstructor(super_call_ref);
|
||||
__ Push(result_register());
|
||||
|
||||
// Push arguments array
|
||||
@ -4665,7 +4690,7 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
|
||||
context()->DropAndPlug(1, v0);
|
||||
|
||||
// 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: {
|
||||
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForAccumulatorValue(
|
||||
prop->obj()->AsSuperReference()->home_object_var());
|
||||
prop->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
__ Push(result_register());
|
||||
const Register scratch = a1;
|
||||
__ lw(scratch, MemOperand(sp, kPointerSize));
|
||||
@ -4902,9 +4927,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
}
|
||||
|
||||
case KEYED_SUPER_PROPERTY: {
|
||||
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForAccumulatorValue(
|
||||
prop->obj()->AsSuperReference()->home_object_var());
|
||||
prop->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
const Register scratch = a1;
|
||||
const Register scratch1 = t0;
|
||||
__ Move(scratch, result_register());
|
||||
|
@ -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();
|
||||
if (home_object_var != nullptr) {
|
||||
__ Push(a1);
|
||||
@ -1987,9 +2005,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
}
|
||||
break;
|
||||
case NAMED_SUPER_PROPERTY:
|
||||
VisitForStackValue(property->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(
|
||||
property->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForAccumulatorValue(
|
||||
property->obj()->AsSuperReference()->home_object_var());
|
||||
property->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
__ Push(result_register());
|
||||
if (expr->is_compound()) {
|
||||
const Register scratch = a1;
|
||||
@ -1999,9 +2018,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
break;
|
||||
case KEYED_SUPER_PROPERTY: {
|
||||
const Register scratch = a1;
|
||||
VisitForStackValue(property->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(
|
||||
property->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForAccumulatorValue(
|
||||
property->obj()->AsSuperReference()->home_object_var());
|
||||
property->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
__ Move(scratch, result_register());
|
||||
VisitForAccumulatorValue(property->key());
|
||||
__ Push(scratch, result_register());
|
||||
@ -2635,9 +2655,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr,
|
||||
}
|
||||
case NAMED_SUPER_PROPERTY: {
|
||||
__ Push(v0);
|
||||
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForAccumulatorValue(
|
||||
prop->obj()->AsSuperReference()->home_object_var());
|
||||
prop->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
// stack: value, this; v0: home_object
|
||||
Register scratch = a2;
|
||||
Register scratch2 = a3;
|
||||
@ -2652,8 +2672,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr,
|
||||
}
|
||||
case KEYED_SUPER_PROPERTY: {
|
||||
__ Push(v0);
|
||||
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
|
||||
VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForStackValue(
|
||||
prop->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
VisitForAccumulatorValue(prop->key());
|
||||
Register scratch = a2;
|
||||
Register scratch2 = a3;
|
||||
@ -2886,8 +2907,9 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
|
||||
__ Move(LoadDescriptor::ReceiverRegister(), v0);
|
||||
EmitNamedPropertyLoad(expr);
|
||||
} else {
|
||||
VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
|
||||
VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForStackValue(
|
||||
expr->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
EmitNamedSuperPropertyLoad(expr);
|
||||
}
|
||||
} else {
|
||||
@ -2898,8 +2920,9 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
|
||||
__ pop(LoadDescriptor::ReceiverRegister());
|
||||
EmitKeyedPropertyLoad(expr);
|
||||
} else {
|
||||
VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
|
||||
VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForStackValue(
|
||||
expr->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
VisitForStackValue(expr->key());
|
||||
EmitKeyedSuperPropertyLoad(expr);
|
||||
}
|
||||
@ -2961,7 +2984,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
|
||||
DCHECK(!key->value()->IsSmi());
|
||||
// Load the function from the receiver.
|
||||
const Register scratch = a1;
|
||||
SuperReference* super_ref = prop->obj()->AsSuperReference();
|
||||
SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
|
||||
VisitForAccumulatorValue(super_ref->home_object_var());
|
||||
__ mov(scratch, v0);
|
||||
VisitForAccumulatorValue(super_ref->this_var());
|
||||
@ -3019,7 +3042,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
|
||||
SetSourcePosition(prop->position());
|
||||
// Load the function from the receiver.
|
||||
const Register scratch = a1;
|
||||
SuperReference* super_ref = prop->obj()->AsSuperReference();
|
||||
SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
|
||||
VisitForAccumulatorValue(super_ref->home_object_var());
|
||||
__ Move(scratch, v0);
|
||||
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(
|
||||
SuperReference* super_ref, FeedbackVectorICSlot slot) {
|
||||
SuperCallReference* super_ref, FeedbackVectorICSlot slot) {
|
||||
Variable* this_var = super_ref->this_var()->var();
|
||||
GetVar(a1, this_var);
|
||||
__ 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
|
||||
// receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
|
||||
// ignored.
|
||||
DCHECK(!expr->expression()->IsSuperReference());
|
||||
DCHECK(!expr->expression()->IsSuperPropertyReference());
|
||||
VisitForStackValue(expr->expression());
|
||||
|
||||
// Push the arguments ("left-to-right") on the stack.
|
||||
@ -3300,11 +3316,14 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
|
||||
Variable* new_target_var = scope()->DeclarationScope()->new_target_var();
|
||||
GetVar(result_register(), new_target_var);
|
||||
__ Push(result_register());
|
||||
SuperCallReference* super_call_ref =
|
||||
expr->expression()->AsSuperCallReference();
|
||||
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 the arguments ("left-to-right") on the stack.
|
||||
@ -3342,8 +3361,7 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
|
||||
|
||||
RecordJSReturnSite(expr);
|
||||
|
||||
EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(),
|
||||
expr->CallFeedbackICSlot());
|
||||
EmitInitializeThisAfterSuper(super_call_ref, expr->CallFeedbackICSlot());
|
||||
context()->Plug(v0);
|
||||
}
|
||||
|
||||
@ -4231,11 +4249,15 @@ void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitDefaultConstructorCallSuper(CallRuntime* expr) {
|
||||
Variable* new_target_var = scope()->DeclarationScope()->new_target_var();
|
||||
GetVar(result_register(), new_target_var);
|
||||
__ Push(result_register());
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK(args->length() == 2);
|
||||
|
||||
EmitLoadSuperConstructor();
|
||||
// new.target
|
||||
VisitForStackValue(args->at(0));
|
||||
|
||||
// .this_function
|
||||
VisitForStackValue(args->at(1));
|
||||
__ CallRuntime(Runtime::kGetPrototype, 1);
|
||||
__ Push(result_register());
|
||||
|
||||
// Check if the calling frame is an arguments adaptor frame.
|
||||
@ -4637,11 +4659,14 @@ void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
|
||||
|
||||
void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
|
||||
// Assert: expr === CallRuntime("ReflectConstruct")
|
||||
DCHECK_EQ(1, expr->arguments()->length());
|
||||
CallRuntime* call = expr->arguments()->at(0)->AsCallRuntime();
|
||||
|
||||
ZoneList<Expression*>* args = call->arguments();
|
||||
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
|
||||
EmitLoadJSRuntimeFunction(call);
|
||||
@ -4651,8 +4676,8 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
|
||||
__ push(at);
|
||||
__ sd(v0, MemOperand(sp, kPointerSize));
|
||||
|
||||
// Push super
|
||||
EmitLoadSuperConstructor();
|
||||
// Push super constructor
|
||||
EmitLoadSuperConstructor(super_call_ref);
|
||||
__ Push(result_register());
|
||||
|
||||
// Push arguments array
|
||||
@ -4669,7 +4694,7 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
|
||||
context()->DropAndPlug(1, v0);
|
||||
|
||||
// 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: {
|
||||
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForAccumulatorValue(
|
||||
prop->obj()->AsSuperReference()->home_object_var());
|
||||
prop->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
__ Push(result_register());
|
||||
const Register scratch = a1;
|
||||
__ ld(scratch, MemOperand(sp, kPointerSize));
|
||||
@ -4905,9 +4930,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
}
|
||||
|
||||
case KEYED_SUPER_PROPERTY: {
|
||||
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForAccumulatorValue(
|
||||
prop->obj()->AsSuperReference()->home_object_var());
|
||||
prop->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
const Register scratch = a1;
|
||||
const Register scratch1 = a4;
|
||||
__ Move(scratch, result_register());
|
||||
|
@ -359,8 +359,17 @@ FunctionLiteral* Parser::DefaultConstructor(bool call_super, Scope* scope,
|
||||
body = new (zone()) ZoneList<Statement*>(call_super ? 2 : 1, zone());
|
||||
AddAssertIsConstruct(body, pos);
|
||||
if (call_super) {
|
||||
// %_DefaultConstructorCallSuper(new.target, .this_function)
|
||||
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(
|
||||
ast_value_factory()->empty_string(),
|
||||
Runtime::FunctionForId(Runtime::kInlineDefaultConstructorCallSuper),
|
||||
@ -747,19 +756,32 @@ Expression* ParserTraits::ThisExpression(Scope* scope, AstNodeFactory* factory,
|
||||
Variable::THIS, pos, pos + 4);
|
||||
}
|
||||
|
||||
Expression* ParserTraits::SuperReference(Scope* scope, AstNodeFactory* factory,
|
||||
int pos) {
|
||||
// TODO(arv): Split into SuperProperty and SuperCall?
|
||||
Expression* ParserTraits::SuperPropertyReference(Scope* scope,
|
||||
AstNodeFactory* factory,
|
||||
int pos) {
|
||||
VariableProxy* home_object_proxy = scope->NewUnresolved(
|
||||
factory, parser_->ast_value_factory()->home_object_string(),
|
||||
Variable::NORMAL, pos);
|
||||
|
||||
return factory->NewSuperReference(
|
||||
return factory->NewSuperPropertyReference(
|
||||
ThisExpression(scope, factory, pos)->AsVariableProxy(), home_object_proxy,
|
||||
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,
|
||||
int pos, int 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,
|
||||
ZoneList<v8::internal::Expression*>* args,
|
||||
int pos) {
|
||||
if (function->IsSuperReference()) {
|
||||
if (function->IsSuperCallReference()) {
|
||||
// Super calls
|
||||
// %_CallSuperWithSpread(%ReflectConstruct(<super>, args, new.target))
|
||||
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(
|
||||
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());
|
||||
return factory()->NewCallRuntime(
|
||||
ast_value_factory()->empty_string(),
|
||||
|
@ -724,7 +724,10 @@ class ParserTraits {
|
||||
|
||||
Expression* ThisExpression(Scope* scope, AstNodeFactory* factory,
|
||||
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,
|
||||
int end_pos);
|
||||
Literal* ExpressionFromLiteral(Token::Value token, int pos, Scanner* scanner,
|
||||
|
@ -404,7 +404,8 @@ NOT_A_PATTERN(NativeFunctionLiteral)
|
||||
NOT_A_PATTERN(Property)
|
||||
NOT_A_PATTERN(RegExpLiteral)
|
||||
NOT_A_PATTERN(ReturnStatement)
|
||||
NOT_A_PATTERN(SuperReference)
|
||||
NOT_A_PATTERN(SuperPropertyReference)
|
||||
NOT_A_PATTERN(SuperCallReference)
|
||||
NOT_A_PATTERN(SwitchStatement)
|
||||
NOT_A_PATTERN(ThisFunction)
|
||||
NOT_A_PATTERN(Throw)
|
||||
|
@ -1715,9 +1715,15 @@ class PreParserTraits {
|
||||
return PreParserExpression::This();
|
||||
}
|
||||
|
||||
static PreParserExpression SuperReference(Scope* scope,
|
||||
PreParserFactory* factory,
|
||||
int pos) {
|
||||
static PreParserExpression SuperPropertyReference(Scope* scope,
|
||||
PreParserFactory* factory,
|
||||
int pos) {
|
||||
return PreParserExpression::Default();
|
||||
}
|
||||
|
||||
static PreParserExpression SuperCallReference(Scope* scope,
|
||||
PreParserFactory* factory,
|
||||
int pos) {
|
||||
return PreParserExpression::Default();
|
||||
}
|
||||
|
||||
@ -3515,7 +3521,7 @@ ParserBase<Traits>::ParseStrongSuperCallExpression(
|
||||
Consume(Token::SUPER);
|
||||
int pos = position();
|
||||
Scanner::Location super_loc = scanner()->location();
|
||||
ExpressionT expr = this->SuperReference(scope_, factory(), pos);
|
||||
ExpressionT expr = this->SuperCallReference(scope_, factory(), pos);
|
||||
|
||||
if (peek() != Token::LPAREN) {
|
||||
ReportMessage(MessageTemplate::kStrongConstructorSuper);
|
||||
@ -3580,7 +3586,7 @@ ParserBase<Traits>::ParseSuperExpression(bool is_new,
|
||||
i::IsConstructor(kind)) {
|
||||
if (peek() == Token::PERIOD || peek() == Token::LBRACK) {
|
||||
scope->RecordSuperPropertyUsage();
|
||||
return this->SuperReference(scope_, factory(), pos);
|
||||
return this->SuperPropertyReference(scope_, factory(), pos);
|
||||
}
|
||||
// new super() is never allowed.
|
||||
// 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
|
||||
// method here.
|
||||
function_state_->set_super_location(scanner()->location());
|
||||
return this->SuperReference(scope_, factory(), pos);
|
||||
return this->SuperCallReference(scope_, factory(), pos);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -364,7 +364,10 @@ void CallPrinter::VisitSpread(Spread* 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) {
|
||||
@ -835,8 +838,13 @@ void PrettyPrinter::VisitThisFunction(ThisFunction* node) {
|
||||
}
|
||||
|
||||
|
||||
void PrettyPrinter::VisitSuperReference(SuperReference* node) {
|
||||
Print("<super-reference>");
|
||||
void PrettyPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) {
|
||||
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) {
|
||||
IndentedScope indent(this, "SUPER-REFERENCE");
|
||||
void AstPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) {
|
||||
IndentedScope indent(this, "SUPER-PROPERTY-REFERENCE");
|
||||
}
|
||||
|
||||
|
||||
void AstPrinter::VisitSuperCallReference(SuperCallReference* node) {
|
||||
IndentedScope indent(this, "SUPER-CALL-REFERENCE");
|
||||
}
|
||||
|
||||
|
||||
#endif // DEBUG
|
||||
|
||||
} } // namespace v8::internal
|
||||
|
@ -72,8 +72,8 @@ namespace internal {
|
||||
F(StoreKeyedToSuper_Strict, 4, 1) \
|
||||
F(StoreKeyedToSuper_Sloppy, 4, 1) \
|
||||
F(HandleStepInForDerivedConstructors, 1, 1) \
|
||||
F(DefaultConstructorCallSuper, 0, 1) \
|
||||
F(CallSuperWithSpread, 0, 1)
|
||||
F(DefaultConstructorCallSuper, 2, 1) \
|
||||
F(CallSuperWithSpread, 1, 1)
|
||||
|
||||
|
||||
#define FOR_EACH_INTRINSIC_COLLECTIONS(F) \
|
||||
|
102
src/scopes.cc
102
src/scopes.cc
@ -160,6 +160,7 @@ void Scope::SetDefaults(ScopeType scope_type, Scope* outer_scope,
|
||||
function_ = nullptr;
|
||||
arguments_ = nullptr;
|
||||
home_object_ = nullptr;
|
||||
this_function_ = nullptr;
|
||||
illegal_redecl_ = nullptr;
|
||||
scope_inside_with_ = false;
|
||||
scope_contains_with_ = false;
|
||||
@ -308,45 +309,44 @@ void Scope::Initialize() {
|
||||
}
|
||||
|
||||
// Declare convenience variables and the receiver.
|
||||
if (is_declaration_scope()) {
|
||||
DCHECK(!subclass_constructor || is_function_scope());
|
||||
if (has_this_declaration()) {
|
||||
Variable* var = variables_.Declare(
|
||||
this, ast_value_factory_->this_string(),
|
||||
subclass_constructor ? CONST : VAR, Variable::THIS,
|
||||
subclass_constructor ? kNeedsInitialization : kCreatedInitialized);
|
||||
receiver_ = var;
|
||||
if (is_declaration_scope() && has_this_declaration()) {
|
||||
Variable* var = variables_.Declare(
|
||||
this, ast_value_factory_->this_string(),
|
||||
subclass_constructor ? CONST : VAR, Variable::THIS,
|
||||
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) {
|
||||
new_target_ =
|
||||
variables_.Declare(this, ast_value_factory_->new_target_string(),
|
||||
CONST, Variable::NEW_TARGET, kCreatedInitialized);
|
||||
new_target_->AllocateTo(Variable::PARAMETER, -2);
|
||||
new_target_->set_is_used();
|
||||
DCHECK(!is_arrow_scope());
|
||||
variables_.Declare(this, ast_value_factory_->new_target_string(), CONST,
|
||||
Variable::NORMAL, kCreatedInitialized);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_function_scope() && !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 (IsConciseMethod(function_kind_) || IsConstructor(function_kind_) ||
|
||||
IsAccessorFunction(function_kind_)) {
|
||||
DCHECK(!is_arrow_scope());
|
||||
// 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(), CONST,
|
||||
Variable::NORMAL, kCreatedInitialized);
|
||||
}
|
||||
|
||||
if (is_function_scope() &&
|
||||
(IsConciseMethod(function_kind_) || IsConstructor(function_kind_) ||
|
||||
IsAccessorFunction(function_kind_))) {
|
||||
DCHECK(!is_arrow_scope());
|
||||
// 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);
|
||||
if (IsSubclassConstructor(function_kind_)) {
|
||||
DCHECK(!is_arrow_scope());
|
||||
variables_.Declare(this, ast_value_factory_->this_function_string(),
|
||||
CONST, 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
|
||||
// via an eval() call. This is only possible if the variable has a
|
||||
// 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_ ||
|
||||
inner_scope_calls_eval_ || scope_contains_with_ || is_catch_scope() ||
|
||||
is_block_scope() || is_module_scope() || is_script_scope())) {
|
||||
@ -1403,18 +1403,6 @@ void Scope::AllocateParameterLocals(Isolate* isolate) {
|
||||
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.
|
||||
// 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
|
||||
@ -1503,13 +1491,31 @@ void Scope::AllocateNonParameterLocals(Isolate* isolate) {
|
||||
// allocated in the context, it must be the last slot in the context,
|
||||
// because of the current ScopeInfo implementation (see
|
||||
// ScopeInfo::ScopeInfo(FunctionScope* scope) constructor).
|
||||
if (function_ != NULL) {
|
||||
if (function_ != nullptr) {
|
||||
AllocateNonParameterLocal(isolate, function_->proxy()->var());
|
||||
}
|
||||
|
||||
if (rest_parameter_) {
|
||||
if (rest_parameter_ != nullptr) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -419,6 +419,13 @@ class Scope: public ZoneObject {
|
||||
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.
|
||||
ZoneList<Declaration*>* declarations() { return &decls_; }
|
||||
|
||||
@ -579,6 +586,8 @@ class Scope: public ZoneObject {
|
||||
Variable* arguments_;
|
||||
// Convenience variable; method scopes only.
|
||||
Variable* home_object_;
|
||||
// Convenience variable; Subclass constructor only
|
||||
Variable* this_function_;
|
||||
// Module descriptor; module scopes only.
|
||||
ModuleDescriptor* module_descriptor_;
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -20,7 +20,7 @@ class ClassVariable;
|
||||
|
||||
class Variable: public ZoneObject {
|
||||
public:
|
||||
enum Kind { NORMAL, FUNCTION, CLASS, THIS, NEW_TARGET, ARGUMENTS };
|
||||
enum Kind { NORMAL, FUNCTION, CLASS, THIS, ARGUMENTS };
|
||||
|
||||
enum Location {
|
||||
// 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_class() const { return kind_ == CLASS; }
|
||||
bool is_this() const { return kind_ == THIS; }
|
||||
bool is_new_target() const { return kind_ == NEW_TARGET; }
|
||||
bool is_arguments() const { return kind_ == ARGUMENTS; }
|
||||
|
||||
ClassVariable* AsClassVariable() {
|
||||
|
@ -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();
|
||||
if (home_object_var != nullptr) {
|
||||
__ Push(rdi);
|
||||
@ -1959,9 +1977,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
}
|
||||
break;
|
||||
case NAMED_SUPER_PROPERTY:
|
||||
VisitForStackValue(property->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(
|
||||
property->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForAccumulatorValue(
|
||||
property->obj()->AsSuperReference()->home_object_var());
|
||||
property->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
__ Push(result_register());
|
||||
if (expr->is_compound()) {
|
||||
__ Push(MemOperand(rsp, kPointerSize));
|
||||
@ -1969,9 +1988,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
}
|
||||
break;
|
||||
case KEYED_SUPER_PROPERTY:
|
||||
VisitForStackValue(property->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(
|
||||
property->obj()->AsSuperReference()->home_object_var());
|
||||
property->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForStackValue(
|
||||
property->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
VisitForAccumulatorValue(property->key());
|
||||
__ Push(result_register());
|
||||
if (expr->is_compound()) {
|
||||
@ -2563,9 +2583,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr,
|
||||
}
|
||||
case NAMED_SUPER_PROPERTY: {
|
||||
__ Push(rax);
|
||||
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForAccumulatorValue(
|
||||
prop->obj()->AsSuperReference()->home_object_var());
|
||||
prop->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
// stack: value, this; rax: home_object
|
||||
Register scratch = rcx;
|
||||
Register scratch2 = rdx;
|
||||
@ -2580,8 +2600,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr,
|
||||
}
|
||||
case KEYED_SUPER_PROPERTY: {
|
||||
__ Push(rax);
|
||||
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
|
||||
VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForStackValue(
|
||||
prop->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
VisitForAccumulatorValue(prop->key());
|
||||
Register scratch = rcx;
|
||||
Register scratch2 = rdx;
|
||||
@ -2800,8 +2821,9 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
|
||||
__ movp(LoadDescriptor::ReceiverRegister(), rax);
|
||||
EmitNamedPropertyLoad(expr);
|
||||
} else {
|
||||
VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
|
||||
VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForStackValue(
|
||||
expr->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
EmitNamedSuperPropertyLoad(expr);
|
||||
}
|
||||
} else {
|
||||
@ -2812,8 +2834,9 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
|
||||
__ Pop(LoadDescriptor::ReceiverRegister());
|
||||
EmitKeyedPropertyLoad(expr);
|
||||
} else {
|
||||
VisitForStackValue(expr->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(expr->obj()->AsSuperReference()->home_object_var());
|
||||
VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForStackValue(
|
||||
expr->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
VisitForStackValue(expr->key());
|
||||
EmitKeyedSuperPropertyLoad(expr);
|
||||
}
|
||||
@ -2871,7 +2894,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
|
||||
Literal* key = prop->key()->AsLiteral();
|
||||
DCHECK(!key->value()->IsSmi());
|
||||
// Load the function from the receiver.
|
||||
SuperReference* super_ref = prop->obj()->AsSuperReference();
|
||||
SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
|
||||
VisitForStackValue(super_ref->home_object_var());
|
||||
VisitForAccumulatorValue(super_ref->this_var());
|
||||
__ Push(rax);
|
||||
@ -2928,7 +2951,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
|
||||
|
||||
SetSourcePosition(prop->position());
|
||||
// Load the function from the receiver.
|
||||
SuperReference* super_ref = prop->obj()->AsSuperReference();
|
||||
SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
|
||||
VisitForStackValue(super_ref->home_object_var());
|
||||
VisitForAccumulatorValue(super_ref->this_var());
|
||||
__ 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(
|
||||
SuperReference* super_ref, FeedbackVectorICSlot slot) {
|
||||
SuperCallReference* super_ref, FeedbackVectorICSlot slot) {
|
||||
Variable* this_var = super_ref->this_var()->var();
|
||||
GetVar(rcx, this_var);
|
||||
__ 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
|
||||
// receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
|
||||
// ignored.
|
||||
DCHECK(!expr->expression()->IsSuperReference());
|
||||
DCHECK(!expr->expression()->IsSuperPropertyReference());
|
||||
VisitForStackValue(expr->expression());
|
||||
|
||||
// Push the arguments ("left-to-right") on the stack.
|
||||
@ -3202,11 +3219,14 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
|
||||
Variable* new_target_var = scope()->DeclarationScope()->new_target_var();
|
||||
GetVar(result_register(), new_target_var);
|
||||
__ Push(result_register());
|
||||
SuperCallReference* super_call_ref =
|
||||
expr->expression()->AsSuperCallReference();
|
||||
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 the arguments ("left-to-right") on the stack.
|
||||
@ -3244,8 +3264,7 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
|
||||
|
||||
RecordJSReturnSite(expr);
|
||||
|
||||
EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(),
|
||||
expr->CallFeedbackICSlot());
|
||||
EmitInitializeThisAfterSuper(super_call_ref, expr->CallFeedbackICSlot());
|
||||
context()->Plug(rax);
|
||||
}
|
||||
|
||||
@ -4112,11 +4131,15 @@ void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitDefaultConstructorCallSuper(CallRuntime* expr) {
|
||||
Variable* new_target_var = scope()->DeclarationScope()->new_target_var();
|
||||
GetVar(result_register(), new_target_var);
|
||||
__ Push(result_register());
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK(args->length() == 2);
|
||||
|
||||
EmitLoadSuperConstructor();
|
||||
// new.target
|
||||
VisitForStackValue(args->at(0));
|
||||
|
||||
// .this_function
|
||||
VisitForStackValue(args->at(1));
|
||||
__ CallRuntime(Runtime::kGetPrototype, 1);
|
||||
__ Push(result_register());
|
||||
|
||||
// Check if the calling frame is an arguments adaptor frame.
|
||||
@ -4568,11 +4591,14 @@ void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
|
||||
|
||||
void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
|
||||
// Assert: expr === CallRuntime("ReflectConstruct")
|
||||
DCHECK_EQ(1, expr->arguments()->length());
|
||||
CallRuntime* call = expr->arguments()->at(0)->AsCallRuntime();
|
||||
|
||||
ZoneList<Expression*>* args = call->arguments();
|
||||
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
|
||||
EmitLoadJSRuntimeFunction(call);
|
||||
@ -4581,8 +4607,8 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
|
||||
__ Push(Operand(rsp, 0));
|
||||
__ movp(Operand(rsp, kPointerSize), rax);
|
||||
|
||||
// Push super
|
||||
EmitLoadSuperConstructor();
|
||||
// Push super constructor
|
||||
EmitLoadSuperConstructor(super_call_ref);
|
||||
__ Push(result_register());
|
||||
|
||||
// Push arguments array
|
||||
@ -4599,7 +4625,7 @@ void FullCodeGenerator::EmitCallSuperWithSpread(CallRuntime* expr) {
|
||||
context()->DropAndPlug(1, rax);
|
||||
|
||||
// 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: {
|
||||
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForAccumulatorValue(
|
||||
prop->obj()->AsSuperReference()->home_object_var());
|
||||
prop->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
__ Push(result_register());
|
||||
__ Push(MemOperand(rsp, kPointerSize));
|
||||
__ Push(result_register());
|
||||
@ -4835,8 +4861,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
}
|
||||
|
||||
case KEYED_SUPER_PROPERTY: {
|
||||
VisitForStackValue(prop->obj()->AsSuperReference()->this_var());
|
||||
VisitForStackValue(prop->obj()->AsSuperReference()->home_object_var());
|
||||
VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForStackValue(
|
||||
prop->obj()->AsSuperPropertyReference()->home_object_var());
|
||||
VisitForAccumulatorValue(prop->key());
|
||||
__ Push(result_register());
|
||||
__ Push(MemOperand(rsp, 2 * kPointerSize));
|
||||
|
@ -3,7 +3,7 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --harmony-classes --harmony-arrow-functions --allow-natives-syntax
|
||||
|
||||
// Flags: --harmony-spreadcalls
|
||||
|
||||
(function TestSuperNamedLoads() {
|
||||
function Base() { }
|
||||
@ -2107,3 +2107,99 @@ TestKeyedSetterCreatingOwnPropertiesNonConfigurable(42, 43, 44);
|
||||
let d = new Derived();
|
||||
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);
|
||||
})();
|
||||
|
Loading…
Reference in New Issue
Block a user