mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1243252 - Baldr: refactor exports (r=bbouvier)
This commit is contained in:
parent
1cc2cd5959
commit
3ed0e03775
@ -7411,8 +7411,11 @@ CheckBuffer(JSContext* cx, AsmJSModule& module, HandleValue bufferVal,
|
||||
}
|
||||
|
||||
static bool
|
||||
DynamicallyLinkModule(JSContext* cx, const CallArgs& args, AsmJSModule& module)
|
||||
DynamicallyLinkModule(JSContext* cx, const CallArgs& args, Handle<WasmModuleObject*> moduleObj,
|
||||
MutableHandleObject exportObj)
|
||||
{
|
||||
AsmJSModule& module = moduleObj->module().asAsmJS();
|
||||
|
||||
HandleValue globalVal = args.get(0);
|
||||
HandleValue importVal = args.get(1);
|
||||
HandleValue bufferVal = args.get(2);
|
||||
@ -7469,7 +7472,7 @@ DynamicallyLinkModule(JSContext* cx, const CallArgs& args, AsmJSModule& module)
|
||||
return false;
|
||||
}
|
||||
|
||||
return module.dynamicallyLink(cx, buffer, imports);
|
||||
return module.dynamicallyLink(cx, moduleObj, buffer, imports, module.exportMap(), exportObj);
|
||||
}
|
||||
|
||||
static bool
|
||||
@ -7579,19 +7582,14 @@ LinkAsmJS(JSContext* cx, unsigned argc, JS::Value* vp)
|
||||
// asm.js spec and then patching the generated module to associate it with
|
||||
// the given heap (ArrayBuffer) and a new global data segment (the closure
|
||||
// state shared by the inner asm.js functions).
|
||||
if (!DynamicallyLinkModule(cx, args, *module)) {
|
||||
RootedObject exportObj(cx);
|
||||
if (!DynamicallyLinkModule(cx, args, moduleObj, &exportObj)) {
|
||||
// Linking failed, so reparse the entire asm.js module from scratch to
|
||||
// get normal interpreted bytecode which we can simply Invoke. Very slow.
|
||||
RootedPropertyName name(cx, fun->name());
|
||||
return HandleDynamicLinkFailure(cx, args, *module, name);
|
||||
}
|
||||
|
||||
// Link-time validation succeed!
|
||||
|
||||
RootedObject exportObj(cx);
|
||||
if (!module->createExportObject(cx, moduleObj, module->exportMap(), &exportObj))
|
||||
return false;
|
||||
|
||||
args.rval().set(ObjectValue(*exportObj));
|
||||
return true;
|
||||
}
|
||||
|
@ -674,11 +674,8 @@ WasmEval(JSContext* cx, unsigned argc, Value* vp)
|
||||
if (module.imports().length() > 0)
|
||||
return Fail(cx, "Imports not implemented yet");
|
||||
|
||||
if (!module.dynamicallyLink(cx, heap, imports))
|
||||
return false;
|
||||
|
||||
RootedObject exportObj(cx);
|
||||
if (!module.createExportObject(cx, moduleObj, exportMap, &exportObj))
|
||||
if (!module.dynamicallyLink(cx, moduleObj, heap, imports, exportMap, &exportObj))
|
||||
return false;
|
||||
|
||||
args.rval().setObject(*exportObj);
|
||||
|
@ -1066,10 +1066,99 @@ Module::staticallyLink(ExclusiveContext* cx, const StaticLinkData& linkData)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
Module::dynamicallyLink(JSContext* cx, Handle<ArrayBufferObjectMaybeShared*> heap,
|
||||
Handle<FunctionVector> importArgs)
|
||||
static bool
|
||||
WasmCall(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
RootedFunction callee(cx, &args.callee().as<JSFunction>());
|
||||
|
||||
Module& module = ExportedFunctionToModuleObject(callee)->module();
|
||||
uint32_t exportIndex = ExportedFunctionToIndex(callee);
|
||||
|
||||
return module.callExport(cx, exportIndex, args);
|
||||
}
|
||||
|
||||
static JSFunction*
|
||||
NewExportedFunction(JSContext* cx, Handle<WasmModuleObject*> moduleObj, const ExportMap& exportMap,
|
||||
uint32_t exportIndex)
|
||||
{
|
||||
unsigned numArgs = moduleObj->module().exports()[exportIndex].sig().args().length();
|
||||
|
||||
const char* chars = exportMap.exportNames[exportIndex].get();
|
||||
RootedAtom name(cx, AtomizeUTF8Chars(cx, chars, strlen(chars)));
|
||||
if (!name)
|
||||
return nullptr;
|
||||
|
||||
JSFunction* fun = NewNativeConstructor(cx, WasmCall, numArgs, name,
|
||||
gc::AllocKind::FUNCTION_EXTENDED, GenericObject,
|
||||
JSFunction::ASMJS_CTOR);
|
||||
if (!fun)
|
||||
return nullptr;
|
||||
|
||||
fun->setExtendedSlot(FunctionExtended::WASM_MODULE_SLOT, ObjectValue(*moduleObj));
|
||||
fun->setExtendedSlot(FunctionExtended::WASM_EXPORT_INDEX_SLOT, Int32Value(exportIndex));
|
||||
return fun;
|
||||
}
|
||||
|
||||
static bool
|
||||
CreateExportObject(JSContext* cx, Handle<WasmModuleObject*> moduleObj, const ExportMap& exportMap,
|
||||
const ExportVector& exports, MutableHandleObject exportObj)
|
||||
{
|
||||
MOZ_ASSERT(exportMap.exportNames.length() == exports.length());
|
||||
MOZ_ASSERT(exportMap.fieldNames.length() == exportMap.fieldsToExports.length());
|
||||
|
||||
for (size_t fieldIndex = 0; fieldIndex < exportMap.fieldNames.length(); fieldIndex++) {
|
||||
const char* fieldName = exportMap.fieldNames[fieldIndex].get();
|
||||
if (!*fieldName) {
|
||||
MOZ_ASSERT(!exportObj);
|
||||
uint32_t exportIndex = exportMap.fieldsToExports[fieldIndex];
|
||||
exportObj.set(NewExportedFunction(cx, moduleObj, exportMap, exportIndex));
|
||||
if (!exportObj)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Rooted<ValueVector> vals(cx, ValueVector(cx));
|
||||
for (size_t exportIndex = 0; exportIndex < exports.length(); exportIndex++) {
|
||||
JSFunction* fun = NewExportedFunction(cx, moduleObj, exportMap, exportIndex);
|
||||
if (!fun || !vals.append(ObjectValue(*fun)))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!exportObj) {
|
||||
exportObj.set(JS_NewPlainObject(cx));
|
||||
if (!exportObj)
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t fieldIndex = 0; fieldIndex < exportMap.fieldNames.length(); fieldIndex++) {
|
||||
const char* fieldName = exportMap.fieldNames[fieldIndex].get();
|
||||
if (!*fieldName)
|
||||
continue;
|
||||
|
||||
JSAtom* atom = AtomizeUTF8Chars(cx, fieldName, strlen(fieldName));
|
||||
if (!atom)
|
||||
return false;
|
||||
|
||||
RootedId id(cx, AtomToId(atom));
|
||||
HandleValue val = vals[exportMap.fieldsToExports[fieldIndex]];
|
||||
if (!JS_DefinePropertyById(cx, exportObj, id, val, JSPROP_ENUMERATE))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
Module::dynamicallyLink(JSContext* cx,
|
||||
Handle<WasmModuleObject*> moduleObj,
|
||||
Handle<ArrayBufferObjectMaybeShared*> heap,
|
||||
Handle<FunctionVector> importArgs,
|
||||
const ExportMap& exportMap,
|
||||
MutableHandleObject exportObj)
|
||||
{
|
||||
MOZ_ASSERT(this == &moduleObj->module());
|
||||
MOZ_ASSERT(staticallyLinked_);
|
||||
MOZ_ASSERT(!dynamicallyLinked_);
|
||||
dynamicallyLinked_ = true;
|
||||
@ -1101,93 +1190,10 @@ Module::dynamicallyLink(JSContext* cx, Handle<ArrayBufferObjectMaybeShared*> hea
|
||||
return false;
|
||||
}
|
||||
|
||||
return sendCodeRangesToProfiler(cx);
|
||||
}
|
||||
if (!sendCodeRangesToProfiler(cx))
|
||||
return false;
|
||||
|
||||
static bool
|
||||
WasmCall(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
RootedFunction callee(cx, &args.callee().as<JSFunction>());
|
||||
|
||||
Module& module = ExportedFunctionToModuleObject(callee)->module();
|
||||
uint32_t exportIndex = ExportedFunctionToIndex(callee);
|
||||
|
||||
return module.callExport(cx, exportIndex, args);
|
||||
}
|
||||
|
||||
static JSFunction*
|
||||
NewExportedFunction(JSContext* cx, Handle<WasmModuleObject*> moduleObj, const ExportMap& map,
|
||||
uint32_t exportIndex)
|
||||
{
|
||||
unsigned numArgs = moduleObj->module().exports()[exportIndex].sig().args().length();
|
||||
|
||||
const char* chars = map.exportNames[exportIndex].get();
|
||||
RootedAtom name(cx, AtomizeUTF8Chars(cx, chars, strlen(chars)));
|
||||
if (!name)
|
||||
return nullptr;
|
||||
|
||||
JSFunction* fun = NewNativeConstructor(cx, WasmCall, numArgs, name,
|
||||
gc::AllocKind::FUNCTION_EXTENDED, GenericObject,
|
||||
JSFunction::ASMJS_CTOR);
|
||||
if (!fun)
|
||||
return nullptr;
|
||||
|
||||
fun->setExtendedSlot(FunctionExtended::WASM_MODULE_SLOT, ObjectValue(*moduleObj));
|
||||
fun->setExtendedSlot(FunctionExtended::WASM_EXPORT_INDEX_SLOT, Int32Value(exportIndex));
|
||||
return fun;
|
||||
}
|
||||
|
||||
bool
|
||||
Module::createExportObject(JSContext* cx, Handle<WasmModuleObject*> moduleObj,
|
||||
const ExportMap& map, MutableHandleObject exportObj)
|
||||
{
|
||||
MOZ_ASSERT(this == &moduleObj->module());
|
||||
MOZ_ASSERT(map.exportNames.length() == exports().length());
|
||||
MOZ_ASSERT(map.fieldNames.length() == map.fieldsToExports.length());
|
||||
|
||||
for (size_t fieldIndex = 0; fieldIndex < map.fieldNames.length(); fieldIndex++) {
|
||||
const char* fieldName = map.fieldNames[fieldIndex].get();
|
||||
if (!*fieldName) {
|
||||
MOZ_ASSERT_IF(isAsmJS(), exports().length() == 1);
|
||||
MOZ_ASSERT(!exportObj);
|
||||
uint32_t exportIndex = map.fieldsToExports[fieldIndex];
|
||||
exportObj.set(NewExportedFunction(cx, moduleObj, map, exportIndex));
|
||||
if (!exportObj)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Rooted<ValueVector> vals(cx, ValueVector(cx));
|
||||
for (size_t exportIndex = 0; exportIndex < exports().length(); exportIndex++) {
|
||||
JSFunction* fun = NewExportedFunction(cx, moduleObj, map, exportIndex);
|
||||
if (!fun || !vals.append(ObjectValue(*fun)))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!exportObj) {
|
||||
exportObj.set(JS_NewPlainObject(cx));
|
||||
if (!exportObj)
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t fieldIndex = 0; fieldIndex < map.fieldNames.length(); fieldIndex++) {
|
||||
const char* fieldName = map.fieldNames[fieldIndex].get();
|
||||
if (!*fieldName)
|
||||
continue;
|
||||
|
||||
JSAtom* atom = AtomizeUTF8Chars(cx, fieldName, strlen(fieldName));
|
||||
if (!atom)
|
||||
return false;
|
||||
|
||||
RootedId id(cx, AtomToId(atom));
|
||||
HandleValue val = vals[map.fieldsToExports[fieldIndex]];
|
||||
if (!JS_DefinePropertyById(cx, exportObj, id, val, JSPROP_ENUMERATE))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return CreateExportObject(cx, moduleObj, exportMap, exports(), exportObj);
|
||||
}
|
||||
|
||||
SharedMem<uint8_t*>
|
||||
|
@ -534,16 +534,14 @@ class Module
|
||||
// This function transitions the module from a statically-linked state to a
|
||||
// dynamically-linked state. If this module usesHeap(), a non-null heap
|
||||
// buffer must be given. The given import vector must match the module's
|
||||
// ImportVector.
|
||||
// ImportVector. The function returns a new export object for this module.
|
||||
|
||||
bool dynamicallyLink(JSContext* cx, Handle<ArrayBufferObjectMaybeShared*> heap,
|
||||
Handle<FunctionVector> imports);
|
||||
|
||||
// This function creates and returns a new export object for this module.
|
||||
// The lengths of exports() and map.exportNames must be the same.
|
||||
|
||||
bool createExportObject(JSContext* cx, Handle<WasmModuleObject*> moduleObj,
|
||||
const ExportMap& map, MutableHandleObject exportObj);
|
||||
bool dynamicallyLink(JSContext* cx,
|
||||
Handle<WasmModuleObject*> moduleObj,
|
||||
Handle<ArrayBufferObjectMaybeShared*> heap,
|
||||
Handle<FunctionVector> imports,
|
||||
const ExportMap& exportMap,
|
||||
MutableHandleObject exportObj);
|
||||
|
||||
// The wasm heap, established by dynamicallyLink.
|
||||
|
||||
|
@ -34,7 +34,6 @@ using namespace js;
|
||||
using namespace js::wasm;
|
||||
using mozilla::CheckedInt;
|
||||
using mozilla::Maybe;
|
||||
using mozilla::Range;
|
||||
|
||||
static const unsigned AST_LIFO_DEFAULT_CHUNK_SIZE = 4096;
|
||||
|
||||
@ -216,31 +215,15 @@ class WasmAstFunc : public WasmAstNode
|
||||
|
||||
class WasmAstExport : public WasmAstNode
|
||||
{
|
||||
const char16_t* const externalName_;
|
||||
const size_t externalNameLength_;
|
||||
uint32_t internalIndex_;
|
||||
TwoByteChars name_;
|
||||
uint32_t funcIndex_;
|
||||
|
||||
public:
|
||||
WasmAstExport(const char16_t* externalNameBegin,
|
||||
const char16_t* externalNameEnd)
|
||||
: WasmAstNode(WasmAstKind::Export),
|
||||
externalName_(externalNameBegin),
|
||||
externalNameLength_(externalNameEnd - externalNameBegin),
|
||||
internalIndex_(UINT32_MAX)
|
||||
{
|
||||
MOZ_ASSERT(externalNameBegin <= externalNameEnd);
|
||||
}
|
||||
const char16_t* externalName() const { return externalName_; }
|
||||
size_t externalNameLength() const { return externalNameLength_; }
|
||||
|
||||
void initInternalIndex(uint32_t internalIndex) {
|
||||
MOZ_ASSERT(internalIndex_ == UINT32_MAX);
|
||||
internalIndex_ = internalIndex;
|
||||
}
|
||||
size_t internalIndex() const {
|
||||
MOZ_ASSERT(internalIndex_ != UINT32_MAX);
|
||||
return internalIndex_;
|
||||
}
|
||||
WasmAstExport(TwoByteChars name, uint32_t funcIndex)
|
||||
: WasmAstNode(WasmAstKind::Export), name_(name), funcIndex_(funcIndex)
|
||||
{}
|
||||
TwoByteChars name() const { return name_; }
|
||||
size_t funcIndex() const { return funcIndex_; }
|
||||
};
|
||||
|
||||
class WasmAstModule : public WasmAstNode
|
||||
@ -372,15 +355,12 @@ class WasmToken
|
||||
const char16_t* end() const {
|
||||
return end_;
|
||||
}
|
||||
const char16_t* textBegin() const {
|
||||
TwoByteChars text() const {
|
||||
MOZ_ASSERT(kind_ == Text);
|
||||
MOZ_ASSERT(begin_[0] == '"');
|
||||
return begin_ + 1;
|
||||
}
|
||||
const char16_t* textEnd() const {
|
||||
MOZ_ASSERT(kind_ == Text);
|
||||
MOZ_ASSERT(end_[-1] == '"');
|
||||
return end_ - 1;
|
||||
MOZ_ASSERT(end_ - begin_ >= 2);
|
||||
return TwoByteChars(begin_ + 1, end_ - begin_ - 2);
|
||||
}
|
||||
uint32_t integer() const {
|
||||
MOZ_ASSERT(kind_ == Integer);
|
||||
@ -818,25 +798,15 @@ ParseFunc(WasmParseContext& c, WasmAstModule* module)
|
||||
static WasmAstExport*
|
||||
ParseExport(WasmParseContext& c)
|
||||
{
|
||||
WasmToken externalName;
|
||||
if (!c.ts.match(WasmToken::Text, &externalName, c.error))
|
||||
WasmToken name;
|
||||
if (!c.ts.match(WasmToken::Text, &name, c.error))
|
||||
return nullptr;
|
||||
|
||||
auto exp = new(c.lifo) WasmAstExport(externalName.textBegin(), externalName.textEnd());
|
||||
if (!exp)
|
||||
WasmToken funcIndex;
|
||||
if (!c.ts.match(WasmToken::Integer, &funcIndex, c.error))
|
||||
return nullptr;
|
||||
|
||||
WasmToken internalName = c.ts.get();
|
||||
switch (internalName.kind()) {
|
||||
case WasmToken::Integer:
|
||||
exp->initInternalIndex(internalName.integer());
|
||||
break;
|
||||
default:
|
||||
c.ts.generateError(internalName, c.error);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return exp;
|
||||
return new(c.lifo) WasmAstExport(name.text(), funcIndex.integer());
|
||||
}
|
||||
|
||||
static WasmAstModule*
|
||||
@ -1024,15 +994,14 @@ EncodeExport(Encoder& e, WasmAstExport& exp)
|
||||
if (!e.writeCString(FuncSubsection))
|
||||
return false;
|
||||
|
||||
if (!e.writeVarU32(exp.internalIndex()))
|
||||
if (!e.writeVarU32(exp.funcIndex()))
|
||||
return false;
|
||||
|
||||
Range<const char16_t> twoByte(exp.externalName(), exp.externalNameLength());
|
||||
UniqueChars utf8(JS::CharsToNewUTF8CharsZ(nullptr, twoByte).c_str());
|
||||
if (!utf8)
|
||||
UniqueChars utf8Name(JS::CharsToNewUTF8CharsZ(nullptr, exp.name()).c_str());
|
||||
if (!utf8Name)
|
||||
return false;
|
||||
|
||||
if (!e.writeCString(utf8.get()))
|
||||
if (!e.writeCString(utf8Name.get()))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
Loading…
Reference in New Issue
Block a user