__ Push(r1);
}
+ // 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);
+ }
+
ArgumentsAccessStub::HasNewTarget has_new_target =
IsSubclassConstructor(info->function()->kind())
? ArgumentsAccessStub::HAS_NEW_TARGET
}
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;
}
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()) {
}
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;
}
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;
__ 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 {
__ 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);
}
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);
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);
}
-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);
// 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.
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.
RecordJSReturnSite(expr);
- EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(),
- expr->CallFeedbackICSlot());
+ EmitInitializeThisAfterSuper(super_call_ref, expr->CallFeedbackICSlot());
context()->Plug(r0);
}
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);
+
+ // new.target
+ VisitForStackValue(args->at(0));
- EmitLoadSuperConstructor();
+ // .this_function
+ VisitForStackValue(args->at(1));
+ __ CallRuntime(Runtime::kGetPrototype, 1);
__ Push(result_register());
// Check if the calling frame is an arguments adaptor frame.
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);
__ push(ip);
__ str(r0, MemOperand(sp, kPointerSize));
- // Push super
- EmitLoadSuperConstructor();
+ // Push super constructor
+ EmitLoadSuperConstructor(super_call_ref);
__ Push(result_register());
// Push arguments array
context()->DropAndPlug(1, r0);
// TODO(mvstanton): with FLAG_vector_stores this needs a slot id.
- EmitInitializeThisAfterSuper(super_reference);
+ EmitInitializeThisAfterSuper(super_call_ref);
}
}
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));
}
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;
__ Push(x1);
}
+ // 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);
+ }
+
ArgumentsAccessStub::HasNewTarget has_new_target =
IsSubclassConstructor(info->function()->kind())
? ArgumentsAccessStub::HAS_NEW_TARGET
}
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;
}
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()) {
}
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;
}
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;
__ 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 {
__ 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);
}
// 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);
// 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);
}
-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;
// 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.
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.
RecordJSReturnSite(expr);
- EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(),
- expr->CallFeedbackICSlot());
+ EmitInitializeThisAfterSuper(super_call_ref, expr->CallFeedbackICSlot());
context()->Plug(x0);
}
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);
+
+ // new.target
+ VisitForStackValue(args->at(0));
- EmitLoadSuperConstructor();
+ // .this_function
+ VisitForStackValue(args->at(1));
+ __ CallRuntime(Runtime::kGetPrototype, 1);
__ Push(result_register());
// Check if the calling frame is an arguments adaptor frame.
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);
__ Pop(x10);
__ Push(x0, x10);
- // Push super
- EmitLoadSuperConstructor();
+ // Push super constructor
+ EmitLoadSuperConstructor(super_call_ref);
__ Push(result_register());
// Push arguments array
context()->DropAndPlug(1, x0);
// TODO(mvstanton): with FLAG_vector_stores this needs a slot id.
- EmitInitializeThisAfterSuper(super_reference);
+ EmitInitializeThisAfterSuper(super_call_ref);
}
}
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);
}
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;
}
-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);
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") \
}
}
- if (expression()->AsSuperReference() != NULL) return SUPER_CALL;
+ if (expression()->IsSuperCallReference()) return SUPER_CALL;
Property* property = expression()->AsProperty();
return property != NULL ? PROPERTY_CALL : OTHER_CALL;
V(CompareOperation) \
V(Spread) \
V(ThisFunction) \
- V(SuperReference) \
+ V(SuperPropertyReference) \
+ V(SuperCallReference) \
V(CaseClause)
#define AST_NODE_LIST(V) \
}
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 {
};
-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) {
};
+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
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:
}
-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());
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) {}
// ---------------------------------------------------------------------------
}
-void BreakableStatementChecker::VisitSuperReference(SuperReference* expr) {}
+void BreakableStatementChecker::VisitSuperPropertyReference(
+ SuperPropertyReference* expr) {}
+
+
+void BreakableStatementChecker::VisitSuperCallReference(
+ SuperCallReference* expr) {}
#define __ ACCESS_MASM(masm())
}
-void FullCodeGenerator::VisitSuperReference(SuperReference* super) {
+void FullCodeGenerator::VisitSuperPropertyReference(
+ SuperPropertyReference* super) {
+ __ CallRuntime(Runtime::kThrowUnsupportedSuperError, 0);
+}
+
+
+void FullCodeGenerator::VisitSuperCallReference(SuperCallReference* super) {
__ CallRuntime(Runtime::kThrowUnsupportedSuperError, 0);
}
}
+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);
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,
}
-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());
__ push(edi);
}
+ // 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);
+ }
+
ArgumentsAccessStub::HasNewTarget has_new_target =
IsSubclassConstructor(info->function()->kind())
? ArgumentsAccessStub::HAS_NEW_TARGET
// 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));
}
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()) {
}
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;
}
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;
__ 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 {
__ 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);
}
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);
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);
}
-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;
// 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.
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.
RecordJSReturnSite(expr);
- EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(),
- expr->CallFeedbackICSlot());
+ EmitInitializeThisAfterSuper(super_call_ref, expr->CallFeedbackICSlot());
context()->Plug(eax);
}
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);
+
+ // new.target
+ VisitForStackValue(args->at(0));
- EmitLoadSuperConstructor();
+ // .this_function
+ VisitForStackValue(args->at(1));
+ __ CallRuntime(Runtime::kGetPrototype, 1);
__ push(result_register());
// Check if the calling frame is an arguments adaptor frame.
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);
__ 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
context()->DropAndPlug(1, eax);
// TODO(mvstanton): with FLAG_vector_stores this needs a slot id.
- EmitInitializeThisAfterSuper(super_reference);
+ EmitInitializeThisAfterSuper(super_call_ref);
}
}
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());
}
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));
__ Push(a1);
}
+ // 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);
+ }
+
ArgumentsAccessStub::HasNewTarget has_new_target =
IsSubclassConstructor(info->function()->kind())
? ArgumentsAccessStub::HAS_NEW_TARGET
}
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;
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());
}
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;
}
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;
__ 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 {
__ 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);
}
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());
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());
}
-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);
// 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.
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);
+
+ VariableProxy* new_target_proxy = super_call_ref->new_target_var();
+ VisitForStackValue(new_target_proxy);
- EmitLoadSuperConstructor();
+ EmitLoadSuperConstructor(super_call_ref);
__ push(result_register());
// Push the arguments ("left-to-right") on the stack.
RecordJSReturnSite(expr);
- EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(),
- expr->CallFeedbackICSlot());
+ EmitInitializeThisAfterSuper(super_call_ref, expr->CallFeedbackICSlot());
context()->Plug(v0);
}
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.
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);
__ push(at);
__ sw(v0, MemOperand(sp, kPointerSize));
- // Push super
- EmitLoadSuperConstructor();
+ // Push super constructor
+ EmitLoadSuperConstructor(super_call_ref);
__ Push(result_register());
// Push arguments array
context()->DropAndPlug(1, v0);
// TODO(mvstanton): with FLAG_vector_stores this needs a slot id.
- EmitInitializeThisAfterSuper(super_reference);
+ EmitInitializeThisAfterSuper(super_call_ref);
}
}
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));
}
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());
__ Push(a1);
}
+ // 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);
+ }
+
ArgumentsAccessStub::HasNewTarget has_new_target =
IsSubclassConstructor(info->function()->kind())
? ArgumentsAccessStub::HAS_NEW_TARGET
}
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;
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());
}
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;
}
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;
__ 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 {
__ 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);
}
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());
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());
}
-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);
// 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.
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);
+
+ VariableProxy* new_target_proxy = super_call_ref->new_target_var();
+ VisitForStackValue(new_target_proxy);
- EmitLoadSuperConstructor();
+ EmitLoadSuperConstructor(super_call_ref);
__ push(result_register());
// Push the arguments ("left-to-right") on the stack.
RecordJSReturnSite(expr);
- EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(),
- expr->CallFeedbackICSlot());
+ EmitInitializeThisAfterSuper(super_call_ref, expr->CallFeedbackICSlot());
context()->Plug(v0);
}
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.
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);
__ push(at);
__ sd(v0, MemOperand(sp, kPointerSize));
- // Push super
- EmitLoadSuperConstructor();
+ // Push super constructor
+ EmitLoadSuperConstructor(super_call_ref);
__ Push(result_register());
// Push arguments array
context()->DropAndPlug(1, v0);
// TODO(mvstanton): with FLAG_vector_stores this needs a slot id.
- EmitInitializeThisAfterSuper(super_reference);
+ EmitInitializeThisAfterSuper(super_call_ref);
}
}
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));
}
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());
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),
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);
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(),
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,
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)
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();
}
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);
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
// 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);
}
}
void CallPrinter::VisitThisFunction(ThisFunction* node) {}
-void CallPrinter::VisitSuperReference(SuperReference* node) {}
+void CallPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) {}
+
+
+void CallPrinter::VisitSuperCallReference(SuperCallReference* node) {}
void CallPrinter::FindStatements(ZoneList<Statement*>* statements) {
}
-void 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>");
}
}
-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 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) \
function_ = nullptr;
arguments_ = nullptr;
home_object_ = nullptr;
+ this_function_ = nullptr;
illegal_redecl_ = nullptr;
scope_inside_with_ = false;
scope_contains_with_ = false;
}
// 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);
+ }
}
}
// 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())) {
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
// 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;
+ }
}
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_; }
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_;
}
-void AstTyper::VisitSuperReference(SuperReference* expr) {}
+void AstTyper::VisitSuperPropertyReference(SuperPropertyReference* expr) {}
+
+
+void AstTyper::VisitSuperCallReference(SuperCallReference* expr) {}
void AstTyper::VisitDeclarations(ZoneList<Declaration*>* decls) {
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
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() {
__ Push(rdi);
}
+ // 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);
+ }
+
ArgumentsAccessStub::HasNewTarget has_new_target =
IsSubclassConstructor(info->function()->kind())
? ArgumentsAccessStub::HAS_NEW_TARGET
}
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));
}
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()) {
}
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;
}
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;
__ 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 {
__ 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);
}
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);
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);
}
-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);
// 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.
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.
RecordJSReturnSite(expr);
- EmitInitializeThisAfterSuper(expr->expression()->AsSuperReference(),
- expr->CallFeedbackICSlot());
+ EmitInitializeThisAfterSuper(super_call_ref, expr->CallFeedbackICSlot());
context()->Plug(rax);
}
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);
+
+ // new.target
+ VisitForStackValue(args->at(0));
- EmitLoadSuperConstructor();
+ // .this_function
+ VisitForStackValue(args->at(1));
+ __ CallRuntime(Runtime::kGetPrototype, 1);
__ Push(result_register());
// Check if the calling frame is an arguments adaptor frame.
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);
__ 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
context()->DropAndPlug(1, rax);
// TODO(mvstanton): with FLAG_vector_stores this needs a slot id.
- EmitInitializeThisAfterSuper(super_reference);
+ EmitInitializeThisAfterSuper(super_call_ref);
}
}
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());
}
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));
// found in the LICENSE file.
// Flags: --harmony-classes --harmony-arrow-functions --allow-natives-syntax
-
+// Flags: --harmony-spreadcalls
(function TestSuperNamedLoads() {
function Base() { }
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);
+})();