Skip to content
Permalink
Browse files
WebAssembly: handle and optimize wasm export → wasm import calls
https://bugs.webkit.org/show_bug.cgi?id=165282

Reviewed by Saam Barati.

JSTests:

* wasm/Builder.js: Add a Proxy to Builder.js, which intercepts
unknown property lookups. This creates way better error messages
on typos than 'undefined is not a function', which happens
semi-frequently as I typo opcode names (and which one is a typo is
hard to find because we chain builders).
(const._isValidValue):
(get target):
(const._importFunctionContinuation):
(const._importMemoryContinuation):
(const._importTableContinuation):
(const._exportFunctionContinuation):
(export.default.Builder.prototype._registerSectionBuilders.const.section.in.WASM.description.section.switch.section.case.string_appeared_here.this.section):
(export.default.Builder.prototype._registerSectionBuilders.this.Unknown):
* wasm/LowLevelBinary.js: Add limited support for var{u}int64 (only the 32-bit values)
(export.default.LowLevelBinary.prototype.varint32):
(export.default.LowLevelBinary.prototype.varuint64):
(export.default.LowLevelBinary.prototype.varint64):
* wasm/function-tests/exceptions.js: update error message
* wasm/function-tests/trap-load.js: update error message
* wasm/function-tests/trap-store.js: update error message
* wasm/js-api/wasm-to-wasm-bad-signature.js: Added. Test a bunch of bad wasm->wasm import signatures
(const.makeImportee.signature.switch):
(BadSignatureDropStartParams):
* wasm/js-api/wasm-to-wasm.js: Added. Test 64-bit wasm->wasm import calls
(const.callerModule):
(const.calleeModule):
(WasmToWasm):

Source/JavaScriptCore:

  - Add a new JSType for WebAssemblyFunction, and use it when creating its
    structure. This will is used to quickly detect from wasm whether the import
    call is to another wasm module, or whether it's to JS.
  - Generate two stubs from the import stub generator: one for wasm->JS and one
    for wasm -> wasm. This is done at Module time. Which is called will only be
    known at Instance time, once we've received the import object. We want to
    avoid codegen at Instance time, so having both around is great.
  - Restore the WebAssembly global state (VM top Instance, and pinned registers)
    after call / call_indirect, and in the JS->wasm entry stub.
  - Pinned registers are now a global thing, not per-Memory, because the wasm ->
    wasm stubs are generated at Module time where we don't really have enough
    information to do the right thing (doing so would generate too much code).

* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* runtime/JSType.h: add WebAssemblyFunctionType as a JSType
* wasm/WasmB3IRGenerator.cpp: significantly rework how calls which
could be external work, and how we save / restore global state:
VM's top Instance, and pinned registers
(JSC::Wasm::B3IRGenerator::B3IRGenerator):
(JSC::Wasm::getMemoryBaseAndSize):
(JSC::Wasm::restoreWebAssemblyGlobalState):
(JSC::Wasm::createJSToWasmWrapper):
(JSC::Wasm::parseAndCompile):
* wasm/WasmB3IRGenerator.h:
* wasm/WasmBinding.cpp:
(JSC::Wasm::materializeImportJSCell):
(JSC::Wasm::wasmToJS):
(JSC::Wasm::wasmToWasm): the main goal of this patch was adding this function
(JSC::Wasm::exitStubGenerator):
* wasm/WasmBinding.h:
* wasm/WasmFormat.h: Get rid of much of the function index space:
we already have all of its information elsewhere, and as-is it
provides no extra efficiency.
(JSC::Wasm::ModuleInformation::functionIndexSpaceSize):
(JSC::Wasm::ModuleInformation::isImportedFunctionFromFunctionIndexSpace):
(JSC::Wasm::ModuleInformation::signatureIndexFromFunctionIndexSpace):
* wasm/WasmFunctionParser.h:
(JSC::Wasm::FunctionParser<Context>::FunctionParser):
* wasm/WasmMemory.cpp: Add some logging.
(JSC::Wasm::Memory::dump): this was nice when debugging
(JSC::Wasm::Memory::makeString):
(JSC::Wasm::Memory::Memory):
(JSC::Wasm::Memory::~Memory):
(JSC::Wasm::Memory::grow):
* wasm/WasmMemory.h: don't use extra indirection, it wasn't
needed. Reorder some of the fields which are looked up at runtime
so they're more cache-friendly.
(JSC::Wasm::Memory::Memory):
(JSC::Wasm::Memory::mode):
(JSC::Wasm::Memory::offsetOfSize):
* wasm/WasmMemoryInformation.cpp: Pinned registers are now a
global thing for all of JSC, not a per-Memory thing
anymore. wasm->wasm calls are more complex otherwise: they have to
figure out how to bridge between the caller and callee's
special-snowflake pinning.
(JSC::Wasm::PinnedRegisterInfo::get):
(JSC::Wasm::PinnedRegisterInfo::PinnedRegisterInfo):
(JSC::Wasm::MemoryInformation::MemoryInformation):
* wasm/WasmMemoryInformation.h:
* wasm/WasmModuleParser.cpp:
* wasm/WasmModuleParser.h:
* wasm/WasmPageCount.cpp: Copied from Source/JavaScriptCore/wasm/WasmBinding.h.
(JSC::Wasm::PageCount::dump): nice for debugging
* wasm/WasmPageCount.h:
* wasm/WasmPlan.cpp:
(JSC::Wasm::Plan::parseAndValidateModule):
(JSC::Wasm::Plan::run):
* wasm/WasmPlan.h:
(JSC::Wasm::Plan::takeWasmExitStubs):
* wasm/WasmSignature.cpp:
(JSC::Wasm::Signature::toString):
(JSC::Wasm::Signature::dump):
* wasm/WasmSignature.h:
* wasm/WasmValidate.cpp:
(JSC::Wasm::validateFunction):
* wasm/WasmValidate.h:
* wasm/js/JSWebAssemblyInstance.h:
(JSC::JSWebAssemblyInstance::offsetOfTable):
(JSC::JSWebAssemblyInstance::offsetOfImportFunctions):
(JSC::JSWebAssemblyInstance::offsetOfImportFunction):
* wasm/js/JSWebAssemblyMemory.cpp:
(JSC::JSWebAssemblyMemory::create):
(JSC::JSWebAssemblyMemory::JSWebAssemblyMemory):
(JSC::JSWebAssemblyMemory::buffer):
(JSC::JSWebAssemblyMemory::grow):
* wasm/js/JSWebAssemblyMemory.h:
(JSC::JSWebAssemblyMemory::memory):
(JSC::JSWebAssemblyMemory::offsetOfMemory):
(JSC::JSWebAssemblyMemory::offsetOfSize):
* wasm/js/JSWebAssemblyModule.cpp:
(JSC::JSWebAssemblyModule::create):
(JSC::JSWebAssemblyModule::JSWebAssemblyModule):
* wasm/js/JSWebAssemblyModule.h:
(JSC::JSWebAssemblyModule::signatureIndexFromFunctionIndexSpace):
(JSC::JSWebAssemblyModule::functionImportCount):
* wasm/js/WebAssemblyFunction.cpp:
(JSC::callWebAssemblyFunction):
(JSC::WebAssemblyFunction::create):
(JSC::WebAssemblyFunction::createStructure):
(JSC::WebAssemblyFunction::WebAssemblyFunction):
(JSC::WebAssemblyFunction::finishCreation):
* wasm/js/WebAssemblyFunction.h:
(JSC::WebAssemblyFunction::wasmEntrypoint):
(JSC::WebAssemblyFunction::offsetOfInstance):
(JSC::WebAssemblyFunction::offsetOfWasmEntryPointCode):
* wasm/js/WebAssemblyInstanceConstructor.cpp:
(JSC::constructJSWebAssemblyInstance): always start with a dummy
memory, so wasm->wasm calls don't need to null-check
* wasm/js/WebAssemblyMemoryConstructor.cpp:
(JSC::constructJSWebAssemblyMemory):
* wasm/js/WebAssemblyModuleConstructor.cpp:
(JSC::WebAssemblyModuleConstructor::createModule):
* wasm/js/WebAssemblyModuleRecord.cpp:
(JSC::WebAssemblyModuleRecord::link):
(JSC::WebAssemblyModuleRecord::evaluate):
* wasm/js/WebAssemblyModuleRecord.h:


Canonical link: https://commits.webkit.org/183789@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210229 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
jfbastien committed Jan 3, 2017
1 parent 4f7d44e commit bf1977f0a5116bec61a40df1fe968732c1a59b96
Showing with 927 additions and 298 deletions.
  1. +35 −0 JSTests/ChangeLog
  2. +51 −40 JSTests/wasm/Builder.js
  3. +12 −0 JSTests/wasm/LowLevelBinary.js
  4. +3 −3 JSTests/wasm/function-tests/exceptions.js
  5. +1 −1 JSTests/wasm/function-tests/trap-load.js
  6. +1 −1 JSTests/wasm/function-tests/trap-store.js
  7. +105 −0 JSTests/wasm/js-api/wasm-to-wasm-bad-signature.js
  8. +72 −0 JSTests/wasm/js-api/wasm-to-wasm.js
  9. +1 −0 Source/JavaScriptCore/CMakeLists.txt
  10. +125 −0 Source/JavaScriptCore/ChangeLog
  11. +6 −2 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
  12. +0 −1 Source/JavaScriptCore/jsc.cpp
  13. +2 −0 Source/JavaScriptCore/runtime/JSType.h
  14. +136 −86 Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp
  15. +1 −1 Source/JavaScriptCore/wasm/WasmB3IRGenerator.h
  16. +61 −6 Source/JavaScriptCore/wasm/WasmBinding.cpp
  17. +1 −1 Source/JavaScriptCore/wasm/WasmBinding.h
  18. +20 −8 Source/JavaScriptCore/wasm/WasmFormat.h
  19. +8 −8 Source/JavaScriptCore/wasm/WasmFunctionParser.h
  20. +54 −3 Source/JavaScriptCore/wasm/WasmMemory.cpp
  21. +21 −10 Source/JavaScriptCore/wasm/WasmMemory.h
  22. +42 −17 Source/JavaScriptCore/wasm/WasmMemoryInformation.cpp
  23. +3 −6 Source/JavaScriptCore/wasm/WasmMemoryInformation.h
  24. +11 −16 Source/JavaScriptCore/wasm/WasmModuleParser.cpp
  25. +1 −1 Source/JavaScriptCore/wasm/WasmModuleParser.h
  26. +45 −0 Source/JavaScriptCore/wasm/WasmPageCount.cpp
  27. +6 −0 Source/JavaScriptCore/wasm/WasmPageCount.h
  28. +26 −18 Source/JavaScriptCore/wasm/WasmPlan.cpp
  29. +4 −10 Source/JavaScriptCore/wasm/WasmPlan.h
  30. +14 −4 Source/JavaScriptCore/wasm/WasmSignature.cpp
  31. +1 −0 Source/JavaScriptCore/wasm/WasmSignature.h
  32. +2 −2 Source/JavaScriptCore/wasm/WasmValidate.cpp
  33. +1 −1 Source/JavaScriptCore/wasm/WasmValidate.h
  34. +3 −6 Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h
  35. +6 −6 Source/JavaScriptCore/wasm/js/JSWebAssemblyMemory.cpp
  36. +6 −5 Source/JavaScriptCore/wasm/js/JSWebAssemblyMemory.h
  37. +4 −5 Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.cpp
  38. +6 −10 Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h
  39. +6 −3 Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp
  40. +6 −2 Source/JavaScriptCore/wasm/js/WebAssemblyFunction.h
  41. +13 −7 Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp
  42. +1 −1 Source/JavaScriptCore/wasm/js/WebAssemblyMemoryConstructor.cpp
  43. +1 −1 Source/JavaScriptCore/wasm/js/WebAssemblyModuleConstructor.cpp
  44. +3 −6 Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp
