bool Module::instantiate(JSContext* cx, Handle<FunctionVector> funcImports, HandleWasmTableObject tableImport, HandleWasmMemoryObject memoryImport, const ValVector& globalImports, HandleObject instanceProto, MutableHandleWasmInstanceObject instanceObj) const { MOZ_ASSERT(funcImports.length() == metadata_->funcImports.length()); RootedWasmMemoryObject memory(cx, memoryImport); if (!instantiateMemory(cx, &memory)) return false; auto codeSegment = CodeSegment::create(cx, code_, linkData_, *metadata_, memory); if (!codeSegment) return false; SharedTableVector tables; if (!instantiateTable(cx, tableImport, &tables)) return false; // To support viewing the source of an instance (Instance::createText), the // instance must hold onto a ref of the bytecode (keeping it alive). This // wastes memory for most users, so we try to only save the source when a // developer actually cares: when the compartment is debuggable (which is // true when the web console is open) or a names section is present (since // this going to be stripped for non-developer builds). const ShareableBytes* maybeBytecode = nullptr; if (cx->compartment()->isDebuggee() || !metadata_->funcNames.empty()) maybeBytecode = bytecode_.get(); // Create the Instance, ensuring that it is traceable via 'instanceObj' // before any GC can occur and invalidate the pointers stored in global // memory. { instanceObj.set(WasmInstanceObject::create(cx, instanceProto)); if (!instanceObj) return false; auto instance = cx->make_unique<Instance>(cx, Move(codeSegment), *metadata_, maybeBytecode, memory, Move(tables), funcImports, globalImports); if (!instance) return false; instanceObj->init(Move(instance)); } if (!instanceObj->instance().init(cx)) return false; // Create the export object. RootedObject exportObj(cx); RootedWasmTableObject table(cx, tableImport); if (!CreateExportObject(cx, instanceObj, &table, memory, globalImports, exports_, &exportObj)) return false; JSAtom* atom = Atomize(cx, InstanceExportField, strlen(InstanceExportField)); if (!atom) return false; RootedId id(cx, AtomToId(atom)); RootedValue val(cx, ObjectValue(*exportObj)); if (!JS_DefinePropertyById(cx, instanceObj, id, val, JSPROP_ENUMERATE)) return false; // Initialize table elements only after the instance is fully initialized // since the Table object needs to point to a valid instance object. Perform // initialization as the final step after the instance is fully live since // it is observable (in the case of an imported Table object). if (!initElems(cx, instanceObj, globalImports, table)) return false; // Done! Notify the Debugger of the new Instance. Debugger::onNewWasmInstance(cx, instanceObj); // Call the start function, if there's one. By specification, it does not // take any arguments nor does it return a value, so just create a dummy // arguments object. if (metadata_->hasStartFunction()) { FixedInvokeArgs<0> args(cx); if (!instanceObj->instance().callExport(cx, metadata_->startFuncIndex(), args)) return false; } return true; }
bool Module::instantiate(JSContext* cx, Handle<FunctionVector> funcImports, HandleWasmTableObject tableImport, HandleWasmMemoryObject memoryImport, const ValVector& globalImports, HandleObject instanceProto, MutableHandleWasmInstanceObject instance) const { if (!instantiateFunctions(cx, funcImports)) return false; RootedWasmMemoryObject memory(cx, memoryImport); if (!instantiateMemory(cx, &memory)) return false; RootedWasmTableObject table(cx, tableImport); SharedTableVector tables; if (!instantiateTable(cx, &table, &tables)) return false; // To support viewing the source of an instance (Instance::createText), the // instance must hold onto a ref of the bytecode (keeping it alive). This // wastes memory for most users, so we try to only save the source when a // developer actually cares: when the compartment is debuggable (which is // true when the web console is open), has code compiled with debug flag // enabled or a names section is present (since this going to be stripped // for non-developer builds). const ShareableBytes* maybeBytecode = nullptr; if (cx->compartment()->isDebuggee() || metadata_->debugEnabled || !metadata_->funcNames.empty()) { maybeBytecode = bytecode_.get(); } auto codeSegment = CodeSegment::create(cx, code_, linkData_, *metadata_, memory); if (!codeSegment) return false; auto code = cx->make_unique<Code>(Move(codeSegment), *metadata_, maybeBytecode); if (!code) return false; instance.set(WasmInstanceObject::create(cx, Move(code), memory, Move(tables), funcImports, globalImports, instanceProto)); if (!instance) return false; RootedObject exportObj(cx); if (!CreateExportObject(cx, instance, funcImports, table, memory, globalImports, exports_, &exportObj)) return false; JSAtom* atom = Atomize(cx, InstanceExportField, strlen(InstanceExportField)); if (!atom) return false; RootedId id(cx, AtomToId(atom)); RootedValue val(cx, ObjectValue(*exportObj)); if (!JS_DefinePropertyById(cx, instance, id, val, JSPROP_ENUMERATE)) return false; // Register the instance with the JSCompartment so that it can find out // about global events like profiling being enabled in the compartment. // Registration does not require a fully-initialized instance and must // precede initSegments as the final pre-requisite for a live instance. if (!cx->compartment()->wasm.registerInstance(cx, instance)) return false; // Perform initialization as the final step after the instance is fully // constructed since this can make the instance live to content (even if the // start function fails). if (!initSegments(cx, instance, funcImports, memory, globalImports)) return false; // Now that the instance is fully live and initialized, the start function. // Note that failure may cause instantiation to throw, but the instance may // still be live via edges created by initSegments or the start function. if (metadata_->startFuncIndex) { FixedInvokeArgs<0> args(cx); if (!instance->instance().callExport(cx, *metadata_->startFuncIndex, args)) return false; } uint32_t mode = uint32_t(metadata().isAsmJS() ? Telemetry::ASMJS : Telemetry::WASM); cx->runtime()->addTelemetry(JS_TELEMETRY_AOT_USAGE, mode); return true; }