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

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: non-inline ToName 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 1446 matching lines...) Expand 10 before | Expand all | Expand 10 after
2229 const AstRawString* variable_name; 2229 const AstRawString* variable_name;
2230 if (default_export && (peek() == Token::EXTENDS || peek() == Token::LBRACE)) { 2230 if (default_export && (peek() == Token::EXTENDS || peek() == Token::LBRACE)) {
2231 name = ast_value_factory()->default_string(); 2231 name = ast_value_factory()->default_string();
2232 is_strict_reserved = false; 2232 is_strict_reserved = false;
2233 variable_name = ast_value_factory()->star_default_star_string(); 2233 variable_name = ast_value_factory()->star_default_star_string();
2234 } else { 2234 } else {
2235 name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK); 2235 name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
2236 variable_name = name; 2236 variable_name = name;
2237 } 2237 }
2238 2238
2239 ClassLiteral* value = ParseClassLiteral(nullptr, name, scanner()->location(), 2239 Expression* value = ParseClassLiteral(nullptr, name, scanner()->location(),
2240 is_strict_reserved, pos, CHECK_OK); 2240 is_strict_reserved, pos, CHECK_OK);
2241 2241
2242 VariableProxy* proxy = NewUnresolved(variable_name, LET); 2242 VariableProxy* proxy = NewUnresolved(variable_name, LET);
2243 Declaration* declaration = 2243 Declaration* declaration =
2244 factory()->NewVariableDeclaration(proxy, LET, scope_, pos); 2244 factory()->NewVariableDeclaration(proxy, LET, scope_, pos);
2245 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK); 2245 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
2246 proxy->var()->set_initializer_position(position()); 2246 proxy->var()->set_initializer_position(position());
2247 Assignment* assignment = 2247 Assignment* assignment =
2248 factory()->NewAssignment(Token::INIT, proxy, value, pos); 2248 factory()->NewAssignment(Token::INIT, proxy, value, pos);
2249 Statement* assignment_statement = 2249 Statement* assignment_statement =
2250 factory()->NewExpressionStatement(assignment, kNoSourcePosition); 2250 factory()->NewExpressionStatement(assignment, kNoSourcePosition);
(...skipping 2720 matching lines...) Expand 10 before | Expand all | Expand 10 after
4971 } 4971 }
4972 PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction( 4972 PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction(
4973 language_mode(), function_state_->kind(), scope_->has_simple_parameters(), 4973 language_mode(), function_state_->kind(), scope_->has_simple_parameters(),
4974 parsing_module_, logger, bookmark, use_counts_); 4974 parsing_module_, logger, bookmark, use_counts_);
4975 if (pre_parse_timer_ != NULL) { 4975 if (pre_parse_timer_ != NULL) {
4976 pre_parse_timer_->Stop(); 4976 pre_parse_timer_->Stop();
4977 } 4977 }
4978 return result; 4978 return result;
4979 } 4979 }
4980 4980
4981 ClassLiteral* Parser::ParseClassLiteral(ExpressionClassifier* classifier, 4981 Expression* Parser::ParseClassLiteral(ExpressionClassifier* classifier,
4982 const AstRawString* name, 4982 const AstRawString* name,
4983 Scanner::Location class_name_location, 4983 Scanner::Location class_name_location,
4984 bool name_is_strict_reserved, int pos, 4984 bool name_is_strict_reserved, int pos,
4985 bool* ok) { 4985 bool* ok) {
4986 // All parts of a ClassDeclaration and ClassExpression are strict code. 4986 // All parts of a ClassDeclaration and ClassExpression are strict code.
4987 if (name_is_strict_reserved) { 4987 if (name_is_strict_reserved) {
4988 ReportMessageAt(class_name_location, 4988 ReportMessageAt(class_name_location,
4989 MessageTemplate::kUnexpectedStrictReserved); 4989 MessageTemplate::kUnexpectedStrictReserved);
4990 *ok = false; 4990 *ok = false;
4991 return NULL; 4991 return NULL;
4992 } 4992 }
4993 if (IsEvalOrArguments(name)) { 4993 if (IsEvalOrArguments(name)) {
4994 ReportMessageAt(class_name_location, MessageTemplate::kStrictEvalArguments); 4994 ReportMessageAt(class_name_location, MessageTemplate::kStrictEvalArguments);
4995 *ok = false; 4995 *ok = false;
(...skipping 23 matching lines...) Expand all
5019 if (classifier != nullptr) { 5019 if (classifier != nullptr) {
5020 classifier->Accumulate(&extends_classifier, 5020 classifier->Accumulate(&extends_classifier,
5021 ExpressionClassifier::ExpressionProductions); 5021 ExpressionClassifier::ExpressionProductions);
5022 } 5022 }
5023 } else { 5023 } else {
5024 block_scope->set_start_position(scanner()->location().end_pos); 5024 block_scope->set_start_position(scanner()->location().end_pos);
5025 } 5025 }
5026 5026
5027 5027
5028 ClassLiteralChecker checker(this); 5028 ClassLiteralChecker checker(this);
5029 ZoneList<ObjectLiteral::Property*>* properties = NewPropertyList(4, zone());
5030 FunctionLiteral* constructor = NULL; 5029 FunctionLiteral* constructor = NULL;
5030
5031 ZoneList<Expression*>* property_names =
5032 new (zone()) ZoneList<Expression*>(4, zone());
5033 ZoneList<Expression*>* property_funcs =
5034 new (zone()) ZoneList<Expression*>(4, zone());
5035 ZoneList<Expression*>* property_infos =
5036 new (zone()) ZoneList<Expression*>(4, zone());
5037
5031 bool has_seen_constructor = false; 5038 bool has_seen_constructor = false;
5032 5039
5033 Expect(Token::LBRACE, CHECK_OK); 5040 Expect(Token::LBRACE, CHECK_OK);
5034 5041
5035 const bool has_extends = extends != nullptr; 5042 const bool has_extends = extends != nullptr;
5036 while (peek() != Token::RBRACE) { 5043 while (peek() != Token::RBRACE) {
5037 if (Check(Token::SEMICOLON)) continue; 5044 if (Check(Token::SEMICOLON)) continue;
5038 FuncNameInferrer::State fni_state(fni_); 5045 FuncNameInferrer::State fni_state(fni_);
5039 const bool in_class = true; 5046 const bool in_class = true;
5040 bool is_computed_name = false; // Classes do not care about computed 5047 bool is_computed_name = false; // Classes do not care about computed
5041 // property names here. 5048 // property names here.
5042 ExpressionClassifier property_classifier(this); 5049 ExpressionClassifier property_classifier(this);
5043 const AstRawString* property_name = nullptr; 5050 const AstRawString* property_name = nullptr;
5044 ObjectLiteral::Property* property = ParsePropertyDefinition( 5051 ObjectLiteral::Property* property = ParsePropertyDefinition(
5045 &checker, in_class, has_extends, MethodKind::Normal, &is_computed_name, 5052 &checker, in_class, has_extends, MethodKind::Normal, &is_computed_name,
5046 &has_seen_constructor, &property_classifier, &property_name, CHECK_OK); 5053 &has_seen_constructor, &property_classifier, &property_name, CHECK_OK);
5047 RewriteNonPattern(&property_classifier, CHECK_OK); 5054 RewriteNonPattern(&property_classifier, CHECK_OK);
5048 if (classifier != nullptr) { 5055 if (classifier != nullptr) {
5049 classifier->Accumulate(&property_classifier, 5056 classifier->Accumulate(&property_classifier,
5050 ExpressionClassifier::ExpressionProductions); 5057 ExpressionClassifier::ExpressionProductions);
5051 } 5058 }
5052 5059
5053 if (has_seen_constructor && constructor == NULL) { 5060 if (has_seen_constructor && constructor == NULL) {
5054 constructor = GetPropertyValue(property)->AsFunctionLiteral(); 5061 constructor = GetPropertyValue(property)->AsFunctionLiteral();
5055 DCHECK_NOT_NULL(constructor); 5062 DCHECK_NOT_NULL(constructor);
5056 constructor->set_raw_name( 5063 constructor->set_raw_name(
5057 name != nullptr ? name : ast_value_factory()->empty_string()); 5064 name != nullptr ? name : ast_value_factory()->empty_string());
5058 } else { 5065 } else {
5059 properties->Add(property, zone()); 5066 Expression* value = property->value();
5067 int property_position = value->position();
5068
5069 Expression* property_key;
5070
5071 if (property_name != nullptr) {
5072 // For static keys, no ToName call is necessary.
5073 if (property->key()->IsPropertyName()) {
5074 property_key = property->key();
5075 } else {
5076 property_key =
5077 factory()->NewStringLiteral(property_name, property_position);
5078 }
5079 } else {
5080 ZoneList<Expression*>* to_name_args =
5081 new (zone()) ZoneList<Expression*>(1, zone());
5082 to_name_args->Add(property->key(), zone());
5083
5084 property_key = factory()->NewCallRuntime(Runtime::kToName, to_name_args,
5085 property_position);
5086 }
5087
5088 int info = property->is_static() ? kIsStaticMask : 0;
5089 switch (property->kind()) {
5090 case ObjectLiteral::Property::CONSTANT:
5091 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
5092 case ObjectLiteral::Property::PROTOTYPE:
5093 UNREACHABLE();
5094 case ObjectLiteral::Property::COMPUTED:
5095 break;
5096
5097 case ObjectLiteral::Property::GETTER:
5098 info |= kIsAccessorMask;
5099 break;
5100
5101 case ObjectLiteral::Property::SETTER:
5102 info |= kIsAccessorMask | kIsSetterMask;
5103 break;
5104 }
5105
5106 property_names->Add(property_key, zone());
5107 property_funcs->Add(value, zone());
5108 property_infos->Add(factory()->NewNumberLiteral(info, kNoSourcePosition),
5109 zone());
5060 } 5110 }
5061 5111
5062 if (fni_ != NULL) fni_->Infer(); 5112 if (fni_ != NULL) fni_->Infer();
5063 5113
5064 if (property_name != ast_value_factory()->constructor_string()) { 5114 if (property_name != ast_value_factory()->constructor_string()) {
5065 SetFunctionNameFromPropertyName(property, property_name); 5115 SetFunctionNameFromPropertyName(property, property_name);
5066 } 5116 }
5067 } 5117 }
5068 5118
5069 Expect(Token::RBRACE, CHECK_OK); 5119 Expect(Token::RBRACE, CHECK_OK);
5070 int end_pos = scanner()->location().end_pos; 5120 int end_pos = scanner()->location().end_pos;
5071 5121
5072 if (constructor == NULL) { 5122 if (constructor == NULL) {
5073 constructor = DefaultConstructor(name, has_extends, block_scope, pos, 5123 constructor = DefaultConstructor(name, has_extends, block_scope, pos,
5074 end_pos, block_scope->language_mode()); 5124 end_pos, block_scope->language_mode());
5075 } 5125 }
5076 5126
5077 // Note that we do not finalize this block scope because it is 5127 // Note that we do not finalize this block scope because it is
5078 // used as a sentinel value indicating an anonymous class. 5128 // used as a sentinel value indicating an anonymous class.
5079 block_scope->set_end_position(end_pos); 5129 block_scope->set_end_position(end_pos);
5080 5130
5081 if (name != NULL) { 5131 if (name != NULL) {
5082 DCHECK_NOT_NULL(proxy); 5132 DCHECK_NOT_NULL(proxy);
5083 proxy->var()->set_initializer_position(end_pos); 5133 proxy->var()->set_initializer_position(end_pos);
5084 } 5134 }
5085 5135
5086 return factory()->NewClassLiteral(block_scope, proxy, extends, constructor, 5136 // Construct a DoExpression representing the class literal.
5087 properties, pos, end_pos); 5137 Block* do_block = factory()->NewBlock(nullptr, 16, false, pos);
5138 do_block->set_scope(scope_);
5139
5140 // Call DefineClass. It takes seven arguments:
5141 // 1. The superclass constructor, or the Hole if not present.
5142 // 2. The constructor function.
5143 // 3. An array of method names.
5144 // 4. An array of said method's corresponding functions.
5145 // 5. An array of flags signalling if they are accessors and/or static.
5146 // 6. The location where the class's source starts.
5147 // 7. The location where the class's source ends.
5148 ZoneList<Expression*>* define_class_args =
5149 new (zone()) ZoneList<Expression*>(7, zone());
5150 define_class_args->Add(extends != nullptr
5151 ? extends
5152 : factory()->NewTheHoleLiteral(kNoSourcePosition),
5153 zone());
5154 define_class_args->Add(constructor, zone());
5155
5156 int names_idx = function_state_->NextMaterializedLiteralIndex();
5157 int funcs_idx = function_state_->NextMaterializedLiteralIndex();
5158 int infos_idx = function_state_->NextMaterializedLiteralIndex();
5159
5160 define_class_args->Add(
5161 factory()->NewArrayLiteral(property_names, names_idx, kNoSourcePosition),
5162 zone());
5163 define_class_args->Add(
5164 factory()->NewArrayLiteral(property_funcs, funcs_idx, kNoSourcePosition),
5165 zone());
5166 define_class_args->Add(
5167 factory()->NewArrayLiteral(property_infos, infos_idx, kNoSourcePosition),
5168 zone());
5169
5170 define_class_args->Add(factory()->NewNumberLiteral(pos, kNoSourcePosition),
5171 zone());
5172 define_class_args->Add(
5173 factory()->NewNumberLiteral(end_pos, kNoSourcePosition), zone());
5174
5175 Expression* define_class_call = factory()->NewCallRuntime(
5176 Runtime::kDefineClass, define_class_args, kNoSourcePosition);
5177
5178 // Set the constructor to have fast properties.
5179 ZoneList<Expression*>* fast_properties_args =
5180 new (zone()) ZoneList<Expression*>(1, zone());
5181 fast_properties_args->Add(define_class_call, zone());
5182
5183 Expression* fast_properties_call = factory()->NewCallRuntime(
5184 Runtime::kToFastProperties, fast_properties_args, kNoSourcePosition);
5185
5186 if (name != nullptr) {
5187 DCHECK_NOT_NULL(proxy);
5188 // Init the variable representing the class name only after evaluating all
5189 // property names.
5190 Expression* name_assignment = factory()->NewAssignment(
5191 Token::INIT, proxy, fast_properties_call, end_pos);
5192
5193 do_block->statements()->Add(
5194 factory()->NewExpressionStatement(name_assignment, end_pos), zone());
5195 } else {
5196 do_block->statements()->Add(factory()->NewExpressionStatement(
5197 fast_properties_call, kNoSourcePosition),
5198 zone());
5199 }
5200
5201 Variable* result = scope_->NewTemporary(ast_value_factory()->empty_string());
5202 DoExpression* expr = factory()->NewDoExpression(do_block, result, pos);
5203
5204 Rewriter::Rewrite(this, expr,
5205 ast_value_factory()); // TODO(bakkot) This is just going to
5206 // turn the final ExpressionStatement
5207 // into an assignment to result; we
5208 // could do that ourselves slightly
5209 // cheaper.
5210
5211 // This enables function name inference.
5212 expr->set_represented_function(constructor);
5213
5214 return expr;
5088 } 5215 }
5089 5216
5090 5217
5091 Expression* Parser::ParseV8Intrinsic(bool* ok) { 5218 Expression* Parser::ParseV8Intrinsic(bool* ok) {
5092 // CallRuntime :: 5219 // CallRuntime ::
5093 // '%' Identifier Arguments 5220 // '%' Identifier Arguments
5094 5221
5095 int pos = peek_position(); 5222 int pos = peek_position();
5096 Expect(Token::MOD, CHECK_OK); 5223 Expect(Token::MOD, CHECK_OK);
5097 // Allow "eval" or "arguments" for backward compatibility. 5224 // Allow "eval" or "arguments" for backward compatibility.
(...skipping 955 matching lines...) Expand 10 before | Expand all | Expand 10 after
6053 DCHECK_NOT_NULL(name); 6180 DCHECK_NOT_NULL(name);
6054 6181
6055 // Ignore "__proto__" as a name when it's being used to set the [[Prototype]] 6182 // Ignore "__proto__" as a name when it's being used to set the [[Prototype]]
6056 // of an object literal. 6183 // of an object literal.
6057 if (property->kind() == ObjectLiteralProperty::PROTOTYPE) return; 6184 if (property->kind() == ObjectLiteralProperty::PROTOTYPE) return;
6058 6185
6059 if (function != nullptr) { 6186 if (function != nullptr) {
6060 function->set_raw_name(name); 6187 function->set_raw_name(name);
6061 DCHECK_EQ(ObjectLiteralProperty::COMPUTED, property->kind()); 6188 DCHECK_EQ(ObjectLiteralProperty::COMPUTED, property->kind());
6062 } else { 6189 } else {
6063 DCHECK(value->IsClassLiteral()); 6190 DCHECK(value->IsDoExpression());
6064 DCHECK_EQ(ObjectLiteralProperty::COMPUTED, property->kind()); 6191 DCHECK_EQ(ObjectLiteralProperty::COMPUTED, property->kind());
6065 value->AsClassLiteral()->constructor()->set_raw_name(name); 6192 DCHECK_NOT_NULL(value->AsDoExpression()->represented_function());
6193 value->AsDoExpression()->represented_function()->set_raw_name(name);
6066 } 6194 }
6067 } 6195 }
6068 6196
6069 6197
6070 void ParserTraits::SetFunctionNameFromIdentifierRef(Expression* value, 6198 void ParserTraits::SetFunctionNameFromIdentifierRef(Expression* value,
6071 Expression* identifier) { 6199 Expression* identifier) {
6072 if (!value->IsAnonymousFunctionDefinition()) return; 6200 if (!value->IsAnonymousFunctionDefinition()) return;
6073 if (!identifier->IsVariableProxy()) return; 6201 if (!identifier->IsVariableProxy()) return;
6074 6202
6075 auto name = identifier->AsVariableProxy()->raw_name(); 6203 auto name = identifier->AsVariableProxy()->raw_name();
6076 DCHECK_NOT_NULL(name); 6204 DCHECK_NOT_NULL(name);
6077 6205
6078 auto function = value->AsFunctionLiteral(); 6206 auto function = value->AsFunctionLiteral();
6079 if (function != nullptr) { 6207 if (function != nullptr) {
6080 function->set_raw_name(name); 6208 function->set_raw_name(name);
6081 } else { 6209 } else {
6082 DCHECK(value->IsClassLiteral()); 6210 DCHECK(value->IsDoExpression());
6083 value->AsClassLiteral()->constructor()->set_raw_name(name); 6211 DCHECK_NOT_NULL(value->AsDoExpression()->represented_function());
6212 value->AsDoExpression()->represented_function()->set_raw_name(name);
6084 } 6213 }
6085 } 6214 }
6086 6215
6087 6216
6088 // Desugaring of yield* 6217 // Desugaring of yield*
6089 // ==================== 6218 // ====================
6090 // 6219 //
6091 // With the help of do-expressions and function.sent, we desugar yield* into a 6220 // With the help of do-expressions and function.sent, we desugar yield* into a
6092 // loop containing a "raw" yield (a yield that doesn't wrap an iterator result 6221 // loop containing a "raw" yield (a yield that doesn't wrap an iterator result
6093 // object around its argument). Concretely, "yield* iterable" turns into 6222 // object around its argument). Concretely, "yield* iterable" turns into
(...skipping 956 matching lines...) Expand 10 before | Expand all | Expand 10 after
7050 7179
7051 #ifdef DEBUG 7180 #ifdef DEBUG
7052 void Parser::Print(AstNode* node) { 7181 void Parser::Print(AstNode* node) {
7053 ast_value_factory()->Internalize(Isolate::Current()); 7182 ast_value_factory()->Internalize(Isolate::Current());
7054 node->Print(Isolate::Current()); 7183 node->Print(Isolate::Current());
7055 } 7184 }
7056 #endif // DEBUG 7185 #endif // DEBUG
7057 7186
7058 } // namespace internal 7187 } // namespace internal
7059 } // namespace v8 7188 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698