WebAssembly JS API: implement Module
authorjfbastien@apple.com <jfbastien@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 25 Oct 2016 17:23:53 +0000 (17:23 +0000)
committerjfbastien@apple.com <jfbastien@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 25 Oct 2016 17:23:53 +0000 (17:23 +0000)
This implementation allows us to:
 - Syncrhonously create a WebAssembly.Module with a typed array.
 - Creates a compilation plan.
 - Parse the Module and creates corresponding code.
 - Throw WebAssembly.CompileError with mildly helpful [*] error messages on
   failure.

Consult the API documentation for expected behavior: https://github.com/WebAssembly/design/blob/master/JS.md#webassemblymodule-constructor

For now the implementation discards the generated code.

The next steps will be:
 - Expose a Module's exports.
 - Implement WebAssembly.Instance, which allows instantiating and running a
   compiled Module.
 - Beef up the testing infrastructure under JSTests/wasm so that more complex
   modules can be created and tested (instead of writing the bits by hand).

This patch also:
 - Adds assert.instanceof in assert.js.
 - Refactors Wasm::Parser and friends to accept const uint8_t* as well as a
   Vector, to avoid copying when invoked synchronously.
 - Remove useless Structure from some of the wasm constructors: they're already
   on the JSGlobalObject, visited properly and all.
 - Fix off-by-one error in parsing: Parser::parseUInt32 failed if the integer
   was exactly at end of file.

 [*] On error messages while parsing: I filed https://bugs.webkit.org/show_bug.cgi?id=163919

WebAssembly JS API: implement Module
https://bugs.webkit.org/show_bug.cgi?id=163903

Reviewed by Keith Miller.

JSTests:

* wasm/assert.js: use underscore in name, and remove when exporting to avoid clasing with builtin names
(const._notUndef):
(const._isUndef):
(const._eq):
(const._ge):
(const._throws):
* wasm/js-api/test_basic_api.js: test the WebAssembly.Module API
(const.c.in.constructorProperties.switch):

Source/JavaScriptCore:

