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 <stdlib.h>
7 #include <string.h>
8
9 #include "src/wasm/wasm-macro-gen.h"
10
11 #include "test/cctest/cctest.h"
12 #include "test/cctest/wasm/test-signatures.h"
13 #include "test/cctest/wasm/wasm-run-utils.h"
14
15 using namespace v8::base;
16 using namespace v8::internal;
17 using namespace v8::internal::compiler;
18 using namespace v8::internal::wasm;
19
20 #define BUILD(r, ...) \
21 do { \
22 byte code[] = {__VA_ARGS__}; \
23 r.Build(code, code + arraysize(code)); \
24 } while (false)
25
26
AddJsFunction(TestingModule * module,FunctionSig * sig,const char * source)27 static uint32_t AddJsFunction(TestingModule* module, FunctionSig* sig,
28 const char* source) {
29 Handle<JSFunction> jsfunc = Handle<JSFunction>::cast(v8::Utils::OpenHandle(
30 *v8::Local<v8::Function>::Cast(CompileRun(source))));
31 module->AddFunction(sig, Handle<Code>::null());
32 uint32_t index = static_cast<uint32_t>(module->module->functions->size() - 1);
33 Isolate* isolate = CcTest::InitIsolateOnce();
34 Handle<Code> code = CompileWasmToJSWrapper(isolate, module, jsfunc, index);
35 module->function_code->at(index) = code;
36 return index;
37 }
38
39
WrapCode(ModuleEnv * module,uint32_t index)40 static Handle<JSFunction> WrapCode(ModuleEnv* module, uint32_t index) {
41 Isolate* isolate = module->module->shared_isolate;
42 // Wrap the code so it can be called as a JS function.
43 Handle<String> name = isolate->factory()->NewStringFromStaticChars("main");
44 Handle<JSObject> module_object = Handle<JSObject>(0, isolate);
45 Handle<Code> code = module->function_code->at(index);
46 WasmJs::InstallWasmFunctionMap(isolate, isolate->native_context());
47 return compiler::CompileJSToWasmWrapper(isolate, module, name, code,
48 module_object, index);
49 }
50
51
EXPECT_CALL(double expected,Handle<JSFunction> jsfunc,double a,double b)52 static void EXPECT_CALL(double expected, Handle<JSFunction> jsfunc, double a,
53 double b) {
54 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);
58 MaybeHandle<Object> retval =
59 Execution::Call(isolate, jsfunc, global, 2, buffer);
60
61 CHECK(!retval.is_null());
62 Handle<Object> result = retval.ToHandleChecked();
63 if (result->IsSmi()) {
64 CHECK_EQ(expected, Smi::cast(*result)->value());
65 } else {
66 CHECK(result->IsHeapNumber());
67 CHECK_EQ(expected, HeapNumber::cast(*result)->value());
68 }
69 }
70
71
TEST(Run_Int32Sub_jswrapped)72 TEST(Run_Int32Sub_jswrapped) {
73 TestSignatures sigs;
74 TestingModule module;
75 WasmFunctionCompiler t(sigs.i_ii());
76 BUILD(t, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
77 Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd(&module));
78
79 EXPECT_CALL(33, jsfunc, 44, 11);
80 EXPECT_CALL(-8723487, jsfunc, -8000000, 723487);
81 }
82
83
TEST(Run_Float32Div_jswrapped)84 TEST(Run_Float32Div_jswrapped) {
85 TestSignatures sigs;
86 TestingModule module;
87 WasmFunctionCompiler t(sigs.f_ff());
88 BUILD(t, WASM_F32_DIV(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
89 Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd(&module));
90
91 EXPECT_CALL(92, jsfunc, 46, 0.5);
92 EXPECT_CALL(64, jsfunc, -16, -0.25);
93 }
94
95
TEST(Run_Float64Add_jswrapped)96 TEST(Run_Float64Add_jswrapped) {
97 TestSignatures sigs;
98 TestingModule module;
99 WasmFunctionCompiler t(sigs.d_dd());
100 BUILD(t, WASM_F64_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
101 Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd(&module));
102
103 EXPECT_CALL(3, jsfunc, 2, 1);
104 EXPECT_CALL(-5.5, jsfunc, -5.25, -0.25);
105 }
106
107
TEST(Run_I32Popcount_jswrapped)108 TEST(Run_I32Popcount_jswrapped) {
109 TestSignatures sigs;
110 TestingModule module;
111 WasmFunctionCompiler t(sigs.i_i());
112 BUILD(t, WASM_I32_POPCNT(WASM_GET_LOCAL(0)));
113 Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd(&module));
114
115 EXPECT_CALL(2, jsfunc, 9, 0);
116 EXPECT_CALL(3, jsfunc, 11, 0);
117 EXPECT_CALL(6, jsfunc, 0x3F, 0);
118
119 USE(AddJsFunction);
120 }
121
122
123 #if !V8_TARGET_ARCH_ARM64
124 // TODO(titzer): fix wasm->JS calls on arm64 (wrapper issues)
125
TEST(Run_CallJS_Add_jswrapped)126 TEST(Run_CallJS_Add_jswrapped) {
127 TestSignatures sigs;
128 TestingModule module;
129 WasmFunctionCompiler t(sigs.i_i(), &module);
130 uint32_t js_index =
131 AddJsFunction(&module, sigs.i_i(), "(function(a) { return a + 99; })");
132 BUILD(t, WASM_CALL_FUNCTION(js_index, WASM_GET_LOCAL(0)));
133
134 Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd(&module));
135
136 EXPECT_CALL(101, jsfunc, 2, -8);
137 EXPECT_CALL(199, jsfunc, 100, -1);
138 EXPECT_CALL(-666666801, jsfunc, -666666900, -1);
139 }
140
141 #endif
142