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 |