* runtime/ExceptionHelpers.cpp:
(JSC::defaultSourceAppender): make this public so that WebAssembly can use it: it generates those fancy (evaluating '...') messages at the end
* runtime/ExceptionHelpers.h:
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init): remove the useless Structure from the WebAssembly objects (it's already in this file, no need to hold two references and visit them twice)
* testWasm.cpp:
(runWasmTests): update API
* wasm/WasmB3IRGenerator.cpp:
(JSC::Wasm::parseAndCompile): use updated API
* wasm/WasmB3IRGenerator.h:
* wasm/WasmFunctionParser.h:
(JSC::Wasm::FunctionParser<Context>::FunctionParser): use updated API
(JSC::Wasm::FunctionParser<Context>::parseExpression): use updated API
* wasm/WasmModuleParser.cpp:
(JSC::Wasm::ModuleParser::parse): generate error messages
* wasm/WasmModuleParser.h:
(JSC::Wasm::ModuleParser::ModuleParser):
(JSC::Wasm::ModuleParser::failed):
(JSC::Wasm::ModuleParser::errorMessage):
(JSC::Wasm::ModuleParser::functionInformation):
(JSC::Wasm::ModuleParser::memory):
* wasm/WasmParser.h: use update non-public API
(JSC::Wasm::Parser::parseVarUInt32):
(JSC::Wasm::Parser::parseVarUInt64):
(JSC::Wasm::Parser::source):
(JSC::Wasm::Parser::length):
(JSC::Wasm::Parser::Parser):
(JSC::Wasm::Parser::consumeCharacter):
(JSC::Wasm::Parser::consumeString):
(JSC::Wasm::Parser::parseUInt32):
(JSC::Wasm::Parser::parseUInt7):
* wasm/WasmPlan.cpp:
(JSC::Wasm::Plan::Plan):
(JSC::Wasm::Plan::~Plan):
* wasm/WasmPlan.h:
(JSC::Wasm::Plan::failed):
(JSC::Wasm::Plan::errorMessage):
(JSC::Wasm::Plan::resultSize):
(JSC::Wasm::Plan::result):
(JSC::Wasm::Plan::memory):
* wasm/js/JSWebAssemblyCompileError.cpp:
(JSC::createWebAssemblyCompileError): makes it easier to throw a WebAssembly.CompileError from Module
* wasm/js/JSWebAssemblyCompileError.h:
* wasm/js/WebAssemblyCompileErrorConstructor.cpp:
(JSC::WebAssemblyCompileErrorConstructor::create):
(JSC::WebAssemblyCompileErrorConstructor::finishCreation):
* wasm/js/WebAssemblyCompileErrorConstructor.h:
* wasm/js/WebAssemblyInstanceConstructor.cpp:
(JSC::WebAssemblyInstanceConstructor::create):
(JSC::WebAssemblyInstanceConstructor::finishCreation):
(JSC::WebAssemblyInstanceConstructor::visitChildren):
* wasm/js/WebAssemblyInstanceConstructor.h:
* wasm/js/WebAssemblyMemoryConstructor.cpp:
(JSC::WebAssemblyMemoryConstructor::create):
(JSC::WebAssemblyMemoryConstructor::finishCreation):
(JSC::WebAssemblyMemoryConstructor::visitChildren):
* wasm/js/WebAssemblyMemoryConstructor.h:
* wasm/js/WebAssemblyModuleConstructor.cpp:
(JSC::constructJSWebAssemblyModule):
(JSC::WebAssemblyModuleConstructor::create):
(JSC::WebAssemblyModuleConstructor::finishCreation):
(JSC::WebAssemblyModuleConstructor::visitChildren):
* wasm/js/WebAssemblyModuleConstructor.h:
* wasm/js/WebAssemblyRuntimeErrorConstructor.cpp:
(JSC::WebAssemblyRuntimeErrorConstructor::create):
(JSC::WebAssemblyRuntimeErrorConstructor::finishCreation):
* wasm/js/WebAssemblyRuntimeErrorConstructor.h:
* wasm/js/WebAssemblyTableConstructor.cpp:
(JSC::WebAssemblyTableConstructor::create):
(JSC::WebAssemblyTableConstructor::finishCreation):
(JSC::WebAssemblyTableConstructor::visitChildren):
* wasm/js/WebAssemblyTableConstructor.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207825 268f45cc-cd09-0410-ab3c-d52691b4dbfc

30 files changed:
JSTests/ChangeLog
JSTests/wasm/assert.js
JSTests/wasm/js-api/test_basic_api.js
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/runtime/ExceptionHelpers.cpp
Source/JavaScriptCore/runtime/ExceptionHelpers.h
Source/JavaScriptCore/runtime/JSGlobalObject.cpp
Source/JavaScriptCore/testWasm.cpp
Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp
Source/JavaScriptCore/wasm/WasmB3IRGenerator.h
Source/JavaScriptCore/wasm/WasmFunctionParser.h
Source/JavaScriptCore/wasm/WasmModuleParser.cpp
Source/JavaScriptCore/wasm/WasmModuleParser.h
Source/JavaScriptCore/wasm/WasmParser.h
Source/JavaScriptCore/wasm/WasmPlan.cpp
Source/JavaScriptCore/wasm/WasmPlan.h
Source/JavaScriptCore/wasm/js/JSWebAssemblyCompileError.cpp
Source/JavaScriptCore/wasm/js/JSWebAssemblyCompileError.h
Source/JavaScriptCore/wasm/js/WebAssemblyCompileErrorConstructor.cpp
Source/JavaScriptCore/wasm/js/WebAssemblyCompileErrorConstructor.h
Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp
Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.h
Source/JavaScriptCore/wasm/js/WebAssemblyMemoryConstructor.cpp
Source/JavaScriptCore/wasm/js/WebAssemblyMemoryConstructor.h
Source/JavaScriptCore/wasm/js/WebAssemblyModuleConstructor.cpp
Source/JavaScriptCore/wasm/js/WebAssemblyModuleConstructor.h
Source/JavaScriptCore/wasm/js/WebAssemblyRuntimeErrorConstructor.cpp
Source/JavaScriptCore/wasm/js/WebAssemblyRuntimeErrorConstructor.h
Source/JavaScriptCore/wasm/js/WebAssemblyTableConstructor.cpp
Source/JavaScriptCore/wasm/js/WebAssemblyTableConstructor.h

index f096be1..8d52629 100644 (file)
@@ -1,3 +1,50 @@
+2016-10-25  JF Bastien  <jfbastien@apple.com>
+
+        WebAssembly JS API: implement Module
+
+        This implementation allows us to:
+         - Syncrhonously create a WebAssembly.Module with a typed array.
+         - Creates a compilation plan.
+         - Parse the Module and creates corresponding code.
+         - Throw WebAssembly.CompileError with mildly helpful [*] error messages on
+           failure.
+
+        Consult the API documentation for expected behavior: https://github.com/WebAssembly/design/blob/master/JS.md#webassemblymodule-constructor
+
+        For now the implementation discards the generated code.
+
+        The next steps will be:
+         - Expose a Module's exports.
+         - Implement WebAssembly.Instance, which allows instantiating and running a
+           compiled Module.
+         - Beef up the testing infrastructure under JSTests/wasm so that more complex
+           modules can be created and tested (instead of writing the bits by hand).
+
+        This patch also:
+         - Adds assert.instanceof in assert.js.
+         - Refactors Wasm::Parser and friends to accept const uint8_t* as well as a
+           Vector, to avoid copying when invoked synchronously.
+         - Remove useless Structure from some of the wasm constructors: they're already
+           on the JSGlobalObject, visited properly and all.
+         - Fix off-by-one error in parsing: Parser::parseUInt32 failed if the integer
+           was exactly at end of file.
+
+         [*] On error messages while parsing: I filed https://bugs.webkit.org/show_bug.cgi?id=163919
+
+        WebAssembly JS API: implement Module
+        https://bugs.webkit.org/show_bug.cgi?id=163903
+
+        Reviewed by Keith Miller.
+
+        * wasm/assert.js: use underscore in name, and remove when exporting to avoid clasing with builtin names
+        (const._notUndef):
+        (const._isUndef):
+        (const._eq):
+        (const._ge):
+        (const._throws):
+        * wasm/js-api/test_basic_api.js: test the WebAssembly.Module API
+        (const.c.in.constructorProperties.switch):
+
 2016-10-25  Keith Miller  <keith_miller@apple.com>
 
         Add trivial Wasm conversion opcodes
index 5c71cc4..2ea5f70 100644 (file)
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-export const notUndef = (v) => {
+const _notUndef = (v) => {
     if (typeof v === "undefined")
         throw new Error("Shouldn't be undefined");
 };
 
-export const isUndef = (v) => {
+const _isUndef = (v) => {
     if (typeof v !== "undefined")
         throw new Error("Should be undefined");
 };
 
-export const eq = (lhs, rhs) => {
+const _eq = (lhs, rhs) => {
     if (lhs !== rhs)
         throw new Error(`Not the same: "${lhs}" and "${rhs}"`);
 };
 
-export const ge = (lhs, rhs) => {
-    notUndef(lhs);
-    notUndef(rhs);
+const _ge = (lhs, rhs) => {
+    _notUndef(lhs);
+    _notUndef(rhs);
     if (!(lhs >= rhs))
         throw new Error(`Expected: "${lhs}" < "${rhs}"`);
 };
 
-export const throws = (func, type, message, ...args) => {
+const _throws = (func, type, message, ...args) => {
     try {
         func(...args);
     } catch (e) {
@@ -55,3 +55,15 @@ export const throws = (func, type, message, ...args) => {
     }
     throw new Error(`Expected to throw a ${type.name} with message "${message}"`);
 };
+
+const _instanceof = (obj, type) => obj instanceof type;
+
+// Use underscore names to avoid clashing with builtin names.
+export {
+    _notUndef as notUndef,
+    _isUndef as isUndef,
+    _eq as eq,
+    _ge as ge,
+    _throws as throws,
+    _instanceof as instanceof,
+};
index c4e1927..4ee8853 100644 (file)
@@ -1,6 +1,9 @@
 import * as assert from '../assert.js';
 import * as utilities from '../utilities.js';
 
+const version = 0xC;
+const emptyModule = Uint8Array.of(0x0, 0x61, 0x73, 0x6d, version, 0x00, 0x00, 0x00);
+
 const checkOwnPropertyDescriptor = (obj, prop, expect) => {
     const descriptor = Object.getOwnPropertyDescriptor(obj, prop);
     assert.eq(typeof descriptor.value, expect.typeofvalue);
@@ -14,12 +17,12 @@ const functionProperties = {
     "compile":  { length: 1 },
 };
 const constructorProperties = {
-    "Module":       { typeofvalue: "function", writable: true, configurable: true, enumerable: false, length: 1, isError: false },
-    "Instance":     { typeofvalue: "function", writable: true, configurable: true, enumerable: false, length: 1, isError: false },
-    "Memory":       { typeofvalue: "function", writable: true, configurable: true, enumerable: false, length: 1, isError: false },
-    "Table":        { typeofvalue: "function", writable: true, configurable: true, enumerable: false, length: 1, isError: false },
-    "CompileError": { typeofvalue: "function", writable: true, configurable: true, enumerable: false, length: 1, isError: true  },
-    "RuntimeError": { typeofvalue: "function", writable: true, configurable: true, enumerable: false, length: 1, isError: true  },
+    "Module":       { typeofvalue: "function", writable: true, configurable: true, enumerable: false, length: 1 },
+    "Instance":     { typeofvalue: "function", writable: true, configurable: true, enumerable: false, length: 1 },
+    "Memory":       { typeofvalue: "function", writable: true, configurable: true, enumerable: false, length: 1 },
+    "Table":        { typeofvalue: "function", writable: true, configurable: true, enumerable: false, length: 1 },
+    "CompileError": { typeofvalue: "function", writable: true, configurable: true, enumerable: false, length: 1 },
+    "RuntimeError": { typeofvalue: "function", writable: true, configurable: true, enumerable: false, length: 1 },
 };
 
 
@@ -44,7 +47,30 @@ for (const c in constructorProperties) {
     checkOwnPropertyDescriptor(WebAssembly, c, constructorProperties[c]);
     checkOwnPropertyDescriptor(WebAssembly[c], "prototype", { typeofvalue: "object", writable: false, configurable: false, enumerable: false });
     assert.throws(() => WebAssembly[c](), TypeError, `calling WebAssembly.${c} constructor without new is invalid`);
-    if (constructorProperties[c].isError) {
+    switch (c) {
+    case "Module":
+        for (const invalid of [undefined, "", 1, {}, []])
+            assert.throws(() => new WebAssembly[c](invalid), TypeError, `first argument to WebAssembly.Module must be an ArrayBufferView or an ArrayBuffer (evaluating 'new WebAssembly[c](invalid)')`);
+        for (const buffer of [new ArrayBuffer(), new DataView(new ArrayBuffer()), new Int8Array(), new Uint8Array(), new Uint8ClampedArray(), new Int16Array(), new Uint16Array(), new Int32Array(), new Uint32Array(), new Float32Array(), new Float64Array()])
+            // FIXME the following should be WebAssembly.CompileError. https://bugs.webkit.org/show_bug.cgi?id=163768
+            assert.throws(() => new WebAssembly[c](buffer), Error, `Module is 0 bytes, expected at least 8 bytes (evaluating 'new WebAssembly[c](buffer)')`);
+        assert.instanceof(new WebAssembly[c](emptyModule), WebAssembly.Module);
+        // FIXME test neutered TypedArray and TypedArrayView. https://bugs.webkit.org/show_bug.cgi?id=163899
+        break;
+    case "Instance":
+        // FIXME Implement and test these APIs further. For now they just throw. https://bugs.webkit.org/show_bug.cgi?id=159775
+        assert.throws(() => new WebAssembly[c](), Error, `WebAssembly doesn't yet implement the ${c} constructor property`);
+        break;
+    case "Memory":
+        // FIXME Implement and test these APIs further. For now they just throw. https://bugs.webkit.org/show_bug.cgi?id=159775
+        assert.throws(() => new WebAssembly[c](), Error, `WebAssembly doesn't yet implement the ${c} constructor property`);
+        break;
+    case "Table":
+        // FIXME Implement and test these APIs further. For now they just throw. https://bugs.webkit.org/show_bug.cgi?id=159775
+        assert.throws(() => new WebAssembly[c](), Error, `WebAssembly doesn't yet implement the ${c} constructor property`);
+        break;
+    case "CompileError":
+    case "RuntimeError": {
         const e = new WebAssembly[c];
         assert.eq(e instanceof WebAssembly[c], true);
         assert.eq(e instanceof Error, true);
@@ -54,16 +80,12 @@ for (const c in constructorProperties) {
         const sillyString = "uh-oh!";
         const e2 = new WebAssembly[c](sillyString);
         assert.eq(e2.message, sillyString);
+    } break;
+    default: throw new Error(`Implementation error: unexpected constructor property "${c}"`);
     }
 }
 
 // FIXME Implement and test these APIs further. For now they just throw. https://bugs.webkit.org/show_bug.cgi?id=159775
-
 for (const f in functionProperties) {
     assert.throws(() => WebAssembly[f](), Error, `WebAssembly doesn't yet implement the ${f} function property`);
 }
-
-for (const c in constructorProperties) {
-    if (!constructorProperties[c].isError)
-        assert.throws(() => new WebAssembly[c](), Error, `WebAssembly doesn't yet implement the ${c} constructor property`);
-}
index 9ae82f2..a851c61 100644 (file)
@@ -1,3 +1,114 @@
+2016-10-25  JF Bastien  <jfbastien@apple.com>
+
+        WebAssembly JS API: implement Module
+
+        This implementation allows us to:
+         - Syncrhonously create a WebAssembly.Module with a typed array.
+         - Creates a compilation plan.
+         - Parse the Module and creates corresponding code.
+         - Throw WebAssembly.CompileError with mildly helpful [*] error messages on
+           failure.
+
+        Consult the API documentation for expected behavior: https://github.com/WebAssembly/design/blob/master/JS.md#webassemblymodule-constructor
+
+        For now the implementation discards the generated code.
+
+        The next steps will be:
+         - Expose a Module's exports.
+         - Implement WebAssembly.Instance, which allows instantiating and running a
+           compiled Module.
+         - Beef up the testing infrastructure under JSTests/wasm so that more complex
+           modules can be created and tested (instead of writing the bits by hand).
+
+        This patch also:
+         - Adds assert.instanceof in assert.js.
+         - Refactors Wasm::Parser and friends to accept const uint8_t* as well as a
+           Vector, to avoid copying when invoked synchronously.
+         - Remove useless Structure from some of the wasm constructors: they're already
+           on the JSGlobalObject, visited properly and all.
+         - Fix off-by-one error in parsing: Parser::parseUInt32 failed if the integer
+           was exactly at end of file.
+
+         [*] On error messages while parsing: I filed https://bugs.webkit.org/show_bug.cgi?id=163919
+
+        WebAssembly JS API: implement Module
+        https://bugs.webkit.org/show_bug.cgi?id=163903
+
+        Reviewed by Keith Miller.
+
+        * runtime/ExceptionHelpers.cpp:
+        (JSC::defaultSourceAppender): make this public so that WebAssembly can use it: it generates those fancy (evaluating '...') messages at the end
+        * runtime/ExceptionHelpers.h:
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::init): remove the useless Structure from the WebAssembly objects (it's already in this file, no need to hold two references and visit them twice)
+        * testWasm.cpp:
+        (runWasmTests): update API
+        * wasm/WasmB3IRGenerator.cpp:
+        (JSC::Wasm::parseAndCompile): use updated API
+        * wasm/WasmB3IRGenerator.h:
+        * wasm/WasmFunctionParser.h:
+        (JSC::Wasm::FunctionParser<Context>::FunctionParser): use updated API
+        (JSC::Wasm::FunctionParser<Context>::parseExpression): use updated API
+        * wasm/WasmModuleParser.cpp:
+        (JSC::Wasm::ModuleParser::parse): generate error messages
+        * wasm/WasmModuleParser.h:
+        (JSC::Wasm::ModuleParser::ModuleParser):
+        (JSC::Wasm::ModuleParser::failed):
+        (JSC::Wasm::ModuleParser::errorMessage):
+        (JSC::Wasm::ModuleParser::functionInformation):
+        (JSC::Wasm::ModuleParser::memory):
+        * wasm/WasmParser.h: use update non-public API
+        (JSC::Wasm::Parser::parseVarUInt32):
+        (JSC::Wasm::Parser::parseVarUInt64):
+        (JSC::Wasm::Parser::source):
+        (JSC::Wasm::Parser::length):
+        (JSC::Wasm::Parser::Parser):
+        (JSC::Wasm::Parser::consumeCharacter):
+        (JSC::Wasm::Parser::consumeString):
+        (JSC::Wasm::Parser::parseUInt32):
+        (JSC::Wasm::Parser::parseUInt7):
+        * wasm/WasmPlan.cpp:
+        (JSC::Wasm::Plan::Plan):
+        (JSC::Wasm::Plan::~Plan):
+        * wasm/WasmPlan.h:
+        (JSC::Wasm::Plan::failed):
+        (JSC::Wasm::Plan::errorMessage):
+        (JSC::Wasm::Plan::resultSize):
+        (JSC::Wasm::Plan::result):
+        (JSC::Wasm::Plan::memory):
+        * wasm/js/JSWebAssemblyCompileError.cpp:
+        (JSC::createWebAssemblyCompileError): makes it easier to throw a WebAssembly.CompileError from Module
+        * wasm/js/JSWebAssemblyCompileError.h:
+        * wasm/js/WebAssemblyCompileErrorConstructor.cpp:
+        (JSC::WebAssemblyCompileErrorConstructor::create):
+        (JSC::WebAssemblyCompileErrorConstructor::finishCreation):
+        * wasm/js/WebAssemblyCompileErrorConstructor.h:
+        * wasm/js/WebAssemblyInstanceConstructor.cpp:
+        (JSC::WebAssemblyInstanceConstructor::create):
+        (JSC::WebAssemblyInstanceConstructor::finishCreation):
+        (JSC::WebAssemblyInstanceConstructor::visitChildren):
+        * wasm/js/WebAssemblyInstanceConstructor.h:
+        * wasm/js/WebAssemblyMemoryConstructor.cpp:
+        (JSC::WebAssemblyMemoryConstructor::create):
+        (JSC::WebAssemblyMemoryConstructor::finishCreation):
+        (JSC::WebAssemblyMemoryConstructor::visitChildren):
+        * wasm/js/WebAssemblyMemoryConstructor.h:
+        * wasm/js/WebAssemblyModuleConstructor.cpp:
+        (JSC::constructJSWebAssemblyModule):
+        (JSC::WebAssemblyModuleConstructor::create):
+        (JSC::WebAssemblyModuleConstructor::finishCreation):
+        (JSC::WebAssemblyModuleConstructor::visitChildren):
+        * wasm/js/WebAssemblyModuleConstructor.h:
+        * wasm/js/WebAssemblyRuntimeErrorConstructor.cpp:
+        (JSC::WebAssemblyRuntimeErrorConstructor::create):
+        (JSC::WebAssemblyRuntimeErrorConstructor::finishCreation):
+        * wasm/js/WebAssemblyRuntimeErrorConstructor.h:
+        * wasm/js/WebAssemblyTableConstructor.cpp:
+        (JSC::WebAssemblyTableConstructor::create):
+        (JSC::WebAssemblyTableConstructor::finishCreation):
+        (JSC::WebAssemblyTableConstructor::visitChildren):
+        * wasm/js/WebAssemblyTableConstructor.h:
+
 2016-10-25  Keith Miller  <keith_miller@apple.com>
 
         Add trivial Wasm conversion opcodes
index 905091a..ef1b204 100644 (file)
@@ -101,7 +101,7 @@ static String defaultApproximateSourceError(const String& originalMessage, const
     return makeString(originalMessage, " (near '...", sourceText, "...')");
 }
 
-static String defaultSourceAppender(const String& originalMessage, const String& sourceText, RuntimeType, ErrorInstance::SourceTextWhereErrorOccurred occurrence)
+String defaultSourceAppender(const String& originalMessage, const String& sourceText, RuntimeType, ErrorInstance::SourceTextWhereErrorOccurred occurrence)
 {
     if (occurrence == ErrorInstance::FoundApproximateSource)
         return defaultApproximateSourceError(originalMessage, sourceText);
index d8f3912..ec05294 100644 (file)
@@ -37,6 +37,8 @@ namespace JSC {
 
 typedef JSObject* (*ErrorFactory)(ExecState*, const String&, ErrorInstance::SourceAppender);
 
+String defaultSourceAppender(const String&, const String&, RuntimeType, ErrorInstance::SourceTextWhereErrorOccurred);
+
 JSObject* createTerminatedExecutionException(VM*);
 JS_EXPORT_PRIVATE bool isTerminatedExecutionException(Exception*);
 JS_EXPORT_PRIVATE JSObject* createError(ExecState*, JSValue, const String&, ErrorInstance::SourceAppender);
index f48cbcf..384082d 100644 (file)
@@ -832,7 +832,7 @@ putDirectWithoutTransition(vm, vm.propertyNames-> jsName, lowerName ## Construct
         auto* base = m_ ## prototypeBase ## Prototype.get(); \
         auto* prototype = Prototype::create(vm, this, Prototype::createStructure(vm, this, base)); \
         auto* structure = JSObj::createStructure(vm, this, prototype); \
-        auto* constructor = Constructor::create(vm, Constructor::createStructure(vm, this, this->functionPrototype()), prototype, structure); \
+        auto* constructor = Constructor::create(vm, Constructor::createStructure(vm, this, this->functionPrototype()), prototype); \
         prototype->putDirectWithoutTransition(vm, vm.propertyNames->constructor, constructor, DontEnum); \
         m_ ## lowerName ## Prototype.set(vm, this, prototype); \
         m_ ## properName ## Structure.set(vm, this, structure); \
index a91be33..34aea85 100644 (file)
@@ -290,16 +290,16 @@ static void runWasmTests()
         };
 
         Plan plan(*vm, vector);
-        if (plan.result.size() != 2 || !plan.result[0] || !plan.result[1]) {
+        if (plan.failed() || plan.resultSize() != 2 || !plan.result(0) || !plan.result(1)) {
             dataLogLn("Module failed to compile correctly.");
             CRASH();
         }
 
         // Test this doesn't crash.
-        CHECK(isIdentical(invoke<float>(*plan.result[1]->jsEntryPoint, { boxf(0.0), boxf(1.5) }), -1.5f));
-        CHECK(isIdentical(invoke<float>(*plan.result[1]->jsEntryPoint, { boxf(100.1234), boxf(12.5) }), 87.6234f));
-        CHECK(isIdentical(invoke<float>(*plan.result[0]->jsEntryPoint, { boxf(0.0), boxf(1.5) }), -1.5f));
-        CHECK(isIdentical(invoke<float>(*plan.result[0]->jsEntryPoint, { boxf(100.1234), boxf(12.5) }), 87.6234f));
+        CHECK(isIdentical(invoke<float>(*plan.result(1)->jsEntryPoint, { boxf(0.0), boxf(1.5) }), -1.5f));
+        CHECK(isIdentical(invoke<float>(*plan.result(1)->jsEntryPoint, { boxf(100.1234), boxf(12.5) }), 87.6234f));
+        CHECK(isIdentical(invoke<float>(*plan.result(0)->jsEntryPoint, { boxf(0.0), boxf(1.5) }), -1.5f));
+        CHECK(isIdentical(invoke<float>(*plan.result(0)->jsEntryPoint, { boxf(100.1234), boxf(12.5) }), 87.6234f));
     }
 
     {
@@ -319,16 +319,16 @@ static void runWasmTests()
         };
 
         Plan plan(*vm, vector);
-        if (plan.result.size() != 2 || !plan.result[0] || !plan.result[1]) {
+        if (plan.failed() || plan.resultSize() != 2 || !plan.result(0) || !plan.result(1)) {
             dataLogLn("Module failed to compile correctly.");
             CRASH();
         }
 
         // Test this doesn't crash.
-        CHECK(isIdentical(invoke<float>(*plan.result[1]->jsEntryPoint, { boxf(0.0), boxf(1.5) }), 1.5f));
-        CHECK(isIdentical(invoke<float>(*plan.result[1]->jsEntryPoint, { boxf(100.1234), boxf(12.5) }), 112.6234f));
-        CHECK(isIdentical(invoke<float>(*plan.result[0]->jsEntryPoint, { boxf(0.0), boxf(1.5) }), 1.5f));
-        CHECK(isIdentical(invoke<float>(*plan.result[0]->jsEntryPoint, { boxf(100.1234), boxf(12.5) }), 112.6234f));
+        CHECK(isIdentical(invoke<float>(*plan.result(1)->jsEntryPoint, { boxf(0.0), boxf(1.5) }), 1.5f));
+        CHECK(isIdentical(invoke<float>(*plan.result(1)->jsEntryPoint, { boxf(100.1234), boxf(12.5) }), 112.6234f));
+        CHECK(isIdentical(invoke<float>(*plan.result(0)->jsEntryPoint, { boxf(0.0), boxf(1.5) }), 1.5f));
+        CHECK(isIdentical(invoke<float>(*plan.result(0)->jsEntryPoint, { boxf(100.1234), boxf(12.5) }), 112.6234f));
     }
 
     {
@@ -353,17 +353,17 @@ static void runWasmTests()
         };
 
         Plan plan(*vm, vector);
-        if (plan.result.size() != 2 || !plan.result[0] || !plan.result[1]) {
+        if (plan.failed() || plan.resultSize() != 2 || !plan.result(0) || !plan.result(1)) {
             dataLogLn("Module failed to compile correctly.");
             CRASH();
         }
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.result[1]->jsEntryPoint, { box(0) }), 0);
-        CHECK_EQ(invoke<int>(*plan.result[1]->jsEntryPoint, { box(100) }), 1200);
-        CHECK_EQ(invoke<int>(*plan.result[1]->jsEntryPoint, { box(1) }), 12);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1), box(2), box(3), box(4), box(5), box(6), box(7), box(8), box(9), box(10), box(11), box(12) }), 78);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1), box(2), box(3), box(4), box(5), box(6), box(7), box(8), box(9), box(10), box(11), box(100) }), 166);
+        CHECK_EQ(invoke<int>(*plan.result(1)->jsEntryPoint, { box(0) }), 0);
+        CHECK_EQ(invoke<int>(*plan.result(1)->jsEntryPoint, { box(100) }), 1200);
+        CHECK_EQ(invoke<int>(*plan.result(1)->jsEntryPoint, { box(1) }), 12);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1), box(2), box(3), box(4), box(5), box(6), box(7), box(8), box(9), box(10), box(11), box(12) }), 78);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1), box(2), box(3), box(4), box(5), box(6), box(7), box(8), box(9), box(10), box(11), box(100) }), 166);
     }
 
     {
@@ -387,16 +387,16 @@ static void runWasmTests()
         };
 
         Plan plan(*vm, vector);
-        if (plan.result.size() != 1 || !plan.result[0]) {
+        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
             dataLogLn("Module failed to compile correctly.");
             CRASH();
         }
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(0) }), 1);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1) }), 1);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(2) }), 2);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(4) }), 24);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(0) }), 1);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1) }), 1);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(2) }), 2);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(4) }), 24);
     }
 
     {
@@ -416,18 +416,18 @@ static void runWasmTests()
         };
 
         Plan plan(*vm, vector);
-        if (plan.result.size() != 2 || !plan.result[0] || !plan.result[1]) {
+        if (plan.resultSize() != 2 || !plan.result(0) || !plan.result(1)) {
             dataLogLn("Module failed to compile correctly.");
             CRASH();
         }
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.result[1]->jsEntryPoint, { box(0), box(0) }), 0);
-        CHECK_EQ(invoke<int>(*plan.result[1]->jsEntryPoint, { box(100), box(0) }), 100);
-        CHECK_EQ(invoke<int>(*plan.result[1]->jsEntryPoint, { box(1), box(15) }), 16);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(0) }), 0);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(100) }), 200);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1) }), 2);
+        CHECK_EQ(invoke<int>(*plan.result(1)->jsEntryPoint, { box(0), box(0) }), 0);
+        CHECK_EQ(invoke<int>(*plan.result(1)->jsEntryPoint, { box(100), box(0) }), 100);
+        CHECK_EQ(invoke<int>(*plan.result(1)->jsEntryPoint, { box(1), box(15) }), 16);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(0) }), 0);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(100) }), 200);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1) }), 2);
     }
 
     {
@@ -447,18 +447,18 @@ static void runWasmTests()
         };
 
         Plan plan(*vm, vector);
-        if (plan.result.size() != 2 || !plan.result[0] || !plan.result[1]) {
+        if (plan.failed() || plan.resultSize() != 2 || !plan.result(0) || !plan.result(1)) {
             dataLogLn("Module failed to compile correctly.");
             CRASH();
         }
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.result[1]->jsEntryPoint, { box(0) }), 0);
-        CHECK_EQ(invoke<int>(*plan.result[1]->jsEntryPoint, { box(100) }), 100);
-        CHECK_EQ(invoke<int>(*plan.result[1]->jsEntryPoint, { box(1) }), 1);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(0) }), 0);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(100) }), 100);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1) }), 1);
+        CHECK_EQ(invoke<int>(*plan.result(1)->jsEntryPoint, { box(0) }), 0);
+        CHECK_EQ(invoke<int>(*plan.result(1)->jsEntryPoint, { box(100) }), 100);
+        CHECK_EQ(invoke<int>(*plan.result(1)->jsEntryPoint, { box(1) }), 1);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(0) }), 0);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(100) }), 100);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1) }), 1);
     }
 
     {
@@ -480,15 +480,15 @@ static void runWasmTests()
         };
 
         Plan plan(*vm, vector);
-        if (plan.result.size() != 1 || !plan.result[0]) {
+        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
             dataLogLn("Module failed to compile correctly.");
             CRASH();
         }
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(0), box(10) }), 0);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(100), box(2) }), 100);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1), box(100) }), 1);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(0), box(10) }), 0);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(100), box(2) }), 100);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1), box(100) }), 1);
     }
 
     {
@@ -510,15 +510,15 @@ static void runWasmTests()
         };
 
         Plan plan(*vm, vector);
-        if (plan.result.size() != 1 || !plan.result[0]) {
+        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
             dataLogLn("Module failed to compile correctly.");
             CRASH();
         }
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(0), box(10) }), 0);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(100), box(2) }), 100);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1), box(100) }), 1);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(0), box(10) }), 0);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(100), box(2) }), 100);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1), box(100) }), 1);
     }
 
     {
@@ -550,17 +550,17 @@ static void runWasmTests()
         };
 
         Plan plan(*vm, vector);
