| 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 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 417 public: | 417 public: |
| 418 FrameStateBeforeAndAfter(AstGraphBuilder* builder, BailoutId id_before) | 418 FrameStateBeforeAndAfter(AstGraphBuilder* builder, BailoutId id_before) |
| 419 : builder_(builder), frame_state_before_(nullptr) { | 419 : builder_(builder), frame_state_before_(nullptr) { |
| 420 frame_state_before_ = id_before == BailoutId::None() | 420 frame_state_before_ = id_before == BailoutId::None() |
| 421 ? builder_->GetEmptyFrameState() | 421 ? builder_->GetEmptyFrameState() |
| 422 : builder_->environment()->Checkpoint(id_before); | 422 : builder_->environment()->Checkpoint(id_before); |
| 423 if (id_before != BailoutId::None()) { | 423 if (id_before != BailoutId::None()) { |
| 424 // Create an explicit checkpoint node for before the operation. | 424 // Create an explicit checkpoint node for before the operation. |
| 425 Node* node = builder_->NewNode(builder_->common()->Checkpoint()); | 425 Node* node = builder_->NewNode(builder_->common()->Checkpoint()); |
| 426 DCHECK_EQ(IrOpcode::kDead, | 426 DCHECK_EQ(IrOpcode::kDead, |
| 427 NodeProperties::GetFrameStateInput(node, 0)->opcode()); | 427 NodeProperties::GetFrameStateInput(node)->opcode()); |
| 428 NodeProperties::ReplaceFrameStateInput(node, 0, frame_state_before_); | 428 NodeProperties::ReplaceFrameStateInput(node, frame_state_before_); |
| 429 } | 429 } |
| 430 } | 430 } |
| 431 | 431 |
| 432 void AddToNode( | 432 void AddToNode( |
| 433 Node* node, BailoutId id_after, | 433 Node* node, BailoutId id_after, |
| 434 OutputFrameStateCombine combine = OutputFrameStateCombine::Ignore()) { | 434 OutputFrameStateCombine combine = OutputFrameStateCombine::Ignore()) { |
| 435 int count = OperatorProperties::GetFrameStateInputCount(node->op()); | 435 if (OperatorProperties::HasFrameStateInput(node->op())) { |
| 436 DCHECK_LE(count, 2); | |
| 437 | |
| 438 if (count >= 1) { | |
| 439 // Add the frame state for after the operation. | 436 // Add the frame state for after the operation. |
| 440 DCHECK_EQ(IrOpcode::kDead, | 437 DCHECK_EQ(IrOpcode::kDead, |
| 441 NodeProperties::GetFrameStateInput(node, 0)->opcode()); | 438 NodeProperties::GetFrameStateInput(node)->opcode()); |
| 442 | 439 |
| 443 bool node_has_exception = NodeProperties::IsExceptionalCall(node); | 440 bool node_has_exception = NodeProperties::IsExceptionalCall(node); |
| 444 | 441 |
| 445 Node* frame_state_after = | 442 Node* frame_state_after = |
| 446 id_after == BailoutId::None() | 443 id_after == BailoutId::None() |
| 447 ? builder_->GetEmptyFrameState() | 444 ? builder_->GetEmptyFrameState() |
| 448 : builder_->environment()->Checkpoint(id_after, combine, | 445 : builder_->environment()->Checkpoint(id_after, combine, |
| 449 node_has_exception); | 446 node_has_exception); |
| 450 | 447 |
| 451 NodeProperties::ReplaceFrameStateInput(node, 0, frame_state_after); | 448 NodeProperties::ReplaceFrameStateInput(node, frame_state_after); |
| 452 } | |
| 453 | |
| 454 if (count >= 2) { | |
| 455 // Add the frame state for before the operation. | |
| 456 // TODO(mstarzinger): Get rid of frame state input before! | |
| 457 DCHECK_EQ(IrOpcode::kDead, | |
| 458 NodeProperties::GetFrameStateInput(node, 1)->opcode()); | |
| 459 NodeProperties::ReplaceFrameStateInput(node, 1, frame_state_before_); | |
| 460 } | 449 } |
| 461 } | 450 } |
| 462 | 451 |
| 463 private: | 452 private: |
| 464 AstGraphBuilder* builder_; | 453 AstGraphBuilder* builder_; |
| 465 Node* frame_state_before_; | 454 Node* frame_state_before_; |
| 466 }; | 455 }; |
| 467 | 456 |
| 468 AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info, | 457 AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info, |
| 469 JSGraph* jsgraph, LoopAssignmentAnalysis* loop, | 458 JSGraph* jsgraph, LoopAssignmentAnalysis* loop, |
| (...skipping 3572 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4042 info()->set_osr_expr_stack_height(std::max( | 4031 info()->set_osr_expr_stack_height(std::max( |
| 4043 environment()->stack_height(), info()->osr_expr_stack_height())); | 4032 environment()->stack_height(), info()->osr_expr_stack_height())); |
| 4044 return true; | 4033 return true; |
| 4045 } | 4034 } |
| 4046 return false; | 4035 return false; |
| 4047 } | 4036 } |
| 4048 | 4037 |
| 4049 | 4038 |
| 4050 void AstGraphBuilder::PrepareFrameState(Node* node, BailoutId ast_id, | 4039 void AstGraphBuilder::PrepareFrameState(Node* node, BailoutId ast_id, |
| 4051 OutputFrameStateCombine combine) { | 4040 OutputFrameStateCombine combine) { |
| 4052 if (OperatorProperties::GetFrameStateInputCount(node->op()) > 0) { | 4041 if (OperatorProperties::HasFrameStateInput(node->op())) { |
| 4053 DCHECK(ast_id.IsNone() || info()->shared_info()->VerifyBailoutId(ast_id)); | 4042 DCHECK(ast_id.IsNone() || info()->shared_info()->VerifyBailoutId(ast_id)); |
| 4054 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op())); | 4043 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op())); |
| 4055 DCHECK_EQ(IrOpcode::kDead, | 4044 DCHECK_EQ(IrOpcode::kDead, |
| 4056 NodeProperties::GetFrameStateInput(node, 0)->opcode()); | 4045 NodeProperties::GetFrameStateInput(node)->opcode()); |
| 4057 bool has_exception = NodeProperties::IsExceptionalCall(node); | 4046 bool has_exception = NodeProperties::IsExceptionalCall(node); |
| 4058 Node* state = environment()->Checkpoint(ast_id, combine, has_exception); | 4047 Node* state = environment()->Checkpoint(ast_id, combine, has_exception); |
| 4059 NodeProperties::ReplaceFrameStateInput(node, 0, state); | 4048 NodeProperties::ReplaceFrameStateInput(node, state); |
| 4060 } | 4049 } |
| 4061 } | 4050 } |
| 4062 | 4051 |
| 4063 void AstGraphBuilder::PrepareEagerCheckpoint(BailoutId ast_id) { | 4052 void AstGraphBuilder::PrepareEagerCheckpoint(BailoutId ast_id) { |
| 4064 if (environment()->GetEffectDependency()->opcode() == IrOpcode::kCheckpoint) { | 4053 if (environment()->GetEffectDependency()->opcode() == IrOpcode::kCheckpoint) { |
| 4065 // We skip preparing a checkpoint if there already is one the current effect | 4054 // We skip preparing a checkpoint if there already is one the current effect |
| 4066 // dependency. This is just an optimization and not need for correctness. | 4055 // dependency. This is just an optimization and not need for correctness. |
| 4067 return; | 4056 return; |
| 4068 } | 4057 } |
| 4069 if (ast_id != BailoutId::None()) { | 4058 if (ast_id != BailoutId::None()) { |
| 4070 DCHECK(info()->shared_info()->VerifyBailoutId(ast_id)); | 4059 DCHECK(info()->shared_info()->VerifyBailoutId(ast_id)); |
| 4071 Node* node = NewNode(common()->Checkpoint()); | 4060 Node* node = NewNode(common()->Checkpoint()); |
| 4072 DCHECK_EQ(IrOpcode::kDead, | 4061 DCHECK_EQ(IrOpcode::kDead, |
| 4073 NodeProperties::GetFrameStateInput(node, 0)->opcode()); | 4062 NodeProperties::GetFrameStateInput(node)->opcode()); |
| 4074 Node* state = environment()->Checkpoint(ast_id); | 4063 Node* state = environment()->Checkpoint(ast_id); |
| 4075 NodeProperties::ReplaceFrameStateInput(node, 0, state); | 4064 NodeProperties::ReplaceFrameStateInput(node, state); |
| 4076 } | 4065 } |
| 4077 } | 4066 } |
| 4078 | 4067 |
| 4079 BitVector* AstGraphBuilder::GetVariablesAssignedInLoop( | 4068 BitVector* AstGraphBuilder::GetVariablesAssignedInLoop( |
| 4080 IterationStatement* stmt) { | 4069 IterationStatement* stmt) { |
| 4081 if (loop_assignment_analysis_ == nullptr) return nullptr; | 4070 if (loop_assignment_analysis_ == nullptr) return nullptr; |
| 4082 return loop_assignment_analysis_->GetVariablesAssignedInLoop(stmt); | 4071 return loop_assignment_analysis_->GetVariablesAssignedInLoop(stmt); |
| 4083 } | 4072 } |
| 4084 | 4073 |
| 4085 | 4074 |
| 4086 Node** AstGraphBuilder::EnsureInputBufferSize(int size) { | 4075 Node** AstGraphBuilder::EnsureInputBufferSize(int size) { |
| 4087 if (size > input_buffer_size_) { | 4076 if (size > input_buffer_size_) { |
| 4088 size = size + kInputBufferSizeIncrement + input_buffer_size_; | 4077 size = size + kInputBufferSizeIncrement + input_buffer_size_; |
| 4089 input_buffer_ = local_zone()->NewArray<Node*>(size); | 4078 input_buffer_ = local_zone()->NewArray<Node*>(size); |
| 4090 input_buffer_size_ = size; | 4079 input_buffer_size_ = size; |
| 4091 } | 4080 } |
| 4092 return input_buffer_; | 4081 return input_buffer_; |
| 4093 } | 4082 } |
| 4094 | 4083 |
| 4095 | 4084 |
| 4096 Node* AstGraphBuilder::MakeNode(const Operator* op, int value_input_count, | 4085 Node* AstGraphBuilder::MakeNode(const Operator* op, int value_input_count, |
| 4097 Node** value_inputs, bool incomplete) { | 4086 Node** value_inputs, bool incomplete) { |
| 4098 DCHECK_EQ(op->ValueInputCount(), value_input_count); | 4087 DCHECK_EQ(op->ValueInputCount(), value_input_count); |
| 4099 | 4088 |
| 4100 bool has_context = OperatorProperties::HasContextInput(op); | 4089 bool has_context = OperatorProperties::HasContextInput(op); |
| 4101 int frame_state_count = OperatorProperties::GetFrameStateInputCount(op); | 4090 bool has_frame_state = OperatorProperties::HasFrameStateInput(op); |
| 4102 bool has_control = op->ControlInputCount() == 1; | 4091 bool has_control = op->ControlInputCount() == 1; |
| 4103 bool has_effect = op->EffectInputCount() == 1; | 4092 bool has_effect = op->EffectInputCount() == 1; |
| 4104 | 4093 |
| 4105 DCHECK(op->ControlInputCount() < 2); | 4094 DCHECK(op->ControlInputCount() < 2); |
| 4106 DCHECK(op->EffectInputCount() < 2); | 4095 DCHECK(op->EffectInputCount() < 2); |
| 4107 | 4096 |
| 4108 Node* result = nullptr; | 4097 Node* result = nullptr; |
| 4109 if (!has_context && frame_state_count == 0 && !has_control && !has_effect) { | 4098 if (!has_context && !has_frame_state && !has_control && !has_effect) { |
| 4110 result = graph()->NewNode(op, value_input_count, value_inputs, incomplete); | 4099 result = graph()->NewNode(op, value_input_count, value_inputs, incomplete); |
| 4111 } else { | 4100 } else { |
| 4112 bool inside_try_scope = try_nesting_level_ > 0; | 4101 bool inside_try_scope = try_nesting_level_ > 0; |
| 4113 int input_count_with_deps = value_input_count; | 4102 int input_count_with_deps = value_input_count; |
| 4114 if (has_context) ++input_count_with_deps; | 4103 if (has_context) ++input_count_with_deps; |
| 4115 input_count_with_deps += frame_state_count; | 4104 if (has_frame_state) ++input_count_with_deps; |
| 4116 if (has_control) ++input_count_with_deps; | 4105 if (has_control) ++input_count_with_deps; |
| 4117 if (has_effect) ++input_count_with_deps; | 4106 if (has_effect) ++input_count_with_deps; |
| 4118 Node** buffer = EnsureInputBufferSize(input_count_with_deps); | 4107 Node** buffer = EnsureInputBufferSize(input_count_with_deps); |
| 4119 memcpy(buffer, value_inputs, kPointerSize * value_input_count); | 4108 memcpy(buffer, value_inputs, kPointerSize * value_input_count); |
| 4120 Node** current_input = buffer + value_input_count; | 4109 Node** current_input = buffer + value_input_count; |
| 4121 if (has_context) { | 4110 if (has_context) { |
| 4122 *current_input++ = current_context(); | 4111 *current_input++ = current_context(); |
| 4123 } | 4112 } |
| 4124 for (int i = 0; i < frame_state_count; i++) { | 4113 if (has_frame_state) { |
| 4125 // The frame state will be inserted later. Here we misuse | 4114 // The frame state will be inserted later. Here we misuse |
| 4126 // the {Dead} node as a sentinel to be later overwritten | 4115 // the {Dead} node as a sentinel to be later overwritten |
| 4127 // with the real frame state. | 4116 // with the real frame state. |
| 4128 *current_input++ = jsgraph()->Dead(); | 4117 *current_input++ = jsgraph()->Dead(); |
| 4129 } | 4118 } |
| 4130 if (has_effect) { | 4119 if (has_effect) { |
| 4131 *current_input++ = environment_->GetEffectDependency(); | 4120 *current_input++ = environment_->GetEffectDependency(); |
| 4132 } | 4121 } |
| 4133 if (has_control) { | 4122 if (has_control) { |
| 4134 *current_input++ = environment_->GetControlDependency(); | 4123 *current_input++ = environment_->GetControlDependency(); |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4375 // Phi does not exist yet, introduce one. | 4364 // Phi does not exist yet, introduce one. |
| 4376 value = NewPhi(inputs, value, control); | 4365 value = NewPhi(inputs, value, control); |
| 4377 value->ReplaceInput(inputs - 1, other); | 4366 value->ReplaceInput(inputs - 1, other); |
| 4378 } | 4367 } |
| 4379 return value; | 4368 return value; |
| 4380 } | 4369 } |
| 4381 | 4370 |
| 4382 } // namespace compiler | 4371 } // namespace compiler |
| 4383 } // namespace internal | 4372 } // namespace internal |
| 4384 } // namespace v8 | 4373 } // namespace v8 |
| OLD | NEW |