deps: update v8 to 4.3.61.21
[platform/upstream/nodejs.git] / deps / v8 / test / cctest / compiler / call-tester.h
1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef V8_CCTEST_COMPILER_CALL_TESTER_H_
6 #define V8_CCTEST_COMPILER_CALL_TESTER_H_
7
8 #include "src/v8.h"
9
10 #include "src/simulator.h"
11
12 #if V8_TARGET_ARCH_IA32
13 #if __GNUC__
14 #define V8_CDECL __attribute__((cdecl))
15 #else
16 #define V8_CDECL __cdecl
17 #endif
18 #else
19 #define V8_CDECL
20 #endif
21
22 namespace v8 {
23 namespace internal {
24 namespace compiler {
25
26 // TODO(titzer): use c-signature.h instead of ReturnValueTraits
27 template <typename R>
28 struct ReturnValueTraits {
29   static R Cast(uintptr_t r) { return reinterpret_cast<R>(r); }
30   static MachineType Representation() {
31     // TODO(dcarney): detect when R is of a subclass of Object* instead of this
32     // type check.
33     while (false) {
34       *(static_cast<Object* volatile*>(0)) = static_cast<R>(0);
35     }
36     return kMachAnyTagged;
37   }
38 };
39
40 template <>
41 struct ReturnValueTraits<int32_t*> {
42   static int32_t* Cast(uintptr_t r) { return reinterpret_cast<int32_t*>(r); }
43   static MachineType Representation() { return kMachPtr; }
44 };
45
46 template <>
47 struct ReturnValueTraits<void> {
48   static void Cast(uintptr_t r) {}
49   static MachineType Representation() { return kMachPtr; }
50 };
51
52 template <>
53 struct ReturnValueTraits<bool> {
54   static bool Cast(uintptr_t r) { return static_cast<bool>(r); }
55   static MachineType Representation() { return kRepBit; }
56 };
57
58 template <>
59 struct ReturnValueTraits<int32_t> {
60   static int32_t Cast(uintptr_t r) { return static_cast<int32_t>(r); }
61   static MachineType Representation() { return kMachInt32; }
62 };
63
64 template <>
65 struct ReturnValueTraits<uint32_t> {
66   static uint32_t Cast(uintptr_t r) { return static_cast<uint32_t>(r); }
67   static MachineType Representation() { return kMachUint32; }
68 };
69
70 template <>
71 struct ReturnValueTraits<int64_t> {
72   static int64_t Cast(uintptr_t r) { return static_cast<int64_t>(r); }
73   static MachineType Representation() { return kMachInt64; }
74 };
75
76 template <>
77 struct ReturnValueTraits<uint64_t> {
78   static uint64_t Cast(uintptr_t r) { return static_cast<uint64_t>(r); }
79   static MachineType Representation() { return kMachUint64; }
80 };
81
82 template <>
83 struct ReturnValueTraits<int16_t> {
84   static int16_t Cast(uintptr_t r) { return static_cast<int16_t>(r); }
85   static MachineType Representation() { return kMachInt16; }
86 };
87
88 template <>
89 struct ReturnValueTraits<uint16_t> {
90   static uint16_t Cast(uintptr_t r) { return static_cast<uint16_t>(r); }
91   static MachineType Representation() { return kMachUint16; }
92 };
93
94 template <>
95 struct ReturnValueTraits<int8_t> {
96   static int8_t Cast(uintptr_t r) { return static_cast<int8_t>(r); }
97   static MachineType Representation() { return kMachInt8; }
98 };
99
100 template <>
101 struct ReturnValueTraits<uint8_t> {
102   static uint8_t Cast(uintptr_t r) { return static_cast<uint8_t>(r); }
103   static MachineType Representation() { return kMachUint8; }
104 };
105
106 template <>
107 struct ReturnValueTraits<double> {
108   static double Cast(uintptr_t r) {
109     UNREACHABLE();
110     return 0.0;
111   }
112   static MachineType Representation() { return kMachFloat64; }
113 };
114
115
116 template <typename R>
117 struct ParameterTraits {
118   static uintptr_t Cast(R r) { return static_cast<uintptr_t>(r); }
119 };
120
121 template <>
122 struct ParameterTraits<int*> {
123   static uintptr_t Cast(int* r) { return reinterpret_cast<uintptr_t>(r); }
124 };
125
126 template <typename T>
127 struct ParameterTraits<T*> {
128   static uintptr_t Cast(void* r) { return reinterpret_cast<uintptr_t>(r); }
129 };
130
131 // Additional template specialization required for mips64 to sign-extend
132 // parameters defined by calling convention.
133 template <>
134 struct ParameterTraits<int32_t> {
135   static int64_t Cast(int32_t r) { return static_cast<int64_t>(r); }
136 };
137
138 template <>
139 struct ParameterTraits<uint32_t> {
140   static int64_t Cast(uint32_t r) {
141     return static_cast<int64_t>(static_cast<int32_t>(r));
142   }
143 };
144
145 class CallHelper {
146  public:
147   explicit CallHelper(Isolate* isolate, MachineSignature* machine_sig)
148       : machine_sig_(machine_sig), isolate_(isolate) {
149     USE(isolate_);
150   }
151   virtual ~CallHelper() {}
152
153   static MachineSignature* MakeMachineSignature(
154       Zone* zone, MachineType return_type, MachineType p0 = kMachNone,
155       MachineType p1 = kMachNone, MachineType p2 = kMachNone,
156       MachineType p3 = kMachNone, MachineType p4 = kMachNone) {
157     // Count the number of parameters.
158     size_t param_count = 5;
159     MachineType types[] = {p0, p1, p2, p3, p4};
160     while (param_count > 0 && types[param_count - 1] == kMachNone)
161       param_count--;
162     size_t return_count = return_type == kMachNone ? 0 : 1;
163
164     // Build the machine signature.
165     MachineSignature::Builder builder(zone, return_count, param_count);
166     if (return_count > 0) builder.AddReturn(return_type);
167     for (size_t i = 0; i < param_count; i++) {
168       builder.AddParam(types[i]);
169     }
170     return builder.Build();
171   }
172
173  protected:
174   MachineSignature* machine_sig_;
175   void VerifyParameters(size_t parameter_count, MachineType* parameter_types) {
176     CHECK(machine_sig_->parameter_count() == parameter_count);
177     for (size_t i = 0; i < parameter_count; i++) {
178       CHECK_EQ(machine_sig_->GetParam(i), parameter_types[i]);
179     }
180   }
181   virtual byte* Generate() = 0;
182
183  private:
184 #if USE_SIMULATOR && V8_TARGET_ARCH_ARM64
185   uintptr_t CallSimulator(byte* f, Simulator::CallArgument* args) {
186     Simulator* simulator = Simulator::current(isolate_);
187     return static_cast<uintptr_t>(simulator->CallInt64(f, args));
188   }
189
190   template <typename R, typename F>
191   R DoCall(F* f) {
192     Simulator::CallArgument args[] = {Simulator::CallArgument::End()};
193     return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f), args));
194   }
195   template <typename R, typename F, typename P1>
196   R DoCall(F* f, P1 p1) {
197     Simulator::CallArgument args[] = {Simulator::CallArgument(p1),
198                                       Simulator::CallArgument::End()};
199     return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f), args));
200   }
201   template <typename R, typename F, typename P1, typename P2>
202   R DoCall(F* f, P1 p1, P2 p2) {
203     Simulator::CallArgument args[] = {Simulator::CallArgument(p1),
204                                       Simulator::CallArgument(p2),
205                                       Simulator::CallArgument::End()};
206     return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f), args));
207   }
208   template <typename R, typename F, typename P1, typename P2, typename P3>
209   R DoCall(F* f, P1 p1, P2 p2, P3 p3) {
210     Simulator::CallArgument args[] = {
211         Simulator::CallArgument(p1), Simulator::CallArgument(p2),
212         Simulator::CallArgument(p3), Simulator::CallArgument::End()};
213     return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f), args));
214   }
215   template <typename R, typename F, typename P1, typename P2, typename P3,
216             typename P4>
217   R DoCall(F* f, P1 p1, P2 p2, P3 p3, P4 p4) {
218     Simulator::CallArgument args[] = {
219         Simulator::CallArgument(p1), Simulator::CallArgument(p2),
220         Simulator::CallArgument(p3), Simulator::CallArgument(p4),
221         Simulator::CallArgument::End()};
222     return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f), args));
223   }
224 #elif USE_SIMULATOR && (V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_PPC64)
225   uintptr_t CallSimulator(byte* f, int64_t p1 = 0, int64_t p2 = 0,
226                           int64_t p3 = 0, int64_t p4 = 0) {
227     Simulator* simulator = Simulator::current(isolate_);
228     return static_cast<uintptr_t>(simulator->Call(f, 4, p1, p2, p3, p4));
229   }
230
231
232   template <typename R, typename F>
233   R DoCall(F* f) {
234     return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f)));
235   }
236   template <typename R, typename F, typename P1>
237   R DoCall(F* f, P1 p1) {
238     return ReturnValueTraits<R>::Cast(
239         CallSimulator(FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1)));
240   }
241   template <typename R, typename F, typename P1, typename P2>
242   R DoCall(F* f, P1 p1, P2 p2) {
243     return ReturnValueTraits<R>::Cast(
244         CallSimulator(FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1),
245                       ParameterTraits<P2>::Cast(p2)));
246   }
247   template <typename R, typename F, typename P1, typename P2, typename P3>
248   R DoCall(F* f, P1 p1, P2 p2, P3 p3) {
249     return ReturnValueTraits<R>::Cast(CallSimulator(
250         FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1),
251         ParameterTraits<P2>::Cast(p2), ParameterTraits<P3>::Cast(p3)));
252   }
253   template <typename R, typename F, typename P1, typename P2, typename P3,
254             typename P4>
255   R DoCall(F* f, P1 p1, P2 p2, P3 p3, P4 p4) {
256     return ReturnValueTraits<R>::Cast(CallSimulator(
257         FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1),
258         ParameterTraits<P2>::Cast(p2), ParameterTraits<P3>::Cast(p3),
259         ParameterTraits<P4>::Cast(p4)));
260   }
261 #elif USE_SIMULATOR && \
262     (V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_PPC)
263   uintptr_t CallSimulator(byte* f, int32_t p1 = 0, int32_t p2 = 0,
264                           int32_t p3 = 0, int32_t p4 = 0) {
265     Simulator* simulator = Simulator::current(isolate_);
266     return static_cast<uintptr_t>(simulator->Call(f, 4, p1, p2, p3, p4));
267   }
268   template <typename R, typename F>
269   R DoCall(F* f) {
270     return ReturnValueTraits<R>::Cast(CallSimulator(FUNCTION_ADDR(f)));
271   }
272   template <typename R, typename F, typename P1>
273   R DoCall(F* f, P1 p1) {
274     return ReturnValueTraits<R>::Cast(
275         CallSimulator(FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1)));
276   }
277   template <typename R, typename F, typename P1, typename P2>
278   R DoCall(F* f, P1 p1, P2 p2) {
279     return ReturnValueTraits<R>::Cast(
280         CallSimulator(FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1),
281                       ParameterTraits<P2>::Cast(p2)));
282   }
283   template <typename R, typename F, typename P1, typename P2, typename P3>
284   R DoCall(F* f, P1 p1, P2 p2, P3 p3) {
285     return ReturnValueTraits<R>::Cast(CallSimulator(
286         FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1),
287         ParameterTraits<P2>::Cast(p2), ParameterTraits<P3>::Cast(p3)));
288   }
289   template <typename R, typename F, typename P1, typename P2, typename P3,
290             typename P4>
291   R DoCall(F* f, P1 p1, P2 p2, P3 p3, P4 p4) {
292     return ReturnValueTraits<R>::Cast(CallSimulator(
293         FUNCTION_ADDR(f), ParameterTraits<P1>::Cast(p1),
294         ParameterTraits<P2>::Cast(p2), ParameterTraits<P3>::Cast(p3),
295         ParameterTraits<P4>::Cast(p4)));
296   }
297 #else
298   template <typename R, typename F>
299   R DoCall(F* f) {
300     return f();
301   }
302   template <typename R, typename F, typename P1>
303   R DoCall(F* f, P1 p1) {
304     return f(p1);
305   }
306   template <typename R, typename F, typename P1, typename P2>
307   R DoCall(F* f, P1 p1, P2 p2) {
308     return f(p1, p2);
309   }
310   template <typename R, typename F, typename P1, typename P2, typename P3>
311   R DoCall(F* f, P1 p1, P2 p2, P3 p3) {
312     return f(p1, p2, p3);
313   }
314   template <typename R, typename F, typename P1, typename P2, typename P3,
315             typename P4>
316   R DoCall(F* f, P1 p1, P2 p2, P3 p3, P4 p4) {
317     return f(p1, p2, p3, p4);
318   }
319 #endif
320
321 #ifndef DEBUG
322   void VerifyParameters0() {}
323
324   template <typename P1>
325   void VerifyParameters1() {}
326
327   template <typename P1, typename P2>
328   void VerifyParameters2() {}
329
330   template <typename P1, typename P2, typename P3>
331   void VerifyParameters3() {}
332
333   template <typename P1, typename P2, typename P3, typename P4>
334   void VerifyParameters4() {}
335 #else
336   void VerifyParameters0() { VerifyParameters(0, NULL); }
337
338   template <typename P1>
339   void VerifyParameters1() {
340     MachineType parameters[] = {ReturnValueTraits<P1>::Representation()};
341     VerifyParameters(arraysize(parameters), parameters);
342   }
343
344   template <typename P1, typename P2>
345   void VerifyParameters2() {
346     MachineType parameters[] = {ReturnValueTraits<P1>::Representation(),
347                                 ReturnValueTraits<P2>::Representation()};
348     VerifyParameters(arraysize(parameters), parameters);
349   }
350
351   template <typename P1, typename P2, typename P3>
352   void VerifyParameters3() {
353     MachineType parameters[] = {ReturnValueTraits<P1>::Representation(),
354                                 ReturnValueTraits<P2>::Representation(),
355                                 ReturnValueTraits<P3>::Representation()};
356     VerifyParameters(arraysize(parameters), parameters);
357   }
358
359   template <typename P1, typename P2, typename P3, typename P4>
360   void VerifyParameters4() {
361     MachineType parameters[] = {ReturnValueTraits<P1>::Representation(),
362                                 ReturnValueTraits<P2>::Representation(),
363                                 ReturnValueTraits<P3>::Representation(),
364                                 ReturnValueTraits<P4>::Representation()};
365     VerifyParameters(arraysize(parameters), parameters);
366   }
367 #endif
368
369   // TODO(dcarney): replace Call() in CallHelper2 with these.
370   template <typename R>
371   R Call0() {
372     typedef R V8_CDECL FType();
373     VerifyParameters0();
374     return DoCall<R>(FUNCTION_CAST<FType*>(Generate()));
375   }
376
377   template <typename R, typename P1>
378   R Call1(P1 p1) {
379     typedef R V8_CDECL FType(P1);
380     VerifyParameters1<P1>();
381     return DoCall<R>(FUNCTION_CAST<FType*>(Generate()), p1);
382   }
383
384   template <typename R, typename P1, typename P2>
385   R Call2(P1 p1, P2 p2) {
386     typedef R V8_CDECL FType(P1, P2);
387     VerifyParameters2<P1, P2>();
388     return DoCall<R>(FUNCTION_CAST<FType*>(Generate()), p1, p2);
389   }
390
391   template <typename R, typename P1, typename P2, typename P3>
392   R Call3(P1 p1, P2 p2, P3 p3) {
393     typedef R V8_CDECL FType(P1, P2, P3);
394     VerifyParameters3<P1, P2, P3>();
395     return DoCall<R>(FUNCTION_CAST<FType*>(Generate()), p1, p2, p3);
396   }
397
398   template <typename R, typename P1, typename P2, typename P3, typename P4>
399   R Call4(P1 p1, P2 p2, P3 p3, P4 p4) {
400     typedef R V8_CDECL FType(P1, P2, P3, P4);
401     VerifyParameters4<P1, P2, P3, P4>();
402     return DoCall<R>(FUNCTION_CAST<FType*>(Generate()), p1, p2, p3, p4);
403   }
404
405   template <typename R, typename C>
406   friend class CallHelper2;
407   Isolate* isolate_;
408 };
409
410
411 // TODO(dcarney): replace CallHelper with CallHelper2 and rename.
412 template <typename R, typename C>
413 class CallHelper2 {
414  public:
415   R Call() { return helper()->template Call0<R>(); }
416
417   template <typename P1>
418   R Call(P1 p1) {
419     return helper()->template Call1<R>(p1);
420   }
421
422   template <typename P1, typename P2>
423   R Call(P1 p1, P2 p2) {
424     return helper()->template Call2<R>(p1, p2);
425   }
426
427   template <typename P1, typename P2, typename P3>
428   R Call(P1 p1, P2 p2, P3 p3) {
429     return helper()->template Call3<R>(p1, p2, p3);
430   }
431
432   template <typename P1, typename P2, typename P3, typename P4>
433   R Call(P1 p1, P2 p2, P3 p3, P4 p4) {
434     return helper()->template Call4<R>(p1, p2, p3, p4);
435   }
436
437  private:
438   CallHelper* helper() { return static_cast<C*>(this); }
439 };
440
441 }  // namespace compiler
442 }  // namespace internal
443 }  // namespace v8
444
445 #endif  // V8_CCTEST_COMPILER_CALL_TESTER_H_