[turbofan] Clean up cctest "framework" for dealing with native calls.

R=mstarzinger@chromium.org
BUG=

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

Cr-Commit-Position: refs/heads/master@{#28703}
This commit is contained in:
titzer 2015-05-29 07:05:39 -07:00 committed by Commit bot
parent 43638cd4e8
commit 30ef6b7a69
5 changed files with 131 additions and 188 deletions

View File

@ -302,15 +302,6 @@ class RawMachineAssembler : public GraphBuilder {
return NewNode(machine()->Uint64Mod(), a, b);
}
// TODO(turbofan): What is this used for?
Node* ConvertIntPtrToInt32(Node* a) {
return kPointerSize == 8 ? NewNode(machine()->TruncateInt64ToInt32(), a)
: a;
}
Node* ConvertInt32ToIntPtr(Node* a) {
return kPointerSize == 8 ? NewNode(machine()->ChangeInt32ToInt64(), a) : a;
}
#define INTPTR_BINOP(prefix, name) \
Node* IntPtr##name(Node* a, Node* b) { \
return kPointerSize == 8 ? prefix##64##name(a, b) \
@ -454,6 +445,17 @@ class RawMachineAssembler : public GraphBuilder {
// Parameters.
Node* Parameter(size_t index);
// Pointer utilities.
Node* LoadFromPointer(void* address, MachineType rep, int32_t offset = 0) {
return Load(rep, PointerConstant(address), Int32Constant(offset));
}
void StoreToPointer(void* address, MachineType rep, Node* node) {
Store(rep, PointerConstant(address), node);
}
Node* StringConstant(const char* string) {
return HeapConstant(isolate()->factory()->InternalizeUtf8String(string));
}
// Control flow.
Label* Exit();
void Goto(Label* label);

View File

@ -148,6 +148,7 @@ struct ParameterTraits<uint32_t> {
#endif // !V8_TARGET_ARCH_64_BIT
template <typename R>
class CallHelper {
public:
explicit CallHelper(Isolate* isolate, MachineSignature* machine_sig)
@ -156,34 +157,50 @@ class CallHelper {
}
virtual ~CallHelper() {}
static MachineSignature* MakeMachineSignature(
Zone* zone, MachineType return_type, MachineType p0 = kMachNone,
MachineType p1 = kMachNone, MachineType p2 = kMachNone,
MachineType p3 = kMachNone, MachineType p4 = kMachNone) {
// 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;
R Call() {
typedef R V8_CDECL FType();
VerifyParameters0();
return DoCall(FUNCTION_CAST<FType*>(Generate()));
}
// 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 builder.Build();
template <typename P1>
R Call(P1 p1) {
typedef R V8_CDECL FType(P1);
VerifyParameters1<P1>();
return DoCall(FUNCTION_CAST<FType*>(Generate()), p1);
}
template <typename P1, typename P2>
R Call(P1 p1, P2 p2) {
typedef R V8_CDECL FType(P1, P2);
VerifyParameters2<P1, P2>();
return DoCall(FUNCTION_CAST<FType*>(Generate()), p1, p2);
}
template <typename P1, typename P2, typename P3>
R Call(P1 p1, P2 p2, P3 p3) {
typedef R V8_CDECL FType(P1, P2, P3);
VerifyParameters3<P1, P2, P3>();
return DoCall(FUNCTION_CAST<FType*>(Generate()), p1, p2, p3);
}
template <typename P1, typename P2, typename P3, typename P4>
R Call(P1 p1, P2 p2, P3 p3, P4 p4) {
typedef R V8_CDECL FType(P1, P2, P3, P4);
VerifyParameters4<P1, P2, P3, P4>();
return DoCall(FUNCTION_CAST<FType*>(Generate()), p1, p2, p3, p4);
}
protected:
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:
@ -193,33 +210,32 @@ class CallHelper {
return static_cast<uintptr_t>(simulator->CallInt64(f, args));
}
template <typename R, typename F>
template <typename F>
R DoCall(F* f) {
Simulator::CallArgument args[] = {Simulator::CallArgument::End()};
return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f), args));
}
template <typename R, typename F, typename P1>
template <typename F, typename P1>
R DoCall(F* f, P1 p1) {
Simulator::CallArgument args[] = {Simulator::CallArgument(p1),
Simulator::CallArgument::End()};
return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f), args));
}
template <typename R, typename F, typename P1, typename P2>
template <typename F, typename P1, typename P2>
R DoCall(F* f, P1 p1, P2 p2) {
Simulator::CallArgument args[] = {Simulator::CallArgument(p1),
Simulator::CallArgument(p2),
Simulator::CallArgument::End()};
return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f), args));
}
template <typename R, typename F, typename P1, typename P2, typename P3>
template <typename F, typename P1, typename P2, typename P3>
R DoCall(F* f, P1 p1, P2 p2, P3 p3) {
Simulator::CallArgument args[] = {
Simulator::CallArgument(p1), Simulator::CallArgument(p2),
Simulator::CallArgument(p3), Simulator::CallArgument::End()};
return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f), args));
}
template <typename R, typename F, typename P1, typename P2, typename P3,
typename P4>
template <typename F, typename P1, typename P2, typename P3, typename P4>
R DoCall(F* f, P1 p1, P2 p2, P3 p3, P4 p4) {
Simulator::CallArgument args[] = {
Simulator::CallArgument(p1), Simulator::CallArgument(p2),
@ -235,29 +251,28 @@ class CallHelper {
}
template <typename R, typename F>
template <typename F>
R DoCall(F* f) {
return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f)));
}
template <typename R, typename F, typename P1>
template <typename F, typename P1>
R DoCall(F* f, P1 p1) {
return ReturnValueTraits<R>::Cast(
CallSimulator(FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1)));
}
template <typename R, typename F, typename P1, typename P2>
template <typename F, typename P1, typename P2>
R DoCall(F* f, P1 p1, P2 p2) {
return ReturnValueTraits<R>::Cast(
CallSimulator(FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1),
ParameterTraits<P2>::Cast(p2)));
}
template <typename R, typename F, typename P1, typename P2, typename P3>
template <typename F, typename P1, typename P2, typename P3>
R DoCall(F* f, P1 p1, P2 p2, P3 p3) {
return ReturnValueTraits<R>::Cast(CallSimulator(
FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1),
ParameterTraits<P2>::Cast(p2), ParameterTraits<P3>::Cast(p3)));
}
template <typename R, typename F, typename P1, typename P2, typename P3,
typename P4>
template <typename F, typename P1, typename P2, typename P3, typename P4>
R DoCall(F* f, P1 p1, P2 p2, P3 p3, P4 p4) {
return ReturnValueTraits<R>::Cast(CallSimulator(
FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1),
@ -271,29 +286,28 @@ class CallHelper {
Simulator* simulator = Simulator::current(isolate_);
return static_cast<uintptr_t>(simulator->Call(f, 4, p1, p2, p3, p4));
}
template <typename R, typename F>
template <typename F>
R DoCall(F* f) {
return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f)));
}
template <typename R, typename F, typename P1>
template <typename F, typename P1>
R DoCall(F* f, P1 p1) {
return ReturnValueTraits<R>::Cast(
CallSimulator(FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1)));
}
template <typename R, typename F, typename P1, typename P2>
template <typename F, typename P1, typename P2>
R DoCall(F* f, P1 p1, P2 p2) {
return ReturnValueTraits<R>::Cast(
CallSimulator(FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1),
ParameterTraits<P2>::Cast(p2)));
}
template <typename R, typename F, typename P1, typename P2, typename P3>
template <typename F, typename P1, typename P2, typename P3>
R DoCall(F* f, P1 p1, P2 p2, P3 p3) {
return ReturnValueTraits<R>::Cast(CallSimulator(
FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1),
ParameterTraits<P2>::Cast(p2), ParameterTraits<P3>::Cast(p3)));
}
template <typename R, typename F, typename P1, typename P2, typename P3,
typename P4>
template <typename F, typename P1, typename P2, typename P3, typename P4>
R DoCall(F* f, P1 p1, P2 p2, P3 p3, P4 p4) {
return ReturnValueTraits<R>::Cast(CallSimulator(
FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1),
@ -301,24 +315,23 @@ class CallHelper {
ParameterTraits<P4>::Cast(p4)));
}
#else
template <typename R, typename F>
template <typename F>
R DoCall(F* f) {
return f();
}
template <typename R, typename F, typename P1>
template <typename F, typename P1>
R DoCall(F* f, P1 p1) {
return f(p1);
}
template <typename R, typename F, typename P1, typename P2>
template <typename F, typename P1, typename P2>
R DoCall(F* f, P1 p1, P2 p2) {
return f(p1, p2);
}
template <typename R, typename F, typename P1, typename P2, typename P3>
template <typename F, typename P1, typename P2, typename P3>
R DoCall(F* f, P1 p1, P2 p2, P3 p3) {
return f(p1, p2, p3);
}
template <typename R, typename F, typename P1, typename P2, typename P3,
typename P4>
template <typename F, typename P1, typename P2, typename P3, typename P4>
R DoCall(F* f, P1 p1, P2 p2, P3 p3, P4 p4) {
return f(p1, p2, p3, p4);
}
@ -372,78 +385,9 @@ class CallHelper {
}
#endif
// TODO(dcarney): replace Call() in CallHelper2 with these.
template <typename R>
R Call0() {
typedef R V8_CDECL FType();
VerifyParameters0();
return DoCall<R>(FUNCTION_CAST<FType*>(Generate()));
}
template <typename R, typename P1>
R Call1(P1 p1) {
typedef R V8_CDECL FType(P1);
VerifyParameters1<P1>();
return DoCall<R>(FUNCTION_CAST<FType*>(Generate()), p1);
}
template <typename R, typename P1, typename P2>
R Call2(P1 p1, P2 p2) {
typedef R V8_CDECL FType(P1, P2);
VerifyParameters2<P1, P2>();
return DoCall<R>(FUNCTION_CAST<FType*>(Generate()), p1, p2);
}
template <typename R, typename P1, typename P2, typename P3>
R Call3(P1 p1, P2 p2, P3 p3) {
typedef R V8_CDECL FType(P1, P2, P3);
VerifyParameters3<P1, P2, P3>();
return DoCall<R>(FUNCTION_CAST<FType*>(Generate()), p1, p2, p3);
}
template <typename R, typename P1, typename P2, typename P3, typename P4>
R Call4(P1 p1, P2 p2, P3 p3, P4 p4) {
typedef R V8_CDECL FType(P1, P2, P3, P4);
VerifyParameters4<P1, P2, P3, P4>();
return DoCall<R>(FUNCTION_CAST<FType*>(Generate()), p1, p2, p3, p4);
}
template <typename R, typename C>
friend class CallHelper2;
Isolate* isolate_;
};
// TODO(dcarney): replace CallHelper with CallHelper2 and rename.
template <typename R, typename C>
class CallHelper2 {
public:
R Call() { return helper()->template Call0<R>(); }
template <typename P1>
R Call(P1 p1) {
return helper()->template Call1<R>(p1);
}
template <typename P1, typename P2>
R Call(P1 p1, P2 p2) {
return helper()->template Call2<R>(p1, p2);
}
template <typename P1, typename P2, typename P3>
R Call(P1 p1, P2 p2, P3 p3) {
return helper()->template Call3<R>(p1, p2, p3);
}
template <typename P1, typename P2, typename P3, typename P4>
R Call(P1 p1, P2 p2, P3 p3, P4 p4) {
return helper()->template Call4<R>(p1, p2, p3, p4);
}
private:
CallHelper* helper() { return static_cast<C*>(this); }
};
} // namespace compiler
} // namespace internal
} // namespace v8

