Home | History | Annotate | Download | only in wasm
      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