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

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

Issue 2297733002: [parser] Refactor bookmark in SkipLazyFunctionBody (Closed)
Patch Set: Fix error with UNREACHABLE Created 4 years, 3 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 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
119 119
120 120
121 // ---------------------------------------------------------------------------- 121 // ----------------------------------------------------------------------------
122 // The CHECK_OK macro is a convenient macro to enforce error 122 // The CHECK_OK macro is a convenient macro to enforce error
123 // handling for functions that may fail (by returning !*ok). 123 // handling for functions that may fail (by returning !*ok).
124 // 124 //
125 // CAUTION: This macro appends extra statements after a call, 125 // CAUTION: This macro appends extra statements after a call,
126 // thus it must never be used where only a single statement 126 // thus it must never be used where only a single statement
127 // is correct (e.g. an if statement branch w/o braces)! 127 // is correct (e.g. an if statement branch w/o braces)!
128 128
129 #define CHECK_OK_CUSTOM(x) ok); \ 129 #define CHECK_OK_CUSTOM(x, ...) ok); \
130 if (!*ok) return impl()->x(); \ 130 if (!*ok) return impl()->x(__VA_ARGS__); \
131 ((void)0 131 ((void)0
132 #define DUMMY ) // to make indentation work 132 #define DUMMY ) // to make indentation work
133 #undef DUMMY 133 #undef DUMMY
134 134
135 // Used in functions where the return type is ExpressionT. 135 // Used in functions where the return type is ExpressionT.
136 #define CHECK_OK CHECK_OK_CUSTOM(EmptyExpression) 136 #define CHECK_OK CHECK_OK_CUSTOM(EmptyExpression)
137 137
138 // Common base class template shared between parser and pre-parser. 138 // Common base class template shared between parser and pre-parser.
139 // The Impl parameter is the actual class of the parser/pre-parser, 139 // The Impl parameter is the actual class of the parser/pre-parser,
140 // following the Curiously Recurring Template Pattern (CRTP). 140 // following the Curiously Recurring Template Pattern (CRTP).
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
266 266
267 uintptr_t stack_limit() const { return stack_limit_; } 267 uintptr_t stack_limit() const { return stack_limit_; }
268 268
269 void set_stack_limit(uintptr_t stack_limit) { stack_limit_ = stack_limit; } 269 void set_stack_limit(uintptr_t stack_limit) { stack_limit_ = stack_limit; }
270 270
271 Zone* zone() const { return zone_; } 271 Zone* zone() const { return zone_; }
272 272
273 protected: 273 protected:
274 friend class v8::internal::ExpressionClassifier<ParserTypes<Impl>>; 274 friend class v8::internal::ExpressionClassifier<ParserTypes<Impl>>;
275 275
276 // clang-format off
276 enum AllowRestrictedIdentifiers { 277 enum AllowRestrictedIdentifiers {
277 kAllowRestrictedIdentifiers, 278 kAllowRestrictedIdentifiers,
278 kDontAllowRestrictedIdentifiers 279 kDontAllowRestrictedIdentifiers
279 }; 280 };
280 281
281 enum Mode { 282 enum Mode {
282 PARSE_LAZILY, 283 PARSE_LAZILY,
283 PARSE_EAGERLY 284 PARSE_EAGERLY
284 }; 285 };
285 286
287 enum LazyParsingResult {
288 kLazyParsingComplete,
289 kLazyParsingAborted
290 };
291
286 enum VariableDeclarationContext { 292 enum VariableDeclarationContext {
287 kStatementListItem, 293 kStatementListItem,
288 kStatement, 294 kStatement,
289 kForStatement 295 kForStatement
290 }; 296 };
297 // clang-format on
291 298
292 class Checkpoint; 299 class Checkpoint;
293 class ObjectLiteralCheckerBase; 300 class ObjectLiteralCheckerBase;
294 301
295 // --------------------------------------------------------------------------- 302 // ---------------------------------------------------------------------------
296 // ScopeState and its subclasses implement the parser's scope stack. 303 // ScopeState and its subclasses implement the parser's scope stack.
297 // ScopeState keeps track of the current scope, and the outer ScopeState. The 304 // ScopeState keeps track of the current scope, and the outer ScopeState. The
298 // parser's scope_state_ points to the top ScopeState. ScopeState's 305 // parser's scope_state_ points to the top ScopeState. ScopeState's
299 // constructor push on the scope stack and the destructors pop. BlockState and 306 // constructor push on the scope stack and the destructors pop. BlockState and
300 // FunctionState are used to hold additional per-block and per-function state. 307 // FunctionState are used to hold additional per-block and per-function state.
(...skipping 477 matching lines...) Expand 10 before | Expand all | Expand 10 after
778 return; 785 return;
779 } 786 }
780 if (scanner()->HasAnyLineTerminatorBeforeNext() || 787 if (scanner()->HasAnyLineTerminatorBeforeNext() ||
781 tok == Token::RBRACE || 788 tok == Token::RBRACE ||
782 tok == Token::EOS) { 789 tok == Token::EOS) {
783 return; 790 return;
784 } 791 }
785 Expect(Token::SEMICOLON, ok); 792 Expect(Token::SEMICOLON, ok);
786 } 793 }
787 794
788 // A dummy function, just useful as an argument to CHECK_OK_CUSTOM. 795 // Dummy functions, just useful as arguments to CHECK_OK_CUSTOM.
789 static void Void() {} 796 static void Void() {}
797 template <typename T>
798 static T Return(T result) {
799 return result;
800 }
790 801
791 bool is_any_identifier(Token::Value token) { 802 bool is_any_identifier(Token::Value token) {
792 return token == Token::IDENTIFIER || token == Token::ENUM || 803 return token == Token::IDENTIFIER || token == Token::ENUM ||
793 token == Token::AWAIT || token == Token::ASYNC || 804 token == Token::AWAIT || token == Token::ASYNC ||
794 token == Token::FUTURE_STRICT_RESERVED_WORD || token == Token::LET || 805 token == Token::FUTURE_STRICT_RESERVED_WORD || token == Token::LET ||
795 token == Token::STATIC || token == Token::YIELD; 806 token == Token::STATIC || token == Token::YIELD;
796 } 807 }
797 bool peek_any_identifier() { return is_any_identifier(peek()); } 808 bool peek_any_identifier() { return is_any_identifier(peek()); }
798 809
799 bool CheckContextualKeyword(Vector<const char> keyword) { 810 bool CheckContextualKeyword(Vector<const char> keyword) {
(...skipping 13 matching lines...) Expand all
813 const char* full_name, int pos, bool* ok); 824 const char* full_name, int pos, bool* ok);
814 825
815 void ExpectContextualKeyword(Vector<const char> keyword, bool* ok) { 826 void ExpectContextualKeyword(Vector<const char> keyword, bool* ok) {
816 Expect(Token::IDENTIFIER, CHECK_OK_CUSTOM(Void)); 827 Expect(Token::IDENTIFIER, CHECK_OK_CUSTOM(Void));
817 if (!scanner()->is_literal_contextual_keyword(keyword)) { 828 if (!scanner()->is_literal_contextual_keyword(keyword)) {
818 ReportUnexpectedToken(scanner()->current_token()); 829 ReportUnexpectedToken(scanner()->current_token());
819 *ok = false; 830 *ok = false;
820 } 831 }
821 } 832 }
822 833
823 bool CheckInOrOf(ForEachStatement::VisitMode* visit_mode, bool* ok) { 834 bool CheckInOrOf(ForEachStatement::VisitMode* visit_mode) {
824 if (Check(Token::IN)) { 835 if (Check(Token::IN)) {
825 *visit_mode = ForEachStatement::ENUMERATE; 836 *visit_mode = ForEachStatement::ENUMERATE;
826 return true; 837 return true;
827 } else if (CheckContextualKeyword(CStrVector("of"))) { 838 } else if (CheckContextualKeyword(CStrVector("of"))) {
828 *visit_mode = ForEachStatement::ITERATE; 839 *visit_mode = ForEachStatement::ITERATE;
829 return true; 840 return true;
830 } 841 }
831 return false; 842 return false;
832 } 843 }
833 844
(...skipping 2643 matching lines...) Expand 10 before | Expand all | Expand 10 after
3477 bool* ok) { 3488 bool* ok) {
3478 if (peek() == Token::ARROW && scanner_->HasAnyLineTerminatorBeforeNext()) { 3489 if (peek() == Token::ARROW && scanner_->HasAnyLineTerminatorBeforeNext()) {
3479 // ASI inserts `;` after arrow parameters if a line terminator is found. 3490 // ASI inserts `;` after arrow parameters if a line terminator is found.
3480 // `=> ...` is never a valid expression, so report as syntax error. 3491 // `=> ...` is never a valid expression, so report as syntax error.
3481 // If next token is not `=>`, it's a syntax error anyways. 3492 // If next token is not `=>`, it's a syntax error anyways.
3482 ReportUnexpectedTokenAt(scanner_->peek_location(), Token::ARROW); 3493 ReportUnexpectedTokenAt(scanner_->peek_location(), Token::ARROW);
3483 *ok = false; 3494 *ok = false;
3484 return impl()->EmptyExpression(); 3495 return impl()->EmptyExpression();
3485 } 3496 }
3486 3497
3487 typename Types::StatementList body; 3498 typename Types::StatementList body = impl()->NullStatementList();
3488 int num_parameters = formal_parameters.scope->num_parameters(); 3499 int num_parameters = formal_parameters.scope->num_parameters();
3489 int materialized_literal_count = -1; 3500 int materialized_literal_count = -1;
3490 int expected_property_count = -1; 3501 int expected_property_count = -1;
3491 3502
3492 FunctionKind arrow_kind = is_async ? kAsyncArrowFunction : kArrowFunction; 3503 FunctionKind arrow_kind = is_async ? kAsyncArrowFunction : kArrowFunction;
3504 FunctionLiteral::EagerCompileHint eager_compile_hint =
3505 FunctionLiteral::kShouldLazyCompile;
3506 bool should_be_used_once_hint = false;
3493 { 3507 {
3494 FunctionState function_state(&function_state_, &scope_state_, 3508 FunctionState function_state(&function_state_, &scope_state_,
3495 formal_parameters.scope, arrow_kind); 3509 formal_parameters.scope, arrow_kind);
3496 3510
3497 function_state.SkipMaterializedLiterals( 3511 function_state.SkipMaterializedLiterals(
3498 formal_parameters.materialized_literals_count); 3512 formal_parameters.materialized_literals_count);
3499 3513
3500 impl()->ReindexLiterals(formal_parameters); 3514 impl()->ReindexLiterals(formal_parameters);
3501 3515
3502 Expect(Token::ARROW, CHECK_OK); 3516 Expect(Token::ARROW, CHECK_OK);
3503 3517
3504 if (peek() == Token::LBRACE) { 3518 if (peek() == Token::LBRACE) {
3505 // Multiple statement body 3519 // Multiple statement body
3506 Consume(Token::LBRACE); 3520 Consume(Token::LBRACE);
3507 DCHECK_EQ(scope(), formal_parameters.scope); 3521 DCHECK_EQ(scope(), formal_parameters.scope);
3508 bool is_lazily_parsed = (mode() == PARSE_LAZILY && 3522 bool is_lazily_parsed = (mode() == PARSE_LAZILY &&
3509 formal_parameters.scope->AllowsLazyParsing()); 3523 formal_parameters.scope->AllowsLazyParsing());
3510 if (is_lazily_parsed) { 3524 if (is_lazily_parsed) {
3511 body = impl()->NewStatementList(0); 3525 Scanner::BookmarkScope bookmark(scanner());
3512 impl()->SkipLazyFunctionBody(&materialized_literal_count, 3526 bool may_abort = bookmark.Set();
3513 &expected_property_count, CHECK_OK); 3527 LazyParsingResult result = impl()->SkipLazyFunctionBody(
3528 &materialized_literal_count, &expected_property_count, may_abort,
3529 CHECK_OK);
3530
3514 if (formal_parameters.materialized_literals_count > 0) { 3531 if (formal_parameters.materialized_literals_count > 0) {
3515 materialized_literal_count += 3532 materialized_literal_count +=
3516 formal_parameters.materialized_literals_count; 3533 formal_parameters.materialized_literals_count;
3517 } 3534 }
3518 } else { 3535
3536 if (result == kLazyParsingAborted) {
3537 bookmark.Reset();
3538 // Trigger eager (re-)parsing, just below this block.
3539 is_lazily_parsed = false;
3540
3541 // This is probably an initialization function. Inform the compiler it
3542 // should also eager-compile this function, and that we expect it to
3543 // be used once.
3544 eager_compile_hint = FunctionLiteral::kShouldEagerCompile;
3545 should_be_used_once_hint = true;
3546 }
3547 }
3548 if (!is_lazily_parsed) {
3519 body = impl()->ParseEagerFunctionBody( 3549 body = impl()->ParseEagerFunctionBody(
3520 impl()->EmptyIdentifier(), kNoSourcePosition, formal_parameters, 3550 impl()->EmptyIdentifier(), kNoSourcePosition, formal_parameters,
3521 arrow_kind, FunctionLiteral::kAnonymousExpression, CHECK_OK); 3551 arrow_kind, FunctionLiteral::kAnonymousExpression, CHECK_OK);
3522 materialized_literal_count = 3552 materialized_literal_count =
3523 function_state.materialized_literal_count(); 3553 function_state.materialized_literal_count();
3524 expected_property_count = function_state.expected_property_count(); 3554 expected_property_count = function_state.expected_property_count();
3525 } 3555 }
3526 } else { 3556 } else {
3527 // Single-expression body 3557 // Single-expression body
3528 int pos = position(); 3558 int pos = position();
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
3569 } 3599 }
3570 impl()->CheckConflictingVarDeclarations(formal_parameters.scope, CHECK_OK); 3600 impl()->CheckConflictingVarDeclarations(formal_parameters.scope, CHECK_OK);
3571 3601
3572 impl()->RewriteDestructuringAssignments(); 3602 impl()->RewriteDestructuringAssignments();
3573 } 3603 }
3574 3604
3575 FunctionLiteralT function_literal = factory()->NewFunctionLiteral( 3605 FunctionLiteralT function_literal = factory()->NewFunctionLiteral(
3576 impl()->EmptyIdentifierString(), formal_parameters.scope, body, 3606 impl()->EmptyIdentifierString(), formal_parameters.scope, body,
3577 materialized_literal_count, expected_property_count, num_parameters, 3607 materialized_literal_count, expected_property_count, num_parameters,
3578 FunctionLiteral::kNoDuplicateParameters, 3608 FunctionLiteral::kNoDuplicateParameters,
3579 FunctionLiteral::kAnonymousExpression, 3609 FunctionLiteral::kAnonymousExpression, eager_compile_hint, arrow_kind,
3580 FunctionLiteral::kShouldLazyCompile, arrow_kind,
3581 formal_parameters.scope->start_position()); 3610 formal_parameters.scope->start_position());
3582 3611
3583 function_literal->set_function_token_position( 3612 function_literal->set_function_token_position(
3584 formal_parameters.scope->start_position()); 3613 formal_parameters.scope->start_position());
3614 if (should_be_used_once_hint) {
3615 function_literal->set_should_be_used_once_hint();
3616 }
3585 3617
3586 if (fni_ != NULL) impl()->InferFunctionName(fni_, function_literal); 3618 if (fni_ != NULL) impl()->InferFunctionName(fni_, function_literal);
3587 3619
3588 return function_literal; 3620 return function_literal;
3589 } 3621 }
3590 3622
3591 template <typename Impl> 3623 template <typename Impl>
3592 typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseTemplateLiteral( 3624 typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseTemplateLiteral(
3593 ExpressionT tag, int start, bool* ok) { 3625 ExpressionT tag, int start, bool* ok) {
3594 // A TemplateLiteral is made up of 0 or more TEMPLATE_SPAN tokens (literal 3626 // A TemplateLiteral is made up of 0 or more TEMPLATE_SPAN tokens (literal
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
3726 void ParserBase<Impl>::CheckDestructuringElement(ExpressionT expression, 3758 void ParserBase<Impl>::CheckDestructuringElement(ExpressionT expression,
3727 int begin, int end) { 3759 int begin, int end) {
3728 if (!IsValidPattern(expression) && !expression->IsAssignment() && 3760 if (!IsValidPattern(expression) && !expression->IsAssignment() &&
3729 !IsValidReferenceExpression(expression)) { 3761 !IsValidReferenceExpression(expression)) {
3730 classifier()->RecordAssignmentPatternError( 3762 classifier()->RecordAssignmentPatternError(
3731 Scanner::Location(begin, end), 3763 Scanner::Location(begin, end),
3732 MessageTemplate::kInvalidDestructuringTarget); 3764 MessageTemplate::kInvalidDestructuringTarget);
3733 } 3765 }
3734 } 3766 }
3735 3767
3736
3737 #undef CHECK_OK 3768 #undef CHECK_OK
3738 #undef CHECK_OK_CUSTOM 3769 #undef CHECK_OK_CUSTOM
3739 3770
3740 template <typename Impl> 3771 template <typename Impl>
3741 void ParserBase<Impl>::ObjectLiteralChecker::CheckProperty( 3772 void ParserBase<Impl>::ObjectLiteralChecker::CheckProperty(
3742 Token::Value property, PropertyKind type, MethodKind method_type, 3773 Token::Value property, PropertyKind type, MethodKind method_type,
3743 bool* ok) { 3774 bool* ok) {
3744 DCHECK(!IsStaticMethod(method_type)); 3775 DCHECK(!IsStaticMethod(method_type));
3745 DCHECK(!IsSpecialMethod(method_type) || 3776 DCHECK(!IsSpecialMethod(method_type) ||
3746 type == PropertyKind::kMethodProperty); 3777 type == PropertyKind::kMethodProperty);
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
3792 has_seen_constructor_ = true; 3823 has_seen_constructor_ = true;
3793 return; 3824 return;
3794 } 3825 }
3795 } 3826 }
3796 3827
3797 3828
3798 } // namespace internal 3829 } // namespace internal
3799 } // namespace v8 3830 } // namespace v8
3800 3831
3801 #endif // V8_PARSING_PARSER_BASE_H 3832 #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