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/ast/scopes.h" | 7 #include "src/ast/scopes.h" |
8 #include "src/compiler.h" | 8 #include "src/compiler.h" |
9 #include "src/compiler/ast-loop-assignment-analyzer.h" | 9 #include "src/compiler/ast-loop-assignment-analyzer.h" |
10 #include "src/compiler/control-builders.h" | 10 #include "src/compiler/control-builders.h" |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
171 enum Command { CMD_BREAK, CMD_CONTINUE, CMD_RETURN, CMD_THROW }; | 171 enum Command { CMD_BREAK, CMD_CONTINUE, CMD_RETURN, CMD_THROW }; |
172 | 172 |
173 // Performs one of the above commands on this stack of control scopes. This | 173 // Performs one of the above commands on this stack of control scopes. This |
174 // walks through the stack giving each scope a chance to execute or defer the | 174 // walks through the stack giving each scope a chance to execute or defer the |
175 // given command by overriding the {Execute} method appropriately. Note that | 175 // given command by overriding the {Execute} method appropriately. Note that |
176 // this also drops extra operands from the environment for each skipped scope. | 176 // this also drops extra operands from the environment for each skipped scope. |
177 void PerformCommand(Command cmd, Statement* target, Node* value); | 177 void PerformCommand(Command cmd, Statement* target, Node* value); |
178 | 178 |
179 // Interface to execute a given command in this scope. Returning {true} here | 179 // Interface to execute a given command in this scope. Returning {true} here |
180 // indicates successful execution whereas {false} requests to skip scope. | 180 // indicates successful execution whereas {false} requests to skip scope. |
181 virtual bool Execute(Command cmd, Statement* target, Node* value) { | 181 virtual bool Execute(Command cmd, Statement* target, Node** value) { |
182 // For function-level control. | 182 // For function-level control. |
183 switch (cmd) { | 183 switch (cmd) { |
184 case CMD_THROW: | 184 case CMD_THROW: |
185 builder()->BuildThrow(value); | 185 builder()->BuildThrow(*value); |
186 return true; | 186 return true; |
187 case CMD_RETURN: | 187 case CMD_RETURN: |
188 builder()->BuildReturn(value); | 188 builder()->BuildReturn(*value); |
189 return true; | 189 return true; |
190 case CMD_BREAK: | 190 case CMD_BREAK: |
191 case CMD_CONTINUE: | 191 case CMD_CONTINUE: |
192 break; | 192 break; |
193 } | 193 } |
194 return false; | 194 return false; |
195 } | 195 } |
196 | 196 |
197 Environment* environment() { return builder_->environment(); } | 197 Environment* environment() { return builder_->environment(); } |
198 AstGraphBuilder* builder() const { return builder_; } | 198 AstGraphBuilder* builder() const { return builder_; } |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
296 | 296 |
297 | 297 |
298 // Control scope implementation for a BreakableStatement. | 298 // Control scope implementation for a BreakableStatement. |
299 class AstGraphBuilder::ControlScopeForBreakable : public ControlScope { | 299 class AstGraphBuilder::ControlScopeForBreakable : public ControlScope { |
300 public: | 300 public: |
301 ControlScopeForBreakable(AstGraphBuilder* owner, BreakableStatement* target, | 301 ControlScopeForBreakable(AstGraphBuilder* owner, BreakableStatement* target, |
302 ControlBuilder* control) | 302 ControlBuilder* control) |
303 : ControlScope(owner), target_(target), control_(control) {} | 303 : ControlScope(owner), target_(target), control_(control) {} |
304 | 304 |
305 protected: | 305 protected: |
306 bool Execute(Command cmd, Statement* target, Node* value) override { | 306 bool Execute(Command cmd, Statement* target, Node** value) override { |
307 if (target != target_) return false; // We are not the command target. | 307 if (target != target_) return false; // We are not the command target. |
308 switch (cmd) { | 308 switch (cmd) { |
309 case CMD_BREAK: | 309 case CMD_BREAK: |
310 control_->Break(); | 310 control_->Break(); |
311 return true; | 311 return true; |
312 case CMD_CONTINUE: | 312 case CMD_CONTINUE: |
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 ControlBuilder* control_; | 322 ControlBuilder* control_; |
323 }; | 323 }; |
324 | 324 |
325 | 325 |
326 // Control scope implementation for an IterationStatement. | 326 // Control scope implementation for an IterationStatement. |
327 class AstGraphBuilder::ControlScopeForIteration : public ControlScope { | 327 class AstGraphBuilder::ControlScopeForIteration : public ControlScope { |
328 public: | 328 public: |
329 ControlScopeForIteration(AstGraphBuilder* owner, IterationStatement* target, | 329 ControlScopeForIteration(AstGraphBuilder* owner, IterationStatement* target, |
330 LoopBuilder* control) | 330 LoopBuilder* control) |
331 : ControlScope(owner), target_(target), control_(control) {} | 331 : ControlScope(owner), target_(target), control_(control) {} |
332 | 332 |
333 protected: | 333 protected: |
334 bool Execute(Command cmd, Statement* target, Node* value) override { | 334 bool Execute(Command cmd, Statement* target, Node** value) override { |
335 if (target != target_) return false; // We are not the command target. | 335 if (target != target_) { |
336 control_->ExitLoop(value); | |
337 return false; | |
338 } | |
336 switch (cmd) { | 339 switch (cmd) { |
337 case CMD_BREAK: | 340 case CMD_BREAK: |
338 control_->Break(); | 341 control_->Break(); |
339 return true; | 342 return true; |
340 case CMD_CONTINUE: | 343 case CMD_CONTINUE: |
341 control_->Continue(); | 344 control_->Continue(); |
342 return true; | 345 return true; |
343 case CMD_THROW: | 346 case CMD_THROW: |
344 case CMD_RETURN: | 347 case CMD_RETURN: |
345 break; | 348 break; |
(...skipping 17 matching lines...) Expand all Loading... | |
363 outer_prediction_(owner->try_catch_prediction_) { | 366 outer_prediction_(owner->try_catch_prediction_) { |
364 builder()->try_nesting_level_++; // Increment nesting. | 367 builder()->try_nesting_level_++; // Increment nesting. |
365 builder()->try_catch_prediction_ = stmt->catch_predicted(); | 368 builder()->try_catch_prediction_ = stmt->catch_predicted(); |
366 } | 369 } |
367 ~ControlScopeForCatch() { | 370 ~ControlScopeForCatch() { |
368 builder()->try_nesting_level_--; // Decrement nesting. | 371 builder()->try_nesting_level_--; // Decrement nesting. |
369 builder()->try_catch_prediction_ = outer_prediction_; | 372 builder()->try_catch_prediction_ = outer_prediction_; |
370 } | 373 } |
371 | 374 |
372 protected: | 375 protected: |
373 bool Execute(Command cmd, Statement* target, Node* value) override { | 376 bool Execute(Command cmd, Statement* target, Node** value) override { |
374 switch (cmd) { | 377 switch (cmd) { |
375 case CMD_THROW: | 378 case CMD_THROW: |
376 control_->Throw(value); | 379 control_->Throw(*value); |
377 return true; | 380 return true; |
378 case CMD_BREAK: | 381 case CMD_BREAK: |
379 case CMD_CONTINUE: | 382 case CMD_CONTINUE: |
380 case CMD_RETURN: | 383 case CMD_RETURN: |
381 break; | 384 break; |
382 } | 385 } |
383 return false; | 386 return false; |
384 } | 387 } |
385 | 388 |
386 private: | 389 private: |
(...skipping 13 matching lines...) Expand all Loading... | |
400 outer_prediction_(owner->try_catch_prediction_) { | 403 outer_prediction_(owner->try_catch_prediction_) { |
401 builder()->try_nesting_level_++; // Increment nesting. | 404 builder()->try_nesting_level_++; // Increment nesting. |
402 builder()->try_catch_prediction_ = stmt->catch_predicted(); | 405 builder()->try_catch_prediction_ = stmt->catch_predicted(); |
403 } | 406 } |
404 ~ControlScopeForFinally() { | 407 ~ControlScopeForFinally() { |
405 builder()->try_nesting_level_--; // Decrement nesting. | 408 builder()->try_nesting_level_--; // Decrement nesting. |
406 builder()->try_catch_prediction_ = outer_prediction_; | 409 builder()->try_catch_prediction_ = outer_prediction_; |
407 } | 410 } |
408 | 411 |
409 protected: | 412 protected: |
410 bool Execute(Command cmd, Statement* target, Node* value) override { | 413 bool Execute(Command cmd, Statement* target, Node** value) override { |
411 Node* token = commands_->RecordCommand(cmd, target, value); | 414 Node* token = commands_->RecordCommand(cmd, target, *value); |
412 control_->LeaveTry(token, value); | 415 control_->LeaveTry(token, *value); |
413 return true; | 416 return true; |
414 } | 417 } |
415 | 418 |
416 private: | 419 private: |
417 DeferredCommands* commands_; | 420 DeferredCommands* commands_; |
418 TryFinallyBuilder* control_; | 421 TryFinallyBuilder* control_; |
419 bool outer_prediction_; | 422 bool outer_prediction_; |
420 }; | 423 }; |
421 | 424 |
422 | 425 |
(...skipping 505 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
928 // to use an explicit frame state for the exceptional path. | 931 // to use an explicit frame state for the exceptional path. |
929 if (owner_has_exception) { | 932 if (owner_has_exception) { |
930 liveness_block()->GetPredecessor()->Checkpoint(result); | 933 liveness_block()->GetPredecessor()->Checkpoint(result); |
931 } else { | 934 } else { |
932 liveness_block()->Checkpoint(result); | 935 liveness_block()->Checkpoint(result); |
933 } | 936 } |
934 } | 937 } |
935 return result; | 938 return result; |
936 } | 939 } |
937 | 940 |
941 void AstGraphBuilder::Environment::PrepareForLoopExit( | |
942 Node* loop, BitVector* assigned_variables) { | |
943 if (IsMarkedAsUnreachable()) return; | |
944 | |
945 DCHECK_EQ(loop->opcode(), IrOpcode::kLoop); | |
946 | |
947 Node* control = GetControlDependency(); | |
948 | |
949 // Create the loop exit node. | |
950 Node* loop_exit = graph()->NewNode(common()->LoopExit(), control, loop); | |
951 UpdateControlDependency(loop_exit); | |
952 | |
953 // Rename the environmnent values. | |
954 for (size_t i = 0; i < values()->size(); i++) { | |
955 if (assigned_variables == nullptr || | |
956 static_cast<int>(i) >= assigned_variables->length() || | |
957 assigned_variables->Contains(static_cast<int>(i))) { | |
958 Node* rename = graph()->NewNode(common()->LoopExitValue(), (*values())[i], | |
959 loop_exit); | |
960 (*values())[i] = rename; | |
Michael Starzinger
2016/07/14 13:09:40
nit: Why not just "values_[i] = rename"?
| |
961 } | |
962 } | |
963 | |
964 // Rename the effect. | |
965 Node* effect_rename = graph()->NewNode(common()->LoopExitEffect(), | |
966 GetEffectDependency(), loop_exit); | |
967 UpdateEffectDependency(effect_rename); | |
968 } | |
938 | 969 |
939 bool AstGraphBuilder::Environment::IsLivenessAnalysisEnabled() { | 970 bool AstGraphBuilder::Environment::IsLivenessAnalysisEnabled() { |
940 return FLAG_analyze_environment_liveness && | 971 return FLAG_analyze_environment_liveness && |
941 builder()->info()->is_deoptimization_enabled(); | 972 builder()->info()->is_deoptimization_enabled(); |
942 } | 973 } |
943 | 974 |
944 | 975 |
945 bool AstGraphBuilder::Environment::IsLivenessBlockConsistent() { | 976 bool AstGraphBuilder::Environment::IsLivenessBlockConsistent() { |
946 return (!IsLivenessAnalysisEnabled() || IsMarkedAsUnreachable()) == | 977 return (!IsLivenessAnalysisEnabled() || IsMarkedAsUnreachable()) == |
947 (liveness_block() == nullptr); | 978 (liveness_block() == nullptr); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1020 | 1051 |
1021 | 1052 |
1022 void AstGraphBuilder::ControlScope::PerformCommand(Command command, | 1053 void AstGraphBuilder::ControlScope::PerformCommand(Command command, |
1023 Statement* target, | 1054 Statement* target, |
1024 Node* value) { | 1055 Node* value) { |
1025 Environment* env = environment()->CopyAsUnreachable(); | 1056 Environment* env = environment()->CopyAsUnreachable(); |
1026 ControlScope* current = this; | 1057 ControlScope* current = this; |
1027 while (current != nullptr) { | 1058 while (current != nullptr) { |
1028 environment()->TrimStack(current->stack_height()); | 1059 environment()->TrimStack(current->stack_height()); |
1029 environment()->TrimContextChain(current->context_length()); | 1060 environment()->TrimContextChain(current->context_length()); |
1030 if (current->Execute(command, target, value)) break; | 1061 if (current->Execute(command, target, &value)) break; |
1031 current = current->outer_; | 1062 current = current->outer_; |
1032 } | 1063 } |
1033 builder()->set_environment(env); | 1064 builder()->set_environment(env); |
1034 DCHECK_NOT_NULL(current); // Always handled (unless stack is malformed). | 1065 DCHECK_NOT_NULL(current); // Always handled (unless stack is malformed). |
1035 } | 1066 } |
1036 | 1067 |
1037 | 1068 |
1038 void AstGraphBuilder::ControlScope::BreakTo(BreakableStatement* stmt) { | 1069 void AstGraphBuilder::ControlScope::BreakTo(BreakableStatement* stmt) { |
1039 PerformCommand(CMD_BREAK, stmt, builder()->jsgraph()->TheHoleConstant()); | 1070 PerformCommand(CMD_BREAK, stmt, builder()->jsgraph()->TheHoleConstant()); |
1040 } | 1071 } |
(...skipping 3345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4386 // Phi does not exist yet, introduce one. | 4417 // Phi does not exist yet, introduce one. |
4387 value = NewPhi(inputs, value, control); | 4418 value = NewPhi(inputs, value, control); |
4388 value->ReplaceInput(inputs - 1, other); | 4419 value->ReplaceInput(inputs - 1, other); |
4389 } | 4420 } |
4390 return value; | 4421 return value; |
4391 } | 4422 } |
4392 | 4423 |
4393 } // namespace compiler | 4424 } // namespace compiler |
4394 } // namespace internal | 4425 } // namespace internal |
4395 } // namespace v8 | 4426 } // namespace v8 |
OLD | NEW |