Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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/compiler/ast-graph-builder.h" | 5 #include "src/compiler/ast-graph-builder.h" |
| 6 | 6 |
| 7 #include "src/compiler.h" | 7 #include "src/compiler.h" |
| 8 #include "src/compiler/ast-loop-assignment-analyzer.h" | 8 #include "src/compiler/ast-loop-assignment-analyzer.h" |
| 9 #include "src/compiler/control-builders.h" | 9 #include "src/compiler/control-builders.h" |
| 10 #include "src/compiler/linkage.h" | 10 #include "src/compiler/linkage.h" |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 132 | 132 |
| 133 // Scoped class tracking control statements entered by the visitor. There are | 133 // Scoped class tracking control statements entered by the visitor. There are |
| 134 // different types of statements participating in this stack to properly track | 134 // different types of statements participating in this stack to properly track |
| 135 // local as well as non-local control flow: | 135 // local as well as non-local control flow: |
| 136 // - IterationStatement : Allows proper 'break' and 'continue' behavior. | 136 // - IterationStatement : Allows proper 'break' and 'continue' behavior. |
| 137 // - BreakableStatement : Allows 'break' from block and switch statements. | 137 // - BreakableStatement : Allows 'break' from block and switch statements. |
| 138 // - TryCatchStatement : Intercepts 'throw' and implicit exceptional edges. | 138 // - TryCatchStatement : Intercepts 'throw' and implicit exceptional edges. |
| 139 // - TryFinallyStatement: Intercepts 'break', 'continue', 'throw' and 'return'. | 139 // - TryFinallyStatement: Intercepts 'break', 'continue', 'throw' and 'return'. |
| 140 class AstGraphBuilder::ControlScope BASE_EMBEDDED { | 140 class AstGraphBuilder::ControlScope BASE_EMBEDDED { |
| 141 public: | 141 public: |
| 142 ControlScope(AstGraphBuilder* builder, int stack_delta) | 142 explicit ControlScope(AstGraphBuilder* builder) |
| 143 : builder_(builder), | 143 : builder_(builder), |
| 144 outer_(builder->execution_control()), | 144 outer_(builder->execution_control()), |
| 145 stack_delta_(stack_delta) { | 145 stack_height_(builder->environment()->stack_height()) { |
| 146 builder_->set_execution_control(this); // Push. | 146 builder_->set_execution_control(this); // Push. |
| 147 } | 147 } |
| 148 | 148 |
| 149 virtual ~ControlScope() { | 149 virtual ~ControlScope() { |
| 150 builder_->set_execution_control(outer_); // Pop. | 150 builder_->set_execution_control(outer_); // Pop. |
| 151 } | 151 } |
| 152 | 152 |
| 153 // Either 'break' or 'continue' to the target statement. | 153 // Either 'break' or 'continue' to the target statement. |
| 154 void BreakTo(BreakableStatement* target); | 154 void BreakTo(BreakableStatement* target); |
| 155 void ContinueTo(BreakableStatement* target); | 155 void ContinueTo(BreakableStatement* target); |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 182 return true; | 182 return true; |
| 183 case CMD_BREAK: | 183 case CMD_BREAK: |
| 184 case CMD_CONTINUE: | 184 case CMD_CONTINUE: |
| 185 break; | 185 break; |
| 186 } | 186 } |
| 187 return false; | 187 return false; |
| 188 } | 188 } |
| 189 | 189 |
| 190 Environment* environment() { return builder_->environment(); } | 190 Environment* environment() { return builder_->environment(); } |
| 191 AstGraphBuilder* builder() const { return builder_; } | 191 AstGraphBuilder* builder() const { return builder_; } |
| 192 int stack_delta() const { return stack_delta_; } | 192 int stack_height() const { return stack_height_; } |
| 193 | 193 |
| 194 private: | 194 private: |
| 195 AstGraphBuilder* builder_; | 195 AstGraphBuilder* builder_; |
| 196 ControlScope* outer_; | 196 ControlScope* outer_; |
| 197 int stack_delta_; | 197 int stack_height_; |
| 198 }; | 198 }; |
| 199 | 199 |
| 200 | 200 |
| 201 // Helper class for a try-finally control scope. It can record intercepted | 201 // Helper class for a try-finally control scope. It can record intercepted |
| 202 // control-flow commands that cause entry into a finally-block, and re-apply | 202 // control-flow commands that cause entry into a finally-block, and re-apply |
| 203 // them after again leaving that block. Special tokens are used to identify | 203 // them after again leaving that block. Special tokens are used to identify |
| 204 // paths going through the finally-block to dispatch after leaving the block. | 204 // paths going through the finally-block to dispatch after leaving the block. |
| 205 class AstGraphBuilder::ControlScope::DeferredCommands : public ZoneObject { | 205 class AstGraphBuilder::ControlScope::DeferredCommands : public ZoneObject { |
| 206 public: | 206 public: |
| 207 explicit DeferredCommands(AstGraphBuilder* owner) | 207 explicit DeferredCommands(AstGraphBuilder* owner) |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 263 AstGraphBuilder* owner_; | 263 AstGraphBuilder* owner_; |
| 264 ZoneVector<Entry> deferred_; | 264 ZoneVector<Entry> deferred_; |
| 265 }; | 265 }; |
| 266 | 266 |
| 267 | 267 |
| 268 // Control scope implementation for a BreakableStatement. | 268 // Control scope implementation for a BreakableStatement. |
| 269 class AstGraphBuilder::ControlScopeForBreakable : public ControlScope { | 269 class AstGraphBuilder::ControlScopeForBreakable : public ControlScope { |
| 270 public: | 270 public: |
| 271 ControlScopeForBreakable(AstGraphBuilder* owner, BreakableStatement* target, | 271 ControlScopeForBreakable(AstGraphBuilder* owner, BreakableStatement* target, |
| 272 ControlBuilder* control) | 272 ControlBuilder* control) |
| 273 : ControlScope(owner, 0), target_(target), control_(control) {} | 273 : ControlScope(owner), target_(target), control_(control) {} |
| 274 | 274 |
| 275 protected: | 275 protected: |
| 276 virtual bool Execute(Command cmd, Statement* target, Node* value) OVERRIDE { | 276 virtual bool Execute(Command cmd, Statement* target, Node* value) OVERRIDE { |
| 277 if (target != target_) return false; // We are not the command target. | 277 if (target != target_) return false; // We are not the command target. |
| 278 switch (cmd) { | 278 switch (cmd) { |
| 279 case CMD_BREAK: | 279 case CMD_BREAK: |
| 280 control_->Break(); | 280 control_->Break(); |
| 281 return true; | 281 return true; |
| 282 case CMD_CONTINUE: | 282 case CMD_CONTINUE: |
| 283 case CMD_THROW: | 283 case CMD_THROW: |
| 284 case CMD_RETURN: | 284 case CMD_RETURN: |
| 285 break; | 285 break; |
| 286 } | 286 } |
| 287 return false; | 287 return false; |
| 288 } | 288 } |
| 289 | 289 |
| 290 private: | 290 private: |
| 291 BreakableStatement* target_; | 291 BreakableStatement* target_; |
| 292 ControlBuilder* control_; | 292 ControlBuilder* control_; |
| 293 }; | 293 }; |
| 294 | 294 |
| 295 | 295 |
| 296 // Control scope implementation for an IterationStatement. | 296 // Control scope implementation for an IterationStatement. |
| 297 class AstGraphBuilder::ControlScopeForIteration : public ControlScope { | 297 class AstGraphBuilder::ControlScopeForIteration : public ControlScope { |
| 298 public: | 298 public: |
| 299 ControlScopeForIteration(AstGraphBuilder* owner, IterationStatement* target, | 299 ControlScopeForIteration(AstGraphBuilder* owner, IterationStatement* target, |
| 300 LoopBuilder* control, int stack_delta) | 300 LoopBuilder* control) |
| 301 : ControlScope(owner, stack_delta), target_(target), control_(control) {} | 301 : ControlScope(owner), target_(target), control_(control) {} |
| 302 | 302 |
| 303 protected: | 303 protected: |
| 304 virtual bool Execute(Command cmd, Statement* target, Node* value) OVERRIDE { | 304 virtual bool Execute(Command cmd, Statement* target, Node* value) OVERRIDE { |
| 305 if (target != target_) return false; // We are not the command target. | 305 if (target != target_) return false; // We are not the command target. |
| 306 switch (cmd) { | 306 switch (cmd) { |
| 307 case CMD_BREAK: | 307 case CMD_BREAK: |
| 308 control_->Break(); | 308 control_->Break(); |
| 309 return true; | 309 return true; |
| 310 case CMD_CONTINUE: | 310 case CMD_CONTINUE: |
| 311 control_->Continue(); | 311 control_->Continue(); |
| 312 return true; | 312 return true; |
| 313 case CMD_THROW: | 313 case CMD_THROW: |
| 314 case CMD_RETURN: | 314 case CMD_RETURN: |
| 315 break; | 315 break; |
| 316 } | 316 } |
| 317 return false; | 317 return false; |
| 318 } | 318 } |
| 319 | 319 |
| 320 private: | 320 private: |
| 321 BreakableStatement* target_; | 321 BreakableStatement* target_; |
| 322 LoopBuilder* control_; | 322 LoopBuilder* control_; |
| 323 }; | 323 }; |
| 324 | 324 |
| 325 | 325 |
| 326 // Control scope implementation for a TryCatchStatement. | 326 // Control scope implementation for a TryCatchStatement. |
| 327 class AstGraphBuilder::ControlScopeForCatch : public ControlScope { | 327 class AstGraphBuilder::ControlScopeForCatch : public ControlScope { |
| 328 public: | 328 public: |
| 329 ControlScopeForCatch(AstGraphBuilder* owner, TryCatchBuilder* control) | 329 ControlScopeForCatch(AstGraphBuilder* owner, TryCatchBuilder* control) |
| 330 : ControlScope(owner, 0), control_(control) { | 330 : ControlScope(owner), control_(control) { |
| 331 builder()->try_nesting_level_++; // Increment nesting. | 331 builder()->try_nesting_level_++; // Increment nesting. |
| 332 } | 332 } |
| 333 ~ControlScopeForCatch() { | 333 ~ControlScopeForCatch() { |
| 334 builder()->try_nesting_level_--; // Decrement nesting. | 334 builder()->try_nesting_level_--; // Decrement nesting. |
| 335 } | 335 } |
| 336 | 336 |
| 337 protected: | 337 protected: |
| 338 virtual bool Execute(Command cmd, Statement* target, Node* value) OVERRIDE { | 338 virtual bool Execute(Command cmd, Statement* target, Node* value) OVERRIDE { |
| 339 switch (cmd) { | 339 switch (cmd) { |
| 340 case CMD_THROW: | 340 case CMD_THROW: |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 351 private: | 351 private: |
| 352 TryCatchBuilder* control_; | 352 TryCatchBuilder* control_; |
| 353 }; | 353 }; |
| 354 | 354 |
| 355 | 355 |
| 356 // Control scope implementation for a TryFinallyStatement. | 356 // Control scope implementation for a TryFinallyStatement. |
| 357 class AstGraphBuilder::ControlScopeForFinally : public ControlScope { | 357 class AstGraphBuilder::ControlScopeForFinally : public ControlScope { |
| 358 public: | 358 public: |
| 359 ControlScopeForFinally(AstGraphBuilder* owner, DeferredCommands* commands, | 359 ControlScopeForFinally(AstGraphBuilder* owner, DeferredCommands* commands, |
| 360 TryFinallyBuilder* control) | 360 TryFinallyBuilder* control) |
| 361 : ControlScope(owner, 0), commands_(commands), control_(control) { | 361 : ControlScope(owner), commands_(commands), control_(control) { |
| 362 builder()->try_nesting_level_++; // Increment nesting. | 362 builder()->try_nesting_level_++; // Increment nesting. |
| 363 } | 363 } |
| 364 ~ControlScopeForFinally() { | 364 ~ControlScopeForFinally() { |
| 365 builder()->try_nesting_level_--; // Decrement nesting. | 365 builder()->try_nesting_level_--; // Decrement nesting. |
| 366 } | 366 } |
| 367 | 367 |
| 368 protected: | 368 protected: |
| 369 virtual bool Execute(Command cmd, Statement* target, Node* value) OVERRIDE { | 369 virtual bool Execute(Command cmd, Statement* target, Node* value) OVERRIDE { |
| 370 Node* token = commands_->RecordCommand(cmd, target, value); | 370 Node* token = commands_->RecordCommand(cmd, target, value); |
| 371 control_->LeaveTry(token); | 371 control_->LeaveTry(token); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 420 | 420 |
| 421 | 421 |
| 422 bool AstGraphBuilder::CreateGraph() { | 422 bool AstGraphBuilder::CreateGraph() { |
| 423 Scope* scope = info()->scope(); | 423 Scope* scope = info()->scope(); |
| 424 DCHECK(graph() != NULL); | 424 DCHECK(graph() != NULL); |
| 425 | 425 |
| 426 // Set up the basic structure of the graph. | 426 // Set up the basic structure of the graph. |
| 427 int parameter_count = info()->num_parameters(); | 427 int parameter_count = info()->num_parameters(); |
| 428 graph()->SetStart(graph()->NewNode(common()->Start(parameter_count))); | 428 graph()->SetStart(graph()->NewNode(common()->Start(parameter_count))); |
| 429 | 429 |
| 430 // Initialize control scope. | |
| 431 ControlScope control(this, 0); | |
| 432 | |
| 433 // Initialize the top-level environment. | 430 // Initialize the top-level environment. |
| 434 Environment env(this, scope, graph()->start()); | 431 Environment env(this, scope, graph()->start()); |
| 435 set_environment(&env); | 432 set_environment(&env); |
| 436 | 433 |
| 434 // Initialize control scope. | |
| 435 ControlScope control(this); | |
| 436 | |
| 437 if (info()->is_osr()) { | 437 if (info()->is_osr()) { |
| 438 // Use OSR normal entry as the start of the top-level environment. | 438 // Use OSR normal entry as the start of the top-level environment. |
| 439 // It will be replaced with {Dead} after typing and optimizations. | 439 // It will be replaced with {Dead} after typing and optimizations. |
| 440 NewNode(common()->OsrNormalEntry()); | 440 NewNode(common()->OsrNormalEntry()); |
| 441 } | 441 } |
| 442 | 442 |
| 443 // Initialize the incoming context. | 443 // Initialize the incoming context. |
| 444 Node* incoming_context = GetFunctionContext(); | 444 Node* incoming_context = GetFunctionContext(); |
| 445 ContextScope incoming(this, scope, incoming_context); | 445 ContextScope incoming(this, scope, incoming_context); |
| 446 | 446 |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 673 return execution_context_->context(); | 673 return execution_context_->context(); |
| 674 } | 674 } |
| 675 | 675 |
| 676 | 676 |
| 677 void AstGraphBuilder::ControlScope::PerformCommand(Command command, | 677 void AstGraphBuilder::ControlScope::PerformCommand(Command command, |
| 678 Statement* target, | 678 Statement* target, |
| 679 Node* value) { | 679 Node* value) { |
| 680 Environment* env = environment()->CopyAsUnreachable(); | 680 Environment* env = environment()->CopyAsUnreachable(); |
| 681 ControlScope* current = this; | 681 ControlScope* current = this; |
| 682 while (current != NULL) { | 682 while (current != NULL) { |
| 683 int stack_delta = environment()->stack_height() - current->stack_height(); | |
| 684 if (stack_delta > 0) environment()->Drop(stack_delta); | |
|
titzer
2015/02/19 12:33:00
environment()->TrimStack() ?
Michael Starzinger
2015/02/19 12:58:21
Done. Called it just "Trim" as per offline discuss
| |
| 683 if (current->Execute(command, target, value)) break; | 685 if (current->Execute(command, target, value)) break; |
| 684 environment()->Drop(current->stack_delta()); | |
| 685 current = current->outer_; | 686 current = current->outer_; |
| 686 } | 687 } |
| 687 builder()->set_environment(env); | 688 builder()->set_environment(env); |
| 688 DCHECK(current != NULL); // Always handled (unless stack is malformed). | 689 DCHECK(current != NULL); // Always handled (unless stack is malformed). |
| 689 } | 690 } |
| 690 | 691 |
| 691 | 692 |
| 692 void AstGraphBuilder::ControlScope::BreakTo(BreakableStatement* stmt) { | 693 void AstGraphBuilder::ControlScope::BreakTo(BreakableStatement* stmt) { |
| 693 PerformCommand(CMD_BREAK, stmt, nullptr); | 694 PerformCommand(CMD_BREAK, stmt, nullptr); |
| 694 } | 695 } |
| (...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 988 compare_switch.EndCase(); | 989 compare_switch.EndCase(); |
| 989 } | 990 } |
| 990 | 991 |
| 991 compare_switch.EndSwitch(); | 992 compare_switch.EndSwitch(); |
| 992 } | 993 } |
| 993 | 994 |
| 994 | 995 |
| 995 void AstGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { | 996 void AstGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { |
| 996 LoopBuilder while_loop(this); | 997 LoopBuilder while_loop(this); |
| 997 while_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt)); | 998 while_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt)); |
| 998 VisitIterationBody(stmt, &while_loop, 0); | 999 VisitIterationBody(stmt, &while_loop); |
| 999 while_loop.EndBody(); | 1000 while_loop.EndBody(); |
| 1000 VisitForTest(stmt->cond()); | 1001 VisitForTest(stmt->cond()); |
| 1001 Node* condition = environment()->Pop(); | 1002 Node* condition = environment()->Pop(); |
| 1002 while_loop.BreakUnless(condition); | 1003 while_loop.BreakUnless(condition); |
| 1003 while_loop.EndLoop(); | 1004 while_loop.EndLoop(); |
| 1004 } | 1005 } |
| 1005 | 1006 |
| 1006 | 1007 |
| 1007 void AstGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { | 1008 void AstGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { |
| 1008 LoopBuilder while_loop(this); | 1009 LoopBuilder while_loop(this); |
| 1009 while_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt)); | 1010 while_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt)); |
| 1010 VisitForTest(stmt->cond()); | 1011 VisitForTest(stmt->cond()); |
| 1011 Node* condition = environment()->Pop(); | 1012 Node* condition = environment()->Pop(); |
| 1012 while_loop.BreakUnless(condition); | 1013 while_loop.BreakUnless(condition); |
| 1013 VisitIterationBody(stmt, &while_loop, 0); | 1014 VisitIterationBody(stmt, &while_loop); |
| 1014 while_loop.EndBody(); | 1015 while_loop.EndBody(); |
| 1015 while_loop.EndLoop(); | 1016 while_loop.EndLoop(); |
| 1016 } | 1017 } |
| 1017 | 1018 |
| 1018 | 1019 |
| 1019 void AstGraphBuilder::VisitForStatement(ForStatement* stmt) { | 1020 void AstGraphBuilder::VisitForStatement(ForStatement* stmt) { |
| 1020 LoopBuilder for_loop(this); | 1021 LoopBuilder for_loop(this); |
| 1021 VisitIfNotNull(stmt->init()); | 1022 VisitIfNotNull(stmt->init()); |
| 1022 for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt)); | 1023 for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt)); |
| 1023 if (stmt->cond() != NULL) { | 1024 if (stmt->cond() != NULL) { |
| 1024 VisitForTest(stmt->cond()); | 1025 VisitForTest(stmt->cond()); |
| 1025 Node* condition = environment()->Pop(); | 1026 Node* condition = environment()->Pop(); |
| 1026 for_loop.BreakUnless(condition); | 1027 for_loop.BreakUnless(condition); |
| 1027 } else { | 1028 } else { |
| 1028 for_loop.BreakUnless(jsgraph()->TrueConstant()); | 1029 for_loop.BreakUnless(jsgraph()->TrueConstant()); |
| 1029 } | 1030 } |
| 1030 VisitIterationBody(stmt, &for_loop, 0); | 1031 VisitIterationBody(stmt, &for_loop); |
| 1031 for_loop.EndBody(); | 1032 for_loop.EndBody(); |
| 1032 VisitIfNotNull(stmt->next()); | 1033 VisitIfNotNull(stmt->next()); |
| 1033 for_loop.EndLoop(); | 1034 for_loop.EndLoop(); |
| 1034 } | 1035 } |
| 1035 | 1036 |
| 1036 | 1037 |
| 1037 // TODO(dcarney): this is a big function. Try to clean up some. | 1038 // TODO(dcarney): this is a big function. Try to clean up some. |
| 1038 void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) { | 1039 void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) { |
| 1039 VisitForValue(stmt->subject()); | 1040 VisitForValue(stmt->subject()); |
| 1040 Node* obj = environment()->Pop(); | 1041 Node* obj = environment()->Pop(); |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1159 is_property_missing.End(); | 1160 is_property_missing.End(); |
| 1160 } | 1161 } |
| 1161 // Replace 'value' in environment. | 1162 // Replace 'value' in environment. |
| 1162 environment()->Push(res); | 1163 environment()->Push(res); |
| 1163 test_should_filter.Else(); | 1164 test_should_filter.Else(); |
| 1164 test_should_filter.End(); | 1165 test_should_filter.End(); |
| 1165 } | 1166 } |
| 1166 value = environment()->Pop(); | 1167 value = environment()->Pop(); |
| 1167 // Bind value and do loop body. | 1168 // Bind value and do loop body. |
| 1168 VisitForInAssignment(stmt->each(), value, stmt->AssignmentId()); | 1169 VisitForInAssignment(stmt->each(), value, stmt->AssignmentId()); |
| 1169 VisitIterationBody(stmt, &for_loop, 5); | 1170 VisitIterationBody(stmt, &for_loop); |
| 1170 for_loop.EndBody(); | 1171 for_loop.EndBody(); |
| 1171 // Inc counter and continue. | 1172 // Inc counter and continue. |
| 1172 Node* index_inc = | 1173 Node* index_inc = |
| 1173 NewNode(javascript()->Add(), index, jsgraph()->OneConstant()); | 1174 NewNode(javascript()->Add(), index, jsgraph()->OneConstant()); |
| 1174 // TODO(jarin): provide real bailout id. | 1175 // TODO(jarin): provide real bailout id. |
| 1175 PrepareFrameState(index_inc, BailoutId::None()); | 1176 PrepareFrameState(index_inc, BailoutId::None()); |
| 1176 environment()->Poke(0, index_inc); | 1177 environment()->Poke(0, index_inc); |
| 1177 for_loop.EndLoop(); | 1178 for_loop.EndLoop(); |
| 1178 environment()->Drop(5); | 1179 environment()->Drop(5); |
| 1179 // PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); | 1180 // PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); |
| 1180 } | 1181 } |
| 1181 | 1182 |
| 1182 | 1183 |
| 1183 void AstGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) { | 1184 void AstGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) { |
| 1184 LoopBuilder for_loop(this); | 1185 LoopBuilder for_loop(this); |
| 1185 VisitForEffect(stmt->assign_iterator()); | 1186 VisitForEffect(stmt->assign_iterator()); |
| 1186 for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt)); | 1187 for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt)); |
| 1187 VisitForEffect(stmt->next_result()); | 1188 VisitForEffect(stmt->next_result()); |
| 1188 VisitForTest(stmt->result_done()); | 1189 VisitForTest(stmt->result_done()); |
| 1189 Node* condition = environment()->Pop(); | 1190 Node* condition = environment()->Pop(); |
| 1190 for_loop.BreakWhen(condition); | 1191 for_loop.BreakWhen(condition); |
| 1191 VisitForEffect(stmt->assign_each()); | 1192 VisitForEffect(stmt->assign_each()); |
| 1192 VisitIterationBody(stmt, &for_loop, 0); | 1193 VisitIterationBody(stmt, &for_loop); |
| 1193 for_loop.EndBody(); | 1194 for_loop.EndBody(); |
| 1194 for_loop.EndLoop(); | 1195 for_loop.EndLoop(); |
| 1195 } | 1196 } |
| 1196 | 1197 |
| 1197 | 1198 |
| 1198 void AstGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { | 1199 void AstGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { |
| 1199 TryCatchBuilder try_control(this); | 1200 TryCatchBuilder try_control(this); |
| 1200 | 1201 |
| 1201 // Evaluate the try-block inside a control scope. This simulates a handler | 1202 // Evaluate the try-block inside a control scope. This simulates a handler |
| 1202 // that is intercepting 'throw' control commands. | 1203 // that is intercepting 'throw' control commands. |
| (...skipping 1069 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2272 } | 2273 } |
| 2273 | 2274 |
| 2274 | 2275 |
| 2275 void AstGraphBuilder::VisitIfNotNull(Statement* stmt) { | 2276 void AstGraphBuilder::VisitIfNotNull(Statement* stmt) { |
| 2276 if (stmt == NULL) return; | 2277 if (stmt == NULL) return; |
| 2277 Visit(stmt); | 2278 Visit(stmt); |
| 2278 } | 2279 } |
| 2279 | 2280 |
| 2280 | 2281 |
| 2281 void AstGraphBuilder::VisitIterationBody(IterationStatement* stmt, | 2282 void AstGraphBuilder::VisitIterationBody(IterationStatement* stmt, |
| 2282 LoopBuilder* loop, int stack_delta) { | 2283 LoopBuilder* loop) { |
| 2283 ControlScopeForIteration scope(this, stmt, loop, stack_delta); | 2284 ControlScopeForIteration scope(this, stmt, loop); |
| 2284 Visit(stmt->body()); | 2285 Visit(stmt->body()); |
| 2285 } | 2286 } |
| 2286 | 2287 |
| 2287 | 2288 |
| 2288 void AstGraphBuilder::VisitDelete(UnaryOperation* expr) { | 2289 void AstGraphBuilder::VisitDelete(UnaryOperation* expr) { |
| 2289 Node* value; | 2290 Node* value; |
| 2290 if (expr->expression()->IsVariableProxy()) { | 2291 if (expr->expression()->IsVariableProxy()) { |
| 2291 // Delete of an unqualified identifier is only allowed in classic mode but | 2292 // Delete of an unqualified identifier is only allowed in classic mode but |
| 2292 // deleting "this" is allowed in all language modes. | 2293 // deleting "this" is allowed in all language modes. |
| 2293 Variable* variable = expr->expression()->AsVariableProxy()->var(); | 2294 Variable* variable = expr->expression()->AsVariableProxy()->var(); |
| (...skipping 700 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2994 } | 2995 } |
| 2995 if (!environment()->IsMarkedAsUnreachable()) { | 2996 if (!environment()->IsMarkedAsUnreachable()) { |
| 2996 // Update the current control dependency for control-producing nodes. | 2997 // Update the current control dependency for control-producing nodes. |
| 2997 if (NodeProperties::IsControl(result)) { | 2998 if (NodeProperties::IsControl(result)) { |
| 2998 environment_->UpdateControlDependency(result); | 2999 environment_->UpdateControlDependency(result); |
| 2999 } | 3000 } |
| 3000 // Add implicit exception continuation for throwing nodes. | 3001 // Add implicit exception continuation for throwing nodes. |
| 3001 if (!result->op()->HasProperty(Operator::kNoThrow) && inside_try_scope) { | 3002 if (!result->op()->HasProperty(Operator::kNoThrow) && inside_try_scope) { |
| 3002 Node* on_exception = graph()->NewNode(common()->IfException(), result); | 3003 Node* on_exception = graph()->NewNode(common()->IfException(), result); |
| 3003 environment_->UpdateControlDependency(on_exception); | 3004 environment_->UpdateControlDependency(on_exception); |
| 3004 if (FLAG_turbo_exceptions) { | 3005 execution_control()->ThrowValue(jsgraph()->UndefinedConstant()); |
| 3005 execution_control()->ThrowValue(jsgraph()->UndefinedConstant()); | |
| 3006 } | |
| 3007 } | 3006 } |
| 3008 // Add implicit success continuation for throwing nodes. | 3007 // Add implicit success continuation for throwing nodes. |
| 3009 if (!result->op()->HasProperty(Operator::kNoThrow)) { | 3008 if (!result->op()->HasProperty(Operator::kNoThrow)) { |
| 3010 Node* on_success = graph()->NewNode(common()->IfSuccess(), result); | 3009 Node* on_success = graph()->NewNode(common()->IfSuccess(), result); |
| 3011 environment_->UpdateControlDependency(on_success); | 3010 environment_->UpdateControlDependency(on_success); |
| 3012 } | 3011 } |
| 3013 } | 3012 } |
| 3014 } | 3013 } |
| 3015 | 3014 |
| 3016 return result; | 3015 return result; |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3176 // Phi does not exist yet, introduce one. | 3175 // Phi does not exist yet, introduce one. |
| 3177 value = NewPhi(inputs, value, control); | 3176 value = NewPhi(inputs, value, control); |
| 3178 value->ReplaceInput(inputs - 1, other); | 3177 value->ReplaceInput(inputs - 1, other); |
| 3179 } | 3178 } |
| 3180 return value; | 3179 return value; |
| 3181 } | 3180 } |
| 3182 | 3181 |
| 3183 } // namespace compiler | 3182 } // namespace compiler |
| 3184 } // namespace internal | 3183 } // namespace internal |
| 3185 } // namespace v8 | 3184 } // namespace v8 |
| OLD | NEW |