| Index: src/compiler/int64-lowering.cc
|
| diff --git a/src/compiler/int64-lowering.cc b/src/compiler/int64-lowering.cc
|
| index c2952319be24a4345a4095bb6a2e221f6b7a9edf..c9c87b65d6de55807e5fa6a13afbe5bc232a3287 100644
|
| --- a/src/compiler/int64-lowering.cc
|
| +++ b/src/compiler/int64-lowering.cc
|
| @@ -5,8 +5,12 @@
|
| #include "src/compiler/int64-lowering.h"
|
| #include "src/compiler/common-operator.h"
|
| #include "src/compiler/graph.h"
|
| +#include "src/compiler/linkage.h"
|
| #include "src/compiler/machine-operator.h"
|
| +#include "src/compiler/node-properties.h"
|
| +
|
| #include "src/compiler/node.h"
|
| +#include "src/wasm/wasm-module.h"
|
| #include "src/zone.h"
|
|
|
| namespace v8 {
|
| @@ -14,17 +18,23 @@ namespace internal {
|
| namespace compiler {
|
|
|
| Int64Lowering::Int64Lowering(Graph* graph, MachineOperatorBuilder* machine,
|
| - CommonOperatorBuilder* common, Zone* zone)
|
| - : graph_(graph),
|
| + CommonOperatorBuilder* common, Zone* zone,
|
| + Signature<MachineRepresentation>* signature)
|
| + : zone_(zone),
|
| + graph_(graph),
|
| machine_(machine),
|
| common_(common),
|
| state_(graph, 4),
|
| stack_(zone),
|
| - replacements_(zone->NewArray<Replacement>(graph->NodeCount())) {
|
| + replacements_(zone->NewArray<Replacement>(graph->NodeCount())),
|
| + signature_(signature) {
|
| memset(replacements_, 0, sizeof(Replacement) * graph->NodeCount());
|
| }
|
|
|
| -void Int64Lowering::ReduceGraph() {
|
| +void Int64Lowering::LowerGraph() {
|
| + if (4 != kPointerSize) {
|
| + return;
|
| + }
|
| stack_.push(graph()->end());
|
| state_.Set(graph()->end(), State::kOnStack);
|
|
|
| @@ -34,7 +44,7 @@ void Int64Lowering::ReduceGraph() {
|
| stack_.pop();
|
| state_.Set(top, State::kVisited);
|
| // All inputs of top have already been reduced, now reduce top.
|
| - ReduceNode(top);
|
| + LowerNode(top);
|
| } else {
|
| // Push all children onto the stack.
|
| for (Node* input : top->inputs()) {
|
| @@ -48,7 +58,35 @@ void Int64Lowering::ReduceGraph() {
|
| }
|
| }
|
|
|
| -void Int64Lowering::ReduceNode(Node* node) {
|
| +static int GetParameterIndexAfterLowering(
|
| + Signature<MachineRepresentation>* signature, int old_index) {
|
| + int result = old_index;
|
| + for (int i = 0; i < old_index; i++) {
|
| + if (signature->GetParam(i) == MachineRepresentation::kWord64) {
|
| + result++;
|
| + }
|
| + }
|
| + return result;
|
| +}
|
| +
|
| +static int GetParameterCountAfterLowering(
|
| + Signature<MachineRepresentation>* signature) {
|
| + return GetParameterIndexAfterLowering(
|
| + signature, static_cast<int>(signature->parameter_count()));
|
| +}
|
| +
|
| +static int GetReturnCountAfterLowering(
|
| + Signature<MachineRepresentation>* signature) {
|
| + int result = static_cast<int>(signature->return_count());
|
| + for (int i = 0; i < static_cast<int>(signature->return_count()); i++) {
|
| + if (signature->GetReturn(i) == MachineRepresentation::kWord64) {
|
| + result++;
|
| + }
|
| + }
|
| + return result;
|
| +}
|
| +
|
| +void Int64Lowering::LowerNode(Node* node) {
|
| switch (node->opcode()) {
|
| case IrOpcode::kInt64Constant: {
|
| int64_t value = OpParameter<int64_t>(node);
|
| @@ -56,48 +94,207 @@ void Int64Lowering::ReduceNode(Node* node) {
|
| common()->Int32Constant(static_cast<int32_t>(value & 0xFFFFFFFF)));
|
| Node* high_node = graph()->NewNode(
|
| common()->Int32Constant(static_cast<int32_t>(value >> 32)));
|
| - replacements_[node->id()].low = low_node;
|
| - replacements_[node->id()].high = high_node;
|
| + ReplaceNode(node, low_node, high_node);
|
| + break;
|
| + }
|
| + case IrOpcode::kLoad: {
|
| + LoadRepresentation load_rep = LoadRepresentationOf(node->op());
|
| +
|
| + if (load_rep.representation() == MachineRepresentation::kWord64) {
|
| + Node* base = node->InputAt(0);
|
| + Node* index = node->InputAt(1);
|
| + Node* index_high =
|
| + graph()->NewNode(machine()->Int32Add(), index,
|
| + graph()->NewNode(common()->Int32Constant(4)));
|
| +
|
| + const Operator* load_op = machine()->Load(MachineType::Int32());
|
| + Node* high_node;
|
| + if (node->InputCount() > 2) {
|
| + Node* effect_high = node->InputAt(2);
|
| + Node* control_high = node->InputAt(3);
|
| + high_node = graph()->NewNode(load_op, base, index_high, effect_high,
|
| + control_high);
|
| + // change the effect change from old_node --> old_effect to
|
| + // old_node --> high_node --> old_effect.
|
| + node->ReplaceInput(2, high_node);
|
| + } else {
|
| + high_node = graph()->NewNode(load_op, base, index_high);
|
| + }
|
| + NodeProperties::ChangeOp(node, load_op);
|
| + ReplaceNode(node, node, high_node);
|
| + }
|
| + break;
|
| + }
|
| + case IrOpcode::kStore: {
|
| + StoreRepresentation store_rep = StoreRepresentationOf(node->op());
|
| + if (store_rep.representation() == MachineRepresentation::kWord64) {
|
| + // We change the original store node to store the low word, and create
|
| + // a new store node to store the high word. The effect and control edges
|
| + // are copied from the original store to the new store node, the effect
|
| + // edge of the original store is redirected to the new store.
|
| + WriteBarrierKind write_barrier_kind = store_rep.write_barrier_kind();
|
| +
|
| + Node* base = node->InputAt(0);
|
| + Node* index = node->InputAt(1);
|
| + Node* index_high =
|
| + graph()->NewNode(machine()->Int32Add(), index,
|
| + graph()->NewNode(common()->Int32Constant(4)));
|
| +
|
| + Node* value = node->InputAt(2);
|
| + DCHECK(HasReplacementLow(value));
|
| + DCHECK(HasReplacementHigh(value));
|
| +
|
| + const Operator* store_op = machine()->Store(StoreRepresentation(
|
| + MachineRepresentation::kWord32, write_barrier_kind));
|
| +
|
| + Node* high_node;
|
| + if (node->InputCount() > 3) {
|
| + Node* effect_high = node->InputAt(3);
|
| + Node* control_high = node->InputAt(4);
|
| + high_node = graph()->NewNode(store_op, base, index_high,
|
| + GetReplacementHigh(value), effect_high,
|
| + control_high);
|
| + node->ReplaceInput(3, high_node);
|
| +
|
| + } else {
|
| + high_node = graph()->NewNode(store_op, base, index_high,
|
| + GetReplacementHigh(value));
|
| + }
|
| +
|
| + node->ReplaceInput(2, GetReplacementLow(value));
|
| + NodeProperties::ChangeOp(node, store_op);
|
| + ReplaceNode(node, node, high_node);
|
| + }
|
| break;
|
| }
|
| case IrOpcode::kWord64And: {
|
| + DCHECK(node->InputCount() == 2);
|
| Node* left = node->InputAt(0);
|
| - DCHECK(replacements_[left->id()].low);
|
| - Node* left_low = replacements_[left->id()].low;
|
| - Node* left_high = replacements_[left->id()].high;
|
| -
|
| Node* right = node->InputAt(1);
|
| - DCHECK(replacements_[right->id()].low);
|
| - Node* right_low = replacements_[right->id()].low;
|
| - Node* right_high = replacements_[right->id()].high;
|
| -
|
| - replacements_[node->id()].low =
|
| - graph()->NewNode(machine()->Word32And(), left_low, right_low);
|
| - replacements_[node->id()].high =
|
| - graph()->NewNode(machine()->Word32And(), left_high, right_high);
|
| +
|
| + Node* low_node =
|
| + graph()->NewNode(machine()->Word32And(), GetReplacementLow(left),
|
| + GetReplacementLow(right));
|
| + Node* high_node =
|
| + graph()->NewNode(machine()->Word32And(), GetReplacementHigh(left),
|
| + GetReplacementHigh(right));
|
| + ReplaceNode(node, low_node, high_node);
|
| break;
|
| }
|
| case IrOpcode::kTruncateInt64ToInt32: {
|
| + DCHECK(node->InputCount() == 1);
|
| Node* input = node->InputAt(0);
|
| - DCHECK(replacements_[input->id()].low);
|
| - replacements_[node->id()].low = replacements_[input->id()].low;
|
| + ReplaceNode(node, GetReplacementLow(input), nullptr);
|
| + node->NullAllInputs();
|
| break;
|
| }
|
| - default: {
|
| - // Also the inputs of nodes can change which do not expect int64 inputs.
|
| - for (int i = 0; i < node->InputCount(); i++) {
|
| - Node* input = node->InputAt(i);
|
| - // The input has changed altough it was not an int64 input. This can
|
| - // happen e.g. if the input node is IrOpcode::kTruncateInt64ToInt32. We
|
| - // use the low word replacement as the new input.
|
| - if (replacements_[input->id()].low) {
|
| - node->ReplaceInput(i, replacements_[input->id()].low);
|
| + case IrOpcode::kStart: {
|
| + int parameter_count = GetParameterCountAfterLowering(signature());
|
| + // Only exchange the node if the parameter count actually changed.
|
| + if (parameter_count != signature()->parameter_count()) {
|
| + int delta =
|
| + parameter_count - static_cast<int>(signature()->parameter_count());
|
| + int new_output_count = node->op()->ValueOutputCount() + delta;
|
| + NodeProperties::ChangeOp(node, common()->Start(new_output_count));
|
| + }
|
| + break;
|
| + }
|
| + case IrOpcode::kParameter: {
|
| + DCHECK(node->InputCount() == 1);
|
| + // Only exchange the node if the parameter count actually changed. We do
|
| + // not even have to do the default lowering because the the start node,
|
| + // the only input of a parameter node, only changes if the parameter count
|
| + // changes.
|
| + if (GetParameterCountAfterLowering(signature()) !=
|
| + signature()->parameter_count()) {
|
| + int old_index = ParameterIndexOf(node->op());
|
| + int new_index = GetParameterIndexAfterLowering(signature(), old_index);
|
| + Node* low_node =
|
| + graph()->NewNode(common()->Parameter(new_index), graph()->start());
|
| +
|
| + Node* high_node = nullptr;
|
| + if (signature()->GetParam(old_index) ==
|
| + MachineRepresentation::kWord64) {
|
| + high_node = graph()->NewNode(common()->Parameter(new_index + 1),
|
| + graph()->start());
|
| }
|
| + ReplaceNode(node, low_node, high_node);
|
| + }
|
| + break;
|
| + }
|
| + case IrOpcode::kReturn: {
|
| + DefaultLowering(node);
|
| + int new_return_count = GetReturnCountAfterLowering(signature());
|
| + if (signature()->return_count() != new_return_count) {
|
| + NodeProperties::ChangeOp(node, common()->Return(new_return_count));
|
| }
|
| + break;
|
| + }
|
| + case IrOpcode::kCall: {
|
| + CallDescriptor* descriptor = OpParameter<CallDescriptor*>(node);
|
| + if (DefaultLowering(node) ||
|
| + (descriptor->ReturnCount() == 1 &&
|
| + descriptor->GetReturnType(0) == MachineType::Int64())) {
|
| + // We have to adjust the call descriptor.
|
| + const Operator* op = common()->Call(
|
| + wasm::ModuleEnv::GetI32WasmCallDescriptor(zone(), descriptor));
|
| + NodeProperties::ChangeOp(node, op);
|
| + }
|
| + if (descriptor->ReturnCount() == 1 &&
|
| + descriptor->GetReturnType(0) == MachineType::Int64()) {
|
| + // We access the additional return values through projections.
|
| + Node* low_node = graph()->NewNode(common()->Projection(0), node);
|
| + Node* high_node = graph()->NewNode(common()->Projection(1), node);
|
| + ReplaceNode(node, low_node, high_node);
|
| + }
|
| + break;
|
| }
|
| + default: { DefaultLowering(node); }
|
| }
|
| }
|
|
|
| +bool Int64Lowering::DefaultLowering(Node* node) {
|
| + bool something_changed = false;
|
| + for (int i = NodeProperties::PastValueIndex(node) - 1; i >= 0; i--) {
|
| + Node* input = node->InputAt(i);
|
| + if (HasReplacementLow(input)) {
|
| + something_changed = true;
|
| + node->ReplaceInput(i, GetReplacementLow(input));
|
| + }
|
| + if (HasReplacementHigh(input)) {
|
| + something_changed = true;
|
| + node->InsertInput(zone(), i + 1, GetReplacementHigh(input));
|
| + }
|
| + }
|
| + return something_changed;
|
| +}
|
| +
|
| +void Int64Lowering::ReplaceNode(Node* old, Node* new_low, Node* new_high) {
|
| + // if new_low == nullptr, then also new_high == nullptr.
|
| + DCHECK(new_low != nullptr || new_high == nullptr);
|
| + replacements_[old->id()].low = new_low;
|
| + replacements_[old->id()].high = new_high;
|
| +}
|
| +
|
| +bool Int64Lowering::HasReplacementLow(Node* node) {
|
| + return replacements_[node->id()].low != nullptr;
|
| +}
|
| +
|
| +Node* Int64Lowering::GetReplacementLow(Node* node) {
|
| + Node* result = replacements_[node->id()].low;
|
| + DCHECK(result);
|
| + return result;
|
| +}
|
| +
|
| +bool Int64Lowering::HasReplacementHigh(Node* node) {
|
| + return replacements_[node->id()].high != nullptr;
|
| +}
|
| +
|
| +Node* Int64Lowering::GetReplacementHigh(Node* node) {
|
| + Node* result = replacements_[node->id()].high;
|
| + DCHECK(result);
|
| + return result;
|
| +}
|
| } // namespace compiler
|
| } // namespace internal
|
| } // namespace v8
|
|
|