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/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 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 402 Node* token = commands_->RecordCommand(cmd, target, value); | 402 Node* token = commands_->RecordCommand(cmd, target, value); |
| 403 control_->LeaveTry(token, value); | 403 control_->LeaveTry(token, value); |
| 404 return true; | 404 return true; |
| 405 } | 405 } |
| 406 | 406 |
| 407 private: | 407 private: |
| 408 DeferredCommands* commands_; | 408 DeferredCommands* commands_; |
| 409 TryFinallyBuilder* control_; | 409 TryFinallyBuilder* control_; |
| 410 }; | 410 }; |
| 411 | 411 |
| 412 namespace { | |
| 413 | |
| 414 bool NodeHasExceptionUse(Node* node) { | |
|
Michael Starzinger
2016/02/12 09:32:40
Please use NodeProperties::IsExceptionalCall inste
Jarin
2016/02/12 09:58:32
Done.
| |
| 415 if (node->op()->HasProperty(Operator::kNoThrow)) return false; | |
| 416 for (Node* const user : node->uses()) { | |
| 417 if (user->opcode() == IrOpcode::kIfException) { | |
| 418 return true; | |
| 419 } | |
| 420 } | |
| 421 return false; | |
| 422 } | |
| 423 | |
| 424 } // namespace | |
| 412 | 425 |
| 413 // Helper for generating before and after frame states. | 426 // Helper for generating before and after frame states. |
| 414 class AstGraphBuilder::FrameStateBeforeAndAfter { | 427 class AstGraphBuilder::FrameStateBeforeAndAfter { |
| 415 public: | 428 public: |
| 416 FrameStateBeforeAndAfter(AstGraphBuilder* builder, BailoutId id_before) | 429 FrameStateBeforeAndAfter(AstGraphBuilder* builder, BailoutId id_before) |
| 417 : builder_(builder), frame_state_before_(nullptr) { | 430 : builder_(builder), frame_state_before_(nullptr) { |
| 418 frame_state_before_ = id_before == BailoutId::None() | 431 frame_state_before_ = id_before == BailoutId::None() |
| 419 ? builder_->jsgraph()->EmptyFrameState() | 432 ? builder_->jsgraph()->EmptyFrameState() |
| 420 : builder_->environment()->Checkpoint(id_before); | 433 : builder_->environment()->Checkpoint(id_before); |
| 421 } | 434 } |
| 422 | 435 |
| 423 void AddToNode( | 436 void AddToNode( |
| 424 Node* node, BailoutId id_after, | 437 Node* node, BailoutId id_after, |
| 425 OutputFrameStateCombine combine = OutputFrameStateCombine::Ignore()) { | 438 OutputFrameStateCombine combine = OutputFrameStateCombine::Ignore()) { |
| 426 int count = OperatorProperties::GetFrameStateInputCount(node->op()); | 439 int count = OperatorProperties::GetFrameStateInputCount(node->op()); |
| 427 DCHECK_LE(count, 2); | 440 DCHECK_LE(count, 2); |
| 428 | 441 |
| 429 if (count >= 1) { | 442 if (count >= 1) { |
| 430 // Add the frame state for after the operation. | 443 // Add the frame state for after the operation. |
| 431 DCHECK_EQ(IrOpcode::kDead, | 444 DCHECK_EQ(IrOpcode::kDead, |
| 432 NodeProperties::GetFrameStateInput(node, 0)->opcode()); | 445 NodeProperties::GetFrameStateInput(node, 0)->opcode()); |
| 433 | 446 |
| 447 bool node_has_exception = NodeHasExceptionUse(node); | |
| 448 | |
| 434 Node* frame_state_after = | 449 Node* frame_state_after = |
| 435 id_after == BailoutId::None() | 450 id_after == BailoutId::None() |
| 436 ? builder_->jsgraph()->EmptyFrameState() | 451 ? builder_->jsgraph()->EmptyFrameState() |
| 437 : builder_->environment()->Checkpoint(id_after, combine); | 452 : builder_->environment()->Checkpoint(id_after, combine, |
| 453 node_has_exception); | |
| 438 | 454 |
| 439 NodeProperties::ReplaceFrameStateInput(node, 0, frame_state_after); | 455 NodeProperties::ReplaceFrameStateInput(node, 0, frame_state_after); |
| 440 } | 456 } |
| 441 | 457 |
| 442 if (count >= 2) { | 458 if (count >= 2) { |
| 443 // Add the frame state for before the operation. | 459 // Add the frame state for before the operation. |
| 444 DCHECK_EQ(IrOpcode::kDead, | 460 DCHECK_EQ(IrOpcode::kDead, |
| 445 NodeProperties::GetFrameStateInput(node, 1)->opcode()); | 461 NodeProperties::GetFrameStateInput(node, 1)->opcode()); |
| 446 NodeProperties::ReplaceFrameStateInput(node, 1, frame_state_before_); | 462 NodeProperties::ReplaceFrameStateInput(node, 1, frame_state_before_); |
| 447 } | 463 } |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 862 } | 878 } |
| 863 | 879 |
| 864 | 880 |
| 865 void AstGraphBuilder::Environment::UpdateStateValuesWithCache( | 881 void AstGraphBuilder::Environment::UpdateStateValuesWithCache( |
| 866 Node** state_values, int offset, int count) { | 882 Node** state_values, int offset, int count) { |
| 867 Node** env_values = (count == 0) ? nullptr : &values()->at(offset); | 883 Node** env_values = (count == 0) ? nullptr : &values()->at(offset); |
| 868 *state_values = builder_->state_values_cache_.GetNodeForValues( | 884 *state_values = builder_->state_values_cache_.GetNodeForValues( |
| 869 env_values, static_cast<size_t>(count)); | 885 env_values, static_cast<size_t>(count)); |
| 870 } | 886 } |
| 871 | 887 |
| 872 | 888 Node* AstGraphBuilder::Environment::Checkpoint(BailoutId ast_id, |
| 873 Node* AstGraphBuilder::Environment::Checkpoint( | 889 OutputFrameStateCombine combine, |
| 874 BailoutId ast_id, OutputFrameStateCombine combine) { | 890 bool owner_has_exception) { |
| 875 if (!builder()->info()->is_deoptimization_enabled()) { | 891 if (!builder()->info()->is_deoptimization_enabled()) { |
| 876 return builder()->jsgraph()->EmptyFrameState(); | 892 return builder()->jsgraph()->EmptyFrameState(); |
| 877 } | 893 } |
| 878 | 894 |
| 879 UpdateStateValues(¶meters_node_, 0, parameters_count()); | 895 UpdateStateValues(¶meters_node_, 0, parameters_count()); |
| 880 UpdateStateValuesWithCache(&locals_node_, parameters_count(), locals_count()); | 896 UpdateStateValuesWithCache(&locals_node_, parameters_count(), locals_count()); |
| 881 UpdateStateValues(&stack_node_, parameters_count() + locals_count(), | 897 UpdateStateValues(&stack_node_, parameters_count() + locals_count(), |
| 882 stack_height()); | 898 stack_height()); |
| 883 | 899 |
| 884 const Operator* op = common()->FrameState( | 900 const Operator* op = common()->FrameState( |
| 885 ast_id, combine, builder()->frame_state_function_info()); | 901 ast_id, combine, builder()->frame_state_function_info()); |
| 886 | 902 |
| 887 Node* result = graph()->NewNode(op, parameters_node_, locals_node_, | 903 Node* result = graph()->NewNode(op, parameters_node_, locals_node_, |
| 888 stack_node_, builder()->current_context(), | 904 stack_node_, builder()->current_context(), |
| 889 builder()->GetFunctionClosure(), | 905 builder()->GetFunctionClosure(), |
| 890 builder()->graph()->start()); | 906 builder()->graph()->start()); |
| 891 | 907 |
| 892 DCHECK(IsLivenessBlockConsistent()); | 908 DCHECK(IsLivenessBlockConsistent()); |
| 893 if (liveness_block() != nullptr) { | 909 if (liveness_block() != nullptr) { |
| 894 liveness_block()->Checkpoint(result); | 910 // If the owning node has an exception, register the checkpoint to the |
| 911 // predecessor so that the checkpoint is used for both the normal and the | |
| 912 // exceptional paths. Yes, this is a terrible hack and we might want | |
| 913 // to use an explicit frame state for the exceptional path. | |
| 914 if (owner_has_exception) { | |
| 915 liveness_block()->GetPredecessor()->Checkpoint(result); | |
| 916 } else { | |
| 917 liveness_block()->Checkpoint(result); | |
| 918 } | |
| 895 } | 919 } |
| 896 return result; | 920 return result; |
| 897 } | 921 } |
| 898 | 922 |
| 899 | 923 |
| 900 bool AstGraphBuilder::Environment::IsLivenessAnalysisEnabled() { | 924 bool AstGraphBuilder::Environment::IsLivenessAnalysisEnabled() { |
| 901 return FLAG_analyze_environment_liveness && | 925 return FLAG_analyze_environment_liveness && |
| 902 builder()->info()->is_deoptimization_enabled(); | 926 builder()->info()->is_deoptimization_enabled(); |
| 903 } | 927 } |
| 904 | 928 |
| (...skipping 3133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4038 } | 4062 } |
| 4039 | 4063 |
| 4040 | 4064 |
| 4041 void AstGraphBuilder::PrepareFrameState(Node* node, BailoutId ast_id, | 4065 void AstGraphBuilder::PrepareFrameState(Node* node, BailoutId ast_id, |
| 4042 OutputFrameStateCombine combine) { | 4066 OutputFrameStateCombine combine) { |
| 4043 if (OperatorProperties::GetFrameStateInputCount(node->op()) > 0) { | 4067 if (OperatorProperties::GetFrameStateInputCount(node->op()) > 0) { |
| 4044 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op())); | 4068 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op())); |
| 4045 | 4069 |
| 4046 DCHECK_EQ(IrOpcode::kDead, | 4070 DCHECK_EQ(IrOpcode::kDead, |
| 4047 NodeProperties::GetFrameStateInput(node, 0)->opcode()); | 4071 NodeProperties::GetFrameStateInput(node, 0)->opcode()); |
| 4072 bool node_has_exception = NodeHasExceptionUse(node); | |
| 4048 NodeProperties::ReplaceFrameStateInput( | 4073 NodeProperties::ReplaceFrameStateInput( |
| 4049 node, 0, environment()->Checkpoint(ast_id, combine)); | 4074 node, 0, |
| 4075 environment()->Checkpoint(ast_id, combine, node_has_exception)); | |
| 4050 } | 4076 } |
| 4051 } | 4077 } |
| 4052 | 4078 |
| 4053 | 4079 |
| 4054 BitVector* AstGraphBuilder::GetVariablesAssignedInLoop( | 4080 BitVector* AstGraphBuilder::GetVariablesAssignedInLoop( |
| 4055 IterationStatement* stmt) { | 4081 IterationStatement* stmt) { |
| 4056 if (loop_assignment_analysis_ == nullptr) return nullptr; | 4082 if (loop_assignment_analysis_ == nullptr) return nullptr; |
| 4057 return loop_assignment_analysis_->GetVariablesAssignedInLoop(stmt); | 4083 return loop_assignment_analysis_->GetVariablesAssignedInLoop(stmt); |
| 4058 } | 4084 } |
| 4059 | 4085 |
| (...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4355 // Phi does not exist yet, introduce one. | 4381 // Phi does not exist yet, introduce one. |
| 4356 value = NewPhi(inputs, value, control); | 4382 value = NewPhi(inputs, value, control); |
| 4357 value->ReplaceInput(inputs - 1, other); | 4383 value->ReplaceInput(inputs - 1, other); |
| 4358 } | 4384 } |
| 4359 return value; | 4385 return value; |
| 4360 } | 4386 } |
| 4361 | 4387 |
| 4362 } // namespace compiler | 4388 } // namespace compiler |
| 4363 } // namespace internal | 4389 } // namespace internal |
| 4364 } // namespace v8 | 4390 } // namespace v8 |
| OLD | NEW |