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 |