Index: test/cctest/compiler/compiler/call-tester.h |
diff --git a/test/cctest/compiler/compiler/call-tester.h b/test/cctest/compiler/compiler/call-tester.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..6998f1936ae2263f9549cecea5325567cc8eb4d9 |
--- /dev/null |
+++ b/test/cctest/compiler/compiler/call-tester.h |
@@ -0,0 +1,391 @@ |
+// Copyright 2014 the V8 project authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#ifndef V8_CCTEST_COMPILER_CALL_TESTER_H_ |
+#define V8_CCTEST_COMPILER_CALL_TESTER_H_ |
+ |
+#include "src/v8.h" |
+ |
+#include "src/simulator.h" |
+ |
+#if V8_TARGET_ARCH_IA32 |
+#if __GNUC__ |
+#define V8_CDECL __attribute__((cdecl)) |
+#else |
+#define V8_CDECL __cdecl |
+#endif |
+#else |
+#define V8_CDECL |
+#endif |
+ |
+namespace v8 { |
+namespace internal { |
+namespace compiler { |
+ |
+template <typename R> |
+struct ReturnValueTraits { |
+ static R Cast(uintptr_t r) { return reinterpret_cast<R>(r); } |
+ static MachineRepresentation Representation() { |
+ // TODO(dcarney): detect when R is of a subclass of Object* instead of this |
+ // type check. |
+ while (false) { |
+ *(static_cast<Object* volatile*>(0)) = static_cast<R>(0); |
+ } |
+ return kMachineTagged; |
+ } |
+}; |
+ |
+template <> |
+struct ReturnValueTraits<int32_t*> { |
+ static int32_t* Cast(uintptr_t r) { return reinterpret_cast<int32_t*>(r); } |
+ static MachineRepresentation Representation() { |
+ return MachineOperatorBuilder::pointer_rep(); |
+ } |
+}; |
+ |
+template <> |
+struct ReturnValueTraits<void> { |
+ static void Cast(uintptr_t r) {} |
+ static MachineRepresentation Representation() { |
+ return MachineOperatorBuilder::pointer_rep(); |
+ } |
+}; |
+ |
+template <> |
+struct ReturnValueTraits<bool> { |
+ static bool Cast(uintptr_t r) { return static_cast<bool>(r); } |
+ static MachineRepresentation Representation() { |
+ return MachineOperatorBuilder::pointer_rep(); |
+ } |
+}; |
+ |
+template <> |
+struct ReturnValueTraits<int32_t> { |
+ static int32_t Cast(uintptr_t r) { return static_cast<int32_t>(r); } |
+ static MachineRepresentation Representation() { return kMachineWord32; } |
+}; |
+ |
+template <> |
+struct ReturnValueTraits<uint32_t> { |
+ static uint32_t Cast(uintptr_t r) { return static_cast<uint32_t>(r); } |
+ static MachineRepresentation Representation() { return kMachineWord32; } |
+}; |
+ |
+template <> |
+struct ReturnValueTraits<int64_t> { |
+ static int64_t Cast(uintptr_t r) { return static_cast<int64_t>(r); } |
+ static MachineRepresentation Representation() { return kMachineWord64; } |
+}; |
+ |
+template <> |
+struct ReturnValueTraits<uint64_t> { |
+ static uint64_t Cast(uintptr_t r) { return static_cast<uint64_t>(r); } |
+ static MachineRepresentation Representation() { return kMachineWord64; } |
+}; |
+ |
+template <> |
+struct ReturnValueTraits<int16_t> { |
+ static int16_t Cast(uintptr_t r) { return static_cast<int16_t>(r); } |
+ static MachineRepresentation Representation() { |
+ return MachineOperatorBuilder::pointer_rep(); |
+ } |
+}; |
+ |
+template <> |
+struct ReturnValueTraits<int8_t> { |
+ static int8_t Cast(uintptr_t r) { return static_cast<int8_t>(r); } |
+ static MachineRepresentation Representation() { |
+ return MachineOperatorBuilder::pointer_rep(); |
+ } |
+}; |
+ |
+template <> |
+struct ReturnValueTraits<double> { |
+ static double Cast(uintptr_t r) { |
+ UNREACHABLE(); |
+ return 0.0; |
+ } |
+}; |
+ |
+ |
+template <typename R> |
+struct ParameterTraits { |
+ static uintptr_t Cast(R r) { return static_cast<uintptr_t>(r); } |
+}; |
+ |
+template <> |
+struct ParameterTraits<int*> { |
+ static uintptr_t Cast(int* r) { return reinterpret_cast<uintptr_t>(r); } |
+}; |
+ |
+template <typename T> |
+struct ParameterTraits<T*> { |
+ static uintptr_t Cast(void* r) { return reinterpret_cast<uintptr_t>(r); } |
+}; |
+ |
+class CallHelper { |
+ public: |
+ explicit CallHelper(Isolate* isolate) : isolate_(isolate) { USE(isolate_); } |
+ virtual ~CallHelper() {} |
+ |
+ static MachineCallDescriptorBuilder* ToCallDescriptorBuilder( |
+ Zone* zone, MachineRepresentation return_type, |
+ MachineRepresentation p0 = kMachineLast, |
+ MachineRepresentation p1 = kMachineLast, |
+ MachineRepresentation p2 = kMachineLast, |
+ MachineRepresentation p3 = kMachineLast, |
+ MachineRepresentation p4 = kMachineLast) { |
+ const int kSize = 5; |
+ MachineRepresentation* params = |
+ zone->NewArray<MachineRepresentation>(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] == kMachineLast) { |
+ break; |
+ } |
+ parameter_count++; |
+ } |
+ return new (zone) |
+ MachineCallDescriptorBuilder(return_type, parameter_count, params); |
+ } |
+ |
+ protected: |
+ virtual void VerifyParameters(int parameter_count, |
+ MachineRepresentation* parameters) = 0; |
+ virtual byte* Generate() = 0; |
+ |
+ private: |
+#if USE_SIMULATOR && V8_TARGET_ARCH_ARM64 |
+ uintptr_t CallSimulator(byte* f, Simulator::CallArgument* args) { |
+ Simulator* simulator = Simulator::current(isolate_); |
+ return static_cast<uintptr_t>(simulator->CallInt64(f, args)); |
+ } |
+ |
+ template <typename R, 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> |
+ 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> |
+ 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> |
+ 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> |
+ R DoCall(F* f, P1 p1, P2 p2, P3 p3, P4 p4) { |
+ Simulator::CallArgument args[] = { |
+ Simulator::CallArgument(p1), Simulator::CallArgument(p2), |
+ Simulator::CallArgument(p3), Simulator::CallArgument(p4), |
+ Simulator::CallArgument::End()}; |
+ return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f), args)); |
+ } |
+#elif USE_SIMULATOR && V8_TARGET_ARCH_ARM |
+ uintptr_t CallSimulator(byte* f, int32_t p1 = 0, int32_t p2 = 0, |
+ int32_t p3 = 0, int32_t p4 = 0) { |
+ Simulator* simulator = Simulator::current(isolate_); |
+ return static_cast<uintptr_t>(simulator->Call(f, 4, p1, p2, p3, p4)); |
+ } |
+ template <typename R, typename F> |
+ R DoCall(F* f) { |
+ return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f))); |
+ } |
+ template <typename R, 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> |
+ 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> |
+ 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> |
+ R DoCall(F* f, P1 p1, P2 p2, P3 p3, P4 p4) { |
+ return ReturnValueTraits<R>::Cast(CallSimulator( |
+ FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1), |
+ ParameterTraits<P2>::Cast(p2), ParameterTraits<P3>::Cast(p3), |
+ ParameterTraits<P4>::Cast(p4))); |
+ } |
+#else |
+ template <typename R, typename F> |
+ R DoCall(F* f) { |
+ return f(); |
+ } |
+ template <typename R, typename F, typename P1> |
+ R DoCall(F* f, P1 p1) { |
+ return f(p1); |
+ } |
+ template <typename R, 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> |
+ 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> |
+ R DoCall(F* f, P1 p1, P2 p2, P3 p3, P4 p4) { |
+ return f(p1, p2, p3, p4); |
+ } |
+#endif |
+ |
+#ifndef DEBUG |
+ void VerifyParameters0() {} |
+ |
+ template <typename P1> |
+ void VerifyParameters1() {} |
+ |
+ template <typename P1, typename P2> |
+ void VerifyParameters2() {} |
+ |
+ template <typename P1, typename P2, typename P3> |
+ void VerifyParameters3() {} |
+ |
+ template <typename P1, typename P2, typename P3, typename P4> |
+ void VerifyParameters4() {} |
+#else |
+ void VerifyParameters0() { VerifyParameters(0, NULL); } |
+ |
+ template <typename P1> |
+ void VerifyParameters1() { |
+ MachineRepresentation parameters[] = { |
+ ReturnValueTraits<P1>::Representation()}; |
+ VerifyParameters(ARRAY_SIZE(parameters), parameters); |
+ } |
+ |
+ template <typename P1, typename P2> |
+ void VerifyParameters2() { |
+ MachineRepresentation parameters[] = { |
+ ReturnValueTraits<P1>::Representation(), |
+ ReturnValueTraits<P2>::Representation()}; |
+ VerifyParameters(ARRAY_SIZE(parameters), parameters); |
+ } |
+ |
+ template <typename P1, typename P2, typename P3> |
+ void VerifyParameters3() { |
+ MachineRepresentation parameters[] = { |
+ ReturnValueTraits<P1>::Representation(), |
+ ReturnValueTraits<P2>::Representation(), |
+ ReturnValueTraits<P3>::Representation()}; |
+ VerifyParameters(ARRAY_SIZE(parameters), parameters); |
+ } |
+ |
+ template <typename P1, typename P2, typename P3, typename P4> |
+ void VerifyParameters4() { |
+ MachineRepresentation parameters[] = { |
+ ReturnValueTraits<P1>::Representation(), |
+ ReturnValueTraits<P2>::Representation(), |
+ ReturnValueTraits<P3>::Representation(), |
+ ReturnValueTraits<P4>::Representation()}; |
+ VerifyParameters(ARRAY_SIZE(parameters), parameters); |
+ } |
+#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 |
+ |
+#endif // V8_CCTEST_COMPILER_CALL_TESTER_H_ |