зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1253137 - Baldr: update memory section to match BinaryEncoding.md, part 1 (r=sunfish)
MozReview-Commit-ID: EKCvmgPnLmv
This commit is contained in:
Родитель
0edd0e532e
Коммит
aa77e448b2
|
@ -18,6 +18,8 @@
|
|||
|
||||
#include "asmjs/Wasm.h"
|
||||
|
||||
#include "mozilla/CheckedInt.h"
|
||||
|
||||
#include "jsprf.h"
|
||||
|
||||
#include "asmjs/WasmGenerator.h"
|
||||
|
@ -30,6 +32,7 @@
|
|||
using namespace js;
|
||||
using namespace js::wasm;
|
||||
|
||||
using mozilla::CheckedInt;
|
||||
using mozilla::IsNaN;
|
||||
|
||||
typedef Handle<WasmModuleObject*> HandleWasmModule;
|
||||
|
@ -890,28 +893,29 @@ DecodeMemorySection(JSContext* cx, Decoder& d, ModuleGenerator& mg,
|
|||
if (sectionStart == Decoder::NotStarted)
|
||||
return true;
|
||||
|
||||
|
||||
if (!d.readCStringIf(InitialLabel))
|
||||
return Fail(cx, d, "expected memory section initial field");
|
||||
|
||||
uint32_t initialHeapSize;
|
||||
if (!d.readVarU32(&initialHeapSize))
|
||||
uint32_t initialSizePages;
|
||||
if (!d.readVarU32(&initialSizePages))
|
||||
return Fail(cx, d, "expected initial memory size");
|
||||
|
||||
if (initialHeapSize < PageSize || initialHeapSize % PageSize != 0)
|
||||
return Fail(cx, d, "initial memory size not a multiple of 0x10000");
|
||||
|
||||
if (initialHeapSize > INT32_MAX)
|
||||
CheckedInt<int32_t> initialSize = initialSizePages;
|
||||
initialSize *= PageSize;
|
||||
if (!initialSize.isValid())
|
||||
return Fail(cx, d, "initial memory size too big");
|
||||
|
||||
if (!d.readCStringIf(EndLabel))
|
||||
return Fail(cx, d, "expected end field of memory section");
|
||||
uint32_t maxSizePages;
|
||||
if (!d.readVarU32(&maxSizePages))
|
||||
return Fail(cx, d, "expected initial memory size");
|
||||
|
||||
CheckedInt<int32_t> maxSize = maxSizePages;
|
||||
maxSize *= PageSize;
|
||||
if (!maxSize.isValid())
|
||||
return Fail(cx, d, "initial memory size too big");
|
||||
|
||||
if (!d.finishSection(sectionStart))
|
||||
return Fail(cx, d, "memory section byte size mismatch");
|
||||
|
||||
bool signalsForOOB = CompileArgs(cx).useSignalHandlersForOOB;
|
||||
heap.set(ArrayBufferObject::createForWasm(cx, initialHeapSize, signalsForOOB));
|
||||
heap.set(ArrayBufferObject::createForWasm(cx, initialSize.value(), signalsForOOB));
|
||||
if (!heap)
|
||||
return false;
|
||||
|
||||
|
|
|
@ -54,7 +54,6 @@ static const char ExportLabel[] = "export";
|
|||
static const char FuncLabel[] = "func";
|
||||
static const char DataLabel[] = "data";
|
||||
static const char SegmentLabel[] = "segment";
|
||||
static const char InitialLabel[] = "initial";
|
||||
static const char EndLabel[] = "";
|
||||
|
||||
enum class Expr : uint16_t
|
||||
|
|
|
@ -562,14 +562,18 @@ typedef WasmAstVector<WasmAstSegment*> WasmAstSegmentVector;
|
|||
class WasmAstMemory : public WasmAstNode
|
||||
{
|
||||
uint32_t initialSize_;
|
||||
Maybe<uint32_t> maxSize_;
|
||||
WasmAstSegmentVector segments_;
|
||||
|
||||
public:
|
||||
explicit WasmAstMemory(uint32_t initialSize, WasmAstSegmentVector&& segments)
|
||||
explicit WasmAstMemory(uint32_t initialSize, Maybe<uint32_t> maxSize,
|
||||
WasmAstSegmentVector&& segments)
|
||||
: initialSize_(initialSize),
|
||||
maxSize_(maxSize),
|
||||
segments_(Move(segments))
|
||||
{}
|
||||
uint32_t initialSize() const { return initialSize_; }
|
||||
const Maybe<uint32_t>& maxSize() const { return maxSize_; }
|
||||
const WasmAstSegmentVector& segments() const { return segments_; }
|
||||
};
|
||||
|
||||
|
@ -2897,6 +2901,11 @@ ParseMemory(WasmParseContext& c)
|
|||
if (!c.ts.match(WasmToken::Index, &initialSize, c.error))
|
||||
return nullptr;
|
||||
|
||||
Maybe<uint32_t> maxSize;
|
||||
WasmToken token;
|
||||
if (c.ts.getIf(WasmToken::Index, &token))
|
||||
maxSize.emplace(token.index());
|
||||
|
||||
WasmAstSegmentVector segments(c.lifo);
|
||||
while (c.ts.getIf(WasmToken::OpenParen)) {
|
||||
WasmAstSegment* segment = ParseSegment(c);
|
||||
|
@ -2906,7 +2915,7 @@ ParseMemory(WasmParseContext& c)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
return new(c.lifo) WasmAstMemory(initialSize.index(), Move(segments));
|
||||
return new(c.lifo) WasmAstMemory(initialSize.index(), maxSize, Move(segments));
|
||||
}
|
||||
|
||||
static WasmAstImport*
|
||||
|
@ -3814,13 +3823,11 @@ EncodeMemorySection(Encoder& e, WasmAstModule& module)
|
|||
|
||||
WasmAstMemory& memory = *module.maybeMemory();
|
||||
|
||||
if (!e.writeCString(InitialLabel))
|
||||
return false;
|
||||
|
||||
if (!e.writeVarU32(memory.initialSize()))
|
||||
return false;
|
||||
|
||||
if (!e.writeCString(EndLabel))
|
||||
uint32_t maxSize = memory.maxSize() ? *memory.maxSize() : memory.initialSize();
|
||||
if (!e.writeVarU32(maxSize))
|
||||
return false;
|
||||
|
||||
e.finishSection(offset);
|
||||
|
|
|
@ -6,7 +6,7 @@ if (!wasmIsSupported())
|
|||
function testLoad(type, ext, base, offset, align, expect) {
|
||||
assertEq(wasmEvalText(
|
||||
'(module' +
|
||||
' (memory 0x10000' +
|
||||
' (memory 1' +
|
||||
' (segment 0 "\\00\\01\\02\\03\\04\\05\\06\\07\\08\\09\\0a\\0b\\0c\\0d\\0e\\0f")' +
|
||||
' (segment 16 "\\f0\\f1\\f2\\f3\\f4\\f5\\f6\\f7\\f8\\f9\\fa\\fb\\fc\\fd\\fe\\ff")' +
|
||||
' )' +
|
||||
|
@ -23,7 +23,7 @@ function testLoad(type, ext, base, offset, align, expect) {
|
|||
function testStore(type, ext, base, offset, align, value) {
|
||||
assertEq(wasmEvalText(
|
||||
'(module' +
|
||||
' (memory 0x10000' +
|
||||
' (memory 1' +
|
||||
' (segment 0 "\\00\\01\\02\\03\\04\\05\\06\\07\\08\\09\\0a\\0b\\0c\\0d\\0e\\0f")' +
|
||||
' (segment 16 "\\f0\\f1\\f2\\f3\\f4\\f5\\f6\\f7\\f8\\f9\\fa\\fb\\fc\\fd\\fe\\ff")' +
|
||||
' )' +
|
||||
|
@ -41,7 +41,7 @@ function testStore(type, ext, base, offset, align, value) {
|
|||
function testLoadError(type, ext, base, offset, align, errorMsg) {
|
||||
assertErrorMessage(() => wasmEvalText(
|
||||
'(module' +
|
||||
' (memory 0x10000' +
|
||||
' (memory 1' +
|
||||
' (segment 0 "\\00\\01\\02\\03\\04\\05\\06\\07\\08\\09\\0a\\0b\\0c\\0d\\0e\\0f")' +
|
||||
' (segment 16 "\\f0\\f1\\f2\\f3\\f4\\f5\\f6\\f7\\f8\\f9\\fa\\fb\\fc\\fd\\fe\\ff")' +
|
||||
' )' +
|
||||
|
@ -58,7 +58,7 @@ function testLoadError(type, ext, base, offset, align, errorMsg) {
|
|||
function testStoreError(type, ext, base, offset, align, errorMsg) {
|
||||
assertErrorMessage(() => wasmEvalText(
|
||||
'(module' +
|
||||
' (memory 0x10000' +
|
||||
' (memory 1' +
|
||||
' (segment 0 "\\00\\01\\02\\03\\04\\05\\06\\07\\08\\09\\0a\\0b\\0c\\0d\\0e\\0f")' +
|
||||
' (segment 16 "\\f0\\f1\\f2\\f3\\f4\\f5\\f6\\f7\\f8\\f9\\fa\\fb\\fc\\fd\\fe\\ff")' +
|
||||
' )' +
|
||||
|
@ -100,7 +100,7 @@ testLoad('i32', '16_u', 16, 0, 0, 0xf1f0);
|
|||
|
||||
// When these tests fail, uncomment the load/store tests below.
|
||||
function testLoadNYI(ext) {
|
||||
assertErrorMessage(() => wasmEvalText(`(module (memory 0x10000) (func (i64.load${ext} (i32.const 0))))`), TypeError, /NYI/);
|
||||
assertErrorMessage(() => wasmEvalText(`(module (memory 1) (func (i64.load${ext} (i32.const 0))))`), TypeError, /NYI/);
|
||||
}
|
||||
testLoadNYI('');
|
||||
testLoadNYI('8_s');
|
||||
|
@ -122,7 +122,7 @@ testStore('i32', '', 0, 0, 0, -0x3f3e2c2c);
|
|||
//testStore('i32', '', 1, 1, 4, 0xc0c1d3d4); // TODO: offset NYI
|
||||
|
||||
function testStoreNYI(ext) {
|
||||
assertErrorMessage(() => wasmEvalText(`(module (memory 0x10000) (func (i64.store${ext} (i32.const 0) (i32.const 0))))`), TypeError, /NYI/);
|
||||
assertErrorMessage(() => wasmEvalText(`(module (memory 1) (func (i64.store${ext} (i32.const 0) (i32.const 0))))`), TypeError, /NYI/);
|
||||
}
|
||||
testStoreNYI('');
|
||||
testStoreNYI('8');
|
||||
|
@ -151,11 +151,11 @@ testStore('i32', '16', 0, 0, 0, 0x2345);
|
|||
testLoadError('i32', '', 0, 0, 3, /memory access alignment must be a power of two/);
|
||||
testStoreError('i32', '', 0, 0, 3, /memory access alignment must be a power of two/);
|
||||
|
||||
assertErrorMessage(() => wasmEvalText('(module (memory 0x10000) (func (f64.store offset=0 (i32.const 0) (i32.const 0))))'), TypeError, mismatchError("i32", "f64"));
|
||||
assertErrorMessage(() => wasmEvalText('(module (memory 0x10000) (func (f64.store offset=0 (i32.const 0) (f32.const 0))))'), TypeError, mismatchError("f32", "f64"));
|
||||
assertErrorMessage(() => wasmEvalText('(module (memory 1) (func (f64.store offset=0 (i32.const 0) (i32.const 0))))'), TypeError, mismatchError("i32", "f64"));
|
||||
assertErrorMessage(() => wasmEvalText('(module (memory 1) (func (f64.store offset=0 (i32.const 0) (f32.const 0))))'), TypeError, mismatchError("f32", "f64"));
|
||||
|
||||
assertErrorMessage(() => wasmEvalText('(module (memory 0x10000) (func (f32.store offset=0 (i32.const 0) (i32.const 0))))'), TypeError, mismatchError("i32", "f32"));
|
||||
assertErrorMessage(() => wasmEvalText('(module (memory 0x10000) (func (f32.store offset=0 (i32.const 0) (f64.const 0))))'), TypeError, mismatchError("f64", "f32"));
|
||||
assertErrorMessage(() => wasmEvalText('(module (memory 1) (func (f32.store offset=0 (i32.const 0) (i32.const 0))))'), TypeError, mismatchError("i32", "f32"));
|
||||
assertErrorMessage(() => wasmEvalText('(module (memory 1) (func (f32.store offset=0 (i32.const 0) (f64.const 0))))'), TypeError, mismatchError("f64", "f32"));
|
||||
|
||||
assertErrorMessage(() => wasmEvalText('(module (memory 0x10000) (func (i32.store offset=0 (i32.const 0) (f32.const 0))))'), TypeError, mismatchError("f32", "i32"));
|
||||
assertErrorMessage(() => wasmEvalText('(module (memory 0x10000) (func (i32.store offset=0 (i32.const 0) (f64.const 0))))'), TypeError, mismatchError("f64", "i32"));
|
||||
assertErrorMessage(() => wasmEvalText('(module (memory 1) (func (i32.store offset=0 (i32.const 0) (f32.const 0))))'), TypeError, mismatchError("f32", "i32"));
|
||||
assertErrorMessage(() => wasmEvalText('(module (memory 1) (func (i32.store offset=0 (i32.const 0) (f64.const 0))))'), TypeError, mismatchError("f64", "i32"));
|
||||
|
|
|
@ -132,34 +132,32 @@ wasmEvalText('(module (import $foo "a" "" (result f64)))', {a: ()=> {}});
|
|||
// ----------------------------------------------------------------------------
|
||||
// memory
|
||||
|
||||
wasmEvalText('(module (memory 65536))');
|
||||
wasmEvalText('(module (memory 131072))');
|
||||
assertErrorMessage(() => wasmEvalText('(module (memory 0))'), TypeError, /not a multiple of 0x10000/);
|
||||
assertErrorMessage(() => wasmEvalText('(module (memory 1))'), TypeError, /not a multiple of 0x10000/);
|
||||
assertErrorMessage(() => wasmEvalText('(module (memory 65535))'), TypeError, /not a multiple of 0x10000/);
|
||||
assertErrorMessage(() => wasmEvalText('(module (memory 131071))'), TypeError, /not a multiple of 0x10000/);
|
||||
assertErrorMessage(() => wasmEvalText('(module (memory 2147483648))'), TypeError, /initial memory size too big/);
|
||||
wasmEvalText('(module (memory 0))');
|
||||
wasmEvalText('(module (memory 1))');
|
||||
assertErrorMessage(() => wasmEvalText('(module (memory 65536))'), TypeError, /initial memory size too big/);
|
||||
assertErrorMessage(() => wasmEvalText('(module (memory 32768))'), TypeError, /initial memory size too big/);
|
||||
|
||||
// May OOM, but must not crash:
|
||||
try {
|
||||
wasmEvalText('(module (memory 2147418112))');
|
||||
wasmEvalText('(module (memory 32767))');
|
||||
} catch (e) {
|
||||
print(e);
|
||||
assertEq(String(e).indexOf("out of memory") != -1, true);
|
||||
}
|
||||
|
||||
assertErrorMessage(() => wasmEvalText('(module (export "" memory))'), TypeError, /no memory section/);
|
||||
|
||||
var buf = wasmEvalText('(module (memory 65536) (export "" memory))');
|
||||
var buf = wasmEvalText('(module (memory 1) (export "" memory))');
|
||||
assertEq(buf instanceof ArrayBuffer, true);
|
||||
assertEq(buf.byteLength, 65536);
|
||||
|
||||
assertErrorMessage(() => wasmEvalText('(module (memory 65536) (export "a" memory) (export "a" memory))'), TypeError, /duplicate export/);
|
||||
assertErrorMessage(() => wasmEvalText('(module (memory 65536) (func) (export "a" memory) (export "a" 0))'), TypeError, /duplicate export/);
|
||||
var {a, b} = wasmEvalText('(module (memory 65536) (export "a" memory) (export "b" memory))');
|
||||
assertErrorMessage(() => wasmEvalText('(module (memory 1) (export "a" memory) (export "a" memory))'), TypeError, /duplicate export/);
|
||||
assertErrorMessage(() => wasmEvalText('(module (memory 1) (func) (export "a" memory) (export "a" 0))'), TypeError, /duplicate export/);
|
||||
var {a, b} = wasmEvalText('(module (memory 1) (export "a" memory) (export "b" memory))');
|
||||
assertEq(a instanceof ArrayBuffer, true);
|
||||
assertEq(a, b);
|
||||
|
||||
var obj = wasmEvalText('(module (memory 65536) (func (result i32) (i32.const 42)) (func (nop)) (export "a" memory) (export "b" 0) (export "c" 1))');
|
||||
var obj = wasmEvalText('(module (memory 1) (func (result i32) (i32.const 42)) (func (nop)) (export "a" memory) (export "b" 0) (export "c" 1))');
|
||||
assertEq(obj.a instanceof ArrayBuffer, true);
|
||||
assertEq(obj.b instanceof Function, true);
|
||||
assertEq(obj.c instanceof Function, true);
|
||||
|
@ -167,7 +165,7 @@ assertEq(obj.a.byteLength, 65536);
|
|||
assertEq(obj.b(), 42);
|
||||
assertEq(obj.c(), undefined);
|
||||
|
||||
var obj = wasmEvalText('(module (memory 65536) (func (result i32) (i32.const 42)) (export "" memory) (export "a" 0) (export "b" 0))');
|
||||
var obj = wasmEvalText('(module (memory 1) (func (result i32) (i32.const 42)) (export "" memory) (export "a" 0) (export "b" 0))');
|
||||
assertEq(obj instanceof ArrayBuffer, true);
|
||||
assertEq(obj.a instanceof Function, true);
|
||||
assertEq(obj.b instanceof Function, true);
|
||||
|
@ -175,26 +173,26 @@ assertEq(obj.a, obj.b);
|
|||
assertEq(obj.byteLength, 65536);
|
||||
assertEq(obj.a(), 42);
|
||||
|
||||
var buf = wasmEvalText('(module (memory 65536 (segment 0 "")) (export "" memory))');
|
||||
var buf = wasmEvalText('(module (memory 1 (segment 0 "")) (export "" memory))');
|
||||
assertEq(new Uint8Array(buf)[0], 0);
|
||||
|
||||
var buf = wasmEvalText('(module (memory 65536 (segment 65536 "")) (export "" memory))');
|
||||
var buf = wasmEvalText('(module (memory 1 (segment 65536 "")) (export "" memory))');
|
||||
assertEq(new Uint8Array(buf)[0], 0);
|
||||
|
||||
var buf = wasmEvalText('(module (memory 65536 (segment 0 "a")) (export "" memory))');
|
||||
var buf = wasmEvalText('(module (memory 1 (segment 0 "a")) (export "" memory))');
|
||||
assertEq(new Uint8Array(buf)[0], 'a'.charCodeAt(0));
|
||||
|
||||
var buf = wasmEvalText('(module (memory 65536 (segment 0 "a") (segment 2 "b")) (export "" memory))');
|
||||
var buf = wasmEvalText('(module (memory 1 (segment 0 "a") (segment 2 "b")) (export "" memory))');
|
||||
assertEq(new Uint8Array(buf)[0], 'a'.charCodeAt(0));
|
||||
assertEq(new Uint8Array(buf)[1], 0);
|
||||
assertEq(new Uint8Array(buf)[2], 'b'.charCodeAt(0));
|
||||
|
||||
var buf = wasmEvalText('(module (memory 65536 (segment 65535 "c")) (export "" memory))');
|
||||
var buf = wasmEvalText('(module (memory 1 (segment 65535 "c")) (export "" memory))');
|
||||
assertEq(new Uint8Array(buf)[0], 0);
|
||||
assertEq(new Uint8Array(buf)[65535], 'c'.charCodeAt(0));
|
||||
|
||||
assertErrorMessage(() => wasmEvalText('(module (memory 65536 (segment 65536 "a")) (export "" memory))'), TypeError, /data segment does not fit/);
|
||||
assertErrorMessage(() => wasmEvalText('(module (memory 65536 (segment 65535 "ab")) (export "" memory))'), TypeError, /data segment does not fit/);
|
||||
assertErrorMessage(() => wasmEvalText('(module (memory 1 (segment 65536 "a")) (export "" memory))'), TypeError, /data segment does not fit/);
|
||||
assertErrorMessage(() => wasmEvalText('(module (memory 1 (segment 65535 "ab")) (export "" memory))'), TypeError, /data segment does not fit/);
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// locals
|
||||
|
|
Загрузка…
Ссылка в новой задаче