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

Side by Side Diff: src/parser.cc

Issue 688243005: Reland "Fix stepping in for-loops." (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: fix 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 | Annotate | Revision Log
« no previous file with comments | « src/mips64/full-codegen-mips64.cc ('k') | src/x64/full-codegen-x64.cc » ('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/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 2921 matching lines...) Expand 10 before | Expand all | Expand 10 after
2932 ast_value_factory()->dot_result_string()); 2932 ast_value_factory()->dot_result_string());
2933 2933
2934 Expression* assign_iterator; 2934 Expression* assign_iterator;
2935 Expression* next_result; 2935 Expression* next_result;
2936 Expression* result_done; 2936 Expression* result_done;
2937 Expression* assign_each; 2937 Expression* assign_each;
2938 2938
2939 // var iterator = subject[Symbol.iterator](); 2939 // var iterator = subject[Symbol.iterator]();
2940 assign_iterator = factory()->NewAssignment( 2940 assign_iterator = factory()->NewAssignment(
2941 Token::ASSIGN, factory()->NewVariableProxy(iterator), 2941 Token::ASSIGN, factory()->NewVariableProxy(iterator),
2942 GetIterator(subject, factory()), RelocInfo::kNoPosition); 2942 GetIterator(subject, factory()), subject->position());
2943 2943
2944 // var result = iterator.next(); 2944 // var result = iterator.next();
2945 { 2945 {
2946 Expression* iterator_proxy = factory()->NewVariableProxy(iterator); 2946 Expression* iterator_proxy = factory()->NewVariableProxy(iterator);
2947 Expression* next_literal = factory()->NewStringLiteral( 2947 Expression* next_literal = factory()->NewStringLiteral(
2948 ast_value_factory()->next_string(), RelocInfo::kNoPosition); 2948 ast_value_factory()->next_string(), RelocInfo::kNoPosition);
2949 Expression* next_property = factory()->NewProperty( 2949 Expression* next_property = factory()->NewProperty(
2950 iterator_proxy, next_literal, RelocInfo::kNoPosition); 2950 iterator_proxy, next_literal, RelocInfo::kNoPosition);
2951 ZoneList<Expression*>* next_arguments = 2951 ZoneList<Expression*>* next_arguments =
2952 new(zone()) ZoneList<Expression*>(0, zone()); 2952 new(zone()) ZoneList<Expression*>(0, zone());
2953 Expression* next_call = factory()->NewCall( 2953 Expression* next_call = factory()->NewCall(next_property, next_arguments,
2954 next_property, next_arguments, RelocInfo::kNoPosition); 2954 subject->position());
2955 Expression* result_proxy = factory()->NewVariableProxy(result); 2955 Expression* result_proxy = factory()->NewVariableProxy(result);
2956 next_result = factory()->NewAssignment( 2956 next_result = factory()->NewAssignment(Token::ASSIGN, result_proxy,
2957 Token::ASSIGN, result_proxy, next_call, RelocInfo::kNoPosition); 2957 next_call, subject->position());
2958 } 2958 }
2959 2959
2960 // result.done 2960 // result.done
2961 { 2961 {
2962 Expression* done_literal = factory()->NewStringLiteral( 2962 Expression* done_literal = factory()->NewStringLiteral(
2963 ast_value_factory()->done_string(), RelocInfo::kNoPosition); 2963 ast_value_factory()->done_string(), RelocInfo::kNoPosition);
2964 Expression* result_proxy = factory()->NewVariableProxy(result); 2964 Expression* result_proxy = factory()->NewVariableProxy(result);
2965 result_done = factory()->NewProperty( 2965 result_done = factory()->NewProperty(
2966 result_proxy, done_literal, RelocInfo::kNoPosition); 2966 result_proxy, done_literal, RelocInfo::kNoPosition);
2967 } 2967 }
2968 2968
2969 // each = result.value 2969 // each = result.value
2970 { 2970 {
2971 Expression* value_literal = factory()->NewStringLiteral( 2971 Expression* value_literal = factory()->NewStringLiteral(
2972 ast_value_factory()->value_string(), RelocInfo::kNoPosition); 2972 ast_value_factory()->value_string(), RelocInfo::kNoPosition);
2973 Expression* result_proxy = factory()->NewVariableProxy(result); 2973 Expression* result_proxy = factory()->NewVariableProxy(result);
2974 Expression* result_value = factory()->NewProperty( 2974 Expression* result_value = factory()->NewProperty(
2975 result_proxy, value_literal, RelocInfo::kNoPosition); 2975 result_proxy, value_literal, RelocInfo::kNoPosition);
2976 assign_each = factory()->NewAssignment( 2976 assign_each = factory()->NewAssignment(Token::ASSIGN, each, result_value,
2977 Token::ASSIGN, each, result_value, RelocInfo::kNoPosition); 2977 each->position());
2978 } 2978 }
2979 2979
2980 for_of->Initialize(each, subject, body, 2980 for_of->Initialize(each, subject, body,
2981 assign_iterator, 2981 assign_iterator,
2982 next_result, 2982 next_result,
2983 result_done, 2983 result_done,
2984 assign_each); 2984 assign_each);
2985 } else { 2985 } else {
2986 stmt->Initialize(each, subject, body); 2986 stmt->Initialize(each, subject, body);
2987 } 2987 }
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
3145 loop->Initialize(NULL, NULL, NULL, inner_block); 3145 loop->Initialize(NULL, NULL, NULL, inner_block);
3146 return outer_block; 3146 return outer_block;
3147 } 3147 }
3148 3148
3149 3149
3150 Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, 3150 Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
3151 bool* ok) { 3151 bool* ok) {
3152 // ForStatement :: 3152 // ForStatement ::
3153 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement 3153 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
3154 3154
3155 int pos = peek_position(); 3155 int stmt_pos = peek_position();
3156 Statement* init = NULL; 3156 Statement* init = NULL;
3157 ZoneList<const AstRawString*> let_bindings(1, zone()); 3157 ZoneList<const AstRawString*> let_bindings(1, zone());
3158 3158
3159 // Create an in-between scope for let-bound iteration variables. 3159 // Create an in-between scope for let-bound iteration variables.
3160 Scope* saved_scope = scope_; 3160 Scope* saved_scope = scope_;
3161 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE); 3161 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE);
3162 scope_ = for_scope; 3162 scope_ = for_scope;
3163 3163
3164 Expect(Token::FOR, CHECK_OK); 3164 Expect(Token::FOR, CHECK_OK);
3165 Expect(Token::LPAREN, CHECK_OK); 3165 Expect(Token::LPAREN, CHECK_OK);
3166 for_scope->set_start_position(scanner()->location().beg_pos); 3166 for_scope->set_start_position(scanner()->location().beg_pos);
3167 if (peek() != Token::SEMICOLON) { 3167 if (peek() != Token::SEMICOLON) {
3168 if (peek() == Token::VAR || 3168 if (peek() == Token::VAR ||
3169 (peek() == Token::CONST && strict_mode() == SLOPPY)) { 3169 (peek() == Token::CONST && strict_mode() == SLOPPY)) {
3170 bool is_const = peek() == Token::CONST; 3170 bool is_const = peek() == Token::CONST;
3171 const AstRawString* name = NULL; 3171 const AstRawString* name = NULL;
3172 VariableDeclarationProperties decl_props = kHasNoInitializers; 3172 VariableDeclarationProperties decl_props = kHasNoInitializers;
3173 Block* variable_statement = 3173 Block* variable_statement =
3174 ParseVariableDeclarations(kForStatement, &decl_props, NULL, &name, 3174 ParseVariableDeclarations(kForStatement, &decl_props, NULL, &name,
3175 CHECK_OK); 3175 CHECK_OK);
3176 bool accept_OF = decl_props == kHasNoInitializers; 3176 bool accept_OF = decl_props == kHasNoInitializers;
3177 ForEachStatement::VisitMode mode; 3177 ForEachStatement::VisitMode mode;
3178 int each_pos = position();
3178 3179
3179 if (name != NULL && CheckInOrOf(accept_OF, &mode)) { 3180 if (name != NULL && CheckInOrOf(accept_OF, &mode)) {
3180 Interface* interface = 3181 Interface* interface =
3181 is_const ? Interface::NewConst() : Interface::NewValue(); 3182 is_const ? Interface::NewConst() : Interface::NewValue();
3182 ForEachStatement* loop = 3183 ForEachStatement* loop =
3183 factory()->NewForEachStatement(mode, labels, pos); 3184 factory()->NewForEachStatement(mode, labels, stmt_pos);
3184 Target target(&this->target_stack_, loop); 3185 Target target(&this->target_stack_, loop);
3185 3186
3186 Expression* enumerable = ParseExpression(true, CHECK_OK); 3187 Expression* enumerable = ParseExpression(true, CHECK_OK);
3187 Expect(Token::RPAREN, CHECK_OK); 3188 Expect(Token::RPAREN, CHECK_OK);
3188 3189
3189 VariableProxy* each = 3190 VariableProxy* each =
3190 scope_->NewUnresolved(factory(), name, interface); 3191 scope_->NewUnresolved(factory(), name, interface, each_pos);
3191 Statement* body = ParseStatement(NULL, CHECK_OK); 3192 Statement* body = ParseStatement(NULL, CHECK_OK);
3192 InitializeForEachStatement(loop, each, enumerable, body); 3193 InitializeForEachStatement(loop, each, enumerable, body);
3193 Block* result = 3194 Block* result =
3194 factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition); 3195 factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition);
3195 result->AddStatement(variable_statement, zone()); 3196 result->AddStatement(variable_statement, zone());
3196 result->AddStatement(loop, zone()); 3197 result->AddStatement(loop, zone());
3197 scope_ = saved_scope; 3198 scope_ = saved_scope;
3198 for_scope->set_end_position(scanner()->location().end_pos); 3199 for_scope->set_end_position(scanner()->location().end_pos);
3199 for_scope = for_scope->FinalizeBlockScope(); 3200 for_scope = for_scope->FinalizeBlockScope();
3200 DCHECK(for_scope == NULL); 3201 DCHECK(for_scope == NULL);
3201 // Parsed for-in loop w/ variable/const declaration. 3202 // Parsed for-in loop w/ variable/const declaration.
3202 return result; 3203 return result;
3203 } else { 3204 } else {
3204 init = variable_statement; 3205 init = variable_statement;
3205 } 3206 }
3206 } else if ((peek() == Token::LET || peek() == Token::CONST) && 3207 } else if ((peek() == Token::LET || peek() == Token::CONST) &&
3207 strict_mode() == STRICT) { 3208 strict_mode() == STRICT) {
3208 bool is_const = peek() == Token::CONST; 3209 bool is_const = peek() == Token::CONST;
3209 const AstRawString* name = NULL; 3210 const AstRawString* name = NULL;
3210 VariableDeclarationProperties decl_props = kHasNoInitializers; 3211 VariableDeclarationProperties decl_props = kHasNoInitializers;
3211 Block* variable_statement = 3212 Block* variable_statement =
3212 ParseVariableDeclarations(kForStatement, &decl_props, &let_bindings, 3213 ParseVariableDeclarations(kForStatement, &decl_props, &let_bindings,
3213 &name, CHECK_OK); 3214 &name, CHECK_OK);
3214 bool accept_IN = name != NULL && decl_props != kHasInitializers; 3215 bool accept_IN = name != NULL && decl_props != kHasInitializers;
3215 bool accept_OF = decl_props == kHasNoInitializers; 3216 bool accept_OF = decl_props == kHasNoInitializers;
3216 ForEachStatement::VisitMode mode; 3217 ForEachStatement::VisitMode mode;
3218 int each_pos = position();
3217 3219
3218 if (accept_IN && CheckInOrOf(accept_OF, &mode)) { 3220 if (accept_IN && CheckInOrOf(accept_OF, &mode)) {
3219 // Rewrite a for-in statement of the form 3221 // Rewrite a for-in statement of the form
3220 // 3222 //
3221 // for (let/const x in e) b 3223 // for (let/const x in e) b
3222 // 3224 //
3223 // into 3225 // into
3224 // 3226 //
3225 // <let x' be a temporary variable> 3227 // <let x' be a temporary variable>
3226 // for (x' in e) { 3228 // for (x' in e) {
3227 // let/const x; 3229 // let/const x;
3228 // x = x'; 3230 // x = x';
3229 // b; 3231 // b;
3230 // } 3232 // }
3231 3233
3232 // TODO(keuchel): Move the temporary variable to the block scope, after 3234 // TODO(keuchel): Move the temporary variable to the block scope, after
3233 // implementing stack allocated block scoped variables. 3235 // implementing stack allocated block scoped variables.
3234 Variable* temp = scope_->DeclarationScope()->NewTemporary( 3236 Variable* temp = scope_->DeclarationScope()->NewTemporary(
3235 ast_value_factory()->dot_for_string()); 3237 ast_value_factory()->dot_for_string());
3236 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp); 3238 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp, each_pos);
3237 ForEachStatement* loop = 3239 ForEachStatement* loop =
3238 factory()->NewForEachStatement(mode, labels, pos); 3240 factory()->NewForEachStatement(mode, labels, stmt_pos);
3239 Target target(&this->target_stack_, loop); 3241 Target target(&this->target_stack_, loop);
3240 3242
3241 // The expression does not see the loop variable. 3243 // The expression does not see the loop variable.
3242 scope_ = saved_scope; 3244 scope_ = saved_scope;
3243 Expression* enumerable = ParseExpression(true, CHECK_OK); 3245 Expression* enumerable = ParseExpression(true, CHECK_OK);
3244 scope_ = for_scope; 3246 scope_ = for_scope;
3245 Expect(Token::RPAREN, CHECK_OK); 3247 Expect(Token::RPAREN, CHECK_OK);
3246 3248
3247 VariableProxy* each = scope_->NewUnresolved(factory(), name); 3249 VariableProxy* each = scope_->NewUnresolved(
3250 factory(), name, Interface::NewValue(), each_pos);
3248 Statement* body = ParseStatement(NULL, CHECK_OK); 3251 Statement* body = ParseStatement(NULL, CHECK_OK);
3249 Block* body_block = 3252 Block* body_block =
3250 factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition); 3253 factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition);
3251 Token::Value init_op = is_const ? Token::INIT_CONST : Token::ASSIGN; 3254 Token::Value init_op = is_const ? Token::INIT_CONST : Token::ASSIGN;
3252 Assignment* assignment = factory()->NewAssignment( 3255 Assignment* assignment = factory()->NewAssignment(
3253 init_op, each, temp_proxy, RelocInfo::kNoPosition); 3256 init_op, each, temp_proxy, RelocInfo::kNoPosition);
3254 Statement* assignment_statement = factory()->NewExpressionStatement( 3257 Statement* assignment_statement = factory()->NewExpressionStatement(
3255 assignment, RelocInfo::kNoPosition); 3258 assignment, RelocInfo::kNoPosition);
3256 body_block->AddStatement(variable_statement, zone()); 3259 body_block->AddStatement(variable_statement, zone());
3257 body_block->AddStatement(assignment_statement, zone()); 3260 body_block->AddStatement(assignment_statement, zone());
(...skipping 13 matching lines...) Expand all
3271 Scanner::Location lhs_location = scanner()->peek_location(); 3274 Scanner::Location lhs_location = scanner()->peek_location();
3272 Expression* expression = ParseExpression(false, CHECK_OK); 3275 Expression* expression = ParseExpression(false, CHECK_OK);
3273 ForEachStatement::VisitMode mode; 3276 ForEachStatement::VisitMode mode;
3274 bool accept_OF = expression->IsVariableProxy(); 3277 bool accept_OF = expression->IsVariableProxy();
3275 3278
3276 if (CheckInOrOf(accept_OF, &mode)) { 3279 if (CheckInOrOf(accept_OF, &mode)) {
3277 expression = this->CheckAndRewriteReferenceExpression( 3280 expression = this->CheckAndRewriteReferenceExpression(
3278 expression, lhs_location, "invalid_lhs_in_for", CHECK_OK); 3281 expression, lhs_location, "invalid_lhs_in_for", CHECK_OK);
3279 3282
3280 ForEachStatement* loop = 3283 ForEachStatement* loop =
3281 factory()->NewForEachStatement(mode, labels, pos); 3284 factory()->NewForEachStatement(mode, labels, stmt_pos);
3282 Target target(&this->target_stack_, loop); 3285 Target target(&this->target_stack_, loop);
3283 3286
3284 Expression* enumerable = ParseExpression(true, CHECK_OK); 3287 Expression* enumerable = ParseExpression(true, CHECK_OK);
3285 Expect(Token::RPAREN, CHECK_OK); 3288 Expect(Token::RPAREN, CHECK_OK);
3286 3289
3287 Statement* body = ParseStatement(NULL, CHECK_OK); 3290 Statement* body = ParseStatement(NULL, CHECK_OK);
3288 InitializeForEachStatement(loop, expression, enumerable, body); 3291 InitializeForEachStatement(loop, expression, enumerable, body);
3289 scope_ = saved_scope; 3292 scope_ = saved_scope;
3290 for_scope->set_end_position(scanner()->location().end_pos); 3293 for_scope->set_end_position(scanner()->location().end_pos);
3291 for_scope = for_scope->FinalizeBlockScope(); 3294 for_scope = for_scope->FinalizeBlockScope();
3292 DCHECK(for_scope == NULL); 3295 DCHECK(for_scope == NULL);
3293 // Parsed for-in loop. 3296 // Parsed for-in loop.
3294 return loop; 3297 return loop;
3295 3298
3296 } else { 3299 } else {
3297 init = factory()->NewExpressionStatement( 3300 init = factory()->NewExpressionStatement(expression, position());
3298 expression, RelocInfo::kNoPosition);
3299 } 3301 }
3300 } 3302 }
3301 } 3303 }
3302 3304
3303 // Standard 'for' loop 3305 // Standard 'for' loop
3304 ForStatement* loop = factory()->NewForStatement(labels, pos); 3306 ForStatement* loop = factory()->NewForStatement(labels, stmt_pos);
3305 Target target(&this->target_stack_, loop); 3307 Target target(&this->target_stack_, loop);
3306 3308
3307 // Parsed initializer at this point. 3309 // Parsed initializer at this point.
3308 Expect(Token::SEMICOLON, CHECK_OK); 3310 Expect(Token::SEMICOLON, CHECK_OK);
3309 3311
3310 // If there are let bindings, then condition and the next statement of the 3312 // If there are let bindings, then condition and the next statement of the
3311 // for loop must be parsed in a new scope. 3313 // for loop must be parsed in a new scope.
3312 Scope* inner_scope = NULL; 3314 Scope* inner_scope = NULL;
3313 if (let_bindings.length() > 0) { 3315 if (let_bindings.length() > 0) {
3314 inner_scope = NewScope(for_scope, BLOCK_SCOPE); 3316 inner_scope = NewScope(for_scope, BLOCK_SCOPE);
3315 inner_scope->set_start_position(scanner()->location().beg_pos); 3317 inner_scope->set_start_position(scanner()->location().beg_pos);
3316 scope_ = inner_scope; 3318 scope_ = inner_scope;
3317 } 3319 }
3318 3320
3319 Expression* cond = NULL; 3321 Expression* cond = NULL;
3320 if (peek() != Token::SEMICOLON) { 3322 if (peek() != Token::SEMICOLON) {
3321 cond = ParseExpression(true, CHECK_OK); 3323 cond = ParseExpression(true, CHECK_OK);
3322 } 3324 }
3323 Expect(Token::SEMICOLON, CHECK_OK); 3325 Expect(Token::SEMICOLON, CHECK_OK);
3324 3326
3325 Statement* next = NULL; 3327 Statement* next = NULL;
3326 if (peek() != Token::RPAREN) { 3328 if (peek() != Token::RPAREN) {
3329 int next_pos = position();
3327 Expression* exp = ParseExpression(true, CHECK_OK); 3330 Expression* exp = ParseExpression(true, CHECK_OK);
3328 next = factory()->NewExpressionStatement(exp, RelocInfo::kNoPosition); 3331 next = factory()->NewExpressionStatement(exp, next_pos);
3329 } 3332 }
3330 Expect(Token::RPAREN, CHECK_OK); 3333 Expect(Token::RPAREN, CHECK_OK);
3331 3334
3332 Statement* body = ParseStatement(NULL, CHECK_OK); 3335 Statement* body = ParseStatement(NULL, CHECK_OK);
3333 3336
3334 Statement* result = NULL; 3337 Statement* result = NULL;
3335 if (let_bindings.length() > 0) { 3338 if (let_bindings.length() > 0) {
3336 scope_ = for_scope; 3339 scope_ = for_scope;
3337 result = DesugarLetBindingsInForStatement(inner_scope, &let_bindings, loop, 3340 result = DesugarLetBindingsInForStatement(inner_scope, &let_bindings, loop,
3338 init, cond, next, body, CHECK_OK); 3341 init, cond, next, body, CHECK_OK);
(...skipping 1684 matching lines...) Expand 10 before | Expand all | Expand 10 after
5023 5026
5024 // We cannot internalize on a background thread; a foreground task will take 5027 // We cannot internalize on a background thread; a foreground task will take
5025 // care of calling Parser::Internalize just before compilation. 5028 // care of calling Parser::Internalize just before compilation.
5026 5029
5027 if (compile_options() == ScriptCompiler::kProduceParserCache) { 5030 if (compile_options() == ScriptCompiler::kProduceParserCache) {
5028 if (result != NULL) *info_->cached_data() = recorder.GetScriptData(); 5031 if (result != NULL) *info_->cached_data() = recorder.GetScriptData();
5029 log_ = NULL; 5032 log_ = NULL;
5030 } 5033 }
5031 } 5034 }
5032 } } // namespace v8::internal 5035 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/mips64/full-codegen-mips64.cc ('k') | src/x64/full-codegen-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698