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

Side by Side Diff: src/parsing/parser-base.h

Issue 2188153002: Speed up parsing w/ grammar shortcut. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fix PreParserTraits::EmptyExpression Created 4 years, 4 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.cc ('k') | src/parsing/preparser.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 #ifndef V8_PARSING_PARSER_BASE_H 5 #ifndef V8_PARSING_PARSER_BASE_H
6 #define V8_PARSING_PARSER_BASE_H 6 #define V8_PARSING_PARSER_BASE_H
7 7
8 #include "src/ast/scopes.h" 8 #include "src/ast/scopes.h"
9 #include "src/bailout-reason.h" 9 #include "src/bailout-reason.h"
10 #include "src/base/hashmap.h" 10 #include "src/base/hashmap.h"
(...skipping 1059 matching lines...) Expand 10 before | Expand all | Expand 10 after
1070 ExpressionClassifier* classifier, bool* ok); 1070 ExpressionClassifier* classifier, bool* ok);
1071 typename Traits::Type::ExpressionList ParseArguments( 1071 typename Traits::Type::ExpressionList ParseArguments(
1072 Scanner::Location* first_spread_pos, ExpressionClassifier* classifier, 1072 Scanner::Location* first_spread_pos, ExpressionClassifier* classifier,
1073 bool* ok) { 1073 bool* ok) {
1074 return ParseArguments(first_spread_pos, false, classifier, ok); 1074 return ParseArguments(first_spread_pos, false, classifier, ok);
1075 } 1075 }
1076 1076
1077 ExpressionT ParseAssignmentExpression(bool accept_IN, 1077 ExpressionT ParseAssignmentExpression(bool accept_IN,
1078 ExpressionClassifier* classifier, 1078 ExpressionClassifier* classifier,
1079 bool* ok); 1079 bool* ok);
1080 ExpressionT ParseTrivialAssignmentExpression(ExpressionClassifier* classifier,
1081 bool* ok);
1080 ExpressionT ParseYieldExpression(bool accept_IN, 1082 ExpressionT ParseYieldExpression(bool accept_IN,
1081 ExpressionClassifier* classifier, bool* ok); 1083 ExpressionClassifier* classifier, bool* ok);
1082 ExpressionT ParseTailCallExpression(ExpressionClassifier* classifier, 1084 ExpressionT ParseTailCallExpression(ExpressionClassifier* classifier,
1083 bool* ok); 1085 bool* ok);
1084 ExpressionT ParseConditionalExpression(bool accept_IN, 1086 ExpressionT ParseConditionalExpression(bool accept_IN,
1085 ExpressionClassifier* classifier, 1087 ExpressionClassifier* classifier,
1086 bool* ok); 1088 bool* ok);
1087 ExpressionT ParseBinaryExpression(int prec, bool accept_IN, 1089 ExpressionT ParseBinaryExpression(int prec, bool accept_IN,
1088 ExpressionClassifier* classifier, bool* ok); 1090 ExpressionClassifier* classifier, bool* ok);
1089 ExpressionT ParseUnaryExpression(ExpressionClassifier* classifier, bool* ok); 1091 ExpressionT ParseUnaryExpression(ExpressionClassifier* classifier, bool* ok);
(...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after
1543 switch (peek()) { 1545 switch (peek()) {
1544 case Token::THIS: { 1546 case Token::THIS: {
1545 BindingPatternUnexpectedToken(classifier); 1547 BindingPatternUnexpectedToken(classifier);
1546 Consume(Token::THIS); 1548 Consume(Token::THIS);
1547 return this->ThisExpression(scope(), factory(), beg_pos); 1549 return this->ThisExpression(scope(), factory(), beg_pos);
1548 } 1550 }
1549 1551
1550 case Token::NULL_LITERAL: 1552 case Token::NULL_LITERAL:
1551 case Token::TRUE_LITERAL: 1553 case Token::TRUE_LITERAL:
1552 case Token::FALSE_LITERAL: 1554 case Token::FALSE_LITERAL:
1553 BindingPatternUnexpectedToken(classifier);
1554 return this->ExpressionFromLiteral(Next(), beg_pos, scanner(), factory());
1555 case Token::SMI: 1555 case Token::SMI:
1556 case Token::NUMBER: 1556 case Token::NUMBER:
1557 BindingPatternUnexpectedToken(classifier); 1557 BindingPatternUnexpectedToken(classifier);
1558 return this->ExpressionFromLiteral(Next(), beg_pos, scanner(), factory()); 1558 return this->ExpressionFromLiteral(Next(), beg_pos, scanner(), factory());
1559 1559
1560 case Token::ASYNC: 1560 case Token::ASYNC:
1561 if (allow_harmony_async_await() && 1561 if (allow_harmony_async_await() &&
1562 !scanner()->HasAnyLineTerminatorAfterNext() && 1562 !scanner()->HasAnyLineTerminatorAfterNext() &&
1563 PeekAhead() == Token::FUNCTION) { 1563 PeekAhead() == Token::FUNCTION) {
1564 Consume(Token::ASYNC); 1564 Consume(Token::ASYNC);
(...skipping 705 matching lines...) Expand 10 before | Expand all | Expand 10 after
2270 2270
2271 return result; 2271 return result;
2272 } 2272 }
2273 2273
2274 // Precedence = 2 2274 // Precedence = 2
2275 template <class Traits> 2275 template <class Traits>
2276 typename ParserBase<Traits>::ExpressionT 2276 typename ParserBase<Traits>::ExpressionT
2277 ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, 2277 ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN,
2278 ExpressionClassifier* classifier, 2278 ExpressionClassifier* classifier,
2279 bool* ok) { 2279 bool* ok) {
2280 // Try to parse a simple sub-grammar and early-out if successful.
2281 typename ParserBase<Traits>::ExpressionT trivial_result =
2282 this->ParseTrivialAssignmentExpression(classifier, ok);
2283 if (!Traits::IsEmptyExpression(trivial_result)) return trivial_result;
marja 2016/07/29 07:56:04 Ah right, since we have 2 expression types, this c
vogelheim 2016/08/09 11:26:08 Done. (2nd version)
2284
2280 // AssignmentExpression :: 2285 // AssignmentExpression ::
2281 // ConditionalExpression 2286 // ConditionalExpression
2282 // ArrowFunction 2287 // ArrowFunction
2283 // YieldExpression 2288 // YieldExpression
2284 // LeftHandSideExpression AssignmentOperator AssignmentExpression 2289 // LeftHandSideExpression AssignmentOperator AssignmentExpression
2285 bool is_destructuring_assignment = false; 2290 bool is_destructuring_assignment = false;
2286 int lhs_beg_pos = peek_position(); 2291 int lhs_beg_pos = peek_position();
2287 2292
2288 if (peek() == Token::YIELD && is_generator()) { 2293 if (peek() == Token::YIELD && is_generator()) {
2289 return this->ParseYieldExpression(accept_IN, classifier, ok); 2294 return this->ParseYieldExpression(accept_IN, classifier, ok);
2290 } 2295 }
2291 2296
2292 FuncNameInferrer::State fni_state(fni_); 2297 FuncNameInferrer::State fni_state(fni_);
2293 ParserBase<Traits>::Checkpoint checkpoint(this); 2298 ParserBase<Traits>::Checkpoint checkpoint(this);
2294 ExpressionClassifier arrow_formals_classifier(this, 2299 ExpressionClassifier arrow_formals_classifier(this,
2295 classifier->duplicate_finder()); 2300 classifier->duplicate_finder());
2296 2301
2297 bool is_async = allow_harmony_async_await() && peek() == Token::ASYNC && 2302 bool is_async = allow_harmony_async_await() && peek() == Token::ASYNC &&
2298 !scanner()->HasAnyLineTerminatorAfterNext() && 2303 !scanner()->HasAnyLineTerminatorAfterNext() &&
2299 IsValidArrowFormalParametersStart(PeekAhead()); 2304 IsValidArrowFormalParametersStart(PeekAhead());
2300 2305
2301 bool parenthesized_formals = peek() == Token::LPAREN; 2306 bool parenthesized_formals = peek() == Token::LPAREN;
2302 if (!is_async && !parenthesized_formals) { 2307 if (!is_async && !parenthesized_formals) {
2303 ArrowFormalParametersUnexpectedToken(&arrow_formals_classifier); 2308 ArrowFormalParametersUnexpectedToken(&arrow_formals_classifier);
2304 } 2309 }
2305 ExpressionT expression = this->ParseConditionalExpression( 2310 ExpressionT expression = this->ParseConditionalExpression(
adamk 2016/07/28 17:51:55 What if, rather than putting ParseTrivialAssignmen
vogelheim 2016/08/09 11:26:08 Well... it would also do a lot of work that I'm no
adamk 2016/08/09 16:39:16 But we'd still be skipping the function calls, rig
2306 accept_IN, &arrow_formals_classifier, CHECK_OK); 2311 accept_IN, &arrow_formals_classifier, CHECK_OK);
2307 2312
2308 if (is_async && peek_any_identifier() && PeekAhead() == Token::ARROW) { 2313 if (is_async && peek_any_identifier() && PeekAhead() == Token::ARROW) {
2309 // async Identifier => AsyncConciseBody 2314 // async Identifier => AsyncConciseBody
2310 IdentifierT name = 2315 IdentifierT name =
2311 ParseAndClassifyIdentifier(&arrow_formals_classifier, CHECK_OK); 2316 ParseAndClassifyIdentifier(&arrow_formals_classifier, CHECK_OK);
2312 expression = this->ExpressionFromIdentifier( 2317 expression = this->ExpressionFromIdentifier(
2313 name, position(), scanner()->location().end_pos, scope(), factory()); 2318 name, position(), scanner()->location().end_pos, scope(), factory());
2314 } 2319 }
2315 2320
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
2458 if (is_destructuring_assignment) { 2463 if (is_destructuring_assignment) {
2459 result = factory()->NewRewritableExpression(result); 2464 result = factory()->NewRewritableExpression(result);
2460 Traits::QueueDestructuringAssignmentForRewriting(result); 2465 Traits::QueueDestructuringAssignmentForRewriting(result);
2461 } 2466 }
2462 2467
2463 return result; 2468 return result;
2464 } 2469 }
2465 2470
2466 template <class Traits> 2471 template <class Traits>
2467 typename ParserBase<Traits>::ExpressionT 2472 typename ParserBase<Traits>::ExpressionT
2473 ParserBase<Traits>::ParseTrivialAssignmentExpression(
2474 ExpressionClassifier* classifier, bool* ok) {
2475 // Parser shortcut: The following scope is a micro-optimization to reduce
adamk 2016/07/28 17:51:55 This can be rewritten now that it's in its own fun
vogelheim 2016/08/09 11:26:08 Done.
2476 // parsing time. It should be functionally neutral and deliver either nullptr
2477 // or the same result as the canonical ParseAssignmentExpression.
2478 // When we encounter
2479 // [SMI|NUMBER|{NULL,TRUE,FALSE}_LITERAL|THIS|STRING|IDENTIFIER]
2480 // followed by
2481 // [COMMA|RPAREN|RBRACK|SEMICOLON]
2482 // then this will result in a single AST node. Instead of parsing this
2483 // 'properly' (a call chain 11-levels deep), we will just generate the
2484 // appropriate AST nodes right here.
2485 Token::Value peek_token = peek();
2486 bool is_number = peek_token == Token::SMI || peek_token == Token::NUMBER;
2487 bool is_literal = peek_token == Token::NULL_LITERAL ||
2488 peek_token == Token::TRUE_LITERAL ||
2489 peek_token == Token::FALSE_LITERAL;
2490 bool is_string = peek_token == Token::STRING;
2491 bool is_identifier = peek_token == Token::IDENTIFIER;
2492 bool is_this = peek_token == Token::THIS;
2493 if (is_number || is_literal || is_string || is_identifier || is_this) {
2494 // PeekAhead() is expensive & may not always be called, so we only call it
2495 // after checking peek().
2496 Token::Value peek_ahead = PeekAhead();
2497 if (peek_ahead == Token::COMMA || peek_ahead == Token::RPAREN ||
2498 peek_ahead == Token::SEMICOLON || peek_ahead == Token::RBRACK) {
2499 Scanner::Location pos = scanner()->peek_location();
2500 if (is_string) {
2501 FuncNameInferrer::State fni_state(fni_);
2502 classifier->RecordBindingPatternError(
2503 pos, MessageTemplate::kUnexpectedTokenString);
2504 Consume(Token::STRING);
2505 return this->ExpressionFromString(pos.beg_pos, scanner(), factory());
2506 } else if (is_this) {
2507 classifier->RecordBindingPatternError(
2508 pos, MessageTemplate::kUnexpectedToken, Token::Name(Token::THIS));
2509 Consume(Token::THIS);
2510 return this->ThisExpression(scope(), factory(), pos.beg_pos);
2511 } else if (is_number) {
2512 classifier->RecordBindingPatternError(
2513 pos, MessageTemplate::kUnexpectedTokenNumber);
2514 Consume(peek_token);
2515 return this->ExpressionFromLiteral(peek_token, pos.beg_pos, scanner(),
2516 factory());
2517 } else if (is_literal) {
2518 classifier->RecordBindingPatternError(
2519 pos, MessageTemplate::kUnexpectedToken, Token::Name(peek_token));
2520 Consume(peek_token);
2521 return this->ExpressionFromLiteral(peek_token, pos.beg_pos, scanner(),
2522 factory());
2523 } else if (is_identifier) {
2524 FuncNameInferrer::State fni_state(fni_);
2525 ExpressionClassifier arrow_formals_classifier(
2526 this, classifier->duplicate_finder());
2527 IdentifierT name =
2528 ParseAndClassifyIdentifier(&arrow_formals_classifier, CHECK_OK);
2529 typename ParserBase<Traits>::ExpressionT shortcut_result =
2530 this->ExpressionFromIdentifier(name, pos.beg_pos, pos.end_pos,
2531 scope(), factory());
2532 if (this->IsAssignableIdentifier(shortcut_result)) {
2533 arrow_formals_classifier.ForgiveAssignmentPatternError();
2534 }
2535 classifier->Accumulate(
2536 &arrow_formals_classifier,
2537 ExpressionClassifier::StandardProductions |
2538 ExpressionClassifier::FormalParametersProductions |
2539 ExpressionClassifier::CoverInitializedNameProduction |
2540 ExpressionClassifier::AsyncArrowFormalParametersProduction |
2541 ExpressionClassifier::AsyncBindingPatternProduction,
2542 false);
2543 DCHECK(!Token::IsAssignmentOp(peek_ahead));
2544 classifier->MergeNonPatterns(&arrow_formals_classifier);
2545 return shortcut_result;
2546 } else {
2547 UNREACHABLE();
2548 }
2549 }
2550 }
2551 // No applicable shortcut found: Proceed w/ regular parsing.
2552 return this->EmptyExpression();
2553 }
2554
2555 template <class Traits>
2556 typename ParserBase<Traits>::ExpressionT
2468 ParserBase<Traits>::ParseYieldExpression(bool accept_IN, 2557 ParserBase<Traits>::ParseYieldExpression(bool accept_IN,
2469 ExpressionClassifier* classifier, 2558 ExpressionClassifier* classifier,
2470 bool* ok) { 2559 bool* ok) {
2471 // YieldExpression :: 2560 // YieldExpression ::
2472 // 'yield' ([no line terminator] '*'? AssignmentExpression)? 2561 // 'yield' ([no line terminator] '*'? AssignmentExpression)?
2473 int pos = peek_position(); 2562 int pos = peek_position();
2474 classifier->RecordPatternError(scanner()->peek_location(), 2563 classifier->RecordPatternError(scanner()->peek_location(),
2475 MessageTemplate::kInvalidDestructuringTarget); 2564 MessageTemplate::kInvalidDestructuringTarget);
2476 classifier->RecordFormalParameterInitializerError( 2565 classifier->RecordFormalParameterInitializerError(
2477 scanner()->peek_location(), MessageTemplate::kYieldInParameter); 2566 scanner()->peek_location(), MessageTemplate::kYieldInParameter);
(...skipping 1219 matching lines...) Expand 10 before | Expand all | Expand 10 after
3697 has_seen_constructor_ = true; 3786 has_seen_constructor_ = true;
3698 return; 3787 return;
3699 } 3788 }
3700 } 3789 }
3701 3790
3702 3791
3703 } // namespace internal 3792 } // namespace internal
3704 } // namespace v8 3793 } // namespace v8
3705 3794
3706 #endif // V8_PARSING_PARSER_BASE_H 3795 #endif // V8_PARSING_PARSER_BASE_H
OLDNEW
« no previous file with comments | « src/parsing/parser.cc ('k') | src/parsing/preparser.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698