-        if (plan.result.size() != 1 || !plan.result[0]) {
+        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
             dataLogLn("Module failed to compile correctly.");
             CRASH();
         }
-        ASSERT(plan.memory->size());
+        ASSERT(plan.memory()->size());
 
         // Test this doesn't crash.
         unsigned length = 5;
         unsigned offset = sizeof(uint32_t);
-        uint32_t* memory = static_cast<uint32_t*>(plan.memory->memory());
-        invoke<void>(*plan.result[0]->jsEntryPoint, { box(100), box(offset), box(length) });
+        uint32_t* memory = static_cast<uint32_t*>(plan.memory()->memory());
+        invoke<void>(*plan.result(0)->jsEntryPoint, { box(100), box(offset), box(length) });
         offset /= sizeof(uint32_t);
         CHECK_EQ(memory[offset - 1], 0u);
         CHECK_EQ(memory[offset + length], 0u);
@@ -569,7 +569,7 @@ static void runWasmTests()
 
         length = 10;
         offset = 5 * sizeof(uint32_t);
-        invoke<void>(*plan.result[0]->jsEntryPoint, { box(5), box(offset), box(length) });
+        invoke<void>(*plan.result(0)->jsEntryPoint, { box(5), box(offset), box(length) });
         offset /= sizeof(uint32_t);
         CHECK_EQ(memory[offset - 1], 100u);
         CHECK_EQ(memory[offset + length], 0u);
@@ -605,17 +605,17 @@ static void runWasmTests()
         };
 
         Plan plan(*vm, vector);
-        if (plan.result.size() != 1 || !plan.result[0]) {
+        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
             dataLogLn("Module failed to compile correctly.");
             CRASH();
         }
-        ASSERT(plan.memory->size());
+        ASSERT(plan.memory()->size());
 
         // Test this doesn't crash.
         unsigned length = 5;
         unsigned offset = 1;
-        uint8_t* memory = static_cast<uint8_t*>(plan.memory->memory());
-        invoke<void>(*plan.result[0]->jsEntryPoint, { box(100), box(offset), box(length) });
+        uint8_t* memory = static_cast<uint8_t*>(plan.memory()->memory());
+        invoke<void>(*plan.result(0)->jsEntryPoint, { box(100), box(offset), box(length) });
         CHECK_EQ(memory[offset - 1], 0u);
         CHECK_EQ(memory[offset + length], 0u);
         for (unsigned i = 0; i < length; ++i)
@@ -623,7 +623,7 @@ static void runWasmTests()
 
         length = 10;
         offset = 5;
-        invoke<void>(*plan.result[0]->jsEntryPoint, { box(5), box(offset), box(length) });
+        invoke<void>(*plan.result(0)->jsEntryPoint, { box(5), box(offset), box(length) });
         CHECK_EQ(memory[offset - 1], 100u);
         CHECK_EQ(memory[offset + length], 0u);
         for (unsigned i = 0; i < length; ++i)
@@ -649,16 +649,16 @@ static void runWasmTests()
         };
 
         Plan plan(*vm, vector);
-        if (plan.result.size() != 1 || !plan.result[0]) {
+        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
             dataLogLn("Module failed to compile correctly.");
             CRASH();
         }
-        ASSERT(plan.memory->size());
+        ASSERT(plan.memory()->size());
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(0), box(10) }), 0);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(100), box(2) }), 100);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1), box(100) }), 1);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(0), box(10) }), 0);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(100), box(2) }), 100);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1), box(100) }), 1);
     }
 
     {
@@ -680,15 +680,15 @@ static void runWasmTests()
         };
 
         Plan plan(*vm, vector);
-        if (plan.result.size() != 1 || !plan.result[0]) {
+        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
             dataLogLn("Module failed to compile correctly.");
             CRASH();
         }
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(0) }), 0);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(100) }), 100);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1) }), 1);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(0) }), 0);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(100) }), 100);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1) }), 1);
     }
 
     {
@@ -710,16 +710,16 @@ static void runWasmTests()
         };
 
         Plan plan(*vm, vector);
-        if (plan.result.size() != 1 || !plan.result[0]) {
+        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
             dataLogLn("Module failed to compile correctly.");
             CRASH();
         }
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(0), box(10) }), 0);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(100), box(2) }), 100);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1), box(100) }), 1);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(-12), box(plan.memory->size() - sizeof(uint64_t)) }), -12);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(0), box(10) }), 0);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(100), box(2) }), 100);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1), box(100) }), 1);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(-12), box(plan.memory()->size() - sizeof(uint64_t)) }), -12);
     }
 
     {
@@ -741,15 +741,15 @@ static void runWasmTests()
         };
 
         Plan plan(*vm, vector);
-        if (plan.result.size() != 1 || !plan.result[0]) {
+        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
             dataLogLn("Module failed to compile correctly.");
             CRASH();
         }
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(0), box(10) }), 0);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(100), box(2) }), 100);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1), box(100) }), 1);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(0), box(10) }), 0);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(100), box(2) }), 100);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1), box(100) }), 1);
     }
 
     {
@@ -781,17 +781,17 @@ static void runWasmTests()
         };
 
         Plan plan(*vm, vector);
-        if (plan.result.size() != 1 || !plan.result[0]) {
+        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
             dataLogLn("Module failed to compile correctly.");
             CRASH();
         }
-        ASSERT(plan.memory->size());
+        ASSERT(plan.memory()->size());
 
         // Test this doesn't crash.
         unsigned length = 5;
         unsigned offset = sizeof(uint32_t);
-        uint32_t* memory = static_cast<uint32_t*>(plan.memory->memory());
-        invoke<void>(*plan.result[0]->jsEntryPoint, { box(100), box(offset), box(length) });
+        uint32_t* memory = static_cast<uint32_t*>(plan.memory()->memory());
+        invoke<void>(*plan.result(0)->jsEntryPoint, { box(100), box(offset), box(length) });
         offset /= sizeof(uint32_t);
         CHECK_EQ(memory[offset - 1], 0u);
         CHECK_EQ(memory[offset + length], 0u);
@@ -800,7 +800,7 @@ static void runWasmTests()
 
         length = 10;
         offset = 5 * sizeof(uint32_t);
-        invoke<void>(*plan.result[0]->jsEntryPoint, { box(5), box(offset), box(length) });
+        invoke<void>(*plan.result(0)->jsEntryPoint, { box(5), box(offset), box(length) });
         offset /= sizeof(uint32_t);
         CHECK_EQ(memory[offset - 1], 100u);
         CHECK_EQ(memory[offset + length], 0u);
@@ -836,17 +836,17 @@ static void runWasmTests()
         };
 
         Plan plan(*vm, vector);
-        if (plan.result.size() != 1 || !plan.result[0]) {
+        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
             dataLogLn("Module failed to compile correctly.");
             CRASH();
         }
-        ASSERT(plan.memory->size());
+        ASSERT(plan.memory()->size());
 
         // Test this doesn't crash.
         unsigned length = 5;
         unsigned offset = 1;
-        uint8_t* memory = static_cast<uint8_t*>(plan.memory->memory());
-        invoke<void>(*plan.result[0]->jsEntryPoint, { box(100), box(offset), box(length) });
+        uint8_t* memory = static_cast<uint8_t*>(plan.memory()->memory());
+        invoke<void>(*plan.result(0)->jsEntryPoint, { box(100), box(offset), box(length) });
         CHECK_EQ(memory[offset - 1], 0u);
         CHECK_EQ(memory[offset + length], 0u);
         for (unsigned i = 0; i < length; ++i)
@@ -854,7 +854,7 @@ static void runWasmTests()
 
         length = 10;
         offset = 5;
-        invoke<void>(*plan.result[0]->jsEntryPoint, { box(5), box(offset), box(length) });
+        invoke<void>(*plan.result(0)->jsEntryPoint, { box(5), box(offset), box(length) });
         CHECK_EQ(memory[offset - 1], 100u);
         CHECK_EQ(memory[offset + length], 0u);
         for (unsigned i = 0; i < length; ++i)
@@ -880,16 +880,16 @@ static void runWasmTests()
         };
 
         Plan plan(*vm, vector);
-        if (plan.result.size() != 1 || !plan.result[0]) {
+        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
             dataLogLn("Module failed to compile correctly.");
             CRASH();
         }
-        ASSERT(plan.memory->size());
+        ASSERT(plan.memory()->size());
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(0), box(10) }), 0);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(100), box(2) }), 100);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1), box(100) }), 1);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(0), box(10) }), 0);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(100), box(2) }), 100);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1), box(100) }), 1);
     }
 
     {
@@ -911,15 +911,15 @@ static void runWasmTests()
         };
 
         Plan plan(*vm, vector);
-        if (plan.result.size() != 1 || !plan.result[0]) {
+        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
             dataLogLn("Module failed to compile correctly.");
             CRASH();
         }
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(0) }), 0);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(100) }), 100);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1) }), 1);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(0) }), 0);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(100) }), 100);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1) }), 1);
     }
 
     {
@@ -941,20 +941,20 @@ static void runWasmTests()
         };
 
         Plan plan(*vm, vector);
-        if (plan.result.size() != 1 || !plan.result[0]) {
+        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
             dataLogLn("Module failed to compile correctly.");
             CRASH();
         }
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(0), box(1) }), 1);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1), box(0) }), 1);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(2), box(1) }), 1);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1), box(2) }), 1);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(2), box(2) }), 0);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1), box(1) }), 0);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(2), box(6) }), 1);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(100), box(6) }), 1);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(0), box(1) }), 1);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1), box(0) }), 1);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(2), box(1) }), 1);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1), box(2) }), 1);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(2), box(2) }), 0);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1), box(1) }), 0);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(2), box(6) }), 1);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(100), box(6) }), 1);
     }
 
     {
@@ -982,20 +982,20 @@ static void runWasmTests()
         };
 
         Plan plan(*vm, vector);
-        if (plan.result.size() != 1 || !plan.result[0]) {
+        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
             dataLogLn("Module failed to compile correctly.");
             CRASH();
         }
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(0), box(1) }), 1);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1), box(0) }), 0);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(2), box(1) }), 0);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1), box(2) }), 1);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(2), box(2) }), 0);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1), box(1) }), 0);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(2), box(6) }), 1);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(100), box(6) }), 0);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(0), box(1) }), 1);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1), box(0) }), 0);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(2), box(1) }), 0);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1), box(2) }), 1);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(2), box(2) }), 0);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1), box(1) }), 0);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(2), box(6) }), 1);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(100), box(6) }), 0);
     }
 
 
@@ -1009,13 +1009,13 @@ static void runWasmTests()
         };
 
         Plan plan(*vm, vector);
-        if (plan.result.size() != 1 || !plan.result[0]) {
+        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
             dataLogLn("Module failed to compile correctly.");
             CRASH();
         }
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { }), 5);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { }), 5);
     }
 
 
@@ -1030,13 +1030,13 @@ static void runWasmTests()
         };
 
         Plan plan(*vm, vector);
-        if (plan.result.size() != 1 || !plan.result[0]) {
+        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
             dataLogLn("Module failed to compile correctly.");
             CRASH();
         }
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { }), 11);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { }), 11);
     }
 
     {
@@ -1050,13 +1050,13 @@ static void runWasmTests()
         };
 
         Plan plan(*vm, vector);
-        if (plan.result.size() != 1 || !plan.result[0]) {
+        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
             dataLogLn("Module failed to compile correctly.");
             CRASH();
         }
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { }), 11);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { }), 11);
     }
 
     {
@@ -1070,13 +1070,13 @@ static void runWasmTests()
         };
 
         Plan plan(*vm, vector);
