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

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

Powered by Google App Engine
This is Rietveld 408576698