[turbofan] Pass type information of arguments to EmitPrepareArguments.

On ia32 the code which pushes parameters on the stack depends on the
types of the parameters which are to be pushed. I provide this type
information now by not only passing parameter nodes to
EmitPrepareArguments, but also the index in the call descriptor which
belongs to the parameter nodes.

This type information will also be necessary if we want to use the
PokePair instruction on arm64 again.

R=bradnelson@chromium.org, bmeurer@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#32982}
This commit is contained in:
ahaas 2015-12-21 02:32:34 -08:00 committed by Commit bot
parent bf8c5160dc
commit c0c8c756de
13 changed files with 146 additions and 84 deletions

View File

@ -1158,9 +1158,9 @@ void InstructionSelector::VisitFloat64RoundTiesEven(Node* node) {
}
void InstructionSelector::EmitPrepareArguments(NodeVector* arguments,
const CallDescriptor* descriptor,
Node* node) {
void InstructionSelector::EmitPrepareArguments(
ZoneVector<PushParameter>* arguments, const CallDescriptor* descriptor,
Node* node) {
ArmOperandGenerator g(this);
// Prepare for C function call.
@ -1171,18 +1171,19 @@ void InstructionSelector::EmitPrepareArguments(NodeVector* arguments,
// Poke any stack arguments.
for (size_t n = 0; n < arguments->size(); ++n) {
if (Node* input = (*arguments)[n]) {
PushParameter input = (*arguments)[n];
if (input.node()) {
int slot = static_cast<int>(n);
Emit(kArmPoke | MiscField::encode(slot), g.NoOutput(),
g.UseRegister(input));
g.UseRegister(input.node()));
}
}
} else {
// Push any stack arguments.
for (Node* input : base::Reversed(*arguments)) {
for (PushParameter input : base::Reversed(*arguments)) {
// Skip any alignment holes in pushed nodes.
if (input == nullptr) continue;
Emit(kArmPush, g.NoOutput(), g.UseRegister(input));
if (input.node() == nullptr) continue;
Emit(kArmPush, g.NoOutput(), g.UseRegister(input.node()));
}
}
}

View File

@ -1574,9 +1574,9 @@ void InstructionSelector::VisitFloat64RoundTiesEven(Node* node) {
}
void InstructionSelector::EmitPrepareArguments(NodeVector* arguments,
const CallDescriptor* descriptor,
Node* node) {
void InstructionSelector::EmitPrepareArguments(
ZoneVector<PushParameter>* arguments, const CallDescriptor* descriptor,
Node* node) {
Arm64OperandGenerator g(this);
// Push the arguments to the stack.
@ -1602,7 +1602,7 @@ void InstructionSelector::EmitPrepareArguments(NodeVector* arguments,
// Move arguments to the stack.
int slot = aligned_push_count - 1;
while (slot >= 0) {
Emit(kArm64Poke, g.NoOutput(), g.UseRegister((*arguments)[slot]),
Emit(kArm64Poke, g.NoOutput(), g.UseRegister((*arguments)[slot].node()),
g.TempImmediate(slot));
slot--;
// TODO(ahaas): Poke arguments in pairs if two subsequent arguments have the

View File

@ -1000,6 +1000,40 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
}
break;
}
case kIA32PushFloat32:
if (instr->InputAt(0)->IsDoubleRegister()) {
__ sub(esp, Immediate(kDoubleSize));
__ movss(Operand(esp, 0), i.InputDoubleRegister(0));
frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
} else if (HasImmediateInput(instr, 0)) {
__ Move(kScratchDoubleReg, i.InputDouble(0));
__ sub(esp, Immediate(kDoubleSize));
__ movss(Operand(esp, 0), kScratchDoubleReg);
frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
} else {
__ movsd(kScratchDoubleReg, i.InputOperand(0));
__ sub(esp, Immediate(kDoubleSize));
__ movss(Operand(esp, 0), kScratchDoubleReg);
frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
}
break;
case kIA32PushFloat64:
if (instr->InputAt(0)->IsDoubleRegister()) {
__ sub(esp, Immediate(kDoubleSize));
__ movsd(Operand(esp, 0), i.InputDoubleRegister(0));
frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
} else if (HasImmediateInput(instr, 0)) {
__ Move(kScratchDoubleReg, i.InputDouble(0));
__ sub(esp, Immediate(kDoubleSize));
__ movsd(Operand(esp, 0), kScratchDoubleReg);
frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
} else {
__ movsd(kScratchDoubleReg, i.InputOperand(0));
__ sub(esp, Immediate(kDoubleSize));
__ movsd(Operand(esp, 0), kScratchDoubleReg);
frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
}
break;
case kIA32Push:
if (instr->InputAt(0)->IsDoubleRegister()) {
__ sub(esp, Immediate(kDoubleSize));

View File

@ -96,6 +96,8 @@ namespace compiler {
V(IA32BitcastIF) \
V(IA32Lea) \
V(IA32Push) \
V(IA32PushFloat32) \
V(IA32PushFloat64) \
V(IA32Poke) \
V(IA32StackCheck)

View File

@ -108,6 +108,8 @@ int InstructionScheduler::GetTargetInstructionFlags(
return kIsLoadOperation;
case kIA32Push:
case kIA32PushFloat32:
case kIA32PushFloat64:
case kIA32Poke:
return kHasSideEffect;

View File

@ -896,9 +896,9 @@ void InstructionSelector::VisitFloat64RoundTiesEven(Node* node) {
}
void InstructionSelector::EmitPrepareArguments(NodeVector* arguments,
const CallDescriptor* descriptor,
Node* node) {
void InstructionSelector::EmitPrepareArguments(
ZoneVector<PushParameter>* arguments, const CallDescriptor* descriptor,
Node* node) {
IA32OperandGenerator g(this);
// Prepare for C function call.
@ -911,29 +911,34 @@ void InstructionSelector::EmitPrepareArguments(NodeVector* arguments,
// Poke any stack arguments.
for (size_t n = 0; n < arguments->size(); ++n) {
if (Node* input = (*arguments)[n]) {
PushParameter input = (*arguments)[n];
if (input.node()) {
int const slot = static_cast<int>(n);
InstructionOperand value = g.CanBeImmediate(node)
? g.UseImmediate(input)
: g.UseRegister(input);
? g.UseImmediate(input.node())
: g.UseRegister(input.node());
Emit(kIA32Poke | MiscField::encode(slot), g.NoOutput(), value);
}
}
} else {
// Push any stack arguments.
for (Node* input : base::Reversed(*arguments)) {
for (PushParameter input : base::Reversed(*arguments)) {
// Skip any alignment holes in pushed nodes.
if (input == nullptr) continue;
// TODO(titzer): IA32Push cannot handle stack->stack double moves
// because there is no way to encode fixed double slots.
if (input.node() == nullptr) continue;
InstructionOperand value =
g.CanBeImmediate(input)
? g.UseImmediate(input)
g.CanBeImmediate(input.node())
? g.UseImmediate(input.node())
: IsSupported(ATOM) ||
sequence()->IsFloat(GetVirtualRegister(input))
? g.UseRegister(input)
: g.Use(input);
Emit(kIA32Push, g.NoOutput(), value);
sequence()->IsFloat(GetVirtualRegister(input.node()))
? g.UseRegister(input.node())
: g.Use(input.node());
if (input.type() == MachineType::Float32()) {
Emit(kIA32PushFloat32, g.NoOutput(), value);
} else if (input.type() == MachineType::Float64()) {
Emit(kIA32PushFloat64, g.NoOutput(), value);
} else {
Emit(kIA32Push, g.NoOutput(), value);
}
}
}
}

View File

@ -397,7 +397,7 @@ struct CallBuffer {
NodeVector output_nodes;
InstructionOperandVector outputs;
InstructionOperandVector instruction_args;
NodeVector pushed_nodes;
ZoneVector<PushParameter> pushed_nodes;
size_t input_count() const { return descriptor->InputCount(); }
@ -539,10 +539,10 @@ void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer,
if (UnallocatedOperand::cast(op).HasFixedSlotPolicy() && !call_tail) {
int stack_index = -UnallocatedOperand::cast(op).fixed_slot_index() - 1;
if (static_cast<size_t>(stack_index) >= buffer->pushed_nodes.size()) {
buffer->pushed_nodes.resize(stack_index + 1, NULL);
buffer->pushed_nodes.resize(stack_index + 1);
}
DCHECK(!buffer->pushed_nodes[stack_index]);
buffer->pushed_nodes[stack_index] = *iter;
PushParameter parameter(*iter, buffer->descriptor->GetInputType(index));
buffer->pushed_nodes[stack_index] = parameter;
pushed_count++;
} else {
buffer->instruction_args.push_back(op);

View File

@ -28,6 +28,20 @@ struct SwitchInfo;
typedef ZoneVector<InstructionOperand> InstructionOperandVector;
// This struct connects nodes of parameters which are going to be pushed on the
// call stack with their parameter index in the call descriptor of the callee.
class PushParameter {
public:
PushParameter() : node_(nullptr), type_(MachineType::None()) {}
PushParameter(Node* node, MachineType type) : node_(node), type_(type) {}
Node* node() const { return node_; }
MachineType type() const { return type_; }
private:
Node* node_;
MachineType type_;
};
// Instruction selection generates an InstructionSequence for a given Schedule.
class InstructionSelector final {
@ -233,7 +247,7 @@ class InstructionSelector final {
void VisitReturn(Node* ret);
void VisitThrow(Node* value);
void EmitPrepareArguments(NodeVector* arguments,
void EmitPrepareArguments(ZoneVector<compiler::PushParameter>* arguments,
const CallDescriptor* descriptor, Node* node);
// ===========================================================================

View File

@ -805,9 +805,9 @@ void InstructionSelector::VisitFloat64RoundTiesEven(Node* node) {
}
void InstructionSelector::EmitPrepareArguments(NodeVector* arguments,
const CallDescriptor* descriptor,
Node* node) {
void InstructionSelector::EmitPrepareArguments(
ZoneVector<PushParameter>* arguments, const CallDescriptor* descriptor,
Node* node) {
MipsOperandGenerator g(this);
// Prepare for C function call.
@ -818,8 +818,8 @@ void InstructionSelector::EmitPrepareArguments(NodeVector* arguments,
// Poke any stack arguments.
int slot = kCArgSlotCount;
for (Node* input : (*arguments)) {
Emit(kMipsStoreToStackSlot, g.NoOutput(), g.UseRegister(input),
for (PushParameter input : (*arguments)) {
Emit(kMipsStoreToStackSlot, g.NoOutput(), g.UseRegister(input.node()),
g.TempImmediate(slot << kPointerSizeLog2));
++slot;
}
@ -831,8 +831,9 @@ void InstructionSelector::EmitPrepareArguments(NodeVector* arguments,
g.TempImmediate(push_count << kPointerSizeLog2));
}
for (size_t n = 0; n < arguments->size(); ++n) {
if (Node* input = (*arguments)[n]) {
Emit(kMipsStoreToStackSlot, g.NoOutput(), g.UseRegister(input),
PushParameter input = (*arguments)[n];
if (input.node()) {
Emit(kMipsStoreToStackSlot, g.NoOutput(), g.UseRegister(input.node()),
g.TempImmediate(n << kPointerSizeLog2));
}
}

View File

@ -1241,9 +1241,9 @@ void InstructionSelector::VisitFloat64RoundTiesEven(Node* node) {
}
void InstructionSelector::EmitPrepareArguments(NodeVector* arguments,
const CallDescriptor* descriptor,
Node* node) {
void InstructionSelector::EmitPrepareArguments(
ZoneVector<PushParameter>* arguments, const CallDescriptor* descriptor,
Node* node) {
Mips64OperandGenerator g(this);
// Prepare for C function call.
@ -1254,8 +1254,8 @@ void InstructionSelector::EmitPrepareArguments(NodeVector* arguments,
// Poke any stack arguments.
int slot = kCArgSlotCount;
for (Node* input : (*arguments)) {
Emit(kMips64StoreToStackSlot, g.NoOutput(), g.UseRegister(input),
for (PushParameter input : (*arguments)) {
Emit(kMips64StoreToStackSlot, g.NoOutput(), g.UseRegister(input.node()),
g.TempImmediate(slot << kPointerSizeLog2));
++slot;
}
@ -1266,8 +1266,9 @@ void InstructionSelector::EmitPrepareArguments(NodeVector* arguments,
g.TempImmediate(push_count << kPointerSizeLog2));
}
for (size_t n = 0; n < arguments->size(); ++n) {
if (Node* input = (*arguments)[n]) {
Emit(kMips64StoreToStackSlot, g.NoOutput(), g.UseRegister(input),
PushParameter input = (*arguments)[n];
if (input.node()) {
Emit(kMips64StoreToStackSlot, g.NoOutput(), g.UseRegister(input.node()),
g.TempImmediate(static_cast<int>(n << kPointerSizeLog2)));
}
}

View File

@ -1611,9 +1611,9 @@ void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) {
}
void InstructionSelector::EmitPrepareArguments(NodeVector* arguments,
const CallDescriptor* descriptor,
Node* node) {
void InstructionSelector::EmitPrepareArguments(
ZoneVector<PushParameter>* arguments, const CallDescriptor* descriptor,
Node* node) {
PPCOperandGenerator g(this);
// Prepare for C function call.
@ -1624,8 +1624,8 @@ void InstructionSelector::EmitPrepareArguments(NodeVector* arguments,
// Poke any stack arguments.
int slot = kStackFrameExtraParamSlot;
for (Node* node : (*arguments)) {
Emit(kPPC_StoreToStackSlot, g.NoOutput(), g.UseRegister(node),
for (PushParameter input : (*arguments)) {
Emit(kPPC_StoreToStackSlot, g.NoOutput(), g.UseRegister(input.node()),
g.TempImmediate(slot));
++slot;
}
@ -1633,15 +1633,15 @@ void InstructionSelector::EmitPrepareArguments(NodeVector* arguments,
// Push any stack arguments.
int num_slots = static_cast<int>(descriptor->StackParameterCount());
int slot = 0;
for (Node* input : (*arguments)) {
for (PushParameter input : (*arguments)) {
if (slot == 0) {
DCHECK(input);
Emit(kPPC_PushFrame, g.NoOutput(), g.UseRegister(input),
DCHECK(input.node());
Emit(kPPC_PushFrame, g.NoOutput(), g.UseRegister(input.node()),
g.TempImmediate(num_slots));
} else {
// Skip any alignment holes in pushed nodes.
if (input) {
Emit(kPPC_StoreToStackSlot, g.NoOutput(), g.UseRegister(input),
if (input.node()) {
Emit(kPPC_StoreToStackSlot, g.NoOutput(), g.UseRegister(input.node()),
g.TempImmediate(slot));
}
}

View File

@ -1233,9 +1233,9 @@ void InstructionSelector::VisitFloat64RoundTiesEven(Node* node) {
}
void InstructionSelector::EmitPrepareArguments(NodeVector* arguments,
const CallDescriptor* descriptor,
Node* node) {
void InstructionSelector::EmitPrepareArguments(
ZoneVector<PushParameter>* arguments, const CallDescriptor* descriptor,
Node* node) {
X64OperandGenerator g(this);
// Prepare for C function call.
@ -1246,26 +1246,27 @@ void InstructionSelector::EmitPrepareArguments(NodeVector* arguments,
// Poke any stack arguments.
for (size_t n = 0; n < arguments->size(); ++n) {
if (Node* input = (*arguments)[n]) {
PushParameter input = (*arguments)[n];
if (input.node()) {
int slot = static_cast<int>(n);
InstructionOperand value = g.CanBeImmediate(input)
? g.UseImmediate(input)
: g.UseRegister(input);
InstructionOperand value = g.CanBeImmediate(input.node())
? g.UseImmediate(input.node())
: g.UseRegister(input.node());
Emit(kX64Poke | MiscField::encode(slot), g.NoOutput(), value);
}
}
} else {
// Push any stack arguments.
for (Node* input : base::Reversed(*arguments)) {
for (PushParameter 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 =
g.CanBeImmediate(input)
? g.UseImmediate(input)
g.CanBeImmediate(input.node())
? g.UseImmediate(input.node())
: IsSupported(ATOM) ||
sequence()->IsFloat(GetVirtualRegister(input))
? g.UseRegister(input)
: g.Use(input);
sequence()->IsFloat(GetVirtualRegister(input.node()))
? g.UseRegister(input.node())
: g.Use(input.node());
Emit(kX64Push, g.NoOutput(), value);
}
}

View File

@ -903,9 +903,9 @@ void InstructionSelector::VisitFloat64RoundTiesEven(Node* node) {
}
void InstructionSelector::EmitPrepareArguments(NodeVector* arguments,
const CallDescriptor* descriptor,
Node* node) {
void InstructionSelector::EmitPrepareArguments(
ZoneVector<PushParameter>* arguments, const CallDescriptor* descriptor,
Node* node) {
X87OperandGenerator g(this);
// Prepare for C function call.
@ -918,26 +918,27 @@ void InstructionSelector::EmitPrepareArguments(NodeVector* arguments,
// Poke any stack arguments.
for (size_t n = 0; n < arguments->size(); ++n) {
if (Node* input = (*arguments)[n]) {
PushParameter input = (*arguments)[n];
if (input.node()) {
int const slot = static_cast<int>(n);
InstructionOperand value = g.CanBeImmediate(input)
? g.UseImmediate(input)
: g.UseRegister(input);
InstructionOperand value = g.CanBeImmediate(input.node())
? g.UseImmediate(input.node())
: g.UseRegister(input.node());
Emit(kX87Poke | MiscField::encode(slot), g.NoOutput(), value);
}
}
} else {
// Push any stack arguments.
for (Node* input : base::Reversed(*arguments)) {
for (PushParameter input : base::Reversed(*arguments)) {
// TODO(titzer): handle pushing double parameters.
if (input == nullptr) continue;
if (input.node() == nullptr) continue;
InstructionOperand value =
g.CanBeImmediate(input)
? g.UseImmediate(input)
g.CanBeImmediate(input.node())
? g.UseImmediate(input.node())
: IsSupported(ATOM) ||
sequence()->IsFloat(GetVirtualRegister(input))
? g.UseRegister(input)
: g.Use(input);
sequence()->IsFloat(GetVirtualRegister(input.node()))
? g.UseRegister(input.node())
: g.Use(input.node());
Emit(kX87Push, g.NoOutput(), value);
}
}