Bug 1310949: Factor out DecodeDataSection; r=luke

MozReview-Commit-ID: 2M84eKv8sIj

--HG--
extra : rebase_source : 01577305b499cb45d59913585bb58c85a86bcf9a
This commit is contained in:
Benjamin Bouvier 2016-10-20 12:48:44 +02:00
Родитель eb51521368
Коммит 7173e505bd
9 изменённых файлов: 123 добавлений и 118 удалений

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

@ -802,6 +802,9 @@ class Decoder
size_t currentOffset() const {
return cur_ - beg_;
}
const uint8_t* begin() const {
return beg_;
}
// Fixed-size encoding operations simply copy the literal bytes (without
// attempting to align).

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

@ -210,6 +210,62 @@ wasm::DecodeLimits(Decoder& d, Limits* limits)
return true;
}
bool
wasm::DecodeDataSection(Decoder& d, bool usesMemory, uint32_t minMemoryByteLength,
const GlobalDescVector& globals, DataSegmentVector* segments)
{
uint32_t sectionStart, sectionSize;
if (!d.startSection(SectionId::Data, &sectionStart, &sectionSize, "data"))
return false;
if (sectionStart == Decoder::NotStarted)
return true;
if (!usesMemory)
return d.fail("data section requires a memory section");
uint32_t numSegments;
if (!d.readVarU32(&numSegments))
return d.fail("failed to read number of data segments");
if (numSegments > MaxDataSegments)
return d.fail("too many data segments");
for (uint32_t i = 0; i < numSegments; i++) {
uint32_t linearMemoryIndex;
if (!d.readVarU32(&linearMemoryIndex))
return d.fail("expected linear memory index");
if (linearMemoryIndex != 0)
return d.fail("linear memory index must currently be 0");
DataSegment seg;
if (!DecodeInitializerExpression(d, globals, ValType::I32, &seg.offset))
return false;
if (!d.readVarU32(&seg.length))
return d.fail("expected segment size");
if (seg.offset.isVal()) {
uint32_t off = seg.offset.val().i32();
if (off > minMemoryByteLength || minMemoryByteLength - off < seg.length)
return d.fail("data segment does not fit");
}
seg.bytecodeOffset = d.currentOffset();
if (!d.readBytes(seg.length))
return d.fail("data segment shorter than declared");
if (!segments->append(seg))
return false;
}
if (!d.finishSection(sectionStart, sectionSize, "data"))
return false;
return true;
}
bool
wasm::DecodeUnknownSections(Decoder& d)
{

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

@ -51,6 +51,10 @@ DecodeLimits(Decoder& d, Limits* limits);
MOZ_MUST_USE bool
DecodeUnknownSections(Decoder& d);
MOZ_MUST_USE bool
DecodeDataSection(Decoder& d, bool usesMemory, uint32_t minMemoryByteLength,
const GlobalDescVector& globals, DataSegmentVector* segments);
} // namespace wasm
} // namespace js

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

@ -1785,6 +1785,23 @@ AstDecodeMemorySection(AstDecodeContext& c)
return true;
}
static AstExpr*
ToAstExpr(AstDecodeContext& c, const InitExpr& initExpr)
{
switch (initExpr.kind()) {
case InitExpr::Kind::Constant: {
return new(c.lifo) AstConst(Val(initExpr.val()));
}
case InitExpr::Kind::GetGlobal: {
AstRef globalRef;
if (!AstDecodeGenerateRef(c, AstName(u"global"), initExpr.globalIndex(), &globalRef))
return nullptr;
return new(c.lifo) AstGetGlobal(globalRef);
}
}
return nullptr;
}
static bool
AstDecodeInitializerExpression(AstDecodeContext& c, ValType type, AstExpr** init)
{
@ -1792,20 +1809,7 @@ AstDecodeInitializerExpression(AstDecodeContext& c, ValType type, AstExpr** init
if (!DecodeInitializerExpression(c.d, c.globalDescs(), type, &initExpr))
return false;
switch (initExpr.kind()) {
case InitExpr::Kind::Constant: {
*init = new(c.lifo) AstConst(Val(initExpr.val()));
break;
}
case InitExpr::Kind::GetGlobal: {
AstRef globalRef;
if (!AstDecodeGenerateRef(c, AstName(u"global"), initExpr.globalIndex(), &globalRef))
return false;
*init = new(c.lifo) AstGetGlobal(globalRef);
break;
}
}
*init = ToAstExpr(c, initExpr);
return !!*init;
}
@ -2048,55 +2052,31 @@ AstDecodeCodeSection(AstDecodeContext &c)
static bool
AstDecodeDataSection(AstDecodeContext &c)
{
uint32_t sectionStart, sectionSize;
if (!c.d.startSection(SectionId::Data, &sectionStart, &sectionSize, "data"))
DataSegmentVector segments;
bool hasMemory = c.module().hasMemory();
uint32_t memByteLength = hasMemory ? c.module().memory().initial * PageSize : 0;
if (!DecodeDataSection(c.d, hasMemory, memByteLength, c.globalDescs(), &segments))
return false;
if (sectionStart == Decoder::NotStarted)
return true;
uint32_t numSegments;
if (!c.d.readVarU32(&numSegments))
return c.d.fail("failed to read number of data segments");
const uint32_t heapLength = c.module().hasMemory() ? c.module().memory().initial : 0;
for (uint32_t i = 0; i < numSegments; i++) {
uint32_t dstOffset;
if (!c.d.readVarU32(&dstOffset))
return c.d.fail("expected segment destination offset");
uint32_t numBytes;
if (!c.d.readVarU32(&numBytes))
return c.d.fail("expected segment size");
if (dstOffset > heapLength || heapLength - dstOffset < numBytes)
return c.d.fail("data segment does not fit in memory");
const uint8_t* src;
if (!c.d.readBytes(numBytes, &src))
return c.d.fail("data segment shorter than declared");
char16_t *buffer = static_cast<char16_t *>(c.lifo.alloc(numBytes * sizeof(char16_t)));
for (size_t i = 0; i < numBytes; i++)
for (DataSegment& s : segments) {
const uint8_t* src = c.d.begin() + s.bytecodeOffset;
char16_t* buffer = static_cast<char16_t*>(c.lifo.alloc(s.length * sizeof(char16_t)));
for (size_t i = 0; i < s.length; i++)
buffer[i] = src[i];
AstExpr* offset = new(c.lifo) AstConst(Val(dstOffset));
AstExpr* offset = ToAstExpr(c, s.offset);
if (!offset)
return false;
AstName name(buffer, numBytes);
AstName name(buffer, s.length);
AstDataSegment* segment = new(c.lifo) AstDataSegment(offset, name);
if (!segment || !c.module().append(segment))
return false;
}
if (!c.d.finishSection(sectionStart, sectionSize, "data"))
return false;
return true;
}
static bool
AstDecodeElemSection(AstDecodeContext &c)
{

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

@ -1139,62 +1139,6 @@ DecodeElemSection(Decoder& d, Uint32Vector&& oldElems, ModuleGenerator& mg)
return true;
}
static bool
DecodeDataSection(Decoder& d, ModuleGenerator& mg)
{
uint32_t sectionStart, sectionSize;
if (!d.startSection(SectionId::Data, &sectionStart, &sectionSize, "data"))
return false;
if (sectionStart == Decoder::NotStarted)
return true;
if (!mg.usesMemory())
return d.fail("data section requires a memory section");
uint32_t numSegments;
if (!d.readVarU32(&numSegments))
return d.fail("failed to read number of data segments");
if (numSegments > MaxDataSegments)
return d.fail("too many data segments");
uint32_t max = mg.minMemoryLength();
for (uint32_t i = 0; i < numSegments; i++) {
uint32_t linearMemoryIndex;
if (!d.readVarU32(&linearMemoryIndex))
return d.fail("expected linear memory index");
if (linearMemoryIndex != 0)
return d.fail("linear memory index must currently be 0");
DataSegment seg;
if (!DecodeInitializerExpression(d, mg.globals(), ValType::I32, &seg.offset))
return false;
if (!d.readVarU32(&seg.length))
return d.fail("expected segment size");
if (seg.offset.isVal()) {
uint32_t off = seg.offset.val().i32();
if (off > max || max - off < seg.length)
return d.fail("data segment does not fit");
}
seg.bytecodeOffset = d.currentOffset();
if (!d.readBytes(seg.length))
return d.fail("data segment shorter than declared");
if (!mg.addDataSegment(seg))
return false;
}
if (!d.finishSection(sectionStart, sectionSize, "data"))
return false;
return true;
}
static void
MaybeDecodeNameSectionBody(Decoder& d, ModuleGenerator& mg)
{
@ -1241,6 +1185,17 @@ MaybeDecodeNameSectionBody(Decoder& d, ModuleGenerator& mg)
mg.setFuncNames(Move(funcNames));
}
static bool
DecodeDataSection(Decoder& d, ModuleGenerator& mg)
{
DataSegmentVector dataSegments;
if (!DecodeDataSection(d, mg.usesMemory(), mg.minMemoryLength(), mg.globals(), &dataSegments))
return false;
mg.setDataSegments(Move(dataSegments));
return true;
}
static bool
DecodeNameSection(Decoder& d, ModuleGenerator& mg)
{
@ -1317,7 +1272,7 @@ wasm::Compile(const ShareableBytes& bytecode, const CompileArgs& args, UniqueCha
if (!DecodeCodeSection(d, mg))
return nullptr;
if (!DecodeDataSection(d, mg))
if (!::DecodeDataSection(d, mg))
return nullptr;
if (!DecodeNameSection(d, mg))

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

@ -860,6 +860,13 @@ ModuleGenerator::addElemSegment(InitExpr offset, Uint32Vector&& elemFuncIndices)
return elemSegments_.emplaceBack(0, offset, Move(elemFuncIndices));
}
void
ModuleGenerator::setDataSegments(DataSegmentVector&& segments)
{
MOZ_ASSERT(dataSegments_.empty());
dataSegments_ = Move(segments);
}
bool
ModuleGenerator::startFuncDefs()
{

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

@ -192,7 +192,7 @@ class MOZ_STACK_CLASS ModuleGenerator
bool setStartFunction(uint32_t funcIndex);
// Segments:
MOZ_MUST_USE bool addDataSegment(DataSegment s) { return dataSegments_.append(s); }
void setDataSegments(DataSegmentVector&& segments);
MOZ_MUST_USE bool addElemSegment(InitExpr offset, Uint32Vector&& elemFuncIndices);
// Function names:

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

@ -131,18 +131,6 @@ class Export
typedef Vector<Export, 0, SystemAllocPolicy> ExportVector;
// DataSegment describes the offset of a data segment in the bytecode that is
// to be copied at a given offset into linear memory upon instantiation.
struct DataSegment
{
InitExpr offset;
uint32_t bytecodeOffset;
uint32_t length;
};
typedef Vector<DataSegment, 0, SystemAllocPolicy> DataSegmentVector;
// ElemSegment represents an element segment in the module where each element
// describes both its function index and its code range.

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

@ -574,6 +574,18 @@ class GlobalDesc
typedef Vector<GlobalDesc, 0, SystemAllocPolicy> GlobalDescVector;
// DataSegment describes the offset of a data segment in the bytecode that is
// to be copied at a given offset into linear memory upon instantiation.
struct DataSegment
{
InitExpr offset;
uint32_t bytecodeOffset;
uint32_t length;
};
typedef Vector<DataSegment, 0, SystemAllocPolicy> DataSegmentVector;
// SigIdDesc describes a signature id that can be used by call_indirect and
// table-entry prologues to structurally compare whether the caller and callee's
// signatures *structurally* match. To handle the general case, a Sig is