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

Side by Side Diff: src/parser.cc

Issue 682413004: Fix stepping in for-loops. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: 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 2853 matching lines...) Expand 10 before | Expand all | Expand 10 after
2864 ast_value_factory()->dot_result_string()); 2864 ast_value_factory()->dot_result_string());
2865 2865
2866 Expression* assign_iterator; 2866 Expression* assign_iterator;
2867 Expression* next_result; 2867 Expression* next_result;
2868 Expression* result_done; 2868 Expression* result_done;
2869 Expression* assign_each; 2869 Expression* assign_each;
2870 2870
2871 // var iterator = subject[Symbol.iterator](); 2871 // var iterator = subject[Symbol.iterator]();
2872 assign_iterator = factory()->NewAssignment( 2872 assign_iterator = factory()->NewAssignment(
2873 Token::ASSIGN, factory()->NewVariableProxy(iterator), 2873 Token::ASSIGN, factory()->NewVariableProxy(iterator),
2874 GetIterator(subject, factory()), RelocInfo::kNoPosition); 2874 GetIterator(subject, factory()), subject->position());
2875 2875
2876 // var result = iterator.next(); 2876 // var result = iterator.next();
2877 { 2877 {
2878 Expression* iterator_proxy = factory()->NewVariableProxy(iterator); 2878 Expression* iterator_proxy = factory()->NewVariableProxy(iterator);
2879 Expression* next_literal = factory()->NewStringLiteral( 2879 Expression* next_literal = factory()->NewStringLiteral(
2880 ast_value_factory()->next_string(), RelocInfo::kNoPosition); 2880 ast_value_factory()->next_string(), RelocInfo::kNoPosition);
2881 Expression* next_property = factory()->NewProperty( 2881 Expression* next_property = factory()->NewProperty(
2882 iterator_proxy, next_literal, RelocInfo::kNoPosition); 2882 iterator_proxy, next_literal, RelocInfo::kNoPosition);
2883 ZoneList<Expression*>* next_arguments = 2883 ZoneList<Expression*>* next_arguments =
2884 new(zone()) ZoneList<Expression*>(0, zone()); 2884 new(zone()) ZoneList<Expression*>(0, zone());
2885 Expression* next_call = factory()->NewCall( 2885 Expression* next_call = factory()->NewCall(next_property, next_arguments,
2886 next_property, next_arguments, RelocInfo::kNoPosition); 2886 subject->position());
2887 Expression* result_proxy = factory()->NewVariableProxy(result); 2887 Expression* result_proxy = factory()->NewVariableProxy(result);
2888 next_result = factory()->NewAssignment( 2888 next_result = factory()->NewAssignment(Token::ASSIGN, result_proxy,
2889 Token::ASSIGN, result_proxy, next_call, RelocInfo::kNoPosition); 2889 next_call, subject->position());
2890 } 2890 }
2891 2891
2892 // result.done 2892 // result.done
2893 { 2893 {
2894 Expression* done_literal = factory()->NewStringLiteral( 2894 Expression* done_literal = factory()->NewStringLiteral(
2895 ast_value_factory()->done_string(), RelocInfo::kNoPosition); 2895 ast_value_factory()->done_string(), RelocInfo::kNoPosition);
2896 Expression* result_proxy = factory()->NewVariableProxy(result); 2896 Expression* result_proxy = factory()->NewVariableProxy(result);
2897 result_done = factory()->NewProperty( 2897 result_done = factory()->NewProperty(
2898 result_proxy, done_literal, RelocInfo::kNoPosition); 2898 result_proxy, done_literal, RelocInfo::kNoPosition);
2899 } 2899 }
2900 2900
2901 // each = result.value 2901 // each = result.value
2902 { 2902 {
2903 Expression* value_literal = factory()->NewStringLiteral( 2903 Expression* value_literal = factory()->NewStringLiteral(
2904 ast_value_factory()->value_string(), RelocInfo::kNoPosition); 2904 ast_value_factory()->value_string(), RelocInfo::kNoPosition);
2905 Expression* result_proxy = factory()->NewVariableProxy(result); 2905 Expression* result_proxy = factory()->NewVariableProxy(result);
2906 Expression* result_value = factory()->NewProperty( 2906 Expression* result_value = factory()->NewProperty(
2907 result_proxy, value_literal, RelocInfo::kNoPosition); 2907 result_proxy, value_literal, RelocInfo::kNoPosition);
2908 assign_each = factory()->NewAssignment( 2908 assign_each = factory()->NewAssignment(Token::ASSIGN, each, result_value,
2909 Token::ASSIGN, each, result_value, RelocInfo::kNoPosition); 2909 each->position());
2910 } 2910 }
2911 2911
2912 for_of->Initialize(each, subject, body, 2912 for_of->Initialize(each, subject, body,
2913 assign_iterator, 2913 assign_iterator,
2914 next_result, 2914 next_result,
2915 result_done, 2915 result_done,
2916 assign_each); 2916 assign_each);
2917 } else { 2917 } else {
2918 stmt->Initialize(each, subject, body); 2918 stmt->Initialize(each, subject, body);
2919 } 2919 }
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
3077 loop->Initialize(NULL, NULL, NULL, inner_block); 3077 loop->Initialize(NULL, NULL, NULL, inner_block);
3078 return outer_block; 3078 return outer_block;
3079 } 3079 }
3080 3080
3081 3081
3082 Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, 3082 Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
3083 bool* ok) { 3083 bool* ok) {
3084 // ForStatement :: 3084 // ForStatement ::
3085 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement 3085 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
3086 3086
3087 int pos = peek_position(); 3087 int stmt_pos = peek_position();
3088 Statement* init = NULL; 3088 Statement* init = NULL;
3089 ZoneList<const AstRawString*> let_bindings(1, zone()); 3089 ZoneList<const AstRawString*> let_bindings(1, zone());
3090 3090
3091 // Create an in-between scope for let-bound iteration variables. 3091 // Create an in-between scope for let-bound iteration variables.
3092 Scope* saved_scope = scope_; 3092 Scope* saved_scope = scope_;
3093 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE); 3093 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE);
3094 scope_ = for_scope; 3094 scope_ = for_scope;
3095 3095
3096 Expect(Token::FOR, CHECK_OK); 3096 Expect(Token::FOR, CHECK_OK);
3097 Expect(Token::LPAREN, CHECK_OK); 3097 Expect(Token::LPAREN, CHECK_OK);
3098 for_scope->set_start_position(scanner()->location().beg_pos); 3098 for_scope->set_start_position(scanner()->location().beg_pos);
3099 if (peek() != Token::SEMICOLON) { 3099 if (peek() != Token::SEMICOLON) {
3100 if (peek() == Token::VAR || 3100 if (peek() == Token::VAR ||
3101 (peek() == Token::CONST && strict_mode() == SLOPPY)) { 3101 (peek() == Token::CONST && strict_mode() == SLOPPY)) {
3102 bool is_const = peek() == Token::CONST; 3102 bool is_const = peek() == Token::CONST;
3103 const AstRawString* name = NULL; 3103 const AstRawString* name = NULL;
3104 VariableDeclarationProperties decl_props = kHasNoInitializers; 3104 VariableDeclarationProperties decl_props = kHasNoInitializers;
3105 Block* variable_statement = 3105 Block* variable_statement =
3106 ParseVariableDeclarations(kForStatement, &decl_props, NULL, &name, 3106 ParseVariableDeclarations(kForStatement, &decl_props, NULL, &name,
3107 CHECK_OK); 3107 CHECK_OK);
3108 bool accept_OF = decl_props == kHasNoInitializers; 3108 bool accept_OF = decl_props == kHasNoInitializers;
3109 ForEachStatement::VisitMode mode; 3109 ForEachStatement::VisitMode mode;
3110 int each_pos = position();
3110 3111
3111 if (name != NULL && CheckInOrOf(accept_OF, &mode)) { 3112 if (name != NULL && CheckInOrOf(accept_OF, &mode)) {
3112 Interface* interface = 3113 Interface* interface =
3113 is_const ? Interface::NewConst() : Interface::NewValue(); 3114 is_const ? Interface::NewConst() : Interface::NewValue();
3114 ForEachStatement* loop = 3115 ForEachStatement* loop =
3115 factory()->NewForEachStatement(mode, labels, pos); 3116 factory()->NewForEachStatement(mode, labels, stmt_pos);
3116 Target target(&this->target_stack_, loop); 3117 Target target(&this->target_stack_, loop);
3117 3118
3118 Expression* enumerable = ParseExpression(true, CHECK_OK); 3119 Expression* enumerable = ParseExpression(true, CHECK_OK);
3119 Expect(Token::RPAREN, CHECK_OK); 3120 Expect(Token::RPAREN, CHECK_OK);
3120 3121
3121 VariableProxy* each = 3122 VariableProxy* each =
3122 scope_->NewUnresolved(factory(), name, interface); 3123 scope_->NewUnresolved(factory(), name, interface, each_pos);
3123 Statement* body = ParseStatement(NULL, CHECK_OK); 3124 Statement* body = ParseStatement(NULL, CHECK_OK);
3124 InitializeForEachStatement(loop, each, enumerable, body); 3125 InitializeForEachStatement(loop, each, enumerable, body);
3125 Block* result = 3126 Block* result =
3126 factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition); 3127 factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition);
3127 result->AddStatement(variable_statement, zone()); 3128 result->AddStatement(variable_statement, zone());
3128 result->AddStatement(loop, zone()); 3129 result->AddStatement(loop, zone());
3129 scope_ = saved_scope; 3130 scope_ = saved_scope;
3130 for_scope->set_end_position(scanner()->location().end_pos); 3131 for_scope->set_end_position(scanner()->location().end_pos);
3131 for_scope = for_scope->FinalizeBlockScope(); 3132 for_scope = for_scope->FinalizeBlockScope();
3132 DCHECK(for_scope == NULL); 3133 DCHECK(for_scope == NULL);
3133 // Parsed for-in loop w/ variable/const declaration. 3134 // Parsed for-in loop w/ variable/const declaration.
3134 return result; 3135 return result;
3135 } else { 3136 } else {
3136 init = variable_statement; 3137 init = variable_statement;
3137 } 3138 }
3138 } else if ((peek() == Token::LET || peek() == Token::CONST) && 3139 } else if ((peek() == Token::LET || peek() == Token::CONST) &&
3139 strict_mode() == STRICT) { 3140 strict_mode() == STRICT) {
3140 bool is_const = peek() == Token::CONST; 3141 bool is_const = peek() == Token::CONST;
3141 const AstRawString* name = NULL; 3142 const AstRawString* name = NULL;
3142 VariableDeclarationProperties decl_props = kHasNoInitializers; 3143 VariableDeclarationProperties decl_props = kHasNoInitializers;
3143 Block* variable_statement = 3144 Block* variable_statement =
3144 ParseVariableDeclarations(kForStatement, &decl_props, &let_bindings, 3145 ParseVariableDeclarations(kForStatement, &decl_props, &let_bindings,
3145 &name, CHECK_OK); 3146 &name, CHECK_OK);
3146 bool accept_IN = name != NULL && decl_props != kHasInitializers; 3147 bool accept_IN = name != NULL && decl_props != kHasInitializers;
3147 bool accept_OF = decl_props == kHasNoInitializers; 3148 bool accept_OF = decl_props == kHasNoInitializers;
3148 ForEachStatement::VisitMode mode; 3149 ForEachStatement::VisitMode mode;
3150 int each_pos = position();
3149 3151
3150 if (accept_IN && CheckInOrOf(accept_OF, &mode)) { 3152 if (accept_IN && CheckInOrOf(accept_OF, &mode)) {
3151 // Rewrite a for-in statement of the form 3153 // Rewrite a for-in statement of the form
3152 // 3154 //
3153 // for (let/const x in e) b 3155 // for (let/const x in e) b
3154 // 3156 //
3155 // into 3157 // into
3156 // 3158 //
3157 // <let x' be a temporary variable> 3159 // <let x' be a temporary variable>
3158 // for (x' in e) { 3160 // for (x' in e) {
3159 // let/const x; 3161 // let/const x;
3160 // x = x'; 3162 // x = x';
3161 // b; 3163 // b;
3162 // } 3164 // }
3163 3165
3164 // TODO(keuchel): Move the temporary variable to the block scope, after 3166 // TODO(keuchel): Move the temporary variable to the block scope, after
3165 // implementing stack allocated block scoped variables. 3167 // implementing stack allocated block scoped variables.
3166 Variable* temp = scope_->DeclarationScope()->NewTemporary( 3168 Variable* temp = scope_->DeclarationScope()->NewTemporary(
3167 ast_value_factory()->dot_for_string()); 3169 ast_value_factory()->dot_for_string());
3168 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp); 3170 VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
3169 ForEachStatement* loop = 3171 ForEachStatement* loop =
3170 factory()->NewForEachStatement(mode, labels, pos); 3172 factory()->NewForEachStatement(mode, labels, stmt_pos);
3171 Target target(&this->target_stack_, loop); 3173 Target target(&this->target_stack_, loop);
3172 3174
3173 // The expression does not see the loop variable. 3175 // The expression does not see the loop variable.
3174 scope_ = saved_scope; 3176 scope_ = saved_scope;
3175 Expression* enumerable = ParseExpression(true, CHECK_OK); 3177 Expression* enumerable = ParseExpression(true, CHECK_OK);
3176 scope_ = for_scope; 3178 scope_ = for_scope;
3177 Expect(Token::RPAREN, CHECK_OK); 3179 Expect(Token::RPAREN, CHECK_OK);
3178 3180
3179 VariableProxy* each = scope_->NewUnresolved(factory(), name); 3181 VariableProxy* each = scope_->NewUnresolved(
3182 factory(), name, Interface::NewValue(), each_pos);
3180 Statement* body = ParseStatement(NULL, CHECK_OK); 3183 Statement* body = ParseStatement(NULL, CHECK_OK);
3181 Block* body_block = 3184 Block* body_block =
3182 factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition); 3185 factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition);
3183 Token::Value init_op = is_const ? Token::INIT_CONST : Token::ASSIGN; 3186 Token::Value init_op = is_const ? Token::INIT_CONST : Token::ASSIGN;
3184 Assignment* assignment = factory()->NewAssignment( 3187 Assignment* assignment = factory()->NewAssignment(
3185 init_op, each, temp_proxy, RelocInfo::kNoPosition); 3188 init_op, each, temp_proxy, RelocInfo::kNoPosition);
3186 Statement* assignment_statement = factory()->NewExpressionStatement( 3189 Statement* assignment_statement = factory()->NewExpressionStatement(
3187 assignment, RelocInfo::kNoPosition); 3190 assignment, RelocInfo::kNoPosition);
3188 body_block->AddStatement(variable_statement, zone()); 3191 body_block->AddStatement(variable_statement, zone());
3189 body_block->AddStatement(assignment_statement, zone()); 3192 body_block->AddStatement(assignment_statement, zone());
(...skipping 13 matching lines...) Expand all
3203 Scanner::Location lhs_location = scanner()->peek_location(); 3206 Scanner::Location lhs_location = scanner()->peek_location();
3204 Expression* expression = ParseExpression(false, CHECK_OK); 3207 Expression* expression = ParseExpression(false, CHECK_OK);
3205 ForEachStatement::VisitMode mode; 3208 ForEachStatement::VisitMode mode;
3206 bool accept_OF = expression->IsVariableProxy(); 3209 bool accept_OF = expression->IsVariableProxy();
3207 3210
3208 if (CheckInOrOf(accept_OF, &mode)) { 3211 if (CheckInOrOf(accept_OF, &mode)) {
3209 expression = this->CheckAndRewriteReferenceExpression( 3212 expression = this->CheckAndRewriteReferenceExpression(
3210 expression, lhs_location, "invalid_lhs_in_for", CHECK_OK); 3213 expression, lhs_location, "invalid_lhs_in_for", CHECK_OK);
3211 3214
3212 ForEachStatement* loop = 3215 ForEachStatement* loop =
3213 factory()->NewForEachStatement(mode, labels, pos); 3216 factory()->NewForEachStatement(mode, labels, stmt_pos);
3214 Target target(&this->target_stack_, loop); 3217 Target target(&this->target_stack_, loop);
3215 3218
3216 Expression* enumerable = ParseExpression(true, CHECK_OK); 3219 Expression* enumerable = ParseExpression(true, CHECK_OK);
3217 Expect(Token::RPAREN, CHECK_OK); 3220 Expect(Token::RPAREN, CHECK_OK);
3218 3221
3219 Statement* body = ParseStatement(NULL, CHECK_OK); 3222 Statement* body = ParseStatement(NULL, CHECK_OK);
3220 InitializeForEachStatement(loop, expression, enumerable, body); 3223 InitializeForEachStatement(loop, expression, enumerable, body);
3221 scope_ = saved_scope; 3224 scope_ = saved_scope;
3222 for_scope->set_end_position(scanner()->location().end_pos); 3225 for_scope->set_end_position(scanner()->location().end_pos);
3223 for_scope = for_scope->FinalizeBlockScope(); 3226 for_scope = for_scope->FinalizeBlockScope();
3224 DCHECK(for_scope == NULL); 3227 DCHECK(for_scope == NULL);
3225 // Parsed for-in loop. 3228 // Parsed for-in loop.
3226 return loop; 3229 return loop;
3227 3230
3228 } else { 3231 } else {
3229 init = factory()->NewExpressionStatement( 3232 init = factory()->NewExpressionStatement(expression, position());
3230 expression, RelocInfo::kNoPosition);
3231 } 3233 }
3232 } 3234 }
3233 } 3235 }
3234 3236
3235 // Standard 'for' loop 3237 // Standard 'for' loop
3236 ForStatement* loop = factory()->NewForStatement(labels, pos); 3238 ForStatement* loop = factory()->NewForStatement(labels, stmt_pos);
3237 Target target(&this->target_stack_, loop); 3239 Target target(&this->target_stack_, loop);
3238 3240
3239 // Parsed initializer at this point. 3241 // Parsed initializer at this point.
3240 Expect(Token::SEMICOLON, CHECK_OK); 3242 Expect(Token::SEMICOLON, CHECK_OK);
3241 3243
3242 // If there are let bindings, then condition and the next statement of the 3244 // If there are let bindings, then condition and the next statement of the
3243 // for loop must be parsed in a new scope. 3245 // for loop must be parsed in a new scope.
3244 Scope* inner_scope = NULL; 3246 Scope* inner_scope = NULL;
3245 if (let_bindings.length() > 0) { 3247 if (let_bindings.length() > 0) {
3246 inner_scope = NewScope(for_scope, BLOCK_SCOPE); 3248 inner_scope = NewScope(for_scope, BLOCK_SCOPE);
3247 inner_scope->set_start_position(scanner()->location().beg_pos); 3249 inner_scope->set_start_position(scanner()->location().beg_pos);
3248 scope_ = inner_scope; 3250 scope_ = inner_scope;
3249 } 3251 }
3250 3252
3251 Expression* cond = NULL; 3253 Expression* cond = NULL;
3252 if (peek() != Token::SEMICOLON) { 3254 if (peek() != Token::SEMICOLON) {
3253 cond = ParseExpression(true, CHECK_OK); 3255 cond = ParseExpression(true, CHECK_OK);
3254 } 3256 }
3255 Expect(Token::SEMICOLON, CHECK_OK); 3257 Expect(Token::SEMICOLON, CHECK_OK);
3256 3258
3257 Statement* next = NULL; 3259 Statement* next = NULL;
3258 if (peek() != Token::RPAREN) { 3260 if (peek() != Token::RPAREN) {
3261 int next_pos = position();
3259 Expression* exp = ParseExpression(true, CHECK_OK); 3262 Expression* exp = ParseExpression(true, CHECK_OK);
3260 next = factory()->NewExpressionStatement(exp, RelocInfo::kNoPosition); 3263 next = factory()->NewExpressionStatement(exp, next_pos);
3261 } 3264 }
3262 Expect(Token::RPAREN, CHECK_OK); 3265 Expect(Token::RPAREN, CHECK_OK);
3263 3266
3264 Statement* body = ParseStatement(NULL, CHECK_OK); 3267 Statement* body = ParseStatement(NULL, CHECK_OK);
3265 3268
3266 Statement* result = NULL; 3269 Statement* result = NULL;
3267 if (let_bindings.length() > 0) { 3270 if (let_bindings.length() > 0) {
3268 scope_ = for_scope; 3271 scope_ = for_scope;
3269 result = DesugarLetBindingsInForStatement(inner_scope, &let_bindings, loop, 3272 result = DesugarLetBindingsInForStatement(inner_scope, &let_bindings, loop,
3270 init, cond, next, body, CHECK_OK); 3273 init, cond, next, body, CHECK_OK);
(...skipping 1684 matching lines...) Expand 10 before | Expand all | Expand 10 after
4955 4958
4956 // We cannot internalize on a background thread; a foreground task will take 4959 // We cannot internalize on a background thread; a foreground task will take
4957 // care of calling Parser::Internalize just before compilation. 4960 // care of calling Parser::Internalize just before compilation.
4958 4961
4959 if (compile_options() == ScriptCompiler::kProduceParserCache) { 4962 if (compile_options() == ScriptCompiler::kProduceParserCache) {
4960 if (result != NULL) *info_->cached_data() = recorder.GetScriptData(); 4963 if (result != NULL) *info_->cached_data() = recorder.GetScriptData();
4961 log_ = NULL; 4964 log_ = NULL;
4962 } 4965 }
4963 } 4966 }
4964 } } // namespace v8::internal 4967 } } // 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