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

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: 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
« no previous file with comments | « src/parsing/parser.h ('k') | src/parsing/parser-base.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 Expression* value = property->value();
5018 int property_position = value->position();
5019
5020 Expression* property_key;
5021
5022 if (property_name != nullptr) {
5023 // For static keys, no ToName call is necessary.
5024 if (property->key()->IsPropertyName()) {
5025 property_key = property->key();
5026 } else {
5027 property_key =
5028 factory()->NewStringLiteral(property_name, property_position);
5029 }
5030 } else {
5031 ZoneList<Expression*>* to_name_args =
5032 new (zone()) ZoneList<Expression*>(1, zone());
5033 to_name_args->Add(property->key(), zone());
5034
5035 property_key = factory()->NewCallRuntime(
5036 Runtime::kInlineToName, to_name_args, property_position);
5037 }
5038
5039 int info = property->is_static() ? kIsStaticMask : 0;
5040 switch (property->kind()) {
5041 case ObjectLiteral::Property::CONSTANT:
5042 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
5043 case ObjectLiteral::Property::PROTOTYPE:
5044 UNREACHABLE();
5045 case ObjectLiteral::Property::COMPUTED:
5046 break;
5047
5048 case ObjectLiteral::Property::GETTER:
5049 info |= kIsAccessorMask;
5050 break;
5051
5052 case ObjectLiteral::Property::SETTER:
5053 info |= kIsAccessorMask | kIsSetterMask;
5054 break;
5055 }
5056
5057 property_names->Add(property_key, zone());
5058 property_funcs->Add(value, zone());
5059 property_infos->Add(factory()->NewNumberLiteral(info, kNoSourcePosition),
5060 zone());
5011 } 5061 }
5012 5062
5013 if (fni_ != NULL) fni_->Infer(); 5063 if (fni_ != NULL) fni_->Infer();
5014 5064
5015 if (property_name != ast_value_factory()->constructor_string()) { 5065 if (property_name != ast_value_factory()->constructor_string()) {
5016 SetFunctionNameFromPropertyName(property, property_name); 5066 SetFunctionNameFromPropertyName(property, property_name);
5017 } 5067 }
5018 } 5068 }
5019 5069
5020 Expect(Token::RBRACE, CHECK_OK); 5070 Expect(Token::RBRACE, CHECK_OK);
5021 int end_pos = scanner()->location().end_pos; 5071 int end_pos = scanner()->location().end_pos;
5022 5072
5023 if (constructor == NULL) { 5073 if (constructor == NULL) {
5024 constructor = DefaultConstructor(name, has_extends, block_scope, pos, 5074 constructor = DefaultConstructor(name, has_extends, block_scope, pos,
5025 end_pos, block_scope->language_mode()); 5075 end_pos, block_scope->language_mode());
5026 } 5076 }
5027 5077
5028 // Note that we do not finalize this block scope because it is 5078 // Note that we do not finalize this block scope because it is
5029 // used as a sentinel value indicating an anonymous class. 5079 // used as a sentinel value indicating an anonymous class.
5030 block_scope->set_end_position(end_pos); 5080 block_scope->set_end_position(end_pos);
5031 5081
5032 if (name != NULL) { 5082 if (name != NULL) {
5033 DCHECK_NOT_NULL(proxy); 5083 DCHECK_NOT_NULL(proxy);
5034 proxy->var()->set_initializer_position(end_pos); 5084 proxy->var()->set_initializer_position(end_pos);
5035 } 5085 }
5036 5086
5037 return factory()->NewClassLiteral(block_scope, proxy, extends, constructor, 5087 // Construct a DoExpression representing the class literal.
5038 properties, pos, end_pos); 5088 Block* do_block = factory()->NewBlock(nullptr, 16, false, pos);
adamk 2016/07/14 22:00:47 s/16/1/ I think (looks like this block only contai
bakkot 2016/07/14 22:46:01 Done.
5089 do_block->set_scope(scope_);
5090
5091 // Call DefineClass. It takes seven arguments:
5092 // 1. The superclass constructor, or the Hole if not present.
5093 // 2. The constructor function.
5094 // 3. An array of method names.
5095 // 4. An array of said method's corresponding functions.
5096 // 5. An array of flags signalling if they are accessors and/or static.
5097 // 6. The location where the class's source starts.
5098 // 7. The location where the class's source ends.
5099 ZoneList<Expression*>* define_class_args =
5100 new (zone()) ZoneList<Expression*>(7, zone());
5101 define_class_args->Add(extends != nullptr
5102 ? extends
5103 : factory()->NewTheHoleLiteral(kNoSourcePosition),
5104 zone());
5105 define_class_args->Add(constructor, zone());
5106
5107 int names_idx = function_state_->NextMaterializedLiteralIndex();
5108 int funcs_idx = function_state_->NextMaterializedLiteralIndex();
5109 int infos_idx = function_state_->NextMaterializedLiteralIndex();
5110
5111 define_class_args->Add(
5112 factory()->NewArrayLiteral(property_names, names_idx, kNoSourcePosition),
5113 zone());
5114 define_class_args->Add(
5115 factory()->NewArrayLiteral(property_funcs, funcs_idx, kNoSourcePosition),
5116 zone());
5117 define_class_args->Add(
5118 factory()->NewArrayLiteral(property_infos, infos_idx, kNoSourcePosition),
5119 zone());
5120
5121 define_class_args->Add(factory()->NewNumberLiteral(pos, kNoSourcePosition),
5122 zone());
5123 define_class_args->Add(
5124 factory()->NewNumberLiteral(end_pos, kNoSourcePosition), zone());
5125
5126 Expression* define_class_call = factory()->NewCallRuntime(
5127 Runtime::kDefineClass, define_class_args, kNoSourcePosition);
5128
5129 // Set the constructor to have fast properties.
5130 ZoneList<Expression*>* fast_properties_args =
5131 new (zone()) ZoneList<Expression*>(1, zone());
5132 fast_properties_args->Add(define_class_call, zone());
5133
5134 Expression* fast_properties_call = factory()->NewCallRuntime(
adamk 2016/07/14 22:00:47 Probably worth adding a comment that kToFastProper
5135 Runtime::kToFastProperties, fast_properties_args, kNoSourcePosition);
5136
5137 if (name != nullptr) {
5138 DCHECK_NOT_NULL(proxy);
5139 // Init the variable representing the class name only after evaluating all
5140 // property names.
5141 Expression* name_assignment = factory()->NewAssignment(
5142 Token::INIT, proxy, fast_properties_call, end_pos);
5143
5144 do_block->statements()->Add(
5145 factory()->NewExpressionStatement(name_assignment, end_pos), zone());
5146 } else {
5147 do_block->statements()->Add(factory()->NewExpressionStatement(
5148 fast_properties_call, kNoSourcePosition),
5149 zone());
5150 }
5151
5152 Variable* result = scope_->NewTemporary(ast_value_factory()->empty_string());
5153 DoExpression* expr = factory()->NewDoExpression(do_block, result, pos);
5154
5155 Rewriter::Rewrite(this, expr,
5156 ast_value_factory()); // TODO(bakkot) This is just going to
5157 // turn the final ExpressionStatement
5158 // into an assignment to result; we
5159 // could do that ourselves slightly
5160 // cheaper.
5161
5162 // This enables function name inference.
5163 expr->set_represented_function(constructor);
5164
5165 return expr;
5039 } 5166 }
5040 5167
5041 5168
5042 Expression* Parser::ParseV8Intrinsic(bool* ok) { 5169 Expression* Parser::ParseV8Intrinsic(bool* ok) {
5043 // CallRuntime :: 5170 // CallRuntime ::
5044 // '%' Identifier Arguments 5171 // '%' Identifier Arguments
5045 5172
5046 int pos = peek_position(); 5173 int pos = peek_position();
5047 Expect(Token::MOD, CHECK_OK); 5174 Expect(Token::MOD, CHECK_OK);
5048 // Allow "eval" or "arguments" for backward compatibility. 5175 // Allow "eval" or "arguments" for backward compatibility.
(...skipping 955 matching lines...) Expand 10 before | Expand all | Expand 10 after
6004 DCHECK_NOT_NULL(name); 6131 DCHECK_NOT_NULL(name);
6005 6132
6006 // Ignore "__proto__" as a name when it's being used to set the [[Prototype]] 6133 // Ignore "__proto__" as a name when it's being used to set the [[Prototype]]
6007 // of an object literal. 6134 // of an object literal.
6008 if (property->kind() == ObjectLiteralProperty::PROTOTYPE) return; 6135 if (property->kind() == ObjectLiteralProperty::PROTOTYPE) return;
6009 6136
6010 if (function != nullptr) { 6137 if (function != nullptr) {
6011 function->set_raw_name(name); 6138 function->set_raw_name(name);
6012 DCHECK_EQ(ObjectLiteralProperty::COMPUTED, property->kind()); 6139 DCHECK_EQ(ObjectLiteralProperty::COMPUTED, property->kind());
6013 } else { 6140 } else {
6014 DCHECK(value->IsClassLiteral()); 6141 DCHECK(value->IsDoExpression());
6015 DCHECK_EQ(ObjectLiteralProperty::COMPUTED, property->kind()); 6142 DCHECK_EQ(ObjectLiteralProperty::COMPUTED, property->kind());
6016 value->AsClassLiteral()->constructor()->set_raw_name(name); 6143 DCHECK_NOT_NULL(value->AsDoExpression()->represented_function());
6144 value->AsDoExpression()->represented_function()->set_raw_name(name);
6017 } 6145 }
6018 } 6146 }
6019 6147
6020 6148
6021 void ParserTraits::SetFunctionNameFromIdentifierRef(Expression* value, 6149 void ParserTraits::SetFunctionNameFromIdentifierRef(Expression* value,
6022 Expression* identifier) { 6150 Expression* identifier) {
6023 if (!value->IsAnonymousFunctionDefinition()) return; 6151 if (!value->IsAnonymousFunctionDefinition()) return;
6024 if (!identifier->IsVariableProxy()) return; 6152 if (!identifier->IsVariableProxy()) return;
6025 6153
6026 auto name = identifier->AsVariableProxy()->raw_name(); 6154 auto name = identifier->AsVariableProxy()->raw_name();
6027 DCHECK_NOT_NULL(name); 6155 DCHECK_NOT_NULL(name);
6028 6156
6029 auto function = value->AsFunctionLiteral(); 6157 auto function = value->AsFunctionLiteral();
6030 if (function != nullptr) { 6158 if (function != nullptr) {
6031 function->set_raw_name(name); 6159 function->set_raw_name(name);
6032 } else { 6160 } else {
6033 DCHECK(value->IsClassLiteral()); 6161 DCHECK(value->IsDoExpression());
6034 value->AsClassLiteral()->constructor()->set_raw_name(name); 6162 DCHECK_NOT_NULL(value->AsDoExpression()->represented_function());
6163 value->AsDoExpression()->represented_function()->set_raw_name(name);
6035 } 6164 }
6036 } 6165 }
6037 6166
6038 6167
6039 // Desugaring of yield* 6168 // Desugaring of yield*
6040 // ==================== 6169 // ====================
6041 // 6170 //
6042 // With the help of do-expressions and function.sent, we desugar yield* into a 6171 // 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 6172 // loop containing a "raw" yield (a yield that doesn't wrap an iterator result
6044 // object around its argument). Concretely, "yield* iterable" turns into 6173 // object around its argument). Concretely, "yield* iterable" turns into
(...skipping 956 matching lines...) Expand 10 before | Expand all | Expand 10 after
7001 7130
7002 #ifdef DEBUG 7131 #ifdef DEBUG
7003 void Parser::Print(AstNode* node) { 7132 void Parser::Print(AstNode* node) {
7004 ast_value_factory()->Internalize(Isolate::Current()); 7133 ast_value_factory()->Internalize(Isolate::Current());
7005 node->Print(Isolate::Current()); 7134 node->Print(Isolate::Current());
7006 } 7135 }
7007 #endif // DEBUG 7136 #endif // DEBUG
7008 7137
7009 } // namespace internal 7138 } // namespace internal
7010 } // namespace v8 7139 } // namespace v8
OLDNEW
« no previous file with comments | « 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