-        if (plan.result.size() != 1 || !plan.result[0]) {
+        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
             dataLogLn("Module failed to compile correctly.");
             CRASH();
         }
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { }), 11);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { }), 11);
     }
 
     {
@@ -1089,16 +1089,16 @@ static void runWasmTests()
         };
 
         Plan plan(*vm, vector);
-        if (plan.result.size() != 1 || !plan.result[0]) {
+        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
             dataLogLn("Module failed to compile correctly.");
             CRASH();
         }
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(0), box(1) }), 1);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(100), box(1) }), 101);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(-1), box(1)}), 0);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(std::numeric_limits<int>::max()), box(1) }), std::numeric_limits<int>::min());
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(0), box(1) }), 1);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(100), box(1) }), 101);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(-1), box(1)}), 0);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(std::numeric_limits<int>::max()), box(1) }), std::numeric_limits<int>::min());
     }
 
     {
@@ -1118,14 +1118,14 @@ static void runWasmTests()
         };
 
         Plan plan(*vm, vector);
-        if (plan.result.size() != 1 || !plan.result[0]) {
+        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
             dataLogLn("Module failed to compile correctly.");
             CRASH();
         }
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(0) }), 0);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(10) }), 10);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(0) }), 0);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(10) }), 10);
     }
 
     {
@@ -1154,16 +1154,16 @@ static void runWasmTests()
         };
 
         Plan plan(*vm, vector);
-        if (plan.result.size() != 1 || !plan.result[0]) {
+        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
             dataLogLn("Module failed to compile correctly.");
             CRASH();
         }
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(0) }), 0);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1) }), 1);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(2)}), 3);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(100) }), 5050);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(0) }), 0);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1) }), 1);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(2)}), 3);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(100) }), 5050);
     }
 
     {
@@ -1198,20 +1198,20 @@ static void runWasmTests()
         };
 
         Plan plan(*vm, vector);
-        if (plan.result.size() != 1 || !plan.result[0]) {
+        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
             dataLogLn("Module failed to compile correctly.");
             CRASH();
         }
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(0), box(1) }), 0);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1), box(0) }), 0);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(2), box(1) }), 2);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1), box(2) }), 2);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(2), box(2) }), 4);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(2), box(6) }), 12);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(100), box(6) }), 600);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(100), box(100) }), 10000);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(0), box(1) }), 0);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1), box(0) }), 0);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(2), box(1) }), 2);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1), box(2) }), 2);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(2), box(2) }), 4);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(2), box(6) }), 12);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(100), box(6) }), 600);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(100), box(100) }), 10000);
     }
 
     {
@@ -1251,20 +1251,20 @@ static void runWasmTests()
         };
 
         Plan plan(*vm, vector);
-        if (plan.result.size() != 1 || !plan.result[0]) {
+        if (plan.failed() || plan.resultSize() != 1 || !plan.result(0)) {
             dataLogLn("Module failed to compile correctly.");
             CRASH();
         }
 
         // Test this doesn't crash.
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(0), box(1) }), 1);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1), box(0) }), 0);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(2), box(1) }), 0);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1), box(2) }), 1);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(2), box(2) }), 0);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(1), box(1) }), 0);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(2), box(6) }), 1);
-        CHECK_EQ(invoke<int>(*plan.result[0]->jsEntryPoint, { box(100), box(6) }), 0);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(0), box(1) }), 1);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1), box(0) }), 0);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(2), box(1) }), 0);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1), box(2) }), 1);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(2), box(2) }), 0);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1), box(1) }), 0);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(2), box(6) }), 1);
+        CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(100), box(6) }), 0);
     }
 
 }
index 8f66c42..b5ac7a4 100644 (file)
@@ -718,13 +718,13 @@ static std::unique_ptr<Compilation> createJSWrapper(VM& vm, const Signature* sig
     return std::make_unique<Compilation>(vm, proc);
 }
 
-std::unique_ptr<FunctionCompilation> parseAndCompile(VM& vm, Vector<uint8_t>& source, Memory* memory, FunctionInformation info, const Vector<FunctionInformation>& functions, unsigned optLevel)
+std::unique_ptr<FunctionCompilation> parseAndCompile(VM& vm, const uint8_t* functionStart, size_t functionLength, Memory* memory, const Signature* signature, const Vector<FunctionInformation>& functions, unsigned optLevel)
 {
     auto result = std::make_unique<FunctionCompilation>();
 
     Procedure procedure;
     B3IRGenerator context(memory, procedure, result->unlinkedCalls);
-    FunctionParser<B3IRGenerator> parser(context, source, info, functions);
+    FunctionParser<B3IRGenerator> parser(context, functionStart, functionLength, signature, functions);
     if (!parser.parse())
         RELEASE_ASSERT_NOT_REACHED();
 
@@ -736,7 +736,7 @@ std::unique_ptr<FunctionCompilation> parseAndCompile(VM& vm, Vector<uint8_t>& so
         dataLog("Post SSA: ", procedure);
 
     result->code = std::make_unique<Compilation>(vm, procedure, optLevel);
-    result->jsEntryPoint = createJSWrapper(vm, info.signature, result->code->code(), memory);
+    result->jsEntryPoint = createJSWrapper(vm, signature, result->code->code(), memory);
     return result;
 }
 
index f8d8420..43ddb9e 100644 (file)
@@ -37,7 +37,7 @@ namespace JSC { namespace Wasm {
 
 class Memory;
 
-std::unique_ptr<FunctionCompilation> parseAndCompile(VM&, Vector<uint8_t>&, Memory*, FunctionInformation, const Vector<FunctionInformation>&, unsigned optLevel = 1);
+std::unique_ptr<FunctionCompilation> parseAndCompile(VM&, const uint8_t*, size_t, Memory*, const Signature*, const Vector<FunctionInformation>&, unsigned optLevel = 1);
 
 } } // namespace JSC::Wasm
 
index a0d5b3d..51e2f8b 100644 (file)
@@ -44,7 +44,7 @@ public:
     typedef typename Context::ExpressionType ExpressionType;
     typedef typename Context::ControlType ControlType;
 
-    FunctionParser(Context&, const Vector<uint8_t>& sourceBuffer, const FunctionInformation&, const Vector<FunctionInformation>& functions);
+    FunctionParser(Context&, const uint8_t* functionStart, size_t functionLength, const Signature*, const Vector<FunctionInformation>& functions);
 
     bool WARN_UNUSED_RETURN parse();
 
@@ -59,21 +59,21 @@ private:
     Context& m_context;
     Vector<ExpressionType, 1> m_expressionStack;
     Vector<ControlType> m_controlStack;
-    const Signature& m_signature;
+    const Signature* m_signature;
     const Vector<FunctionInformation>& m_functions;
     unsigned m_unreachableBlocks { 0 };
 };
 
 template<typename Context>
-FunctionParser<Context>::FunctionParser(Context& context, const Vector<uint8_t>& sourceBuffer, const FunctionInformation& info, const Vector<FunctionInformation>& functions)
-    : Parser(sourceBuffer, info.start, info.end)
+FunctionParser<Context>::FunctionParser(Context& context, const uint8_t* functionStart, size_t functionLength, const Signature* signature, const Vector<FunctionInformation>& functions)
+    : Parser(functionStart, functionLength)
     , m_context(context)
-    , m_signature(*info.signature)
+    , m_signature(signature)
     , m_functions(functions)
 {
     if (verbose)
-        dataLogLn("Parsing function starting at: ", info.start, " ending at: ", info.end);
-    m_context.addArguments(m_signature.arguments);
+        dataLogLn("Parsing function starting at: ", (uintptr_t)functionStart, " of length: ", functionLength);
+    m_context.addArguments(m_signature->arguments);
 }
 
 template<typename Context>
@@ -309,7 +309,7 @@ bool FunctionParser<Context>::parseExpression(OpType op)
 
     case OpType::Return: {
         Vector<ExpressionType, 1> returnValues;
-        if (m_signature.returnType != Void)
+        if (m_signature->returnType != Void)
             returnValues.append(m_expressionStack.takeLast());
 
         m_unreachableBlocks = 1;
index 7ee01b0..276d897 100644 (file)
@@ -41,33 +41,45 @@ static const bool verbose = false;
 
 bool ModuleParser::parse()
 {
-    if (m_sourceLength < 8)
+    const size_t minSize = 8;
+    if (length() < minSize) {
+        m_errorMessage = "Module is " + String::number(length()) + " bytes, expected at least " + String::number(minSize) + " bytes";
         return false;
-    if (!consumeCharacter(0))
-        return false;
-    if (!consumeString("asm"))
+    }
+    if (!consumeCharacter(0) || !consumeString("asm")) {
+        m_errorMessage = "Modules doesn't start with '\\0asm'";
         return false;
+    }
 
     // Skip the version number for now since we don't do anything with it.
     uint32_t versionNumber;
-    if (!parseUInt32(versionNumber))
+    if (!parseUInt32(versionNumber)) {
+        // FIXME improve error message https://bugs.webkit.org/show_bug.cgi?id=163919
+        m_errorMessage = "couldn't parse version number";
         return false;
+    }
 
-    if (versionNumber != magicNumber)
+    if (versionNumber != magicNumber) {
+        // FIXME improve error message https://bugs.webkit.org/show_bug.cgi?id=163919
+        m_errorMessage = "unexpected version number";
         return false;
+    }
 
 
     if (verbose)
         dataLogLn("Passed processing header.");
 
     Sections::Section previousSection = Sections::Unknown;
-    while (m_offset < m_sourceLength) {
+    while (m_offset < length()) {
         if (verbose)
             dataLogLn("Starting to parse next section at offset: ", m_offset);
 
         uint8_t sectionByte;
-        if (!parseUInt7(sectionByte))
+        if (!parseUInt7(sectionByte)) {
+            // FIXME improve error message https://bugs.webkit.org/show_bug.cgi?id=163919
+            m_errorMessage = "couldn't get section byte";
             return false;
+        }
 
         if (verbose)
             dataLogLn("Section byte: ", sectionByte);
@@ -78,24 +90,36 @@ bool ModuleParser::parse()
                 section = static_cast<Sections::Section>(sectionByte);
         } else {
             uint32_t sectionNameLength;
-            if (!parseVarUInt32(sectionNameLength))
+            if (!parseVarUInt32(sectionNameLength)) {
+                // FIXME improve error message https://bugs.webkit.org/show_bug.cgi?id=163919
+                m_errorMessage = "couldn't get section name length";
                 return false;
+            }
 
             // Make sure we can read up to the section's size.
-            if (m_offset + sectionNameLength + WTF::LEBDecoder::max32BitLEBByteLength >= m_sourceLength)
+            if (m_offset + sectionNameLength + WTF::LEBDecoder::max32BitLEBByteLength >= length()) {
+                // FIXME improve error message https://bugs.webkit.org/show_bug.cgi?id=163919
+                m_errorMessage = "section length is bigger than actual size";
                 return false;
+            }
 
             // We don't support any custom sections yet.
 
             m_offset += sectionNameLength;
         }
 
-        if (!Sections::validateOrder(previousSection, section))
+        if (!Sections::validateOrder(previousSection, section)) {
+            // FIXME improve error message https://bugs.webkit.org/show_bug.cgi?id=163919
+            m_errorMessage = "invalid section order";
             return false;
+        }
 
         uint32_t sectionLength;
-        if (!parseVarUInt32(sectionLength))
+        if (!parseVarUInt32(sectionLength)) {
+            // FIXME improve error message https://bugs.webkit.org/show_bug.cgi?id=163919
+            m_errorMessage = "couldn't get section length";
             return false;
+        }
 
         unsigned end = m_offset + sectionLength;
 
@@ -104,32 +128,44 @@ bool ModuleParser::parse()
         case Sections::Memory: {
             if (verbose)
                 dataLogLn("Parsing Memory.");
-            if (!parseMemory())
+            if (!parseMemory()) {
+                // FIXME improve error message https://bugs.webkit.org/show_bug.cgi?id=163919
+                m_errorMessage = "couldn't parse memory";
                 return false;
+            }
             break;
         }
 
         case Sections::FunctionTypes: {
             if (verbose)
                 dataLogLn("Parsing types.");
-            if (!parseFunctionTypes())
+            if (!parseFunctionTypes()) {
+                // FIXME improve error message https://bugs.webkit.org/show_bug.cgi?id=163919
+                m_errorMessage = "couldn't parse types";
                 return false;
+            }
             break;
         }
 
         case Sections::Signatures: {
             if (verbose)
                 dataLogLn("Parsing function signatures.");
-            if (!parseFunctionSignatures())
+            if (!parseFunctionSignatures()) {
+                // FIXME improve error message https://bugs.webkit.org/show_bug.cgi?id=163919
+                m_errorMessage = "couldn't parse function signatures";
                 return false;
+            }
             break;
         }
 
         case Sections::Definitions: {
             if (verbose)
                 dataLogLn("Parsing function definitions.");
-            if (!parseFunctionDefinitions())
+            if (!parseFunctionDefinitions()) {
+                // FIXME improve error message https://bugs.webkit.org/show_bug.cgi?id=163919
+                m_errorMessage = "couldn't parse function definitions";
                 return false;
+            }
             break;
         }
 
@@ -146,13 +182,17 @@ bool ModuleParser::parse()
         if (verbose)
             dataLogLn("Finished parsing section.");
 
-        if (end != m_offset)
+        if (end != m_offset) {
+            // FIXME improve error message https://bugs.webkit.org/show_bug.cgi?id=163919
+            m_errorMessage = "parsing ended before the end of the section";
             return false;
+        }
 
         previousSection = section;
     }
 
     // TODO
+    m_failed = false;
     return true;
 }
 
index 540d5a6..38293ac 100644 (file)
@@ -39,15 +39,33 @@ public:
 
     static const unsigned magicNumber = 0xc;
 
+    ModuleParser(const uint8_t* sourceBuffer, size_t sourceLength)
+        : Parser(sourceBuffer, sourceLength)
+    {
+    }
     ModuleParser(const Vector<uint8_t>& sourceBuffer)
-        : Parser(sourceBuffer, 0, sourceBuffer.size())
+        : Parser(sourceBuffer.data(), sourceBuffer.size())
     {
     }
 
     bool WARN_UNUSED_RETURN parse();
+    bool WARN_UNUSED_RETURN failed() const { return m_failed; }
+    const String& errorMessage() const
+    {
+        RELEASE_ASSERT(failed());
+        return m_errorMessage;
+    }
 
-    const Vector<FunctionInformation>& functionInformation() const { return m_functions; }
-    std::unique_ptr<Memory>& memory() { return m_memory; }
+    const Vector<FunctionInformation>& functionInformation() const
+    {
+        RELEASE_ASSERT(!failed());
+        return m_functions;
+    }
+    std::unique_ptr<Memory>& memory()
+    {
+        RELEASE_ASSERT(!failed());
+        return m_memory;
+    }
 
 private:
     bool WARN_UNUSED_RETURN parseMemory();
@@ -59,6 +77,8 @@ private:
     Vector<FunctionInformation> m_functions;
     Vector<Signature> m_signatures;
     std::unique_ptr<Memory> m_memory;
+    bool m_failed { true };
+    String m_errorMessage;
 };
 
 } } // namespace JSC::Wasm
