Commit 4b8051a0 authored by arv's avatar arv Committed by Commit bot

[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.

This is a revert of the revert 88b1c917

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

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

Cr-Commit-Position: refs/heads/master@{#28769}
parent 6a6388f0
This diff is collapsed.
This diff is collapsed.
...@@ -168,15 +168,26 @@ void AstNumberingVisitor::VisitThisFunction(ThisFunction* node) { ...@@ -168,15 +168,26 @@ void AstNumberingVisitor::VisitThisFunction(ThisFunction* node) {
} }
void AstNumberingVisitor::VisitSuperReference(SuperReference* node) { void AstNumberingVisitor::VisitSuperPropertyReference(
SuperPropertyReference* node) {
IncrementNodeCount(); IncrementNodeCount();
DisableOptimization(kSuperReference); DisableOptimization(kSuperReference);
node->set_base_id(ReserveIdRange(SuperReference::num_ids())); node->set_base_id(ReserveIdRange(SuperPropertyReference::num_ids()));
Visit(node->this_var()); Visit(node->this_var());
Visit(node->home_object_var()); Visit(node->home_object_var());
} }
void AstNumberingVisitor::VisitSuperCallReference(SuperCallReference* node) {
IncrementNodeCount();
DisableOptimization(kSuperReference);
node->set_base_id(ReserveIdRange(SuperCallReference::num_ids()));
Visit(node->this_var());
Visit(node->new_target_var());
Visit(node->this_function_var());
}
void AstNumberingVisitor::VisitImportDeclaration(ImportDeclaration* node) { void AstNumberingVisitor::VisitImportDeclaration(ImportDeclaration* node) {
IncrementNodeCount(); IncrementNodeCount();
DisableOptimization(kImportDeclaration); DisableOptimization(kImportDeclaration);
......
...@@ -267,6 +267,7 @@ class AstValue : public ZoneObject { ...@@ -267,6 +267,7 @@ class AstValue : public ZoneObject {
F(spread_arguments, "$spreadArguments") \ F(spread_arguments, "$spreadArguments") \
F(spread_iterable, "$spreadIterable") \ F(spread_iterable, "$spreadIterable") \
F(this, "this") \ F(this, "this") \
F(this_function, ".this_function") \
F(throw_iterator_result_not_an_object, "ThrowIteratorResultNotAnObject") \ F(throw_iterator_result_not_an_object, "ThrowIteratorResultNotAnObject") \
F(to_string, "$toString") \ F(to_string, "$toString") \
F(undefined, "undefined") \ F(undefined, "undefined") \
......
...@@ -734,7 +734,7 @@ Call::CallType Call::GetCallType(Isolate* isolate) const { ...@@ -734,7 +734,7 @@ Call::CallType Call::GetCallType(Isolate* isolate) const {
} }
} }
if (expression()->AsSuperReference() != NULL) return SUPER_CALL; if (expression()->IsSuperCallReference()) return SUPER_CALL;
Property* property = expression()->AsProperty(); Property* property = expression()->AsProperty();
return property != NULL ? PROPERTY_CALL : OTHER_CALL; return property != NULL ? PROPERTY_CALL : OTHER_CALL;
......
...@@ -87,7 +87,8 @@ namespace internal { ...@@ -87,7 +87,8 @@ namespace internal {
V(CompareOperation) \ V(CompareOperation) \
V(Spread) \ V(Spread) \
V(ThisFunction) \ V(ThisFunction) \
V(SuperReference) \ V(SuperPropertyReference) \
V(SuperCallReference) \
V(CaseClause) V(CaseClause)
#define AST_NODE_LIST(V) \ #define AST_NODE_LIST(V) \
...@@ -1760,9 +1761,7 @@ class Property final : public Expression { ...@@ -1760,9 +1761,7 @@ class Property final : public Expression {
} }
bool is_for_call() const { return IsForCallField::decode(bit_field_); } bool is_for_call() const { return IsForCallField::decode(bit_field_); }
bool IsSuperAccess() { bool IsSuperAccess() { return obj()->IsSuperPropertyReference(); }
return obj()->IsSuperReference();
}
virtual FeedbackVectorRequirements ComputeFeedbackRequirements( virtual FeedbackVectorRequirements ComputeFeedbackRequirements(
Isolate* isolate, const ICSlotCache* cache) override { Isolate* isolate, const ICSlotCache* cache) override {
...@@ -2791,16 +2790,16 @@ class ThisFunction final : public Expression { ...@@ -2791,16 +2790,16 @@ class ThisFunction final : public Expression {
}; };
class SuperReference final : public Expression { class SuperPropertyReference final : public Expression {
public: public:
DECLARE_NODE_TYPE(SuperReference) DECLARE_NODE_TYPE(SuperPropertyReference)
VariableProxy* this_var() const { return this_var_; } VariableProxy* this_var() const { return this_var_; }
VariableProxy* home_object_var() const { return home_object_var_; } VariableProxy* home_object_var() const { return home_object_var_; }
protected: protected:
SuperReference(Zone* zone, VariableProxy* this_var, SuperPropertyReference(Zone* zone, VariableProxy* this_var,
VariableProxy* home_object_var, int pos) VariableProxy* home_object_var, int pos)
: Expression(zone, pos), : Expression(zone, pos),
this_var_(this_var), this_var_(this_var),
home_object_var_(home_object_var) { home_object_var_(home_object_var) {
...@@ -2814,6 +2813,34 @@ class SuperReference final : public Expression { ...@@ -2814,6 +2813,34 @@ class SuperReference final : public Expression {
}; };
class SuperCallReference final : public Expression {
public:
DECLARE_NODE_TYPE(SuperCallReference)
VariableProxy* this_var() const { return this_var_; }
VariableProxy* new_target_var() const { return new_target_var_; }
VariableProxy* this_function_var() const { return this_function_var_; }
protected:
SuperCallReference(Zone* zone, VariableProxy* this_var,
VariableProxy* new_target_var,
VariableProxy* this_function_var, int pos)
: Expression(zone, pos),
this_var_(this_var),
new_target_var_(new_target_var),
this_function_var_(this_function_var) {
DCHECK(this_var->is_this());
DCHECK(new_target_var->raw_name()->IsOneByteEqualTo("new.target"));
DCHECK(this_function_var->raw_name()->IsOneByteEqualTo(".this_function"));
}
private:
VariableProxy* this_var_;
VariableProxy* new_target_var_;
VariableProxy* this_function_var_;
};
#undef DECLARE_NODE_TYPE #undef DECLARE_NODE_TYPE
...@@ -3581,9 +3608,18 @@ class AstNodeFactory final BASE_EMBEDDED { ...@@ -3581,9 +3608,18 @@ class AstNodeFactory final BASE_EMBEDDED {
return new (zone_) ThisFunction(zone_, pos); return new (zone_) ThisFunction(zone_, pos);
} }
SuperReference* NewSuperReference(VariableProxy* this_var, SuperPropertyReference* NewSuperPropertyReference(
VariableProxy* home_object_var, int pos) { VariableProxy* this_var, VariableProxy* home_object_var, int pos) {
return new (zone_) SuperReference(zone_, this_var, home_object_var, pos); return new (zone_)
SuperPropertyReference(zone_, this_var, home_object_var, pos);
}
SuperCallReference* NewSuperCallReference(VariableProxy* this_var,
VariableProxy* new_target_var,
VariableProxy* this_function_var,
int pos) {
return new (zone_) SuperCallReference(zone_, this_var, new_target_var,
this_function_var, pos);
} }
private: private:
......
...@@ -2589,7 +2589,15 @@ void AstGraphBuilder::VisitThisFunction(ThisFunction* expr) { ...@@ -2589,7 +2589,15 @@ void AstGraphBuilder::VisitThisFunction(ThisFunction* expr) {
} }
void AstGraphBuilder::VisitSuperReference(SuperReference* expr) { void AstGraphBuilder::VisitSuperPropertyReference(
SuperPropertyReference* expr) {
// TODO(turbofan): Implement super here.
SetStackOverflow();
ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
}
void AstGraphBuilder::VisitSuperCallReference(SuperCallReference* expr) {
// TODO(turbofan): Implement super here. // TODO(turbofan): Implement super here.
SetStackOverflow(); SetStackOverflow();
ast_context()->ProduceValue(jsgraph()->UndefinedConstant()); ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
......
...@@ -67,7 +67,8 @@ void ALAA::VisitVariableProxy(VariableProxy* leaf) {} ...@@ -67,7 +67,8 @@ void ALAA::VisitVariableProxy(VariableProxy* leaf) {}
void ALAA::VisitLiteral(Literal* leaf) {} void ALAA::VisitLiteral(Literal* leaf) {}
void ALAA::VisitRegExpLiteral(RegExpLiteral* leaf) {} void ALAA::VisitRegExpLiteral(RegExpLiteral* leaf) {}
void ALAA::VisitThisFunction(ThisFunction* leaf) {} void ALAA::VisitThisFunction(ThisFunction* leaf) {}
void ALAA::VisitSuperReference(SuperReference* leaf) {} void ALAA::VisitSuperPropertyReference(SuperPropertyReference* leaf) {}
void ALAA::VisitSuperCallReference(SuperCallReference* leaf) {}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
......
...@@ -276,7 +276,12 @@ void BreakableStatementChecker::VisitThisFunction(ThisFunction* expr) { ...@@ -276,7 +276,12 @@ void BreakableStatementChecker::VisitThisFunction(ThisFunction* expr) {
} }
void BreakableStatementChecker::VisitSuperReference(SuperReference* expr) {} void BreakableStatementChecker::VisitSuperPropertyReference(
SuperPropertyReference* expr) {}
void BreakableStatementChecker::VisitSuperCallReference(
SuperCallReference* expr) {}
#define __ ACCESS_MASM(masm()) #define __ ACCESS_MASM(masm())
...@@ -669,7 +674,13 @@ void FullCodeGenerator::SetStatementPosition(Statement* stmt) { ...@@ -669,7 +674,13 @@ void FullCodeGenerator::SetStatementPosition(Statement* stmt) {
} }
void FullCodeGenerator::VisitSuperReference(SuperReference* super) { void FullCodeGenerator::VisitSuperPropertyReference(
SuperPropertyReference* super) {
__ CallRuntime(Runtime::kThrowUnsupportedSuperError, 0);
}
void FullCodeGenerator::VisitSuperCallReference(SuperCallReference* super) {
__ CallRuntime(Runtime::kThrowUnsupportedSuperError, 0); __ CallRuntime(Runtime::kThrowUnsupportedSuperError, 0);
} }
...@@ -979,6 +990,12 @@ void FullCodeGenerator::EmitPropertyKey(ObjectLiteralProperty* property, ...@@ -979,6 +990,12 @@ void FullCodeGenerator::EmitPropertyKey(ObjectLiteralProperty* property,
} }
void FullCodeGenerator::EmitLoadSuperConstructor(SuperCallReference* ref) {
VisitForStackValue(ref->this_function_var());
__ CallRuntime(Runtime::kGetPrototype, 1);
}
void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
Comment cmnt(masm_, "[ ReturnStatement"); Comment cmnt(masm_, "[ ReturnStatement");
SetStatementPosition(stmt); SetStatementPosition(stmt);
......
...@@ -672,9 +672,9 @@ class FullCodeGenerator: public AstVisitor { ...@@ -672,9 +672,9 @@ class FullCodeGenerator: public AstVisitor {
Expression* initializer, int offset, Expression* initializer, int offset,
FeedbackVectorICSlot slot = FeedbackVectorICSlot::Invalid()); FeedbackVectorICSlot slot = FeedbackVectorICSlot::Invalid());
void EmitLoadSuperConstructor(); void EmitLoadSuperConstructor(SuperCallReference* super_call_ref);
void EmitInitializeThisAfterSuper( void EmitInitializeThisAfterSuper(
SuperReference* super_ref, SuperCallReference* super_call_ref,
FeedbackVectorICSlot slot = FeedbackVectorICSlot::Invalid()); FeedbackVectorICSlot slot = FeedbackVectorICSlot::Invalid());
void CallIC(Handle<Code> code, void CallIC(Handle<Code> code,
......
...@@ -11567,7 +11567,16 @@ void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) { ...@@ -11567,7 +11567,16 @@ void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) {
} }
void HOptimizedGraphBuilder::VisitSuperReference(SuperReference* expr) { void HOptimizedGraphBuilder::VisitSuperPropertyReference(
SuperPropertyReference* expr) {
DCHECK(!HasStackOverflow());
DCHECK(current_block() != NULL);
DCHECK(current_block()->HasPredecessor());
return Bailout(kSuperReference);
}
void HOptimizedGraphBuilder::VisitSuperCallReference(SuperCallReference* expr) {
DCHECK(!HasStackOverflow()); DCHECK(!HasStackOverflow());
DCHECK(current_block() != NULL); DCHECK(current_block() != NULL);
DCHECK(current_block()->HasPredecessor()); DCHECK(current_block()->HasPredecessor());
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -359,8 +359,17 @@ FunctionLiteral* Parser::DefaultConstructor(bool call_super, Scope* scope, ...@@ -359,8 +359,17 @@ FunctionLiteral* Parser::DefaultConstructor(bool call_super, Scope* scope,
body = new (zone()) ZoneList<Statement*>(call_super ? 2 : 1, zone()); body = new (zone()) ZoneList<Statement*>(call_super ? 2 : 1, zone());
AddAssertIsConstruct(body, pos); AddAssertIsConstruct(body, pos);
if (call_super) { if (call_super) {
// %_DefaultConstructorCallSuper(new.target, .this_function)
ZoneList<Expression*>* args = ZoneList<Expression*>* args =
new (zone()) ZoneList<Expression*>(0, zone()); new (zone()) ZoneList<Expression*>(2, zone());
VariableProxy* new_target_proxy = scope_->NewUnresolved(
factory(), ast_value_factory()->new_target_string(), Variable::NORMAL,
pos);
args->Add(new_target_proxy, zone());
VariableProxy* this_function_proxy = scope_->NewUnresolved(
factory(), ast_value_factory()->this_function_string(),
Variable::NORMAL, pos);
args->Add(this_function_proxy, zone());
CallRuntime* call = factory()->NewCallRuntime( CallRuntime* call = factory()->NewCallRuntime(
ast_value_factory()->empty_string(), ast_value_factory()->empty_string(),
Runtime::FunctionForId(Runtime::kInlineDefaultConstructorCallSuper), Runtime::FunctionForId(Runtime::kInlineDefaultConstructorCallSuper),
...@@ -747,19 +756,32 @@ Expression* ParserTraits::ThisExpression(Scope* scope, AstNodeFactory* factory, ...@@ -747,19 +756,32 @@ Expression* ParserTraits::ThisExpression(Scope* scope, AstNodeFactory* factory,
Variable::THIS, pos, pos + 4); Variable::THIS, pos, pos + 4);
} }
Expression* ParserTraits::SuperReference(Scope* scope, AstNodeFactory* factory, Expression* ParserTraits::SuperPropertyReference(Scope* scope,
int pos) { AstNodeFactory* factory,
// TODO(arv): Split into SuperProperty and SuperCall? int pos) {
VariableProxy* home_object_proxy = scope->NewUnresolved( VariableProxy* home_object_proxy = scope->NewUnresolved(
factory, parser_->ast_value_factory()->home_object_string(), factory, parser_->ast_value_factory()->home_object_string(),
Variable::NORMAL, pos); Variable::NORMAL, pos);
return factory->NewSuperPropertyReference(
return factory->NewSuperReference(
ThisExpression(scope, factory, pos)->AsVariableProxy(), home_object_proxy, ThisExpression(scope, factory, pos)->AsVariableProxy(), home_object_proxy,
pos); pos);
} }
Expression* ParserTraits::SuperCallReference(Scope* scope,
AstNodeFactory* factory, int pos) {
VariableProxy* new_target_proxy = scope->NewUnresolved(
factory, parser_->ast_value_factory()->new_target_string(),
Variable::NORMAL, pos);
VariableProxy* this_function_proxy = scope->NewUnresolved(
factory, parser_->ast_value_factory()->this_function_string(),
Variable::NORMAL, pos);
return factory->NewSuperCallReference(
ThisExpression(scope, factory, pos)->AsVariableProxy(), new_target_proxy,
this_function_proxy, pos);
}
Expression* ParserTraits::DefaultConstructor(bool call_super, Scope* scope, Expression* ParserTraits::DefaultConstructor(bool call_super, Scope* scope,
int pos, int end_pos) { int pos, int end_pos) {
return parser_->DefaultConstructor(call_super, scope, pos, end_pos); return parser_->DefaultConstructor(call_super, scope, pos, end_pos);
...@@ -5744,13 +5766,14 @@ ZoneList<v8::internal::Expression*>* Parser::PrepareSpreadArguments( ...@@ -5744,13 +5766,14 @@ ZoneList<v8::internal::Expression*>* Parser::PrepareSpreadArguments(
Expression* Parser::SpreadCall(Expression* function, Expression* Parser::SpreadCall(Expression* function,
ZoneList<v8::internal::Expression*>* args, ZoneList<v8::internal::Expression*>* args,
int pos) { int pos) {
if (function->IsSuperReference()) { if (function->IsSuperCallReference()) {
// Super calls // Super calls
// %_CallSuperWithSpread(%ReflectConstruct(<super>, args, new.target))
args->InsertAt(0, function, zone()); args->InsertAt(0, function, zone());
args->Add(factory()->NewVariableProxy(scope_->new_target_var()), zone()); args->Add(function->AsSuperCallReference()->new_target_var(), zone());
Expression* result = factory()->NewCallRuntime( Expression* result = factory()->NewCallRuntime(
ast_value_factory()->reflect_construct_string(), NULL, args, pos); ast_value_factory()->reflect_construct_string(), NULL, args, pos);
args = new (zone()) ZoneList<Expression*>(0, zone()); args = new (zone()) ZoneList<Expression*>(1, zone());
args->Add(result, zone()); args->Add(result, zone());
return factory()->NewCallRuntime( return factory()->NewCallRuntime(
ast_value_factory()->empty_string(), ast_value_factory()->empty_string(),
......
...@@ -724,7 +724,10 @@ class ParserTraits { ...@@ -724,7 +724,10 @@ class ParserTraits {
Expression* ThisExpression(Scope* scope, AstNodeFactory* factory, Expression* ThisExpression(Scope* scope, AstNodeFactory* factory,
int pos = RelocInfo::kNoPosition); int pos = RelocInfo::kNoPosition);
Expression* SuperReference(Scope* scope, AstNodeFactory* factory, int pos); Expression* SuperPropertyReference(Scope* scope, AstNodeFactory* factory,
int pos);
Expression* SuperCallReference(Scope* scope, AstNodeFactory* factory,
int pos);
Expression* DefaultConstructor(bool call_super, Scope* scope, int pos, Expression* DefaultConstructor(bool call_super, Scope* scope, int pos,
int end_pos); int end_pos);
Literal* ExpressionFromLiteral(Token::Value token, int pos, Scanner* scanner, Literal* ExpressionFromLiteral(Token::Value token, int pos, Scanner* scanner,
......
...@@ -404,7 +404,8 @@ NOT_A_PATTERN(NativeFunctionLiteral) ...@@ -404,7 +404,8 @@ NOT_A_PATTERN(NativeFunctionLiteral)
NOT_A_PATTERN(Property) NOT_A_PATTERN(Property)
NOT_A_PATTERN(RegExpLiteral) NOT_A_PATTERN(RegExpLiteral)
NOT_A_PATTERN(ReturnStatement) NOT_A_PATTERN(ReturnStatement)
NOT_A_PATTERN(SuperReference) NOT_A_PATTERN(SuperPropertyReference)
NOT_A_PATTERN(SuperCallReference)
NOT_A_PATTERN(SwitchStatement) NOT_A_PATTERN(SwitchStatement)
NOT_A_PATTERN(ThisFunction) NOT_A_PATTERN(ThisFunction)
NOT_A_PATTERN(Throw) NOT_A_PATTERN(Throw)
......
...@@ -1715,9 +1715,15 @@ class PreParserTraits { ...@@ -1715,9 +1715,15 @@ class PreParserTraits {
return PreParserExpression::This(); return PreParserExpression::This();
} }
static PreParserExpression SuperReference(Scope* scope, static PreParserExpression SuperPropertyReference(Scope* scope,
PreParserFactory* factory, PreParserFactory* factory,
int pos) { int pos) {
return PreParserExpression::Default();
}
static PreParserExpression SuperCallReference(Scope* scope,
PreParserFactory* factory,
int pos) {
return PreParserExpression::Default(); return PreParserExpression::Default();
} }
...@@ -3515,7 +3521,7 @@ ParserBase<Traits>::ParseStrongSuperCallExpression( ...@@ -3515,7 +3521,7 @@ ParserBase<Traits>::ParseStrongSuperCallExpression(
Consume(Token::SUPER); Consume(Token::SUPER);
int pos = position(); int pos = position();
Scanner::Location super_loc = scanner()->location(); Scanner::Location super_loc = scanner()->location();
ExpressionT expr = this->SuperReference(scope_, factory(), pos); ExpressionT expr = this->SuperCallReference(scope_, factory(), pos);
if (peek() != Token::LPAREN) { if (peek() != Token::LPAREN) {
ReportMessage(MessageTemplate::kStrongConstructorSuper); ReportMessage(MessageTemplate::kStrongConstructorSuper);
...@@ -3580,7 +3586,7 @@ ParserBase<Traits>::ParseSuperExpression(bool is_new, ...@@ -3580,7 +3586,7 @@ ParserBase<Traits>::ParseSuperExpression(bool is_new,
i::IsConstructor(kind)) { i::IsConstructor(kind)) {
if (peek() == Token::PERIOD || peek() == Token::LBRACK) { if (peek() == Token::PERIOD || peek() == Token::LBRACK) {
scope->RecordSuperPropertyUsage(); scope->RecordSuperPropertyUsage();
return this->SuperReference(scope_, factory(), pos); return this->SuperPropertyReference(scope_, factory(), pos);
} }
// new super() is never allowed. // new super() is never allowed.
// super() is only allowed in derived constructor // super() is only allowed in derived constructor
...@@ -3595,7 +3601,7 @@ ParserBase<Traits>::ParseSuperExpression(bool is_new, ...@@ -3595,7 +3601,7 @@ ParserBase<Traits>::ParseSuperExpression(bool is_new,
// TODO(rossberg): This might not be the correct FunctionState for the // TODO(rossberg): This might not be the correct FunctionState for the
// method here. // method here.
function_state_->set_super_location(scanner()->location()); function_state_->set_super_location(scanner()->location());
return this->SuperReference(scope_, factory(), pos); return this->SuperCallReference(scope_, factory(), pos);
} }
} }
......
...@@ -364,7 +364,10 @@ void CallPrinter::VisitSpread(Spread* node) { ...@@ -364,7 +364,10 @@ void CallPrinter::VisitSpread(Spread* node) {
void CallPrinter::VisitThisFunction(ThisFunction* node) {} void CallPrinter::VisitThisFunction(ThisFunction* node) {}
void CallPrinter::VisitSuperReference(SuperReference* node) {} void CallPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) {}
void CallPrinter::VisitSuperCallReference(SuperCallReference* node) {}
void CallPrinter::FindStatements(ZoneList<Statement*>* statements) { void CallPrinter::FindStatements(ZoneList<Statement*>* statements) {
...@@ -835,8 +838,13 @@ void PrettyPrinter::VisitThisFunction(ThisFunction* node) { ...@@ -835,8 +838,13 @@ void PrettyPrinter::VisitThisFunction(ThisFunction* node) {
} }
void PrettyPrinter::VisitSuperReference(SuperReference* node) { void PrettyPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) {
Print("<super-reference>"); Print("<super-property-reference>");
}
void PrettyPrinter::VisitSuperCallReference(SuperCallReference* node) {
Print("<super-call-reference>");
} }
...@@ -1527,10 +1535,16 @@ void AstPrinter::VisitThisFunction(ThisFunction* node) { ...@@ -1527,10 +1535,16 @@ void AstPrinter::VisitThisFunction(ThisFunction* node) {
} }
void AstPrinter::VisitSuperReference(SuperReference* node) { void AstPrinter::VisitSuperPropertyReference(SuperPropertyReference* node) {
IndentedScope indent(this, "SUPER-REFERENCE"); IndentedScope indent(this, "SUPER-PROPERTY-REFERENCE");
} }
void AstPrinter::VisitSuperCallReference(SuperCallReference* node) {
IndentedScope indent(this, "SUPER-CALL-REFERENCE");
}
#endif // DEBUG #endif // DEBUG
} // namespace internal } // namespace internal
......
...@@ -72,8 +72,8 @@ namespace internal { ...@@ -72,8 +72,8 @@ namespace internal {
F(StoreKeyedToSuper_Strict, 4, 1) \ F(StoreKeyedToSuper_Strict, 4, 1) \
F(StoreKeyedToSuper_Sloppy, 4, 1) \ F(StoreKeyedToSuper_Sloppy, 4, 1) \
F(HandleStepInForDerivedConstructors, 1, 1) \ F(HandleStepInForDerivedConstructors, 1, 1) \
F(DefaultConstructorCallSuper, 0, 1) \ F(DefaultConstructorCallSuper, 2, 1) \
F(CallSuperWithSpread, 0, 1) F(CallSuperWithSpread, 1, 1)
#define FOR_EACH_INTRINSIC_COLLECTIONS(F) \ #define FOR_EACH_INTRINSIC_COLLECTIONS(F) \
......
...@@ -160,6 +160,7 @@ void Scope::SetDefaults(ScopeType scope_type, Scope* outer_scope, ...@@ -160,6 +160,7 @@ void Scope::SetDefaults(ScopeType scope_type, Scope* outer_scope,
function_ = nullptr; function_ = nullptr;
arguments_ = nullptr; arguments_ = nullptr;
home_object_ = nullptr; home_object_ = nullptr;
this_function_ = nullptr;
illegal_redecl_ = nullptr; illegal_redecl_ = nullptr;
scope_inside_with_ = false; scope_inside_with_ = false;
scope_contains_with_ = false; scope_contains_with_ = false;
...@@ -308,45 +309,44 @@ void Scope::Initialize() { ...@@ -308,45 +309,44 @@ void Scope::Initialize() {
} }
// Declare convenience variables and the receiver. // Declare convenience variables and the receiver.
if (is_declaration_scope()) { if (is_declaration_scope() && has_this_declaration()) {
DCHECK(!subclass_constructor || is_function_scope()); Variable* var = variables_.Declare(
if (has_this_declaration()) { this, ast_value_factory_->this_string(),
Variable* var = variables_.Declare( subclass_constructor ? CONST : VAR, Variable::THIS,
this, ast_value_factory_->this_string(), subclass_constructor ? kNeedsInitialization : kCreatedInitialized);
subclass_constructor ? CONST : VAR, Variable::THIS, receiver_ = var;
subclass_constructor ? kNeedsInitialization : kCreatedInitialized); }
receiver_ = var;
if (is_function_scope()) {
if (!is_arrow_scope()) {
// Declare 'arguments' variable which exists in all non arrow functions.
// Note that it might never be accessed, in which case it won't be
// allocated during variable allocation.
variables_.Declare(this, ast_value_factory_->arguments_string(), VAR,
Variable::ARGUMENTS, kCreatedInitialized);
} }
if (subclass_constructor) { if (subclass_constructor) {
new_target_ = DCHECK(!is_arrow_scope());
variables_.Declare(this, ast_value_factory_->new_target_string(), variables_.Declare(this, ast_value_factory_->new_target_string(), CONST,
CONST, Variable::NEW_TARGET, kCreatedInitialized); Variable::NORMAL, kCreatedInitialized);
new_target_->AllocateTo(Variable::PARAMETER, -2);
new_target_->set_is_used();
} }
}
if (is_function_scope() && !is_arrow_scope()) { if (IsConciseMethod(function_kind_) || IsConstructor(function_kind_) ||
// Declare 'arguments' variable which exists in all non arrow functions. IsAccessorFunction(function_kind_)) {
// Note that it might never be accessed, in which case it won't be DCHECK(!is_arrow_scope());
// allocated during variable allocation. // Declare '.home_object' variable which exists in all methods.
variables_.Declare(this, // Note that it might never be accessed, in which case it won't be
ast_value_factory_->arguments_string(), // allocated during variable allocation.
VAR, variables_.Declare(this, ast_value_factory_->home_object_string(), CONST,
Variable::ARGUMENTS, Variable::NORMAL, kCreatedInitialized);
kCreatedInitialized); }
}
if (is_function_scope() && if (IsSubclassConstructor(function_kind_)) {
(IsConciseMethod(function_kind_) || IsConstructor(function_kind_) || DCHECK(!is_arrow_scope());
IsAccessorFunction(function_kind_))) { variables_.Declare(this, ast_value_factory_->this_function_string(),
DCHECK(!is_arrow_scope()); CONST, Variable::NORMAL, kCreatedInitialized);
// Declare '.home_object' variable which exists in all methods. }
// Note that it might never be accessed, in which case it won't be
// allocated during variable allocation.
variables_.Declare(this, ast_value_factory_->home_object_string(), VAR,
Variable::NORMAL, kCreatedInitialized);
} }
} }
...@@ -1311,7 +1311,7 @@ bool Scope::MustAllocate(Variable* var) { ...@@ -1311,7 +1311,7 @@ bool Scope::MustAllocate(Variable* var) {
// Give var a read/write use if there is a chance it might be accessed // Give var a read/write use if there is a chance it might be accessed
// via an eval() call. This is only possible if the variable has a // via an eval() call. This is only possible if the variable has a
// visible name. // visible name.
if ((var->is_this() || var->is_new_target() || !var->raw_name()->IsEmpty()) && if ((var->is_this() || !var->raw_name()->IsEmpty()) &&
(var->has_forced_context_allocation() || scope_calls_eval_ || (var->has_forced_context_allocation() || scope_calls_eval_ ||
inner_scope_calls_eval_ || scope_contains_with_ || is_catch_scope() || inner_scope_calls_eval_ || scope_contains_with_ || is_catch_scope() ||
is_block_scope() || is_module_scope() || is_script_scope())) { is_block_scope() || is_module_scope() || is_script_scope())) {
...@@ -1403,18 +1403,6 @@ void Scope::AllocateParameterLocals(Isolate* isolate) { ...@@ -1403,18 +1403,6 @@ void Scope::AllocateParameterLocals(Isolate* isolate) {
rest_parameter_ = NULL; rest_parameter_ = NULL;
} }
Variable* home_object_var =
LookupLocal(ast_value_factory_->home_object_string());
if (home_object_var != nullptr && uses_super_property() &&
MustAllocate(home_object_var)) {
// TODO(arv): super() uses a SuperReference so it generates a VariableProxy
// for the .home_object which makes it look like we need to allocate the
// home_object_var.
// Consider splitting the AST node into 2 different nodes since the
// semantics is just so different.
home_object_ = home_object_var;
}
// The same parameter may occur multiple times in the parameters_ list. // The same parameter may occur multiple times in the parameters_ list.
// If it does, and if it is not copied into the context object, it must // If it does, and if it is not copied into the context object, it must
// receive the highest parameter index for that parameter; thus iteration // receive the highest parameter index for that parameter; thus iteration
...@@ -1503,13 +1491,31 @@ void Scope::AllocateNonParameterLocals(Isolate* isolate) { ...@@ -1503,13 +1491,31 @@ void Scope::AllocateNonParameterLocals(Isolate* isolate) {
// allocated in the context, it must be the last slot in the context, // allocated in the context, it must be the last slot in the context,
// because of the current ScopeInfo implementation (see // because of the current ScopeInfo implementation (see
// ScopeInfo::ScopeInfo(FunctionScope* scope) constructor). // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor).
if (function_ != NULL) { if (function_ != nullptr) {
AllocateNonParameterLocal(isolate, function_->proxy()->var()); AllocateNonParameterLocal(isolate, function_->proxy()->var());
} }
if (rest_parameter_) { if (rest_parameter_ != nullptr) {
AllocateNonParameterLocal(isolate, rest_parameter_); AllocateNonParameterLocal(isolate, rest_parameter_);
} }
Variable* home_object_var =
LookupLocal(ast_value_factory_->home_object_string());
if (home_object_var != nullptr && MustAllocate(home_object_var)) {
home_object_ = home_object_var;
}
Variable* new_target_var =
LookupLocal(ast_value_factory_->new_target_string());
if (new_target_var != nullptr && MustAllocate(new_target_var)) {
new_target_ = new_target_var;
}
Variable* this_function_var =
LookupLocal(ast_value_factory_->this_function_string());
if (this_function_var != nullptr && MustAllocate(this_function_var)) {
this_function_ = this_function_var;
}
} }
......
...@@ -419,6 +419,13 @@ class Scope: public ZoneObject { ...@@ -419,6 +419,13 @@ class Scope: public ZoneObject {
return home_object_; return home_object_;
} }
Variable* this_function_var() const {
// This is only used in derived constructors atm.
DCHECK(this_function_ == nullptr ||
(is_function_scope() && IsSubclassConstructor(function_kind())));
return this_function_;
}
// Declarations list. // Declarations list.
ZoneList<Declaration*>* declarations() { return &decls_; } ZoneList<Declaration*>* declarations() { return &decls_; }
...@@ -579,6 +586,8 @@ class Scope: public ZoneObject { ...@@ -579,6 +586,8 @@ class Scope: public ZoneObject {
Variable* arguments_; Variable* arguments_;
// Convenience variable; method scopes only. // Convenience variable; method scopes only.
Variable* home_object_; Variable* home_object_;
// Convenience variable; Subclass constructor only
Variable* this_function_;
// Module descriptor; module scopes only. // Module descriptor; module scopes only.
ModuleDescriptor* module_descriptor_; ModuleDescriptor* module_descriptor_;
......
...@@ -761,7 +761,10 @@ void AstTyper::VisitThisFunction(ThisFunction* expr) { ...@@ -761,7 +761,10 @@ void AstTyper::VisitThisFunction(ThisFunction* expr) {
} }
void AstTyper::VisitSuperReference(SuperReference* expr) {} void AstTyper::VisitSuperPropertyReference(SuperPropertyReference* expr) {}
void AstTyper::VisitSuperCallReference(SuperCallReference* expr) {}
void AstTyper::VisitDeclarations(ZoneList<Declaration*>* decls) { void AstTyper::VisitDeclarations(ZoneList<Declaration*>* decls) {
......
...@@ -20,7 +20,7 @@ class ClassVariable; ...@@ -20,7 +20,7 @@ class ClassVariable;
class Variable: public ZoneObject { class Variable: public ZoneObject {
public: public:
enum Kind { NORMAL, FUNCTION, CLASS, THIS, NEW_TARGET, ARGUMENTS }; enum Kind { NORMAL, FUNCTION, CLASS, THIS, ARGUMENTS };
enum Location { enum Location {
// Before and during variable allocation, a variable whose location is // Before and during variable allocation, a variable whose location is
...@@ -103,7 +103,6 @@ class Variable: public ZoneObject { ...@@ -103,7 +103,6 @@ class Variable: public ZoneObject {
bool is_function() const { return kind_ == FUNCTION; } bool is_function() const { return kind_ == FUNCTION; }
bool is_class() const { return kind_ == CLASS; } bool is_class() const { return kind_ == CLASS; }
bool is_this() const { return kind_ == THIS; } bool is_this() const { return kind_ == THIS; }
bool is_new_target() const { return kind_ == NEW_TARGET; }
bool is_arguments() const { return kind_ == ARGUMENTS; } bool is_arguments() const { return kind_ == ARGUMENTS; }
ClassVariable* AsClassVariable() { ClassVariable* AsClassVariable() {
......
This diff is collapsed.
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
// found in the LICENSE file. // found in the LICENSE file.
// Flags: --harmony-classes --harmony-arrow-functions --allow-natives-syntax // Flags: --harmony-classes --harmony-arrow-functions --allow-natives-syntax
// Flags: --harmony-spreadcalls
(function TestSuperNamedLoads() { (function TestSuperNamedLoads() {
function Base() { } function Base() { }
...@@ -2107,3 +2107,99 @@ TestKeyedSetterCreatingOwnPropertiesNonConfigurable(42, 43, 44); ...@@ -2107,3 +2107,99 @@ TestKeyedSetterCreatingOwnPropertiesNonConfigurable(42, 43, 44);
let d = new Derived(); let d = new Derived();
assertSame(1, d.arrow()); assertSame(1, d.arrow());
})(); })();
(function TestSuperCallInEval() {
'use strict';
class Base {
constructor(x) {
this.x = x;
}
}
class Derived extends Base {
constructor(x) {
eval('super(x)');
}
}
let d = new Derived(42);
assertSame(42, d.x);
})();
(function TestSuperCallInArrow() {
'use strict';
class Base {
constructor(x) {
this.x = x;
}
}
class Derived extends Base {
constructor(x) {
(() => super(x))();
}
}
let d = new Derived(42);
assertSame(42, d.x);
})();
(function TestSuperCallEscapes() {
'use strict';
class Base {
constructor(x) {
this.x = x;
}
}
let f;
class Derived extends Base {
constructor() {
f = () => super(2);
}
}
assertThrows(function() {
new Derived();
}, ReferenceError);
let o = f();
assertEquals(2, o.x);
assertInstanceof(o, Derived);
assertThrows(function() {
f();
}, ReferenceError);
})();
(function TestSuperCallSpreadInEval() {
'use strict';
class Base {
constructor(x) {
this.x = x;
}
}
class Derived extends Base {
constructor(x) {
eval('super(...[x])');
}
}
let d = new Derived(42);
assertSame(42, d.x);
})();
(function TestSuperCallSpreadInArrow() {
'use strict';
class Base {
constructor(x) {
this.x = x;
}
}
class Derived extends Base {
constructor(x) {
(() => super(...[x]))();
}
}
let d = new Derived(42);
assertSame(42, d.x);
})();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment