зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1310949: Factor out DecodeDataSection; r=luke
MozReview-Commit-ID: 2M84eKv8sIj --HG-- extra : rebase_source : 01577305b499cb45d59913585bb58c85a86bcf9a
This commit is contained in:
Родитель
eb51521368
Коммит
7173e505bd
|
@ -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, §ionStart, §ionSize, "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, §ionStart, §ionSize, "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, §ionStart, §ionSize, "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
|
||||
|
|
Загрузка…
Ссылка в новой задаче