Bug 1292724 - Baldr: simplify elem segments (r=sunfish)

MozReview-Commit-ID: 4DCTydSm1ew

--HG--
extra : rebase_source : 5b326573d02e1f731e0bbdee8f51c1c142cea94d
This commit is contained in:
Luke Wagner 2016-08-30 12:45:51 -05:00
parent 4067fc4876
commit c7f11b44a9
5 changed files with 77 additions and 55 deletions

View File

@ -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;
}

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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)
};