@@ -1,3 +1,38 @@
2017-01-02 JF Bastien <jfbastien@apple.com>

WebAssembly: handle and optimize wasm export → wasm import calls
https://bugs.webkit.org/show_bug.cgi?id=165282

Reviewed by Saam Barati.

* wasm/Builder.js: Add a Proxy to Builder.js, which intercepts
unknown property lookups. This creates way better error messages
on typos than 'undefined is not a function', which happens
semi-frequently as I typo opcode names (and which one is a typo is
hard to find because we chain builders).
(const._isValidValue):
(get target):
(const._importFunctionContinuation):
(const._importMemoryContinuation):
(const._importTableContinuation):
(const._exportFunctionContinuation):
(export.default.Builder.prototype._registerSectionBuilders.const.section.in.WASM.description.section.switch.section.case.string_appeared_here.this.section):
(export.default.Builder.prototype._registerSectionBuilders.this.Unknown):
* wasm/LowLevelBinary.js: Add limited support for var{u}int64 (only the 32-bit values)
(export.default.LowLevelBinary.prototype.varint32):
(export.default.LowLevelBinary.prototype.varuint64):
(export.default.LowLevelBinary.prototype.varint64):
* wasm/function-tests/exceptions.js: update error message
* wasm/function-tests/trap-load.js: update error message
* wasm/function-tests/trap-store.js: update error message
* wasm/js-api/wasm-to-wasm-bad-signature.js: Added. Test a bunch of bad wasm->wasm import signatures
(const.makeImportee.signature.switch):
(BadSignatureDropStartParams):
* wasm/js-api/wasm-to-wasm.js: Added. Test 64-bit wasm->wasm import calls
(const.callerModule):
(const.calleeModule):
(WasmToWasm):

2017-01-02 Saam Barati <sbarati@apple.com>

WebAssembly: Some loads don't take into account the offset
@@ -38,7 +38,7 @@ const _isValidValue = (value, type) => {
switch (type) {
// We allow both signed and unsigned numbers.
case "i32": return Math.round(value) === value && LLB.varint32Min <= value && value <= LLB.varuint32Max;
case "i64": throw new Error(`Unimplemented: value check for ${type}`); // FIXME https://bugs.webkit.org/show_bug.cgi?id=163420 64-bit values
case "i64": return true; // FIXME https://bugs.webkit.org/show_bug.cgi?id=163420 64-bit values
case "f32": return typeof(value) === "number" && isFinite(value);
case "f64": return typeof(value) === "number" && isFinite(value);
default: throw new Error(`Implementation problem: unknown type ${type}`);
@@ -57,6 +57,16 @@ const _normalizeFunctionSignature = (params, ret) => {
return [params, ret];
};

const _errorHandlingProxyFor = builder => builder["__isProxy"] ? builder : new Proxy(builder, {
get: (target, property, receiver) => {
if (property === "__isProxy")
return true;
if (target[property] === undefined)
throw new Error(`WebAssembly builder received unknown property '${property}'`);
return target[property];
}
});

const _maybeRegisterType = (builder, type) => {
const typeSection = builder._getSection("Type");
if (typeof(type) === "number") {
@@ -100,7 +110,7 @@ const _importFunctionContinuation = (builder, section, nextBuilder) => {
section.data.push({ field: field, type: type, kind: "Function", module: module });
// Imports also count in the function index space. Map them as objects to avoid clashing with Code functions' names.
builder._registerFunctionToIndexSpace({ module: module, field: field });
return nextBuilder;
return _errorHandlingProxyFor(nextBuilder);
};
};

@@ -109,7 +119,7 @@ const _importMemoryContinuation = (builder, section, nextBuilder) => {
assert.isString(module, `Import Memory module should be a string, got "${module}"`);
assert.isString(field, `Import Memory field should be a string, got "${field}"`);
section.data.push({module, field, kind: "Memory", memoryDescription: {initial, maximum}});
return nextBuilder;
return _errorHandlingProxyFor(nextBuilder);
};
};

@@ -118,7 +128,7 @@ const _importTableContinuation = (builder, section, nextBuilder) => {
assert.isString(module, `Import Table module should be a string, got "${module}"`);
assert.isString(field, `Import Table field should be a string, got "${field}"`);
section.data.push({module, field, kind: "Table", tableDescription: {initial, maximum, element}});
return nextBuilder;
return _errorHandlingProxyFor(nextBuilder);
};
};

@@ -172,7 +182,7 @@ const _exportFunctionContinuation = (builder, section, nextBuilder) => {
assert.eq(type, exportedImport.type, `Re-exporting import "${exportedImport.field}" as "${field}" has mismatching type`);
}
section.data.push({ field: field, type: type, kind: "Function", index: index });
return nextBuilder;
return _errorHandlingProxyFor(nextBuilder);
};
};

