| 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..a64f1fb509fe39a186044d82a582d5158eaea1dd 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) {
|
| + 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,21 @@ class BytecodeGraphBuilder::FrameStateBeforeAndAfter {
|
| NodeProperties::GetFrameStateInput(node, 1)->opcode());
|
| NodeProperties::ReplaceFrameStateInput(node, 1, frame_state_before_);
|
| }
|
| - accumulator_update_mode_ = update_mode;
|
| +
|
| + if (!combine.IsOutputIgnored()) {
|
| + output_poke_offset_ = static_cast<int>(combine.GetOffsetToPokeAt());
|
| + output_poke_count_ = node->op()->ValueOutputCount();
|
| + }
|
| + 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 +148,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 +168,55 @@ 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));
|
| }
|
| 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));
|
| + }
|
| + 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,
|
| + FrameStateBeforeAndAfter* states) {
|
| + int values_index = RegisterToValuesIndex(first_reg);
|
| + if (states) {
|
| + states->AddToNode(node, OutputFrameStateCombine::PokeAt(accumulator_base_ -
|
| + values_index));
|
| + }
|
| + for (int i = 0; i < node->op()->ValueOutputCount(); 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());
|
| }
|
|
|
|
|
| @@ -290,7 +324,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 +335,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 +347,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 +468,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 +1251,17 @@ 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, &states);
|
| }
|
|
|
|
|
|
|