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 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 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 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 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 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 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 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 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