@@ -189,23 +199,23 @@ const _exportGlobalContinuation = (builder, section, nextBuilder) => {
return (field, index) => {
assert.isNumber(index, `Global exports only support number indices right now`);
section.data.push({ field, kind: "Global", index });
return nextBuilder;
return _errorHandlingProxyFor(nextBuilder);
}
};

const _exportMemoryContinuation = (builder, section, nextBuilder) => {
return (field, index) => {
assert.isNumber(index, `Memory exports only support number indices`);
section.data.push({field, kind: "Memory", index});
return nextBuilder;
return _errorHandlingProxyFor(nextBuilder);
}
};

const _exportTableContinuation = (builder, section, nextBuilder) => {
return (field, index) => {
assert.isNumber(index, `Table exports only support number indices`);
section.data.push({field, kind: "Table", index});
return nextBuilder;
return _errorHandlingProxyFor(nextBuilder);
}
};

@@ -220,10 +230,10 @@ const _importGlobalContinuation = (builder, section, nextBuilder) => {
assert.isString(field, `Import global field should be a string, got "${field}"`);
assert.isString(mutability, `Import global mutability should be a string, got "${mutability}"`);
section.data.push({ globalDescription: { type: op, mutability: _normalizeMutability(mutability) }, module, field, kind: "Global" });
return globalBuilder;
return _errorHandlingProxyFor(globalBuilder);
};
}
return globalBuilder;
return _errorHandlingProxyFor(globalBuilder);
};
};

@@ -324,11 +334,11 @@ const _createFunctionBuilder = (func, builder, previousBuilder) => {
default:
nextBuilder = functionBuilder;
break;
case "End":
case "End":
nextBuilder = previousBuilder;
break;
break;
case "Block":
case "Loop":
case "Loop":
case "If":
nextBuilder = _createFunctionBuilder(func, builder, functionBuilder);
break;
@@ -344,11 +354,12 @@ const _createFunctionBuilder = (func, builder, previousBuilder) => {
const stackArgs = []; // FIXME https://bugs.webkit.org/show_bug.cgi?id=162706
func.code.push({ name: op, value: value, arguments: stackArgs, immediates: imms });
if (hasContinuation)
return continuation(nextBuilder).End();
return nextBuilder;
return _errorHandlingProxyFor(continuation(nextBuilder).End());
return _errorHandlingProxyFor(nextBuilder);
};
}
return functionBuilder;
};

return _errorHandlingProxyFor(functionBuilder);
}

const _createFunction = (section, builder, previousBuilder) => {
@@ -449,10 +460,10 @@ export default class Builder {
Func: (params, ret) => {
[params, ret] = _normalizeFunctionSignature(params, ret);
s.data.push({ params: params, ret: ret });
return typeBuilder;
return _errorHandlingProxyFor(typeBuilder);
},
};
return typeBuilder;
return _errorHandlingProxyFor(typeBuilder);
};
break;

@@ -466,7 +477,7 @@ export default class Builder {
importBuilder.Function = _importFunctionContinuation(this, s, importBuilder);
importBuilder.Memory = _importMemoryContinuation(this, s, importBuilder);
importBuilder.Table = _importTableContinuation(this, s, importBuilder);
return importBuilder;
return _errorHandlingProxyFor(importBuilder);
};
break;

@@ -477,7 +488,7 @@ export default class Builder {
End: () => this
// FIXME: add ability to add this with whatever.
};
return functionBuilder;
return _errorHandlingProxyFor(functionBuilder);
};
break;

@@ -488,10 +499,10 @@ export default class Builder {
End: () => this,
Table: ({initial, maximum, element}) => {
s.data.push({tableDescription: {initial, maximum, element}});
return tableBuilder;
return _errorHandlingProxyFor(tableBuilder);
}
};
return tableBuilder;
return _errorHandlingProxyFor(tableBuilder);
};
break;

@@ -502,10 +513,10 @@ export default class Builder {
End: () => this,
InitialMaxPages: (initial, max) => {
s.data.push({ initial, max });
return memoryBuilder;
return _errorHandlingProxyFor(memoryBuilder);
}
};
return memoryBuilder;
return _errorHandlingProxyFor(memoryBuilder);
};
break;

@@ -516,16 +527,16 @@ export default class Builder {
End: () => this,
GetGlobal: (type, initValue, mutability) => {
s.data.push({ type, op: "get_global", mutability: _normalizeMutability(mutability), initValue });
return globalBuilder;
return _errorHandlingProxyFor(globalBuilder);
}
};
for (let op of WASM.description.value_type) {
globalBuilder[_toJavaScriptName(op)] = (initValue, mutability) => {
s.data.push({ type: op, op: op + ".const", mutability: _normalizeMutability(mutability), initValue });
return globalBuilder;
return _errorHandlingProxyFor(globalBuilder);
};
}
return globalBuilder;
return _errorHandlingProxyFor(globalBuilder);
};
break;

@@ -539,7 +550,7 @@ export default class Builder {
exportBuilder.Function = _exportFunctionContinuation(this, s, exportBuilder);
exportBuilder.Memory = _exportMemoryContinuation(this, s, exportBuilder);
exportBuilder.Table = _exportTableContinuation(this, s, exportBuilder);
return exportBuilder;
return _errorHandlingProxyFor(exportBuilder);
};
break;

@@ -552,7 +563,7 @@ export default class Builder {
if (typeof(functionIndexOrName) !== "number" && typeof(functionIndexOrName) !== "string")
throw new Error(`Start section's function index must either be a number or a string`);
s.data.push(functionIndexOrName);
return startBuilder;
return _errorHandlingProxyFor(startBuilder);
};
break;

@@ -563,11 +574,11 @@ export default class Builder {
End: () => this,
Element: ({tableIndex = 0, offset, functionIndices}) => {
s.data.push({tableIndex, offset, functionIndices});
return elementBuilder;
return _errorHandlingProxyFor(elementBuilder);
}
};

return elementBuilder;
return _errorHandlingProxyFor(elementBuilder);
};
break;

@@ -632,12 +643,12 @@ export default class Builder {
// FIXME in checked mode, test that the type is acceptable for start function. We probably want _registerFunctionToIndexSpace to also register types per index. https://bugs.webkit.org/show_bug.cgi?id=165658
}
}
return builder;
return _errorHandlingProxyFor(builder);
},

};
codeBuilder.Function = _createFunction(s, builder, codeBuilder);
return codeBuilder;
return _errorHandlingProxyFor(codeBuilder);
};
break;

