Пример #1
0
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;
}