[es6] Super call in arrows and eval

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

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

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

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

View File

@ -242,6 +242,24 @@ void FullCodeGenerator::Generate() {
}
}
// Possibly set up a local binding to the this function which is used in
// derived constructors with super calls.
Variable* this_function_var = scope()->this_function_var();
if (this_function_var != nullptr) {
Comment cmnt(masm_, "[ This function");
SetVar(this_function_var, r1, r0, r2);
}
Variable* new_target_var = scope()->new_target_var();
if (new_target_var != nullptr) {
Comment cmnt(masm_, "[ new.target");
// new.target is parameter -2.
int offset = 2 * kPointerSize +
(info_->scope()->num_parameters() + 1) * kPointerSize;
__ ldr(r0, MemOperand(fp, offset));
SetVar(new_target_var, r0, r2, r3);
}
Variable* home_object_var = scope()->home_object_var();
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;

View File

@ -243,6 +243,24 @@ void FullCodeGenerator::Generate() {
}
}
// Possibly set up a local binding to the this function which is used in
// derived constructors with super calls.
Variable* this_function_var = scope()->this_function_var();
if (this_function_var != nullptr) {
Comment cmnt(masm_, "[ This function");
SetVar(this_function_var, x1, x0, x2);
}
Variable* new_target_var = scope()->new_target_var();
if (new_target_var != nullptr) {
Comment cmnt(masm_, "[ new.target");
// new.target is parameter -2.
int offset =
2 * kXRegSize + (info_->scope()->num_parameters() + 1) * kPointerSize;
__ Ldr(x0, MemOperand(fp, offset));
SetVar(new_target_var, x0, x2, x3);
}
Variable* home_object_var = scope()->home_object_var();
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;

View File

@ -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);

View File

@ -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") \

View File

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

View File

@ -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:

View File

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

View File

@ -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) {}
// ---------------------------------------------------------------------------

View File

@ -276,7 +276,12 @@ void BreakableStatementChecker::VisitThisFunction(ThisFunction* expr) {
}
void BreakableStatementChecker::VisitSuperReference(SuperReference* expr) {}
void BreakableStatementChecker::VisitSuperPropertyReference(
SuperPropertyReference* expr) {}
void BreakableStatementChecker::VisitSuperCallReference(
SuperCallReference* expr) {}
#define __ ACCESS_MASM(masm())
@ -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);

View File

@ -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,

View File

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

View File

@ -238,6 +238,24 @@ void FullCodeGenerator::Generate() {
}
}
// Possibly set up a local binding to the this function which is used in
// derived constructors with super calls.
Variable* this_function_var = scope()->this_function_var();
if (this_function_var != nullptr) {
Comment cmnt(masm_, "[ This function");
SetVar(this_function_var, edi, ebx, edx);
}
Variable* new_target_var = scope()->new_target_var();
if (new_target_var != nullptr) {
Comment cmnt(masm_, "[ new.target");
// new.target is parameter -2.
int offset = 2 * kPointerSize + kFPOnStackSize + kPCOnStackSize +
(info_->scope()->num_parameters() - 1) * kPointerSize;
__ mov(eax, Operand(ebp, offset));
SetVar(new_target_var, eax, ebx, edx);
}
Variable* home_object_var = scope()->home_object_var();
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));

View File

@ -251,6 +251,24 @@ void FullCodeGenerator::Generate() {
}
}
// Possibly set up a local binding to the this function which is used in
// derived constructors with super calls.
Variable* this_function_var = scope()->this_function_var();
if (this_function_var != nullptr) {
Comment cmnt(masm_, "[ This function");
SetVar(this_function_var, a1, a2, a3);
}
Variable* new_target_var = scope()->new_target_var();
if (new_target_var != nullptr) {
Comment cmnt(masm_, "[ new.target");
// new.target is parameter -2.
int offset = 2 * kPointerSize +
(info_->scope()->num_parameters() + 1) * kPointerSize;
__ lw(v0, MemOperand(fp, offset));
SetVar(new_target_var, v0, a2, a3);
}
Variable* home_object_var = scope()->home_object_var();
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());

View File

@ -248,6 +248,24 @@ void FullCodeGenerator::Generate() {
}
}
// Possibly set up a local binding to the this function which is used in
// derived constructors with super calls.
Variable* this_function_var = scope()->this_function_var();
if (this_function_var != nullptr) {
Comment cmnt(masm_, "[ This function");
SetVar(this_function_var, a1, a2, a3);
}
Variable* new_target_var = scope()->new_target_var();
if (new_target_var != nullptr) {
Comment cmnt(masm_, "[ new.target");
// new.target is parameter -2.
int offset = 2 * kPointerSize +
(info_->scope()->num_parameters() + 1) * kPointerSize;
__ lw(v0, MemOperand(fp, offset));
SetVar(new_target_var, v0, a2, a3);
}
Variable* home_object_var = scope()->home_object_var();
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());

View File

@ -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(),

View File

@ -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,

View File

@ -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)

View File

@ -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);
}
}

View File

@ -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

View File

@ -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) \

View File

@ -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;
}
}

View File

@ -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_;

View File

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

View File

@ -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() {

View File

@ -234,6 +234,24 @@ void FullCodeGenerator::Generate() {
}
}
// Possibly set up a local binding to the this function which is used in
// derived constructors with super calls.
Variable* this_function_var = scope()->this_function_var();
if (this_function_var != nullptr) {
Comment cmnt(masm_, "[ This function");
SetVar(this_function_var, rdi, rbx, rdx);
}
Variable* new_target_var = scope()->new_target_var();
if (new_target_var != nullptr) {
Comment cmnt(masm_, "[ new.target");
// new.target is parameter -2.
int offset = 2 * kPointerSize + kFPOnStackSize + kPCOnStackSize +
(info_->scope()->num_parameters() - 1) * kPointerSize;
__ movp(rax, Operand(rbp, offset));
SetVar(new_target_var, rax, rbx, rdx);
}
Variable* home_object_var = scope()->home_object_var();
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));

View File

@ -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);
})();