@@ -660,19 +671,19 @@ export default class Builder {
Index: index => {
assert.eq(index, 0); // Linear memory index must be zero in MVP.
thisSegment.index = index;
return segmentBuilder;
return _errorHandlingProxyFor(segmentBuilder);
},
Offset: offset => {
// FIXME allow complex init_expr here. https://bugs.webkit.org/show_bug.cgi?id=165700
assert.isNumber(offset);
thisSegment.offset = offset;
return segmentBuilder;
return _errorHandlingProxyFor(segmentBuilder);
},
};
return segmentBuilder;
return _errorHandlingProxyFor(segmentBuilder);
},
};
return dataBuilder;
return _errorHandlingProxyFor(dataBuilder);
};
break;

@@ -690,10 +701,10 @@ export default class Builder {
Byte: b => {
assert.eq(b & 0xFF, b, `Unknown section expected byte, got: "${b}"`);
s.data.push(b);
return unknownBuilder;
return _errorHandlingProxyFor(unknownBuilder);
}
};
return unknownBuilder;
return _errorHandlingProxyFor(unknownBuilder);
};
}
_addSection(nameOrNumber, extraObject) {
@@ -170,6 +170,18 @@ export default class LowLevelBinary {
this.uint8(0x80 | b);
} while (true);
}
varuint64(v) {
assert.isNumber(v);
if (v < varuint32Min || varuint32Max < v)
throw new RangeError(`unimplemented: varuint64 larger than 32-bit`);
this.varuint32(v); // FIXME implement 64-bit var{u}int https://bugs.webkit.org/show_bug.cgi?id=163420
}
varint64(v) {
assert.isNumber(v);
if (v < varint32Min || varint32Max < v)
throw new RangeError(`unimplemented: varint64 larger than 32-bit`);
this.varint32(v); // FIXME implement 64-bit var{u}int https://bugs.webkit.org/show_bug.cgi?id=163420
}
varuint1(v) {
if (v !== 0 && v !== 1)
throw new RangeError(`Invalid varuint1 ${v} range is [0, 1]`);
@@ -45,18 +45,18 @@ function makeInstance() {
assert.eq(table.get(0), null);

for (let i = 0; i < 1000; i++) {
assert.throws(() => foo(0, i), WebAssembly.RuntimeError, "call_indirect to a null table entry (evaluating 'func(...args)')");
assert.throws(() => foo(0, i), WebAssembly.RuntimeError, "call_indirect to a null table entry");
}

table.set(0, foo);
assert.eq(table.get(0), foo);

for (let i = 0; i < 1000; i++) {
assert.throws(() => foo(1 + i, i), WebAssembly.RuntimeError, "Out of bounds call_indirect (evaluating 'func(...args)')");
assert.throws(() => foo(1 + i, i), WebAssembly.RuntimeError, "Out of bounds call_indirect");
}

for (let i = 0; i < 1000; i++) {
assert.throws(() => foo(0, i), WebAssembly.RuntimeError, "call_indirect to a signature that does not match (evaluating 'func(...args)')");
assert.throws(() => foo(0, i), WebAssembly.RuntimeError, "call_indirect to a signature that does not match");
}

table.set(0, bar);
@@ -29,6 +29,6 @@ function wasmFrameCountFromError(e) {
}

for (let i = 0; i < 1000; i++) {
const e = assert.throws(() => foo(numPages * pageSize + 1), WebAssembly.RuntimeError, "Out of bounds memory access (evaluating 'func(...args)')");
const e = assert.throws(() => foo(numPages * pageSize + 1), WebAssembly.RuntimeError, "Out of bounds memory access");
assert.eq(wasmFrameCountFromError(e), 2);
}
@@ -25,5 +25,5 @@ const numPages = 10;
const foo = new WebAssembly.Instance(module, {a: {b: new WebAssembly.Memory({initial: numPages})}}).exports.foo;

for (let i = 0; i < 10000; i++)
assert.throws(() => foo(i, numPages * pageSize + 1), WebAssembly.RuntimeError, "Out of bounds memory access (evaluating 'func(...args)')");
assert.throws(() => foo(i, numPages * pageSize + 1), WebAssembly.RuntimeError, "Out of bounds memory access");
}

0 comments on commit bf1977f

Please sign in to comment.