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

Side by Side Diff: src/parsing/parser.cc

Issue 1655313003: Eagerly declare variables in ParseVariableDeclarations where possible (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Add comment Created 4 years, 10 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') | test/message/try-catch-lexical-conflict.out » ('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 2314 matching lines...) Expand 10 before | Expand all | Expand 10 after
2325 // Scope declaration, and rewrite the source-level initialization into an 2325 // Scope declaration, and rewrite the source-level initialization into an
2326 // assignment statement. We use a block to collect multiple assignments. 2326 // assignment statement. We use a block to collect multiple assignments.
2327 // 2327 //
2328 // We mark the block as initializer block because we don't want the 2328 // We mark the block as initializer block because we don't want the
2329 // rewriter to add a '.result' assignment to such a block (to get compliant 2329 // rewriter to add a '.result' assignment to such a block (to get compliant
2330 // behavior for code such as print(eval('var x = 7')), and for cosmetic 2330 // behavior for code such as print(eval('var x = 7')), and for cosmetic
2331 // reasons when pretty-printing. Also, unless an assignment (initialization) 2331 // reasons when pretty-printing. Also, unless an assignment (initialization)
2332 // is inside an initializer block, it is ignored. 2332 // is inside an initializer block, it is ignored.
2333 2333
2334 DeclarationParsingResult parsing_result; 2334 DeclarationParsingResult parsing_result;
2335 ParseVariableDeclarations(var_context, &parsing_result, CHECK_OK); 2335 Block* result =
2336 ParseVariableDeclarations(var_context, &parsing_result, names, CHECK_OK);
2336 ExpectSemicolon(CHECK_OK); 2337 ExpectSemicolon(CHECK_OK);
2337
2338 Block* result = parsing_result.BuildInitializationBlock(names, CHECK_OK);
2339 return result; 2338 return result;
2340 } 2339 }
2341 2340
2342 2341 Block* Parser::ParseVariableDeclarations(
2343 void Parser::ParseVariableDeclarations(VariableDeclarationContext var_context, 2342 VariableDeclarationContext var_context,
2344 DeclarationParsingResult* parsing_result, 2343 DeclarationParsingResult* parsing_result,
2345 bool* ok) { 2344 ZoneList<const AstRawString*>* names, bool* ok) {
2346 // VariableDeclarations :: 2345 // VariableDeclarations ::
2347 // ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[','] 2346 // ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[',']
2348 // 2347 //
2349 // The ES6 Draft Rev3 specifies the following grammar for const declarations 2348 // The ES6 Draft Rev3 specifies the following grammar for const declarations
2350 // 2349 //
2351 // ConstDeclaration :: 2350 // ConstDeclaration ::
2352 // const ConstBinding (',' ConstBinding)* ';' 2351 // const ConstBinding (',' ConstBinding)* ';'
2353 // ConstBinding :: 2352 // ConstBinding ::
2354 // Identifier '=' AssignmentExpression 2353 // Identifier '=' AssignmentExpression
2355 // 2354 //
2356 // TODO(ES6): 2355 // TODO(ES6):
2357 // ConstBinding :: 2356 // ConstBinding ::
2358 // BindingPattern '=' AssignmentExpression 2357 // BindingPattern '=' AssignmentExpression
2359 2358
2360 parsing_result->descriptor.parser = this; 2359 parsing_result->descriptor.parser = this;
2361 parsing_result->descriptor.declaration_kind = DeclarationDescriptor::NORMAL; 2360 parsing_result->descriptor.declaration_kind = DeclarationDescriptor::NORMAL;
2362 parsing_result->descriptor.declaration_pos = peek_position(); 2361 parsing_result->descriptor.declaration_pos = peek_position();
2363 parsing_result->descriptor.initialization_pos = peek_position(); 2362 parsing_result->descriptor.initialization_pos = peek_position();
2364 parsing_result->descriptor.mode = VAR; 2363 parsing_result->descriptor.mode = VAR;
2364
2365 Block* init_block = nullptr;
2366 if (var_context != kForStatement) {
2367 init_block = factory()->NewBlock(
2368 NULL, 1, true, parsing_result->descriptor.declaration_pos);
2369 }
2370
2365 if (peek() == Token::VAR) { 2371 if (peek() == Token::VAR) {
2366 if (is_strong(language_mode())) { 2372 if (is_strong(language_mode())) {
2367 Scanner::Location location = scanner()->peek_location(); 2373 Scanner::Location location = scanner()->peek_location();
2368 ReportMessageAt(location, MessageTemplate::kStrongVar); 2374 ReportMessageAt(location, MessageTemplate::kStrongVar);
2369 *ok = false; 2375 *ok = false;
2370 return; 2376 return nullptr;
2371 } 2377 }
2372 Consume(Token::VAR); 2378 Consume(Token::VAR);
2373 } else if (peek() == Token::CONST && allow_const()) { 2379 } else if (peek() == Token::CONST && allow_const()) {
2374 Consume(Token::CONST); 2380 Consume(Token::CONST);
2375 if (is_sloppy(language_mode()) && allow_legacy_const()) { 2381 if (is_sloppy(language_mode()) && allow_legacy_const()) {
2376 parsing_result->descriptor.mode = CONST_LEGACY; 2382 parsing_result->descriptor.mode = CONST_LEGACY;
2377 ++use_counts_[v8::Isolate::kLegacyConst]; 2383 ++use_counts_[v8::Isolate::kLegacyConst];
2378 } else { 2384 } else {
2379 DCHECK(is_strict(language_mode()) || allow_harmony_sloppy()); 2385 DCHECK(is_strict(language_mode()) || allow_harmony_sloppy());
2380 DCHECK(var_context != kStatement); 2386 DCHECK(var_context != kStatement);
(...skipping 17 matching lines...) Expand all
2398 FuncNameInferrer::State fni_state(fni_); 2404 FuncNameInferrer::State fni_state(fni_);
2399 2405
2400 // Parse name. 2406 // Parse name.
2401 if (!first_declaration) Consume(Token::COMMA); 2407 if (!first_declaration) Consume(Token::COMMA);
2402 2408
2403 Expression* pattern; 2409 Expression* pattern;
2404 int decl_pos = peek_position(); 2410 int decl_pos = peek_position();
2405 { 2411 {
2406 ExpressionClassifier pattern_classifier; 2412 ExpressionClassifier pattern_classifier;
2407 Token::Value next = peek(); 2413 Token::Value next = peek();
2408 pattern = ParsePrimaryExpression(&pattern_classifier, ok); 2414 pattern = ParsePrimaryExpression(&pattern_classifier, CHECK_OK);
2409 if (!*ok) return; 2415 ValidateBindingPattern(&pattern_classifier, CHECK_OK);
2410 ValidateBindingPattern(&pattern_classifier, ok);
2411 if (!*ok) return;
2412 if (IsLexicalVariableMode(parsing_result->descriptor.mode)) { 2416 if (IsLexicalVariableMode(parsing_result->descriptor.mode)) {
2413 ValidateLetPattern(&pattern_classifier, ok); 2417 ValidateLetPattern(&pattern_classifier, CHECK_OK);
2414 if (!*ok) return;
2415 } 2418 }
2416 if (!allow_harmony_destructuring_bind() && !pattern->IsVariableProxy()) { 2419 if (!allow_harmony_destructuring_bind() && !pattern->IsVariableProxy()) {
2417 ReportUnexpectedToken(next); 2420 ReportUnexpectedToken(next);
2418 *ok = false; 2421 *ok = false;
2419 return; 2422 return nullptr;
2420 } 2423 }
2421 } 2424 }
2422 2425
2423 Scanner::Location variable_loc = scanner()->location(); 2426 Scanner::Location variable_loc = scanner()->location();
2424 const AstRawString* single_name = 2427 const AstRawString* single_name =
2425 pattern->IsVariableProxy() ? pattern->AsVariableProxy()->raw_name() 2428 pattern->IsVariableProxy() ? pattern->AsVariableProxy()->raw_name()
2426 : nullptr; 2429 : nullptr;
2427 if (single_name != nullptr) { 2430 if (single_name != nullptr) {
2428 if (fni_ != NULL) fni_->PushVariableName(single_name); 2431 if (fni_ != NULL) fni_->PushVariableName(single_name);
2429 } 2432 }
2430 2433
2431 Expression* value = NULL; 2434 Expression* value = NULL;
2432 int initializer_position = RelocInfo::kNoPosition; 2435 int initializer_position = RelocInfo::kNoPosition;
2433 if (Check(Token::ASSIGN)) { 2436 if (Check(Token::ASSIGN)) {
2434 ExpressionClassifier classifier; 2437 ExpressionClassifier classifier;
2435 value = ParseAssignmentExpression(var_context != kForStatement, 2438 value = ParseAssignmentExpression(var_context != kForStatement,
2436 &classifier, ok); 2439 &classifier, CHECK_OK);
2437 if (!*ok) return; 2440 value = ParserTraits::RewriteNonPattern(value, &classifier, CHECK_OK);
2438 value = ParserTraits::RewriteNonPattern(value, &classifier, ok);
2439 if (!*ok) return;
2440 variable_loc.end_pos = scanner()->location().end_pos; 2441 variable_loc.end_pos = scanner()->location().end_pos;
2441 2442
2442 if (!parsing_result->first_initializer_loc.IsValid()) { 2443 if (!parsing_result->first_initializer_loc.IsValid()) {
2443 parsing_result->first_initializer_loc = variable_loc; 2444 parsing_result->first_initializer_loc = variable_loc;
2444 } 2445 }
2445 2446
2446 // Don't infer if it is "a = function(){...}();"-like expression. 2447 // Don't infer if it is "a = function(){...}();"-like expression.
2447 if (single_name) { 2448 if (single_name) {
2448 if (fni_ != NULL && value->AsCall() == NULL && 2449 if (fni_ != NULL && value->AsCall() == NULL &&
2449 value->AsCallNew() == NULL) { 2450 value->AsCallNew() == NULL) {
(...skipping 14 matching lines...) Expand all
2464 // for-in/of iteration variable. 2465 // for-in/of iteration variable.
2465 if (var_context != kForStatement || !PeekInOrOf()) { 2466 if (var_context != kForStatement || !PeekInOrOf()) {
2466 // ES6 'const' and binding patterns require initializers. 2467 // ES6 'const' and binding patterns require initializers.
2467 if (parsing_result->descriptor.mode == CONST || 2468 if (parsing_result->descriptor.mode == CONST ||
2468 !pattern->IsVariableProxy()) { 2469 !pattern->IsVariableProxy()) {
2469 ParserTraits::ReportMessageAt( 2470 ParserTraits::ReportMessageAt(
2470 Scanner::Location(decl_pos, scanner()->location().end_pos), 2471 Scanner::Location(decl_pos, scanner()->location().end_pos),
2471 MessageTemplate::kDeclarationMissingInitializer, 2472 MessageTemplate::kDeclarationMissingInitializer,
2472 !pattern->IsVariableProxy() ? "destructuring" : "const"); 2473 !pattern->IsVariableProxy() ? "destructuring" : "const");
2473 *ok = false; 2474 *ok = false;
2474 return; 2475 return nullptr;
2475 } 2476 }
2476 2477
2477 // 'let x' and (legacy) 'const x' initialize 'x' to undefined. 2478 // 'let x' and (legacy) 'const x' initialize 'x' to undefined.
2478 if (parsing_result->descriptor.mode == LET || 2479 if (parsing_result->descriptor.mode == LET ||
2479 parsing_result->descriptor.mode == CONST_LEGACY) { 2480 parsing_result->descriptor.mode == CONST_LEGACY) {
2480 value = GetLiteralUndefined(position()); 2481 value = GetLiteralUndefined(position());
2481 } 2482 }
2482 } 2483 }
2483 2484
2484 // End position of the initializer is after the variable. 2485 // End position of the initializer is after the variable.
2485 initializer_position = position(); 2486 initializer_position = position();
2486 } 2487 }
2487 2488
2488 parsing_result->declarations.Add(DeclarationParsingResult::Declaration( 2489 DeclarationParsingResult::Declaration decl(pattern, initializer_position,
2489 pattern, initializer_position, value)); 2490 value);
2491 if (var_context == kForStatement) {
2492 // Save the declaration for further handling in ParseForStatement.
2493 parsing_result->declarations.Add(decl);
2494 } else {
2495 // Immediately declare the variable otherwise. This avoids O(N^2)
2496 // behavior (where N is the number of variables in a single
2497 // declaration) in the PatternRewriter having to do with removing
2498 // and adding VariableProxies to the Scope (see bug 4699).
2499 DCHECK_NOT_NULL(init_block);
2500 PatternRewriter::DeclareAndInitializeVariables(
2501 init_block, &parsing_result->descriptor, &decl, names, CHECK_OK);
2502 }
2490 first_declaration = false; 2503 first_declaration = false;
2491 } while (peek() == Token::COMMA); 2504 } while (peek() == Token::COMMA);
2492 2505
2493 parsing_result->bindings_loc = 2506 parsing_result->bindings_loc =
2494 Scanner::Location(bindings_start, scanner()->location().end_pos); 2507 Scanner::Location(bindings_start, scanner()->location().end_pos);
2508
2509 DCHECK(*ok);
2510 return init_block;
2495 } 2511 }
2496 2512
2497 2513
2498 static bool ContainsLabel(ZoneList<const AstRawString*>* labels, 2514 static bool ContainsLabel(ZoneList<const AstRawString*>* labels,
2499 const AstRawString* label) { 2515 const AstRawString* label) {
2500 DCHECK(label != NULL); 2516 DCHECK(label != NULL);
2501 if (labels != NULL) { 2517 if (labels != NULL) {
2502 for (int i = labels->length(); i-- > 0; ) { 2518 for (int i = labels->length(); i-- > 0; ) {
2503 if (labels->at(i) == label) { 2519 if (labels->at(i) == label) {
2504 return true; 2520 return true;
(...skipping 1120 matching lines...) Expand 10 before | Expand all | Expand 10 after
3625 3641
3626 BlockState block_state(&scope_, for_scope); 3642 BlockState block_state(&scope_, for_scope);
3627 Expect(Token::FOR, CHECK_OK); 3643 Expect(Token::FOR, CHECK_OK);
3628 Expect(Token::LPAREN, CHECK_OK); 3644 Expect(Token::LPAREN, CHECK_OK);
3629 for_scope->set_start_position(scanner()->location().beg_pos); 3645 for_scope->set_start_position(scanner()->location().beg_pos);
3630 bool is_let_identifier_expression = false; 3646 bool is_let_identifier_expression = false;
3631 DeclarationParsingResult parsing_result; 3647 DeclarationParsingResult parsing_result;
3632 if (peek() != Token::SEMICOLON) { 3648 if (peek() != Token::SEMICOLON) {
3633 if (peek() == Token::VAR || (peek() == Token::CONST && allow_const()) || 3649 if (peek() == Token::VAR || (peek() == Token::CONST && allow_const()) ||
3634 (peek() == Token::LET && IsNextLetKeyword())) { 3650 (peek() == Token::LET && IsNextLetKeyword())) {
3635 ParseVariableDeclarations(kForStatement, &parsing_result, CHECK_OK); 3651 ParseVariableDeclarations(kForStatement, &parsing_result, nullptr,
3652 CHECK_OK);
3636 3653
3637 ForEachStatement::VisitMode mode; 3654 ForEachStatement::VisitMode mode;
3638 int each_beg_pos = scanner()->location().beg_pos; 3655 int each_beg_pos = scanner()->location().beg_pos;
3639 int each_end_pos = scanner()->location().end_pos; 3656 int each_end_pos = scanner()->location().end_pos;
3640 3657
3641 if (CheckInOrOf(&mode, ok)) { 3658 if (CheckInOrOf(&mode, ok)) {
3642 if (!*ok) return nullptr; 3659 if (!*ok) return nullptr;
3643 if (parsing_result.declarations.length() != 1) { 3660 if (parsing_result.declarations.length() != 1) {
3644 ParserTraits::ReportMessageAt( 3661 ParserTraits::ReportMessageAt(
3645 parsing_result.bindings_loc, 3662 parsing_result.bindings_loc,
(...skipping 2736 matching lines...) Expand 10 before | Expand all | Expand 10 after
6382 6399
6383 statements->Add(get_return, zone); 6400 statements->Add(get_return, zone);
6384 statements->Add(check_return, zone); 6401 statements->Add(check_return, zone);
6385 statements->Add(call_return, zone); 6402 statements->Add(call_return, zone);
6386 statements->Add(validate_output, zone); 6403 statements->Add(validate_output, zone);
6387 } 6404 }
6388 6405
6389 6406
6390 } // namespace internal 6407 } // namespace internal
6391 } // namespace v8 6408 } // namespace v8
OLDNEW
« no previous file with comments | « src/parsing/parser.h ('k') | test/message/try-catch-lexical-conflict.out » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698