Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(765)

Side by Side Diff: test/cctest/wasm/test-run-wasm-js.cc

Issue 1603533002: [wasm] Add more thorough tests for WASM->JS and JS->WASM parameters. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: signedness Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/linkage.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <stdint.h> 5 #include <stdint.h>
6 #include <stdio.h>
6 #include <stdlib.h> 7 #include <stdlib.h>
7 #include <string.h> 8 #include <string.h>
8 9
9 #include "src/wasm/wasm-macro-gen.h" 10 #include "src/wasm/wasm-macro-gen.h"
10 11
11 #include "test/cctest/cctest.h" 12 #include "test/cctest/cctest.h"
12 #include "test/cctest/wasm/test-signatures.h" 13 #include "test/cctest/wasm/test-signatures.h"
13 #include "test/cctest/wasm/wasm-run-utils.h" 14 #include "test/cctest/wasm/wasm-run-utils.h"
14 15
15 using namespace v8::base; 16 using namespace v8::base;
16 using namespace v8::internal; 17 using namespace v8::internal;
17 using namespace v8::internal::compiler; 18 using namespace v8::internal::compiler;
18 using namespace v8::internal::wasm; 19 using namespace v8::internal::wasm;
19 20
20 #define BUILD(r, ...) \ 21 #define BUILD(r, ...) \
21 do { \ 22 do { \
22 byte code[] = {__VA_ARGS__}; \ 23 byte code[] = {__VA_ARGS__}; \
23 r.Build(code, code + arraysize(code)); \ 24 r.Build(code, code + arraysize(code)); \
24 } while (false) 25 } while (false)
25 26
26 27
27 static uint32_t AddJsFunction(TestingModule* module, FunctionSig* sig, 28 #define ADD_CODE(vec, ...) \
28 const char* source) { 29 do { \
30 byte __buf[] = {__VA_ARGS__}; \
31 for (size_t i = 0; i < sizeof(__buf); i++) vec.push_back(__buf[i]); \
32 } while (false)
33
34
35 namespace {
36 // A helper for generating predictable but unique argument values that
37 // are easy to debug (e.g. with misaligned stacks).
38 class PredictableInputValues {
39 public:
40 int base_;
41 explicit PredictableInputValues(int base) : base_(base) {}
42 double arg_d(int which) { return base_ * which + ((which & 1) * 0.5); }
43 float arg_f(int which) { return base_ * which + ((which & 1) * 0.25); }
44 int32_t arg_i(int which) { return base_ * which + ((which & 1) * kMinInt); }
45 int64_t arg_l(int which) {
46 return base_ * which + ((which & 1) * (0x04030201LL << 32));
47 }
48 };
49
50
51 uint32_t AddJsFunction(TestingModule* module, FunctionSig* sig,
52 const char* source) {
29 Handle<JSFunction> jsfunc = Handle<JSFunction>::cast(v8::Utils::OpenHandle( 53 Handle<JSFunction> jsfunc = Handle<JSFunction>::cast(v8::Utils::OpenHandle(
30 *v8::Local<v8::Function>::Cast(CompileRun(source)))); 54 *v8::Local<v8::Function>::Cast(CompileRun(source))));
31 module->AddFunction(sig, Handle<Code>::null()); 55 module->AddFunction(sig, Handle<Code>::null());
32 uint32_t index = static_cast<uint32_t>(module->module->functions->size() - 1); 56 uint32_t index = static_cast<uint32_t>(module->module->functions->size() - 1);
33 Isolate* isolate = CcTest::InitIsolateOnce(); 57 Isolate* isolate = CcTest::InitIsolateOnce();
34 Handle<Code> code = CompileWasmToJSWrapper(isolate, module, jsfunc, index); 58 Handle<Code> code = CompileWasmToJSWrapper(isolate, module, jsfunc, index);
35 module->function_code->at(index) = code; 59 module->function_code->at(index) = code;
36 return index; 60 return index;
37 } 61 }
38 62
39 63
40 static Handle<JSFunction> WrapCode(ModuleEnv* module, uint32_t index) { 64 uint32_t AddJSSelector(TestingModule* module, FunctionSig* sig, int which) {
65 const int kMaxParams = 8;
66 static const char* formals[kMaxParams] = {
67 "", "a", "a,b", "a,b,c",
68 "a,b,c,d", "a,b,c,d,e", "a,b,c,d,e,f", "a,b,c,d,e,f,g",
69 };
70 CHECK_LT(which, static_cast<int>(sig->parameter_count()));
71 CHECK_LT(static_cast<int>(sig->parameter_count()), kMaxParams);
72
73 i::EmbeddedVector<char, 256> source;
74 char param = 'a' + which;
75 SNPrintF(source, "(function(%s) { return %c; })",
76 formals[sig->parameter_count()], param);
77
78 return AddJsFunction(module, sig, source.start());
79 }
80
81
82 Handle<JSFunction> WrapCode(ModuleEnv* module, uint32_t index) {
41 Isolate* isolate = module->module->shared_isolate; 83 Isolate* isolate = module->module->shared_isolate;
42 // Wrap the code so it can be called as a JS function. 84 // Wrap the code so it can be called as a JS function.
43 Handle<String> name = isolate->factory()->NewStringFromStaticChars("main"); 85 Handle<String> name = isolate->factory()->NewStringFromStaticChars("main");
44 Handle<JSObject> module_object = Handle<JSObject>(0, isolate); 86 Handle<JSObject> module_object = Handle<JSObject>(0, isolate);
45 Handle<Code> code = module->function_code->at(index); 87 Handle<Code> code = module->function_code->at(index);
46 WasmJs::InstallWasmFunctionMap(isolate, isolate->native_context()); 88 WasmJs::InstallWasmFunctionMap(isolate, isolate->native_context());
47 return compiler::CompileJSToWasmWrapper(isolate, module, name, code, 89 return compiler::CompileJSToWasmWrapper(isolate, module, name, code,
48 module_object, index); 90 module_object, index);
49 } 91 }
50 92
51 93
52 static void EXPECT_CALL(double expected, Handle<JSFunction> jsfunc, double a, 94 void EXPECT_CALL(double expected, Handle<JSFunction> jsfunc,
53 double b) { 95 Handle<Object>* buffer, int count) {
54 Isolate* isolate = jsfunc->GetIsolate(); 96 Isolate* isolate = jsfunc->GetIsolate();
55 Handle<Object> buffer[] = {isolate->factory()->NewNumber(a),
56 isolate->factory()->NewNumber(b)};
57 Handle<Object> global(isolate->context()->global_object(), isolate); 97 Handle<Object> global(isolate->context()->global_object(), isolate);
58 MaybeHandle<Object> retval = 98 MaybeHandle<Object> retval =
59 Execution::Call(isolate, jsfunc, global, 2, buffer); 99 Execution::Call(isolate, jsfunc, global, count, buffer);
60 100
61 CHECK(!retval.is_null()); 101 CHECK(!retval.is_null());
62 Handle<Object> result = retval.ToHandleChecked(); 102 Handle<Object> result = retval.ToHandleChecked();
63 if (result->IsSmi()) { 103 if (result->IsSmi()) {
64 CHECK_EQ(expected, Smi::cast(*result)->value()); 104 CHECK_EQ(expected, Smi::cast(*result)->value());
65 } else { 105 } else {
66 CHECK(result->IsHeapNumber()); 106 CHECK(result->IsHeapNumber());
67 CHECK_EQ(expected, HeapNumber::cast(*result)->value()); 107 CheckFloatEq(expected, HeapNumber::cast(*result)->value());
68 } 108 }
69 } 109 }
70 110
71 111
112 void EXPECT_CALL(double expected, Handle<JSFunction> jsfunc, double a,
113 double b) {
114 Isolate* isolate = jsfunc->GetIsolate();
115 Handle<Object> buffer[] = {isolate->factory()->NewNumber(a),
116 isolate->factory()->NewNumber(b)};
117 EXPECT_CALL(expected, jsfunc, buffer, 2);
118 }
119 } // namespace
120
72 TEST(Run_Int32Sub_jswrapped) { 121 TEST(Run_Int32Sub_jswrapped) {
73 TestSignatures sigs; 122 TestSignatures sigs;
74 TestingModule module; 123 TestingModule module;
75 WasmFunctionCompiler t(sigs.i_ii()); 124 WasmFunctionCompiler t(sigs.i_ii());
76 BUILD(t, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); 125 BUILD(t, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
77 Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd(&module)); 126 Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd(&module));
78 127
79 EXPECT_CALL(33, jsfunc, 44, 11); 128 EXPECT_CALL(33, jsfunc, 44, 11);
80 EXPECT_CALL(-8723487, jsfunc, -8000000, 723487); 129 EXPECT_CALL(-8723487, jsfunc, -8000000, 723487);
81 } 130 }
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
114 163
115 EXPECT_CALL(2, jsfunc, 9, 0); 164 EXPECT_CALL(2, jsfunc, 9, 0);
116 EXPECT_CALL(3, jsfunc, 11, 0); 165 EXPECT_CALL(3, jsfunc, 11, 0);
117 EXPECT_CALL(6, jsfunc, 0x3F, 0); 166 EXPECT_CALL(6, jsfunc, 0x3F, 0);
118 167
119 USE(AddJsFunction); 168 USE(AddJsFunction);
120 } 169 }
121 170
122 171
123 #if !V8_TARGET_ARCH_ARM64 172 #if !V8_TARGET_ARCH_ARM64
124 // TODO(titzer): fix wasm->JS calls on arm64 (wrapper issues) 173 // TODO(titzer): dynamic frame alignment on arm64
125
126 TEST(Run_CallJS_Add_jswrapped) { 174 TEST(Run_CallJS_Add_jswrapped) {
127 TestSignatures sigs; 175 TestSignatures sigs;
128 TestingModule module; 176 TestingModule module;
129 WasmFunctionCompiler t(sigs.i_i(), &module); 177 WasmFunctionCompiler t(sigs.i_i(), &module);
130 uint32_t js_index = 178 uint32_t js_index =
131 AddJsFunction(&module, sigs.i_i(), "(function(a) { return a + 99; })"); 179 AddJsFunction(&module, sigs.i_i(), "(function(a) { return a + 99; })");
132 BUILD(t, WASM_CALL_FUNCTION(js_index, WASM_GET_LOCAL(0))); 180 BUILD(t, WASM_CALL_FUNCTION(js_index, WASM_GET_LOCAL(0)));
133 181
134 Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd(&module)); 182 Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd(&module));
135 183
136 EXPECT_CALL(101, jsfunc, 2, -8); 184 EXPECT_CALL(101, jsfunc, 2, -8);
137 EXPECT_CALL(199, jsfunc, 100, -1); 185 EXPECT_CALL(199, jsfunc, 100, -1);
138 EXPECT_CALL(-666666801, jsfunc, -666666900, -1); 186 EXPECT_CALL(-666666801, jsfunc, -666666900, -1);
139 } 187 }
140
141 #endif 188 #endif
189
190
191 void RunJSSelectTest(int which) {
192 const int kMaxParams = 8;
193 PredictableInputValues inputs(0x100);
194 LocalType type = kAstF64;
195 LocalType types[kMaxParams + 1] = {type, type, type, type, type,
196 type, type, type, type};
197 for (int num_params = which + 1; num_params < kMaxParams; num_params++) {
198 HandleScope scope(CcTest::InitIsolateOnce());
199 FunctionSig sig(1, num_params, types);
200
201 TestingModule module;
202 uint32_t js_index = AddJSSelector(&module, &sig, which);
203 WasmFunctionCompiler t(&sig, &module);
204
205 {
206 std::vector<byte> code;
207 ADD_CODE(code, kExprCallFunction, static_cast<byte>(js_index));
208
209 for (int i = 0; i < num_params; i++) {
210 ADD_CODE(code, WASM_F64(inputs.arg_d(i)));
211 }
212
213 size_t end = code.size();
214 code.push_back(0);
215 t.Build(&code[0], &code[end]);
216 }
217
218 Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd(&module));
219 double expected = inputs.arg_d(which);
220 EXPECT_CALL(expected, jsfunc, 0.0, 0.0);
221 }
222 }
223
224
225 TEST(Run_JSSelect_0) { RunJSSelectTest(0); }
226
227 TEST(Run_JSSelect_1) { RunJSSelectTest(1); }
228
229 TEST(Run_JSSelect_2) { RunJSSelectTest(2); }
230
231 TEST(Run_JSSelect_3) { RunJSSelectTest(3); }
232
233 TEST(Run_JSSelect_4) { RunJSSelectTest(4); }
234
235 TEST(Run_JSSelect_5) { RunJSSelectTest(5); }
236
237 TEST(Run_JSSelect_6) { RunJSSelectTest(6); }
238
239 TEST(Run_JSSelect_7) { RunJSSelectTest(7); }
240
241
242 void RunWASMSelectTest(int which) {
243 PredictableInputValues inputs(0x200);
244 Isolate* isolate = CcTest::InitIsolateOnce();
245 const int kMaxParams = 8;
246 for (int num_params = which + 1; num_params < kMaxParams; num_params++) {
247 LocalType type = kAstF64;
248 LocalType types[kMaxParams + 1] = {type, type, type, type, type,
249 type, type, type, type};
250 FunctionSig sig(1, num_params, types);
251
252 TestingModule module;
253 WasmFunctionCompiler t(&sig, &module);
254 BUILD(t, WASM_GET_LOCAL(which));
255 Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd(&module));
256
257 Handle<Object> args[] = {
258 isolate->factory()->NewNumber(inputs.arg_d(0)),
259 isolate->factory()->NewNumber(inputs.arg_d(1)),
260 isolate->factory()->NewNumber(inputs.arg_d(2)),
261 isolate->factory()->NewNumber(inputs.arg_d(3)),
262 isolate->factory()->NewNumber(inputs.arg_d(4)),
263 isolate->factory()->NewNumber(inputs.arg_d(5)),
264 isolate->factory()->NewNumber(inputs.arg_d(6)),
265 isolate->factory()->NewNumber(inputs.arg_d(7)),
266 };
267
268 double expected = inputs.arg_d(which);
269 EXPECT_CALL(expected, jsfunc, args, kMaxParams);
270 }
271 }
272
273
274 TEST(Run_WASMSelect_0) { RunWASMSelectTest(0); }
275
276 TEST(Run_WASMSelect_1) { RunWASMSelectTest(1); }
277
278 TEST(Run_WASMSelect_2) { RunWASMSelectTest(2); }
279
280 TEST(Run_WASMSelect_3) { RunWASMSelectTest(3); }
281
282 TEST(Run_WASMSelect_4) { RunWASMSelectTest(4); }
283
284 TEST(Run_WASMSelect_5) { RunWASMSelectTest(5); }
285
286 TEST(Run_WASMSelect_6) { RunWASMSelectTest(6); }
287
288 TEST(Run_WASMSelect_7) { RunWASMSelectTest(7); }
289
290
291 void RunWASMSelectAlignTest(int num_args, int num_params) {
292 PredictableInputValues inputs(0x300);
293 Isolate* isolate = CcTest::InitIsolateOnce();
294 const int kMaxParams = 4;
295 DCHECK_LE(num_args, kMaxParams);
296 LocalType type = kAstF64;
297 LocalType types[kMaxParams + 1] = {type, type, type, type, type};
298 FunctionSig sig(1, num_params, types);
299
300 for (int which = 0; which < num_params; which++) {
301 TestingModule module;
302 WasmFunctionCompiler t(&sig, &module);
303 BUILD(t, WASM_GET_LOCAL(which));
304 Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd(&module));
305
306 Handle<Object> args[] = {
307 isolate->factory()->NewNumber(inputs.arg_d(0)),
308 isolate->factory()->NewNumber(inputs.arg_d(1)),
309 isolate->factory()->NewNumber(inputs.arg_d(2)),
310 isolate->factory()->NewNumber(inputs.arg_d(3)),
311 };
312
313 double nan = std::numeric_limits<double>::quiet_NaN();
314 double expected = which < num_args ? inputs.arg_d(which) : nan;
315 EXPECT_CALL(expected, jsfunc, args, num_args);
316 }
317 }
318
319
320 TEST(Run_WASMSelectAlign_0) {
321 RunWASMSelectAlignTest(0, 1);
322 RunWASMSelectAlignTest(0, 2);
323 }
324
325
326 TEST(Run_WASMSelectAlign_1) {
327 RunWASMSelectAlignTest(1, 2);
328 RunWASMSelectAlignTest(1, 3);
329 }
330
331
332 TEST(Run_WASMSelectAlign_2) {
333 RunWASMSelectAlignTest(2, 3);
334 RunWASMSelectAlignTest(2, 4);
335 }
336
337
338 TEST(Run_WASMSelectAlign_3) {
339 RunWASMSelectAlignTest(3, 3);
340 RunWASMSelectAlignTest(3, 4);
341 }
342
343
344 TEST(Run_WASMSelectAlign_4) {
345 RunWASMSelectAlignTest(4, 3);
346 RunWASMSelectAlignTest(4, 4);
347 }
348
349
350 void RunJSSelectAlignTest(int num_args, int num_params) {
351 PredictableInputValues inputs(0x400);
352 Isolate* isolate = CcTest::InitIsolateOnce();
353 Factory* factory = isolate->factory();
354 const int kMaxParams = 4;
355 CHECK_LE(num_args, kMaxParams);
356 CHECK_LE(num_params, kMaxParams);
357 LocalType type = kAstF64;
358 LocalType types[kMaxParams + 1] = {type, type, type, type, type};
359 FunctionSig sig(1, num_params, types);
360
361 // Build the calling code.
362 std::vector<byte> code;
363 ADD_CODE(code, kExprCallFunction, 0);
364
365 for (int i = 0; i < num_params; i++) {
366 ADD_CODE(code, WASM_GET_LOCAL(i));
367 }
368
369 size_t end = code.size();
370 code.push_back(0);
371
372 // Call different select JS functions.
373 for (int which = 0; which < num_params; which++) {
374 HandleScope scope(isolate);
375 TestingModule module;
376 uint32_t js_index = AddJSSelector(&module, &sig, which);
377 CHECK_EQ(0, js_index);
378 WasmFunctionCompiler t(&sig, &module);
379 t.Build(&code[0], &code[end]);
380
381 Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd(&module));
382
383 Handle<Object> args[] = {
384 factory->NewNumber(inputs.arg_d(0)),
385 factory->NewNumber(inputs.arg_d(1)),
386 factory->NewNumber(inputs.arg_d(2)),
387 factory->NewNumber(inputs.arg_d(3)),
388 };
389
390 double nan = std::numeric_limits<double>::quiet_NaN();
391 double expected = which < num_args ? inputs.arg_d(which) : nan;
392 EXPECT_CALL(expected, jsfunc, args, num_args);
393 }
394 }
395
396
397 TEST(Run_JSSelectAlign_0) {
398 RunJSSelectAlignTest(0, 1);
399 RunJSSelectAlignTest(0, 2);
400 }
401
402
403 TEST(Run_JSSelectAlign_2) {
404 RunJSSelectAlignTest(2, 3);
405 RunJSSelectAlignTest(2, 4);
406 }
407
408
409 TEST(Run_JSSelectAlign_4) {
410 RunJSSelectAlignTest(4, 3);
411 RunJSSelectAlignTest(4, 4);
412 }
413
414
415 #if !V8_TARGET_ARCH_ARM64
416 // TODO(titzer): dynamic frame alignment on arm64
417 TEST(Run_JSSelectAlign_1) {
418 RunJSSelectAlignTest(1, 2);
419 RunJSSelectAlignTest(1, 3);
420 }
421
422
423 TEST(Run_JSSelectAlign_3) {
424 RunJSSelectAlignTest(3, 3);
425 RunJSSelectAlignTest(3, 4);
426 }
427 #endif
OLDNEW
« no previous file with comments | « src/compiler/linkage.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698