Commit e1a948a6 authored by titzer@chromium.org's avatar titzer@chromium.org

Convert Linkage to use MachineSignature.

This simplifies the handling of MachineTypes for parameters and returns
used in tests, and overall improves the regularity with which they
are handled in both tests and in CallDescriptor.

R=bmeurer@chromium.org, jarin@chromium.org
BUG=

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23638 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent dcf4bd63
......@@ -156,9 +156,13 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
break;
}
case kArchCallJSFunction: {
// TODO(jarin) The load of the context should be separated from the call.
Register func = i.InputRegister(0);
__ ldr(cp, FieldMemOperand(func, JSFunction::kContextOffset));
if (FLAG_debug_code) {
// Check the function's context matches the context argument.
__ ldr(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset));
__ cmp(cp, kScratchReg);
__ Assert(eq, kWrongFunctionContext);
}
__ ldr(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset));
__ Call(ip);
AddSafepointAndDeopt(instr);
......@@ -681,8 +685,9 @@ void CodeGenerator::AssembleReturn() {
__ Ret();
} else {
__ LeaveFrame(StackFrame::MANUAL);
int pop_count =
descriptor->IsJSFunctionCall() ? descriptor->ParameterCount() : 0;
int pop_count = descriptor->IsJSFunctionCall()
? static_cast<int>(descriptor->JSParameterCount())
: 0;
__ Drop(pop_count);
__ Ret();
}
......
......@@ -14,7 +14,7 @@ namespace v8 {
namespace internal {
namespace compiler {
struct LinkageHelperTraits {
struct ArmLinkageHelperTraits {
static Register ReturnValueReg() { return r0; }
static Register ReturnValue2Reg() { return r1; }
static Register JSCallFunctionReg() { return r1; }
......@@ -33,33 +33,32 @@ struct LinkageHelperTraits {
};
typedef LinkageHelper<ArmLinkageHelperTraits> LH;
CallDescriptor* Linkage::GetJSCallDescriptor(int parameter_count, Zone* zone) {
return LinkageHelper::GetJSCallDescriptor<LinkageHelperTraits>(
zone, parameter_count);
return LH::GetJSCallDescriptor(zone, parameter_count);
}
CallDescriptor* Linkage::GetRuntimeCallDescriptor(
Runtime::FunctionId function, int parameter_count,
Operator::Properties properties, Zone* zone) {
return LinkageHelper::GetRuntimeCallDescriptor<LinkageHelperTraits>(
zone, function, parameter_count, properties);
return LH::GetRuntimeCallDescriptor(zone, function, parameter_count,
properties);
}
CallDescriptor* Linkage::GetStubCallDescriptor(
CodeStubInterfaceDescriptor* descriptor, int stack_parameter_count,
CallDescriptor::Flags flags, Zone* zone) {
return LinkageHelper::GetStubCallDescriptor<LinkageHelperTraits>(
zone, descriptor, stack_parameter_count, flags);
return LH::GetStubCallDescriptor(zone, descriptor, stack_parameter_count,
flags);
}
CallDescriptor* Linkage::GetSimplifiedCDescriptor(
Zone* zone, int num_params, MachineType return_type,
const MachineType* param_types) {
return LinkageHelper::GetSimplifiedCDescriptor<LinkageHelperTraits>(
zone, num_params, return_type, param_types);
CallDescriptor* Linkage::GetSimplifiedCDescriptor(Zone* zone,
MachineSignature* sig) {
return LH::GetSimplifiedCDescriptor(zone, sig);
}
} // namespace compiler
......
......@@ -149,9 +149,15 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
break;
}
case kArchCallJSFunction: {
// TODO(jarin) The load of the context should be separated from the call.
Register func = i.InputRegister(0);
__ Ldr(cp, FieldMemOperand(func, JSFunction::kContextOffset));
if (FLAG_debug_code) {
// Check the function's context matches the context argument.
UseScratchRegisterScope scope(masm());
Register temp = scope.AcquireX();
__ Ldr(temp, FieldMemOperand(func, JSFunction::kContextOffset));
__ cmp(cp, temp);
__ Assert(eq, kWrongFunctionContext);
}
__ Ldr(x10, FieldMemOperand(func, JSFunction::kCodeEntryOffset));
__ Call(x10);
AddSafepointAndDeopt(instr);
......@@ -701,8 +707,9 @@ void CodeGenerator::AssembleReturn() {
} else {
__ Mov(jssp, fp);
__ Pop(fp, lr);
int pop_count =
descriptor->IsJSFunctionCall() ? descriptor->ParameterCount() : 0;
int pop_count = descriptor->IsJSFunctionCall()
? static_cast<int>(descriptor->JSParameterCount())
: 0;
__ Drop(pop_count);
__ Ret();
}
......
......@@ -14,7 +14,7 @@ namespace v8 {
namespace internal {
namespace compiler {
struct LinkageHelperTraits {
struct Arm64LinkageHelperTraits {
static Register ReturnValueReg() { return x0; }
static Register ReturnValue2Reg() { return x1; }
static Register JSCallFunctionReg() { return x1; }
......@@ -33,33 +33,32 @@ struct LinkageHelperTraits {
};
typedef LinkageHelper<Arm64LinkageHelperTraits> LH;
CallDescriptor* Linkage::GetJSCallDescriptor(int parameter_count, Zone* zone) {
return LinkageHelper::GetJSCallDescriptor<LinkageHelperTraits>(
zone, parameter_count);
return LH::GetJSCallDescriptor(zone, parameter_count);
}
CallDescriptor* Linkage::GetRuntimeCallDescriptor(
Runtime::FunctionId function, int parameter_count,
Operator::Properties properties, Zone* zone) {
return LinkageHelper::GetRuntimeCallDescriptor<LinkageHelperTraits>(
zone, function, parameter_count, properties);
return LH::GetRuntimeCallDescriptor(zone, function, parameter_count,
properties);
}
CallDescriptor* Linkage::GetStubCallDescriptor(
CodeStubInterfaceDescriptor* descriptor, int stack_parameter_count,
CallDescriptor::Flags flags, Zone* zone) {
return LinkageHelper::GetStubCallDescriptor<LinkageHelperTraits>(
zone, descriptor, stack_parameter_count, flags);
return LH::GetStubCallDescriptor(zone, descriptor, stack_parameter_count,
flags);
}
CallDescriptor* Linkage::GetSimplifiedCDescriptor(
Zone* zone, int num_params, MachineType return_type,
const MachineType* param_types) {
return LinkageHelper::GetSimplifiedCDescriptor<LinkageHelperTraits>(
zone, num_params, return_type, param_types);
CallDescriptor* Linkage::GetSimplifiedCDescriptor(Zone* zone,
MachineSignature* sig) {
return LH::GetSimplifiedCDescriptor(zone, sig);
}
} // namespace compiler
......
......@@ -35,11 +35,14 @@ class ControlOperator FINAL : public Operator1<int> {
class CallOperator FINAL : public Operator1<CallDescriptor*> {
public:
// TODO(titzer): Operator still uses int, whereas CallDescriptor uses size_t.
CallOperator(CallDescriptor* descriptor, const char* mnemonic)
: Operator1<CallDescriptor*>(
IrOpcode::kCall, descriptor->properties(),
descriptor->InputCount() + descriptor->FrameStateCount(),
descriptor->ReturnCount(), mnemonic, descriptor) {}
static_cast<int>(descriptor->InputCount() +
descriptor->FrameStateCount()),
static_cast<int>(descriptor->ReturnCount()), mnemonic, descriptor) {
}
virtual OStream& PrintParameter(OStream& os) const OVERRIDE { // NOLINT
return os << "[" << *parameter() << "]";
......
......@@ -22,7 +22,7 @@ Graph::Graph(Zone* zone) : GenericGraph<Node>(zone), decorators_(zone) {}
Node* Graph::NewNode(Operator* op, int input_count, Node** inputs) {
DCHECK(op->InputCount() <= input_count);
DCHECK_LE(op->InputCount(), input_count);
Node* result = Node::New(this, input_count, inputs);
result->Initialize(op);
for (ZoneVector<GraphDecorator*>::iterator i = decorators_.begin();
......
......@@ -132,9 +132,12 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
break;
}
case kArchCallJSFunction: {
// TODO(jarin) The load of the context should be separated from the call.
Register func = i.InputRegister(0);
__ mov(esi, FieldOperand(func, JSFunction::kContextOffset));
if (FLAG_debug_code) {
// Check the function's context matches the context argument.
__ cmp(esi, FieldOperand(func, JSFunction::kContextOffset));
__ Assert(equal, kWrongFunctionContext);
}
__ call(FieldOperand(func, JSFunction::kCodeEntryOffset));
AddSafepointAndDeopt(instr);
break;
......@@ -789,8 +792,9 @@ void CodeGenerator::AssembleReturn() {
} else {
__ mov(esp, ebp); // Move stack pointer back to frame pointer.
__ pop(ebp); // Pop caller's frame pointer.
int pop_count =
descriptor->IsJSFunctionCall() ? descriptor->ParameterCount() : 0;
int pop_count = descriptor->IsJSFunctionCall()
? static_cast<int>(descriptor->JSParameterCount())
: 0;
__ ret(pop_count * kPointerSize);
}
}
......
......@@ -14,7 +14,7 @@ namespace v8 {
namespace internal {
namespace compiler {
struct LinkageHelperTraits {
struct IA32LinkageHelperTraits {
static Register ReturnValueReg() { return eax; }
static Register ReturnValue2Reg() { return edx; }
static Register JSCallFunctionReg() { return edi; }
......@@ -28,34 +28,32 @@ struct LinkageHelperTraits {
static int CRegisterParametersLength() { return 0; }
};
typedef LinkageHelper<IA32LinkageHelperTraits> LH;
CallDescriptor* Linkage::GetJSCallDescriptor(int parameter_count, Zone* zone) {
return LinkageHelper::GetJSCallDescriptor<LinkageHelperTraits>(
zone, parameter_count);
return LH::GetJSCallDescriptor(zone, parameter_count);
}
CallDescriptor* Linkage::GetRuntimeCallDescriptor(
Runtime::FunctionId function, int parameter_count,
Operator::Properties properties, Zone* zone) {
return LinkageHelper::GetRuntimeCallDescriptor<LinkageHelperTraits>(
zone, function, parameter_count, properties);
return LH::GetRuntimeCallDescriptor(zone, function, parameter_count,
properties);
}
CallDescriptor* Linkage::GetStubCallDescriptor(
CodeStubInterfaceDescriptor* descriptor, int stack_parameter_count,
CallDescriptor::Flags flags, Zone* zone) {
return LinkageHelper::GetStubCallDescriptor<LinkageHelperTraits>(
zone, descriptor, stack_parameter_count, flags);
return LH::GetStubCallDescriptor(zone, descriptor, stack_parameter_count,
flags);
}
CallDescriptor* Linkage::GetSimplifiedCDescriptor(
Zone* zone, int num_params, MachineType return_type,
const MachineType* param_types) {
return LinkageHelper::GetSimplifiedCDescriptor<LinkageHelperTraits>(
zone, num_params, return_type, param_types);
CallDescriptor* Linkage::GetSimplifiedCDescriptor(Zone* zone,
MachineSignature* sig) {
return LH::GetSimplifiedCDescriptor(zone, sig);
}
} // namespace compiler
......
......@@ -48,8 +48,9 @@ class OperandGenerator {
return ConstantOperand::Create(node->id(), zone());
}
InstructionOperand* DefineAsLocation(Node* node, LinkageLocation location) {
return Define(node, ToUnallocatedOperand(location));
InstructionOperand* DefineAsLocation(Node* node, LinkageLocation location,
MachineType type) {
return Define(node, ToUnallocatedOperand(location, type));
}
InstructionOperand* Use(Node* node) {
......@@ -94,8 +95,9 @@ class OperandGenerator {
return ImmediateOperand::Create(index, zone());
}
InstructionOperand* UseLocation(Node* node, LinkageLocation location) {
return Use(node, ToUnallocatedOperand(location));
InstructionOperand* UseLocation(Node* node, LinkageLocation location,
MachineType type) {
return Use(node, ToUnallocatedOperand(location, type));
}
InstructionOperand* TempRegister() {
......@@ -174,7 +176,8 @@ class OperandGenerator {
return operand;
}
UnallocatedOperand* ToUnallocatedOperand(LinkageLocation location) {
UnallocatedOperand* ToUnallocatedOperand(LinkageLocation location,
MachineType type) {
if (location.location_ == LinkageLocation::ANY_REGISTER) {
return new (zone())
UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER);
......@@ -183,7 +186,7 @@ class OperandGenerator {
return new (zone()) UnallocatedOperand(UnallocatedOperand::FIXED_SLOT,
location.location_);
}
if (RepresentationOf(location.rep_) == kRepFloat64) {
if (RepresentationOf(type) == kRepFloat64) {
return new (zone()) UnallocatedOperand(
UnallocatedOperand::FIXED_DOUBLE_REGISTER, location.location_);
}
......@@ -338,11 +341,11 @@ struct CallBuffer {
InstructionOperandVector instruction_args;
NodeVector pushed_nodes;
int input_count() const { return descriptor->InputCount(); }
size_t input_count() const { return descriptor->InputCount(); }
int frame_state_count() const { return descriptor->FrameStateCount(); }
size_t frame_state_count() const { return descriptor->FrameStateCount(); }
int frame_state_value_count() const {
size_t frame_state_value_count() const {
return (frame_state_descriptor == NULL)
? 0
: (frame_state_descriptor->size() + 1);
......
......@@ -284,12 +284,14 @@ TARGET_TEST_F(InstructionSelectorTest, ValueEffect) {
// -----------------------------------------------------------------------------
// Calls with deoptimization.
TARGET_TEST_F(InstructionSelectorTest, CallJSFunctionWithDeopt) {
StreamBuilder m(this, kMachAnyTagged, kMachAnyTagged, kMachAnyTagged);
StreamBuilder m(this, kMachAnyTagged, kMachAnyTagged, kMachAnyTagged,
kMachAnyTagged);
BailoutId bailout_id(42);
Node* function_node = m.Parameter(0);
Node* receiver = m.Parameter(1);
Node* context = m.Parameter(2);
Node* parameters = m.NewNode(m.common()->StateValues(1), m.Int32Constant(1));
Node* locals = m.NewNode(m.common()->StateValues(0));
......@@ -298,7 +300,7 @@ TARGET_TEST_F(InstructionSelectorTest, CallJSFunctionWithDeopt) {
Node* state_node = m.NewNode(m.common()->FrameState(bailout_id, kPushOutput),
parameters, locals, stack, context_dummy);
Node* call = m.CallJS0(function_node, receiver, state_node);
Node* call = m.CallJS0(function_node, receiver, context, state_node);
m.Return(call);
Stream s = m.Build(kAllExceptNopInstructions);
......
......@@ -36,28 +36,28 @@ class InstructionSelectorTest : public CompilerTest {
public:
StreamBuilder(InstructionSelectorTest* test, MachineType return_type)
: RawMachineAssembler(new (test->zone()) Graph(test->zone()),
CallDescriptorBuilder(test->zone(), return_type)),
MakeMachineSignature(test->zone(), return_type)),
test_(test) {}
StreamBuilder(InstructionSelectorTest* test, MachineType return_type,
MachineType parameter0_type)
: RawMachineAssembler(new (test->zone()) Graph(test->zone()),
CallDescriptorBuilder(test->zone(), return_type,
parameter0_type)),
: RawMachineAssembler(
new (test->zone()) Graph(test->zone()),
MakeMachineSignature(test->zone(), return_type, parameter0_type)),
test_(test) {}
StreamBuilder(InstructionSelectorTest* test, MachineType return_type,
MachineType parameter0_type, MachineType parameter1_type)
: RawMachineAssembler(
new (test->zone()) Graph(test->zone()),
CallDescriptorBuilder(test->zone(), return_type, parameter0_type,
parameter1_type)),
MakeMachineSignature(test->zone(), return_type, parameter0_type,
parameter1_type)),
test_(test) {}
StreamBuilder(InstructionSelectorTest* test, MachineType return_type,
MachineType parameter0_type, MachineType parameter1_type,
MachineType parameter2_type)
: RawMachineAssembler(
new (test->zone()) Graph(test->zone()),
CallDescriptorBuilder(test->zone(), return_type, parameter0_type,
parameter1_type, parameter2_type)),
MakeMachineSignature(test->zone(), return_type, parameter0_type,
parameter1_type, parameter2_type)),
test_(test) {}
Stream Build(CpuFeature feature) {
......@@ -73,38 +73,41 @@ class InstructionSelectorTest : public CompilerTest {
StreamBuilderMode mode = kTargetInstructions);
private:
MachineCallDescriptorBuilder* CallDescriptorBuilder(
Zone* zone, MachineType return_type) {
return new (zone) MachineCallDescriptorBuilder(return_type, 0, NULL);
}
MachineCallDescriptorBuilder* CallDescriptorBuilder(
Zone* zone, MachineType return_type, MachineType parameter0_type) {
MachineType* parameter_types = zone->NewArray<MachineType>(1);
parameter_types[0] = parameter0_type;
return new (zone)
MachineCallDescriptorBuilder(return_type, 1, parameter_types);
}
MachineCallDescriptorBuilder* CallDescriptorBuilder(
Zone* zone, MachineType return_type, MachineType parameter0_type,
MachineType parameter1_type) {
MachineType* parameter_types = zone->NewArray<MachineType>(2);
parameter_types[0] = parameter0_type;
parameter_types[1] = parameter1_type;
return new (zone)
MachineCallDescriptorBuilder(return_type, 2, parameter_types);
}
MachineCallDescriptorBuilder* CallDescriptorBuilder(
Zone* zone, MachineType return_type, MachineType parameter0_type,
MachineType parameter1_type, MachineType parameter2_type) {
MachineType* parameter_types = zone->NewArray<MachineType>(3);
parameter_types[0] = parameter0_type;
parameter_types[1] = parameter1_type;
parameter_types[2] = parameter2_type;
return new (zone)
MachineCallDescriptorBuilder(return_type, 3, parameter_types);
MachineSignature* MakeMachineSignature(Zone* zone,
MachineType return_type) {
MachineSignature::Builder builder(zone, 1, 0);
builder.AddReturn(return_type);
return builder.Build();
}
MachineSignature* MakeMachineSignature(Zone* zone, MachineType return_type,
MachineType parameter0_type) {
MachineSignature::Builder builder(zone, 1, 1);
builder.AddReturn(return_type);
builder.AddParam(parameter0_type);
return builder.Build();
}
MachineSignature* MakeMachineSignature(Zone* zone, MachineType return_type,
MachineType parameter0_type,
MachineType parameter1_type) {
MachineSignature::Builder builder(zone, 1, 2);
builder.AddReturn(return_type);
builder.AddParam(parameter0_type);
builder.AddParam(parameter1_type);
return builder.Build();
}
MachineSignature* MakeMachineSignature(Zone* zone, MachineType return_type,
MachineType parameter0_type,
MachineType parameter1_type,
MachineType parameter2_type) {
MachineSignature::Builder builder(zone, 1, 3);
builder.AddReturn(return_type);
builder.AddParam(parameter0_type);
builder.AddParam(parameter1_type);
builder.AddParam(parameter2_type);
return builder.Build();
}
private:
......
......@@ -296,10 +296,12 @@ void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer,
for (size_t i = 0; i < buffer->output_nodes.size(); i++) {
if (buffer->output_nodes[i] != NULL) {
Node* output = buffer->output_nodes[i];
MachineType type =
buffer->descriptor->GetReturnType(static_cast<int>(i));
LinkageLocation location =
buffer->descriptor->GetReturnLocation(static_cast<int>(i));
MarkAsRepresentation(location.representation(), output);
buffer->outputs.push_back(g.DefineAsLocation(output, location));
MarkAsRepresentation(type, output);
buffer->outputs.push_back(g.DefineAsLocation(output, location, type));
}
}
}
......@@ -323,7 +325,8 @@ void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer,
break;
case CallDescriptor::kCallJSFunction:
buffer->instruction_args.push_back(
g.UseLocation(callee, buffer->descriptor->GetInputLocation(0)));
g.UseLocation(callee, buffer->descriptor->GetInputLocation(0),
buffer->descriptor->GetInputType(0)));
break;
}
DCHECK_EQ(1, buffer->instruction_args.size());
......@@ -337,14 +340,15 @@ void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer,
sequence()->AddFrameStateDescriptor(buffer->frame_state_descriptor);
buffer->instruction_args.push_back(g.TempImmediate(state_id.ToInt()));
Node* frame_state = call->InputAt(buffer->descriptor->InputCount());
Node* frame_state =
call->InputAt(static_cast<int>(buffer->descriptor->InputCount()));
AddFrameStateInputs(frame_state, &buffer->instruction_args,
buffer->frame_state_descriptor);
}
DCHECK_EQ(1 + buffer->frame_state_value_count(),
buffer->instruction_args.size());
DCHECK(1 + buffer->frame_state_value_count() ==
buffer->instruction_args.size());
int input_count = buffer->input_count();
size_t input_count = static_cast<size_t>(buffer->input_count());
// Split the arguments into pushed_nodes and instruction_args. Pushed
// arguments require an explicit push instruction before the call and do
......@@ -352,13 +356,14 @@ void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer,
// as an InstructionOperand argument to the call.
InputIter iter(call->inputs().begin());
int pushed_count = 0;
for (int index = 0; index < input_count; ++iter, ++index) {
for (size_t index = 0; index < input_count; ++iter, ++index) {
DCHECK(iter != call->inputs().end());
DCHECK(index == iter.index());
DCHECK(index == static_cast<size_t>(iter.index()));
DCHECK((*iter)->op()->opcode() != IrOpcode::kFrameState);
if (index == 0) continue; // The first argument (callee) is already done.
InstructionOperand* op =
g.UseLocation(*iter, buffer->descriptor->GetInputLocation(index));
g.UseLocation(*iter, buffer->descriptor->GetInputLocation(index),
buffer->descriptor->GetInputType(index));
if (UnallocatedOperand::cast(op)->HasFixedSlotPolicy()) {
int stack_index = -UnallocatedOperand::cast(op)->fixed_slot_index() - 1;
if (static_cast<size_t>(stack_index) >= buffer->pushed_nodes.size()) {
......@@ -482,9 +487,8 @@ void InstructionSelector::VisitNode(Node* node) {
case IrOpcode::kFinish:
return MarkAsReference(node), VisitFinish(node);
case IrOpcode::kParameter: {
LinkageLocation location =
linkage()->GetParameterLocation(OpParameter<int>(node));
MarkAsRepresentation(location.representation(), node);
MachineType type = linkage()->GetParameterType(OpParameter<int>(node));
MarkAsRepresentation(type, node);
return VisitParameter(node);
}
case IrOpcode::kPhi:
......@@ -820,8 +824,10 @@ void InstructionSelector::VisitFinish(Node* node) {
void InstructionSelector::VisitParameter(Node* node) {
OperandGenerator g(this);
Emit(kArchNop, g.DefineAsLocation(node, linkage()->GetParameterLocation(
OpParameter<int>(node))));
int index = OpParameter<int>(node);
Emit(kArchNop,
g.DefineAsLocation(node, linkage()->GetParameterLocation(index),
linkage()->GetParameterType(index)));
}
......@@ -985,7 +991,8 @@ void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch,
void InstructionSelector::VisitReturn(Node* value) {
OperandGenerator g(this);
if (value != NULL) {
Emit(kArchRet, NULL, g.UseLocation(value, linkage()->GetReturnLocation()));
Emit(kArchRet, NULL, g.UseLocation(value, linkage()->GetReturnLocation(),
linkage()->GetReturnType()));
} else {
Emit(kArchRet, NULL);
}
......
This diff is collapsed.
......@@ -34,7 +34,7 @@ OStream& operator<<(OStream& os, const CallDescriptor::Kind& k) {
OStream& operator<<(OStream& os, const CallDescriptor& d) {
// TODO(svenpanne) Output properties etc. and be less cryptic.
return os << d.kind() << ":" << d.debug_name() << ":r" << d.ReturnCount()
<< "p" << d.ParameterCount() << "i" << d.InputCount() << "f"
<< "j" << d.JSParameterCount() << "i" << d.InputCount() << "f"
<< d.FrameStateCount();
}
......
......@@ -18,29 +18,32 @@ namespace internal {
namespace compiler {
// Describes the location for a parameter or a return value to a call.
// TODO(titzer): replace with Radium locations when they are ready.
class LinkageLocation {
public:
LinkageLocation(MachineType rep, int location)
: rep_(rep), location_(location) {}
inline MachineType representation() const { return rep_; }
explicit LinkageLocation(int location) : location_(location) {}
static const int16_t ANY_REGISTER = 32767;
static LinkageLocation AnyRegister() { return LinkageLocation(ANY_REGISTER); }
private:
friend class CallDescriptor;
friend class OperandGenerator;
MachineType rep_;
int16_t location_; // >= 0 implies register, otherwise stack slot.
};
typedef Signature<LinkageLocation> LocationSignature;
// Describes a call to various parts of the compiler. Every call has the notion
// of a "target", which is the first input to the call.
class CallDescriptor FINAL : public ZoneObject {
public:
// Describes whether the first parameter is a code object, a JSFunction,
// or an address--all of which require different machine sequences to call.
enum Kind { kCallCodeObject, kCallJSFunction, kCallAddress };
// Describes the kind of this call, which determines the target.
enum Kind {
kCallCodeObject, // target is a Code object
kCallJSFunction, // target is a JSFunction object
kCallAddress // target is a machine pointer
};
enum Flag {
// TODO(jarin) kLazyDeoptimization and kNeedsFrameState should be unified.
......@@ -52,56 +55,74 @@ class CallDescriptor FINAL : public ZoneObject {
};
typedef base::Flags<Flag> Flags;
CallDescriptor(Kind kind, int8_t return_count, int16_t parameter_count,
int16_t input_count, LinkageLocation* locations,
Operator::Properties properties,
CallDescriptor(Kind kind, MachineType target_type, LinkageLocation target_loc,
MachineSignature* machine_sig, LocationSignature* location_sig,
size_t js_param_count, Operator::Properties properties,
RegList callee_saved_registers, Flags flags,
const char* debug_name = "")
: kind_(kind),
return_count_(return_count),
parameter_count_(parameter_count),
input_count_(input_count),
locations_(locations),
target_type_(target_type),
target_loc_(target_loc),
machine_sig_(machine_sig),
location_sig_(location_sig),
js_param_count_(js_param_count),
properties_(properties),
callee_saved_registers_(callee_saved_registers),
flags_(flags),
debug_name_(debug_name) {}
debug_name_(debug_name) {
DCHECK(machine_sig->return_count() == location_sig->return_count());
DCHECK(machine_sig->parameter_count() == location_sig->parameter_count());
}
// Returns the kind of this call.
Kind kind() const { return kind_; }
// Returns {true} if this descriptor is a call to a JSFunction.
bool IsJSFunctionCall() const { return kind_ == kCallJSFunction; }
// The number of return values from this call, usually 0 or 1.
int ReturnCount() const { return return_count_; }
// The number of return values from this call.
size_t ReturnCount() const { return machine_sig_->return_count(); }
// The number of JavaScript parameters to this call, including receiver,
// but not the context.
int ParameterCount() const { return parameter_count_; }
// The number of JavaScript parameters to this call, including the receiver
// object.
size_t JSParameterCount() const { return js_param_count_; }
int InputCount() const { return input_count_; }
// The total number of inputs to this call, which includes the target,
// receiver, context, etc.
// TODO(titzer): this should input the framestate input too.
size_t InputCount() const { return 1 + machine_sig_->parameter_count(); }
int FrameStateCount() const { return NeedsFrameState() ? 1 : 0; }
size_t FrameStateCount() const { return NeedsFrameState() ? 1 : 0; }
Flags flags() const { return flags_; }
bool NeedsFrameState() const { return flags() & kNeedsFrameState; }
LinkageLocation GetReturnLocation(int index) {
DCHECK(index < return_count_);
return locations_[0 + index]; // return locations start at 0.
LinkageLocation GetReturnLocation(size_t index) const {
return location_sig_->GetReturn(index);
}
LinkageLocation GetInputLocation(int index) {
DCHECK(index < input_count_ + 1); // input_count + 1 is the context.
return locations_[return_count_ + index]; // inputs start after returns.
LinkageLocation GetInputLocation(size_t index) const {
if (index == 0) return target_loc_;
return location_sig_->GetParam(index - 1);
}
const MachineSignature* GetMachineSignature() const { return machine_sig_; }
MachineType GetReturnType(size_t index) const {
return machine_sig_->GetReturn(index);
}
MachineType GetInputType(size_t index) const {
if (index == 0) return target_type_;
return machine_sig_->GetParam(index - 1);
}
// Operator properties describe how this call can be optimized, if at all.
Operator::Properties properties() const { return properties_; }
// Get the callee-saved registers, if any, across this call.
RegList CalleeSavedRegisters() { return callee_saved_registers_; }
RegList CalleeSavedRegisters() const { return callee_saved_registers_; }
const char* debug_name() const { return debug_name_; }
......@@ -109,10 +130,11 @@ class CallDescriptor FINAL : public ZoneObject {
friend class Linkage;
Kind kind_;
int8_t return_count_;
int16_t parameter_count_;
int16_t input_count_;
LinkageLocation* locations_;
MachineType target_type_;
LinkageLocation target_loc_;
MachineSignature* machine_sig_;
LocationSignature* location_sig_;
size_t js_param_count_;
Operator::Properties properties_;
RegList callee_saved_registers_;
Flags flags_;
......@@ -166,13 +188,17 @@ class Linkage : public ZoneObject {
// for the host platform. This simplified calling convention only supports
// integers and pointers of one word size each, i.e. no floating point,
// structs, pointers to members, etc.
static CallDescriptor* GetSimplifiedCDescriptor(
Zone* zone, int num_params, MachineType return_type,
const MachineType* param_types);
static CallDescriptor* GetSimplifiedCDescriptor(Zone* zone,
MachineSignature* sig);
// Get the location of an (incoming) parameter to this function.
LinkageLocation GetParameterLocation(int index) {
return incoming_->GetInputLocation(index + 1);
return incoming_->GetInputLocation(index + 1); // + 1 to skip target.
}
// Get the machine type of an (incoming) parameter to this function.
MachineType GetParameterType(int index) {
return incoming_->GetInputType(index + 1); // + 1 to skip target.
}
// Get the location where this function should place its return value.
......@@ -180,6 +206,9 @@ class Linkage : public ZoneObject {
return incoming_->GetReturnLocation(0);
}
// Get the machine type of this function's return value.
MachineType GetReturnType() { return incoming_->GetReturnType(0); }
// Get the frame offset for a given spill slot. The location depends on the
// calling convention and the specific frame layout, and may thus be
// architecture-specific. Negative spill slots indicate arguments on the
......
......@@ -20,32 +20,10 @@ namespace v8 {
namespace internal {
namespace compiler {
class MachineCallDescriptorBuilder : public ZoneObject {
public:
MachineCallDescriptorBuilder(MachineType return_type, int parameter_count,
const MachineType* parameter_types)
: return_type_(return_type),
parameter_count_(parameter_count),
parameter_types_(parameter_types) {}
int parameter_count() const { return parameter_count_; }
const MachineType* parameter_types() const { return parameter_types_; }
CallDescriptor* BuildCallDescriptor(Zone* zone) {
return Linkage::GetSimplifiedCDescriptor(zone, parameter_count_,
return_type_, parameter_types_);
}
private:
const MachineType return_type_;
const int parameter_count_;
const MachineType* const parameter_types_;
};
#define ZONE() static_cast<NodeFactory*>(this)->zone()
#define COMMON() static_cast<NodeFactory*>(this)->common()
#define MACHINE() static_cast<NodeFactory*>(this)->machine()
#define MACHINE_SIG() static_cast<NodeFactory*>(this)->machine_sig()
#define NEW_NODE_0(op) static_cast<NodeFactory*>(this)->NewNode(op)
#define NEW_NODE_1(op, a) static_cast<NodeFactory*>(this)->NewNode(op, a)
#define NEW_NODE_2(op, a, b) static_cast<NodeFactory*>(this)->NewNode(op, a, b)
......@@ -369,8 +347,8 @@ class MachineNodeFactory {
// Call to C.
Node* CallC(Node* function_address, MachineType return_type,
MachineType* arg_types, Node** args, int n_args) {
CallDescriptor* descriptor = Linkage::GetSimplifiedCDescriptor(
ZONE(), n_args, return_type, arg_types);
CallDescriptor* descriptor =
Linkage::GetSimplifiedCDescriptor(ZONE(), MACHINE_SIG());
Node** passed_args =
static_cast<Node**>(alloca((n_args + 1) * sizeof(args[0])));
passed_args[0] = function_address;
......
......@@ -7,6 +7,7 @@
#include "src/base/bits.h"
#include "src/globals.h"
#include "src/zone.h"
namespace v8 {
namespace internal {
......@@ -109,32 +110,71 @@ inline int ElementSizeOf(MachineType machine_type) {
}
}
// Describes the inputs and outputs of a function or call in terms of machine
// types.
class MachineSignature {
// Describes the inputs and outputs of a function or call.
template <typename T>
class Signature : public ZoneObject {
public:
MachineSignature(uint8_t return_count, uint16_t param_count,
MachineType* reps)
: return_count_(return_count), param_count_(param_count), reps_(reps) {}
Signature(size_t return_count, size_t parameter_count, T* reps)
: return_count_(return_count),
parameter_count_(parameter_count),
reps_(reps) {}
int GetReturnCount() const { return return_count_; }
int GetParamCount() const { return param_count_; }
size_t return_count() const { return return_count_; }
size_t parameter_count() const { return parameter_count_; }
MachineType GetParameterType(int index) const {
DCHECK(index >= 0 && index < param_count_);
T GetParam(size_t index) const {
DCHECK(index < parameter_count_);
return reps_[return_count_ + index];
}
MachineType GetReturnType(int index = 0) const {
DCHECK(index >= 0 && index < return_count_);
T GetReturn(size_t index = 0) const {
DCHECK(index < return_count_);
return reps_[index];
}
// For incrementally building signatures.
class Builder {
public:
Builder(Zone* zone, size_t return_count, size_t parameter_count)
: return_count_(return_count),
parameter_count_(parameter_count),
zone_(zone),
rcursor_(0),
pcursor_(0),
buffer_(zone->NewArray<T>(
static_cast<int>(return_count + parameter_count))) {}
const size_t return_count_;
const size_t parameter_count_;
void AddReturn(T val) {
DCHECK(rcursor_ < return_count_);
buffer_[rcursor_++] = val;
}
void AddParam(T val) {
DCHECK(pcursor_ < parameter_count_);
buffer_[return_count_ + pcursor_++] = val;
}
Signature<T>* Build() {
DCHECK(rcursor_ == return_count_);
DCHECK(pcursor_ == parameter_count_);
return new (zone_) Signature<T>(return_count_, parameter_count_, buffer_);
}
private:
Zone* zone_;
size_t rcursor_;
size_t pcursor_;
T* buffer_;
};
protected:
uint8_t return_count_;
uint16_t param_count_;
MachineType* reps_;
size_t return_count_;
size_t parameter_count_;
T* reps_;
};
typedef Signature<MachineType> MachineSignature;
} // namespace compiler
} // namespace internal
} // namespace v8
......
......@@ -10,23 +10,27 @@ namespace v8 {
namespace internal {
namespace compiler {
RawMachineAssembler::RawMachineAssembler(
Graph* graph, MachineCallDescriptorBuilder* call_descriptor_builder,
MachineType word)
RawMachineAssembler::RawMachineAssembler(Graph* graph,
MachineSignature* machine_sig,
MachineType word)
: GraphBuilder(graph),
schedule_(new (zone()) Schedule(zone())),
machine_(zone(), word),
common_(zone()),
call_descriptor_builder_(call_descriptor_builder),
machine_sig_(machine_sig),
call_descriptor_(
Linkage::GetSimplifiedCDescriptor(graph->zone(), machine_sig)),
parameters_(NULL),
exit_label_(schedule()->end()),
current_block_(schedule()->start()) {
Node* s = graph->NewNode(common_.Start(parameter_count()));
int param_count = static_cast<int>(parameter_count());
Node* s = graph->NewNode(common_.Start(param_count));
graph->SetStart(s);
if (parameter_count() == 0) return;
parameters_ = zone()->NewArray<Node*>(parameter_count());
for (int i = 0; i < parameter_count(); ++i) {
parameters_[i] = NewNode(common()->Parameter(i), graph->start());
parameters_ = zone()->NewArray<Node*>(param_count);
for (size_t i = 0; i < parameter_count(); ++i) {
parameters_[i] =
NewNode(common()->Parameter(static_cast<int>(i)), graph->start());
}
}
......@@ -42,8 +46,8 @@ Schedule* RawMachineAssembler::Export() {
}
Node* RawMachineAssembler::Parameter(int index) {
DCHECK(0 <= index && index < parameter_count());
Node* RawMachineAssembler::Parameter(size_t index) {
DCHECK(index < parameter_count());
return parameters_[index];
}
......@@ -95,17 +99,18 @@ Node* RawMachineAssembler::CallFunctionStub0(Node* function, Node* receiver,
Node* RawMachineAssembler::CallJS0(Node* function, Node* receiver,
Node* frame_state) {
Node* context, Node* frame_state) {
CallDescriptor* descriptor = Linkage::GetJSCallDescriptor(1, zone());
Node* call = graph()->NewNode(common()->Call(descriptor), function, receiver,
frame_state);
context, frame_state);
schedule()->AddNode(CurrentBlock(), call);
return call;
}
Node* RawMachineAssembler::CallRuntime1(Runtime::FunctionId function,
Node* arg0, Node* frame_state) {
Node* arg0, Node* context,
Node* frame_state) {
CallDescriptor* descriptor = Linkage::GetRuntimeCallDescriptor(
function, 1, Operator::kNoProperties, zone());
......@@ -113,7 +118,6 @@ Node* RawMachineAssembler::CallRuntime1(Runtime::FunctionId function,
Node* ref = NewNode(
common()->ExternalConstant(ExternalReference(function, isolate())));
Node* arity = Int32Constant(1);
Node* context = Parameter(1);
Node* call = graph()->NewNode(common()->Call(descriptor), centry, arg0, ref,
arity, context, frame_state);
......
......@@ -45,8 +45,7 @@ class RawMachineAssembler : public GraphBuilder,
DISALLOW_COPY_AND_ASSIGN(Label);
};
RawMachineAssembler(Graph* graph,
MachineCallDescriptorBuilder* call_descriptor_builder,
RawMachineAssembler(Graph* graph, MachineSignature* machine_sig,
MachineType word = kMachPtr);
virtual ~RawMachineAssembler() {}
......@@ -54,18 +53,12 @@ class RawMachineAssembler : public GraphBuilder,
Zone* zone() const { return graph()->zone(); }
MachineOperatorBuilder* machine() { return &machine_; }
CommonOperatorBuilder* common() { return &common_; }
CallDescriptor* call_descriptor() const {
return call_descriptor_builder_->BuildCallDescriptor(zone());
}
int parameter_count() const {
return call_descriptor_builder_->parameter_count();
}
const MachineType* parameter_types() const {
return call_descriptor_builder_->parameter_types();
}
CallDescriptor* call_descriptor() const { return call_descriptor_; }
size_t parameter_count() const { return machine_sig_->parameter_count(); }
MachineSignature* machine_sig() const { return machine_sig_; }
// Parameters.
Node* Parameter(int index);
Node* Parameter(size_t index);
// Control flow.
Label* Exit();
......@@ -75,9 +68,10 @@ class RawMachineAssembler : public GraphBuilder,
Node* CallFunctionStub0(Node* function, Node* receiver, Node* context,
Node* frame_state, CallFunctionFlags flags);
// Call to a JS function with zero parameters.
Node* CallJS0(Node* function, Node* receiver, Node* frame_state);
Node* CallJS0(Node* function, Node* receiver, Node* context,
Node* frame_state);
// Call to a runtime function with zero parameters.
Node* CallRuntime1(Runtime::FunctionId function, Node* arg0,
Node* CallRuntime1(Runtime::FunctionId function, Node* arg0, Node* context,
Node* frame_state);
void Return(Node* value);
void Bind(Label* label);
......@@ -113,7 +107,8 @@ class RawMachineAssembler : public GraphBuilder,
Schedule* schedule_;
MachineOperatorBuilder machine_;
CommonOperatorBuilder common_;
MachineCallDescriptorBuilder* call_descriptor_builder_;
MachineSignature* machine_sig_;
CallDescriptor* call_descriptor_;
Node** parameters_;
Label exit_label_;
BasicBlock* current_block_;
......
......@@ -17,23 +17,26 @@ void Variable::Set(Node* value) const { smasm_->SetVariable(offset_, value); }
StructuredMachineAssembler::StructuredMachineAssembler(
Graph* graph, MachineCallDescriptorBuilder* call_descriptor_builder,
MachineType word)
Graph* graph, MachineSignature* machine_sig, MachineType word)
: GraphBuilder(graph),
schedule_(new (zone()) Schedule(zone())),
machine_(zone(), word),
common_(zone()),
call_descriptor_builder_(call_descriptor_builder),
machine_sig_(machine_sig),
call_descriptor_(
Linkage::GetSimplifiedCDescriptor(graph->zone(), machine_sig)),
parameters_(NULL),
current_environment_(new (zone())
Environment(zone(), schedule()->start(), false)),
number_of_variables_(0) {
Node* s = graph->NewNode(common_.Start(parameter_count()));
int param_count = static_cast<int>(parameter_count());
Node* s = graph->NewNode(common_.Start(param_count));
graph->SetStart(s);
if (parameter_count() == 0) return;
parameters_ = zone()->NewArray<Node*>(parameter_count());
for (int i = 0; i < parameter_count(); ++i) {
parameters_[i] = NewNode(common()->Parameter(i), graph->start());
parameters_ = zone()->NewArray<Node*>(param_count);
for (size_t i = 0; i < parameter_count(); ++i) {
parameters_[i] =
NewNode(common()->Parameter(static_cast<int>(i)), graph->start());
}
}
......@@ -49,8 +52,8 @@ Schedule* StructuredMachineAssembler::Export() {
}
Node* StructuredMachineAssembler::Parameter(int index) {
DCHECK(0 <= index && index < parameter_count());
Node* StructuredMachineAssembler::Parameter(size_t index) {
DCHECK(index < parameter_count());
return parameters_[index];
}
......
......@@ -61,27 +61,20 @@ class StructuredMachineAssembler
class LoopBuilder;
friend class LoopBuilder;
StructuredMachineAssembler(
Graph* graph, MachineCallDescriptorBuilder* call_descriptor_builder,
MachineType word = kMachPtr);
StructuredMachineAssembler(Graph* graph, MachineSignature* machine_sig,
MachineType word = kMachPtr);
virtual ~StructuredMachineAssembler() {}
Isolate* isolate() const { return zone()->isolate(); }
Zone* zone() const { return graph()->zone(); }
MachineOperatorBuilder* machine() { return &machine_; }
CommonOperatorBuilder* common() { return &common_; }
CallDescriptor* call_descriptor() const {
return call_descriptor_builder_->BuildCallDescriptor(zone());
}
int parameter_count() const {
return call_descriptor_builder_->parameter_count();
}
const MachineType* parameter_types() const {
return call_descriptor_builder_->parameter_types();
}
CallDescriptor* call_descriptor() const { return call_descriptor_; }
size_t parameter_count() const { return machine_sig_->parameter_count(); }
MachineSignature* machine_sig() const { return machine_sig_; }
// Parameters.
Node* Parameter(int index);
Node* Parameter(size_t index);
// Variables.
Variable NewVariable(Node* initial_value);
// Control flow.
......@@ -126,7 +119,8 @@ class StructuredMachineAssembler
Schedule* schedule_;
MachineOperatorBuilder machine_;
CommonOperatorBuilder common_;
MachineCallDescriptorBuilder* call_descriptor_builder_;
MachineSignature* machine_sig_;
CallDescriptor* call_descriptor_;
Node** parameters_;
Environment* current_environment_;
int number_of_variables_;
......
......@@ -226,9 +226,12 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
}
break;
case kArchCallJSFunction: {
// TODO(jarin) The load of the context should be separated from the call.
Register func = i.InputRegister(0);
__ movp(rsi, FieldOperand(func, JSFunction::kContextOffset));
if (FLAG_debug_code) {
// Check the function's context matches the context argument.
__ cmpp(rsi, FieldOperand(func, JSFunction::kContextOffset));
__ Assert(equal, kWrongFunctionContext);
}
__ Call(FieldOperand(func, JSFunction::kCodeEntryOffset));
AddSafepointAndDeopt(instr);
break;
......@@ -858,8 +861,9 @@ void CodeGenerator::AssembleReturn() {
} else {
__ movq(rsp, rbp); // Move stack pointer back to frame pointer.
__ popq(rbp); // Pop caller's frame pointer.
int pop_count =
descriptor->IsJSFunctionCall() ? descriptor->ParameterCount() : 0;
int pop_count = descriptor->IsJSFunctionCall()
? static_cast<int>(descriptor->JSParameterCount())
: 0;
__ ret(pop_count * kPointerSize);
}
}
......
......@@ -671,8 +671,8 @@ void InstructionSelector::VisitCall(Node* call, BasicBlock* continuation,
FrameStateDescriptor* frame_state_descriptor = NULL;
if (descriptor->NeedsFrameState()) {
frame_state_descriptor =
GetFrameStateDescriptor(call->InputAt(descriptor->InputCount()));
frame_state_descriptor = GetFrameStateDescriptor(
call->InputAt(static_cast<int>(descriptor->InputCount())));
}
CallBuffer buffer(zone(), descriptor, frame_state_descriptor);
......
......@@ -20,7 +20,7 @@ const bool kWin64 = true;
const bool kWin64 = false;
#endif
struct LinkageHelperTraits {
struct X64LinkageHelperTraits {
static Register ReturnValueReg() { return rax; }
static Register ReturnValue2Reg() { return rdx; }
static Register JSCallFunctionReg() { return rdi; }
......@@ -47,34 +47,32 @@ struct LinkageHelperTraits {
static int CRegisterParametersLength() { return kWin64 ? 4 : 6; }
};
typedef LinkageHelper<X64LinkageHelperTraits> LH;
CallDescriptor* Linkage::GetJSCallDescriptor(int parameter_count, Zone* zone) {
return LinkageHelper::GetJSCallDescriptor<LinkageHelperTraits>(
zone, parameter_count);
return LH::GetJSCallDescriptor(zone, parameter_count);
}
CallDescriptor* Linkage::GetRuntimeCallDescriptor(
Runtime::FunctionId function, int parameter_count,
Operator::Properties properties, Zone* zone) {
return LinkageHelper::GetRuntimeCallDescriptor<LinkageHelperTraits>(
zone, function, parameter_count, properties);
return LH::GetRuntimeCallDescriptor(zone, function, parameter_count,
properties);
}
CallDescriptor* Linkage::GetStubCallDescriptor(
CodeStubInterfaceDescriptor* descriptor, int stack_parameter_count,
CallDescriptor::Flags flags, Zone* zone) {
return LinkageHelper::GetStubCallDescriptor<LinkageHelperTraits>(
zone, descriptor, stack_parameter_count, flags);
return LH::GetStubCallDescriptor(zone, descriptor, stack_parameter_count,
flags);
}
CallDescriptor* Linkage::GetSimplifiedCDescriptor(
Zone* zone, int num_params, MachineType return_type,
const MachineType* param_types) {
return LinkageHelper::GetSimplifiedCDescriptor<LinkageHelperTraits>(
zone, num_params, return_type, param_types);
CallDescriptor* Linkage::GetSimplifiedCDescriptor(Zone* zone,
MachineSignature* sig) {
return LH::GetSimplifiedCDescriptor(zone, sig);
}
} // namespace compiler
......
This diff is collapsed.
......@@ -23,7 +23,7 @@ namespace v8 {
namespace internal {
namespace compiler {
// TODO(titzer): move MachineType selection for C types into machine-type.h
// TODO(titzer): use c-signature.h instead of ReturnValueTraits
template <typename R>
struct ReturnValueTraits {
static R Cast(uintptr_t r) { return reinterpret_cast<R>(r); }
......@@ -130,34 +130,40 @@ struct ParameterTraits<T*> {
class CallHelper {
public:
explicit CallHelper(Isolate* isolate) : isolate_(isolate) { USE(isolate_); }
explicit CallHelper(Isolate* isolate, MachineSignature* machine_sig)
: machine_sig_(machine_sig), isolate_(isolate) {
USE(isolate_);
}
virtual ~CallHelper() {}
static MachineCallDescriptorBuilder* ToCallDescriptorBuilder(
static MachineSignature* MakeMachineSignature(
Zone* zone, MachineType return_type, MachineType p0 = kMachNone,
MachineType p1 = kMachNone, MachineType p2 = kMachNone,
MachineType p3 = kMachNone, MachineType p4 = kMachNone) {
const int kSize = 5;
MachineType* params = zone->NewArray<MachineType>(kSize);
params[0] = p0;
params[1] = p1;
params[2] = p2;
params[3] = p3;
params[4] = p4;
int parameter_count = 0;
for (int i = 0; i < kSize; ++i) {
if (params[i] == kMachNone) {
break;
}
parameter_count++;
// Count the number of parameters.
size_t param_count = 5;
MachineType types[] = {p0, p1, p2, p3, p4};
while (param_count > 0 && types[param_count - 1] == kMachNone)
param_count--;
size_t return_count = return_type == kMachNone ? 0 : 1;
// Build the machine signature.
MachineSignature::Builder builder(zone, return_count, param_count);
if (return_count > 0) builder.AddReturn(return_type);
for (size_t i = 0; i < param_count; i++) {
builder.AddParam(types[i]);
}
return new (zone)
MachineCallDescriptorBuilder(return_type, parameter_count, params);
return builder.Build();
}
protected:
virtual void VerifyParameters(int parameter_count,
MachineType* parameters) = 0;
MachineSignature* machine_sig_;
void VerifyParameters(size_t parameter_count, MachineType* parameter_types) {
CHECK(machine_sig_->parameter_count() == parameter_count);
for (size_t i = 0; i < parameter_count; i++) {
CHECK_EQ(machine_sig_->GetParam(i), parameter_types[i]);
}
}
virtual byte* Generate() = 0;
private:
......
......@@ -26,11 +26,13 @@ class MachineAssemblerTester : public HandleAndZoneScope,
MachineType p1, MachineType p2, MachineType p3,
MachineType p4)
: HandleAndZoneScope(),
CallHelper(main_isolate()),
MachineAssembler(new (main_zone()) Graph(main_zone()),
ToCallDescriptorBuilder(main_zone(), return_type, p0,
p1, p2, p3, p4),
kMachPtr) {}
CallHelper(
main_isolate(),
MakeMachineSignature(main_zone(), return_type, p0, p1, p2, p3, p4)),
MachineAssembler(
new (main_zone()) Graph(main_zone()),
MakeMachineSignature(main_zone(), return_type, p0, p1, p2, p3, p4),
kMachPtr) {}
Node* LoadFromPointer(void* address, MachineType rep, int32_t offset = 0) {
return this->Load(rep, this->PointerConstant(address),
......@@ -59,15 +61,6 @@ class MachineAssemblerTester : public HandleAndZoneScope,
void GenerateCode() { Generate(); }
protected:
virtual void VerifyParameters(int parameter_count,
MachineType* parameter_types) {
CHECK_EQ(this->parameter_count(), parameter_count);
const MachineType* expected_types = this->parameter_types();
for (int i = 0; i < parameter_count; i++) {
CHECK_EQ(expected_types[i], parameter_types[i]);
}
}
virtual byte* Generate() {
if (code_.is_null()) {
Schedule* schedule = this->Export();
......
......@@ -9,10 +9,8 @@ namespace v8 {
namespace internal {
namespace compiler {
MachineCallHelper::MachineCallHelper(Zone* zone,
MachineCallDescriptorBuilder* builder)
: CallHelper(zone->isolate()),
call_descriptor_builder_(builder),
MachineCallHelper::MachineCallHelper(Zone* zone, MachineSignature* machine_sig)
: CallHelper(zone->isolate(), machine_sig),
parameters_(NULL),
graph_(NULL) {}
......@@ -21,9 +19,10 @@ void MachineCallHelper::InitParameters(GraphBuilder* builder,
CommonOperatorBuilder* common) {
DCHECK_EQ(NULL, parameters_);
graph_ = builder->graph();
if (parameter_count() == 0) return;
parameters_ = graph_->zone()->NewArray<Node*>(parameter_count());
for (int i = 0; i < parameter_count(); ++i) {
int param_count = static_cast<int>(parameter_count());
if (param_count == 0) return;
parameters_ = graph_->zone()->NewArray<Node*>(param_count);
for (int i = 0; i < param_count; ++i) {
parameters_[i] = builder->NewNode(common->Parameter(i), graph_->start());
}
}
......@@ -35,7 +34,8 @@ byte* MachineCallHelper::Generate() {
if (code_.is_null()) {
Zone* zone = graph_->zone();
CompilationInfo info(zone->isolate(), zone);
Linkage linkage(&info, call_descriptor_builder_->BuildCallDescriptor(zone));
Linkage linkage(&info,
Linkage::GetSimplifiedCDescriptor(zone, machine_sig_));
Pipeline pipeline(&info);
code_ = pipeline.GenerateCodeForMachineGraph(&linkage, graph_);
}
......@@ -43,21 +43,10 @@ byte* MachineCallHelper::Generate() {
}
void MachineCallHelper::VerifyParameters(int parameter_count,
MachineType* parameter_types) {
CHECK_EQ(this->parameter_count(), parameter_count);
const MachineType* expected_types =
call_descriptor_builder_->parameter_types();
for (int i = 0; i < parameter_count; i++) {
CHECK_EQ(expected_types[i], parameter_types[i]);
}
}
Node* MachineCallHelper::Parameter(int offset) {
Node* MachineCallHelper::Parameter(size_t index) {
DCHECK_NE(NULL, parameters_);
DCHECK(0 <= offset && offset < parameter_count());
return parameters_[offset];
DCHECK(index < parameter_count());
return parameters_[index];
}
} // namespace compiler
......
......@@ -37,24 +37,20 @@ class DirectGraphBuilder : public GraphBuilder {
class MachineCallHelper : public CallHelper {
public:
MachineCallHelper(Zone* zone, MachineCallDescriptorBuilder* builder);
MachineCallHelper(Zone* zone, MachineSignature* machine_sig);
Node* Parameter(int offset);
Node* Parameter(size_t index);
void GenerateCode() { Generate(); }
protected:
virtual byte* Generate();
virtual void VerifyParameters(int parameter_count, MachineType* parameters);
void InitParameters(GraphBuilder* builder, CommonOperatorBuilder* common);
protected:
int parameter_count() const {
return call_descriptor_builder_->parameter_count();
}
size_t parameter_count() const { return machine_sig_->parameter_count(); }
private:
MachineCallDescriptorBuilder* call_descriptor_builder_;
Node** parameters_;
// TODO(dcarney): shouldn't need graph stored.
Graph* graph_;
......@@ -95,12 +91,12 @@ class GraphBuilderTester
: GraphAndBuilders(main_zone()),
MachineCallHelper(
main_zone(),
ToCallDescriptorBuilder(
MakeMachineSignature(
main_zone(), ReturnValueTraits<ReturnType>::Representation(),
p0, p1, p2, p3, p4)),
SimplifiedGraphBuilder(main_graph_, &main_common_, &main_machine_,
&main_simplified_) {
Begin(parameter_count());
Begin(static_cast<int>(parameter_count()));
InitParameters(this, &main_common_);
}
virtual ~GraphBuilderTester() {}
......
......@@ -20,6 +20,7 @@
#include "src/parser.h"
#include "src/rewriter.h"
#include "test/cctest/compiler/c-signature.h"
#include "test/cctest/compiler/function-tester.h"
using namespace v8::internal;
......@@ -64,7 +65,9 @@ class DeoptCodegenTester {
void GenerateCodeFromSchedule(Schedule* schedule) {
OFStream os(stdout);
os << *schedule;
if (FLAG_trace_turbo) {
os << *schedule;
}
// Initialize the codegen and generate code.
Linkage* linkage = new (scope_->main_zone()) Linkage(&info);
......@@ -74,20 +77,26 @@ class DeoptCodegenTester {
InstructionSelector selector(code, &source_positions);
selector.SelectInstructions();
os << "----- Instruction sequence before register allocation -----\n"
<< *code;
if (FLAG_trace_turbo) {
os << "----- Instruction sequence before register allocation -----\n"
<< *code;
}
RegisterAllocator allocator(code);
CHECK(allocator.Allocate());
os << "----- Instruction sequence after register allocation -----\n"
<< *code;
if (FLAG_trace_turbo) {
os << "----- Instruction sequence after register allocation -----\n"
<< *code;
}
compiler::CodeGenerator generator(code);
result_code = generator.GenerateCode();
#ifdef DEBUG
result_code->Print();
#ifdef OBJECT_PRINT
if (FLAG_print_opt_code || FLAG_trace_turbo) {
result_code->Print();
}
#endif
}
......@@ -122,11 +131,8 @@ class TrivialDeoptCodegenTester : public DeoptCodegenTester {
// deopt();
// }
MachineType parameter_reps[] = {kMachAnyTagged};
MachineCallDescriptorBuilder descriptor_builder(kMachAnyTagged, 1,
parameter_reps);
RawMachineAssembler m(graph, &descriptor_builder);
CSignature1<Object*, Object*> sig;
RawMachineAssembler m(graph, &sig);
Handle<Object> undef_object =
Handle<Object>(isolate->heap()->undefined_value(), isolate);
......@@ -140,6 +146,10 @@ class TrivialDeoptCodegenTester : public DeoptCodegenTester {
PrintableUnique<Object>::CreateUninitialized(zone(), deopt_function);
Node* deopt_fun_node = m.NewNode(common.HeapConstant(deopt_fun_constant));
Handle<Context> context(deopt_function->context(), isolate);
PrintableUnique<Object> context_constant =
PrintableUnique<Object>::CreateUninitialized(zone(), context);
Node* context_node = m.NewNode(common.HeapConstant(context_constant));
bailout_id = GetCallBailoutId();
Node* parameters = m.NewNode(common.StateValues(1), undef_node);
......@@ -149,7 +159,7 @@ class TrivialDeoptCodegenTester : public DeoptCodegenTester {
Node* state_node = m.NewNode(common.FrameState(bailout_id, kIgnoreOutput),
parameters, locals, stack, undef_node);
m.CallJS0(deopt_fun_node, undef_node, state_node);
m.CallJS0(deopt_fun_node, undef_node, context_node, state_node);
m.Return(undef_node);
......@@ -238,11 +248,8 @@ class TrivialRuntimeDeoptCodegenTester : public DeoptCodegenTester {
// %DeoptimizeFunction(foo);
// }
MachineType parameter_reps[] = {kMachAnyTagged};
MachineCallDescriptorBuilder descriptor_builder(kMachAnyTagged, 2,
parameter_reps);
RawMachineAssembler m(graph, &descriptor_builder);
CSignature1<Object*, Object*> sig;
RawMachineAssembler m(graph, &sig);
Handle<Object> undef_object =
Handle<Object>(isolate->heap()->undefined_value(), isolate);
......@@ -254,6 +261,11 @@ class TrivialRuntimeDeoptCodegenTester : public DeoptCodegenTester {
PrintableUnique<Object>::CreateUninitialized(zone(), function);
Node* this_fun_node = m.NewNode(common.HeapConstant(this_fun_constant));
Handle<Context> context(function->context(), isolate);
PrintableUnique<Object> context_constant =
PrintableUnique<Object>::CreateUninitialized(zone(), context);
Node* context_node = m.NewNode(common.HeapConstant(context_constant));
bailout_id = GetCallBailoutId();
Node* parameters = m.NewNode(common.StateValues(1), undef_node);
Node* locals = m.NewNode(common.StateValues(0));
......@@ -262,7 +274,8 @@ class TrivialRuntimeDeoptCodegenTester : public DeoptCodegenTester {
Node* state_node = m.NewNode(common.FrameState(bailout_id, kIgnoreOutput),
parameters, locals, stack, undef_node);
m.CallRuntime1(Runtime::kDeoptimizeFunction, this_fun_node, state_node);
m.CallRuntime1(Runtime::kDeoptimizeFunction, this_fun_node, context_node,
state_node);
m.Return(undef_node);
......
......@@ -65,7 +65,7 @@ TEST(TestLinkageJSFunctionIncoming) {
CallDescriptor* descriptor = linkage.GetIncomingDescriptor();
CHECK_NE(NULL, descriptor);
CHECK_EQ(1 + i, descriptor->ParameterCount());
CHECK_EQ(1 + i, descriptor->JSParameterCount());
CHECK_EQ(1, descriptor->ReturnCount());
CHECK_EQ(Operator::kNoProperties, descriptor->properties());
CHECK_EQ(true, descriptor->IsJSFunctionCall());
......@@ -92,7 +92,7 @@ TEST(TestLinkageJSCall) {
for (int i = 0; i < 32; i++) {
CallDescriptor* descriptor = linkage.GetJSCallDescriptor(i);
CHECK_NE(NULL, descriptor);
CHECK_EQ(i, descriptor->ParameterCount());
CHECK_EQ(i, descriptor->JSParameterCount());
CHECK_EQ(1, descriptor->ReturnCount());
CHECK_EQ(Operator::kNoProperties, descriptor->properties());
CHECK_EQ(true, descriptor->IsJSFunctionCall());
......
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