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 2968 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2979 Scope* inner_scope, ZoneList<const AstRawString*>* names, | 2979 Scope* inner_scope, ZoneList<const AstRawString*>* names, |
2980 ForStatement* loop, Statement* init, Expression* cond, Statement* next, | 2980 ForStatement* loop, Statement* init, Expression* cond, Statement* next, |
2981 Statement* body, bool* ok) { | 2981 Statement* body, bool* ok) { |
2982 // ES6 13.6.3.4 specifies that on each loop iteration the let variables are | 2982 // ES6 13.6.3.4 specifies that on each loop iteration the let variables are |
2983 // copied into a new environment. After copying, the "next" statement of the | 2983 // copied into a new environment. After copying, the "next" statement of the |
2984 // loop is executed to update the loop variables. The loop condition is | 2984 // loop is executed to update the loop variables. The loop condition is |
2985 // checked and the loop body is executed. | 2985 // checked and the loop body is executed. |
2986 // | 2986 // |
2987 // We rewrite a for statement of the form | 2987 // We rewrite a for statement of the form |
2988 // | 2988 // |
2989 // for (let x = i; cond; next) body | 2989 // labels: for (let x = i; cond; next) body |
2990 // | 2990 // |
2991 // into | 2991 // into |
2992 // | 2992 // |
2993 // { | 2993 // { |
2994 // let x = i; | 2994 // let x = i; |
2995 // temp_x = x; | 2995 // temp_x = x; |
2996 // flag = 1; | 2996 // first = 1; |
2997 // for (;;) { | 2997 // outer: for (;;) { |
2998 // let x = temp_x; | 2998 // let x = temp_x; |
2999 // if (flag == 1) { | 2999 // if (first == 1) { |
3000 // flag = 0; | 3000 // first = 0; |
| 3001 // } else { |
| 3002 // next; |
| 3003 // } |
| 3004 // flag = 1; |
| 3005 // labels: for (; flag == 1; flag = 0, temp_x = x) { |
| 3006 // if (cond) { |
| 3007 // body |
3001 // } else { | 3008 // } else { |
3002 // next; | 3009 // break outer; |
3003 // } | 3010 // } |
3004 // if (cond) { | 3011 // } |
3005 // <empty> | 3012 // if (flag == 1) { |
3006 // } else { | 3013 // break; |
3007 // break; | 3014 // } |
3008 // } | 3015 // } |
3009 // b | |
3010 // temp_x = x; | |
3011 // } | |
3012 // } | 3016 // } |
3013 | 3017 |
3014 DCHECK(names->length() > 0); | 3018 DCHECK(names->length() > 0); |
3015 Scope* for_scope = scope_; | 3019 Scope* for_scope = scope_; |
3016 ZoneList<Variable*> temps(names->length(), zone()); | 3020 ZoneList<Variable*> temps(names->length(), zone()); |
3017 | 3021 |
3018 Block* outer_block = factory()->NewBlock(NULL, names->length() + 3, false, | 3022 Block* outer_block = factory()->NewBlock(NULL, names->length() + 3, false, |
3019 RelocInfo::kNoPosition); | 3023 RelocInfo::kNoPosition); |
| 3024 |
| 3025 // Add statement: let x = i. |
3020 outer_block->AddStatement(init, zone()); | 3026 outer_block->AddStatement(init, zone()); |
3021 | 3027 |
3022 const AstRawString* temp_name = ast_value_factory()->dot_for_string(); | 3028 const AstRawString* temp_name = ast_value_factory()->dot_for_string(); |
3023 | 3029 |
3024 // For each let variable x: | 3030 // For each let variable x: |
3025 // make statement: temp_x = x. | 3031 // make statement: temp_x = x. |
3026 for (int i = 0; i < names->length(); i++) { | 3032 for (int i = 0; i < names->length(); i++) { |
3027 VariableProxy* proxy = | 3033 VariableProxy* proxy = |
3028 NewUnresolved(names->at(i), LET, Interface::NewValue()); | 3034 NewUnresolved(names->at(i), LET, Interface::NewValue()); |
3029 Variable* temp = scope_->DeclarationScope()->NewTemporary(temp_name); | 3035 Variable* temp = scope_->DeclarationScope()->NewTemporary(temp_name); |
3030 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp); | 3036 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp); |
3031 Assignment* assignment = factory()->NewAssignment( | 3037 Assignment* assignment = factory()->NewAssignment( |
3032 Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition); | 3038 Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition); |
3033 Statement* assignment_statement = factory()->NewExpressionStatement( | 3039 Statement* assignment_statement = factory()->NewExpressionStatement( |
3034 assignment, RelocInfo::kNoPosition); | 3040 assignment, RelocInfo::kNoPosition); |
3035 outer_block->AddStatement(assignment_statement, zone()); | 3041 outer_block->AddStatement(assignment_statement, zone()); |
3036 temps.Add(temp, zone()); | 3042 temps.Add(temp, zone()); |
3037 } | 3043 } |
3038 | 3044 |
3039 Variable* flag = scope_->DeclarationScope()->NewTemporary(temp_name); | 3045 Variable* first = NULL; |
3040 // Make statement: flag = 1. | 3046 // Make statement: first = 1. |
3041 { | 3047 if (next) { |
3042 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag); | 3048 first = scope_->DeclarationScope()->NewTemporary(temp_name); |
| 3049 VariableProxy* first_proxy = factory()->NewVariableProxy(first); |
3043 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition); | 3050 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition); |
3044 Assignment* assignment = factory()->NewAssignment( | 3051 Assignment* assignment = factory()->NewAssignment( |
3045 Token::ASSIGN, flag_proxy, const1, RelocInfo::kNoPosition); | 3052 Token::ASSIGN, first_proxy, const1, RelocInfo::kNoPosition); |
3046 Statement* assignment_statement = factory()->NewExpressionStatement( | 3053 Statement* assignment_statement = |
3047 assignment, RelocInfo::kNoPosition); | 3054 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); |
3048 outer_block->AddStatement(assignment_statement, zone()); | 3055 outer_block->AddStatement(assignment_statement, zone()); |
3049 } | 3056 } |
3050 | 3057 |
3051 outer_block->AddStatement(loop, zone()); | 3058 // Make statement: outer: for (;;) |
| 3059 // Note that we don't actually create the label, or set this loop up as an |
| 3060 // explicit break target, instead handing it directly to those nodes that |
| 3061 // need to know about it. This should be safe because we don't run any code |
| 3062 // in this function that looks up break targets. |
| 3063 ForStatement* outer_loop = |
| 3064 factory()->NewForStatement(NULL, RelocInfo::kNoPosition); |
| 3065 outer_block->AddStatement(outer_loop, zone()); |
| 3066 |
3052 outer_block->set_scope(for_scope); | 3067 outer_block->set_scope(for_scope); |
3053 scope_ = inner_scope; | 3068 scope_ = inner_scope; |
3054 | 3069 |
3055 Block* inner_block = factory()->NewBlock(NULL, 2 * names->length() + 3, | 3070 Block* inner_block = factory()->NewBlock(NULL, names->length() + 4, false, |
3056 false, RelocInfo::kNoPosition); | 3071 RelocInfo::kNoPosition); |
3057 int pos = scanner()->location().beg_pos; | 3072 int pos = scanner()->location().beg_pos; |
3058 ZoneList<Variable*> inner_vars(names->length(), zone()); | 3073 ZoneList<Variable*> inner_vars(names->length(), zone()); |
3059 | 3074 |
3060 // For each let variable x: | 3075 // For each let variable x: |
3061 // make statement: let x = temp_x. | 3076 // make statement: let x = temp_x. |
3062 for (int i = 0; i < names->length(); i++) { | 3077 for (int i = 0; i < names->length(); i++) { |
3063 VariableProxy* proxy = | 3078 VariableProxy* proxy = |
3064 NewUnresolved(names->at(i), LET, Interface::NewValue()); | 3079 NewUnresolved(names->at(i), LET, Interface::NewValue()); |
3065 Declaration* declaration = | 3080 Declaration* declaration = |
3066 factory()->NewVariableDeclaration(proxy, LET, scope_, pos); | 3081 factory()->NewVariableDeclaration(proxy, LET, scope_, pos); |
3067 Declare(declaration, true, CHECK_OK); | 3082 Declare(declaration, true, CHECK_OK); |
3068 inner_vars.Add(declaration->proxy()->var(), zone()); | 3083 inner_vars.Add(declaration->proxy()->var(), zone()); |
3069 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i)); | 3084 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i)); |
3070 Assignment* assignment = factory()->NewAssignment( | 3085 Assignment* assignment = factory()->NewAssignment( |
3071 Token::INIT_LET, proxy, temp_proxy, pos); | 3086 Token::INIT_LET, proxy, temp_proxy, pos); |
3072 Statement* assignment_statement = factory()->NewExpressionStatement( | 3087 Statement* assignment_statement = factory()->NewExpressionStatement( |
3073 assignment, pos); | 3088 assignment, pos); |
3074 proxy->var()->set_initializer_position(pos); | 3089 proxy->var()->set_initializer_position(pos); |
3075 inner_block->AddStatement(assignment_statement, zone()); | 3090 inner_block->AddStatement(assignment_statement, zone()); |
3076 } | 3091 } |
3077 | 3092 |
3078 // Make statement: if (flag == 1) { flag = 0; } else { next; }. | 3093 // Make statement: if (first == 1) { first = 0; } else { next; } |
3079 if (next) { | 3094 if (next) { |
| 3095 DCHECK(first); |
| 3096 Expression* compare = NULL; |
| 3097 // Make compare expression: first == 1. |
| 3098 { |
| 3099 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition); |
| 3100 VariableProxy* first_proxy = factory()->NewVariableProxy(first); |
| 3101 compare = |
| 3102 factory()->NewCompareOperation(Token::EQ, first_proxy, const1, pos); |
| 3103 } |
| 3104 Statement* clear_first = NULL; |
| 3105 // Make statement: first = 0. |
| 3106 { |
| 3107 VariableProxy* first_proxy = factory()->NewVariableProxy(first); |
| 3108 Expression* const0 = factory()->NewSmiLiteral(0, RelocInfo::kNoPosition); |
| 3109 Assignment* assignment = factory()->NewAssignment( |
| 3110 Token::ASSIGN, first_proxy, const0, RelocInfo::kNoPosition); |
| 3111 clear_first = |
| 3112 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); |
| 3113 } |
| 3114 Statement* clear_first_or_next = factory()->NewIfStatement( |
| 3115 compare, clear_first, next, RelocInfo::kNoPosition); |
| 3116 inner_block->AddStatement(clear_first_or_next, zone()); |
| 3117 } |
| 3118 |
| 3119 Variable* flag = scope_->DeclarationScope()->NewTemporary(temp_name); |
| 3120 // Make statement: flag = 1. |
| 3121 { |
| 3122 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag); |
| 3123 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition); |
| 3124 Assignment* assignment = factory()->NewAssignment( |
| 3125 Token::ASSIGN, flag_proxy, const1, RelocInfo::kNoPosition); |
| 3126 Statement* assignment_statement = |
| 3127 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); |
| 3128 inner_block->AddStatement(assignment_statement, zone()); |
| 3129 } |
| 3130 |
| 3131 // Make cond expression for main loop: flag == 1. |
| 3132 Expression* flag_cond = NULL; |
| 3133 { |
| 3134 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition); |
| 3135 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag); |
| 3136 flag_cond = |
| 3137 factory()->NewCompareOperation(Token::EQ, flag_proxy, const1, pos); |
| 3138 } |
| 3139 |
| 3140 // Create chain of expressions "flag = 0, temp_x = x, ..." |
| 3141 Statement* compound_next_statement = NULL; |
| 3142 { |
| 3143 Expression* compound_next = NULL; |
| 3144 // Make expression: flag = 0. |
| 3145 { |
| 3146 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag); |
| 3147 Expression* const0 = factory()->NewSmiLiteral(0, RelocInfo::kNoPosition); |
| 3148 compound_next = factory()->NewAssignment(Token::ASSIGN, flag_proxy, |
| 3149 const0, RelocInfo::kNoPosition); |
| 3150 } |
| 3151 |
| 3152 // Make the comma-separated list of temp_x = x assignments. |
| 3153 for (int i = 0; i < names->length(); i++) { |
| 3154 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i)); |
| 3155 VariableProxy* proxy = factory()->NewVariableProxy(inner_vars.at(i), pos); |
| 3156 Assignment* assignment = factory()->NewAssignment( |
| 3157 Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition); |
| 3158 compound_next = factory()->NewBinaryOperation( |
| 3159 Token::COMMA, compound_next, assignment, RelocInfo::kNoPosition); |
| 3160 } |
| 3161 |
| 3162 compound_next_statement = factory()->NewExpressionStatement( |
| 3163 compound_next, RelocInfo::kNoPosition); |
| 3164 } |
| 3165 |
| 3166 // Make statement: if (cond) { body; } else { break outer; } |
| 3167 Statement* body_or_stop = body; |
| 3168 if (cond) { |
| 3169 Statement* stop = |
| 3170 factory()->NewBreakStatement(outer_loop, RelocInfo::kNoPosition); |
| 3171 body_or_stop = |
| 3172 factory()->NewIfStatement(cond, body, stop, cond->position()); |
| 3173 } |
| 3174 |
| 3175 // Make statement: labels: for (; flag == 1; flag = 0, temp_x = x) |
| 3176 // Note that we re-use the original loop node, which retains it labels |
| 3177 // and ensures that any break or continue statements in body point to |
| 3178 // the right place. |
| 3179 loop->Initialize(NULL, flag_cond, compound_next_statement, body_or_stop); |
| 3180 inner_block->AddStatement(loop, zone()); |
| 3181 |
| 3182 // Make statement: if (flag == 1) { break; } |
| 3183 { |
3080 Expression* compare = NULL; | 3184 Expression* compare = NULL; |
3081 // Make compare expresion: flag == 1. | 3185 // Make compare expresion: flag == 1. |
3082 { | 3186 { |
3083 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition); | 3187 Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition); |
3084 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag); | 3188 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag); |
3085 compare = factory()->NewCompareOperation( | 3189 compare = |
3086 Token::EQ, flag_proxy, const1, pos); | 3190 factory()->NewCompareOperation(Token::EQ, flag_proxy, const1, pos); |
3087 } | 3191 } |
3088 Statement* clear_flag = NULL; | 3192 Statement* stop = |
3089 // Make statement: flag = 0. | 3193 factory()->NewBreakStatement(outer_loop, RelocInfo::kNoPosition); |
3090 { | |
3091 VariableProxy* flag_proxy = factory()->NewVariableProxy(flag); | |
3092 Expression* const0 = factory()->NewSmiLiteral(0, RelocInfo::kNoPosition); | |
3093 Assignment* assignment = factory()->NewAssignment( | |
3094 Token::ASSIGN, flag_proxy, const0, RelocInfo::kNoPosition); | |
3095 clear_flag = factory()->NewExpressionStatement(assignment, pos); | |
3096 } | |
3097 Statement* clear_flag_or_next = factory()->NewIfStatement( | |
3098 compare, clear_flag, next, RelocInfo::kNoPosition); | |
3099 inner_block->AddStatement(clear_flag_or_next, zone()); | |
3100 } | |
3101 | |
3102 | |
3103 // Make statement: if (cond) { } else { break; }. | |
3104 if (cond) { | |
3105 Statement* empty = factory()->NewEmptyStatement(RelocInfo::kNoPosition); | 3194 Statement* empty = factory()->NewEmptyStatement(RelocInfo::kNoPosition); |
3106 BreakableStatement* t = LookupBreakTarget(NULL, CHECK_OK); | 3195 Statement* if_flag_break = |
3107 Statement* stop = factory()->NewBreakStatement(t, RelocInfo::kNoPosition); | 3196 factory()->NewIfStatement(compare, stop, empty, RelocInfo::kNoPosition); |
3108 Statement* if_not_cond_break = factory()->NewIfStatement( | 3197 inner_block->AddStatement(if_flag_break, zone()); |
3109 cond, empty, stop, cond->position()); | |
3110 inner_block->AddStatement(if_not_cond_break, zone()); | |
3111 } | |
3112 | |
3113 inner_block->AddStatement(body, zone()); | |
3114 | |
3115 // For each let variable x: | |
3116 // make statement: temp_x = x; | |
3117 for (int i = 0; i < names->length(); i++) { | |
3118 VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i)); | |
3119 int pos = scanner()->location().end_pos; | |
3120 VariableProxy* proxy = factory()->NewVariableProxy(inner_vars.at(i), pos); | |
3121 Assignment* assignment = factory()->NewAssignment( | |
3122 Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition); | |
3123 Statement* assignment_statement = factory()->NewExpressionStatement( | |
3124 assignment, RelocInfo::kNoPosition); | |
3125 inner_block->AddStatement(assignment_statement, zone()); | |
3126 } | 3198 } |
3127 | 3199 |
3128 inner_scope->set_end_position(scanner()->location().end_pos); | 3200 inner_scope->set_end_position(scanner()->location().end_pos); |
3129 inner_block->set_scope(inner_scope); | 3201 inner_block->set_scope(inner_scope); |
3130 scope_ = for_scope; | 3202 scope_ = for_scope; |
3131 | 3203 |
3132 loop->Initialize(NULL, NULL, NULL, inner_block); | 3204 outer_loop->Initialize(NULL, NULL, NULL, inner_block); |
3133 return outer_block; | 3205 return outer_block; |
3134 } | 3206 } |
3135 | 3207 |
3136 | 3208 |
3137 Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, | 3209 Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, |
3138 bool* ok) { | 3210 bool* ok) { |
3139 // ForStatement :: | 3211 // ForStatement :: |
3140 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement | 3212 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement |
3141 | 3213 |
3142 int stmt_pos = peek_position(); | 3214 int stmt_pos = peek_position(); |
(...skipping 1867 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5010 | 5082 |
5011 // We cannot internalize on a background thread; a foreground task will take | 5083 // We cannot internalize on a background thread; a foreground task will take |
5012 // care of calling Parser::Internalize just before compilation. | 5084 // care of calling Parser::Internalize just before compilation. |
5013 | 5085 |
5014 if (compile_options() == ScriptCompiler::kProduceParserCache) { | 5086 if (compile_options() == ScriptCompiler::kProduceParserCache) { |
5015 if (result != NULL) *info_->cached_data() = recorder.GetScriptData(); | 5087 if (result != NULL) *info_->cached_data() = recorder.GetScriptData(); |
5016 log_ = NULL; | 5088 log_ = NULL; |
5017 } | 5089 } |
5018 } | 5090 } |
5019 } } // namespace v8::internal | 5091 } } // namespace v8::internal |
OLD | NEW |