index 748134d..46a7b39 100644 (file)
@@ -38,7 +38,7 @@ namespace JSC { namespace Wasm {
 
 class Parser {
 protected:
-    Parser(const Vector<uint8_t>&, size_t start, size_t end);
+    Parser(const uint8_t*, size_t);
 
     bool WARN_UNUSED_RETURN consumeCharacter(char);
     bool WARN_UNUSED_RETURN consumeString(const char*);
@@ -46,31 +46,32 @@ protected:
     bool WARN_UNUSED_RETURN parseVarUInt1(uint8_t& result);
     bool WARN_UNUSED_RETURN parseUInt7(uint8_t& result);
     bool WARN_UNUSED_RETURN parseUInt32(uint32_t& result);
-    bool WARN_UNUSED_RETURN parseVarUInt32(uint32_t& result) { return WTF::LEBDecoder::decodeUInt32(m_source.data(), m_sourceLength, m_offset, result); }
-    bool WARN_UNUSED_RETURN parseVarUInt64(uint64_t& result) { return WTF::LEBDecoder::decodeUInt64(m_source.data(), m_sourceLength, m_offset, result); }
-
+    bool WARN_UNUSED_RETURN parseVarUInt32(uint32_t& result) { return WTF::LEBDecoder::decodeUInt32(m_source, m_sourceLength, m_offset, result); }
+    bool WARN_UNUSED_RETURN parseVarUInt64(uint64_t& result) { return WTF::LEBDecoder::decodeUInt64(m_source, m_sourceLength, m_offset, result); }
 
     bool WARN_UNUSED_RETURN parseValueType(Type& result);
 
-    const Vector<uint8_t>& m_source;
+    const uint8_t* source() const { return m_source; }
+    size_t length() const { return m_sourceLength; }
+
+    size_t m_offset = 0;
+
+private:
+    const uint8_t* m_source;
     size_t m_sourceLength;
-    size_t m_offset;
 };
 
-ALWAYS_INLINE Parser::Parser(const Vector<uint8_t>& sourceBuffer, size_t start, size_t end)
+ALWAYS_INLINE Parser::Parser(const uint8_t* sourceBuffer, size_t sourceLength)
     : m_source(sourceBuffer)
-    , m_sourceLength(end)
-    , m_offset(start)
+    , m_sourceLength(sourceLength)
 {
-    ASSERT(end <= sourceBuffer.size());
-    ASSERT(start < end);
 }
 
 ALWAYS_INLINE bool Parser::consumeCharacter(char c)
 {
-    if (m_offset >= m_sourceLength)
+    if (m_offset >= length())
         return false;
-    if (c == m_source[m_offset]) {
+    if (c == source()[m_offset]) {
         m_offset++;
         return true;
     }
@@ -80,9 +81,9 @@ ALWAYS_INLINE bool Parser::consumeCharacter(char c)
 ALWAYS_INLINE bool Parser::consumeString(const char* str)
 {
     unsigned start = m_offset;
-    if (m_offset >= m_sourceLength)
+    if (m_offset >= length())
         return false;
-    for (unsigned i = 0; str[i]; i++) {
+    for (size_t i = 0; str[i]; i++) {
         if (!consumeCharacter(str[i])) {
             m_offset = start;
             return false;
@@ -93,18 +94,18 @@ ALWAYS_INLINE bool Parser::consumeString(const char* str)
 
 ALWAYS_INLINE bool Parser::parseUInt32(uint32_t& result)
 {
-    if (m_sourceLength < 4 || m_offset >= m_sourceLength - 4)
+    if (length() < 4 || m_offset > length() - 4)
         return false;
-    result = *reinterpret_cast<const uint32_t*>(m_source.data() + m_offset);
+    result = *reinterpret_cast<const uint32_t*>(source() + m_offset);
     m_offset += 4;
     return true;
 }
 
 ALWAYS_INLINE bool Parser::parseUInt7(uint8_t& result)
 {
-    if (m_offset >= m_sourceLength)
+    if (m_offset >= length())
         return false;
-    result = m_source[m_offset++];
+    result = source()[m_offset++];
     return result < 0x80;
 }
 
index ba0fa3f..f9c8a54 100644 (file)
 namespace JSC { namespace Wasm {
 
 static const bool verbose = false;
-
+    
 Plan::Plan(VM& vm, Vector<uint8_t> source)
+    : Plan(vm, source.data(), source.size())
+{
+}
+
+Plan::Plan(VM& vm, const uint8_t* source, size_t sourceLength)
 {
     if (verbose)
         dataLogLn("Starting plan.");
-    ModuleParser moduleParser(source);
+    ModuleParser moduleParser(source, sourceLength);
     if (!moduleParser.parse()) {
-        dataLogLn("Parsing module failed.");
+        dataLogLn("Parsing module failed: ", moduleParser.errorMessage());
+        m_errorMessage = moduleParser.errorMessage();
         return;
     }
 
@@ -54,19 +60,25 @@ Plan::Plan(VM& vm, Vector<uint8_t> source)
     for (const FunctionInformation& info : moduleParser.functionInformation()) {
         if (verbose)
             dataLogLn("Processing funcion starting at: ", info.start, " and ending at: ", info.end);
-        result.append(parseAndCompile(vm, source, moduleParser.memory().get(), info, moduleParser.functionInformation()));
+        const uint8_t* functionStart = source + info.start;
+        size_t functionLength = info.end - info.start;
+        ASSERT(functionLength <= sourceLength);
+        m_result.append(parseAndCompile(vm, functionStart, functionLength, moduleParser.memory().get(), info.signature, moduleParser.functionInformation()));
     }
 
     // Patch the call sites for each function.
-    for (std::unique_ptr<FunctionCompilation>& functionPtr : result) {
+    for (std::unique_ptr<FunctionCompilation>& functionPtr : m_result) {
         FunctionCompilation* function = functionPtr.get();
         for (auto& call : function->unlinkedCalls)
-            MacroAssembler::repatchCall(call.callLocation, CodeLocationLabel(result[call.functionIndex]->code->code()));
+            MacroAssembler::repatchCall(call.callLocation, CodeLocationLabel(m_result[call.functionIndex]->code->code()));
     }
 
-    memory = WTFMove(moduleParser.memory());
+    m_memory = WTFMove(moduleParser.memory());
+    m_failed = false;
 }
 
+Plan::~Plan() { }
+
 } } // namespace JSC::Wasm
 
 #endif // ENABLE(WEBASSEMBLY)
index fed136a..b794f1e 100644 (file)
 namespace JSC { namespace Wasm {
 class Memory;
 
-// TODO: This should create a Wasm Module not a list of functions.
 class Plan {
 public:
-    JS_EXPORT_PRIVATE Plan(VM&, Vector<uint8_t> source);
+    JS_EXPORT_PRIVATE Plan(VM&, Vector<uint8_t>);
+    JS_EXPORT_PRIVATE Plan(VM&, const uint8_t*, size_t);
+    JS_EXPORT_PRIVATE ~Plan();
 
-    Vector<std::unique_ptr<FunctionCompilation>> result;
-    std::unique_ptr<Memory> memory;
+    bool WARN_UNUSED_RETURN failed() const { return m_failed; }
+    const String& errorMessage() const
+    {
+        RELEASE_ASSERT(failed());
+        return m_errorMessage;
+    }
+    size_t resultSize() const
+    {
+        RELEASE_ASSERT(!failed());
+        return m_result.size();
+    }
+    const FunctionCompilation* result(size_t n) const
+    {
+        RELEASE_ASSERT(!failed());
+        return m_result.at(n).get();
+    }
+    const Memory* memory() const
+    {
+        RELEASE_ASSERT(!failed());
+        return m_memory.get();
+    }
+
+private:
+    Vector<std::unique_ptr<FunctionCompilation>> m_result;
+    std::unique_ptr<Memory> m_memory;
+    bool m_failed { true };
+    String m_errorMessage;
 };
 
 } } // namespace JSC::Wasm
index 02ff885..3bf57ab 100644 (file)
@@ -47,6 +47,14 @@ JSWebAssemblyCompileError::JSWebAssemblyCompileError(VM& vm, Structure* structur
 
 const ClassInfo JSWebAssemblyCompileError::s_info = { "WebAssembly.CompileError", &Base::s_info, 0, CREATE_METHOD_TABLE(JSWebAssemblyCompileError) };
 
+    
+JSObject* createWebAssemblyCompileError(ExecState* exec, const String& message)
+{
+    ASSERT(!message.isEmpty());
+    JSGlobalObject* globalObject = exec->lexicalGlobalObject();
+    return ErrorInstance::create(exec, globalObject->vm(), globalObject->WebAssemblyCompileErrorStructure(), message, defaultSourceAppender, TypeNothing, true);
+}
+
 } // namespace JSC
 
 #endif // ENABLE(WEBASSEMBLY)
index 656b8d0..c14a379 100644 (file)
@@ -47,6 +47,8 @@ protected:
     JSWebAssemblyCompileError(VM&, Structure*);
 };
 
+JSObject* createWebAssemblyCompileError(ExecState*, const String&);
+
 } // namespace JSC
 
 #endif // ENABLE(WEBASSEMBLY)
index 67e6d95..f4e1126 100644 (file)
@@ -48,7 +48,7 @@ static EncodedJSValue JSC_HOST_CALL constructJSWebAssemblyCompileError(ExecState
 {
     auto& vm = state->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
-    JSValue message = state->argumentCount() ? state->argument(0) : jsUndefined();
+    JSValue message = state->argument(0);
     auto* structure = InternalFunction::createSubclassStructure(state, state->newTarget(), asInternalFunction(state->callee())->globalObject()->WebAssemblyCompileErrorStructure());
     RETURN_IF_EXCEPTION(scope, encodedJSValue());
     return JSValue::encode(JSWebAssemblyCompileError::create(state, structure, message, false));
@@ -61,10 +61,10 @@ static EncodedJSValue JSC_HOST_CALL callJSWebAssemblyCompileError(ExecState* sta
     return JSValue::encode(throwConstructorCannotBeCalledAsFunctionTypeError(state, scope, "WebAssembly.CompileError"));
 }
 
-WebAssemblyCompileErrorConstructor* WebAssemblyCompileErrorConstructor::create(VM& vm, Structure* structure, WebAssemblyCompileErrorPrototype* thisPrototype, Structure* thisStructure)
+WebAssemblyCompileErrorConstructor* WebAssemblyCompileErrorConstructor::create(VM& vm, Structure* structure, WebAssemblyCompileErrorPrototype* thisPrototype)
 {
     auto* constructor = new (NotNull, allocateCell<WebAssemblyCompileErrorConstructor>(vm.heap)) WebAssemblyCompileErrorConstructor(vm, structure);
-    constructor->finishCreation(vm, thisPrototype, thisStructure);
+    constructor->finishCreation(vm, thisPrototype);
     return constructor;
 }
 
@@ -73,7 +73,7 @@ Structure* WebAssemblyCompileErrorConstructor::createStructure(VM& vm, JSGlobalO
     return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
 }
 
-void WebAssemblyCompileErrorConstructor::finishCreation(VM& vm, WebAssemblyCompileErrorPrototype* prototype, Structure*)
+void WebAssemblyCompileErrorConstructor::finishCreation(VM& vm, WebAssemblyCompileErrorPrototype* prototype)
 {
     Base::finishCreation(vm, ASCIILiteral("CompileError"));
     putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, ReadOnly | DontEnum | DontDelete);
index d4856c9..34a0e78 100644 (file)
@@ -39,13 +39,13 @@ public:
     typedef InternalFunction Base;
     static const unsigned StructureFlags = Base::StructureFlags | HasStaticPropertyTable;
 
-    static WebAssemblyCompileErrorConstructor* create(VM&, Structure*, WebAssemblyCompileErrorPrototype*, Structure*);
+    static WebAssemblyCompileErrorConstructor* create(VM&, Structure*, WebAssemblyCompileErrorPrototype*);
     static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
 
     DECLARE_INFO;
 
 protected:
-    void finishCreation(VM&, WebAssemblyCompileErrorPrototype*, Structure*);
+    void finishCreation(VM&, WebAssemblyCompileErrorPrototype*);
 
 private:
     WebAssemblyCompileErrorConstructor(VM&, Structure*);
index 85ce9aa..55bf4a1 100644 (file)
@@ -57,10 +57,10 @@ static EncodedJSValue JSC_HOST_CALL callJSWebAssemblyInstance(ExecState* state)
     return JSValue::encode(throwConstructorCannotBeCalledAsFunctionTypeError(state, scope, "WebAssembly.Instance"));
 }
 
-WebAssemblyInstanceConstructor* WebAssemblyInstanceConstructor::create(VM& vm, Structure* structure, WebAssemblyInstancePrototype* thisPrototype, Structure* thisStructure)
+WebAssemblyInstanceConstructor* WebAssemblyInstanceConstructor::create(VM& vm, Structure* structure, WebAssemblyInstancePrototype* thisPrototype)
 {
     auto* constructor = new (NotNull, allocateCell<WebAssemblyInstanceConstructor>(vm.heap)) WebAssemblyInstanceConstructor(vm, structure);
-    constructor->finishCreation(vm, thisPrototype, thisStructure);
+    constructor->finishCreation(vm, thisPrototype);
     return constructor;
 }
 
@@ -69,12 +69,11 @@ Structure* WebAssemblyInstanceConstructor::createStructure(VM& vm, JSGlobalObjec
     return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
 }
 
-void WebAssemblyInstanceConstructor::finishCreation(VM& vm, WebAssemblyInstancePrototype* prototype, Structure* structure)
+void WebAssemblyInstanceConstructor::finishCreation(VM& vm, WebAssemblyInstancePrototype* prototype)
 {
     Base::finishCreation(vm, ASCIILiteral("Instance"));
     putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, DontEnum | DontDelete | ReadOnly);
     putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), ReadOnly | DontEnum | DontDelete);
-    m_InstanceStructure.set(vm, this, structure);
 }
 
 WebAssemblyInstanceConstructor::WebAssemblyInstanceConstructor(VM& vm, Structure* structure)
@@ -99,7 +98,6 @@ void WebAssemblyInstanceConstructor::visitChildren(JSCell* cell, SlotVisitor& vi
     auto* thisObject = jsCast<WebAssemblyInstanceConstructor*>(cell);
     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
     Base::visitChildren(thisObject, visitor);
-    visitor.append(&thisObject->m_InstanceStructure);
 }
 
 } // namespace JSC
index ddddf71..2e857cf 100644 (file)
@@ -39,23 +39,19 @@ public:
     typedef InternalFunction Base;
     static const unsigned StructureFlags = Base::StructureFlags | HasStaticPropertyTable;
 
-    static WebAssemblyInstanceConstructor* create(VM&, Structure*, WebAssemblyInstancePrototype*, Structure*);
+    static WebAssemblyInstanceConstructor* create(VM&, Structure*, WebAssemblyInstancePrototype*);
     static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
 
     DECLARE_INFO;
 
-    Structure* InstanceStructure() const { return m_InstanceStructure.get(); }
-
 protected:
-    void finishCreation(VM&, WebAssemblyInstancePrototype*, Structure*);
+    void finishCreation(VM&, WebAssemblyInstancePrototype*);
 
 private:
     WebAssemblyInstanceConstructor(VM&, Structure*);
     static ConstructType getConstructData(JSCell*, ConstructData&);
     static CallType getCallData(JSCell*, CallData&);
     static void visitChildren(JSCell*, SlotVisitor&);
-
-    WriteBarrier<Structure> m_InstanceStructure;
 };
 
 } // namespace JSC
index ad525cf..1c582b4 100644 (file)
@@ -57,10 +57,10 @@ static EncodedJSValue JSC_HOST_CALL callJSWebAssemblyMemory(ExecState* state)
     return JSValue::encode(throwConstructorCannotBeCalledAsFunctionTypeError(state, scope, "WebAssembly.Memory"));
 }
 
-WebAssemblyMemoryConstructor* WebAssemblyMemoryConstructor::create(VM& vm, Structure* structure, WebAssemblyMemoryPrototype* thisPrototype, Structure* thisStructure)
+WebAssemblyMemoryConstructor* WebAssemblyMemoryConstructor::create(VM& vm, Structure* structure, WebAssemblyMemoryPrototype* thisPrototype)
 {
     auto* constructor = new (NotNull, allocateCell<WebAssemblyMemoryConstructor>(vm.heap)) WebAssemblyMemoryConstructor(vm, structure);
-    constructor->finishCreation(vm, thisPrototype, thisStructure);
+    constructor->finishCreation(vm, thisPrototype);
     return constructor;
 }
 
@@ -69,12 +69,11 @@ Structure* WebAssemblyMemoryConstructor::createStructure(VM& vm, JSGlobalObject*
     return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
 }
 
-void WebAssemblyMemoryConstructor::finishCreation(VM& vm, WebAssemblyMemoryPrototype* prototype, Structure* structure)
+void WebAssemblyMemoryConstructor::finishCreation(VM& vm, WebAssemblyMemoryPrototype* prototype)
 {
     Base::finishCreation(vm, ASCIILiteral("Memory"));
     putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, DontEnum | DontDelete | ReadOnly);
     putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), ReadOnly | DontEnum | DontDelete);
