Bug 1284155 - Baldr: hoist ElemSegment out of static link data (r=bbouvier)

MozReview-Commit-ID: FbdOer3SI5r

--HG--
extra : rebase_source : 5ae1e692a328fa19896559f8238d237b9cc29c65
This commit is contained in:
Luke Wagner 2016-07-08 14:45:39 -05:00
Родитель 9133d68cc4
Коммит cb10757a14
7 изменённых файлов: 129 добавлений и 101 удалений

Просмотреть файл

@ -2108,8 +2108,7 @@ class MOZ_STACK_CLASS ModuleValidator
if (table.defined())
return false;
table.define();
mg_.initSigTableElems(table.sigIndex(), Move(elems));
return true;
return mg_.initSigTableElems(table.sigIndex(), Move(elems));
}
bool declareImport(PropertyName* name, Sig&& sig, unsigned ffiIndex, uint32_t* importIndex) {
ImportMap::AddPtr p = importMap_.lookupForAdd(NamedSig::Lookup(name, sig));

Просмотреть файл

@ -94,16 +94,10 @@ StaticallyLink(CodeSegment& cs, const LinkData& linkData, ExclusiveContext* cx)
}
}
// Initialize data in the code segment that needs absolute addresses:
// These constants are logically part of the code:
*(double*)(cs.globalData() + NaN64GlobalDataOffset) = GenericNaN();
*(float*)(cs.globalData() + NaN32GlobalDataOffset) = GenericNaN();
for (const LinkData::FuncTable& table : linkData.funcTables) {
auto array = reinterpret_cast<void**>(cs.globalData() + table.globalDataOffset);
for (size_t i = 0; i < table.elemOffsets.length(); i++)
array[i] = cs.code() + table.elemOffsets[i];
}
}
static void

Просмотреть файл

