1 // Copyright 2015 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 #include <stdint.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 
10 #include "include/v8-function.h"
11 #include "src/api/api-inl.h"
12 #include "src/codegen/assembler-inl.h"
13 #include "src/objects/heap-number-inl.h"
14 #include "test/cctest/cctest.h"
15 #include "test/cctest/compiler/value-helper.h"
16 #include "test/cctest/wasm/wasm-run-utils.h"
17 #include "test/common/wasm/test-signatures.h"
18 #include "test/common/wasm/wasm-macro-gen.h"
19 
20 namespace v8 {
21 namespace internal {
22 namespace wasm {
23 
24 namespace {
25 // A helper for generating predictable but unique argument values that
26 // are easy to debug (e.g. with misaligned stacks).
27 class PredictableInputValues {
28  public:
29   int base_;
PredictableInputValues(int base)30   explicit PredictableInputValues(int base) : base_(base) {}
arg_d(int which)31   double arg_d(int which) { return base_ * which + ((which & 1) * 0.5); }
arg_f(int which)32   float arg_f(int which) { return base_ * which + ((which & 1) * 0.25); }
arg_i(int which)33   int32_t arg_i(int which) { return base_ * which + ((which & 1) * kMinInt); }
arg_l(int which)34   int64_t arg_l(int which) {
35     return base_ * which + ((which & 1) * (0x04030201LL << 32));
36   }
37 };
38 
CreateJSSelector(FunctionSig * sig,int which)39 ManuallyImportedJSFunction CreateJSSelector(FunctionSig* sig, int which) {
40   const int kMaxParams = 11;
41   static const char* formals[kMaxParams] = {"",
42                                             "a",
43                                             "a,b",
44                                             "a,b,c",
45                                             "a,b,c,d",
46                                             "a,b,c,d,e",
47                                             "a,b,c,d,e,f",
48                                             "a,b,c,d,e,f,g",
49                                             "a,b,c,d,e,f,g,h",
50                                             "a,b,c,d,e,f,g,h,i",
51                                             "a,b,c,d,e,f,g,h,i,j"};
52   CHECK_LT(which, static_cast<int>(sig->parameter_count()));
53   CHECK_LT(static_cast<int>(sig->parameter_count()), kMaxParams);
54 
55   base::EmbeddedVector<char, 256> source;
56   char param = 'a' + which;
57   SNPrintF(source, "(function(%s) { return %c; })",
58            formals[sig->parameter_count()], param);
59 
60   Handle<JSFunction> js_function =
61       Handle<JSFunction>::cast(v8::Utils::OpenHandle(
62           *v8::Local<v8::Function>::Cast(CompileRun(source.begin()))));
63   ManuallyImportedJSFunction import = {sig, js_function};
64 
65   return import;
66 }
67 }  // namespace
68 
WASM_COMPILED_EXEC_TEST(Run_Int32Sub_jswrapped)69 WASM_COMPILED_EXEC_TEST(Run_Int32Sub_jswrapped) {
70   WasmRunner<int, int, int> r(execution_tier);
71   BUILD(r, WASM_I32_SUB(WASM_LOCAL_GET(0), WASM_LOCAL_GET(1)));
72 
73   r.CheckCallViaJS(33, 44, 11);
74   r.CheckCallViaJS(-8723487, -8000000, 723487);
75 }
76 
WASM_COMPILED_EXEC_TEST(Run_Float32Div_jswrapped)77 WASM_COMPILED_EXEC_TEST(Run_Float32Div_jswrapped) {
78   WasmRunner<float, float, float> r(execution_tier);
79   BUILD(r, WASM_F32_DIV(WASM_LOCAL_GET(0), WASM_LOCAL_GET(1)));
80 
81   r.CheckCallViaJS(92, 46, 0.5);
82   r.CheckCallViaJS(64, -16, -0.25);
83 }
84 
WASM_COMPILED_EXEC_TEST(Run_Float64Add_jswrapped)85 WASM_COMPILED_EXEC_TEST(Run_Float64Add_jswrapped) {
86   WasmRunner<double, double, double> r(execution_tier);
87   BUILD(r, WASM_F64_ADD(WASM_LOCAL_GET(0), WASM_LOCAL_GET(1)));
88 
89   r.CheckCallViaJS(3, 2, 1);
90   r.CheckCallViaJS(-5.5, -5.25, -0.25);
91 }
92 
WASM_COMPILED_EXEC_TEST(Run_I32Popcount_jswrapped)93 WASM_COMPILED_EXEC_TEST(Run_I32Popcount_jswrapped) {
94   WasmRunner<int, int> r(execution_tier);
95   BUILD(r, WASM_I32_POPCNT(WASM_LOCAL_GET(0)));
96 
97   r.CheckCallViaJS(2, 9);
98   r.CheckCallViaJS(3, 11);
99   r.CheckCallViaJS(6, 0x3F);
100 }
101 
WASM_COMPILED_EXEC_TEST(Run_CallJS_Add_jswrapped)102 WASM_COMPILED_EXEC_TEST(Run_CallJS_Add_jswrapped) {
103   TestSignatures sigs;
104   HandleScope scope(CcTest::InitIsolateOnce());
105   const char* source = "(function(a) { return a + 99; })";
106   Handle<JSFunction> js_function =
107       Handle<JSFunction>::cast(v8::Utils::OpenHandle(
108           *v8::Local<v8::Function>::Cast(CompileRun(source))));
109   ManuallyImportedJSFunction import = {sigs.i_i(), js_function};
110   WasmRunner<int, int> r(execution_tier, &import);
111   uint32_t js_index = 0;
112   BUILD(r, WASM_CALL_FUNCTION(js_index, WASM_LOCAL_GET(0)));
113 
114   r.CheckCallViaJS(101, 2);
115   r.CheckCallViaJS(199, 100);
116   r.CheckCallViaJS(-666666801, -666666900);
117 }
118 
WASM_COMPILED_EXEC_TEST(Run_IndirectCallJSFunction)119 WASM_COMPILED_EXEC_TEST(Run_IndirectCallJSFunction) {
120   Isolate* isolate = CcTest::InitIsolateOnce();
121   HandleScope scope(isolate);
122   TestSignatures sigs;
123 
124   const char* source = "(function(a, b, c) { if(c) return a; return b; })";
125   Handle<JSFunction> js_function =
126       Handle<JSFunction>::cast(v8::Utils::OpenHandle(
127           *v8::Local<v8::Function>::Cast(CompileRun(source))));
128 
129   ManuallyImportedJSFunction import = {sigs.i_iii(), js_function};
130 
131   WasmRunner<int32_t, int32_t> r(execution_tier, &import);
132 
133   const uint32_t js_index = 0;
134   const int32_t left = -2;
135   const int32_t right = 3;
136 
137   WasmFunctionCompiler& rc_fn = r.NewFunction(sigs.i_i(), "rc");
138 
139   byte sig_index = r.builder().AddSignature(sigs.i_iii());
140   uint16_t indirect_function_table[] = {static_cast<uint16_t>(js_index)};
141 
142   r.builder().AddIndirectFunctionTable(indirect_function_table,
143                                        arraysize(indirect_function_table));
144 
145   BUILD(rc_fn, WASM_CALL_INDIRECT(sig_index, WASM_I32V(left), WASM_I32V(right),
146                                   WASM_LOCAL_GET(0), WASM_I32V(js_index)));
147 
148   Handle<Object> args_left[] = {isolate->factory()->NewNumber(1)};
149   r.CheckCallApplyViaJS(left, rc_fn.function_index(), args_left, 1);
150 
151   Handle<Object> args_right[] = {isolate->factory()->NewNumber(0)};
152   r.CheckCallApplyViaJS(right, rc_fn.function_index(), args_right, 1);
153 }
154 
RunJSSelectTest(TestExecutionTier tier,int which)155 void RunJSSelectTest(TestExecutionTier tier, int which) {
156   const int kMaxParams = 8;
157   PredictableInputValues inputs(0x100);
158   ValueType type = kWasmF64;
159   ValueType types[kMaxParams + 1] = {type, type, type, type, type,
160                                      type, type, type, type};
161   for (int num_params = which + 1; num_params < kMaxParams; num_params++) {
162     HandleScope scope(CcTest::InitIsolateOnce());
163     FunctionSig sig(1, num_params, types);
164 
165     ManuallyImportedJSFunction import = CreateJSSelector(&sig, which);
166     WasmRunner<void> r(tier, &import);
167     uint32_t js_index = 0;
168 
169     WasmFunctionCompiler& t = r.NewFunction(&sig);
170 
171     {
172       std::vector<byte> code;
173 
174       for (int i = 0; i < num_params; i++) {
175         ADD_CODE(code, WASM_F64(inputs.arg_d(i)));
176       }
177 
178       ADD_CODE(code, kExprCallFunction, static_cast<byte>(js_index));
179 
180       size_t end = code.size();
181       code.push_back(0);
182       t.Build(&code[0], &code[end]);
183     }
184 
185     double expected = inputs.arg_d(which);
186     r.CheckCallApplyViaJS(expected, t.function_index(), nullptr, 0);
187   }
188 }
189 
WASM_COMPILED_EXEC_TEST(Run_JSSelect_0)190 WASM_COMPILED_EXEC_TEST(Run_JSSelect_0) {
191   CcTest::InitializeVM();
192   RunJSSelectTest(execution_tier, 0);
193 }
194 
WASM_COMPILED_EXEC_TEST(Run_JSSelect_1)195 WASM_COMPILED_EXEC_TEST(Run_JSSelect_1) {
196   CcTest::InitializeVM();
197   RunJSSelectTest(execution_tier, 1);
198 }
199 
WASM_COMPILED_EXEC_TEST(Run_JSSelect_2)200 WASM_COMPILED_EXEC_TEST(Run_JSSelect_2) {
201   CcTest::InitializeVM();
202   RunJSSelectTest(execution_tier, 2);
203 }
204 
WASM_COMPILED_EXEC_TEST(Run_JSSelect_3)205 WASM_COMPILED_EXEC_TEST(Run_JSSelect_3) {
206   CcTest::InitializeVM();
207   RunJSSelectTest(execution_tier, 3);
208 }
209 
WASM_COMPILED_EXEC_TEST(Run_JSSelect_4)210 WASM_COMPILED_EXEC_TEST(Run_JSSelect_4) {
211   CcTest::InitializeVM();
212   RunJSSelectTest(execution_tier, 4);
213 }
214 
WASM_COMPILED_EXEC_TEST(Run_JSSelect_5)215 WASM_COMPILED_EXEC_TEST(Run_JSSelect_5) {
216   CcTest::InitializeVM();
217   RunJSSelectTest(execution_tier, 5);
218 }
219 
WASM_COMPILED_EXEC_TEST(Run_JSSelect_6)220 WASM_COMPILED_EXEC_TEST(Run_JSSelect_6) {
221   CcTest::InitializeVM();
222   RunJSSelectTest(execution_tier, 6);
223 }
224 
WASM_COMPILED_EXEC_TEST(Run_JSSelect_7)225 WASM_COMPILED_EXEC_TEST(Run_JSSelect_7) {
226   CcTest::InitializeVM();
227   RunJSSelectTest(execution_tier, 7);
228 }
229 
RunWASMSelectTest(TestExecutionTier tier,int which)230 void RunWASMSelectTest(TestExecutionTier tier, int which) {
231   PredictableInputValues inputs(0x200);
232   Isolate* isolate = CcTest::InitIsolateOnce();
233   const int kMaxParams = 8;
234   for (int num_params = which + 1; num_params < kMaxParams; num_params++) {
235     ValueType type = kWasmF64;
236     ValueType types[kMaxParams + 1] = {type, type, type, type, type,
237                                        type, type, type, type};
238     FunctionSig sig(1, num_params, types);
239 
240     WasmRunner<void> r(tier);
241     WasmFunctionCompiler& t = r.NewFunction(&sig);
242     BUILD(t, WASM_LOCAL_GET(which));
243 
244     Handle<Object> args[] = {
245         isolate->factory()->NewNumber(inputs.arg_d(0)),
246         isolate->factory()->NewNumber(inputs.arg_d(1)),
247         isolate->factory()->NewNumber(inputs.arg_d(2)),
248         isolate->factory()->NewNumber(inputs.arg_d(3)),
249         isolate->factory()->NewNumber(inputs.arg_d(4)),
250         isolate->factory()->NewNumber(inputs.arg_d(5)),
251         isolate->factory()->NewNumber(inputs.arg_d(6)),
252         isolate->factory()->NewNumber(inputs.arg_d(7)),
253     };
254 
255     double expected = inputs.arg_d(which);
256     r.CheckCallApplyViaJS(expected, t.function_index(), args, kMaxParams);
257   }
258 }
259 
WASM_COMPILED_EXEC_TEST(Run_WASMSelect_0)260 WASM_COMPILED_EXEC_TEST(Run_WASMSelect_0) {
261   CcTest::InitializeVM();
262   RunWASMSelectTest(execution_tier, 0);
263 }
264 
WASM_COMPILED_EXEC_TEST(Run_WASMSelect_1)265 WASM_COMPILED_EXEC_TEST(Run_WASMSelect_1) {
266   CcTest::InitializeVM();
267   RunWASMSelectTest(execution_tier, 1);
268 }
269 
WASM_COMPILED_EXEC_TEST(Run_WASMSelect_2)270 WASM_COMPILED_EXEC_TEST(Run_WASMSelect_2) {
271   CcTest::InitializeVM();
272   RunWASMSelectTest(execution_tier, 2);
273 }
274 
WASM_COMPILED_EXEC_TEST(Run_WASMSelect_3)275 WASM_COMPILED_EXEC_TEST(Run_WASMSelect_3) {
276   CcTest::InitializeVM();
277   RunWASMSelectTest(execution_tier, 3);
278 }
279 
WASM_COMPILED_EXEC_TEST(Run_WASMSelect_4)280 WASM_COMPILED_EXEC_TEST(Run_WASMSelect_4) {
281   CcTest::InitializeVM();
282   RunWASMSelectTest(execution_tier, 4);
283 }
284 
WASM_COMPILED_EXEC_TEST(Run_WASMSelect_5)285 WASM_COMPILED_EXEC_TEST(Run_WASMSelect_5) {
286   CcTest::InitializeVM();
287   RunWASMSelectTest(execution_tier, 5);
288 }
289 
WASM_COMPILED_EXEC_TEST(Run_WASMSelect_6)290 WASM_COMPILED_EXEC_TEST(Run_WASMSelect_6) {
291   CcTest::InitializeVM();
292   RunWASMSelectTest(execution_tier, 6);
293 }
294 
WASM_COMPILED_EXEC_TEST(Run_WASMSelect_7)295 WASM_COMPILED_EXEC_TEST(Run_WASMSelect_7) {
296   CcTest::InitializeVM();
297   RunWASMSelectTest(execution_tier, 7);
298 }
299 
RunWASMSelectAlignTest(TestExecutionTier tier,int num_args,int num_params)300 void RunWASMSelectAlignTest(TestExecutionTier tier, int num_args,
301                             int num_params) {
302   PredictableInputValues inputs(0x300);
303   Isolate* isolate = CcTest::InitIsolateOnce();
304   const int kMaxParams = 10;
305   DCHECK_LE(num_args, kMaxParams);
306   ValueType type = kWasmF64;
307   ValueType types[kMaxParams + 1] = {type, type, type, type, type, type,
308                                      type, type, type, type, type};
309   FunctionSig sig(1, num_params, types);
310 
311   for (int which = 0; which < num_params; which++) {
312     WasmRunner<void> r(tier);
313     WasmFunctionCompiler& t = r.NewFunction(&sig);
314     BUILD(t, WASM_LOCAL_GET(which));
315 
316     Handle<Object> args[] = {isolate->factory()->NewNumber(inputs.arg_d(0)),
317                              isolate->factory()->NewNumber(inputs.arg_d(1)),
318                              isolate->factory()->NewNumber(inputs.arg_d(2)),
319                              isolate->factory()->NewNumber(inputs.arg_d(3)),
320                              isolate->factory()->NewNumber(inputs.arg_d(4)),
321                              isolate->factory()->NewNumber(inputs.arg_d(5)),
322                              isolate->factory()->NewNumber(inputs.arg_d(6)),
323                              isolate->factory()->NewNumber(inputs.arg_d(7)),
324                              isolate->factory()->NewNumber(inputs.arg_d(8)),
325                              isolate->factory()->NewNumber(inputs.arg_d(9))};
326 
327     double nan = std::numeric_limits<double>::quiet_NaN();
328     double expected = which < num_args ? inputs.arg_d(which) : nan;
329     r.CheckCallApplyViaJS(expected, t.function_index(), args, num_args);
330   }
331 }
332 
WASM_COMPILED_EXEC_TEST(Run_WASMSelectAlign_0)333 WASM_COMPILED_EXEC_TEST(Run_WASMSelectAlign_0) {
334   CcTest::InitializeVM();
335   RunWASMSelectAlignTest(execution_tier, 0, 1);
336   RunWASMSelectAlignTest(execution_tier, 0, 2);
337 }
338 
WASM_COMPILED_EXEC_TEST(Run_WASMSelectAlign_1)339 WASM_COMPILED_EXEC_TEST(Run_WASMSelectAlign_1) {
340   CcTest::InitializeVM();
341   RunWASMSelectAlignTest(execution_tier, 1, 2);
342   RunWASMSelectAlignTest(execution_tier, 1, 3);
343 }
344 
WASM_COMPILED_EXEC_TEST(Run_WASMSelectAlign_2)345 WASM_COMPILED_EXEC_TEST(Run_WASMSelectAlign_2) {
346   CcTest::InitializeVM();
347   RunWASMSelectAlignTest(execution_tier, 2, 3);
348   RunWASMSelectAlignTest(execution_tier, 2, 4);
349 }
350 
WASM_COMPILED_EXEC_TEST(Run_WASMSelectAlign_3)351 WASM_COMPILED_EXEC_TEST(Run_WASMSelectAlign_3) {
352   CcTest::InitializeVM();
353   RunWASMSelectAlignTest(execution_tier, 3, 3);
354   RunWASMSelectAlignTest(execution_tier, 3, 4);
355 }
356 
WASM_COMPILED_EXEC_TEST(Run_WASMSelectAlign_4)357 WASM_COMPILED_EXEC_TEST(Run_WASMSelectAlign_4) {
358   CcTest::InitializeVM();
359   RunWASMSelectAlignTest(execution_tier, 4, 3);
360   RunWASMSelectAlignTest(execution_tier, 4, 4);
361 }
362 
WASM_COMPILED_EXEC_TEST(Run_WASMSelectAlign_7)363 WASM_COMPILED_EXEC_TEST(Run_WASMSelectAlign_7) {
364   CcTest::InitializeVM();
365   RunWASMSelectAlignTest(execution_tier, 7, 5);
366   RunWASMSelectAlignTest(execution_tier, 7, 6);
367   RunWASMSelectAlignTest(execution_tier, 7, 7);
368 }
369 
WASM_COMPILED_EXEC_TEST(Run_WASMSelectAlign_8)370 WASM_COMPILED_EXEC_TEST(Run_WASMSelectAlign_8) {
371   CcTest::InitializeVM();
372   RunWASMSelectAlignTest(execution_tier, 8, 5);
373   RunWASMSelectAlignTest(execution_tier, 8, 6);
374   RunWASMSelectAlignTest(execution_tier, 8, 7);
375   RunWASMSelectAlignTest(execution_tier, 8, 8);
376 }
377 
WASM_COMPILED_EXEC_TEST(Run_WASMSelectAlign_9)378 WASM_COMPILED_EXEC_TEST(Run_WASMSelectAlign_9) {
379   CcTest::InitializeVM();
380   RunWASMSelectAlignTest(execution_tier, 9, 6);
381   RunWASMSelectAlignTest(execution_tier, 9, 7);
382   RunWASMSelectAlignTest(execution_tier, 9, 8);
383   RunWASMSelectAlignTest(execution_tier, 9, 9);
384 }
385 
WASM_COMPILED_EXEC_TEST(Run_WASMSelectAlign_10)386 WASM_COMPILED_EXEC_TEST(Run_WASMSelectAlign_10) {
387   CcTest::InitializeVM();
388   RunWASMSelectAlignTest(execution_tier, 10, 7);
389   RunWASMSelectAlignTest(execution_tier, 10, 8);
390   RunWASMSelectAlignTest(execution_tier, 10, 9);
391   RunWASMSelectAlignTest(execution_tier, 10, 10);
392 }
393 
RunJSSelectAlignTest(TestExecutionTier tier,int num_args,int num_params)394 void RunJSSelectAlignTest(TestExecutionTier tier, int num_args,
395                           int num_params) {
396   PredictableInputValues inputs(0x400);
397   Isolate* isolate = CcTest::InitIsolateOnce();
398   Factory* factory = isolate->factory();
399   const int kMaxParams = 10;
400   CHECK_LE(num_args, kMaxParams);
401   CHECK_LE(num_params, kMaxParams);
402   ValueType type = kWasmF64;
403   ValueType types[kMaxParams + 1] = {type, type, type, type, type, type,
404                                      type, type, type, type, type};
405   FunctionSig sig(1, num_params, types);
406   i::AccountingAllocator allocator;
407   Zone zone(&allocator, ZONE_NAME);
408 
409   // Build the calling code.
410   std::vector<byte> code;
411 
412   for (int i = 0; i < num_params; i++) {
413     ADD_CODE(code, WASM_LOCAL_GET(i));
414   }
415 
416   uint8_t imported_js_index = 0;
417   ADD_CODE(code, kExprCallFunction, imported_js_index);
418 
419   size_t end = code.size();
420   code.push_back(0);
421 
422   // Call different select JS functions.
423   for (int which = 0; which < num_params; which++) {
424     HandleScope scope(isolate);
425     ManuallyImportedJSFunction import = CreateJSSelector(&sig, which);
426     WasmRunner<void> r(tier, &import);
427     WasmFunctionCompiler& t = r.NewFunction(&sig);
428     t.Build(&code[0], &code[end]);
429 
430     Handle<Object> args[] = {
431         factory->NewNumber(inputs.arg_d(0)),
432         factory->NewNumber(inputs.arg_d(1)),
433         factory->NewNumber(inputs.arg_d(2)),
434         factory->NewNumber(inputs.arg_d(3)),
435         factory->NewNumber(inputs.arg_d(4)),
436         factory->NewNumber(inputs.arg_d(5)),
437         factory->NewNumber(inputs.arg_d(6)),
438         factory->NewNumber(inputs.arg_d(7)),
439         factory->NewNumber(inputs.arg_d(8)),
440         factory->NewNumber(inputs.arg_d(9)),
441     };
442 
443     double nan = std::numeric_limits<double>::quiet_NaN();
444     double expected = which < num_args ? inputs.arg_d(which) : nan;
445     r.CheckCallApplyViaJS(expected, t.function_index(), args, num_args);
446   }
447 }
448 
WASM_COMPILED_EXEC_TEST(Run_JSSelectAlign_0)449 WASM_COMPILED_EXEC_TEST(Run_JSSelectAlign_0) {
450   CcTest::InitializeVM();
451   RunJSSelectAlignTest(execution_tier, 0, 1);
452   RunJSSelectAlignTest(execution_tier, 0, 2);
453 }
454 
WASM_COMPILED_EXEC_TEST(Run_JSSelectAlign_1)455 WASM_COMPILED_EXEC_TEST(Run_JSSelectAlign_1) {
456   CcTest::InitializeVM();
457   RunJSSelectAlignTest(execution_tier, 1, 2);
458   RunJSSelectAlignTest(execution_tier, 1, 3);
459 }
460 
WASM_COMPILED_EXEC_TEST(Run_JSSelectAlign_2)461 WASM_COMPILED_EXEC_TEST(Run_JSSelectAlign_2) {
462   CcTest::InitializeVM();
463   RunJSSelectAlignTest(execution_tier, 2, 3);
464   RunJSSelectAlignTest(execution_tier, 2, 4);
465 }
466 
WASM_COMPILED_EXEC_TEST(Run_JSSelectAlign_3)467 WASM_COMPILED_EXEC_TEST(Run_JSSelectAlign_3) {
468   CcTest::InitializeVM();
469   RunJSSelectAlignTest(execution_tier, 3, 3);
470   RunJSSelectAlignTest(execution_tier, 3, 4);
471 }
472 
WASM_COMPILED_EXEC_TEST(Run_JSSelectAlign_4)473 WASM_COMPILED_EXEC_TEST(Run_JSSelectAlign_4) {
474   CcTest::InitializeVM();
475   RunJSSelectAlignTest(execution_tier, 4, 3);
476   RunJSSelectAlignTest(execution_tier, 4, 4);
477 }
478 
WASM_COMPILED_EXEC_TEST(Run_JSSelectAlign_7)479 WASM_COMPILED_EXEC_TEST(Run_JSSelectAlign_7) {
480   CcTest::InitializeVM();
481   RunJSSelectAlignTest(execution_tier, 7, 3);
482   RunJSSelectAlignTest(execution_tier, 7, 4);
483   RunJSSelectAlignTest(execution_tier, 7, 4);
484   RunJSSelectAlignTest(execution_tier, 7, 4);
485 }
486 
WASM_COMPILED_EXEC_TEST(Run_JSSelectAlign_8)487 WASM_COMPILED_EXEC_TEST(Run_JSSelectAlign_8) {
488   CcTest::InitializeVM();
489   RunJSSelectAlignTest(execution_tier, 8, 5);
490   RunJSSelectAlignTest(execution_tier, 8, 6);
491   RunJSSelectAlignTest(execution_tier, 8, 7);
492   RunJSSelectAlignTest(execution_tier, 8, 8);
493 }
494 
WASM_COMPILED_EXEC_TEST(Run_JSSelectAlign_9)495 WASM_COMPILED_EXEC_TEST(Run_JSSelectAlign_9) {
496   CcTest::InitializeVM();
497   RunJSSelectAlignTest(execution_tier, 9, 6);
498   RunJSSelectAlignTest(execution_tier, 9, 7);
499   RunJSSelectAlignTest(execution_tier, 9, 8);
500   RunJSSelectAlignTest(execution_tier, 9, 9);
501 }
502 
WASM_COMPILED_EXEC_TEST(Run_JSSelectAlign_10)503 WASM_COMPILED_EXEC_TEST(Run_JSSelectAlign_10) {
504   CcTest::InitializeVM();
505   RunJSSelectAlignTest(execution_tier, 10, 7);
506   RunJSSelectAlignTest(execution_tier, 10, 8);
507   RunJSSelectAlignTest(execution_tier, 10, 9);
508   RunJSSelectAlignTest(execution_tier, 10, 10);
509 }
510 
511 // Set up a test with an import, so we can return call it.
512 // Create a javascript function that returns left or right arguments
513 // depending on the value of the third argument
514 // function (a,b,c){ if(c)return a; return b; }
515 
RunPickerTest(TestExecutionTier tier,bool indirect)516 void RunPickerTest(TestExecutionTier tier, bool indirect) {
517   EXPERIMENTAL_FLAG_SCOPE(return_call);
518   Isolate* isolate = CcTest::InitIsolateOnce();
519   HandleScope scope(isolate);
520   TestSignatures sigs;
521 
522   const char* source = "(function(a,b,c) { if(c)return a; return b; })";
523   Handle<JSFunction> js_function =
524       Handle<JSFunction>::cast(v8::Utils::OpenHandle(
525           *v8::Local<v8::Function>::Cast(CompileRun(source))));
526 
527   ManuallyImportedJSFunction import = {sigs.i_iii(), js_function};
528 
529   WasmRunner<int32_t, int32_t> r(tier, &import);
530 
531   const uint32_t js_index = 0;
532   const int32_t left = -2;
533   const int32_t right = 3;
534 
535   WasmFunctionCompiler& rc_fn = r.NewFunction(sigs.i_i(), "rc");
536 
537   if (indirect) {
538     byte sig_index = r.builder().AddSignature(sigs.i_iii());
539     uint16_t indirect_function_table[] = {static_cast<uint16_t>(js_index)};
540 
541     r.builder().AddIndirectFunctionTable(indirect_function_table,
542                                          arraysize(indirect_function_table));
543 
544     BUILD(rc_fn, WASM_RETURN_CALL_INDIRECT(sig_index, WASM_I32V(left),
545                                            WASM_I32V(right), WASM_LOCAL_GET(0),
546                                            WASM_I32V(js_index)));
547   } else {
548     BUILD(rc_fn,
549           WASM_RETURN_CALL_FUNCTION(js_index, WASM_I32V(left), WASM_I32V(right),
550                                     WASM_LOCAL_GET(0)));
551   }
552 
553   Handle<Object> args_left[] = {isolate->factory()->NewNumber(1)};
554   r.CheckCallApplyViaJS(left, rc_fn.function_index(), args_left, 1);
555 
556   Handle<Object> args_right[] = {isolate->factory()->NewNumber(0)};
557   r.CheckCallApplyViaJS(right, rc_fn.function_index(), args_right, 1);
558 }
559 
WASM_COMPILED_EXEC_TEST(Run_ReturnCallImportedFunction)560 WASM_COMPILED_EXEC_TEST(Run_ReturnCallImportedFunction) {
561   RunPickerTest(execution_tier, false);
562 }
563 
WASM_COMPILED_EXEC_TEST(Run_ReturnCallIndirectImportedFunction)564 WASM_COMPILED_EXEC_TEST(Run_ReturnCallIndirectImportedFunction) {
565   RunPickerTest(execution_tier, true);
566 }
567 
568 }  // namespace wasm
569 }  // namespace internal
570 }  // namespace v8
571