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

Side by Side Diff: src/preparser.cc

Issue 641283003: Support lazy parsing of inner functions (Closed) Base URL: https://chromium.googlesource.com/external/v8.git@bleeding_edge
Patch Set: Track variable declarations in the preparser Created 6 years, 1 month 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/preparser.h ('k') | src/vector.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 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 <cmath> 5 #include <cmath>
6 6
7 #include "src/allocation.h" 7 #include "src/allocation.h"
8 #include "src/base/logging.h" 8 #include "src/base/logging.h"
9 #include "src/conversions-inl.h" 9 #include "src/conversions-inl.h"
10 #include "src/conversions.h" 10 #include "src/conversions.h"
11 #include "src/globals.h" 11 #include "src/globals.h"
12 #include "src/hashmap.h" 12 #include "src/hashmap.h"
13 #include "src/list.h" 13 #include "src/list.h"
14 #include "src/parser.h"
14 #include "src/preparse-data.h" 15 #include "src/preparse-data.h"
15 #include "src/preparse-data-format.h" 16 #include "src/preparse-data-format.h"
16 #include "src/preparser.h" 17 #include "src/preparser.h"
17 #include "src/unicode.h" 18 #include "src/unicode.h"
18 #include "src/utils.h" 19 #include "src/utils.h"
19 20
20 namespace v8 { 21 namespace v8 {
21 namespace internal { 22 namespace internal {
22 23
24 PreParserScope::~PreParserScope() {
25 if (unbound_variables_ && outer_scope_) {
26 PreParserScope* scope = outer_scope_->DeclarationScope();
27 for (ZoneHashMap::Entry* p = unbound_variables_->Start(); p != NULL;
28 p = unbound_variables_->Next(p)) {
29 AstRawString* identifier = static_cast<AstRawString*>(p->key);
30 if (!declared_variables_->Lookup(identifier, identifier->hash(), false,
31 ZoneAllocationPolicy(zone_))) {
32 scope->RecordVariableUsage(identifier);
33 }
34 }
35 }
36 }
37
38
39 PreParserScope* PreParserScope::DeclarationScope() {
40 PreParserScope* scope = this;
41 while (!scope->is_declaration_scope()) {
42 scope = scope->outer_scope();
43 }
44 return scope;
45 }
46
47
48 void PreParserScope::RecordVariableUsage(const AstRawString* identifier) {
49 if (is_declaration_scope()) {
50 ZoneAllocationPolicy allocator(zone_);
51 if (!declared_variables_->Lookup(const_cast<AstRawString*>(identifier),
52 identifier->hash(), false, allocator)) {
53 unbound_variables_->Lookup(const_cast<AstRawString*>(identifier),
54 identifier->hash(), true, allocator);
55 }
56 } else {
57 DeclarationScope()->Declare(identifier);
rossberg 2014/11/06 11:55:46 Why Declare here?
58 }
59 }
60
61
62 void PreParserScope::LogUnboundVariables(ParserRecorder* recorder) {
63 for (ZoneHashMap::Entry* p = unbound_variables_->Start(); p != NULL;
64 p = unbound_variables_->Next(p)) {
65 AstRawString* identifier = static_cast<AstRawString*>(p->key);
66 if (!declared_variables_->Lookup(identifier, identifier->hash(), false,
67 ZoneAllocationPolicy(zone_))) {
68 recorder->LogIdentifier(identifier);
69 }
70 }
71 unbound_variables_->Clear();
72 }
73
74
75 void PreParserScope::Declare(const AstRawString* identifier) {
76 if (is_declaration_scope()) {
77 DCHECK(declared_variables_);
78 declared_variables_->Lookup(const_cast<AstRawString*>(identifier),
79 identifier->hash(), true,
80 ZoneAllocationPolicy(zone_));
81 } else {
82 DeclarationScope()->Declare(identifier);
83 }
84 }
85
86
87 void PreParserTraits::RecordCurrentSymbolAsIdentifierExpression() {
88 if (pre_parser_->log_ != NULL && pre_parser_->log_identifiers_) {
89 DCHECK(pre_parser_->ast_value_factory_ != NULL);
90 const AstRawString* identifier =
91 pre_parser_->scanner()->CurrentSymbol(pre_parser_->ast_value_factory_);
92 pre_parser_->scope_->RecordVariableUsage(identifier);
93 }
94 }
95
96
23 void PreParserTraits::ReportMessageAt(Scanner::Location location, 97 void PreParserTraits::ReportMessageAt(Scanner::Location location,
24 const char* message, 98 const char* message,
25 const char* arg, 99 const char* arg,
26 bool is_reference_error) { 100 bool is_reference_error) {
27 ReportMessageAt(location.beg_pos, 101 ReportMessageAt(location.beg_pos,
28 location.end_pos, 102 location.end_pos,
29 message, 103 message,
30 arg, 104 arg,
31 is_reference_error); 105 is_reference_error);
32 } 106 }
33 107
34 108
35 void PreParserTraits::ReportMessageAt(int start_pos, 109 void PreParserTraits::ReportMessageAt(int start_pos,
36 int end_pos, 110 int end_pos,
37 const char* message, 111 const char* message,
38 const char* arg, 112 const char* arg,
39 bool is_reference_error) { 113 bool is_reference_error) {
40 pre_parser_->log_->LogMessage(start_pos, end_pos, message, arg, 114 pre_parser_->log_->LogMessage(start_pos, end_pos, message, arg,
41 is_reference_error); 115 is_reference_error);
42 } 116 }
43 117
44 118
119 void PreParserTraits::CheckPossibleEvalCall(PreParserExpression expression,
120 PreParserScope* scope) {
121 if (pre_parser_->log_ != NULL && pre_parser_->log_identifiers_ &&
122 expression.IsIdentifier() && expression.AsIdentifier().IsEval()) {
123 pre_parser_->log_->LogEvalCall();
124 }
125 }
126
127
45 PreParserIdentifier PreParserTraits::GetSymbol(Scanner* scanner) { 128 PreParserIdentifier PreParserTraits::GetSymbol(Scanner* scanner) {
46 if (scanner->current_token() == Token::FUTURE_RESERVED_WORD) { 129 if (scanner->current_token() == Token::FUTURE_RESERVED_WORD) {
47 return PreParserIdentifier::FutureReserved(); 130 return PreParserIdentifier::FutureReserved();
48 } else if (scanner->current_token() == 131 } else if (scanner->current_token() ==
49 Token::FUTURE_STRICT_RESERVED_WORD) { 132 Token::FUTURE_STRICT_RESERVED_WORD) {
50 return PreParserIdentifier::FutureStrictReserved(); 133 return PreParserIdentifier::FutureStrictReserved();
51 } else if (scanner->current_token() == Token::LET) { 134 } else if (scanner->current_token() == Token::LET) {
52 return PreParserIdentifier::Let(); 135 return PreParserIdentifier::Let();
53 } else if (scanner->current_token() == Token::YIELD) { 136 } else if (scanner->current_token() == Token::YIELD) {
54 return PreParserIdentifier::Yield(); 137 return PreParserIdentifier::Yield();
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 bool name_is_strict_reserved, FunctionKind kind, 176 bool name_is_strict_reserved, FunctionKind kind,
94 int function_token_position, FunctionLiteral::FunctionType type, 177 int function_token_position, FunctionLiteral::FunctionType type,
95 FunctionLiteral::ArityRestriction arity_restriction, bool* ok) { 178 FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
96 return pre_parser_->ParseFunctionLiteral( 179 return pre_parser_->ParseFunctionLiteral(
97 name, function_name_location, name_is_strict_reserved, kind, 180 name, function_name_location, name_is_strict_reserved, kind,
98 function_token_position, type, arity_restriction, ok); 181 function_token_position, type, arity_restriction, ok);
99 } 182 }
100 183
101 184
102 PreParser::PreParseResult PreParser::PreParseLazyFunction( 185 PreParser::PreParseResult PreParser::PreParseLazyFunction(
103 StrictMode strict_mode, bool is_generator, ParserRecorder* log) { 186 StrictMode strict_mode, bool is_generator, bool log_identifiers,
187 ParserRecorder* log) {
188 log_identifiers_ = log_identifiers;
104 log_ = log; 189 log_ = log;
105 // Lazy functions always have trivial outer scopes (no with/catch scopes). 190 // Lazy functions always have trivial outer scopes (no with/catch scopes).
106 PreParserScope top_scope(scope_, GLOBAL_SCOPE); 191 PreParserScope top_scope = NewScope(NULL, GLOBAL_SCOPE);
107 PreParserFactory top_factory(NULL); 192 PreParserFactory top_factory(NULL);
108 FunctionState top_state(&function_state_, &scope_, &top_scope, &top_factory); 193 FunctionState top_state(&function_state_, &scope_, &top_scope, &top_factory);
109 scope_->SetStrictMode(strict_mode); 194 scope_->SetStrictMode(strict_mode);
110 PreParserScope function_scope(scope_, FUNCTION_SCOPE); 195 PreParserScope function_scope = NewScope(scope_, FUNCTION_SCOPE);
111 PreParserFactory function_factory(NULL); 196 PreParserFactory function_factory(NULL);
112 FunctionState function_state(&function_state_, &scope_, &function_scope, 197 FunctionState function_state(&function_state_, &scope_, &function_scope,
113 &function_factory); 198 &function_factory);
114 function_state.set_is_generator(is_generator); 199 function_state.set_is_generator(is_generator);
115 DCHECK_EQ(Token::LBRACE, scanner()->current_token()); 200 DCHECK_EQ(Token::LBRACE, scanner()->current_token());
116 bool ok = true; 201 bool ok = true;
117 int start_position = peek_position(); 202 int start_position = peek_position();
118 ParseLazyFunctionLiteralBody(&ok); 203 ParseLazyFunctionLiteralBody(&ok);
119 if (stack_overflow()) return kPreParseStackOverflow; 204 if (stack_overflow()) return kPreParseStackOverflow;
120 if (!ok) { 205 if (!ok) {
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after
452 537
453 // The scope of a var/const declared variable anywhere inside a function 538 // The scope of a var/const declared variable anywhere inside a function
454 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope 539 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope
455 // of a let declared variable is the scope of the immediately enclosing 540 // of a let declared variable is the scope of the immediately enclosing
456 // block. 541 // block.
457 int nvars = 0; // the number of variables declared 542 int nvars = 0; // the number of variables declared
458 do { 543 do {
459 // Parse variable name. 544 // Parse variable name.
460 if (nvars > 0) Consume(Token::COMMA); 545 if (nvars > 0) Consume(Token::COMMA);
461 ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); 546 ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
547 if (log_identifiers_) {
548 DCHECK(ast_value_factory_);
549 const AstRawString* identifier =
550 scanner()->CurrentSymbol(ast_value_factory_);
551 scope_->Declare(identifier);
552 }
462 nvars++; 553 nvars++;
463 if (peek() == Token::ASSIGN || require_initializer) { 554 if (peek() == Token::ASSIGN || require_initializer) {
464 Expect(Token::ASSIGN, CHECK_OK); 555 Expect(Token::ASSIGN, CHECK_OK);
465 ParseAssignmentExpression(var_context != kForStatement, CHECK_OK); 556 ParseAssignmentExpression(var_context != kForStatement, CHECK_OK);
466 if (decl_props != NULL) *decl_props = kHasInitializers; 557 if (decl_props != NULL) *decl_props = kHasInitializers;
467 } 558 }
468 } while (peek() == Token::COMMA); 559 } while (peek() == Token::COMMA);
469 560
470 if (num_decl != NULL) *num_decl = nvars; 561 if (num_decl != NULL) *num_decl = nvars;
471 return Statement::Default(); 562 return Statement::Default();
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
586 Expect(Token::WITH, CHECK_OK); 677 Expect(Token::WITH, CHECK_OK);
587 if (strict_mode() == STRICT) { 678 if (strict_mode() == STRICT) {
588 ReportMessageAt(scanner()->location(), "strict_mode_with"); 679 ReportMessageAt(scanner()->location(), "strict_mode_with");
589 *ok = false; 680 *ok = false;
590 return Statement::Default(); 681 return Statement::Default();
591 } 682 }
592 Expect(Token::LPAREN, CHECK_OK); 683 Expect(Token::LPAREN, CHECK_OK);
593 ParseExpression(true, CHECK_OK); 684 ParseExpression(true, CHECK_OK);
594 Expect(Token::RPAREN, CHECK_OK); 685 Expect(Token::RPAREN, CHECK_OK);
595 686
596 PreParserScope with_scope(scope_, WITH_SCOPE); 687 PreParserScope with_scope = NewScope(scope_, WITH_SCOPE);
597 BlockState block_state(&scope_, &with_scope); 688 BlockState block_state(&scope_, &with_scope);
598 ParseStatement(CHECK_OK); 689 ParseStatement(CHECK_OK);
599 return Statement::Default(); 690 return Statement::Default();
600 } 691 }
601 692
602 693
603 PreParser::Statement PreParser::ParseSwitchStatement(bool* ok) { 694 PreParser::Statement PreParser::ParseSwitchStatement(bool* ok) {
604 // SwitchStatement :: 695 // SwitchStatement ::
605 // 'switch' '(' Expression ')' '{' CaseClause* '}' 696 // 'switch' '(' Expression ')' '{' CaseClause* '}'
606 697
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
760 ReportMessageAt(scanner()->location(), "no_catch_or_finally"); 851 ReportMessageAt(scanner()->location(), "no_catch_or_finally");
761 *ok = false; 852 *ok = false;
762 return Statement::Default(); 853 return Statement::Default();
763 } 854 }
764 if (tok == Token::CATCH) { 855 if (tok == Token::CATCH) {
765 Consume(Token::CATCH); 856 Consume(Token::CATCH);
766 Expect(Token::LPAREN, CHECK_OK); 857 Expect(Token::LPAREN, CHECK_OK);
767 ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); 858 ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
768 Expect(Token::RPAREN, CHECK_OK); 859 Expect(Token::RPAREN, CHECK_OK);
769 { 860 {
770 PreParserScope with_scope(scope_, WITH_SCOPE); 861 PreParserScope with_scope = NewScope(scope_, WITH_SCOPE);
771 BlockState block_state(&scope_, &with_scope); 862 BlockState block_state(&scope_, &with_scope);
772 ParseBlock(CHECK_OK); 863 ParseBlock(CHECK_OK);
773 } 864 }
774 tok = peek(); 865 tok = peek();
775 } 866 }
776 if (tok == Token::FINALLY) { 867 if (tok == Token::FINALLY) {
777 Consume(Token::FINALLY); 868 Consume(Token::FINALLY);
778 ParseBlock(CHECK_OK); 869 ParseBlock(CHECK_OK);
779 } 870 }
780 return Statement::Default(); 871 return Statement::Default();
(...skipping 24 matching lines...) Expand all
805 PreParser::Expression PreParser::ParseFunctionLiteral( 896 PreParser::Expression PreParser::ParseFunctionLiteral(
806 Identifier function_name, Scanner::Location function_name_location, 897 Identifier function_name, Scanner::Location function_name_location,
807 bool name_is_strict_reserved, FunctionKind kind, int function_token_pos, 898 bool name_is_strict_reserved, FunctionKind kind, int function_token_pos,
808 FunctionLiteral::FunctionType function_type, 899 FunctionLiteral::FunctionType function_type,
809 FunctionLiteral::ArityRestriction arity_restriction, bool* ok) { 900 FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
810 // Function :: 901 // Function ::
811 // '(' FormalParameterList? ')' '{' FunctionBody '}' 902 // '(' FormalParameterList? ')' '{' FunctionBody '}'
812 903
813 // Parse function body. 904 // Parse function body.
814 ScopeType outer_scope_type = scope_->type(); 905 ScopeType outer_scope_type = scope_->type();
815 PreParserScope function_scope(scope_, FUNCTION_SCOPE); 906 PreParserScope function_scope = NewScope(scope_, FUNCTION_SCOPE);
816 PreParserFactory factory(NULL); 907 PreParserFactory factory(NULL);
817 FunctionState function_state(&function_state_, &scope_, &function_scope, 908 FunctionState function_state(&function_state_, &scope_, &function_scope,
818 &factory); 909 &factory);
819 function_state.set_is_generator(IsGeneratorFunction(kind)); 910 function_state.set_is_generator(IsGeneratorFunction(kind));
820 // FormalParameterList :: 911 // FormalParameterList ::
821 // '(' (Identifier)*[','] ')' 912 // '(' (Identifier)*[','] ')'
822 Expect(Token::LPAREN, CHECK_OK); 913 Expect(Token::LPAREN, CHECK_OK);
823 int start_position = position(); 914 int start_position = position();
824 DuplicateFinder duplicate_finder(scanner()->unicode_cache()); 915 DuplicateFinder duplicate_finder(scanner()->unicode_cache());
825 // We don't yet know if the function will be strict, so we cannot yet produce 916 // We don't yet know if the function will be strict, so we cannot yet produce
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
908 999
909 1000
910 void PreParser::ParseLazyFunctionLiteralBody(bool* ok) { 1001 void PreParser::ParseLazyFunctionLiteralBody(bool* ok) {
911 int body_start = position(); 1002 int body_start = position();
912 ParseSourceElements(Token::RBRACE, ok); 1003 ParseSourceElements(Token::RBRACE, ok);
913 if (!*ok) return; 1004 if (!*ok) return;
914 1005
915 // Position right after terminal '}'. 1006 // Position right after terminal '}'.
916 DCHECK_EQ(Token::RBRACE, scanner()->peek()); 1007 DCHECK_EQ(Token::RBRACE, scanner()->peek());
917 int body_end = scanner()->peek_location().end_pos; 1008 int body_end = scanner()->peek_location().end_pos;
1009 if (log_identifiers_) {
1010 scope_->LogUnboundVariables(log_);
1011 }
918 log_->LogFunction(body_start, body_end, 1012 log_->LogFunction(body_start, body_end,
919 function_state_->materialized_literal_count(), 1013 function_state_->materialized_literal_count(),
920 function_state_->expected_property_count(), 1014 function_state_->expected_property_count(),
921 strict_mode()); 1015 strict_mode());
922 } 1016 }
923 1017
924 1018
925 PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) { 1019 PreParser::Expression PreParser::ParseV8Intrinsic(bool* ok) {
926 // CallRuntime :: 1020 // CallRuntime ::
927 // '%' Identifier Arguments 1021 // '%' Identifier Arguments
928 Expect(Token::MOD, CHECK_OK); 1022 Expect(Token::MOD, CHECK_OK);
929 if (!allow_natives_syntax()) { 1023 if (!allow_natives_syntax()) {
930 *ok = false; 1024 *ok = false;
931 return Expression::Default(); 1025 return Expression::Default();
932 } 1026 }
933 // Allow "eval" or "arguments" for backward compatibility. 1027 // Allow "eval" or "arguments" for backward compatibility.
934 ParseIdentifier(kAllowEvalOrArguments, CHECK_OK); 1028 ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
935 ParseArguments(ok); 1029 ParseArguments(ok);
936 1030
937 return Expression::Default(); 1031 return Expression::Default();
938 } 1032 }
939 1033
940 #undef CHECK_OK 1034 #undef CHECK_OK
941 1035
942 1036
943 } } // v8::internal 1037 } } // v8::internal
OLDNEW
« no previous file with comments | « src/preparser.h ('k') | src/vector.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698