Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(285)

Side by Side Diff: src/parsing/parser.cc

Issue 2142333002: Refactor class declaration logic to the parser and runtime Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: minor cleanup Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/parsing/parser.h" 5 #include "src/parsing/parser.h"
6 6
7 #include "src/api.h" 7 #include "src/api.h"
8 #include "src/ast/ast.h" 8 #include "src/ast/ast.h"
9 #include "src/ast/ast-expression-rewriter.h" 9 #include "src/ast/ast-expression-rewriter.h"
10 #include "src/ast/ast-expression-visitor.h" 10 #include "src/ast/ast-expression-visitor.h"
(...skipping 751 matching lines...) Expand 10 before | Expand all | Expand 10 after
762 FunctionLiteral* ParserTraits::ParseFunctionLiteral( 762 FunctionLiteral* ParserTraits::ParseFunctionLiteral(
763 const AstRawString* name, Scanner::Location function_name_location, 763 const AstRawString* name, Scanner::Location function_name_location,
764 FunctionNameValidity function_name_validity, FunctionKind kind, 764 FunctionNameValidity function_name_validity, FunctionKind kind,
765 int function_token_position, FunctionLiteral::FunctionType type, 765 int function_token_position, FunctionLiteral::FunctionType type,
766 LanguageMode language_mode, bool* ok) { 766 LanguageMode language_mode, bool* ok) {
767 return parser_->ParseFunctionLiteral( 767 return parser_->ParseFunctionLiteral(
768 name, function_name_location, function_name_validity, kind, 768 name, function_name_location, function_name_validity, kind,
769 function_token_position, type, language_mode, ok); 769 function_token_position, type, language_mode, ok);
770 } 770 }
771 771
772 ClassLiteral* ParserTraits::ParseClassLiteral( 772 Expression* ParserTraits::ParseClassLiteral(
773 Type::ExpressionClassifier* classifier, const AstRawString* name, 773 Type::ExpressionClassifier* classifier, const AstRawString* name,
774 Scanner::Location class_name_location, bool name_is_strict_reserved, 774 Scanner::Location class_name_location, bool name_is_strict_reserved,
775 int pos, bool* ok) { 775 int pos, bool* ok) {
776 return parser_->ParseClassLiteral(classifier, name, class_name_location, 776 return parser_->ParseClassLiteral(classifier, name, class_name_location,
777 name_is_strict_reserved, pos, ok); 777 name_is_strict_reserved, pos, ok);
778 } 778 }
779 779
780 void ParserTraits::MarkTailPosition(Expression* expression) { 780 void ParserTraits::MarkTailPosition(Expression* expression) {
781 expression->MarkTail(); 781 expression->MarkTail();
782 } 782 }
(...skipping 1447 matching lines...) Expand 10 before | Expand all | Expand 10 after
2230 const AstRawString* variable_name; 2230 const AstRawString* variable_name;
2231 if (default_export && (peek() == Token::EXTENDS || peek() == Token::LBRACE)) { 2231 if (default_export && (peek() == Token::EXTENDS || peek() == Token::LBRACE)) {
2232 name = ast_value_factory()->default_string(); 2232 name = ast_value_factory()->default_string();
2233 is_strict_reserved = false; 2233 is_strict_reserved = false;
2234 variable_name = ast_value_factory()->star_default_star_string(); 2234 variable_name = ast_value_factory()->star_default_star_string();
2235 } else { 2235 } else {
2236 name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK); 2236 name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
2237 variable_name = name; 2237 variable_name = name;
2238 } 2238 }
2239 2239
2240 ClassLiteral* value = ParseClassLiteral(nullptr, name, scanner()->location(), 2240 Expression* value = ParseClassLiteral(nullptr, name, scanner()->location(),
2241 is_strict_reserved, pos, CHECK_OK); 2241 is_strict_reserved, pos, CHECK_OK);
2242 2242
2243 VariableProxy* proxy = NewUnresolved(variable_name, LET); 2243 VariableProxy* proxy = NewUnresolved(variable_name, LET);
2244 Declaration* declaration = 2244 Declaration* declaration =
2245 factory()->NewVariableDeclaration(proxy, LET, scope_, pos); 2245 factory()->NewVariableDeclaration(proxy, LET, scope_, pos);
2246 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK); 2246 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
2247 proxy->var()->set_initializer_position(position()); 2247 proxy->var()->set_initializer_position(position());
2248 Assignment* assignment = 2248 Assignment* assignment =
2249 factory()->NewAssignment(Token::INIT, proxy, value, pos); 2249 factory()->NewAssignment(Token::INIT, proxy, value, pos);
2250 Statement* assignment_statement = 2250 Statement* assignment_statement =
2251 factory()->NewExpressionStatement(assignment, kNoSourcePosition); 2251 factory()->NewExpressionStatement(assignment, kNoSourcePosition);
(...skipping 2670 matching lines...) Expand 10 before | Expand all | Expand 10 after
4922 } 4922 }
4923 PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction( 4923 PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction(
4924 language_mode(), function_state_->kind(), scope_->has_simple_parameters(), 4924 language_mode(), function_state_->kind(), scope_->has_simple_parameters(),
4925 parsing_module_, logger, bookmark, use_counts_); 4925 parsing_module_, logger, bookmark, use_counts_);
4926 if (pre_parse_timer_ != NULL) { 4926 if (pre_parse_timer_ != NULL) {
4927 pre_parse_timer_->Stop(); 4927 pre_parse_timer_->Stop();
4928 } 4928 }
4929 return result; 4929 return result;
4930 } 4930 }
4931 4931
4932 ClassLiteral* Parser::ParseClassLiteral(ExpressionClassifier* classifier, 4932 Expression* Parser::ParseClassLiteral(ExpressionClassifier* classifier,
4933 const AstRawString* name, 4933 const AstRawString* name,
4934 Scanner::Location class_name_location, 4934 Scanner::Location class_name_location,
4935 bool name_is_strict_reserved, int pos, 4935 bool name_is_strict_reserved, int pos,
4936 bool* ok) { 4936 bool* ok) {
4937 // All parts of a ClassDeclaration and ClassExpression are strict code. 4937 // All parts of a ClassDeclaration and ClassExpression are strict code.
4938 if (name_is_strict_reserved) { 4938 if (name_is_strict_reserved) {
4939 ReportMessageAt(class_name_location, 4939 ReportMessageAt(class_name_location,
4940 MessageTemplate::kUnexpectedStrictReserved); 4940 MessageTemplate::kUnexpectedStrictReserved);
4941 *ok = false; 4941 *ok = false;
4942 return NULL; 4942 return NULL;
4943 } 4943 }
4944 if (IsEvalOrArguments(name)) { 4944 if (IsEvalOrArguments(name)) {
4945 ReportMessageAt(class_name_location, MessageTemplate::kStrictEvalArguments); 4945 ReportMessageAt(class_name_location, MessageTemplate::kStrictEvalArguments);
4946 *ok = false; 4946 *ok = false;
(...skipping 23 matching lines...) Expand all
4970 if (classifier != nullptr) { 4970 if (classifier != nullptr) {
4971 classifier->Accumulate(&extends_classifier, 4971 classifier->Accumulate(&extends_classifier,
4972 ExpressionClassifier::ExpressionProductions); 4972 ExpressionClassifier::ExpressionProductions);
4973 } 4973 }
4974 } else { 4974 } else {
4975 block_scope->set_start_position(scanner()->location().end_pos); 4975 block_scope->set_start_position(scanner()->location().end_pos);
4976 } 4976 }
4977 4977
4978 4978
4979 ClassLiteralChecker checker(this); 4979 ClassLiteralChecker checker(this);
4980 ZoneList<ObjectLiteral::Property*>* properties = NewPropertyList(4, zone());
4981 FunctionLiteral* constructor = NULL; 4980 FunctionLiteral* constructor = NULL;
4981
4982 ZoneList<Expression*>* property_names =
4983 new (zone()) ZoneList<Expression*>(4, zone());
4984 ZoneList<Expression*>* property_funcs =
4985 new (zone()) ZoneList<Expression*>(4, zone());
4986 ZoneList<Expression*>* property_infos =
4987 new (zone()) ZoneList<Expression*>(4, zone());
4988
4982 bool has_seen_constructor = false; 4989 bool has_seen_constructor = false;
4983 4990
4984 Expect(Token::LBRACE, CHECK_OK); 4991 Expect(Token::LBRACE, CHECK_OK);
4985 4992
4986 const bool has_extends = extends != nullptr; 4993 const bool has_extends = extends != nullptr;
4987 while (peek() != Token::RBRACE) { 4994 while (peek() != Token::RBRACE) {
4988 if (Check(Token::SEMICOLON)) continue; 4995 if (Check(Token::SEMICOLON)) continue;
4989 FuncNameInferrer::State fni_state(fni_); 4996 FuncNameInferrer::State fni_state(fni_);
4990 const bool in_class = true; 4997 const bool in_class = true;
4991 bool is_computed_name = false; // Classes do not care about computed 4998 bool is_computed_name = false; // Classes do not care about computed
4992 // property names here. 4999 // property names here.
4993 ExpressionClassifier property_classifier(this); 5000 ExpressionClassifier property_classifier(this);
4994 const AstRawString* property_name = nullptr; 5001 const AstRawString* property_name = nullptr;
4995 ObjectLiteral::Property* property = ParsePropertyDefinition( 5002 ObjectLiteral::Property* property = ParsePropertyDefinition(
4996 &checker, in_class, has_extends, MethodKind::Normal, &is_computed_name, 5003 &checker, in_class, has_extends, MethodKind::Normal, &is_computed_name,
4997 &has_seen_constructor, &property_classifier, &property_name, CHECK_OK); 5004 &has_seen_constructor, &property_classifier, &property_name, CHECK_OK);
4998 RewriteNonPattern(&property_classifier, CHECK_OK); 5005 RewriteNonPattern(&property_classifier, CHECK_OK);
4999 if (classifier != nullptr) { 5006 if (classifier != nullptr) {
5000 classifier->Accumulate(&property_classifier, 5007 classifier->Accumulate(&property_classifier,
5001 ExpressionClassifier::ExpressionProductions); 5008 ExpressionClassifier::ExpressionProductions);
5002 } 5009 }
5003 5010
5004 if (has_seen_constructor && constructor == NULL) { 5011 if (has_seen_constructor && constructor == NULL) {
5005 constructor = GetPropertyValue(property)->AsFunctionLiteral(); 5012 constructor = GetPropertyValue(property)->AsFunctionLiteral();
5006 DCHECK_NOT_NULL(constructor); 5013 DCHECK_NOT_NULL(constructor);
5007 constructor->set_raw_name( 5014 constructor->set_raw_name(
5008 name != nullptr ? name : ast_value_factory()->empty_string()); 5015 name != nullptr ? name : ast_value_factory()->empty_string());
5009 } else { 5016 } else {
5010 properties->Add(property, zone()); 5017 auto prop_pos =
adamk 2016/07/13 20:57:32 The general practice in v8 has been to use "auto"
5018 GetPropertyValue(property)->AsFunctionLiteral()->position();
adamk 2016/07/13 20:57:32 GetPropertyValue() isn't needed here, you already
5019 Expression* value = property->value();
5020
5021 Expression* property_key;
5022
5023 if (property_name != nullptr) {
adamk 2016/07/13 20:57:32 For the common case of non-numeric properties, you
5024 // For static keys, no ToName call is necessary.
5025 property_key = factory()->NewStringLiteral(property_name, prop_pos);
5026 } else {
5027 ZoneList<Expression*>* toName_args =
adamk 2016/07/13 20:57:32 Style nit: to_name_args
5028 new (zone()) ZoneList<Expression*>(1, zone());
5029 toName_args->Add(property->key(), zone());
5030
5031 property_key =
5032 factory()->NewCallRuntime(Runtime::kToName, toName_args, prop_pos);
adamk 2016/07/13 20:57:32 You can use kInlineToName, which in TurboFan will
5033 }
5034
5035 int info = property->is_static() ? kIsStaticMask : 0;
5036 switch (property->kind()) {
5037 case ObjectLiteral::Property::CONSTANT:
5038 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
5039 case ObjectLiteral::Property::PROTOTYPE:
5040 UNREACHABLE();
5041 case ObjectLiteral::Property::COMPUTED:
5042 break;
5043
5044 case ObjectLiteral::Property::GETTER:
5045 info |= kIsAccessorMask;
5046 break;
5047
5048 case ObjectLiteral::Property::SETTER:
5049 info |= kIsAccessorMask | kIsSetterMask;
5050 break;
5051 }
5052
5053 property_names->Add(property_key, zone());
5054 property_funcs->Add(value, zone());
5055 property_infos->Add(factory()->NewNumberLiteral(info, kNoSourcePosition),
5056 zone());
5011 } 5057 }
5012 5058
5013 if (fni_ != NULL) fni_->Infer(); 5059 if (fni_ != NULL) fni_->Infer();
5014 5060
5015 if (property_name != ast_value_factory()->constructor_string()) { 5061 if (property_name != ast_value_factory()->constructor_string()) {
5016 SetFunctionNameFromPropertyName(property, property_name); 5062 SetFunctionNameFromPropertyName(property, property_name);
5017 } 5063 }
5018 } 5064 }
5019 5065
5020 Expect(Token::RBRACE, CHECK_OK); 5066 Expect(Token::RBRACE, CHECK_OK);
5021 int end_pos = scanner()->location().end_pos; 5067 int end_pos = scanner()->location().end_pos;
5022 5068
5023 if (constructor == NULL) { 5069 if (constructor == NULL) {
5024 constructor = DefaultConstructor(name, has_extends, block_scope, pos, 5070 constructor = DefaultConstructor(name, has_extends, block_scope, pos,
5025 end_pos, block_scope->language_mode()); 5071 end_pos, block_scope->language_mode());
5026 } 5072 }
5027 5073
5028 // Note that we do not finalize this block scope because it is 5074 // Note that we do not finalize this block scope because it is
5029 // used as a sentinel value indicating an anonymous class. 5075 // used as a sentinel value indicating an anonymous class.
5030 block_scope->set_end_position(end_pos); 5076 block_scope->set_end_position(end_pos);
5031 5077
5032 if (name != NULL) { 5078 if (name != NULL) {
5033 DCHECK_NOT_NULL(proxy); 5079 DCHECK_NOT_NULL(proxy);
5034 proxy->var()->set_initializer_position(end_pos); 5080 proxy->var()->set_initializer_position(end_pos);
5035 } 5081 }
5036 5082
5037 return factory()->NewClassLiteral(block_scope, proxy, extends, constructor, 5083 // Construct a DoExpression representing the class literal.
5038 properties, pos, end_pos); 5084 Block* do_block = factory()->NewBlock(nullptr, 16, false, pos);
5085 do_block->set_scope(scope_);
5086
5087 // Call DefineClass. It takes seven arguments:
5088 // 1. The superclass constructor, or the Hole if not present.
5089 // 2. The constructor function.
5090 // 3. An array of method names.
5091 // 4. An array of said method's corresponding functions.
5092 // 5. An array of flags signalling if they are accessors and/or static.
5093 // 6. The location where the class's source starts.
5094 // 7. The location where the class's source ends.
5095 ZoneList<Expression*>* define_class_args =
5096 new (zone()) ZoneList<Expression*>(7, zone());
5097 define_class_args->Add(extends != nullptr
5098 ? extends
5099 : factory()->NewTheHoleLiteral(kNoSourcePosition),
5100 zone());
5101 define_class_args->Add(constructor, zone());
5102
5103 int names_idx = function_state_->NextMaterializedLiteralIndex();
5104 int funcs_idx = function_state_->NextMaterializedLiteralIndex();
5105 int infos_idx = function_state_->NextMaterializedLiteralIndex();
5106
5107 define_class_args->Add(
5108 factory()->NewArrayLiteral(property_names, names_idx, kNoSourcePosition),
5109 zone());
5110 define_class_args->Add(
5111 factory()->NewArrayLiteral(property_funcs, funcs_idx, kNoSourcePosition),
5112 zone());
5113 define_class_args->Add(
5114 factory()->NewArrayLiteral(property_infos, infos_idx, kNoSourcePosition),
5115 zone());
5116
5117 define_class_args->Add(factory()->NewNumberLiteral(pos, kNoSourcePosition),
5118 zone());
5119 define_class_args->Add(
5120 factory()->NewNumberLiteral(end_pos, kNoSourcePosition), zone());
5121
5122 Expression* define_class_call = factory()->NewCallRuntime(
5123 Runtime::kDefineClass, define_class_args, kNoSourcePosition);
5124
5125 // Set the constructor to have fast properties.
5126 ZoneList<Expression*>* fast_properties_args =
5127 new (zone()) ZoneList<Expression*>(1, zone());
5128 fast_properties_args->Add(define_class_call, zone());
5129
5130 Expression* fast_properties_call = factory()->NewCallRuntime(
5131 Runtime::kToFastProperties, fast_properties_args, kNoSourcePosition);
5132
5133 if (name != nullptr) {
5134 DCHECK_NOT_NULL(proxy);
5135 // Init the variable representing the class name only after evaluating all
5136 // property names.
5137 Expression* name_assignment = factory()->NewAssignment(
5138 Token::INIT, proxy, fast_properties_call, end_pos);
5139
5140 do_block->statements()->Add(
5141 factory()->NewExpressionStatement(name_assignment, end_pos), zone());
5142 } else {
5143 do_block->statements()->Add(factory()->NewExpressionStatement(
5144 fast_properties_call, kNoSourcePosition),
5145 zone());
5146 }
5147
5148 Variable* result = scope_->NewTemporary(ast_value_factory()->empty_string());
5149 DoExpression* expr = factory()->NewDoExpression(do_block, result, pos);
5150
5151 Rewriter::Rewrite(this, expr,
5152 ast_value_factory()); // TODO(bakkot) This is just going to
5153 // turn the final ExpressionStatement
5154 // into an assignment to result; we
5155 // could do that ourselves slightly
5156 // cheaper.
5157
5158 // This enables function name inference.
5159 expr->set_represented_function(constructor);
5160
5161 return expr;
5039 } 5162 }
5040 5163
5041 5164
5042 Expression* Parser::ParseV8Intrinsic(bool* ok) { 5165 Expression* Parser::ParseV8Intrinsic(bool* ok) {
5043 // CallRuntime :: 5166 // CallRuntime ::
5044 // '%' Identifier Arguments 5167 // '%' Identifier Arguments
5045 5168
5046 int pos = peek_position(); 5169 int pos = peek_position();
5047 Expect(Token::MOD, CHECK_OK); 5170 Expect(Token::MOD, CHECK_OK);
5048 // Allow "eval" or "arguments" for backward compatibility. 5171 // Allow "eval" or "arguments" for backward compatibility.
(...skipping 955 matching lines...) Expand 10 before | Expand all | Expand 10 after
6004 DCHECK_NOT_NULL(name); 6127 DCHECK_NOT_NULL(name);
6005 6128
6006 // Ignore "__proto__" as a name when it's being used to set the [[Prototype]] 6129 // Ignore "__proto__" as a name when it's being used to set the [[Prototype]]
6007 // of an object literal. 6130 // of an object literal.
6008 if (property->kind() == ObjectLiteralProperty::PROTOTYPE) return; 6131 if (property->kind() == ObjectLiteralProperty::PROTOTYPE) return;
6009 6132
6010 if (function != nullptr) { 6133 if (function != nullptr) {
6011 function->set_raw_name(name); 6134 function->set_raw_name(name);
6012 DCHECK_EQ(ObjectLiteralProperty::COMPUTED, property->kind()); 6135 DCHECK_EQ(ObjectLiteralProperty::COMPUTED, property->kind());
6013 } else { 6136 } else {
6014 DCHECK(value->IsClassLiteral()); 6137 DCHECK(value->IsDoExpression());
6015 DCHECK_EQ(ObjectLiteralProperty::COMPUTED, property->kind()); 6138 DCHECK_EQ(ObjectLiteralProperty::COMPUTED, property->kind());
6016 value->AsClassLiteral()->constructor()->set_raw_name(name); 6139 DCHECK_NOT_NULL(value->AsDoExpression()->represented_function());
6140 value->AsDoExpression()->represented_function()->set_raw_name(name);
6017 } 6141 }
6018 } 6142 }
6019 6143
6020 6144
6021 void ParserTraits::SetFunctionNameFromIdentifierRef(Expression* value, 6145 void ParserTraits::SetFunctionNameFromIdentifierRef(Expression* value,
6022 Expression* identifier) { 6146 Expression* identifier) {
6023 if (!value->IsAnonymousFunctionDefinition()) return; 6147 if (!value->IsAnonymousFunctionDefinition()) return;
6024 if (!identifier->IsVariableProxy()) return; 6148 if (!identifier->IsVariableProxy()) return;
6025 6149
6026 auto name = identifier->AsVariableProxy()->raw_name(); 6150 auto name = identifier->AsVariableProxy()->raw_name();
6027 DCHECK_NOT_NULL(name); 6151 DCHECK_NOT_NULL(name);
6028 6152
6029 auto function = value->AsFunctionLiteral(); 6153 auto function = value->AsFunctionLiteral();
6030 if (function != nullptr) { 6154 if (function != nullptr) {
6031 function->set_raw_name(name); 6155 function->set_raw_name(name);
6032 } else { 6156 } else {
6033 DCHECK(value->IsClassLiteral()); 6157 DCHECK(value->IsDoExpression());
6034 value->AsClassLiteral()->constructor()->set_raw_name(name); 6158 DCHECK_NOT_NULL(value->AsDoExpression()->represented_function());
6159 value->AsDoExpression()->represented_function()->set_raw_name(name);
6035 } 6160 }
6036 } 6161 }
6037 6162
6038 6163
6039 // Desugaring of yield* 6164 // Desugaring of yield*
6040 // ==================== 6165 // ====================
6041 // 6166 //
6042 // With the help of do-expressions and function.sent, we desugar yield* into a 6167 // With the help of do-expressions and function.sent, we desugar yield* into a
6043 // loop containing a "raw" yield (a yield that doesn't wrap an iterator result 6168 // loop containing a "raw" yield (a yield that doesn't wrap an iterator result
6044 // object around its argument). Concretely, "yield* iterable" turns into 6169 // object around its argument). Concretely, "yield* iterable" turns into
(...skipping 956 matching lines...) Expand 10 before | Expand all | Expand 10 after
7001 7126
7002 #ifdef DEBUG 7127 #ifdef DEBUG
7003 void Parser::Print(AstNode* node) { 7128 void Parser::Print(AstNode* node) {
7004 ast_value_factory()->Internalize(Isolate::Current()); 7129 ast_value_factory()->Internalize(Isolate::Current());
7005 node->Print(Isolate::Current()); 7130 node->Print(Isolate::Current());
7006 } 7131 }
7007 #endif // DEBUG 7132 #endif // DEBUG
7008 7133
7009 } // namespace internal 7134 } // namespace internal
7010 } // namespace v8 7135 } // namespace v8
OLDNEW
« no previous file with comments | « src/parsing/parser.h ('k') | src/parsing/parser-base.h » ('j') | src/runtime/runtime-classes.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698