-    m_MemoryStructure.set(vm, this, structure);
 }
 
 WebAssemblyMemoryConstructor::WebAssemblyMemoryConstructor(VM& vm, Structure* structure)
@@ -99,7 +98,6 @@ void WebAssemblyMemoryConstructor::visitChildren(JSCell* cell, SlotVisitor& visi
     auto* thisObject = jsCast<WebAssemblyMemoryConstructor*>(cell);
     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
     Base::visitChildren(thisObject, visitor);
-    visitor.append(&thisObject->m_MemoryStructure);
 }
 
 } // namespace JSC
index 34cd120..4660693 100644 (file)
@@ -39,23 +39,19 @@ public:
     typedef InternalFunction Base;
     static const unsigned StructureFlags = Base::StructureFlags | HasStaticPropertyTable;
 
-    static WebAssemblyMemoryConstructor* create(VM&, Structure*, WebAssemblyMemoryPrototype*, Structure*);
+    static WebAssemblyMemoryConstructor* create(VM&, Structure*, WebAssemblyMemoryPrototype*);
     static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
 
     DECLARE_INFO;
 
-    Structure* MemoryStructure() const { return m_MemoryStructure.get(); }
-
 protected:
-    void finishCreation(VM&, WebAssemblyMemoryPrototype*, Structure*);
+    void finishCreation(VM&, WebAssemblyMemoryPrototype*);
 
 private:
     WebAssemblyMemoryConstructor(VM&, Structure*);
     static ConstructType getConstructData(JSCell*, ConstructData&);
     static CallType getCallData(JSCell*, CallData&);
     static void visitChildren(JSCell*, SlotVisitor&);
-
-    WriteBarrier<Structure> m_MemoryStructure;
 };
 
 } // namespace JSC
index e97b011..e903eef 100644 (file)
 
 #if ENABLE(WEBASSEMBLY)
 
+#include "ExceptionHelpers.h"
 #include "FunctionPrototype.h"
+#include "JSArrayBuffer.h"
 #include "JSCInlines.h"
+#include "JSTypedArrays.h"
+#include "JSWebAssemblyCompileError.h"
+#include "JSWebAssemblyModule.h"
+#include "WasmPlan.h"
 #include "WebAssemblyModulePrototype.h"
 
 #include "WebAssemblyModuleConstructor.lut.h"
