diff options
Diffstat (limited to 'js/src/builtin/TestingFunctions.cpp')
-rw-r--r-- | js/src/builtin/TestingFunctions.cpp | 146 |
1 files changed, 125 insertions, 21 deletions
diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp index f762f28f3e..498fa1746d 100644 --- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -1595,17 +1595,20 @@ static bool WasmLosslessInvoke(JSContext* cx, unsigned argc, Value* vp) { JS_ReportErrorASCII(cx, "not enough arguments"); return false; } - if (!args.get(0).isObject()) { + if (!args.get(0).isObject() || !args.get(0).toObject().is<JSFunction>()) { JS_ReportErrorASCII(cx, "argument is not an object"); return false; } - RootedFunction func(cx, args[0].toObject().maybeUnwrapIf<JSFunction>()); + RootedFunction func(cx, &args[0].toObject().as<JSFunction>()); if (!func || !wasm::IsWasmExportedFunction(func)) { JS_ReportErrorASCII(cx, "argument is not an exported wasm function"); return false; } + // Switch to the function's realm + AutoRealm ar(cx, func); + // Get the instance and funcIndex for calling the function wasm::Instance& instance = wasm::ExportedFunctionToInstance(func); uint32_t funcIndex = wasm::ExportedFunctionToFuncIndex(func); @@ -2042,6 +2045,95 @@ static bool WasmDisassemble(JSContext* cx, unsigned argc, Value* vp) { return false; } +static bool ToIonDumpContents(JSContext* cx, HandleValue value, + wasm::IonDumpContents* contents) { + RootedString option(cx, JS::ToString(cx, value)); + + if (!option) { + return false; + } + + bool isEqual = false; + if (!JS_StringEqualsLiteral(cx, option, "mir", &isEqual) || isEqual) { + *contents = wasm::IonDumpContents::UnoptimizedMIR; + return isEqual; + } else if (!JS_StringEqualsLiteral(cx, option, "unopt-mir", &isEqual) || + isEqual) { + *contents = wasm::IonDumpContents::UnoptimizedMIR; + return isEqual; + } else if (!JS_StringEqualsLiteral(cx, option, "opt-mir", &isEqual) || + isEqual) { + *contents = wasm::IonDumpContents::OptimizedMIR; + return isEqual; + } else if (!JS_StringEqualsLiteral(cx, option, "lir", &isEqual) || isEqual) { + *contents = wasm::IonDumpContents::LIR; + return isEqual; + } else { + return false; + } +} + +static bool WasmDumpIon(JSContext* cx, unsigned argc, Value* vp) { + if (!wasm::HasSupport(cx)) { + JS_ReportErrorASCII(cx, "wasm support unavailable"); + return false; + } + + CallArgs args = CallArgsFromVp(argc, vp); + + args.rval().set(UndefinedValue()); + + SharedMem<uint8_t*> dataPointer; + size_t byteLength; + if (!args.get(0).isObject() || !IsBufferSource(args.get(0).toObjectOrNull(), + &dataPointer, &byteLength)) { + JS_ReportErrorASCII(cx, "argument is not a buffer source"); + return false; + } + + uint32_t targetFuncIndex; + if (!ToUint32(cx, args.get(1), &targetFuncIndex)) { + JS_ReportErrorASCII(cx, "argument is not a func index"); + return false; + } + + wasm::IonDumpContents contents = wasm::IonDumpContents::Default; + if (args.length() > 2 && !ToIonDumpContents(cx, args.get(2), &contents)) { + JS_ReportErrorASCII(cx, "argument is not a valid dump contents"); + return false; + } + + wasm::MutableBytes bytecode = cx->new_<wasm::ShareableBytes>(); + if (!bytecode) { + return false; + } + if (!bytecode->append(dataPointer.unwrap(), byteLength)) { + ReportOutOfMemory(cx); + return false; + } + + UniqueChars error; + JSSprinter out(cx); + if (!out.init()) { + ReportOutOfMemory(cx); + return false; + } + + if (!wasm::DumpIonFunctionInModule(*bytecode, targetFuncIndex, contents, out, + &error)) { + if (error) { + JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, + JSMSG_WASM_COMPILE_ERROR, error.get()); + return false; + } + ReportOutOfMemory(cx); + return false; + } + + args.rval().set(StringValue(out.release(cx))); + return true; +} + enum class Flag { Tier2Complete, Deserialized }; static bool WasmReturnFlag(JSContext* cx, unsigned argc, Value* vp, Flag flag) { @@ -2073,7 +2165,6 @@ static bool WasmReturnFlag(JSContext* cx, unsigned argc, Value* vp, Flag flag) { return true; } -#if defined(DEBUG) static bool wasmMetadataAnalysis(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); @@ -2082,10 +2173,6 @@ static bool wasmMetadataAnalysis(JSContext* cx, unsigned argc, Value* vp) { return false; } - if (!cx->options().wasmTestMetadata()) { - return false; - } - if (args[0].toObject().is<WasmModuleObject>()) { HashMap<const char*, uint32_t, mozilla::CStringHasher, SystemAllocPolicy> hashmap = args[0] @@ -2096,6 +2183,7 @@ static bool wasmMetadataAnalysis(JSContext* cx, unsigned argc, Value* vp) { .metadataAnalysis(cx); if (hashmap.empty()) { JS_ReportErrorASCII(cx, "Metadata analysis has failed"); + return false; } // metadataAnalysis returned a map of {key, value} with various statistics @@ -2107,16 +2195,21 @@ static bool wasmMetadataAnalysis(JSContext* cx, unsigned argc, Value* vp) { auto value = iter.get().value(); JSString* string = JS_NewStringCopyZ(cx, key); + if (!string) { + return false; + } + if (!props.append( IdValuePair(NameToId(string->asLinear().toPropertyName(cx)), NumberValue(value)))) { - ReportOutOfMemory(cx); return false; } } - JSObject* results = - NewPlainObjectWithUniqueNames(cx, props.begin(), props.length()); + JSObject* results = NewPlainObjectWithUniqueNames(cx, props); + if (!results) { + return false; + } args.rval().setObject(*results); return true; @@ -2127,7 +2220,6 @@ static bool wasmMetadataAnalysis(JSContext* cx, unsigned argc, Value* vp) { return false; } -#endif static bool WasmHasTier2CompilationCompleted(JSContext* cx, unsigned argc, Value* vp) { @@ -4523,7 +4615,9 @@ static bool ReadGeckoProfilingStack(JSContext* cx, unsigned argc, Value* vp) { case JS::ProfilingFrameIterator::Frame_Ion: frameKindStr = "ion"; break; - case JS::ProfilingFrameIterator::Frame_Wasm: + case JS::ProfilingFrameIterator::Frame_WasmBaseline: + case JS::ProfilingFrameIterator::Frame_WasmIon: + case JS::ProfilingFrameIterator::Frame_WasmOther: frameKindStr = "wasm"; break; default: @@ -5264,15 +5358,17 @@ class CustomSerializableObject : public NativeObject { static ActivityLog* getThreadLog() { if (!self.initialized() || !self.get()) { self.infallibleInit(); + AutoEnterOOMUnsafeRegion oomUnsafe; self.set(js_new<ActivityLog>()); - MOZ_RELEASE_ASSERT(self.get()); + if (!self.get()) { + oomUnsafe.crash("allocating activity log"); + } if (!TlsContext.get()->runtime()->atExit( [](void* vpData) { auto* log = static_cast<ActivityLog*>(vpData); js_delete(log); }, self.get())) { - AutoEnterOOMUnsafeRegion oomUnsafe; oomUnsafe.crash("atExit"); } } @@ -7199,6 +7295,8 @@ static bool CompileToStencil(JSContext* cx, uint32_t argc, Value* vp) { } CompileOptions options(cx); + options.setFile("<compileToStencil>"); + RootedString displayURL(cx); RootedString sourceMapURL(cx); UniqueChars fileNameBytes; @@ -7230,13 +7328,10 @@ static bool CompileToStencil(JSContext* cx, uint32_t argc, Value* vp) { AutoReportFrontendContext fc(cx); RefPtr<JS::Stencil> stencil; - JS::CompilationStorage compileStorage; if (isModule) { - stencil = - JS::CompileModuleScriptToStencil(&fc, options, srcBuf, compileStorage); + stencil = JS::CompileModuleScriptToStencil(&fc, options, srcBuf); } else { - stencil = - JS::CompileGlobalScriptToStencil(&fc, options, srcBuf, compileStorage); + stencil = JS::CompileGlobalScriptToStencil(&fc, options, srcBuf); } if (!stencil) { return false; @@ -7368,6 +7463,8 @@ static bool CompileToStencilXDR(JSContext* cx, uint32_t argc, Value* vp) { } CompileOptions options(cx); + options.setFile("<compileToStencilXDR>"); + RootedString displayURL(cx); RootedString sourceMapURL(cx); UniqueChars fileNameBytes; @@ -9750,6 +9847,15 @@ JS_FOR_WASM_FEATURES(WASM_FEATURE) " ImportJitExit - wasm-to-jitted-JS stubs\n" " all - all kinds, including obscure ones\n"), + JS_FN_HELP("wasmDumpIon", WasmDumpIon, 2, 0, +"wasmDumpIon(bytecode, funcIndex, [, contents])\n", +"wasmDumpIon(bytecode, funcIndex, [, contents])" +" Returns a dump of compiling a function in the specified module with Ion." +" The `contents` flag controls what is dumped. one of:" +" `mir` | `unopt-mir`: Unoptimized MIR (the default)" +" `opt-mir`: Optimized MIR" +" `lir`: LIR"), + JS_FN_HELP("wasmHasTier2CompilationCompleted", WasmHasTier2CompilationCompleted, 1, 0, "wasmHasTier2CompilationCompleted(module)", " Returns a boolean indicating whether a given module has finished compiled code for tier2. \n" @@ -9948,11 +10054,9 @@ JS_FOR_WASM_FEATURES(WASM_FEATURE) " element's edge is the node of the i+1'th array element; the destination of\n" " the last array element is implicitly |target|.\n"), -#if defined(DEBUG) JS_FN_HELP("wasmMetadataAnalysis", wasmMetadataAnalysis, 1, 0, "wasmMetadataAnalysis(wasmObject)", " Prints an analysis of the size of metadata on this wasm object.\n"), -#endif #if defined(DEBUG) || defined(JS_JITSPEW) JS_FN_HELP("dumpObject", DumpObject, 1, 0, |