Commit a3f782f2 authored by jarin's avatar jarin Committed by Commit bot

[turbofan] Factor out platform-independent part of InstructionSelector::VisitCall.

Review URL: https://codereview.chromium.org/1411093006

Cr-Commit-Position: refs/heads/master@{#31547}
parent ae8f79ef
......@@ -1110,23 +1110,10 @@ void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) {
}
void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
void InstructionSelector::EmitPrepareArguments(NodeVector* arguments,
const CallDescriptor* descriptor,
Node* node) {
ArmOperandGenerator g(this);
const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(node);
FrameStateDescriptor* frame_state_descriptor = nullptr;
if (descriptor->NeedsFrameState()) {
frame_state_descriptor =
GetFrameStateDescriptor(node->InputAt(descriptor->InputCount()));
}
CallBuffer buffer(zone(), descriptor, frame_state_descriptor);
// Compute InstructionOperands for inputs and outputs.
// TODO(turbofan): on ARM it's probably better to use the code object in a
// register if there are multiple uses of it. Improve constant pool and the
// heuristics in the register allocator for where to emit constants.
InitializeCallBuffer(node, &buffer, true, true);
// Prepare for C function call.
if (descriptor->IsCFunctionCall()) {
......@@ -1135,8 +1122,8 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
0, nullptr, 0, nullptr);
// Poke any stack arguments.
for (size_t n = 0; n < buffer.pushed_nodes.size(); ++n) {
if (Node* input = buffer.pushed_nodes[n]) {
for (size_t n = 0; n < arguments->size(); ++n) {
if (Node* input = (*arguments)[n]) {
int slot = static_cast<int>(n);
Emit(kArmPoke | MiscField::encode(slot), g.NoOutput(),
g.UseRegister(input));
......@@ -1144,49 +1131,12 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
}
} else {
// Push any stack arguments.
for (Node* input : base::Reversed(buffer.pushed_nodes)) {
for (Node* input : base::Reversed(*arguments)) {
// Skip any alignment holes in pushed nodes.
if (input == nullptr) continue;
Emit(kArmPush, g.NoOutput(), g.UseRegister(input));
}
}
// Pass label of exception handler block.
CallDescriptor::Flags flags = descriptor->flags();
if (handler) {
DCHECK_EQ(IrOpcode::kIfException, handler->front()->opcode());
IfExceptionHint hint = OpParameter<IfExceptionHint>(handler->front());
if (hint == IfExceptionHint::kLocallyCaught) {
flags |= CallDescriptor::kHasLocalCatchHandler;
}
flags |= CallDescriptor::kHasExceptionHandler;
buffer.instruction_args.push_back(g.Label(handler));
}
// Select the appropriate opcode based on the call type.
InstructionCode opcode = kArchNop;
switch (descriptor->kind()) {
case CallDescriptor::kCallAddress:
opcode =
kArchCallCFunction |
MiscField::encode(static_cast<int>(descriptor->CParameterCount()));
break;
case CallDescriptor::kCallCodeObject:
opcode = kArchCallCodeObject | MiscField::encode(flags);
break;
case CallDescriptor::kCallJSFunction:
opcode = kArchCallJSFunction | MiscField::encode(flags);
break;
case CallDescriptor::kLazyBailout:
opcode = kArchLazyBailout | MiscField::encode(flags);
break;
}
// Emit the call instruction.
size_t const output_count = buffer.outputs.size();
auto* outputs = output_count ? &buffer.outputs.front() : nullptr;
Emit(opcode, output_count, outputs, buffer.instruction_args.size(),
&buffer.instruction_args.front())->MarkAsCall();
}
......
......@@ -1416,26 +1416,13 @@ void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) {
}
void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
void InstructionSelector::EmitPrepareArguments(NodeVector* arguments,
const CallDescriptor* descriptor,
Node* node) {
Arm64OperandGenerator g(this);
const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(node);
FrameStateDescriptor* frame_state_descriptor = nullptr;
if (descriptor->NeedsFrameState()) {
frame_state_descriptor = GetFrameStateDescriptor(
node->InputAt(static_cast<int>(descriptor->InputCount())));
}
CallBuffer buffer(zone(), descriptor, frame_state_descriptor);
// Compute InstructionOperands for inputs and outputs.
// TODO(turbofan): on ARM64 it's probably better to use the code object in a
// register if there are multiple uses of it. Improve constant pool and the
// heuristics in the register allocator for where to emit constants.
InitializeCallBuffer(node, &buffer, true, true);
// Push the arguments to the stack.
int aligned_push_count = static_cast<int>(buffer.pushed_nodes.size());
int aligned_push_count = static_cast<int>(arguments->size());
bool pushed_count_uneven = aligned_push_count & 1;
// TODO(dcarney): claim and poke probably take small immediates,
// loop here or whatever.
......@@ -1450,56 +1437,17 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
int slot = aligned_push_count - 1;
// Emit the uneven pushes.
if (pushed_count_uneven) {
Node* input = buffer.pushed_nodes[slot];
Node* input = (*arguments)[slot];
Emit(kArm64Poke, g.NoOutput(), g.UseRegister(input),
g.TempImmediate(slot));
slot--;
}
// Now all pushes can be done in pairs.
for (; slot >= 0; slot -= 2) {
Emit(kArm64PokePair, g.NoOutput(),
g.UseRegister(buffer.pushed_nodes[slot]),
g.UseRegister(buffer.pushed_nodes[slot - 1]),
g.TempImmediate(slot));
}
}
// Pass label of exception handler block.
CallDescriptor::Flags flags = descriptor->flags();
if (handler != nullptr) {
DCHECK_EQ(IrOpcode::kIfException, handler->front()->opcode());
IfExceptionHint hint = OpParameter<IfExceptionHint>(handler->front());
if (hint == IfExceptionHint::kLocallyCaught) {
flags |= CallDescriptor::kHasLocalCatchHandler;
Emit(kArm64PokePair, g.NoOutput(), g.UseRegister((*arguments)[slot]),
g.UseRegister((*arguments)[slot - 1]), g.TempImmediate(slot));
}
flags |= CallDescriptor::kHasExceptionHandler;
buffer.instruction_args.push_back(g.Label(handler));
}
// Select the appropriate opcode based on the call type.
InstructionCode opcode = kArchNop;
switch (descriptor->kind()) {
case CallDescriptor::kCallAddress:
opcode =
kArchCallCFunction |
MiscField::encode(static_cast<int>(descriptor->CParameterCount()));
break;
case CallDescriptor::kCallCodeObject:
opcode = kArchCallCodeObject | MiscField::encode(flags);
break;
case CallDescriptor::kCallJSFunction:
opcode = kArchCallJSFunction | MiscField::encode(flags);
break;
case CallDescriptor::kLazyBailout:
opcode = kArchLazyBailout | MiscField::encode(flags);
break;
}
// Emit the call instruction.
size_t const output_count = buffer.outputs.size();
auto* outputs = output_count ? &buffer.outputs.front() : nullptr;
Emit(opcode, output_count, outputs, buffer.instruction_args.size(),
&buffer.instruction_args.front())->MarkAsCall();
}
......
......@@ -843,20 +843,10 @@ void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) {
}
void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
void InstructionSelector::EmitPrepareArguments(NodeVector* arguments,
const CallDescriptor* descriptor,
Node* node) {
IA32OperandGenerator g(this);
const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(node);
FrameStateDescriptor* frame_state_descriptor = nullptr;
if (descriptor->NeedsFrameState()) {
frame_state_descriptor =
GetFrameStateDescriptor(node->InputAt(descriptor->InputCount()));
}
CallBuffer buffer(zone(), descriptor, frame_state_descriptor);
// Compute InstructionOperands for inputs and outputs.
InitializeCallBuffer(node, &buffer, true, true);
// Prepare for C function call.
if (descriptor->IsCFunctionCall()) {
......@@ -867,8 +857,8 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
0, nullptr, 0, nullptr, temp_count, temps);
// Poke any stack arguments.
for (size_t n = 0; n < buffer.pushed_nodes.size(); ++n) {
if (Node* input = buffer.pushed_nodes[n]) {
for (size_t n = 0; n < arguments->size(); ++n) {
if (Node* input = (*arguments)[n]) {
int const slot = static_cast<int>(n);
InstructionOperand value = g.CanBeImmediate(node)
? g.UseImmediate(input)
......@@ -878,7 +868,7 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
}
} else {
// Push any stack arguments.
for (Node* input : base::Reversed(buffer.pushed_nodes)) {
for (Node* input : base::Reversed(*arguments)) {
// Skip any alignment holes in pushed nodes.
if (input == nullptr) continue;
// TODO(titzer): IA32Push cannot handle stack->stack double moves
......@@ -893,43 +883,6 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
Emit(kIA32Push, g.NoOutput(), value);
}
}
// Pass label of exception handler block.
CallDescriptor::Flags flags = descriptor->flags();
if (handler) {
DCHECK_EQ(IrOpcode::kIfException, handler->front()->opcode());
IfExceptionHint hint = OpParameter<IfExceptionHint>(handler->front());
if (hint == IfExceptionHint::kLocallyCaught) {
flags |= CallDescriptor::kHasLocalCatchHandler;
}
flags |= CallDescriptor::kHasExceptionHandler;
buffer.instruction_args.push_back(g.Label(handler));
}
// Select the appropriate opcode based on the call type.
InstructionCode opcode = kArchNop;
switch (descriptor->kind()) {
case CallDescriptor::kCallAddress:
opcode =
kArchCallCFunction |
MiscField::encode(static_cast<int>(descriptor->CParameterCount()));
break;
case CallDescriptor::kCallCodeObject:
opcode = kArchCallCodeObject | MiscField::encode(flags);
break;
case CallDescriptor::kCallJSFunction:
opcode = kArchCallJSFunction | MiscField::encode(flags);
break;
case CallDescriptor::kLazyBailout:
opcode = kArchLazyBailout | MiscField::encode(flags);
break;
}
// Emit the call instruction.
size_t const output_count = buffer.outputs.size();
auto* outputs = output_count ? &buffer.outputs.front() : nullptr;
Emit(opcode, output_count, outputs, buffer.instruction_args.size(),
&buffer.instruction_args.front())->MarkAsCall();
}
......
......@@ -1011,6 +1011,67 @@ void InstructionSelector::VisitConstant(Node* node) {
}
void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
OperandGenerator g(this);
const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(node);
FrameStateDescriptor* frame_state_descriptor = nullptr;
if (descriptor->NeedsFrameState()) {
frame_state_descriptor = GetFrameStateDescriptor(
node->InputAt(static_cast<int>(descriptor->InputCount())));
}
CallBuffer buffer(zone(), descriptor, frame_state_descriptor);
// Compute InstructionOperands for inputs and outputs.
// TODO(turbofan): on some architectures it's probably better to use
// the code object in a register if there are multiple uses of it.
// Improve constant pool and the heuristics in the register allocator
// for where to emit constants.
InitializeCallBuffer(node, &buffer, true, true);
EmitPrepareArguments(&(buffer.pushed_nodes), descriptor, node);
// Pass label of exception handler block.
CallDescriptor::Flags flags = descriptor->flags();
if (handler) {
DCHECK_EQ(IrOpcode::kIfException, handler->front()->opcode());
IfExceptionHint hint = OpParameter<IfExceptionHint>(handler->front());
if (hint == IfExceptionHint::kLocallyCaught) {
flags |= CallDescriptor::kHasLocalCatchHandler;
}
flags |= CallDescriptor::kHasExceptionHandler;
buffer.instruction_args.push_back(g.Label(handler));
}
// Select the appropriate opcode based on the call type.
InstructionCode opcode = kArchNop;
switch (descriptor->kind()) {
case CallDescriptor::kCallAddress:
opcode =
kArchCallCFunction |
MiscField::encode(static_cast<int>(descriptor->CParameterCount()));
break;
case CallDescriptor::kCallCodeObject:
opcode = kArchCallCodeObject | MiscField::encode(flags);
break;
case CallDescriptor::kCallJSFunction:
opcode = kArchCallJSFunction | MiscField::encode(flags);
break;
case CallDescriptor::kLazyBailout:
opcode = kArchLazyBailout | MiscField::encode(flags);
break;
}
// Emit the call instruction.
size_t const output_count = buffer.outputs.size();
auto* outputs = output_count ? &buffer.outputs.front() : nullptr;
Emit(opcode, output_count, outputs, buffer.instruction_args.size(),
&buffer.instruction_args.front())
->MarkAsCall();
}
void InstructionSelector::VisitGoto(BasicBlock* target) {
// jump to the next block.
OperandGenerator g(this);
......
......@@ -216,6 +216,9 @@ class InstructionSelector final {
void VisitReturn(Node* ret);
void VisitThrow(Node* value);
void EmitPrepareArguments(NodeVector* arguments,
const CallDescriptor* descriptor, Node* node);
// ===========================================================================
Schedule* schedule() const { return schedule_; }
......
......@@ -528,20 +528,10 @@ void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) {
}
void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
void InstructionSelector::EmitPrepareArguments(NodeVector* arguments,
const CallDescriptor* descriptor,
Node* node) {
MipsOperandGenerator g(this);
const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(node);
FrameStateDescriptor* frame_state_descriptor = nullptr;
if (descriptor->NeedsFrameState()) {
frame_state_descriptor =
GetFrameStateDescriptor(node->InputAt(descriptor->InputCount()));
}
CallBuffer buffer(zone(), descriptor, frame_state_descriptor);
// Compute InstructionOperands for inputs and outputs.
InitializeCallBuffer(node, &buffer, true, true);
// Prepare for C function call.
if (descriptor->IsCFunctionCall()) {
......@@ -551,7 +541,7 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
// Poke any stack arguments.
int slot = kCArgSlotCount;
for (Node* input : buffer.pushed_nodes) {
for (Node* input : (*arguments)) {
Emit(kMipsStoreToStackSlot, g.NoOutput(), g.UseRegister(input),
g.TempImmediate(slot << kPointerSizeLog2));
++slot;
......@@ -563,50 +553,13 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
Emit(kMipsStackClaim, g.NoOutput(),
g.TempImmediate(push_count << kPointerSizeLog2));
}
for (size_t n = 0; n < buffer.pushed_nodes.size(); ++n) {
if (Node* input = buffer.pushed_nodes[n]) {
for (size_t n = 0; n < arguments->size(); ++n) {
if (Node* input = (*arguments)[n]) {
Emit(kMipsStoreToStackSlot, g.NoOutput(), g.UseRegister(input),
g.TempImmediate(n << kPointerSizeLog2));
}
}
}
// Pass label of exception handler block.
CallDescriptor::Flags flags = descriptor->flags();
if (handler) {
DCHECK_EQ(IrOpcode::kIfException, handler->front()->opcode());
IfExceptionHint hint = OpParameter<IfExceptionHint>(handler->front());
if (hint == IfExceptionHint::kLocallyCaught) {
flags |= CallDescriptor::kHasLocalCatchHandler;
}
flags |= CallDescriptor::kHasExceptionHandler;
buffer.instruction_args.push_back(g.Label(handler));
}
// Select the appropriate opcode based on the call type.
InstructionCode opcode = kArchNop;
switch (descriptor->kind()) {
case CallDescriptor::kCallAddress:
opcode =
kArchCallCFunction |
MiscField::encode(static_cast<int>(descriptor->CParameterCount()));
break;
case CallDescriptor::kCallCodeObject:
opcode = kArchCallCodeObject | MiscField::encode(flags);
break;
case CallDescriptor::kCallJSFunction:
opcode = kArchCallJSFunction | MiscField::encode(flags);
break;
case CallDescriptor::kLazyBailout:
opcode = kArchLazyBailout | MiscField::encode(flags);
break;
}
// Emit the call instruction.
size_t const output_count = buffer.outputs.size();
auto* outputs = output_count ? &buffer.outputs.front() : nullptr;
Emit(opcode, output_count, outputs, buffer.instruction_args.size(),
&buffer.instruction_args.front())->MarkAsCall();
}
......
......@@ -716,20 +716,10 @@ void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) {
}
void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
void InstructionSelector::EmitPrepareArguments(NodeVector* arguments,
const CallDescriptor* descriptor,
Node* node) {
Mips64OperandGenerator g(this);
const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(node);
FrameStateDescriptor* frame_state_descriptor = nullptr;
if (descriptor->NeedsFrameState()) {
frame_state_descriptor = GetFrameStateDescriptor(
node->InputAt(static_cast<int>(descriptor->InputCount())));
}
CallBuffer buffer(zone(), descriptor, frame_state_descriptor);
// Compute InstructionOperands for inputs and outputs.
InitializeCallBuffer(node, &buffer, true, true);
// Prepare for C function call.
if (descriptor->IsCFunctionCall()) {
......@@ -739,7 +729,7 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
// Poke any stack arguments.
int slot = kCArgSlotCount;
for (Node* input : buffer.pushed_nodes) {
for (Node* input : (*arguments)) {
Emit(kMips64StoreToStackSlot, g.NoOutput(), g.UseRegister(input),
g.TempImmediate(slot << kPointerSizeLog2));
++slot;
......@@ -750,51 +740,13 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
Emit(kMips64StackClaim, g.NoOutput(),
g.TempImmediate(push_count << kPointerSizeLog2));
}
for (size_t n = 0; n < buffer.pushed_nodes.size(); ++n) {
if (Node* input = buffer.pushed_nodes[n]) {
for (size_t n = 0; n < arguments->size(); ++n) {
if (Node* input = (*arguments)[n]) {
Emit(kMips64StoreToStackSlot, g.NoOutput(), g.UseRegister(input),
g.TempImmediate(static_cast<int>(n << kPointerSizeLog2)));
}
}
}
// Pass label of exception handler block.
CallDescriptor::Flags flags = descriptor->flags();
if (handler) {
DCHECK_EQ(IrOpcode::kIfException, handler->front()->opcode());
IfExceptionHint hint = OpParameter<IfExceptionHint>(handler->front());
if (hint == IfExceptionHint::kLocallyCaught) {
flags |= CallDescriptor::kHasLocalCatchHandler;
}
flags |= CallDescriptor::kHasExceptionHandler;
buffer.instruction_args.push_back(g.Label(handler));
}
// Select the appropriate opcode based on the call type.
InstructionCode opcode = kArchNop;
switch (descriptor->kind()) {
case CallDescriptor::kCallAddress:
opcode =
kArchCallCFunction |
MiscField::encode(static_cast<int>(descriptor->CParameterCount()));
break;
case CallDescriptor::kCallCodeObject:
opcode = kArchCallCodeObject | MiscField::encode(flags);
break;
case CallDescriptor::kCallJSFunction:
opcode = kArchCallJSFunction | MiscField::encode(flags);
break;
case CallDescriptor::kLazyBailout:
opcode = kArchLazyBailout | MiscField::encode(flags);
break;
}
opcode |= MiscField::encode(flags);
// Emit the call instruction.
size_t const output_count = buffer.outputs.size();
auto* outputs = output_count ? &buffer.outputs.front() : nullptr;
Emit(opcode, output_count, outputs, buffer.instruction_args.size(),
&buffer.instruction_args.front())->MarkAsCall();
}
......
......@@ -1481,23 +1481,10 @@ void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) {
}
void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
void InstructionSelector::EmitPrepareArguments(NodeVector* arguments,
const CallDescriptor* descriptor,
Node* node) {
PPCOperandGenerator g(this);
const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(node);
FrameStateDescriptor* frame_state_descriptor = nullptr;
if (descriptor->NeedsFrameState()) {
frame_state_descriptor =
GetFrameStateDescriptor(node->InputAt(descriptor->InputCount()));
}
CallBuffer buffer(zone(), descriptor, frame_state_descriptor);
// Compute InstructionOperands for inputs and outputs.
// TODO(turbofan): on PPC it's probably better to use the code object in a
// register if there are multiple uses of it. Improve constant pool and the
// heuristics in the register allocator for where to emit constants.
InitializeCallBuffer(node, &buffer, true, true);
// Prepare for C function call.
if (descriptor->IsCFunctionCall()) {
......@@ -1507,7 +1494,7 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
// Poke any stack arguments.
int slot = kStackFrameExtraParamSlot;
for (Node* node : buffer.pushed_nodes) {
for (Node* node : (*arguments)) {
Emit(kPPC_StoreToStackSlot, g.NoOutput(), g.UseRegister(node),
g.TempImmediate(slot));
++slot;
......@@ -1516,7 +1503,7 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
// Push any stack arguments.
int num_slots = static_cast<int>(descriptor->StackParameterCount());
int slot = 0;
for (Node* input : buffer.pushed_nodes) {
for (Node* input : (*arguments)) {
if (slot == 0) {
DCHECK(input);
Emit(kPPC_PushFrame, g.NoOutput(), g.UseRegister(input),
......@@ -1531,43 +1518,6 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
++slot;
}
}
// Pass label of exception handler block.
CallDescriptor::Flags flags = descriptor->flags();
if (handler) {
DCHECK_EQ(IrOpcode::kIfException, handler->front()->opcode());
IfExceptionHint hint = OpParameter<IfExceptionHint>(handler->front());
if (hint == IfExceptionHint::kLocallyCaught) {
flags |= CallDescriptor::kHasLocalCatchHandler;
}
flags |= CallDescriptor::kHasExceptionHandler;
buffer.instruction_args.push_back(g.Label(handler));
}
// Select the appropriate opcode based on the call type.
InstructionCode opcode = kArchNop;
switch (descriptor->kind()) {
case CallDescriptor::kCallAddress:
opcode =
kArchCallCFunction |
MiscField::encode(static_cast<int>(descriptor->CParameterCount()));
break;
case CallDescriptor::kCallCodeObject:
opcode = kArchCallCodeObject | MiscField::encode(flags);
break;
case CallDescriptor::kCallJSFunction:
opcode = kArchCallJSFunction | MiscField::encode(flags);
break;
case CallDescriptor::kLazyBailout:
opcode = kArchLazyBailout | MiscField::encode(flags);
break;
}
// Emit the call instruction.
size_t const output_count = buffer.outputs.size();
auto* outputs = output_count ? &buffer.outputs.front() : nullptr;
Emit(opcode, output_count, outputs, buffer.instruction_args.size(),
&buffer.instruction_args.front())->MarkAsCall();
}
......
......@@ -1072,20 +1072,10 @@ void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) {
}
void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
void InstructionSelector::EmitPrepareArguments(NodeVector* arguments,
const CallDescriptor* descriptor,
Node* node) {
X64OperandGenerator g(this);
const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(node);
FrameStateDescriptor* frame_state_descriptor = nullptr;
if (descriptor->NeedsFrameState()) {
frame_state_descriptor = GetFrameStateDescriptor(
node->InputAt(static_cast<int>(descriptor->InputCount())));
}
CallBuffer buffer(zone(), descriptor, frame_state_descriptor);
// Compute InstructionOperands for inputs and outputs.
InitializeCallBuffer(node, &buffer, true, true);
// Prepare for C function call.
if (descriptor->IsCFunctionCall()) {
......@@ -1094,8 +1084,8 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
0, nullptr, 0, nullptr);
// Poke any stack arguments.
for (size_t n = 0; n < buffer.pushed_nodes.size(); ++n) {
if (Node* input = buffer.pushed_nodes[n]) {
for (size_t n = 0; n < arguments->size(); ++n) {
if (Node* input = (*arguments)[n]) {
int slot = static_cast<int>(n);
InstructionOperand value = g.CanBeImmediate(input)
? g.UseImmediate(input)
......@@ -1105,7 +1095,7 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
}
} else {
// Push any stack arguments.
for (Node* input : base::Reversed(buffer.pushed_nodes)) {
for (Node* input : base::Reversed(*arguments)) {
// TODO(titzer): X64Push cannot handle stack->stack double moves
// because there is no way to encode fixed double slots.
InstructionOperand value =
......@@ -1118,43 +1108,6 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
Emit(kX64Push, g.NoOutput(), value);
}
}
// Pass label of exception handler block.
CallDescriptor::Flags flags = descriptor->flags();
if (handler) {
DCHECK_EQ(IrOpcode::kIfException, handler->front()->opcode());
IfExceptionHint hint = OpParameter<IfExceptionHint>(handler->front());
if (hint == IfExceptionHint::kLocallyCaught) {
flags |= CallDescriptor::kHasLocalCatchHandler;
}
flags |= CallDescriptor::kHasExceptionHandler;
buffer.instruction_args.push_back(g.Label(handler));
}
// Select the appropriate opcode based on the call type.
InstructionCode opcode = kArchNop;
switch (descriptor->kind()) {
case CallDescriptor::kCallAddress:
opcode =
kArchCallCFunction |
MiscField::encode(static_cast<int>(descriptor->CParameterCount()));
break;
case CallDescriptor::kCallCodeObject:
opcode = kArchCallCodeObject | MiscField::encode(flags);
break;
case CallDescriptor::kCallJSFunction:
opcode = kArchCallJSFunction | MiscField::encode(flags);
break;
case CallDescriptor::kLazyBailout:
opcode = kArchLazyBailout | MiscField::encode(flags);
break;
}
// Emit the call instruction.
size_t const output_count = buffer.outputs.size();
auto* outputs = output_count ? &buffer.outputs.front() : nullptr;
Emit(opcode, output_count, outputs, buffer.instruction_args.size(),
&buffer.instruction_args.front())->MarkAsCall();
}
......
......@@ -838,20 +838,10 @@ void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) {
}
void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
void InstructionSelector::EmitPrepareArguments(NodeVector* arguments,
const CallDescriptor* descriptor,
Node* node) {
X87OperandGenerator g(this);
const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(node);
FrameStateDescriptor* frame_state_descriptor = nullptr;
if (descriptor->NeedsFrameState()) {
frame_state_descriptor =
GetFrameStateDescriptor(node->InputAt(descriptor->InputCount()));
}
CallBuffer buffer(zone(), descriptor, frame_state_descriptor);
// Compute InstructionOperands for inputs and outputs.
InitializeCallBuffer(node, &buffer, true, true);
// Prepare for C function call.
if (descriptor->IsCFunctionCall()) {
......@@ -862,8 +852,8 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
0, nullptr, 0, nullptr, temp_count, temps);
// Poke any stack arguments.
for (size_t n = 0; n < buffer.pushed_nodes.size(); ++n) {
if (Node* input = buffer.pushed_nodes[n]) {
for (size_t n = 0; n < arguments->size(); ++n) {
if (Node* input = (*arguments)[n]) {
int const slot = static_cast<int>(n);
InstructionOperand value = g.CanBeImmediate(input)
? g.UseImmediate(input)
......@@ -873,7 +863,7 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
}
} else {
// Push any stack arguments.
for (Node* input : base::Reversed(buffer.pushed_nodes)) {
for (Node* input : base::Reversed(*arguments)) {
// TODO(titzer): handle pushing double parameters.
if (input == nullptr) continue;
InstructionOperand value =
......@@ -886,43 +876,6 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
Emit(kX87Push, g.NoOutput(), value);
}
}
// Pass label of exception handler block.
CallDescriptor::Flags flags = descriptor->flags();
if (handler) {
DCHECK_EQ(IrOpcode::kIfException, handler->front()->opcode());
IfExceptionHint hint = OpParameter<IfExceptionHint>(handler->front());
if (hint == IfExceptionHint::kLocallyCaught) {
flags |= CallDescriptor::kHasLocalCatchHandler;
}
flags |= CallDescriptor::kHasExceptionHandler;
buffer.instruction_args.push_back(g.Label(handler));
}
// Select the appropriate opcode based on the call type.
InstructionCode opcode = kArchNop;
switch (descriptor->kind()) {
case CallDescriptor::kCallAddress:
opcode =
kArchCallCFunction |
MiscField::encode(static_cast<int>(descriptor->CParameterCount()));
break;
case CallDescriptor::kCallCodeObject:
opcode = kArchCallCodeObject | MiscField::encode(flags);
break;
case CallDescriptor::kCallJSFunction:
opcode = kArchCallJSFunction | MiscField::encode(flags);
break;
case CallDescriptor::kLazyBailout:
opcode = kArchLazyBailout | MiscField::encode(flags);
break;
}
// Emit the call instruction.
size_t const output_count = buffer.outputs.size();
auto* outputs = output_count ? &buffer.outputs.front() : nullptr;
Emit(opcode, output_count, outputs, buffer.instruction_args.size(),
&buffer.instruction_args.front())->MarkAsCall();
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment