зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1545086: Merge wasm exported function info to not overwrite the explicit bit; r=luke
Differential Revision: https://phabricator.services.mozilla.com/D28068 --HG-- extra : rebase_source : 1974157bae9a8da8ec9d68948a963b8dfd43899b extra : amend_source : 9ef2cf0eae089258687e8cd8c4841fc07cea8911
This commit is contained in:
Родитель
d64c6bcba1
Коммит
e6b10a7881
|
@ -0,0 +1,6 @@
|
|||
wasmEvalText(`(module
|
||||
(func)
|
||||
(start 0)
|
||||
(table $0 1 anyfunc)
|
||||
(elem 0 (i32.const 0) 0)
|
||||
)`);
|
|
@ -307,19 +307,23 @@ bool ModuleGenerator::init(Metadata* maybeAsmJSMetadata) {
|
|||
global.setOffset(globalDataOffset);
|
||||
}
|
||||
|
||||
// Accumulate all exported functions, whether by explicit export or
|
||||
// implicitly by being an element of a function table or by being the start
|
||||
// function. The FuncExportVector stored in Metadata needs to be sorted (to
|
||||
// allow O(log(n)) lookup at runtime) and deduplicated, so use an
|
||||
// intermediate vector to sort and de-duplicate.
|
||||
// Accumulate all exported functions:
|
||||
// - explicitly marked as such;
|
||||
// - implicitly exported by being an element of function tables;
|
||||
// - implicitly exported by being the start function;
|
||||
// The FuncExportVector stored in Metadata needs to be sorted (to allow
|
||||
// O(log(n)) lookup at runtime) and deduplicated. Use a vector with invalid
|
||||
// entries for every single function, that we'll fill as we go through the
|
||||
// exports, and in which we'll remove invalid entries after the fact.
|
||||
|
||||
static_assert((uint64_t(MaxFuncs) << 1) < uint64_t(UINT32_MAX),
|
||||
"bit packing won't work");
|
||||
static_assert(((uint64_t(MaxFuncs) << 1) | 1) < uint64_t(UINT32_MAX),
|
||||
"bit packing won't work in ExportedFunc");
|
||||
|
||||
class ExportedFunc {
|
||||
uint32_t value;
|
||||
|
||||
public:
|
||||
ExportedFunc() : value(UINT32_MAX) {}
|
||||
ExportedFunc(uint32_t index, bool isExplicit)
|
||||
: value((index << 1) | (isExplicit ? 1 : 0)) {}
|
||||
uint32_t index() const { return value >> 1; }
|
||||
|
@ -330,31 +334,48 @@ bool ModuleGenerator::init(Metadata* maybeAsmJSMetadata) {
|
|||
bool operator==(const ExportedFunc& other) const {
|
||||
return index() == other.index();
|
||||
}
|
||||
bool isInvalid() const { return value == UINT32_MAX; }
|
||||
void mergeExplicit(bool explicitBit) {
|
||||
if (!isExplicit() && explicitBit) {
|
||||
value |= 0x1;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Vector<ExportedFunc, 8, SystemAllocPolicy> exportedFuncs;
|
||||
if (!exportedFuncs.resize(env_->numFuncs())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto addOrMerge = [&exportedFuncs](ExportedFunc newEntry) {
|
||||
uint32_t index = newEntry.index();
|
||||
if (exportedFuncs[index].isInvalid()) {
|
||||
exportedFuncs[index] = newEntry;
|
||||
} else {
|
||||
exportedFuncs[index].mergeExplicit(newEntry.isExplicit());
|
||||
}
|
||||
};
|
||||
|
||||
for (const Export& exp : env_->exports) {
|
||||
if (exp.kind() == DefinitionKind::Function) {
|
||||
if (!exportedFuncs.emplaceBack(exp.funcIndex(), true)) {
|
||||
return false;
|
||||
}
|
||||
addOrMerge(ExportedFunc(exp.funcIndex(), true));
|
||||
}
|
||||
}
|
||||
|
||||
if (env_->startFuncIndex) {
|
||||
addOrMerge(ExportedFunc(*env_->startFuncIndex, true));
|
||||
}
|
||||
|
||||
for (const ElemSegment* seg : env_->elemSegments) {
|
||||
TableKind kind = !seg->active() ? TableKind::AnyFunction
|
||||
: env_->tables[seg->tableIndex].kind;
|
||||
switch (kind) {
|
||||
case TableKind::AnyFunction:
|
||||
if (!exportedFuncs.reserve(exportedFuncs.length() + seg->length())) {
|
||||
return false;
|
||||
}
|
||||
for (uint32_t funcIndex : seg->elemFuncIndices) {
|
||||
if (funcIndex == NullFuncIndex) {
|
||||
continue;
|
||||
}
|
||||
exportedFuncs.infallibleEmplaceBack(funcIndex, false);
|
||||
addOrMerge(ExportedFunc(funcIndex, false));
|
||||
}
|
||||
break;
|
||||
case TableKind::TypedFunction:
|
||||
|
@ -365,13 +386,9 @@ bool ModuleGenerator::init(Metadata* maybeAsmJSMetadata) {
|
|||
}
|
||||
}
|
||||
|
||||
if (env_->startFuncIndex &&
|
||||
!exportedFuncs.emplaceBack(*env_->startFuncIndex, true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::sort(exportedFuncs.begin(), exportedFuncs.end());
|
||||
auto* newEnd = std::unique(exportedFuncs.begin(), exportedFuncs.end());
|
||||
auto* newEnd =
|
||||
std::remove_if(exportedFuncs.begin(), exportedFuncs.end(),
|
||||
[](const ExportedFunc& exp) { return exp.isInvalid(); });
|
||||
exportedFuncs.erase(newEnd, exportedFuncs.end());
|
||||
|
||||
if (!metadataTier_->funcExports.reserve(exportedFuncs.length())) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче