[cleanup] Refactor CSignature helper
The implementation can be greatly simplified by using variadic templates. R=mstarzinger@chromium.org Change-Id: I8dbeea3d570bf0fac83109f334c48dbe39aaa853 Reviewed-on: https://chromium-review.googlesource.com/859785 Commit-Queue: Clemens Hammacher <clemensh@chromium.org> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> Cr-Commit-Position: refs/heads/master@{#50611}
This commit is contained in:
parent
e97daee2e5
commit
6b909391fc
@ -28,18 +28,16 @@ namespace compiler {
|
|||||||
V(int*, MachineType::Pointer())
|
V(int*, MachineType::Pointer())
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline MachineType MachineTypeForC() {
|
inline constexpr MachineType MachineTypeForC() {
|
||||||
while (false) {
|
static_assert(std::is_convertible<T, Object*>::value,
|
||||||
// All other types T must be assignable to Object*
|
"all non-specialized types must be convertible to Object*");
|
||||||
*(static_cast<Object* volatile*>(0)) = static_cast<T>(0);
|
|
||||||
}
|
|
||||||
return MachineType::AnyTagged();
|
return MachineType::AnyTagged();
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DECLARE_TEMPLATE_SPECIALIZATION(ctype, mtype) \
|
#define DECLARE_TEMPLATE_SPECIALIZATION(ctype, mtype) \
|
||||||
template <> \
|
template <> \
|
||||||
inline MachineType MachineTypeForC<ctype>() { \
|
inline MachineType constexpr MachineTypeForC<ctype>() { \
|
||||||
return mtype; \
|
return mtype; \
|
||||||
}
|
}
|
||||||
FOREACH_CTYPE_MACHINE_TYPE_MAPPING(DECLARE_TEMPLATE_SPECIALIZATION)
|
FOREACH_CTYPE_MACHINE_TYPE_MAPPING(DECLARE_TEMPLATE_SPECIALIZATION)
|
||||||
#undef DECLARE_TEMPLATE_SPECIALIZATION
|
#undef DECLARE_TEMPLATE_SPECIALIZATION
|
||||||
@ -51,21 +49,13 @@ class CSignature : public MachineSignature {
|
|||||||
: MachineSignature(return_count, parameter_count, reps) {}
|
: MachineSignature(return_count, parameter_count, reps) {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template <typename P1 = void, typename P2 = void, typename P3 = void,
|
template <typename... Params>
|
||||||
typename P4 = void, typename P5 = void>
|
|
||||||
static void VerifyParams(MachineSignature* sig) {
|
static void VerifyParams(MachineSignature* sig) {
|
||||||
// Verifies the C signature against the machine types. Maximum {5} params.
|
// Verifies the C signature against the machine types.
|
||||||
CHECK_LT(sig->parameter_count(), 6u);
|
std::array<MachineType, sizeof...(Params)> params{
|
||||||
const int kMax = 5;
|
MachineTypeForC<Params>()...};
|
||||||
MachineType params[] = {MachineTypeForC<P1>(), MachineTypeForC<P2>(),
|
for (size_t p = 0; p < params.size(); ++p) {
|
||||||
MachineTypeForC<P3>(), MachineTypeForC<P4>(),
|
CHECK_EQ(sig->GetParam(p), params[p]);
|
||||||
MachineTypeForC<P5>()};
|
|
||||||
for (int p = kMax - 1; p >= 0; p--) {
|
|
||||||
if (p < static_cast<int>(sig->parameter_count())) {
|
|
||||||
CHECK_EQ(sig->GetParam(p), params[p]);
|
|
||||||
} else {
|
|
||||||
CHECK_EQ(MachineType::None(), params[p]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,96 +63,59 @@ class CSignature : public MachineSignature {
|
|||||||
return reinterpret_cast<CSignature*>(msig);
|
return reinterpret_cast<CSignature*>(msig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename... ParamMachineTypes>
|
||||||
static CSignature* New(Zone* zone, MachineType ret,
|
static CSignature* New(Zone* zone, MachineType ret,
|
||||||
MachineType p1 = MachineType::None(),
|
ParamMachineTypes... params) {
|
||||||
MachineType p2 = MachineType::None(),
|
constexpr size_t param_count = sizeof...(params);
|
||||||
MachineType p3 = MachineType::None(),
|
std::array<MachineType, param_count> param_arr{params...};
|
||||||
MachineType p4 = MachineType::None(),
|
const size_t buffer_size =
|
||||||
MachineType p5 = MachineType::None()) {
|
param_count + (ret == MachineType::None() ? 0 : 1);
|
||||||
MachineType* buffer = zone->NewArray<MachineType>(6);
|
MachineType* buffer = zone->NewArray<MachineType>(buffer_size);
|
||||||
int pos = 0;
|
size_t pos = 0;
|
||||||
size_t return_count = 0;
|
size_t return_count = 0;
|
||||||
if (ret != MachineType::None()) {
|
if (ret != MachineType::None()) {
|
||||||
buffer[pos++] = ret;
|
buffer[pos++] = ret;
|
||||||
return_count++;
|
return_count++;
|
||||||
}
|
}
|
||||||
buffer[pos++] = p1;
|
for (MachineType p : param_arr) {
|
||||||
buffer[pos++] = p2;
|
// Check that there are no MachineType::None()'s in the parameters.
|
||||||
buffer[pos++] = p3;
|
CHECK_NE(MachineType::None(), p);
|
||||||
buffer[pos++] = p4;
|
buffer[pos++] = p;
|
||||||
buffer[pos++] = p5;
|
|
||||||
size_t param_count = 5;
|
|
||||||
if (p5 == MachineType::None()) param_count--;
|
|
||||||
if (p4 == MachineType::None()) param_count--;
|
|
||||||
if (p3 == MachineType::None()) param_count--;
|
|
||||||
if (p2 == MachineType::None()) param_count--;
|
|
||||||
if (p1 == MachineType::None()) param_count--;
|
|
||||||
for (size_t i = 0; i < param_count; i++) {
|
|
||||||
// Check that there are no MachineType::None()'s in the middle of
|
|
||||||
// parameters.
|
|
||||||
CHECK_NE(MachineType::None(), buffer[return_count + i]);
|
|
||||||
}
|
}
|
||||||
|
DCHECK_EQ(buffer_size, pos);
|
||||||
return new (zone) CSignature(return_count, param_count, buffer);
|
return new (zone) CSignature(return_count, param_count, buffer);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template <typename Ret, uint16_t kParamCount>
|
|
||||||
class CSignatureOf : public CSignature {
|
|
||||||
protected:
|
|
||||||
MachineType storage_[1 + kParamCount];
|
|
||||||
|
|
||||||
CSignatureOf()
|
|
||||||
: CSignature(MachineTypeForC<Ret>() != MachineType::None() ? 1 : 0,
|
|
||||||
kParamCount, reinterpret_cast<MachineType*>(&storage_)) {
|
|
||||||
if (return_count_ == 1) storage_[0] = MachineTypeForC<Ret>();
|
|
||||||
}
|
|
||||||
void Set(int index, MachineType type) {
|
|
||||||
CHECK_LE(0, index);
|
|
||||||
CHECK_LT(index, kParamCount);
|
|
||||||
reps_[return_count_ + index] = type;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Helper classes for instantiating Signature objects to be callable from C.
|
// Helper classes for instantiating Signature objects to be callable from C.
|
||||||
template <typename Ret>
|
template <typename Ret, typename... Params>
|
||||||
class CSignature0 : public CSignatureOf<Ret, 0> {
|
class CSignatureOf : public CSignature {
|
||||||
public:
|
public:
|
||||||
CSignature0() : CSignatureOf<Ret, 0>() {}
|
CSignatureOf() : CSignature(kReturnCount, kParamCount, storage_) {
|
||||||
};
|
constexpr std::array<MachineType, kParamCount> param_types{
|
||||||
|
MachineTypeForC<Params>()...};
|
||||||
template <typename Ret, typename P1>
|
if (kReturnCount == 1) storage_[0] = MachineTypeForC<Ret>();
|
||||||
class CSignature1 : public CSignatureOf<Ret, 1> {
|
static_assert(
|
||||||
public:
|
std::is_same<decltype(*reps_), decltype(*param_types.data())>::value,
|
||||||
CSignature1() : CSignatureOf<Ret, 1>() {
|
"type mismatch, cannot memcpy");
|
||||||
this->Set(0, MachineTypeForC<P1>());
|
memcpy(storage_ + kReturnCount, param_types.data(),
|
||||||
|
sizeof(*storage_) * kParamCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static constexpr size_t kReturnCount =
|
||||||
|
MachineTypeForC<Ret>() == MachineType::None() ? 0 : 1;
|
||||||
|
static constexpr size_t kParamCount = sizeof...(Params);
|
||||||
|
|
||||||
|
MachineType storage_[kReturnCount + kParamCount];
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Ret, typename P1, typename P2>
|
typedef CSignatureOf<int32_t, int32_t, int32_t> CSignature_i_ii;
|
||||||
class CSignature2 : public CSignatureOf<Ret, 2> {
|
typedef CSignatureOf<uint32_t, uint32_t, uint32_t> CSignature_u_uu;
|
||||||
public:
|
typedef CSignatureOf<float, float, float> CSignature_f_ff;
|
||||||
CSignature2() : CSignatureOf<Ret, 2>() {
|
typedef CSignatureOf<double, double, double> CSignature_d_dd;
|
||||||
this->Set(0, MachineTypeForC<P1>());
|
typedef CSignatureOf<Object*, Object*, Object*> CSignature_o_oo;
|
||||||
this->Set(1, MachineTypeForC<P2>());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Ret, typename P1, typename P2, typename P3>
|
|
||||||
class CSignature3 : public CSignatureOf<Ret, 3> {
|
|
||||||
public:
|
|
||||||
CSignature3() : CSignatureOf<Ret, 3>() {
|
|
||||||
this->Set(0, MachineTypeForC<P1>());
|
|
||||||
this->Set(1, MachineTypeForC<P2>());
|
|
||||||
this->Set(2, MachineTypeForC<P3>());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef CSignature2<int32_t, int32_t, int32_t> CSignature_i_ii;
|
|
||||||
typedef CSignature2<uint32_t, uint32_t, uint32_t> CSignature_u_uu;
|
|
||||||
typedef CSignature2<float, float, float> CSignature_f_ff;
|
|
||||||
typedef CSignature2<double, double, double> CSignature_d_dd;
|
|
||||||
typedef CSignature2<Object*, Object*, Object*> CSignature_o_oo;
|
|
||||||
} // namespace compiler
|
} // namespace compiler
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace v8
|
} // namespace v8
|
||||||
|
@ -50,16 +50,12 @@ class GraphBuilderTester : public HandleAndZoneScope,
|
|||||||
public GraphAndBuilders,
|
public GraphAndBuilders,
|
||||||
public CallHelper<ReturnType> {
|
public CallHelper<ReturnType> {
|
||||||
public:
|
public:
|
||||||
explicit GraphBuilderTester(MachineType p0 = MachineType::None(),
|
template <typename... ParamMachTypes>
|
||||||
MachineType p1 = MachineType::None(),
|
explicit GraphBuilderTester(ParamMachTypes... p)
|
||||||
MachineType p2 = MachineType::None(),
|
|
||||||
MachineType p3 = MachineType::None(),
|
|
||||||
MachineType p4 = MachineType::None())
|
|
||||||
: GraphAndBuilders(main_zone()),
|
: GraphAndBuilders(main_zone()),
|
||||||
CallHelper<ReturnType>(
|
CallHelper<ReturnType>(
|
||||||
main_isolate(),
|
main_isolate(),
|
||||||
CSignature::New(main_zone(), MachineTypeForC<ReturnType>(), p0, p1,
|
CSignature::New(main_zone(), MachineTypeForC<ReturnType>(), p...)),
|
||||||
p2, p3, p4)),
|
|
||||||
effect_(nullptr),
|
effect_(nullptr),
|
||||||
return_(nullptr),
|
return_(nullptr),
|
||||||
parameters_(main_zone()->template NewArray<Node*>(parameter_count())) {
|
parameters_(main_zone()->template NewArray<Node*>(parameter_count())) {
|
||||||
@ -192,37 +188,10 @@ class GraphBuilderTester : public HandleAndZoneScope,
|
|||||||
return NewNode(simplified()->StoreElement(access), object, index, value);
|
return NewNode(simplified()->StoreElement(access), object, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Node* NewNode(const Operator* op) {
|
template <typename... NodePtrs>
|
||||||
return MakeNode(op, 0, static_cast<Node**>(nullptr));
|
Node* NewNode(const Operator* op, NodePtrs... n) {
|
||||||
}
|
std::array<Node*, sizeof...(n)> inputs{n...};
|
||||||
|
return MakeNode(op, inputs.size(), inputs.data());
|
||||||
Node* NewNode(const Operator* op, Node* n1) { return MakeNode(op, 1, &n1); }
|
|
||||||
|
|
||||||
Node* NewNode(const Operator* op, Node* n1, Node* n2) {
|
|
||||||
Node* buffer[] = {n1, n2};
|
|
||||||
return MakeNode(op, arraysize(buffer), buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3) {
|
|
||||||
Node* buffer[] = {n1, n2, n3};
|
|
||||||
return MakeNode(op, arraysize(buffer), buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4) {
|
|
||||||
Node* buffer[] = {n1, n2, n3, n4};
|
|
||||||
return MakeNode(op, arraysize(buffer), buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4,
|
|
||||||
Node* n5) {
|
|
||||||
Node* buffer[] = {n1, n2, n3, n4, n5};
|
|
||||||
return MakeNode(op, arraysize(buffer), buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4,
|
|
||||||
Node* n5, Node* n6) {
|
|
||||||
Node* nodes[] = {n1, n2, n3, n4, n5, n6};
|
|
||||||
return MakeNode(op, arraysize(nodes), nodes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Node* NewNode(const Operator* op, int value_input_count,
|
Node* NewNode(const Operator* op, int value_input_count,
|
||||||
|
@ -3524,8 +3524,10 @@ TEST(RunWord32EqualAndWord32ShrP) {
|
|||||||
|
|
||||||
TEST(RunDeadNodes) {
|
TEST(RunDeadNodes) {
|
||||||
for (int i = 0; true; i++) {
|
for (int i = 0; true; i++) {
|
||||||
RawMachineAssemblerTester<int32_t> m(i == 5 ? MachineType::Int32()
|
RawMachineAssemblerTester<int32_t> m_v;
|
||||||
: MachineType::None());
|
RawMachineAssemblerTester<int32_t> m_i(MachineType::Int32());
|
||||||
|
RawMachineAssemblerTester<int32_t>& m = i == 5 ? m_i : m_v;
|
||||||
|
|
||||||
int constant = 0x55 + i;
|
int constant = 0x55 + i;
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case 0:
|
case 0:
|
||||||
@ -6736,7 +6738,7 @@ TEST(RunComputedCodeObject) {
|
|||||||
|
|
||||||
// TODO(titzer): all this descriptor hackery is just to call the above
|
// TODO(titzer): all this descriptor hackery is just to call the above
|
||||||
// functions as code objects instead of direct addresses.
|
// functions as code objects instead of direct addresses.
|
||||||
CSignature0<int32_t> sig;
|
CSignatureOf<int32_t> sig;
|
||||||
CallDescriptor* c = Linkage::GetSimplifiedCDescriptor(r.zone(), &sig);
|
CallDescriptor* c = Linkage::GetSimplifiedCDescriptor(r.zone(), &sig);
|
||||||
LinkageLocation ret[] = {c->GetReturnLocation(0)};
|
LinkageLocation ret[] = {c->GetReturnLocation(0)};
|
||||||
Signature<LinkageLocation> loc(1, 0, ret);
|
Signature<LinkageLocation> loc(1, 0, ret);
|
||||||
|
@ -446,7 +446,7 @@ class Computer {
|
|||||||
inner = CompileGraph("Compute", desc, &graph, raw.Export());
|
inner = CompileGraph("Compute", desc, &graph, raw.Export());
|
||||||
}
|
}
|
||||||
|
|
||||||
CSignature0<int32_t> csig;
|
CSignatureOf<int32_t> csig;
|
||||||
ArgsBuffer<CType> io(num_params, seed);
|
ArgsBuffer<CType> io(num_params, seed);
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -583,7 +583,7 @@ static void CopyTwentyInt32(CallDescriptor* desc) {
|
|||||||
inner = CompileGraph("CopyTwentyInt32", desc, &graph, raw.Export());
|
inner = CompileGraph("CopyTwentyInt32", desc, &graph, raw.Export());
|
||||||
}
|
}
|
||||||
|
|
||||||
CSignature0<int32_t> csig;
|
CSignatureOf<int32_t> csig;
|
||||||
Handle<Code> wrapper = Handle<Code>::null();
|
Handle<Code> wrapper = Handle<Code>::null();
|
||||||
{
|
{
|
||||||
// Loads parameters from the input buffer and calls the above code.
|
// Loads parameters from the input buffer and calls the above code.
|
||||||
@ -1076,7 +1076,7 @@ void MixedParamTest(int start) {
|
|||||||
char bytes[kDoubleSize];
|
char bytes[kDoubleSize];
|
||||||
V8_ALIGNED(8) char output[kDoubleSize];
|
V8_ALIGNED(8) char output[kDoubleSize];
|
||||||
int expected_size = 0;
|
int expected_size = 0;
|
||||||
CSignature0<int32_t> csig;
|
CSignatureOf<int32_t> csig;
|
||||||
{
|
{
|
||||||
// Wrap the select code with a callable function that passes constants.
|
// Wrap the select code with a callable function that passes constants.
|
||||||
Zone zone(&allocator, ZONE_NAME);
|
Zone zone(&allocator, ZONE_NAME);
|
||||||
|
@ -40,7 +40,7 @@ TEST(WasmRelocationArmContextReference) {
|
|||||||
Handle<Code> code =
|
Handle<Code> code =
|
||||||
isolate->factory()->NewCode(desc, Code::STUB, Handle<Code>());
|
isolate->factory()->NewCode(desc, Code::STUB, Handle<Code>());
|
||||||
|
|
||||||
compiler::CSignature0<int32_t> csig;
|
compiler::CSignatureOf<int32_t> csig;
|
||||||
compiler::CodeRunner<int32_t> runnable(isolate, code, &csig);
|
compiler::CodeRunner<int32_t> runnable(isolate, code, &csig);
|
||||||
int32_t ret_value = runnable.Call();
|
int32_t ret_value = runnable.Call();
|
||||||
CHECK_EQ(ret_value, imm);
|
CHECK_EQ(ret_value, imm);
|
||||||
|
@ -45,7 +45,7 @@ TEST(WasmRelocationArm64ContextReference) {
|
|||||||
Handle<Code> code =
|
Handle<Code> code =
|
||||||
isolate->factory()->NewCode(desc, Code::STUB, Handle<Code>());
|
isolate->factory()->NewCode(desc, Code::STUB, Handle<Code>());
|
||||||
|
|
||||||
compiler::CSignature0<int64_t> csig;
|
compiler::CSignatureOf<int64_t> csig;
|
||||||
compiler::CodeRunner<int64_t> runnable(isolate, code, &csig);
|
compiler::CodeRunner<int64_t> runnable(isolate, code, &csig);
|
||||||
int64_t ret_value = runnable.Call();
|
int64_t ret_value = runnable.Call();
|
||||||
CHECK_EQ(ret_value, imm);
|
CHECK_EQ(ret_value, imm);
|
||||||
|
@ -40,7 +40,7 @@ TEST(WasmRelocationIa32ContextReference) {
|
|||||||
__ nop();
|
__ nop();
|
||||||
__ ret(0);
|
__ ret(0);
|
||||||
|
|
||||||
compiler::CSignature0<int32_t> csig;
|
compiler::CSignatureOf<int32_t> csig;
|
||||||
CodeDesc desc;
|
CodeDesc desc;
|
||||||
assm.GetCode(isolate, &desc);
|
assm.GetCode(isolate, &desc);
|
||||||
Handle<Code> code =
|
Handle<Code> code =
|
||||||
|
@ -43,7 +43,7 @@ TEST(WasmRelocationX64ContextReference) {
|
|||||||
isolate->factory()->NewCode(desc, Code::STUB, Handle<Code>());
|
isolate->factory()->NewCode(desc, Code::STUB, Handle<Code>());
|
||||||
USE(code);
|
USE(code);
|
||||||
|
|
||||||
CSignature0<int64_t> csig;
|
CSignatureOf<int64_t> csig;
|
||||||
CodeRunner<int64_t> runnable(isolate, code, &csig);
|
CodeRunner<int64_t> runnable(isolate, code, &csig);
|
||||||
int64_t ret_value = runnable.Call();
|
int64_t ret_value = runnable.Call();
|
||||||
CHECK_EQ(ret_value, imm);
|
CHECK_EQ(ret_value, imm);
|
||||||
|
Loading…
Reference in New Issue
Block a user