Bug 1284155 - Baldr: add element type to Tables (r=bbouvier)

MozReview-Commit-ID: 236qwoLkmH8

--HG--
extra : rebase_source : d37a161e91e6f9626ab8be1c0086919835078a16
This commit is contained in:
Luke Wagner 2016-08-02 10:13:10 -05:00
Родитель c2137a4bda
Коммит 7bae287798
9 изменённых файлов: 69 добавлений и 23 удалений

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

@ -64,6 +64,7 @@ enum class ValType
enum class TypeConstructor
{
AnyFunc = 0x20,
Function = 0x40
};

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

@ -727,6 +727,13 @@ DecodeResizableMemory(Decoder& d, ModuleGeneratorData* init)
static bool
DecodeResizableTable(Decoder& d, ModuleGeneratorData* init)
{
uint32_t elementType;
if (!d.readVarU32(&elementType))
return Fail(d, "expected table element type");
if (elementType != uint32_t(TypeConstructor::AnyFunc))
return Fail(d, "expected 'anyfunc' element type");
Resizable resizable;
if (!DecodeResizable(d, &resizable))
return false;

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

@ -900,18 +900,40 @@ WasmTableObject::construct(JSContext* cx, unsigned argc, Value* vp)
return false;
}
RootedObject obj(cx, &args[0].toObject());
RootedId id(cx);
RootedValue val(cx);
JSAtom* elementAtom = Atomize(cx, "element", strlen("element"));
if (!elementAtom)
return false;
id = AtomToId(elementAtom);
if (!GetProperty(cx, obj, obj, id, &val))
return false;
if (!val.isString()) {
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_ELEMENT);
return false;
}
JSLinearString* str = val.toString()->ensureLinear(cx);
if (!str)
return false;
if (!StringEqualsAscii(str, "anyfunc")) {
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_ELEMENT);
return false;
}
JSAtom* initialAtom = Atomize(cx, "initial", strlen("initial"));
if (!initialAtom)
return false;
RootedObject obj(cx, &args[0].toObject());
RootedId id(cx, AtomToId(initialAtom));
RootedValue initialVal(cx);
if (!GetProperty(cx, obj, obj, id, &initialVal))
id = AtomToId(initialAtom);
if (!GetProperty(cx, obj, obj, id, &val))
return false;
double initialDbl;
if (!ToInteger(cx, initialVal, &initialDbl))
if (!ToInteger(cx, val, &initialDbl))
return false;
if (initialDbl < 0 || initialDbl > INT32_MAX) {

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

@ -3717,6 +3717,15 @@ EncodeResizable(Encoder& e, const AstResizable& resizable)
return true;
}
static bool
EncodeResizableTable(Encoder& e, const AstResizable& resizable)
{
if (!e.writeVarU32(uint32_t(TypeConstructor::AnyFunc)))
return false;
return EncodeResizable(e, resizable);
}
static bool
EncodeImport(Encoder& e, bool newFormat, AstImport& imp)
{
@ -3755,6 +3764,9 @@ EncodeImport(Encoder& e, bool newFormat, AstImport& imp)
return false;
break;
case DefinitionKind::Table:
if (!EncodeResizableTable(e, imp.resizable()))
return false;
break;
case DefinitionKind::Memory:
if (!EncodeResizable(e, imp.resizable()))
return false;
@ -3936,7 +3948,7 @@ EncodeTableSection(Encoder& e, bool newFormat, AstModule& module)
const AstResizable& table = module.table();
if (newFormat) {
if (!EncodeResizable(e, table))
if (!EncodeResizableTable(e, table))
return false;
} else {
if (module.elemSegments().length() != 1)

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

@ -10,10 +10,10 @@ const mem1Page = new Memory({initial:1});
const mem2Page = new Memory({initial:2});
const mem3Page = new Memory({initial:3});
const mem4Page = new Memory({initial:4});
const tab1Elem = new Table({initial:1});
const tab2Elem = new Table({initial:2});
const tab3Elem = new Table({initial:3});
const tab4Elem = new Table({initial:4});
const tab1Elem = new Table({initial:1, element:"anyfunc"});
const tab2Elem = new Table({initial:2, element:"anyfunc"});
const tab3Elem = new Table({initial:3, element:"anyfunc"});
const tab4Elem = new Table({initial:4, element:"anyfunc"});
// Explicitly opt into the new binary format for imports and exports until it
// is used by default everywhere.
@ -259,7 +259,7 @@ assertEq(mem, e.foo);
assertEq(mem, e.bar);
var code = textToBinary('(module (import "a" "b" (table 1 1)) (export "foo" table) (export "bar" table))');
var tbl = new Table({initial:1});
var tbl = new Table({initial:1, element:"anyfunc"});
var e = new Instance(new Module(code), {a:{b:tbl}}).exports;
assertEq(tbl, e.foo);
assertEq(tbl, e.bar);
@ -317,7 +317,7 @@ var m = new Module(textToBinary(`
(func $three (result i32) (i32.const 3))
(func $four (result i32) (i32.const 4)))
`));
var tbl = new Table({initial:10});
var tbl = new Table({initial:10, element:"anyfunc"});
new Instance(m, {a:{b:tbl}});
assertEq(tbl.get(0)(), 1);
assertEq(tbl.get(1)(), 2);

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

@ -171,11 +171,14 @@ assertEq(Table.length, 1);
assertEq(Table.name, "Table");
assertErrorMessage(() => Table(), TypeError, /constructor without new is forbidden/);
assertErrorMessage(() => new Table(1), TypeError, "first argument must be a table descriptor");
assertErrorMessage(() => new Table({initial:{valueOf() { throw new Error("here")}}}), Error, "here");
assertErrorMessage(() => new Table({initial:-1}), TypeError, /bad Table initial size/);
assertErrorMessage(() => new Table({initial:Math.pow(2,32)}), TypeError, /bad Table initial size/);
assertEq(new Table({initial:1}) instanceof Table, true);
assertEq(new Table({initial:1.5}) instanceof Table, true);
assertErrorMessage(() => new Table({initial:1, element:1}), TypeError, /must be "anyfunc"/);
assertErrorMessage(() => new Table({initial:1, element:"any"}), TypeError, /must be "anyfunc"/);
assertErrorMessage(() => new Table({initial:1, element:{valueOf() { return "anyfunc" }}}), TypeError, /must be "anyfunc"/);
assertErrorMessage(() => new Table({initial:{valueOf() { throw new Error("here")}}, element:"anyfunc"}), Error, "here");
assertErrorMessage(() => new Table({initial:-1, element:"anyfunc"}), TypeError, /bad Table initial size/);
assertErrorMessage(() => new Table({initial:Math.pow(2,32), element:"anyfunc"}), TypeError, /bad Table initial size/);
assertEq(new Table({initial:1, element:"anyfunc"}) instanceof Table, true);
assertEq(new Table({initial:1.5, element:"anyfunc"}) instanceof Table, true);
// 'WebAssembly.Table.prototype' property
const tableProtoDesc = Object.getOwnPropertyDescriptor(Table, 'prototype');
@ -191,7 +194,7 @@ assertEq(String(tableProto), "[object Object]");
assertEq(Object.getPrototypeOf(tableProto), Object.prototype);
// 'WebAssembly.Table' instance objects
const tbl1 = new Table({initial:2});
const tbl1 = new Table({initial:2, element:"anyfunc"});
assertEq(typeof tbl1, "object");
assertEq(String(tbl1), "[object WebAssembly.Table]");
assertEq(Object.getPrototypeOf(tbl1), tableProto);

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

@ -108,7 +108,7 @@ assertEq(finalizeCount(), 3);
// Before initialization, a table is not bound to any instance.
resetFinalizeCount();
var i = evalText(`(module (func $f0 (result i32) (i32.const 0)) (export "f0" $f0))`);
var t = new Table({initial:4});
var t = new Table({initial:4, element:"anyfunc"});
i.edge = makeFinalizeObserver();
t.edge = makeFinalizeObserver();
gc();
@ -125,7 +125,7 @@ assertEq(finalizeCount(), 2);
resetFinalizeCount();
var i = evalText(`(module (func $f (result i32) (i32.const 42)) (export "f" $f))`);
var f = i.exports.f;
var t = new Table({initial:1});
var t = new Table({initial:1, element:"anyfunc"});
i.edge = makeFinalizeObserver();
f.edge = makeFinalizeObserver();
t.edge = makeFinalizeObserver();

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

@ -29,7 +29,7 @@ assertErrorMessage(() => evalText(`(module (table (resizable 10)) (import "globa
assertErrorMessage(() => evalText(`(module (table (resizable 10)) (import "globals" "a" (global i32 immutable)) (elem (i32.const 1) $f0 $f0) (elem (get_global 0) $f0) ${callee(0)})`, {globals:{a:0}}), TypeError, /must be.*ordered/);
assertErrorMessage(() => evalText(`(module (table (resizable 10)) (import "globals" "a" (global i32 immutable)) (elem (get_global 0) $f0 $f0) (elem (i32.const 2) $f0) ${callee(0)})`, {globals:{a:1}}), TypeError, /must be.*disjoint/);
var tbl = new Table({initial:50});
var tbl = new Table({initial:50, element:"anyfunc"});
assertErrorMessage(() => evalText(`(module
(import "globals" "table" (table 10 100))
(import "globals" "a" (global i32 immutable))
@ -64,7 +64,7 @@ assertEq(call(5), 2);
assertErrorMessage(() => call(6), Error, /bad wasm indirect call/);
assertErrorMessage(() => call(10), Error, /out-of-range/);
var tbl = new Table({initial:3});
var tbl = new Table({initial:3, element:"anyfunc"});
var call = evalText(`(module (import "a" "b" (table 2)) (export "tbl" table) (elem (i32.const 0) $f0 $f1) ${callee(0)} ${callee(1)} ${caller})`, {a:{b:tbl}}).exports.call;
assertEq(call(0), 0);
assertEq(call(1), 1);

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

@ -350,6 +350,7 @@ MSG_DEF(JSMSG_WASM_BAD_MOD_ARG, 0, JSEXN_TYPEERR, "first argument mus
MSG_DEF(JSMSG_WASM_BAD_DESC_ARG, 1, JSEXN_TYPEERR, "first argument must be a {0} descriptor")
MSG_DEF(JSMSG_WASM_BAD_IMP_SIZE, 1, JSEXN_TYPEERR, "imported {0} with incompatible size")
MSG_DEF(JSMSG_WASM_BAD_SIZE, 2, JSEXN_TYPEERR, "bad {0} {1} size")
MSG_DEF(JSMSG_WASM_BAD_ELEMENT, 0, JSEXN_TYPEERR, "\"element\" property of table descriptor must be \"anyfunc\"")
MSG_DEF(JSMSG_WASM_BAD_IMPORT_ARG, 0, JSEXN_TYPEERR, "second argument, if present, must be an object")
MSG_DEF(JSMSG_WASM_BAD_IMPORT_FIELD, 1, JSEXN_TYPEERR, "import object field is not {0}")
MSG_DEF(JSMSG_WASM_BAD_SET_VALUE, 0, JSEXN_TYPEERR, "second argument must be null or an exported WebAssembly Function object")