@ -592,7 +592,7 @@ DecodeFunctionSection(Decoder& d, ModuleGeneratorData* init)
}
static bool
DecodeTableSection(Decoder& d, ModuleGeneratorData* init)
DecodeTableSection(Decoder& d, ModuleGeneratorData* init, Uint32Vector* elemFuncIndices)
{
uint32_t sectionStart, sectionSize;
if (!d.startSection(TableSectionId, &sectionStart, &sectionSize))
@ -606,7 +606,7 @@ DecodeTableSection(Decoder& d, ModuleGeneratorData* init)
if (init->wasmTable.numElems > MaxTableElems)
return Fail(d, "too many table elements");
if (!init->wasmTable.elemFuncIndices.resize(init->wasmTable.numElems))
if (!elemFuncIndices->resize(init->wasmTable.numElems))
return false;
for (uint32_t i = 0; i < init->wasmTable.numElems; i++) {
@ -617,7 +617,7 @@ DecodeTableSection(Decoder& d, ModuleGeneratorData* init)
if (funcIndex >= init->funcSigs.length())
return Fail(d, "table element out of range");
init->wasmTable.elemFuncIndices[i] = funcIndex;
(*elemFuncIndices)[i] = funcIndex;
}
if (!d.finishSection(sectionStart, sectionSize))
@ -1070,6 +1070,17 @@ DecodeCodeSection(Decoder& d, ModuleGenerator& mg)
return mg.finishFuncDefs();
}
static bool
DecodeElemSection(Decoder& d, Uint32Vector&& elemFuncIndices, ModuleGenerator& mg)
{
// More fun here in the next patch:
if (!mg.addElemSegment(Move(elemFuncIndices)))
return false;
return true;
}
static bool
DecodeDataSection(Decoder& d, bool newFormat, ModuleGenerator& mg)
{
@ -1245,7 +1256,8 @@ wasm::Compile(Bytes&& bytecode, CompileArgs&& args, UniqueChars* error)
if (!DecodeFunctionSection(d, init.get()))
return nullptr;
if (!DecodeTableSection(d, init.get()))
Uint32Vector elemFuncIndices;
if (!DecodeTableSection(d, init.get(), &elemFuncIndices))
return nullptr;
bool memoryExported = false;
@ -1262,6 +1274,9 @@ wasm::Compile(Bytes&& bytecode, CompileArgs&& args, UniqueChars* error)
if (!DecodeCodeSection(d, mg))
return nullptr;
if (!DecodeElemSection(d, Move(elemFuncIndices), mg))
return nullptr;
if (!DecodeDataSection(d, newFormat, mg))
return nullptr;

Просмотреть файл

@ -137,7 +137,6 @@ ModuleGenerator::init(UniqueModuleGeneratorData shared, CompileArgs&& args,
MOZ_ASSERT(linkData_.globalDataLength % sizeof(void*) == 0);
MOZ_ASSERT(shared_->asmJSSigToTable.empty());
MOZ_ASSERT(shared_->wasmTable.numElems == shared_->wasmTable.elemFuncIndices.length());
MOZ_ASSERT(!shared_->wasmTable.globalDataOffset);
shared_->wasmTable.globalDataOffset = linkData_.globalDataLength;
linkData_.globalDataLength += shared_->wasmTable.numElems * sizeof(void*);
@ -488,35 +487,6 @@ ModuleGenerator::finishLinkData(Bytes& code)
MOZ_ASSERT(masm_.numAsmJSGlobalAccesses() == 0);
#endif
// Function pointer table elements
if (shared_->wasmTable.numElems > 0) {
const TableGenDesc& table = shared_->wasmTable;
Uint32Vector elemOffsets;
for (size_t i = 0; i < table.elemFuncIndices.length(); i++) {
if (!elemOffsets.append(funcCodeRange(table.elemFuncIndices[i]).funcTableEntry()))
return false;
}
if (!linkData_.funcTables.emplaceBack(table.globalDataOffset, Move(elemOffsets)))
return false;
}
for (const TableGenDesc& table : shared_->asmJSSigToTable) {
if (table.elemFuncIndices.empty())
continue;
Uint32Vector elemOffsets;
for (size_t i = 0; i < table.elemFuncIndices.length(); i++) {
if (!elemOffsets.append(funcCodeRange(table.elemFuncIndices[i]).funcNonProfilingEntry()))
return false;
}
if (!linkData_.funcTables.emplaceBack(table.globalDataOffset, Move(elemOffsets)))
return false;
}
return true;
}
@ -839,6 +809,13 @@ ModuleGenerator::finishFuncDefs()
return true;
}
bool
ModuleGenerator::addElemSegment(Uint32Vector&& elemFuncIndices)
{
MOZ_ASSERT(!isAsmJS());
return elemSegments_.emplaceBack(shared_->wasmTable.globalDataOffset, Move(elemFuncIndices));
}
void
ModuleGenerator::setFuncNames(NameInBytecodeVector&& funcNames)
{
@ -864,7 +841,7 @@ ModuleGenerator::initSigTableLength(uint32_t sigIndex, uint32_t numElems)
return true;
}
void
bool
ModuleGenerator::initSigTableElems(uint32_t sigIndex, Uint32Vector&& elemFuncIndices)
{
MOZ_ASSERT(isAsmJS());
@ -873,8 +850,7 @@ ModuleGenerator::initSigTableElems(uint32_t sigIndex, Uint32Vector&& elemFuncInd
TableGenDesc& table = shared_->asmJSSigToTable[sigIndex];
MOZ_ASSERT(table.numElems == elemFuncIndices.length());
MOZ_ASSERT(table.elemFuncIndices.empty());
table.elemFuncIndices = Move(elemFuncIndices);
return elemSegments_.emplaceBack(table.globalDataOffset, Move(elemFuncIndices));
}
UniqueModule
@ -938,6 +914,16 @@ ModuleGenerator::finish(ImportVector&& imports, 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;
@ -946,6 +932,7 @@ ModuleGenerator::finish(ImportVector&& imports, const ShareableBytes& bytecode)
Move(imports),
Move(exportMap_),
Move(dataSegments_),
Move(elemSegments_),
*metadata_,
bytecode);
}

Просмотреть файл

