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 3204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3215 // We rewrite a for statement of the form | 3215 // We rewrite a for statement of the form |
3216 // | 3216 // |
3217 // labels: for (let/const x = i; cond; next) body | 3217 // labels: for (let/const x = i; cond; next) body |
3218 // | 3218 // |
3219 // into | 3219 // into |
3220 // | 3220 // |
3221 // { | 3221 // { |
3222 // let/const x = i; | 3222 // let/const x = i; |
3223 // temp_x = x; | 3223 // temp_x = x; |
3224 // first = 1; | 3224 // first = 1; |
| 3225 // undefined; |
3225 // outer: for (;;) { | 3226 // outer: for (;;) { |
3226 // let/const x = temp_x; | 3227 // { // This block's only function is to ensure that the statements it |
3227 // if (first == 1) { | 3228 // // contains do not affect the normal completion value. This is |
3228 // first = 0; | 3229 // // accomplished by setting its ignore_completion_value bit. |
3229 // } else { | 3230 // // No new lexical scope is introduced, so lexically scoped variables |
3230 // next; | 3231 // // declared here will be scoped to the outer for loop. |
| 3232 // let/const x = temp_x; |
| 3233 // if (first == 1) { |
| 3234 // first = 0; |
| 3235 // } else { |
| 3236 // next; |
| 3237 // } |
| 3238 // flag = 1; |
3231 // } | 3239 // } |
3232 // flag = 1; | |
3233 // labels: for (; flag == 1; flag = 0, temp_x = x) { | 3240 // labels: for (; flag == 1; flag = 0, temp_x = x) { |
3234 // if (cond) { | 3241 // if (cond) { |
3235 // body | 3242 // body |
3236 // } else { | 3243 // } else { |
3237 // break outer; | 3244 // break outer; |
3238 // } | 3245 // } |
3239 // } | 3246 // } |
3240 // if (flag == 1) { | 3247 // if (flag == 1) { |
3241 // break; | 3248 // break; |
3242 // } | 3249 // } |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3275 first = scope_->DeclarationScope()->NewTemporary(temp_name); | 3282 first = scope_->DeclarationScope()->NewTemporary(temp_name); |
3276 VariableProxy* first_proxy = factory()->NewVariableProxy(first); | 3283 VariableProxy* first_proxy = factory()->NewVariableProxy(first); |
3277 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition); | 3284 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition); |
3278 Assignment* assignment = factory()->NewAssignment( | 3285 Assignment* assignment = factory()->NewAssignment( |
3279 Token::ASSIGN, first_proxy, const1, RelocInfo::kNoPosition); | 3286 Token::ASSIGN, first_proxy, const1, RelocInfo::kNoPosition); |
3280 Statement* assignment_statement = | 3287 Statement* assignment_statement = |
3281 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); | 3288 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); |
3282 outer_block->AddStatement(assignment_statement, zone()); | 3289 outer_block->AddStatement(assignment_statement, zone()); |
3283 } | 3290 } |
3284 | 3291 |
| 3292 // make statement: undefined; |
| 3293 outer_block->AddStatement( |
| 3294 factory()->NewExpressionStatement( |
| 3295 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), |
| 3296 RelocInfo::kNoPosition), |
| 3297 zone()); |
| 3298 |
3285 // Make statement: outer: for (;;) | 3299 // Make statement: outer: for (;;) |
3286 // Note that we don't actually create the label, or set this loop up as an | 3300 // Note that we don't actually create the label, or set this loop up as an |
3287 // explicit break target, instead handing it directly to those nodes that | 3301 // explicit break target, instead handing it directly to those nodes that |
3288 // need to know about it. This should be safe because we don't run any code | 3302 // need to know about it. This should be safe because we don't run any code |
3289 // in this function that looks up break targets. | 3303 // in this function that looks up break targets. |
3290 ForStatement* outer_loop = | 3304 ForStatement* outer_loop = |
3291 factory()->NewForStatement(NULL, RelocInfo::kNoPosition); | 3305 factory()->NewForStatement(NULL, RelocInfo::kNoPosition); |
3292 outer_block->AddStatement(outer_loop, zone()); | 3306 outer_block->AddStatement(outer_loop, zone()); |
3293 | 3307 |
3294 outer_block->set_scope(for_scope); | 3308 outer_block->set_scope(for_scope); |
3295 scope_ = inner_scope; | 3309 scope_ = inner_scope; |
3296 | 3310 |
3297 Block* inner_block = factory()->NewBlock(NULL, names->length() + 4, false, | 3311 Block* inner_block = |
3298 RelocInfo::kNoPosition); | 3312 factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition); |
| 3313 Block* ignore_completion_block = factory()->NewBlock( |
| 3314 NULL, names->length() + 2, true, RelocInfo::kNoPosition); |
3299 ZoneList<Variable*> inner_vars(names->length(), zone()); | 3315 ZoneList<Variable*> inner_vars(names->length(), zone()); |
3300 // For each let variable x: | 3316 // For each let variable x: |
3301 // make statement: let/const x = temp_x. | 3317 // make statement: let/const x = temp_x. |
3302 VariableMode mode = is_const ? CONST : LET; | 3318 VariableMode mode = is_const ? CONST : LET; |
3303 for (int i = 0; i < names->length(); i++) { | 3319 for (int i = 0; i < names->length(); i++) { |
3304 VariableProxy* proxy = NewUnresolved(names->at(i), mode); | 3320 VariableProxy* proxy = NewUnresolved(names->at(i), mode); |
3305 Declaration* declaration = factory()->NewVariableDeclaration( | 3321 Declaration* declaration = factory()->NewVariableDeclaration( |
3306 proxy, mode, scope_, RelocInfo::kNoPosition); | 3322 proxy, mode, scope_, RelocInfo::kNoPosition); |
3307 Declare(declaration, true, CHECK_OK); | 3323 Declare(declaration, true, CHECK_OK); |
3308 inner_vars.Add(declaration->proxy()->var(), zone()); | 3324 inner_vars.Add(declaration->proxy()->var(), zone()); |
3309 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i)); | 3325 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i)); |
3310 Assignment* assignment = | 3326 Assignment* assignment = |
3311 factory()->NewAssignment(is_const ? Token::INIT_CONST : Token::INIT_LET, | 3327 factory()->NewAssignment(is_const ? Token::INIT_CONST : Token::INIT_LET, |
3312 proxy, temp_proxy, RelocInfo::kNoPosition); | 3328 proxy, temp_proxy, RelocInfo::kNoPosition); |
3313 Statement* assignment_statement = | 3329 Statement* assignment_statement = |
3314 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); | 3330 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); |
3315 DCHECK(init->position() != RelocInfo::kNoPosition); | 3331 DCHECK(init->position() != RelocInfo::kNoPosition); |
3316 proxy->var()->set_initializer_position(init->position()); | 3332 proxy->var()->set_initializer_position(init->position()); |
3317 inner_block->AddStatement(assignment_statement, zone()); | 3333 ignore_completion_block->AddStatement(assignment_statement, zone()); |
3318 } | 3334 } |
3319 | 3335 |
3320 // Make statement: if (first == 1) { first = 0; } else { next; } | 3336 // Make statement: if (first == 1) { first = 0; } else { next; } |
3321 if (next) { | 3337 if (next) { |
3322 DCHECK(first); | 3338 DCHECK(first); |
3323 Expression* compare = NULL; | 3339 Expression* compare = NULL; |
3324 // Make compare expression: first == 1. | 3340 // Make compare expression: first == 1. |
3325 { | 3341 { |
3326 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition); | 3342 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition); |
3327 VariableProxy* first_proxy = factory()->NewVariableProxy(first); | 3343 VariableProxy* first_proxy = factory()->NewVariableProxy(first); |
3328 compare = factory()->NewCompareOperation(Token::EQ, first_proxy, const1, | 3344 compare = factory()->NewCompareOperation(Token::EQ, first_proxy, const1, |
3329 RelocInfo::kNoPosition); | 3345 RelocInfo::kNoPosition); |
3330 } | 3346 } |
3331 Statement* clear_first = NULL; | 3347 Statement* clear_first = NULL; |
3332 // Make statement: first = 0. | 3348 // Make statement: first = 0. |
3333 { | 3349 { |
3334 VariableProxy* first_proxy = factory()->NewVariableProxy(first); | 3350 VariableProxy* first_proxy = factory()->NewVariableProxy(first); |
3335 Expression* const0 = factory()->NewSmiLiteral(0, RelocInfo::kNoPosition); | 3351 Expression* const0 = factory()->NewSmiLiteral(0, RelocInfo::kNoPosition); |
3336 Assignment* assignment = factory()->NewAssignment( | 3352 Assignment* assignment = factory()->NewAssignment( |
3337 Token::ASSIGN, first_proxy, const0, RelocInfo::kNoPosition); | 3353 Token::ASSIGN, first_proxy, const0, RelocInfo::kNoPosition); |
3338 clear_first = | 3354 clear_first = |
3339 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); | 3355 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); |
3340 } | 3356 } |
3341 Statement* clear_first_or_next = factory()->NewIfStatement( | 3357 Statement* clear_first_or_next = factory()->NewIfStatement( |
3342 compare, clear_first, next, RelocInfo::kNoPosition); | 3358 compare, clear_first, next, RelocInfo::kNoPosition); |
3343 inner_block->AddStatement(clear_first_or_next, zone()); | 3359 ignore_completion_block->AddStatement(clear_first_or_next, zone()); |
3344 } | 3360 } |
3345 | 3361 |
3346 Variable* flag = scope_->DeclarationScope()->NewTemporary(temp_name); | 3362 Variable* flag = scope_->DeclarationScope()->NewTemporary(temp_name); |
3347 // Make statement: flag = 1. | 3363 // Make statement: flag = 1. |
3348 { | 3364 { |
3349 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag); | 3365 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag); |
3350 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition); | 3366 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition); |
3351 Assignment* assignment = factory()->NewAssignment( | 3367 Assignment* assignment = factory()->NewAssignment( |
3352 Token::ASSIGN, flag_proxy, const1, RelocInfo::kNoPosition); | 3368 Token::ASSIGN, flag_proxy, const1, RelocInfo::kNoPosition); |
3353 Statement* assignment_statement = | 3369 Statement* assignment_statement = |
3354 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); | 3370 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); |
3355 inner_block->AddStatement(assignment_statement, zone()); | 3371 ignore_completion_block->AddStatement(assignment_statement, zone()); |
3356 } | 3372 } |
3357 | 3373 inner_block->AddStatement(ignore_completion_block, zone()); |
3358 // Make cond expression for main loop: flag == 1. | 3374 // Make cond expression for main loop: flag == 1. |
3359 Expression* flag_cond = NULL; | 3375 Expression* flag_cond = NULL; |
3360 { | 3376 { |
3361 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition); | 3377 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition); |
3362 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag); | 3378 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag); |
3363 flag_cond = factory()->NewCompareOperation(Token::EQ, flag_proxy, const1, | 3379 flag_cond = factory()->NewCompareOperation(Token::EQ, flag_proxy, const1, |
3364 RelocInfo::kNoPosition); | 3380 RelocInfo::kNoPosition); |
3365 } | 3381 } |
3366 | 3382 |
3367 // Create chain of expressions "flag = 0, temp_x = x, ..." | 3383 // Create chain of expressions "flag = 0, temp_x = x, ..." |
(...skipping 27 matching lines...) Expand all Loading... |
3395 // Make statement: if (cond) { body; } else { break outer; } | 3411 // Make statement: if (cond) { body; } else { break outer; } |
3396 Statement* body_or_stop = body; | 3412 Statement* body_or_stop = body; |
3397 if (cond) { | 3413 if (cond) { |
3398 Statement* stop = | 3414 Statement* stop = |
3399 factory()->NewBreakStatement(outer_loop, RelocInfo::kNoPosition); | 3415 factory()->NewBreakStatement(outer_loop, RelocInfo::kNoPosition); |
3400 body_or_stop = | 3416 body_or_stop = |
3401 factory()->NewIfStatement(cond, body, stop, cond->position()); | 3417 factory()->NewIfStatement(cond, body, stop, cond->position()); |
3402 } | 3418 } |
3403 | 3419 |
3404 // Make statement: labels: for (; flag == 1; flag = 0, temp_x = x) | 3420 // Make statement: labels: for (; flag == 1; flag = 0, temp_x = x) |
3405 // Note that we re-use the original loop node, which retains it labels | 3421 // Note that we re-use the original loop node, which retains its labels |
3406 // and ensures that any break or continue statements in body point to | 3422 // and ensures that any break or continue statements in body point to |
3407 // the right place. | 3423 // the right place. |
3408 loop->Initialize(NULL, flag_cond, compound_next_statement, body_or_stop); | 3424 loop->Initialize(NULL, flag_cond, compound_next_statement, body_or_stop); |
3409 inner_block->AddStatement(loop, zone()); | 3425 inner_block->AddStatement(loop, zone()); |
3410 | 3426 |
3411 // Make statement: if (flag == 1) { break; } | 3427 // Make statement: if (flag == 1) { break; } |
3412 { | 3428 { |
3413 Expression* compare = NULL; | 3429 Expression* compare = NULL; |
3414 // Make compare expresion: flag == 1. | 3430 // Make compare expresion: flag == 1. |
3415 { | 3431 { |
(...skipping 2403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5819 Expression* Parser::SpreadCallNew(Expression* function, | 5835 Expression* Parser::SpreadCallNew(Expression* function, |
5820 ZoneList<v8::internal::Expression*>* args, | 5836 ZoneList<v8::internal::Expression*>* args, |
5821 int pos) { | 5837 int pos) { |
5822 args->InsertAt(0, function, zone()); | 5838 args->InsertAt(0, function, zone()); |
5823 | 5839 |
5824 return factory()->NewCallRuntime( | 5840 return factory()->NewCallRuntime( |
5825 ast_value_factory()->reflect_construct_string(), NULL, args, pos); | 5841 ast_value_factory()->reflect_construct_string(), NULL, args, pos); |
5826 } | 5842 } |
5827 } // namespace internal | 5843 } // namespace internal |
5828 } // namespace v8 | 5844 } // namespace v8 |
OLD | NEW |