View File

@ -17,38 +17,28 @@ namespace v8 {
namespace internal {
namespace compiler {
template <typename MachineAssembler>
class MachineAssemblerTester : public HandleAndZoneScope,
public CallHelper,
public MachineAssembler {
template <typename ReturnType>
class RawMachineAssemblerTester : public HandleAndZoneScope,
public CallHelper<ReturnType>,
public RawMachineAssembler {
public:
MachineAssemblerTester(MachineType return_type, MachineType p0,
MachineType p1, MachineType p2, MachineType p3,
MachineType p4,
MachineOperatorBuilder::Flags flags =
MachineOperatorBuilder::Flag::kNoFlags)
RawMachineAssemblerTester(MachineType p0 = kMachNone,
MachineType p1 = kMachNone,
MachineType p2 = kMachNone,
MachineType p3 = kMachNone,
MachineType p4 = kMachNone)
: HandleAndZoneScope(),
CallHelper(
CallHelper<ReturnType>(
main_isolate(),
MakeMachineSignature(main_zone(), return_type, p0, p1, p2, p3, p4)),
MachineAssembler(
MakeMachineSignature(
main_zone(), ReturnValueTraits<ReturnType>::Representation(),
p0, p1, p2, p3, p4)),
RawMachineAssembler(
main_isolate(), new (main_zone()) Graph(main_zone()),
MakeMachineSignature(main_zone(), return_type, p0, p1, p2, p3, p4),
kMachPtr, flags) {}
Node* LoadFromPointer(void* address, MachineType rep, int32_t offset = 0) {
return this->Load(rep, this->PointerConstant(address),
this->Int32Constant(offset));
}
void StoreToPointer(void* address, MachineType rep, Node* node) {
this->Store(rep, this->PointerConstant(address), node);
}
Node* StringConstant(const char* string) {
return this->HeapConstant(
this->isolate()->factory()->InternalizeUtf8String(string));
}
MakeMachineSignature(
main_zone(), ReturnValueTraits<ReturnType>::Representation(),
p0, p1, p2, p3, p4),
kMachPtr, InstructionSelector::SupportedMachineOperatorFlags()) {}
void CheckNumber(double expected, Object* number) {
CHECK(this->isolate()->factory()->NewNumber(expected)->SameValue(number));
@ -76,40 +66,26 @@ class MachineAssemblerTester : public HandleAndZoneScope,
private:
MaybeHandle<Code> code_;
};
// TODO(titzer): factor me elsewhere.
static MachineSignature* MakeMachineSignature(
Zone* zone, MachineType return_type, MachineType p0 = kMachNone,
MachineType p1 = kMachNone, MachineType p2 = kMachNone,
MachineType p3 = kMachNone, MachineType p4 = kMachNone) {
// 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;
template <typename ReturnType>
class RawMachineAssemblerTester
: public MachineAssemblerTester<RawMachineAssembler>,
public CallHelper2<ReturnType, RawMachineAssemblerTester<ReturnType> > {
public:
RawMachineAssemblerTester(MachineType p0 = kMachNone,
MachineType p1 = kMachNone,
MachineType p2 = kMachNone,
MachineType p3 = kMachNone,
MachineType p4 = kMachNone)
: MachineAssemblerTester<RawMachineAssembler>(
ReturnValueTraits<ReturnType>::Representation(), p0, p1, p2, p3, p4,
InstructionSelector::SupportedMachineOperatorFlags()) {}
template <typename Ci, typename Fn>
void Run(const Ci& ci, const Fn& fn) {
typename Ci::const_iterator i;
for (i = ci.begin(); i != ci.end(); ++i) {
CHECK_EQ(fn(*i), this->Call(*i));
}
}
template <typename Ci, typename Cj, typename Fn>
void Run(const Ci& ci, const Cj& cj, const Fn& fn) {
typename Ci::const_iterator i;
typename Cj::const_iterator j;
for (i = ci.begin(); i != ci.end(); ++i) {
for (j = cj.begin(); j != cj.end(); ++j) {
CHECK_EQ(fn(*i, *j), this->Call(*i, *j));
}
// 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 builder.Build();
}
};

View File

@ -39,12 +39,10 @@ class GraphAndBuilders {
template <typename ReturnType>
class GraphBuilderTester
: public HandleAndZoneScope,
private GraphAndBuilders,
public CallHelper,
public SimplifiedGraphBuilder,
public CallHelper2<ReturnType, GraphBuilderTester<ReturnType> > {
class GraphBuilderTester : public HandleAndZoneScope,
private GraphAndBuilders,
public CallHelper<ReturnType>,
public SimplifiedGraphBuilder {
public:
explicit GraphBuilderTester(MachineType p0 = kMachNone,
MachineType p1 = kMachNone,
@ -52,7 +50,7 @@ class GraphBuilderTester
MachineType p3 = kMachNone,
MachineType p4 = kMachNone)
: GraphAndBuilders(main_zone()),
CallHelper(
CallHelper<ReturnType>(
main_isolate(),
MakeMachineSignature(
main_zone(), ReturnValueTraits<ReturnType>::Representation(),
@ -79,7 +77,7 @@ class GraphBuilderTester
if (code_.is_null()) {
Zone* zone = graph()->zone();
CallDescriptor* desc =
Linkage::GetSimplifiedCDescriptor(zone, machine_sig_);
Linkage::GetSimplifiedCDescriptor(zone, this->machine_sig_);
code_ = Pipeline::GenerateCodeForTesting(main_isolate(), desc, graph());
}
return code_.ToHandleChecked()->entry();
@ -92,11 +90,34 @@ class GraphBuilderTester
}
}
size_t parameter_count() const { return machine_sig_->parameter_count(); }
size_t parameter_count() const {
return this->machine_sig_->parameter_count();
}
private:
Node** parameters_;
MaybeHandle<Code> code_;
// TODO(titzer): factor me elsewhere.
static MachineSignature* MakeMachineSignature(
Zone* zone, MachineType return_type, MachineType p0 = kMachNone,
MachineType p1 = kMachNone, MachineType p2 = kMachNone,
MachineType p3 = kMachNone, MachineType p4 = kMachNone) {
// 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 builder.Build();
}
};
} // namespace compiler

View File

@ -4395,7 +4395,7 @@ TEST(RunTestIntPtrArithmetic) {
RawMachineAssemblerTester<int32_t*> m;
Node* input = m.PointerConstant(&inputs[0]);
Node* output = m.PointerConstant(&outputs[kInputSize - 1]);
Node* elem_size = m.ConvertInt32ToIntPtr(m.Int32Constant(sizeof(inputs[0])));
Node* elem_size = m.IntPtrConstant(sizeof(inputs[0]));
for (int i = 0; i < kInputSize; i++) {
m.Store(kMachInt32, output, m.Load(kMachInt32, input));
input = m.IntPtrAdd(input, elem_size);