summaryrefslogtreecommitdiffstats
path: root/js/src/builtin/TestingFunctions.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/builtin/TestingFunctions.cpp')
-rw-r--r--js/src/builtin/TestingFunctions.cpp146
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,