mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-26 20:30:41 +00:00
Bug 1292724 - Baldr: simplify elem segments (r=sunfish)
MozReview-Commit-ID: 4DCTydSm1ew --HG-- extra : rebase_source : 5b326573d02e1f731e0bbdee8f51c1c142cea94d
This commit is contained in:
parent
4067fc4876
commit
c7f11b44a9
@ -1319,7 +1319,7 @@ DecodeElemSection(Decoder& d, bool newFormat, Uint32Vector&& oldElems, ModuleGen
|
||||
return true;
|
||||
}
|
||||
|
||||
return mg.addElemSegment(ElemSegment(0, InitExpr(Val(uint32_t(0))), Move(oldElems)));
|
||||
return mg.addElemSegment(InitExpr(Val(uint32_t(0))), Move(oldElems));
|
||||
}
|
||||
|
||||
uint32_t sectionStart, sectionSize;
|
||||
@ -1336,44 +1336,47 @@ DecodeElemSection(Decoder& d, bool newFormat, Uint32Vector&& oldElems, ModuleGen
|
||||
return Fail(d, "too many elem segments");
|
||||
|
||||
for (uint32_t i = 0, prevEnd = 0; i < numSegments; i++) {
|
||||
ElemSegment seg;
|
||||
if (!d.readVarU32(&seg.tableIndex))
|
||||
uint32_t tableIndex;
|
||||
if (!d.readVarU32(&tableIndex))
|
||||
return Fail(d, "expected table index");
|
||||
|
||||
if (seg.tableIndex >= mg.tables().length())
|
||||
MOZ_ASSERT(mg.tables().length() <= 1);
|
||||
if (tableIndex >= mg.tables().length())
|
||||
return Fail(d, "table index out of range");
|
||||
|
||||
if (!DecodeInitializerExpression(d, mg.globals(), ValType::I32, &seg.offset))
|
||||
InitExpr offset;
|
||||
if (!DecodeInitializerExpression(d, mg.globals(), ValType::I32, &offset))
|
||||
return false;
|
||||
|
||||
if (seg.offset.isVal() && seg.offset.val().i32() < prevEnd)
|
||||
if (offset.isVal() && offset.val().i32() < prevEnd)
|
||||
return Fail(d, "elem segments must be disjoint and ordered");
|
||||
|
||||
uint32_t numElems;
|
||||
if (!d.readVarU32(&numElems))
|
||||
return Fail(d, "expected segment size");
|
||||
|
||||
uint32_t tableLength = mg.tables()[seg.tableIndex].initial;
|
||||
if (seg.offset.isVal()) {
|
||||
uint32_t offset = seg.offset.val().i32();
|
||||
if (offset > tableLength || tableLength - offset < numElems)
|
||||
uint32_t tableLength = mg.tables()[tableIndex].initial;
|
||||
if (offset.isVal()) {
|
||||
uint32_t off = offset.val().i32();
|
||||
if (off > tableLength || tableLength - off < numElems)
|
||||
return Fail(d, "element segment does not fit");
|
||||
}
|
||||
|
||||
if (!seg.elems.resize(numElems))
|
||||
Uint32Vector elemFuncIndices;
|
||||
if (!elemFuncIndices.resize(numElems))
|
||||
return false;
|
||||
|
||||
for (uint32_t i = 0; i < numElems; i++) {
|
||||
if (!d.readVarU32(&seg.elems[i]))
|
||||
if (!d.readVarU32(&elemFuncIndices[i]))
|
||||
return Fail(d, "failed to read element function index");
|
||||
if (seg.elems[i] >= mg.numFuncSigs())
|
||||
if (elemFuncIndices[i] >= mg.numFuncSigs())
|
||||
return Fail(d, "table element out of range");
|
||||
}
|
||||
|
||||
if (seg.offset.isVal())
|
||||
prevEnd = seg.offset.val().i32() + seg.elems.length();
|
||||
if (offset.isVal())
|
||||
prevEnd = offset.val().i32() + elemFuncIndices.length();
|
||||
|
||||
if (!mg.addElemSegment(Move(seg)))
|
||||
if (!mg.addElemSegment(offset, Move(elemFuncIndices)))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -901,18 +901,26 @@ ModuleGenerator::finishFuncDefs()
|
||||
}
|
||||
|
||||
bool
|
||||
ModuleGenerator::addElemSegment(ElemSegment&& seg)
|
||||
ModuleGenerator::addElemSegment(InitExpr offset, Uint32Vector&& elemFuncIndices)
|
||||
{
|
||||
MOZ_ASSERT(!isAsmJS());
|
||||
MOZ_ASSERT(finishedFuncDefs_);
|
||||
MOZ_ASSERT(shared_->tables.length() == 1);
|
||||
|
||||
if (shared_->tables[0].external) {
|
||||
for (uint32_t funcIndex : seg.elems) {
|
||||
for (uint32_t funcIndex : elemFuncIndices) {
|
||||
if (!exportedFuncs_.put(funcIndex))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return elemSegments_.append(Move(seg));
|
||||
Uint32Vector codeRangeIndices;
|
||||
if (!codeRangeIndices.resize(elemFuncIndices.length()))
|
||||
return false;
|
||||
for (size_t i = 0; i < elemFuncIndices.length(); i++)
|
||||
codeRangeIndices[i] = funcIndexToCodeRange_[elemFuncIndices[i]];
|
||||
|
||||
return elemSegments_.emplaceBack(0, offset, Move(elemFuncIndices), Move(codeRangeIndices));
|
||||
}
|
||||
|
||||
void
|
||||
@ -945,11 +953,19 @@ bool
|
||||
ModuleGenerator::initSigTableElems(uint32_t sigIndex, Uint32Vector&& elemFuncIndices)
|
||||
{
|
||||
MOZ_ASSERT(isAsmJS());
|
||||
MOZ_ASSERT(finishedFuncDefs_);
|
||||
|
||||
uint32_t tableIndex = shared_->asmJSSigToTableIndex[sigIndex];
|
||||
MOZ_ASSERT(shared_->tables[tableIndex].initial == elemFuncIndices.length());
|
||||
|
||||
return elemSegments_.emplaceBack(tableIndex, InitExpr(Val(uint32_t(0))), Move(elemFuncIndices));
|
||||
Uint32Vector codeRangeIndices;
|
||||
if (!codeRangeIndices.resize(elemFuncIndices.length()))
|
||||
return false;
|
||||
for (size_t i = 0; i < elemFuncIndices.length(); i++)
|
||||
codeRangeIndices[i] = funcIndexToCodeRange_[elemFuncIndices[i]];
|
||||
|
||||
InitExpr offset(Val(uint32_t(0)));
|
||||
return elemSegments_.emplaceBack(tableIndex, offset, Move(elemFuncIndices), Move(codeRangeIndices));
|
||||
}
|
||||
|
||||
SharedModule
|
||||
@ -1023,16 +1039,6 @@ ModuleGenerator::finish(const ShareableBytes& bytecode)
|
||||
}
|
||||
#endif
|
||||
|
||||
// Convert function indices to offsets into the code section.
|
||||
// WebAssembly's tables are (currently) all untyped and point to the table
|
||||
// entry. asm.js tables are all typed and thus point to the normal entry.
|
||||
for (ElemSegment& seg : elemSegments_) {
|
||||
for (uint32_t& elem : seg.elems) {
|
||||
const CodeRange& cr = funcCodeRange(elem);
|
||||
elem = isAsmJS() ? cr.funcNonProfilingEntry() : cr.funcTableEntry();
|
||||
}
|
||||
}
|
||||
|
||||
if (!finishLinkData(code))
|
||||
return nullptr;
|
||||
|
||||
|
@ -184,7 +184,7 @@ class MOZ_STACK_CLASS ModuleGenerator
|
||||
|
||||
// Segments:
|
||||
MOZ_MUST_USE bool addDataSegment(DataSegment s) { return dataSegments_.append(s); }
|
||||
MOZ_MUST_USE bool addElemSegment(ElemSegment&& s);
|
||||
MOZ_MUST_USE bool addElemSegment(InitExpr offset, Uint32Vector&& elemFuncIndices);
|
||||
|
||||
// Function names:
|
||||
void setFuncNames(NameInBytecodeVector&& funcNames);
|
||||
|
@ -269,7 +269,8 @@ ElemSegment::serializedSize() const
|
||||
{
|
||||
return sizeof(tableIndex) +
|
||||
sizeof(offset) +
|
||||
SerializedPodVectorSize(elems);
|
||||
SerializedPodVectorSize(elemFuncIndices) +
|
||||
SerializedPodVectorSize(elemCodeRangeIndices);
|
||||
}
|
||||
|
||||
uint8_t*
|
||||
@ -277,7 +278,8 @@ ElemSegment::serialize(uint8_t* cursor) const
|
||||
{
|
||||
cursor = WriteBytes(cursor, &tableIndex, sizeof(tableIndex));
|
||||
cursor = WriteBytes(cursor, &offset, sizeof(offset));
|
||||
cursor = SerializePodVector(cursor, elems);
|
||||
cursor = SerializePodVector(cursor, elemFuncIndices);
|
||||
cursor = SerializePodVector(cursor, elemCodeRangeIndices);
|
||||
return cursor;
|
||||
}
|
||||
|
||||
@ -286,14 +288,16 @@ ElemSegment::deserialize(const uint8_t* cursor)
|
||||
{
|
||||
(cursor = ReadBytes(cursor, &tableIndex, sizeof(tableIndex))) &&
|
||||
(cursor = ReadBytes(cursor, &offset, sizeof(offset))) &&
|
||||
(cursor = DeserializePodVector(cursor, &elems));
|
||||
(cursor = DeserializePodVector(cursor, &elemFuncIndices)) &&
|
||||
(cursor = DeserializePodVector(cursor, &elemCodeRangeIndices));
|
||||
return cursor;
|
||||
}
|
||||
|
||||
size_t
|
||||
ElemSegment::sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const
|
||||
{
|
||||
return elems.sizeOfExcludingThis(mallocSizeOf);
|
||||
return elemFuncIndices.sizeOfExcludingThis(mallocSizeOf) +
|
||||
elemCodeRangeIndices.sizeOfExcludingThis(mallocSizeOf);
|
||||
}
|
||||
|
||||
size_t
|
||||
@ -451,26 +455,26 @@ Module::initElems(JSContext* cx, HandleWasmInstanceObject instanceObj,
|
||||
}
|
||||
|
||||
uint32_t tableLength = instance.metadata().tables[seg.tableIndex].initial;
|
||||
if (offset > tableLength || tableLength - offset < seg.elems.length()) {
|
||||
if (offset > tableLength || tableLength - offset < seg.elemCodeRangeIndices.length()) {
|
||||
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_WASM_FAIL,
|
||||
"element segment does not fit");
|
||||
return false;
|
||||
}
|
||||
|
||||
// If profiling is already enabled in the wasm::Compartment, the new
|
||||
// instance must use the profiling entry for typed functions instead of
|
||||
// the default nonProfilingEntry.
|
||||
bool useProfilingEntry = instance.code().profilingEnabled() && table.isTypedFunction();
|
||||
|
||||
bool profilingEnabled = instance.code().profilingEnabled();
|
||||
const CodeRangeVector& codeRanges = instance.code().metadata().codeRanges;
|
||||
uint8_t* codeBase = instance.codeBase();
|
||||
for (uint32_t i = 0; i < seg.elems.length(); i++) {
|
||||
void* code = codeBase + seg.elems[i];
|
||||
if (useProfilingEntry)
|
||||
code = codeBase + instance.code().lookupRange(code)->funcProfilingEntry();
|
||||
table.set(offset + i, code, instance);
|
||||
for (uint32_t i = 0; i < seg.elemCodeRangeIndices.length(); i++) {
|
||||
const CodeRange& cr = codeRanges[seg.elemCodeRangeIndices[i]];
|
||||
uint32_t codeOffset = table.isTypedFunction()
|
||||
? profilingEnabled
|
||||
? cr.funcProfilingEntry()
|
||||
: cr.funcNonProfilingEntry()
|
||||
: cr.funcTableEntry();
|
||||
table.set(offset + i, codeBase + codeOffset, instance);
|
||||
}
|
||||
|
||||
prevEnd = offset + seg.elems.length();
|
||||
prevEnd = offset + seg.elemFuncIndices.length();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -156,19 +156,28 @@ struct DataSegment
|
||||
|
||||
typedef Vector<DataSegment, 0, SystemAllocPolicy> DataSegmentVector;
|
||||
|
||||
// ElemSegment represents an element segment in the module where each element's
|
||||
// function index has been translated to its offset in the code section.
|
||||
// ElemSegment represents an element segment in the module where each element
|
||||
// describes both its function index and its code range.
|
||||
|
||||
struct ElemSegment
|
||||
{
|
||||
MOZ_INIT_OUTSIDE_CTOR uint32_t tableIndex;
|
||||
MOZ_INIT_OUTSIDE_CTOR InitExpr offset;
|
||||
MOZ_INIT_OUTSIDE_CTOR Uint32Vector elems;
|
||||
uint32_t tableIndex;
|
||||
InitExpr offset;
|
||||
Uint32Vector elemFuncIndices;
|
||||
Uint32Vector elemCodeRangeIndices;
|
||||
|
||||
ElemSegment() = default;
|
||||
ElemSegment(uint32_t tableIndex, InitExpr offset, Uint32Vector&& elems)
|
||||
: tableIndex(tableIndex), offset(offset), elems(Move(elems))
|
||||
{}
|
||||
ElemSegment(uint32_t tableIndex,
|
||||
InitExpr offset,
|
||||
Uint32Vector&& elemFuncIndices,
|
||||
Uint32Vector&& elemCodeRangeIndices)
|
||||
: tableIndex(tableIndex),
|
||||
offset(offset),
|
||||
elemFuncIndices(Move(elemFuncIndices)),
|
||||
elemCodeRangeIndices(Move(elemCodeRangeIndices))
|
||||
{
|
||||
MOZ_ASSERT(elemFuncIndices.length() == elemCodeRangeIndices.length());
|
||||
}
|
||||
|
||||
WASM_DECLARE_SERIALIZABLE(ElemSegment)
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user