mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 23:31:56 +00:00
Bug 1284155 - Baldr: allow data segments outside any memory definition (r=bbouvier)
MozReview-Commit-ID: B9QQLBvIVOs --HG-- extra : rebase_source : 2e96bd2b7beb709e04f7ea5fdabec1736683efb1
This commit is contained in:
parent
5f945ff054
commit
e6f8caae67
@ -587,14 +587,10 @@ typedef AstVector<AstSegment*> AstSegmentVector;
|
||||
|
||||
class AstMemory : public AstNode, public AstMemorySignature
|
||||
{
|
||||
AstSegmentVector segments_;
|
||||
|
||||
public:
|
||||
explicit AstMemory(AstMemorySignature memSig, AstSegmentVector&& segments)
|
||||
: AstMemorySignature(memSig),
|
||||
segments_(Move(segments))
|
||||
explicit AstMemory(AstMemorySignature memSig)
|
||||
: AstMemorySignature(memSig)
|
||||
{}
|
||||
const AstSegmentVector& segments() const { return segments_; }
|
||||
};
|
||||
|
||||
class AstModule : public AstNode
|
||||
@ -604,12 +600,14 @@ class AstModule : public AstNode
|
||||
typedef AstVector<AstImport*> ImportVector;
|
||||
typedef AstVector<AstExport*> ExportVector;
|
||||
typedef AstVector<AstSig*> SigVector;
|
||||
typedef AstVector<AstSegment*> SegmentVector;
|
||||
|
||||
private:
|
||||
typedef AstHashMap<AstSig*, uint32_t, AstSig> SigMap;
|
||||
|
||||
LifoAlloc& lifo_;
|
||||
AstMemory* memory_;
|
||||
SegmentVector segments_;
|
||||
SigVector sigs_;
|
||||
SigMap sigMap_;
|
||||
ImportVector imports_;
|
||||
@ -621,6 +619,7 @@ class AstModule : public AstNode
|
||||
explicit AstModule(LifoAlloc& lifo)
|
||||
: lifo_(lifo),
|
||||
memory_(nullptr),
|
||||
segments_(lifo),
|
||||
sigs_(lifo),
|
||||
sigMap_(lifo),
|
||||
imports_(lifo),
|
||||
@ -640,6 +639,12 @@ class AstModule : public AstNode
|
||||
AstMemory* maybeMemory() const {
|
||||
return memory_;
|
||||
}
|
||||
bool append(AstSegment* seg) {
|
||||
return segments_.append(seg);
|
||||
}
|
||||
const SegmentVector& segments() const {
|
||||
return segments_;
|
||||
}
|
||||
bool declare(AstSig&& sig, uint32_t* sigIndex) {
|
||||
SigMap::AddPtr p = sigMap_.lookupForAdd(sig);
|
||||
if (p) {
|
||||
|
@ -1457,13 +1457,12 @@ AstDecodeDataSection(AstDecodeContext &c)
|
||||
if (!c.d.startSection(DataSectionId, §ionStart, §ionSize))
|
||||
return AstDecodeFail(c, "failed to start section");
|
||||
|
||||
AstSegmentVector segments(c.lifo);
|
||||
if (sectionStart == Decoder::NotStarted) {
|
||||
if (!c.initialSizePages)
|
||||
return true;
|
||||
|
||||
AstMemorySignature memSig(*c.initialSizePages, c.maxSizePages);
|
||||
AstMemory* memory = new(c.lifo) AstMemory(memSig, Move(segments));
|
||||
AstMemory* memory = new(c.lifo) AstMemory(memSig);
|
||||
if (!memory)
|
||||
return false;
|
||||
|
||||
@ -1504,14 +1503,14 @@ AstDecodeDataSection(AstDecodeContext &c)
|
||||
|
||||
AstName name(buffer, numBytes);
|
||||
AstSegment* segment = new(c.lifo) AstSegment(dstOffset, name);
|
||||
if (!segment || !segments.append(segment))
|
||||
if (!segment || !c.module().append(segment))
|
||||
return false;
|
||||
|
||||
prevEnd = dstOffset + numBytes;
|
||||
}
|
||||
|
||||
AstMemorySignature memSig(initialSizePages, c.maxSizePages);
|
||||
AstMemory* memory = new(c.lifo) AstMemory(memSig, Move(segments));
|
||||
AstMemory* memory = new(c.lifo) AstMemory(memSig);
|
||||
if (!memory)
|
||||
return false;
|
||||
|
||||
|
@ -1616,7 +1616,7 @@ PrintCodeSection(WasmPrintContext& c, const AstModule::FuncVector& funcs, const
|
||||
|
||||
|
||||
static bool
|
||||
PrintDataSection(WasmPrintContext& c, AstMemory* maybeMemory)
|
||||
PrintDataSection(WasmPrintContext& c, AstMemory* maybeMemory, const AstModule::SegmentVector& segments)
|
||||
{
|
||||
if (!maybeMemory)
|
||||
return true;
|
||||
@ -1636,7 +1636,7 @@ PrintDataSection(WasmPrintContext& c, AstMemory* maybeMemory)
|
||||
|
||||
c.indent++;
|
||||
|
||||
uint32_t numSegments = maybeMemory->segments().length();
|
||||
uint32_t numSegments = segments.length();
|
||||
if (!numSegments) {
|
||||
if (!c.buffer.append(" {}\n\n"))
|
||||
return false;
|
||||
@ -1646,7 +1646,7 @@ PrintDataSection(WasmPrintContext& c, AstMemory* maybeMemory)
|
||||
return false;
|
||||
|
||||
for (uint32_t i = 0; i < numSegments; i++) {
|
||||
const AstSegment* segment = maybeMemory->segments()[i];
|
||||
const AstSegment* segment = segments[i];
|
||||
|
||||
if (!PrintIndent(c))
|
||||
return false;
|
||||
@ -1688,7 +1688,7 @@ PrintModule(WasmPrintContext& c, AstModule& module)
|
||||
if (!PrintCodeSection(c, module.funcs(), module.sigs()))
|
||||
return false;
|
||||
|
||||
if (!PrintDataSection(c, module.maybeMemory()))
|
||||
if (!PrintDataSection(c, module.maybeMemory(), module.segments()))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
@ -1284,7 +1284,7 @@ RenderCodeSection(WasmRenderContext& c, const AstModule::FuncVector& funcs, cons
|
||||
|
||||
|
||||
static bool
|
||||
RenderDataSection(WasmRenderContext& c, AstMemory* maybeMemory)
|
||||
RenderDataSection(WasmRenderContext& c, AstMemory* maybeMemory, const AstModule::SegmentVector& segments)
|
||||
{
|
||||
if (!maybeMemory)
|
||||
return true;
|
||||
@ -1305,7 +1305,7 @@ RenderDataSection(WasmRenderContext& c, AstMemory* maybeMemory)
|
||||
|
||||
c.indent++;
|
||||
|
||||
uint32_t numSegments = maybeMemory->segments().length();
|
||||
uint32_t numSegments = segments.length();
|
||||
if (!numSegments) {
|
||||
if (!c.buffer.append(")\n"))
|
||||
return false;
|
||||
@ -1315,7 +1315,7 @@ RenderDataSection(WasmRenderContext& c, AstMemory* maybeMemory)
|
||||
return false;
|
||||
|
||||
for (uint32_t i = 0; i < numSegments; i++) {
|
||||
const AstSegment* segment = maybeMemory->segments()[i];
|
||||
const AstSegment* segment = segments[i];
|
||||
|
||||
if (!RenderIndent(c))
|
||||
return false;
|
||||
@ -1362,7 +1362,7 @@ RenderModule(WasmRenderContext& c, AstModule& module)
|
||||
if (!RenderCodeSection(c, module.funcs(), module.sigs()))
|
||||
return false;
|
||||
|
||||
if (!RenderDataSection(c, module.maybeMemory()))
|
||||
if (!RenderDataSection(c, module.maybeMemory(), module.segments()))
|
||||
return false;
|
||||
|
||||
c.indent--;
|
||||
|
@ -1071,7 +1071,7 @@ DecodeCodeSection(Decoder& d, ModuleGenerator& mg)
|
||||
}
|
||||
|
||||
static bool
|
||||
DecodeDataSection(Decoder& d, ModuleGenerator& mg)
|
||||
DecodeDataSection(Decoder& d, bool newFormat, ModuleGenerator& mg)
|
||||
{
|
||||
uint32_t sectionStart, sectionSize;
|
||||
if (!d.startSection(DataSectionId, §ionStart, §ionSize))
|
||||
@ -1091,8 +1091,23 @@ DecodeDataSection(Decoder& d, ModuleGenerator& mg)
|
||||
|
||||
uint32_t max = mg.minMemoryLength();
|
||||
for (uint32_t i = 0, prevEnd = 0; i < numSegments; i++) {
|
||||
DataSegment seg;
|
||||
if (newFormat) {
|
||||
uint32_t linearMemoryIndex;
|
||||
if (!d.readVarU32(&linearMemoryIndex))
|
||||
return Fail(d, "expected linear memory index");
|
||||
|
||||
if (linearMemoryIndex != 0)
|
||||
return Fail(d, "linear memory index must currently be 0");
|
||||
|
||||
Expr expr;
|
||||
if (!d.readExpr(&expr))
|
||||
return Fail(d, "failed to read initializer expression");
|
||||
|
||||
if (expr != Expr::I32Const)
|
||||
return Fail(d, "expected i32.const initializer expression");
|
||||
}
|
||||
|
||||
DataSegment seg;
|
||||
if (!d.readVarU32(&seg.memoryOffset))
|
||||
return Fail(d, "expected segment destination offset");
|
||||
|
||||
@ -1247,7 +1262,7 @@ wasm::Compile(Bytes&& bytecode, CompileArgs&& args, UniqueChars* error)
|
||||
if (!DecodeCodeSection(d, mg))
|
||||
return nullptr;
|
||||
|
||||
if (!DecodeDataSection(d, mg))
|
||||
if (!DecodeDataSection(d, newFormat, mg))
|
||||
return nullptr;
|
||||
|
||||
if (!DecodeNameSection(d, mg))
|
||||
|
@ -2341,9 +2341,6 @@ ParseTypeDef(WasmParseContext& c)
|
||||
static AstSegment*
|
||||
ParseSegment(WasmParseContext& c)
|
||||
{
|
||||
if (!c.ts.match(WasmToken::Segment, c.error))
|
||||
return nullptr;
|
||||
|
||||
WasmToken dstOffset;
|
||||
if (!c.ts.match(WasmToken::Index, &dstOffset, c.error))
|
||||
return nullptr;
|
||||
@ -2372,22 +2369,23 @@ ParseMemorySignature(WasmParseContext& c, AstMemorySignature* memSig)
|
||||
}
|
||||
|
||||
static AstMemory*
|
||||
ParseMemory(WasmParseContext& c)
|
||||
ParseMemory(WasmParseContext& c, AstModule* module)
|
||||
{
|
||||
AstMemorySignature memSig;
|
||||
if (!ParseMemorySignature(c, &memSig))
|
||||
return nullptr;
|
||||
|
||||
AstSegmentVector segments(c.lifo);
|
||||
while (c.ts.getIf(WasmToken::OpenParen)) {
|
||||
if (!c.ts.match(WasmToken::Segment, c.error))
|
||||
return nullptr;
|
||||
AstSegment* segment = ParseSegment(c);
|
||||
if (!segment || !segments.append(segment))
|
||||
if (!segment || !module->append(segment))
|
||||
return nullptr;
|
||||
if (!c.ts.match(WasmToken::CloseParen, c.error))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return new(c.lifo) AstMemory(memSig, Move(segments));
|
||||
return new(c.lifo) AstMemory(memSig);
|
||||
}
|
||||
|
||||
static AstImport*
|
||||
@ -2502,7 +2500,7 @@ ParseModule(const char16_t* text, LifoAlloc& lifo, UniqueChars* error)
|
||||
break;
|
||||
}
|
||||
case WasmToken::Memory: {
|
||||
AstMemory* memory = ParseMemory(c);
|
||||
AstMemory* memory = ParseMemory(c, module);
|
||||
if (!memory)
|
||||
return nullptr;
|
||||
if (!module->setMemory(memory)) {
|
||||
@ -2511,6 +2509,16 @@ ParseModule(const char16_t* text, LifoAlloc& lifo, UniqueChars* error)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WasmToken::Segment: {
|
||||
AstSegment* segment = ParseSegment(c);
|
||||
if (!segment)
|
||||
return nullptr;
|
||||
if (!module->append(segment)) {
|
||||
c.ts.generateError(section, c.error);
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WasmToken::Import: {
|
||||
AstImport* imp = ParseImport(c, module);
|
||||
if (!imp || !module->append(imp))
|
||||
@ -3677,8 +3685,16 @@ EncodeCodeSection(Encoder& e, AstModule& module)
|
||||
}
|
||||
|
||||
static bool
|
||||
EncodeDataSegment(Encoder& e, AstSegment& segment)
|
||||
EncodeDataSegment(Encoder& e, bool newFormat, AstSegment& segment)
|
||||
{
|
||||
if (newFormat) {
|
||||
if (!e.writeVarU32(0)) // linear memory index
|
||||
return false;
|
||||
|
||||
if (!e.writeExpr(Expr::I32Const))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!e.writeVarU32(segment.offset()))
|
||||
return false;
|
||||
|
||||
@ -3703,22 +3719,20 @@ EncodeDataSegment(Encoder& e, AstSegment& segment)
|
||||
}
|
||||
|
||||
static bool
|
||||
EncodeDataSection(Encoder& e, AstModule& module)
|
||||
EncodeDataSection(Encoder& e, bool newFormat, AstModule& module)
|
||||
{
|
||||
if (!module.maybeMemory() || module.maybeMemory()->segments().empty())
|
||||
if (module.segments().empty())
|
||||
return true;
|
||||
|
||||
const AstSegmentVector& segments = module.maybeMemory()->segments();
|
||||
|
||||
size_t offset;
|
||||
if (!e.startSection(DataSectionId, &offset))
|
||||
return false;
|
||||
|
||||
if (!e.writeVarU32(segments.length()))
|
||||
if (!e.writeVarU32(module.segments().length()))
|
||||
return false;
|
||||
|
||||
for (AstSegment* segment : segments) {
|
||||
if (!EncodeDataSegment(e, *segment))
|
||||
for (AstSegment* segment : module.segments()) {
|
||||
if (!EncodeDataSegment(e, newFormat, *segment))
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -3758,7 +3772,7 @@ EncodeModule(AstModule& module, bool newFormat, Bytes* bytes)
|
||||
if (!EncodeCodeSection(e, module))
|
||||
return false;
|
||||
|
||||
if (!EncodeDataSection(e, module))
|
||||
if (!EncodeDataSection(e, newFormat, module))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
@ -163,3 +163,30 @@ assertEq(mem, e.bar);
|
||||
|
||||
assertErrorMessage(() => new Module(textToBinary('(module (import "a" "b" (memory 1 1)) (memory 1 1))')), TypeError, /already have default memory/);
|
||||
assertErrorMessage(() => new Module(textToBinary('(module (import "a" "b" (memory 1 1)) (import "x" "y" (memory 2 2)))')), TypeError, /already have default memory/);
|
||||
|
||||
// Data segments on imports
|
||||
|
||||
var m = new Module(textToBinary(`
|
||||
(module
|
||||
(import "a" "b" (memory 1 1))
|
||||
(segment 0 "\\0a\\0b")
|
||||
(segment 100 "\\0c\\0d")
|
||||
(func $get (param $p i32) (result i32)
|
||||
(i32.load8_u (get_local $p)))
|
||||
(export "get" $get))
|
||||
`));
|
||||
var mem = new Memory({initial:1});
|
||||
var {get} = new Instance(m, {a:{b:mem}}).exports;
|
||||
assertEq(get(0), 0xa);
|
||||
assertEq(get(1), 0xb);
|
||||
assertEq(get(2), 0x0);
|
||||
assertEq(get(100), 0xc);
|
||||
assertEq(get(101), 0xd);
|
||||
assertEq(get(102), 0x0);
|
||||
var i8 = new Uint8Array(mem.buffer);
|
||||
assertEq(i8[0], 0xa);
|
||||
assertEq(i8[1], 0xb);
|
||||
assertEq(i8[2], 0x0);
|
||||
assertEq(i8[100], 0xc);
|
||||
assertEq(i8[101], 0xd);
|
||||
assertEq(i8[102], 0x0);
|
||||
|
Loading…
Reference in New Issue
Block a user