| OLD | NEW |
| 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/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/api.h" | 7 #include "src/api.h" |
| 8 #include "src/ast.h" | 8 #include "src/ast.h" |
| 9 #include "src/bailout-reason.h" | 9 #include "src/bailout-reason.h" |
| 10 #include "src/base/platform/platform.h" | 10 #include "src/base/platform/platform.h" |
| (...skipping 2987 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2998 assign_iterator, | 2998 assign_iterator, |
| 2999 next_result, | 2999 next_result, |
| 3000 result_done, | 3000 result_done, |
| 3001 assign_each); | 3001 assign_each); |
| 3002 } else { | 3002 } else { |
| 3003 stmt->Initialize(each, subject, body); | 3003 stmt->Initialize(each, subject, body); |
| 3004 } | 3004 } |
| 3005 } | 3005 } |
| 3006 | 3006 |
| 3007 | 3007 |
| 3008 Statement* Parser::DesugarLetBindingsInForStatement( | 3008 Statement* Parser::DesugarLexicalBindingsInForStatement( |
| 3009 Scope* inner_scope, ZoneList<const AstRawString*>* names, | 3009 Scope* inner_scope, bool is_const, ZoneList<const AstRawString*>* names, |
| 3010 ForStatement* loop, Statement* init, Expression* cond, Statement* next, | 3010 ForStatement* loop, Statement* init, Expression* cond, Statement* next, |
| 3011 Statement* body, bool* ok) { | 3011 Statement* body, bool* ok) { |
| 3012 // ES6 13.6.3.4 specifies that on each loop iteration the let variables are | 3012 // ES6 13.6.3.4 specifies that on each loop iteration the let variables are |
| 3013 // copied into a new environment. After copying, the "next" statement of the | 3013 // copied into a new environment. After copying, the "next" statement of the |
| 3014 // loop is executed to update the loop variables. The loop condition is | 3014 // loop is executed to update the loop variables. The loop condition is |
| 3015 // checked and the loop body is executed. | 3015 // checked and the loop body is executed. |
| 3016 // | 3016 // |
| 3017 // We rewrite a for statement of the form | 3017 // We rewrite a for statement of the form |
| 3018 // | 3018 // |
| 3019 // labels: for (let x = i; cond; next) body | 3019 // labels: for (let/const x = i; cond; next) body |
| 3020 // | 3020 // |
| 3021 // into | 3021 // into |
| 3022 // | 3022 // |
| 3023 // { | 3023 // { |
| 3024 // let x = i; | 3024 // let/const x = i; |
| 3025 // temp_x = x; | 3025 // temp_x = x; |
| 3026 // first = 1; | 3026 // first = 1; |
| 3027 // outer: for (;;) { | 3027 // outer: for (;;) { |
| 3028 // let x = temp_x; | 3028 // let/const x = temp_x; |
| 3029 // if (first == 1) { | 3029 // if (first == 1) { |
| 3030 // first = 0; | 3030 // first = 0; |
| 3031 // } else { | 3031 // } else { |
| 3032 // next; | 3032 // next; |
| 3033 // } | 3033 // } |
| 3034 // flag = 1; | 3034 // flag = 1; |
| 3035 // labels: for (; flag == 1; flag = 0, temp_x = x) { | 3035 // labels: for (; flag == 1; flag = 0, temp_x = x) { |
| 3036 // if (cond) { | 3036 // if (cond) { |
| 3037 // body | 3037 // body |
| 3038 // } else { | 3038 // } else { |
| 3039 // break outer; | 3039 // break outer; |
| 3040 // } | 3040 // } |
| 3041 // } | 3041 // } |
| 3042 // if (flag == 1) { | 3042 // if (flag == 1) { |
| 3043 // break; | 3043 // break; |
| 3044 // } | 3044 // } |
| 3045 // } | 3045 // } |
| 3046 // } | 3046 // } |
| 3047 | 3047 |
| 3048 DCHECK(names->length() > 0); | 3048 DCHECK(names->length() > 0); |
| 3049 Scope* for_scope = scope_; | 3049 Scope* for_scope = scope_; |
| 3050 ZoneList<Variable*> temps(names->length(), zone()); | 3050 ZoneList<Variable*> temps(names->length(), zone()); |
| 3051 | 3051 |
| 3052 Block* outer_block = factory()->NewBlock(NULL, names->length() + 3, false, | 3052 Block* outer_block = factory()->NewBlock(NULL, names->length() + 3, false, |
| 3053 RelocInfo::kNoPosition); | 3053 RelocInfo::kNoPosition); |
| 3054 | 3054 |
| 3055 // Add statement: let x = i. | 3055 // Add statement: let/const x = i. |
| 3056 outer_block->AddStatement(init, zone()); | 3056 outer_block->AddStatement(init, zone()); |
| 3057 | 3057 |
| 3058 const AstRawString* temp_name = ast_value_factory()->dot_for_string(); | 3058 const AstRawString* temp_name = ast_value_factory()->dot_for_string(); |
| 3059 | 3059 |
| 3060 // For each let variable x: | 3060 // For each lexical variable x: |
| 3061 // make statement: temp_x = x. | 3061 // make statement: temp_x = x. |
| 3062 for (int i = 0; i < names->length(); i++) { | 3062 for (int i = 0; i < names->length(); i++) { |
| 3063 VariableProxy* proxy = NewUnresolved(names->at(i), LET); | 3063 VariableProxy* proxy = NewUnresolved(names->at(i), LET); |
| 3064 Variable* temp = scope_->DeclarationScope()->NewTemporary(temp_name); | 3064 Variable* temp = scope_->DeclarationScope()->NewTemporary(temp_name); |
| 3065 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp); | 3065 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp); |
| 3066 Assignment* assignment = factory()->NewAssignment( | 3066 Assignment* assignment = factory()->NewAssignment( |
| 3067 Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition); | 3067 Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition); |
| 3068 Statement* assignment_statement = factory()->NewExpressionStatement( | 3068 Statement* assignment_statement = factory()->NewExpressionStatement( |
| 3069 assignment, RelocInfo::kNoPosition); | 3069 assignment, RelocInfo::kNoPosition); |
| 3070 outer_block->AddStatement(assignment_statement, zone()); | 3070 outer_block->AddStatement(assignment_statement, zone()); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 3095 | 3095 |
| 3096 outer_block->set_scope(for_scope); | 3096 outer_block->set_scope(for_scope); |
| 3097 scope_ = inner_scope; | 3097 scope_ = inner_scope; |
| 3098 | 3098 |
| 3099 Block* inner_block = factory()->NewBlock(NULL, names->length() + 4, false, | 3099 Block* inner_block = factory()->NewBlock(NULL, names->length() + 4, false, |
| 3100 RelocInfo::kNoPosition); | 3100 RelocInfo::kNoPosition); |
| 3101 int pos = scanner()->location().beg_pos; | 3101 int pos = scanner()->location().beg_pos; |
| 3102 ZoneList<Variable*> inner_vars(names->length(), zone()); | 3102 ZoneList<Variable*> inner_vars(names->length(), zone()); |
| 3103 | 3103 |
| 3104 // For each let variable x: | 3104 // For each let variable x: |
| 3105 // make statement: let x = temp_x. | 3105 // make statement: let/const x = temp_x. |
| 3106 VariableMode mode = is_const ? CONST : LET; |
| 3106 for (int i = 0; i < names->length(); i++) { | 3107 for (int i = 0; i < names->length(); i++) { |
| 3107 VariableProxy* proxy = NewUnresolved(names->at(i), LET); | 3108 VariableProxy* proxy = NewUnresolved(names->at(i), mode); |
| 3108 Declaration* declaration = factory()->NewVariableDeclaration( | 3109 Declaration* declaration = factory()->NewVariableDeclaration( |
| 3109 proxy, LET, scope_, RelocInfo::kNoPosition); | 3110 proxy, mode, scope_, RelocInfo::kNoPosition); |
| 3110 Declare(declaration, true, CHECK_OK); | 3111 Declare(declaration, true, CHECK_OK); |
| 3111 inner_vars.Add(declaration->proxy()->var(), zone()); | 3112 inner_vars.Add(declaration->proxy()->var(), zone()); |
| 3112 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i)); | 3113 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i)); |
| 3113 Assignment* assignment = factory()->NewAssignment( | 3114 Assignment* assignment = factory()->NewAssignment( |
| 3114 Token::INIT_LET, proxy, temp_proxy, pos); | 3115 is_const ? Token::INIT_CONST : Token::INIT_LET, proxy, temp_proxy, pos); |
| 3115 Statement* assignment_statement = | 3116 Statement* assignment_statement = |
| 3116 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); | 3117 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); |
| 3117 proxy->var()->set_initializer_position(init->position()); | 3118 proxy->var()->set_initializer_position(init->position()); |
| 3118 inner_block->AddStatement(assignment_statement, zone()); | 3119 inner_block->AddStatement(assignment_statement, zone()); |
| 3119 } | 3120 } |
| 3120 | 3121 |
| 3121 // Make statement: if (first == 1) { first = 0; } else { next; } | 3122 // Make statement: if (first == 1) { first = 0; } else { next; } |
| 3122 if (next) { | 3123 if (next) { |
| 3123 DCHECK(first); | 3124 DCHECK(first); |
| 3124 Expression* compare = NULL; | 3125 Expression* compare = NULL; |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3233 return outer_block; | 3234 return outer_block; |
| 3234 } | 3235 } |
| 3235 | 3236 |
| 3236 | 3237 |
| 3237 Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, | 3238 Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, |
| 3238 bool* ok) { | 3239 bool* ok) { |
| 3239 // ForStatement :: | 3240 // ForStatement :: |
| 3240 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement | 3241 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement |
| 3241 | 3242 |
| 3242 int stmt_pos = peek_position(); | 3243 int stmt_pos = peek_position(); |
| 3244 bool is_const = false; |
| 3243 Statement* init = NULL; | 3245 Statement* init = NULL; |
| 3244 ZoneList<const AstRawString*> let_bindings(1, zone()); | 3246 ZoneList<const AstRawString*> lexical_bindings(1, zone()); |
| 3245 | 3247 |
| 3246 // Create an in-between scope for let-bound iteration variables. | 3248 // Create an in-between scope for let-bound iteration variables. |
| 3247 Scope* saved_scope = scope_; | 3249 Scope* saved_scope = scope_; |
| 3248 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE); | 3250 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE); |
| 3249 scope_ = for_scope; | 3251 scope_ = for_scope; |
| 3250 | 3252 |
| 3251 Expect(Token::FOR, CHECK_OK); | 3253 Expect(Token::FOR, CHECK_OK); |
| 3252 Expect(Token::LPAREN, CHECK_OK); | 3254 Expect(Token::LPAREN, CHECK_OK); |
| 3253 for_scope->set_start_position(scanner()->location().beg_pos); | 3255 for_scope->set_start_position(scanner()->location().beg_pos); |
| 3254 bool is_let_identifier_expression = false; | 3256 bool is_let_identifier_expression = false; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3286 for_scope->set_end_position(scanner()->location().end_pos); | 3288 for_scope->set_end_position(scanner()->location().end_pos); |
| 3287 for_scope = for_scope->FinalizeBlockScope(); | 3289 for_scope = for_scope->FinalizeBlockScope(); |
| 3288 DCHECK(for_scope == NULL); | 3290 DCHECK(for_scope == NULL); |
| 3289 // Parsed for-in loop w/ variable/const declaration. | 3291 // Parsed for-in loop w/ variable/const declaration. |
| 3290 return result; | 3292 return result; |
| 3291 } else { | 3293 } else { |
| 3292 init = variable_statement; | 3294 init = variable_statement; |
| 3293 } | 3295 } |
| 3294 } else if ((peek() == Token::LET || peek() == Token::CONST) && | 3296 } else if ((peek() == Token::LET || peek() == Token::CONST) && |
| 3295 is_strict(language_mode())) { | 3297 is_strict(language_mode())) { |
| 3296 bool is_const = peek() == Token::CONST; | 3298 is_const = peek() == Token::CONST; |
| 3297 const AstRawString* name = NULL; | 3299 const AstRawString* name = NULL; |
| 3298 VariableDeclarationProperties decl_props = kHasNoInitializers; | 3300 VariableDeclarationProperties decl_props = kHasNoInitializers; |
| 3299 Block* variable_statement = | 3301 Block* variable_statement = |
| 3300 ParseVariableDeclarations(kForStatement, &decl_props, &let_bindings, | 3302 ParseVariableDeclarations(kForStatement, &decl_props, |
| 3301 &name, CHECK_OK); | 3303 &lexical_bindings, &name, CHECK_OK); |
| 3302 bool accept_IN = name != NULL && decl_props != kHasInitializers; | 3304 bool accept_IN = name != NULL && decl_props != kHasInitializers; |
| 3303 bool accept_OF = decl_props == kHasNoInitializers; | 3305 bool accept_OF = decl_props == kHasNoInitializers; |
| 3304 ForEachStatement::VisitMode mode; | 3306 ForEachStatement::VisitMode mode; |
| 3305 int each_beg_pos = scanner()->location().beg_pos; | 3307 int each_beg_pos = scanner()->location().beg_pos; |
| 3306 int each_end_pos = scanner()->location().end_pos; | 3308 int each_end_pos = scanner()->location().end_pos; |
| 3307 | 3309 |
| 3308 if (accept_IN && CheckInOrOf(accept_OF, &mode, ok)) { | 3310 if (accept_IN && CheckInOrOf(accept_OF, &mode, ok)) { |
| 3309 if (!*ok) return nullptr; | 3311 if (!*ok) return nullptr; |
| 3310 | 3312 |
| 3311 // Rewrite a for-in statement of the form | 3313 // Rewrite a for-in statement of the form |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3408 is_let_identifier_expression) { | 3410 is_let_identifier_expression) { |
| 3409 ReportMessage("sloppy_lexical", NULL); | 3411 ReportMessage("sloppy_lexical", NULL); |
| 3410 *ok = false; | 3412 *ok = false; |
| 3411 return NULL; | 3413 return NULL; |
| 3412 } | 3414 } |
| 3413 Expect(Token::SEMICOLON, CHECK_OK); | 3415 Expect(Token::SEMICOLON, CHECK_OK); |
| 3414 | 3416 |
| 3415 // If there are let bindings, then condition and the next statement of the | 3417 // If there are let bindings, then condition and the next statement of the |
| 3416 // for loop must be parsed in a new scope. | 3418 // for loop must be parsed in a new scope. |
| 3417 Scope* inner_scope = NULL; | 3419 Scope* inner_scope = NULL; |
| 3418 if (let_bindings.length() > 0) { | 3420 if (lexical_bindings.length() > 0) { |
| 3419 inner_scope = NewScope(for_scope, BLOCK_SCOPE); | 3421 inner_scope = NewScope(for_scope, BLOCK_SCOPE); |
| 3420 inner_scope->set_start_position(scanner()->location().beg_pos); | 3422 inner_scope->set_start_position(scanner()->location().beg_pos); |
| 3421 scope_ = inner_scope; | 3423 scope_ = inner_scope; |
| 3422 } | 3424 } |
| 3423 | 3425 |
| 3424 Expression* cond = NULL; | 3426 Expression* cond = NULL; |
| 3425 if (peek() != Token::SEMICOLON) { | 3427 if (peek() != Token::SEMICOLON) { |
| 3426 cond = ParseExpression(true, CHECK_OK); | 3428 cond = ParseExpression(true, CHECK_OK); |
| 3427 } | 3429 } |
| 3428 Expect(Token::SEMICOLON, CHECK_OK); | 3430 Expect(Token::SEMICOLON, CHECK_OK); |
| 3429 | 3431 |
| 3430 Statement* next = NULL; | 3432 Statement* next = NULL; |
| 3431 if (peek() != Token::RPAREN) { | 3433 if (peek() != Token::RPAREN) { |
| 3432 int next_pos = position(); | 3434 int next_pos = position(); |
| 3433 Expression* exp = ParseExpression(true, CHECK_OK); | 3435 Expression* exp = ParseExpression(true, CHECK_OK); |
| 3434 next = factory()->NewExpressionStatement(exp, next_pos); | 3436 next = factory()->NewExpressionStatement(exp, next_pos); |
| 3435 } | 3437 } |
| 3436 Expect(Token::RPAREN, CHECK_OK); | 3438 Expect(Token::RPAREN, CHECK_OK); |
| 3437 | 3439 |
| 3438 Statement* body = ParseSubStatement(NULL, CHECK_OK); | 3440 Statement* body = ParseSubStatement(NULL, CHECK_OK); |
| 3439 | 3441 |
| 3440 Statement* result = NULL; | 3442 Statement* result = NULL; |
| 3441 if (let_bindings.length() > 0) { | 3443 if (lexical_bindings.length() > 0) { |
| 3442 scope_ = for_scope; | 3444 scope_ = for_scope; |
| 3443 result = DesugarLetBindingsInForStatement(inner_scope, &let_bindings, loop, | 3445 result = DesugarLexicalBindingsInForStatement( |
| 3444 init, cond, next, body, CHECK_OK); | 3446 inner_scope, is_const, &lexical_bindings, loop, init, cond, |
| 3447 next, body, CHECK_OK); |
| 3445 scope_ = saved_scope; | 3448 scope_ = saved_scope; |
| 3446 for_scope->set_end_position(scanner()->location().end_pos); | 3449 for_scope->set_end_position(scanner()->location().end_pos); |
| 3447 } else { | 3450 } else { |
| 3448 scope_ = saved_scope; | 3451 scope_ = saved_scope; |
| 3449 for_scope->set_end_position(scanner()->location().end_pos); | 3452 for_scope->set_end_position(scanner()->location().end_pos); |
| 3450 for_scope = for_scope->FinalizeBlockScope(); | 3453 for_scope = for_scope->FinalizeBlockScope(); |
| 3451 if (for_scope) { | 3454 if (for_scope) { |
| 3452 // Rewrite a for statement of the form | 3455 // Rewrite a for statement of the form |
| 3453 // for (const x = i; c; n) b | 3456 // for (const x = i; c; n) b |
| 3454 // | 3457 // |
| (...skipping 1988 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5443 } else { | 5446 } else { |
| 5444 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data()); | 5447 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data()); |
| 5445 running_hash = StringHasher::ComputeRunningHash(running_hash, data, | 5448 running_hash = StringHasher::ComputeRunningHash(running_hash, data, |
| 5446 raw_string->length()); | 5449 raw_string->length()); |
| 5447 } | 5450 } |
| 5448 } | 5451 } |
| 5449 | 5452 |
| 5450 return running_hash; | 5453 return running_hash; |
| 5451 } | 5454 } |
| 5452 } } // namespace v8::internal | 5455 } } // namespace v8::internal |
| OLD | NEW |