Chromium Code Reviews| Index: src/compiler/bytecode-graph-builder.cc |
| diff --git a/src/compiler/bytecode-graph-builder.cc b/src/compiler/bytecode-graph-builder.cc |
| index 0100198c19d3a49dceb808752c6b03090319e3bd..a0dfec42d88e2e3232775f6b0d70384acb9749bf 100644 |
| --- a/src/compiler/bytecode-graph-builder.cc |
| +++ b/src/compiler/bytecode-graph-builder.cc |
| @@ -18,22 +18,28 @@ class BytecodeGraphBuilder::FrameStateBeforeAndAfter { |
| public: |
| FrameStateBeforeAndAfter(BytecodeGraphBuilder* builder, |
| const interpreter::BytecodeArrayIterator& iterator) |
| - : builder_(builder), id_after_(BailoutId::None()) { |
| + : builder_(builder), |
| + id_after_(BailoutId::None()), |
| + added_to_node_(false), |
| + output_poke_offset_(0), |
| + output_poke_count_(0) { |
| BailoutId id_before(iterator.current_offset()); |
| frame_state_before_ = builder_->environment()->Checkpoint( |
| - id_before, AccumulatorUpdateMode::kOutputIgnored); |
| + id_before, OutputFrameStateCombine::Ignore()); |
| id_after_ = BailoutId(id_before.ToInt() + iterator.current_bytecode_size()); |
| } |
| ~FrameStateBeforeAndAfter() { |
| - DCHECK(builder_->environment()->StateValuesAreUpToDate( |
| - accumulator_update_mode_)); |
| + DCHECK(added_to_node_); |
| + DCHECK(builder_->environment()->StateValuesAreUpToDate(output_poke_offset_, |
| + output_poke_count_)); |
| } |
| private: |
| friend class Environment; |
| - void AddToNode(Node* node, AccumulatorUpdateMode update_mode) { |
| + void AddToNode(Node* node, OutputFrameStateCombine combine, int poke_count) { |
| + DCHECK(!added_to_node_); |
| int count = OperatorProperties::GetFrameStateInputCount(node->op()); |
| DCHECK_LE(count, 2); |
| if (count >= 1) { |
| @@ -41,7 +47,7 @@ class BytecodeGraphBuilder::FrameStateBeforeAndAfter { |
| DCHECK_EQ(IrOpcode::kDead, |
| NodeProperties::GetFrameStateInput(node, 0)->opcode()); |
| Node* frame_state_after = |
| - builder_->environment()->Checkpoint(id_after_, update_mode); |
| + builder_->environment()->Checkpoint(id_after_, combine); |
| NodeProperties::ReplaceFrameStateInput(node, 0, frame_state_after); |
| } |
| @@ -51,13 +57,22 @@ class BytecodeGraphBuilder::FrameStateBeforeAndAfter { |
| NodeProperties::GetFrameStateInput(node, 1)->opcode()); |
| NodeProperties::ReplaceFrameStateInput(node, 1, frame_state_before_); |
| } |
| - accumulator_update_mode_ = update_mode; |
| + |
| + if (poke_count) { |
| + DCHECK(!combine.IsOutputIgnored()); |
| + output_poke_offset_ = static_cast<int>(combine.GetOffsetToPokeAt()); |
| + output_poke_count_ = poke_count; |
| + } |
| + added_to_node_ = true; |
| } |
| BytecodeGraphBuilder* builder_; |
| Node* frame_state_before_; |
| BailoutId id_after_; |
| - AccumulatorUpdateMode accumulator_update_mode_; |
| + |
| + bool added_to_node_; |
| + int output_poke_offset_; |
| + int output_poke_count_; |
| }; |
| @@ -134,10 +149,8 @@ int BytecodeGraphBuilder::Environment::RegisterToValuesIndex( |
| } |
| -void BytecodeGraphBuilder::Environment::BindRegister( |
| - interpreter::Register the_register, Node* node) { |
| - int values_index = RegisterToValuesIndex(the_register); |
| - values()->at(values_index) = node; |
| +Node* BytecodeGraphBuilder::Environment::LookupAccumulator() const { |
| + return values()->at(accumulator_base_); |
| } |
| @@ -156,33 +169,57 @@ Node* BytecodeGraphBuilder::Environment::LookupRegister( |
| } |
| +void BytecodeGraphBuilder::Environment::ExchangeRegisters( |
| + interpreter::Register reg0, interpreter::Register reg1) { |
| + int reg0_index = RegisterToValuesIndex(reg0); |
| + int reg1_index = RegisterToValuesIndex(reg1); |
| + Node* saved_reg0_value = values()->at(reg0_index); |
| + values()->at(reg0_index) = values()->at(reg1_index); |
| + values()->at(reg1_index) = saved_reg0_value; |
| +} |
| + |
| + |
| void BytecodeGraphBuilder::Environment::BindAccumulator( |
| Node* node, FrameStateBeforeAndAfter* states) { |
| if (states) { |
| - states->AddToNode(node, AccumulatorUpdateMode::kOutputInAccumulator); |
| + states->AddToNode(node, OutputFrameStateCombine::PokeAt(0), 1); |
| } |
| values()->at(accumulator_base_) = node; |
| } |
| -void BytecodeGraphBuilder::Environment::RecordAfterState( |
| - Node* node, FrameStateBeforeAndAfter* states) { |
| - states->AddToNode(node, AccumulatorUpdateMode::kOutputIgnored); |
| +void BytecodeGraphBuilder::Environment::BindRegister( |
| + interpreter::Register the_register, Node* node, |
| + FrameStateBeforeAndAfter* states) { |
| + int values_index = RegisterToValuesIndex(the_register); |
| + if (states) { |
| + states->AddToNode( |
| + node, OutputFrameStateCombine::PokeAt(accumulator_base_ - values_index), |
| + 1); |
| + } |
| + values()->at(values_index) = node; |
| } |
| -void BytecodeGraphBuilder::Environment::ExchangeRegisters( |
| - interpreter::Register reg0, interpreter::Register reg1) { |
| - int reg0_index = RegisterToValuesIndex(reg0); |
| - int reg1_index = RegisterToValuesIndex(reg1); |
| - Node* saved_reg0_value = values()->at(reg0_index); |
| - values()->at(reg0_index) = values()->at(reg1_index); |
| - values()->at(reg1_index) = saved_reg0_value; |
| +void BytecodeGraphBuilder::Environment::BindRegistersToProjections( |
| + interpreter::Register first_reg, Node* node, int count, |
| + FrameStateBeforeAndAfter* states) { |
| + int values_index = RegisterToValuesIndex(first_reg); |
| + if (states) { |
|
Jarin
2016/01/08 12:32:55
I think you should check that 'node->op()->ValueOu
rmcilroy
2016/01/08 14:47:20
Right, actually I think we should just use node->o
|
| + states->AddToNode( |
| + node, OutputFrameStateCombine::PokeAt(accumulator_base_ - values_index), |
| + count); |
| + } |
| + for (int i = 0; i < count; i++) { |
| + values()->at(values_index + i) = |
| + builder()->NewNode(common()->Projection(i), node); |
| + } |
| } |
| -Node* BytecodeGraphBuilder::Environment::LookupAccumulator() const { |
| - return values()->at(accumulator_base_); |
| +void BytecodeGraphBuilder::Environment::RecordAfterState( |
| + Node* node, FrameStateBeforeAndAfter* states) { |
| + states->AddToNode(node, OutputFrameStateCombine::Ignore(), 0); |
| } |
| @@ -290,7 +327,7 @@ void BytecodeGraphBuilder::Environment::UpdateStateValues(Node** state_values, |
| Node* BytecodeGraphBuilder::Environment::Checkpoint( |
| - BailoutId bailout_id, AccumulatorUpdateMode update_mode) { |
| + BailoutId bailout_id, OutputFrameStateCombine combine) { |
| if (!builder()->info()->is_deoptimization_enabled()) { |
| return builder()->jsgraph()->EmptyFrameState(); |
| } |
| @@ -301,13 +338,8 @@ Node* BytecodeGraphBuilder::Environment::Checkpoint( |
| register_count()); |
| UpdateStateValues(&accumulator_state_values_, accumulator_base(), 1); |
| - OutputFrameStateCombine combine = |
| - update_mode == AccumulatorUpdateMode::kOutputIgnored |
| - ? OutputFrameStateCombine::Ignore() |
| - : OutputFrameStateCombine::PokeAt(0); |
| const Operator* op = common()->FrameState( |
| bailout_id, combine, builder()->frame_state_function_info()); |
| - |
| Node* result = graph()->NewNode( |
| op, parameters_state_values_, registers_state_values_, |
| accumulator_state_values_, Context(), builder()->GetFunctionClosure(), |
| @@ -318,14 +350,32 @@ Node* BytecodeGraphBuilder::Environment::Checkpoint( |
| bool BytecodeGraphBuilder::Environment::StateValuesAreUpToDate( |
| - AccumulatorUpdateMode update_mode) { |
| - return !StateValuesRequireUpdate(¶meters_state_values_, 0, |
| - parameter_count()) && |
| - !StateValuesRequireUpdate(®isters_state_values_, register_base(), |
| - register_count()) && |
| - (update_mode == AccumulatorUpdateMode::kOutputInAccumulator || |
| - !StateValuesRequireUpdate(&accumulator_state_values_, |
| - accumulator_base(), 1)); |
| + Node** state_values, int offset, int count, int output_poke_start, |
| + int output_poke_end) { |
| + DCHECK_LE(static_cast<size_t>(offset + count), values()->size()); |
| + for (int i = 0; i < count; i++, offset++) { |
| + if (offset < output_poke_start || offset >= output_poke_end) { |
| + if ((*state_values)->InputAt(i) != values()->at(offset)) { |
| + return false; |
| + } |
| + } |
| + } |
| + return true; |
| +} |
| + |
| + |
| +bool BytecodeGraphBuilder::Environment::StateValuesAreUpToDate( |
| + int output_poke_offset, int output_poke_count) { |
| + // Poke offset is relative to the top of the stack (i.e., the accumulator). |
| + int output_poke_start = accumulator_base() - output_poke_offset; |
| + int output_poke_end = output_poke_start + output_poke_count; |
| + return StateValuesAreUpToDate(¶meters_state_values_, 0, parameter_count(), |
| + output_poke_start, output_poke_end) && |
| + StateValuesAreUpToDate(®isters_state_values_, register_base(), |
| + register_count(), output_poke_start, |
| + output_poke_end) && |
| + StateValuesAreUpToDate(&accumulator_state_values_, accumulator_base(), |
| + 1, output_poke_start, output_poke_end); |
| } |
| @@ -421,7 +471,10 @@ Node* BytecodeGraphBuilder::BuildLoadFeedbackVector() { |
| VectorSlotPair BytecodeGraphBuilder::CreateVectorSlotPair(int slot_id) { |
| Handle<TypeFeedbackVector> feedback_vector = info()->feedback_vector(); |
| - FeedbackVectorSlot slot = feedback_vector->ToSlot(slot_id); |
| + FeedbackVectorSlot slot; |
| + if (slot_id >= TypeFeedbackVector::kReservedIndexCount) { |
| + slot = feedback_vector->ToSlot(slot_id); |
| + } |
| return VectorSlotPair(feedback_vector, slot); |
| } |
| @@ -1201,7 +1254,18 @@ void BytecodeGraphBuilder::VisitCallRuntime( |
| void BytecodeGraphBuilder::VisitCallRuntimeForPair( |
| const interpreter::BytecodeArrayIterator& iterator) { |
| - UNIMPLEMENTED(); |
| + FrameStateBeforeAndAfter states(this, iterator); |
| + Runtime::FunctionId functionId = |
| + static_cast<Runtime::FunctionId>(iterator.GetIndexOperand(0)); |
| + interpreter::Register first_arg = iterator.GetRegisterOperand(1); |
| + size_t arg_count = iterator.GetCountOperand(2); |
| + interpreter::Register first_return = iterator.GetRegisterOperand(3); |
| + |
| + // Create node to perform the runtime call. |
| + const Operator* call = javascript()->CallRuntime(functionId, arg_count); |
| + Node* return_pair = ProcessCallRuntimeArguments(call, first_arg, arg_count); |
| + environment()->BindRegistersToProjections(first_return, return_pair, 2, |
| + &states); |
| } |