Commit 8f89ad74 authored by adamk's avatar adamk Committed by Commit bot

Remove unnecessary ClassLiteral name member and simplify Function.name handling

A class's name is its constructor's name, so there's no need to treat it separately,
either in the parser or in code generation. The main parser use of the name is
for ES2015 Function.name handling, and this patch also cleans up handling there
by adding a new IsAnonymousFunctionDefinition() method to Expression (the name
comes from the spec).

Also removed unused ParserTraits::DefaultConstructor method.

BUG=v8:3699
LOG=n

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

Cr-Commit-Position: refs/heads/master@{#33643}
parent c3ff68b6
......@@ -324,6 +324,10 @@ class Expression : public AstNode {
// names because [] for string objects is handled only by keyed ICs.
virtual bool IsPropertyName() const { return false; }
// True iff the expression is a class or function expression without
// a syntactic name.
virtual bool IsAnonymousFunctionDefinition() const { return false; }
// True iff the expression is a literal represented as a smi.
bool IsSmiLiteral() const;
......@@ -2758,6 +2762,13 @@ class FunctionLiteral final : public Expression {
dont_optimize_reason_ = reason;
}
bool IsAnonymousFunctionDefinition() const final {
// TODO(adamk): This isn't quite accurate, as many non-expressions
// (such as concise methods) are marked as anonymous, but it's
// sufficient for the current callers.
return is_anonymous();
}
protected:
FunctionLiteral(Zone* zone, const AstString* name,
AstValueFactory* ast_value_factory, Scope* scope,
......@@ -2825,13 +2836,6 @@ class ClassLiteral final : public Expression {
DECLARE_NODE_TYPE(ClassLiteral)
Handle<String> name() const { return raw_name_->string(); }
const AstRawString* raw_name() const { return raw_name_; }
void set_raw_name(const AstRawString* name) {
DCHECK_NULL(raw_name_);
raw_name_ = name;
}
Scope* scope() const { return scope_; }
VariableProxy* class_variable_proxy() const { return class_variable_proxy_; }
Expression* extends() const { return extends_; }
......@@ -2866,13 +2870,16 @@ class ClassLiteral final : public Expression {
FeedbackVectorSlot ProxySlot() const { return slot_; }
bool IsAnonymousFunctionDefinition() const final {
return constructor()->raw_name()->length() == 0;
}
protected:
ClassLiteral(Zone* zone, const AstRawString* name, Scope* scope,
VariableProxy* class_variable_proxy, Expression* extends,
FunctionLiteral* constructor, ZoneList<Property*>* properties,
int start_position, int end_position)
ClassLiteral(Zone* zone, Scope* scope, VariableProxy* class_variable_proxy,
Expression* extends, FunctionLiteral* constructor,
ZoneList<Property*>* properties, int start_position,
int end_position)
: Expression(zone, start_position),
raw_name_(name),
scope_(scope),
class_variable_proxy_(class_variable_proxy),
extends_(extends),
......@@ -2885,7 +2892,6 @@ class ClassLiteral final : public Expression {
private:
int local_id(int n) const { return base_id() + parent_num_ids() + n; }
const AstRawString* raw_name_;
Scope* scope_;
VariableProxy* class_variable_proxy_;
Expression* extends_;
......@@ -3481,13 +3487,13 @@ class AstNodeFactory final BASE_EMBEDDED {
position);
}
ClassLiteral* NewClassLiteral(const AstRawString* name, Scope* scope,
VariableProxy* proxy, Expression* extends,
ClassLiteral* NewClassLiteral(Scope* scope, VariableProxy* proxy,
Expression* extends,
FunctionLiteral* constructor,
ZoneList<ObjectLiteral::Property*>* properties,
int start_position, int end_position) {
return new (parser_zone_)
ClassLiteral(parser_zone_, name, scope, proxy, extends, constructor,
ClassLiteral(parser_zone_, scope, proxy, extends, constructor,
properties, start_position, end_position);
}
......
......@@ -719,7 +719,7 @@ void PrettyPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
void PrettyPrinter::VisitClassLiteral(ClassLiteral* node) {
Print("(class ");
PrintLiteral(node->name(), false);
PrintLiteral(node->constructor()->name(), false);
if (node->extends()) {
Print(" extends ");
Visit(node->extends());
......@@ -1429,9 +1429,7 @@ void AstPrinter::VisitFunctionLiteral(FunctionLiteral* node) {
void AstPrinter::VisitClassLiteral(ClassLiteral* node) {
IndentedScope indent(this, "CLASS LITERAL", node->position());
if (node->raw_name() != nullptr) {
PrintLiteralIndented("NAME", node->name(), false);
}
PrintLiteralIndented("NAME", node->constructor()->name(), false);
if (node->extends() != nullptr) {
PrintIndentedVisit("EXTENDS", node->extends());
}
......
......@@ -1558,22 +1558,16 @@ void AstGraphBuilder::VisitClassLiteral(ClassLiteral* expr) {
void AstGraphBuilder::VisitClassLiteralContents(ClassLiteral* expr) {
Node* class_name = expr->raw_name() ? jsgraph()->Constant(expr->name())
: jsgraph()->UndefinedConstant();
// The class name is expected on the operand stack.
environment()->Push(class_name);
VisitForValueOrTheHole(expr->extends());
VisitForValue(expr->constructor());
// Create node to instantiate a new class.
Node* constructor = environment()->Pop();
Node* extends = environment()->Pop();
Node* name = environment()->Pop();
Node* start = jsgraph()->Constant(expr->start_position());
Node* end = jsgraph()->Constant(expr->end_position());
const Operator* opc = javascript()->CallRuntime(Runtime::kDefineClass);
Node* literal = NewNode(opc, name, extends, constructor, start, end);
Node* literal = NewNode(opc, extends, constructor, start, end);
PrepareFrameState(literal, expr->CreateLiteralId(),
OutputFrameStateCombine::Push());
......
......@@ -1311,12 +1311,6 @@ void FullCodeGenerator::VisitClassLiteral(ClassLiteral* lit) {
EnterBlockScopeIfNeeded block_scope_state(
this, lit->scope(), lit->EntryId(), lit->DeclsId(), lit->ExitId());
if (lit->raw_name() != NULL) {
__ Push(lit->name());
} else {
__ Push(isolate()->factory()->undefined_value());
}
if (lit->extends() != NULL) {
VisitForStackValue(lit->extends());
} else {
......
......@@ -179,15 +179,14 @@ void Parser::SetCachedData(ParseInfo* info) {
}
}
FunctionLiteral* Parser::DefaultConstructor(bool call_super, Scope* scope,
FunctionLiteral* Parser::DefaultConstructor(const AstRawString* name,
bool call_super, Scope* scope,
int pos, int end_pos,
LanguageMode language_mode) {
int materialized_literal_count = -1;
int expected_property_count = -1;
int parameter_count = 0;
const AstRawString* name = ast_value_factory()->empty_string();
if (name == nullptr) name = ast_value_factory()->empty_string();
FunctionKind kind = call_super ? FunctionKind::kDefaultSubclassConstructor
: FunctionKind::kDefaultBaseConstructor;
......@@ -656,13 +655,6 @@ Expression* ParserTraits::FunctionSentExpression(Scope* scope,
}
Expression* ParserTraits::DefaultConstructor(bool call_super, Scope* scope,
int pos, int end_pos,
LanguageMode mode) {
return parser_->DefaultConstructor(call_super, scope, pos, end_pos, mode);
}
Literal* ParserTraits::ExpressionFromLiteral(Token::Value token, int pos,
Scanner* scanner,
AstNodeFactory* factory) {
......@@ -1110,10 +1102,10 @@ FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info,
}
}
} else if (shared_info->is_default_constructor()) {
result = DefaultConstructor(IsSubclassConstructor(shared_info->kind()),
scope, shared_info->start_position(),
shared_info->end_position(),
shared_info->language_mode());
result = DefaultConstructor(
raw_name, IsSubclassConstructor(shared_info->kind()), scope,
shared_info->start_position(), shared_info->end_position(),
shared_info->language_mode());
} else {
result = ParseFunctionLiteral(
raw_name, Scanner::Location::invalid(), kSkipFunctionNameCheck,
......@@ -2477,18 +2469,8 @@ void Parser::ParseVariableDeclarations(VariableDeclarationContext var_context,
}
}
if (allow_harmony_function_name() && single_name) {
if (value->IsFunctionLiteral()) {
auto function_literal = value->AsFunctionLiteral();
if (function_literal->is_anonymous()) {
function_literal->set_raw_name(single_name);
}
} else if (value->IsClassLiteral()) {
auto class_literal = value->AsClassLiteral();
if (class_literal->raw_name() == nullptr) {
class_literal->set_raw_name(single_name);
}
}
if (allow_harmony_function_name()) {
ParserTraits::SetFunctionNameFromIdentifierRef(value, pattern);
}
// End position of the initializer is after the assignment expression.
......@@ -4896,24 +4878,27 @@ ClassLiteral* Parser::ParseClassLiteral(const AstRawString* name,
bool is_computed_name = false; // Classes do not care about computed
// property names here.
ExpressionClassifier classifier;
const AstRawString* name = nullptr;
const AstRawString* property_name = nullptr;
ObjectLiteral::Property* property = ParsePropertyDefinition(
&checker, in_class, has_extends, is_static, &is_computed_name,
&has_seen_constructor, &classifier, &name, CHECK_OK);
&has_seen_constructor, &classifier, &property_name, CHECK_OK);
property = ParserTraits::RewriteNonPatternObjectLiteralProperty(
property, &classifier, CHECK_OK);
if (has_seen_constructor && constructor == NULL) {
constructor = GetPropertyValue(property)->AsFunctionLiteral();
DCHECK_NOT_NULL(constructor);
constructor->set_raw_name(
name != nullptr ? name : ast_value_factory()->empty_string());
} else {
properties->Add(property, zone());
}
if (fni_ != NULL) fni_->Infer();
if (allow_harmony_function_name()) {
SetFunctionNameFromPropertyName(property, name);
if (allow_harmony_function_name() &&
property_name != ast_value_factory()->constructor_string()) {
SetFunctionNameFromPropertyName(property, property_name);
}
}
......@@ -4921,8 +4906,8 @@ ClassLiteral* Parser::ParseClassLiteral(const AstRawString* name,
int end_pos = scanner()->location().end_pos;
if (constructor == NULL) {
constructor = DefaultConstructor(extends != NULL, block_scope, pos, end_pos,
block_scope->language_mode());
constructor = DefaultConstructor(name, extends != NULL, block_scope, pos,
end_pos, block_scope->language_mode());
}
// Note that we do not finalize this block scope because strong
......@@ -4934,8 +4919,8 @@ ClassLiteral* Parser::ParseClassLiteral(const AstRawString* name,
proxy->var()->set_initializer_position(end_pos);
}
return factory()->NewClassLiteral(name, block_scope, proxy, extends,
constructor, properties, pos, end_pos);
return factory()->NewClassLiteral(block_scope, proxy, extends, constructor,
properties, pos, end_pos);
}
......@@ -5744,7 +5729,7 @@ void ParserTraits::QueueDestructuringAssignmentForRewriting(Expression* expr) {
void ParserTraits::SetFunctionNameFromPropertyName(
ObjectLiteralProperty* property, const AstRawString* name) {
Expression* value = property->value();
if (!value->IsFunctionLiteral() && !value->IsClassLiteral()) return;
if (!value->IsAnonymousFunctionDefinition()) return;
// TODO(adamk): Support computed names.
if (property->is_computed_name()) return;
......@@ -5754,50 +5739,40 @@ void ParserTraits::SetFunctionNameFromPropertyName(
// of an object literal.
if (property->kind() == ObjectLiteralProperty::PROTOTYPE) return;
if (value->IsFunctionLiteral()) {
auto function = value->AsFunctionLiteral();
if (function->is_anonymous()) {
if (property->kind() == ObjectLiteralProperty::GETTER) {
function->set_raw_name(parser_->ast_value_factory()->NewConsString(
parser_->ast_value_factory()->get_space_string(), name));
} else if (property->kind() == ObjectLiteralProperty::SETTER) {
function->set_raw_name(parser_->ast_value_factory()->NewConsString(
parser_->ast_value_factory()->set_space_string(), name));
} else {
function->set_raw_name(name);
DCHECK_EQ(ObjectLiteralProperty::COMPUTED, property->kind());
}
auto function = value->AsFunctionLiteral();
if (function != nullptr) {
if (property->kind() == ObjectLiteralProperty::GETTER) {
function->set_raw_name(parser_->ast_value_factory()->NewConsString(
parser_->ast_value_factory()->get_space_string(), name));
} else if (property->kind() == ObjectLiteralProperty::SETTER) {
function->set_raw_name(parser_->ast_value_factory()->NewConsString(
parser_->ast_value_factory()->set_space_string(), name));
} else {
function->set_raw_name(name);
DCHECK_EQ(ObjectLiteralProperty::COMPUTED, property->kind());
}
} else {
DCHECK(value->IsClassLiteral());
DCHECK_EQ(ObjectLiteralProperty::COMPUTED, property->kind());
auto class_literal = value->AsClassLiteral();
if (class_literal->raw_name() == nullptr) {
class_literal->set_raw_name(name);
}
value->AsClassLiteral()->constructor()->set_raw_name(name);
}
}
void ParserTraits::SetFunctionNameFromIdentifierRef(Expression* value,
Expression* identifier) {
if (!value->IsFunctionLiteral() && !value->IsClassLiteral()) return;
if (!value->IsAnonymousFunctionDefinition()) return;
if (!identifier->IsVariableProxy()) return;
auto name = identifier->AsVariableProxy()->raw_name();
DCHECK_NOT_NULL(name);
if (value->IsFunctionLiteral()) {
auto function = value->AsFunctionLiteral();
if (function->is_anonymous()) {
function->set_raw_name(name);
}
auto function = value->AsFunctionLiteral();
if (function != nullptr) {
function->set_raw_name(name);
} else {
DCHECK(value->IsClassLiteral());
auto class_literal = value->AsClassLiteral();
if (class_literal->raw_name() == nullptr) {
class_literal->set_raw_name(name);
}
value->AsClassLiteral()->constructor()->set_raw_name(name);
}
}
......
......@@ -515,8 +515,6 @@ class ParserTraits {
int pos);
Expression* FunctionSentExpression(Scope* scope, AstNodeFactory* factory,
int pos);
Expression* DefaultConstructor(bool call_super, Scope* scope, int pos,
int end_pos, LanguageMode language_mode);
Literal* ExpressionFromLiteral(Token::Value token, int pos, Scanner* scanner,
AstNodeFactory* factory);
Expression* ExpressionFromIdentifier(const AstRawString* name,
......@@ -968,8 +966,9 @@ class Parser : public ParserBase<ParserTraits> {
Statement* BuildAssertIsCoercible(Variable* var);
// Factory methods.
FunctionLiteral* DefaultConstructor(bool call_super, Scope* scope, int pos,
int end_pos, LanguageMode language_mode);
FunctionLiteral* DefaultConstructor(const AstRawString* name, bool call_super,
Scope* scope, int pos, int end_pos,
LanguageMode language_mode);
// Skip over a lazy function, either using cached data if we have it, or
// by parsing the function with PreParser. Consumes the ending }.
......
......@@ -804,11 +804,6 @@ class PreParserTraits {
return PreParserExpression::Default();
}
static PreParserExpression DefaultConstructor(bool call_super, Scope* scope,
int pos, int end_pos) {
return PreParserExpression::Default();
}
static PreParserExpression ExpressionFromLiteral(
Token::Value token, int pos, Scanner* scanner,
PreParserFactory* factory) {
......
......@@ -81,8 +81,7 @@ RUNTIME_FUNCTION(Runtime_HomeObjectSymbol) {
return isolate->heap()->home_object_symbol();
}
static MaybeHandle<Object> DefineClass(Isolate* isolate, Handle<Object> name,
static MaybeHandle<Object> DefineClass(Isolate* isolate,
Handle<Object> super_class,
Handle<JSFunction> constructor,
int start_position, int end_position) {
......@@ -138,11 +137,6 @@ static MaybeHandle<Object> DefineClass(Isolate* isolate, Handle<Object> name,
map->SetConstructor(*constructor);
Handle<JSObject> prototype = isolate->factory()->NewJSObjectFromMap(map);
Handle<String> name_string = name->IsString()
? Handle<String>::cast(name)
: isolate->factory()->empty_string();
constructor->shared()->set_name(*name_string);
if (!super_class->IsTheHole()) {
// Derived classes, just like builtins, don't create implicit receivers in
// [[construct]]. Instead they just set up new.target and call into the
......@@ -195,16 +189,15 @@ static MaybeHandle<Object> DefineClass(Isolate* isolate, Handle<Object> name,
RUNTIME_FUNCTION(Runtime_DefineClass) {
HandleScope scope(isolate);
DCHECK(args.length() == 5);
CONVERT_ARG_HANDLE_CHECKED(Object, name, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, super_class, 1);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 2);
CONVERT_SMI_ARG_CHECKED(start_position, 3);
CONVERT_SMI_ARG_CHECKED(end_position, 4);
DCHECK(args.length() == 4);
CONVERT_ARG_HANDLE_CHECKED(Object, super_class, 0);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 1);
CONVERT_SMI_ARG_CHECKED(start_position, 2);
CONVERT_SMI_ARG_CHECKED(end_position, 3);
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result, DefineClass(isolate, name, super_class, constructor,
isolate, result, DefineClass(isolate, super_class, constructor,
start_position, end_position));
return *result;
}
......
......@@ -74,7 +74,6 @@ namespace internal {
F(AtomicsFutexWakeOrRequeue, 5, 1) \
F(AtomicsFutexNumWaitersForTesting, 2, 1)
#define FOR_EACH_INTRINSIC_CLASSES(F) \
F(ThrowNonMethodError, 0, 1) \
F(ThrowUnsupportedSuperError, 0, 1) \
......@@ -83,7 +82,7 @@ namespace internal {
F(ThrowStaticPrototypeError, 0, 1) \
F(ThrowIfStaticPrototype, 1, 1) \
F(HomeObjectSymbol, 0, 1) \
F(DefineClass, 5, 1) \
F(DefineClass, 4, 1) \
F(FinalizeClassDefinition, 2, 1) \
F(DefineClassMethod, 3, 1) \
F(LoadFromSuper, 4, 1) \
......@@ -94,7 +93,6 @@ namespace internal {
F(StoreKeyedToSuper_Sloppy, 4, 1) \
F(GetSuperConstructor, 1, 1)
#define FOR_EACH_INTRINSIC_COLLECTIONS(F) \
F(StringGetRawHashField, 1, 1) \
F(TheHole, 0, 1) \
......
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