@@ -45,9 +51,30 @@ const ClassInfo WebAssemblyModuleConstructor::s_info = { "Function", &Base::s_in
 
 static EncodedJSValue JSC_HOST_CALL constructJSWebAssemblyModule(ExecState* state)
 {
-    VM& vm = state->vm();
+    auto& vm = state->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
-    return JSValue::encode(throwException(state, scope, createError(state, ASCIILiteral("WebAssembly doesn't yet implement the Module constructor property"))));
+    JSValue val = state->argument(0);
+    JSArrayBuffer* arrayBuffer = val.getObject() ? jsDynamicCast<JSArrayBuffer*>(val.getObject()) : nullptr;
+    JSArrayBufferView* arrayBufferView = val.getObject() ? jsDynamicCast<JSArrayBufferView*>(val.getObject()) : nullptr;
+    if (!(arrayBuffer || arrayBufferView))
+        return JSValue::encode(throwException(state, scope, createTypeError(state, ASCIILiteral("first argument to WebAssembly.Module must be an ArrayBufferView or an ArrayBuffer"), defaultSourceAppender, runtimeTypeForValue(val))));
+
+    if (arrayBufferView ? arrayBufferView->isNeutered() : arrayBuffer->impl()->isNeutered())
+        return JSValue::encode(throwException(state, scope, createTypeError(state, ASCIILiteral("underlying TypedArray has been detatched from the ArrayBuffer"), defaultSourceAppender, runtimeTypeForValue(val))));
+
+    size_t byteOffset = arrayBufferView ? arrayBufferView->byteOffset() : 0;
+    size_t byteSize = arrayBufferView ? arrayBufferView->length() : arrayBuffer->impl()->byteLength();
+    const auto* base = arrayBufferView ? static_cast<uint8_t*>(arrayBufferView->vector()) : static_cast<uint8_t*>(arrayBuffer->impl()->data());
+
+    Wasm::Plan plan(vm, base + byteOffset, byteSize);
+    if (plan.failed())
+        return JSValue::encode(throwException(state, scope, createWebAssemblyCompileError(state, plan.errorMessage())));
+
+    // FIXME take content from Plan.
+
+    auto* structure = InternalFunction::createSubclassStructure(state, state->newTarget(), asInternalFunction(state->callee())->globalObject()->WebAssemblyModuleStructure());
+    RETURN_IF_EXCEPTION(scope, encodedJSValue());
+    return JSValue::encode(JSWebAssemblyModule::create(vm, structure));
 }
 
 static EncodedJSValue JSC_HOST_CALL callJSWebAssemblyModule(ExecState* state)
@@ -57,10 +84,10 @@ static EncodedJSValue JSC_HOST_CALL callJSWebAssemblyModule(ExecState* state)
     return JSValue::encode(throwConstructorCannotBeCalledAsFunctionTypeError(state, scope, "WebAssembly.Module"));
 }
 
-WebAssemblyModuleConstructor* WebAssemblyModuleConstructor::create(VM& vm, Structure* structure, WebAssemblyModulePrototype* thisPrototype, Structure* thisStructure)
+WebAssemblyModuleConstructor* WebAssemblyModuleConstructor::create(VM& vm, Structure* structure, WebAssemblyModulePrototype* thisPrototype)
 {
     auto* constructor = new (NotNull, allocateCell<WebAssemblyModuleConstructor>(vm.heap)) WebAssemblyModuleConstructor(vm, structure);
-    constructor->finishCreation(vm, thisPrototype, thisStructure);
+    constructor->finishCreation(vm, thisPrototype);
     return constructor;
 }
 
@@ -69,12 +96,11 @@ Structure* WebAssemblyModuleConstructor::createStructure(VM& vm, JSGlobalObject*
     return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
 }
 
-void WebAssemblyModuleConstructor::finishCreation(VM& vm, WebAssemblyModulePrototype* prototype, Structure* structure)
+void WebAssemblyModuleConstructor::finishCreation(VM& vm, WebAssemblyModulePrototype* prototype)
 {
     Base::finishCreation(vm, ASCIILiteral("Module"));
     putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, DontEnum | DontDelete | ReadOnly);
     putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), ReadOnly | DontEnum | DontDelete);
-    m_ModuleStructure.set(vm, this, structure);
 }
 
 WebAssemblyModuleConstructor::WebAssemblyModuleConstructor(VM& vm, Structure* structure)
@@ -99,7 +125,6 @@ void WebAssemblyModuleConstructor::visitChildren(JSCell* cell, SlotVisitor& visi
     auto* thisObject = jsCast<WebAssemblyModuleConstructor*>(cell);
     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
     Base::visitChildren(thisObject, visitor);
-    visitor.append(&thisObject->m_ModuleStructure);
 }
 
 } // namespace JSC
index 56057a6..e45f1a1 100644 (file)
@@ -39,23 +39,19 @@ public:
     typedef InternalFunction Base;
     static const unsigned StructureFlags = Base::StructureFlags | HasStaticPropertyTable;
 
-    static WebAssemblyModuleConstructor* create(VM&, Structure*, WebAssemblyModulePrototype*, Structure*);
+    static WebAssemblyModuleConstructor* create(VM&, Structure*, WebAssemblyModulePrototype*);
     static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
 
     DECLARE_INFO;
 
-    Structure* ModuleStructure() const { return m_ModuleStructure.get(); }
-
 protected:
-    void finishCreation(VM&, WebAssemblyModulePrototype*, Structure*);
+    void finishCreation(VM&, WebAssemblyModulePrototype*);
 
 private:
     WebAssemblyModuleConstructor(VM&, Structure*);
     static ConstructType getConstructData(JSCell*, ConstructData&);
     static CallType getCallData(JSCell*, CallData&);
     static void visitChildren(JSCell*, SlotVisitor&);
-
-    WriteBarrier<Structure> m_ModuleStructure;
 };
 
 } // namespace JSC
index 5528022..01b32f7 100644 (file)
@@ -61,10 +61,10 @@ static EncodedJSValue JSC_HOST_CALL callJSWebAssemblyRuntimeError(ExecState* sta
     return JSValue::encode(throwConstructorCannotBeCalledAsFunctionTypeError(state, scope, "WebAssembly.RuntimeError"));
 }
 
-WebAssemblyRuntimeErrorConstructor* WebAssemblyRuntimeErrorConstructor::create(VM& vm, Structure* structure, WebAssemblyRuntimeErrorPrototype* thisPrototype, Structure* thisStructure)
+WebAssemblyRuntimeErrorConstructor* WebAssemblyRuntimeErrorConstructor::create(VM& vm, Structure* structure, WebAssemblyRuntimeErrorPrototype* thisPrototype)
 {
     auto* constructor = new (NotNull, allocateCell<WebAssemblyRuntimeErrorConstructor>(vm.heap)) WebAssemblyRuntimeErrorConstructor(vm, structure);
-    constructor->finishCreation(vm, thisPrototype, thisStructure);
+    constructor->finishCreation(vm, thisPrototype);
     return constructor;
 }
 
@@ -73,7 +73,7 @@ Structure* WebAssemblyRuntimeErrorConstructor::createStructure(VM& vm, JSGlobalO
     return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
 }
 
-void WebAssemblyRuntimeErrorConstructor::finishCreation(VM& vm, WebAssemblyRuntimeErrorPrototype* prototype, Structure*)
+void WebAssemblyRuntimeErrorConstructor::finishCreation(VM& vm, WebAssemblyRuntimeErrorPrototype* prototype)
 {
     Base::finishCreation(vm, ASCIILiteral("RuntimeError"));
     putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, ReadOnly | DontEnum | DontDelete);
index be419d7..77fb6e4 100644 (file)
@@ -39,13 +39,13 @@ public:
     typedef InternalFunction Base;
     static const unsigned StructureFlags = Base::StructureFlags | HasStaticPropertyTable;
 
-    static WebAssemblyRuntimeErrorConstructor* create(VM&, Structure*, WebAssemblyRuntimeErrorPrototype*, Structure*);
+    static WebAssemblyRuntimeErrorConstructor* create(VM&, Structure*, WebAssemblyRuntimeErrorPrototype*);
     static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
 
     DECLARE_INFO;
 
 protected:
-    void finishCreation(VM&, WebAssemblyRuntimeErrorPrototype*, Structure*);
+    void finishCreation(VM&, WebAssemblyRuntimeErrorPrototype*);
 
 private:
     WebAssemblyRuntimeErrorConstructor(VM&, Structure*);
index 4b6608c..caa7e9e 100644 (file)
@@ -57,10 +57,10 @@ static EncodedJSValue JSC_HOST_CALL callJSWebAssemblyTable(ExecState* state)
     return JSValue::encode(throwConstructorCannotBeCalledAsFunctionTypeError(state, scope, "WebAssembly.Table"));
 }
 
-WebAssemblyTableConstructor* WebAssemblyTableConstructor::create(VM& vm, Structure* structure, WebAssemblyTablePrototype* thisPrototype, Structure* thisStructure)
+WebAssemblyTableConstructor* WebAssemblyTableConstructor::create(VM& vm, Structure* structure, WebAssemblyTablePrototype* thisPrototype)
 {
     auto* constructor = new (NotNull, allocateCell<WebAssemblyTableConstructor>(vm.heap)) WebAssemblyTableConstructor(vm, structure);
-    constructor->finishCreation(vm, thisPrototype, thisStructure);
+    constructor->finishCreation(vm, thisPrototype);
     return constructor;
 }
 
@@ -69,12 +69,11 @@ Structure* WebAssemblyTableConstructor::createStructure(VM& vm, JSGlobalObject*
     return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
 }
 
-void WebAssemblyTableConstructor::finishCreation(VM& vm, WebAssemblyTablePrototype* prototype, Structure* structure)
+void WebAssemblyTableConstructor::finishCreation(VM& vm, WebAssemblyTablePrototype* prototype)
 {
     Base::finishCreation(vm, ASCIILiteral("Table"));
     putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, DontEnum | DontDelete | ReadOnly);
     putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), ReadOnly | DontEnum | DontDelete);
-    m_TableStructure.set(vm, this, structure);
 }
 
 WebAssemblyTableConstructor::WebAssemblyTableConstructor(VM& vm, Structure* structure)
@@ -99,7 +98,6 @@ void WebAssemblyTableConstructor::visitChildren(JSCell* cell, SlotVisitor& visit
     auto* thisObject = jsCast<WebAssemblyTableConstructor*>(cell);
     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
     Base::visitChildren(thisObject, visitor);
-    visitor.append(&thisObject->m_TableStructure);
 }
 
 } // namespace JSC
index e08e735..a61c7ac 100644 (file)
@@ -39,23 +39,19 @@ public:
     typedef InternalFunction Base;
     static const unsigned StructureFlags = Base::StructureFlags | HasStaticPropertyTable;
 
-    static WebAssemblyTableConstructor* create(VM&, Structure*, WebAssemblyTablePrototype*, Structure*);
+    static WebAssemblyTableConstructor* create(VM&, Structure*, WebAssemblyTablePrototype*);
     static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
 
     DECLARE_INFO;
 
-    Structure* TableStructure() const { return m_TableStructure.get(); }
-
 protected:
-    void finishCreation(VM&, WebAssemblyTablePrototype*, Structure*);
+    void finishCreation(VM&, WebAssemblyTablePrototype*);
 
 private:
     WebAssemblyTableConstructor(VM&, Structure*);
     static ConstructType getConstructData(JSCell*, ConstructData&);
     static CallType getCallData(JSCell*, CallData&);
     static void visitChildren(JSCell*, SlotVisitor&);
-
-    WriteBarrier<Structure> m_TableStructure;
 };
 
 } // namespace JSC