testWasmEncoder.cpp (4341B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 */ 4 /* This Source Code Form is subject to the terms of the Mozilla Public 5 * License, v. 2.0. If a copy of the MPL was not distributed with this 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 7 8 #include "jit/MacroAssembler.h" 9 10 #include "jsapi-tests/tests.h" 11 #include "jsapi-tests/testsJit.h" 12 13 #include "wasm/WasmConstants.h" 14 #include "wasm/WasmFeatures.h" // AnyCompilerAvailable 15 #include "wasm/WasmGenerator.h" 16 #include "wasm/WasmSignalHandlers.h" // EnsureFullSignalHandlers 17 #include "wasm/WasmValidate.h" 18 #include "wasm/WasmValType.h" 19 20 using namespace js; 21 using namespace js::jit; 22 using namespace js::wasm; 23 24 static bool TestTruncFn(JSContext* cx, unsigned argc, Value* vp) { 25 CallArgs args = CallArgsFromVp(argc, vp); 26 double d = args[0].toDouble(); 27 args.rval().setInt32((int)d); 28 return true; 29 } 30 31 // Check if wasm modules can be encoded in C++ and run. 32 BEGIN_TEST(testWasmEncodeBasic) { 33 if (!AnyCompilerAvailable(cx)) { 34 knownFail = true; 35 return false; 36 } 37 38 EnsureFullSignalHandlers(cx); 39 40 FeatureOptions options; 41 ScriptedCaller scriptedCaller; 42 SharedCompileArgs compileArgs = 43 CompileArgs::buildAndReport(cx, std::move(scriptedCaller), options); 44 45 MutableModuleMetadata moduleMeta = js_new<ModuleMetadata>(); 46 MOZ_ALWAYS_TRUE(moduleMeta); 47 MOZ_ALWAYS_TRUE(moduleMeta->init(*compileArgs)); 48 MutableCodeMetadata codeMeta = moduleMeta->codeMeta; 49 CompilerEnvironment compilerEnv(CompileMode::Once, Tier::Optimized, 50 DebugEnabled::False); 51 compilerEnv.computeParameters(); 52 53 ValTypeVector paramsImp, resultsImp; 54 MOZ_ALWAYS_TRUE(paramsImp.emplaceBack(ValType::F64) && 55 resultsImp.emplaceBack(ValType::I32)); 56 57 CacheableName ns; 58 CacheableName impName; 59 MOZ_ALWAYS_TRUE(CacheableName::fromUTF8Chars("t", &impName)); 60 MOZ_ALWAYS_TRUE( 61 moduleMeta->addImportedFunc(std::move(paramsImp), std::move(resultsImp), 62 std::move(ns), std::move(impName))); 63 64 ValTypeVector params, results; 65 MOZ_ALWAYS_TRUE(results.emplaceBack(ValType::I32)); 66 CacheableName expName; 67 MOZ_ALWAYS_TRUE(CacheableName::fromUTF8Chars("r", &expName)); 68 MOZ_ALWAYS_TRUE( 69 moduleMeta->addDefinedFunc(std::move(params), std::move(results), true, 70 mozilla::Some(std::move(expName)))); 71 MOZ_ALWAYS_TRUE(moduleMeta->prepareForCompile(compilerEnv.mode())); 72 73 ModuleGenerator mg(*codeMeta, compilerEnv, compilerEnv.initialState(), 74 nullptr, nullptr, nullptr); 75 MOZ_ALWAYS_TRUE(mg.initializeCompleteTier()); 76 77 // Build function and keep bytecode around until the end. 78 Bytes bytecode; 79 { 80 Encoder encoder(bytecode); 81 MOZ_ALWAYS_TRUE(EncodeLocalEntries(encoder, ValTypeVector())); 82 MOZ_ALWAYS_TRUE(encoder.writeOp(Op::F64Const) && 83 encoder.writeFixedF64(42.3)); 84 MOZ_ALWAYS_TRUE(encoder.writeOp(Op::Call) && encoder.writeVarU32(0)); 85 MOZ_ALWAYS_TRUE(encoder.writeOp(Op::End)); 86 } 87 MOZ_ALWAYS_TRUE(mg.compileFuncDef(1, 0, bytecode.begin(), 88 bytecode.begin() + bytecode.length())); 89 MOZ_ALWAYS_TRUE(mg.finishFuncDefs()); 90 91 SharedModule module = mg.finishModule(BytecodeBufferOrSource(), *moduleMeta, 92 /*maybeTier2Listener=*/nullptr); 93 MOZ_ALWAYS_TRUE(module); 94 95 MOZ_ASSERT(module->moduleMeta().imports.length() == 1); 96 MOZ_ASSERT(module->moduleMeta().exports.length() == 1); 97 98 // Instantiate and run. 99 { 100 Rooted<ImportValues> imports(cx); 101 RootedFunction func(cx, NewNativeFunction(cx, TestTruncFn, 0, nullptr)); 102 MOZ_ALWAYS_TRUE(func); 103 MOZ_ALWAYS_TRUE(imports.get().funcs.append(func)); 104 105 Rooted<WasmInstanceObject*> instance(cx); 106 MOZ_ALWAYS_TRUE(module->instantiate(cx, imports.get(), nullptr, &instance)); 107 RootedFunction wasmFunc(cx); 108 MOZ_ALWAYS_TRUE( 109 WasmInstanceObject::getExportedFunction(cx, instance, 1, &wasmFunc)); 110 111 JSAutoRealm ar(cx, wasmFunc); 112 RootedValue rval(cx); 113 RootedValue fval(cx); 114 MOZ_ALWAYS_TRUE( 115 JS::Call(cx, fval, wasmFunc, JS::HandleValueArray::empty(), &rval)); 116 MOZ_RELEASE_ASSERT(rval.toInt32() == 42); 117 } 118 return true; 119 } 120 END_TEST(testWasmEncodeBasic)