@ -40,7 +40,6 @@ struct TableGenDesc
{
uint32_t globalDataOffset;
uint32_t numElems;
Uint32Vector elemFuncIndices;
TableGenDesc()
: globalDataOffset(0), numElems(0)
@ -111,6 +110,7 @@ class MOZ_STACK_CLASS ModuleGenerator
MutableMetadata metadata_;
ExportMap exportMap_;
DataSegmentVector dataSegments_;
ElemSegmentVector elemSegments_;
// Data scoped to the ModuleGenerator's lifetime
UniqueModuleGeneratorData shared_;
@ -160,7 +160,6 @@ class MOZ_STACK_CLASS ModuleGenerator
// Memory:
bool usesMemory() const { return UsesMemory(shared_->memoryUsage); }
uint32_t minMemoryLength() const { return shared_->minMemoryLength; }
MOZ_MUST_USE bool addDataSegment(DataSegment s) { return dataSegments_.append(s); }
// Signatures:
uint32_t numSigs() const { return numSigs_; }
@ -190,6 +189,10 @@ class MOZ_STACK_CLASS ModuleGenerator
MOZ_MUST_USE bool finishFuncDef(uint32_t funcIndex, FunctionGenerator* fg);
MOZ_MUST_USE bool finishFuncDefs();
// Segments:
MOZ_MUST_USE bool addDataSegment(DataSegment s) { return dataSegments_.append(s); }
MOZ_MUST_USE bool addElemSegment(Uint32Vector&& elemFuncIndices);
// Function names:
void setFuncNames(NameInBytecodeVector&& funcNames);
@ -198,7 +201,7 @@ class MOZ_STACK_CLASS ModuleGenerator
void initFuncSig(uint32_t funcIndex, uint32_t sigIndex);
MOZ_MUST_USE bool initImport(uint32_t importIndex, uint32_t sigIndex);
MOZ_MUST_USE bool initSigTableLength(uint32_t sigIndex, uint32_t numElems);
void initSigTableElems(uint32_t sigIndex, Uint32Vector&& elemFuncIndices);
MOZ_MUST_USE bool initSigTableElems(uint32_t sigIndex, Uint32Vector&& elemFuncIndices);
void initMemoryUsage(MemoryUsage memoryUsage);
void bumpMinMemoryLength(uint32_t newMinMemoryLength);

Просмотреть файл

@ -95,42 +95,12 @@ LinkData::SymbolicLinkArray::sizeOfExcludingThis(MallocSizeOf mallocSizeOf) cons
return size;
}
size_t
LinkData::FuncTable::serializedSize() const
{
return sizeof(globalDataOffset) +
SerializedPodVectorSize(elemOffsets);
}
uint8_t*
LinkData::FuncTable::serialize(uint8_t* cursor) const
{
cursor = WriteBytes(cursor, &globalDataOffset, sizeof(globalDataOffset));
cursor = SerializePodVector(cursor, elemOffsets);
return cursor;
}
const uint8_t*
LinkData::FuncTable::deserialize(const uint8_t* cursor)
{
(cursor = ReadBytes(cursor, &globalDataOffset, sizeof(globalDataOffset))) &&
(cursor = DeserializePodVector(cursor, &elemOffsets));
return cursor;
}
size_t
LinkData::FuncTable::sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const
{
return elemOffsets.sizeOfExcludingThis(mallocSizeOf);
}
size_t
LinkData::serializedSize() const
{
return sizeof(pod()) +
SerializedPodVectorSize(internalLinks) +
symbolicLinks.serializedSize() +
SerializedVectorSize(funcTables);
symbolicLinks.serializedSize();
}
uint8_t*
@ -139,7 +109,6 @@ LinkData::serialize(uint8_t* cursor) const
cursor = WriteBytes(cursor, &pod(), sizeof(pod()));
cursor = SerializePodVector(cursor, internalLinks);
cursor = symbolicLinks.serialize(cursor);
cursor = SerializeVector(cursor, funcTables);
return cursor;
}
@ -148,8 +117,7 @@ LinkData::deserialize(const uint8_t* cursor)
{
(cursor = ReadBytes(cursor, &pod(), sizeof(pod()))) &&
(cursor = DeserializePodVector(cursor, &internalLinks)) &&
(cursor = symbolicLinks.deserialize(cursor)) &&
(cursor = DeserializeVector(cursor, &funcTables));
(cursor = symbolicLinks.deserialize(cursor));
return cursor;
}
@ -157,8 +125,7 @@ size_t
LinkData::sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const
{
return internalLinks.sizeOfExcludingThis(mallocSizeOf) +
symbolicLinks.sizeOfExcludingThis(mallocSizeOf) +
SizeOfVectorExcludingThis(funcTables, mallocSizeOf);
symbolicLinks.sizeOfExcludingThis(mallocSizeOf);
}
size_t
@ -221,6 +188,35 @@ ExportMap::sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const
fieldsToExports.sizeOfExcludingThis(mallocSizeOf);
}
size_t
ElemSegment::serializedSize() const
{
return sizeof(globalDataOffset) +
SerializedPodVectorSize(elems);
}
uint8_t*
ElemSegment::serialize(uint8_t* cursor) const
{
cursor = WriteBytes(cursor, &globalDataOffset, sizeof(globalDataOffset));
cursor = SerializePodVector(cursor, elems);
return cursor;
}
const uint8_t*
ElemSegment::deserialize(const uint8_t* cursor)
{
(cursor = ReadBytes(cursor, &globalDataOffset, sizeof(globalDataOffset))) &&
(cursor = DeserializePodVector(cursor, &elems));
return cursor;
}
size_t
ElemSegment::sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const
{
return elems.sizeOfExcludingThis(mallocSizeOf);
}
size_t
Module::serializedSize() const
{
@ -229,6 +225,7 @@ Module::serializedSize() const
SerializedVectorSize(imports_) +
exportMap_.serializedSize() +
SerializedPodVectorSize(dataSegments_) +
SerializedVectorSize(elemSegments_) +
metadata_->serializedSize() +
SerializedPodVectorSize(bytecode_->bytes);
}
@ -241,6 +238,7 @@ Module::serialize(uint8_t* cursor) const
cursor = SerializeVector(cursor, imports_);
cursor = exportMap_.serialize(cursor);
cursor = SerializePodVector(cursor, dataSegments_);
cursor = SerializeVector(cursor, elemSegments_);
cursor = metadata_->serialize(cursor);
cursor = SerializePodVector(cursor, bytecode_->bytes);
return cursor;
@ -274,6 +272,11 @@ Module::deserialize(const uint8_t* cursor, UniquePtr<Module>* module, Metadata*
if (!cursor)
return nullptr;
ElemSegmentVector elemSegments;
cursor = DeserializeVector(cursor, &elemSegments);
if (!cursor)
return nullptr;
MutableMetadata metadata;
if (maybeMetadata) {
metadata = maybeMetadata;
@ -299,6 +302,7 @@ Module::deserialize(const uint8_t* cursor, UniquePtr<Module>* module, Metadata*
Move(imports),
Move(exportMap),
Move(dataSegments),
Move(elemSegments),
*metadata,
*bytecode);
if (!*module)
@ -317,9 +321,10 @@ Module::addSizeOfMisc(MallocSizeOf mallocSizeOf,
*data += mallocSizeOf(this) +
code_.sizeOfExcludingThis(mallocSizeOf) +
linkData_.sizeOfExcludingThis(mallocSizeOf) +
imports_.sizeOfExcludingThis(mallocSizeOf) +
SizeOfVectorExcludingThis(imports_, mallocSizeOf) +
exportMap_.sizeOfExcludingThis(mallocSizeOf) +
dataSegments_.sizeOfExcludingThis(mallocSizeOf) +
SizeOfVectorExcludingThis(elemSegments_, mallocSizeOf) +
metadata_->sizeOfIncludingThisIfNotSeen(mallocSizeOf, seenMetadata) +
bytecode_->sizeOfIncludingThisIfNotSeen(mallocSizeOf, seenBytes);
}
@ -377,6 +382,18 @@ Module::instantiateMemory(JSContext* cx, MutableHandleWasmMemoryObject memory) c
return true;
}
bool
Module::instantiateTable(JSContext* cx, const CodeSegment& cs) const
{
for (const ElemSegment& seg : elemSegments_) {
auto array = reinterpret_cast<void**>(cs.globalData() + seg.globalDataOffset);
for (size_t i = 0; i < seg.elems.length(); i++)
array[i] = cs.code() + seg.elems[i];
}
return true;
}
static bool
WasmCall(JSContext* cx, unsigned argc, Value* vp)
{
@ -484,6 +501,9 @@ Module::instantiate(JSContext* cx,
if (!cs)
return false;
if (!instantiateTable(cx, *cs))
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
@ -501,10 +521,10 @@ Module::instantiate(JSContext* cx,
TypedFuncTableVector typedFuncTables;
if (metadata_->isAsmJS()) {
if (!typedFuncTables.reserve(linkData_.funcTables.length()))
if (!typedFuncTables.reserve(elemSegments_.length()))
return false;
for (const LinkData::FuncTable& tbl : linkData_.funcTables)
typedFuncTables.infallibleEmplaceBack(tbl.globalDataOffset, tbl.elemOffsets.length());
for (const ElemSegment& seg : elemSegments_)
typedFuncTables.infallibleEmplaceBack(seg.globalDataOffset, seg.elems.length());
}
// Create the Instance, ensuring that it is traceable via 'instanceObj'

Просмотреть файл

@ -70,20 +70,8 @@ struct LinkData : LinkDataCacheablePod
WASM_DECLARE_SERIALIZABLE(SymbolicLinkArray)
};
struct FuncTable {
uint32_t globalDataOffset;
Uint32Vector elemOffsets;
FuncTable(uint32_t globalDataOffset, Uint32Vector&& elemOffsets)
: globalDataOffset(globalDataOffset), elemOffsets(Move(elemOffsets))
{}
FuncTable() = default;
WASM_DECLARE_SERIALIZABLE(FuncTable)
};
typedef Vector<FuncTable, 0, SystemAllocPolicy> FuncTableVector;
InternalLinkVector internalLinks;
SymbolicLinkArray symbolicLinks;
FuncTableVector funcTables;
WASM_DECLARE_SERIALIZABLE(LinkData)
};
@ -146,6 +134,24 @@ 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.
struct ElemSegment
{
uint32_t globalDataOffset;
Uint32Vector elems;
ElemSegment() = default;
ElemSegment(uint32_t globalDataOffset, Uint32Vector&& elems)
: globalDataOffset(globalDataOffset), elems(Move(elems))
{}
WASM_DECLARE_SERIALIZABLE(ElemSegment)
};
typedef Vector<ElemSegment, 0, SystemAllocPolicy> ElemSegmentVector;
// Module represents a compiled wasm module and primarily provides two
// operations: instantiation and serialization. A Module can be instantiated any
// number of times to produce new Instance objects. A Module can be serialized
@ -165,10 +171,12 @@ class Module
const ImportVector imports_;
const ExportMap exportMap_;
const DataSegmentVector dataSegments_;
const ElemSegmentVector elemSegments_;
const SharedMetadata metadata_;
const SharedBytes bytecode_;
bool instantiateMemory(JSContext* cx, MutableHandleWasmMemoryObject memory) const;
bool instantiateTable(JSContext* cx, const CodeSegment& cs) const;
public:
Module(Bytes&& code,
@ -176,6 +184,7 @@ class Module
ImportVector&& imports,
ExportMap&& exportMap,
DataSegmentVector&& dataSegments,
ElemSegmentVector&& elemSegments,
const Metadata& metadata,
const ShareableBytes& bytecode)
: code_(Move(code)),
@ -183,6 +192,7 @@ class Module
imports_(Move(imports)),
exportMap_(Move(exportMap)),
dataSegments_(Move(dataSegments)),
elemSegments_(Move(elemSegments)),
metadata_(&metadata),
bytecode_(&bytecode)
{}