feat: try with a Table

This commit is contained in:
Sven SAULEAU 2018-03-09 12:04:27 +01:00
parent faff92c52b
commit 5c6c50bd2e
No known key found for this signature in database
GPG Key ID: F5464AC83B687AD1
4 changed files with 183 additions and 80 deletions

View File

@ -22,6 +22,12 @@ function compose(...fns) {
}, value => value);
}
/**
* Utility functions
*/
const isGlobalImport = moduleImport => moduleImport.descr.type === "GlobalType";
const isInstructionOfName = name => instr => instr.id === name;
/**
* Export the start function and removes the start instruction
*/
@ -51,74 +57,109 @@ function rewriteStartFunc(bin) {
}
/**
* Replaces global imports by func imports
* (which will return the globals at runtime)
* Import the WebAssembly.Table used for interop with other modules managed by
* Webpack.
*
* Also needs to update the calls instructions `get_global` and `set_global`
* which become function calls.
* @param {ArrayBuffer} bin
* @returns {ArrayBuffer} bin'
*
* FIXME(sven): I abrirary choose these names but that might cause conflicts with
* the user's code, example if a module is called webpack?
*
* TODO(sven): what should be the TableDescriptor? We can infer the exact initial
* value from the number of imports.
*/
function rewriteGlobalImports(bin) {
debug("rewriteGlobalImports");
function addImportInteropTable(bin) {
return add(bin, [
t.moduleImport("webpack", "interoptable", t.table("anyfunc", t.limits(10)))
]);
}
/**
* Remove the ModuleImport for globals because they will be reachable throught
* the interoptable now.
*
* @param {ArrayBuffer} bin
* @returns {ArrayBuffer} bin'
*
* FIXME(sven): breaks the non-exported globals because their offset will be
* shifted by i-(number of import removed). We can either shift the index or
* replace by stub ones (non-imported)?
*/
function removeImportedGlobals(bin) {
return edit(bin, {
ModuleImport(path) {
if (isGlobalImport(path.node) === true) {
debug("remove import", path.node.module, path.node.name);
path.remove();
}
}
});
}
/**
* Adds the type definition and update every `get_global` to `call_indirect`.
*
* FIXME(sven): that also breaks the non-import global since they will be
* rewriting to calls
*
* @param {ArrayBuffer} bin
* @returns {ArrayBuffer} bin'
*/
function rewriteGlobalToInteroptable(bin) {
const ast = decode(bin, {
ignoreCodeSection: true,
ignoreDataSection: true
});
const funcType = t.typeInstructionFunc([], ["i32"]);
/**
* Add the functypes corresponding to the global imported
*/
const functypes = [];
// get next func index
let nextFuncindex = 0;
t.traverse(ast, {
Func() {
nextFuncindex++;
},
ModuleImport({ node }) {
if (node.descr.type === "Func") {
nextFuncindex++;
}
}
});
const funcTypeIndex = t.indexLiteral(nextFuncindex);
bin = add(bin, [funcType]);
let importedGlobalIndex = 0;
const mapGlobalAndFuncIndex = {};
bin = edit(bin, {
/**
* import global of type t1
* type = () => t1
*/
ModuleImport(path) {
const { node } = path;
if (isGlobalImport(path.node) === true) {
const { valtype } = path.node.descr;
const functype = t.typeInstructionFunc([], [valtype]);
// is importing a global
if (node.descr.type === "GlobalType") {
node.name = "_global_get_" + node.name;
node.descr = t.funcImportDescr(
funcTypeIndex,
funcType.functype.params,
funcType.functype.results
);
mapGlobalAndFuncIndex[importedGlobalIndex] = funcTypeIndex;
importedGlobalIndex++;
functypes.push(functype);
}
}
});
// Update accessers
debug("add functypes", functypes.map(x => x.functype));
bin = add(bin, functypes);
/**
* Rewrite get_global
*/
const isGetGlobalInstruction = isInstructionOfName("get_global");
bin = edit(bin, {
Instr(path) {
const [firstArg] = path.node.args;
const funcIndex = mapGlobalAndFuncIndex[firstArg.value];
if (isGetGlobalInstruction(path.node) === true) {
const [globalIndex] = path.node.args;
const functypeIndex = functypes[globalIndex.value];
debug(`rename get_global ${firstArg.value} to call ${funcIndex.value}`);
if (typeof functypeIndex === "undefined") {
throw new Error(
"Internal failure: can not find the functype for global at index " +
globalIndex.value
);
}
const newNode = t.callInstruction(funcIndex);
path.replaceWith(newNode);
const callIndirectInstruction = t.callIndirectInstructionIndex(
t.indexLiteral(globalIndex.value)
);
path.replaceWith(callIndirectInstruction);
}
}
});
@ -126,7 +167,9 @@ function rewriteGlobalImports(bin) {
}
const transform = compose(
rewriteGlobalImports,
removeImportedGlobals,
rewriteGlobalToInteroptable,
addImportInteropTable,
rewriteStartFunc
);
@ -139,7 +182,8 @@ class WebAssemblyGenerator {
const newBin = transform(bin);
debug("__________________________________________________________");
// console.log(print(decode(newBin)))
// decode(newBin, { dump: true });
// console.log(print(decode(newBin)));
return new RawSource(newBin);
}

View File

@ -82,7 +82,7 @@ class FetchCompileWasmMainTemplatePlugin {
}
if (data.description.type === "GlobalType") {
data.exportName = "_global_get_" + data.exportName;
data.exportName = "_global_get_" + data.exportName;
result = `__webpack_require__(${JSON.stringify(
data.module.id
@ -99,6 +99,10 @@ class FetchCompileWasmMainTemplatePlugin {
`\n\t${JSON.stringify(pair[0])}: {${properties.join(",")}\n\t}`
);
}
// Add interoptable
importsCode.push(`\n\t"webpack": { "interoptable": interoptable }\n\t`);
return (
JSON.stringify(module.id) + ": {" + importsCode.join(",") + "\n}"
);
@ -142,6 +146,12 @@ class FetchCompileWasmMainTemplatePlugin {
"",
"// Fetch + compile chunk loading for webassembly",
"",
"var interoptable = new WebAssembly.Table({",
Template.indent(["element: 'anyfunc',", "initial: 0"]),
"})",
"",
"interoptable.set(0, () => console.log('called'))",
"",
"var importObjects = {",
Template.indent([importObjects]),
"}",

View File

@ -5,9 +5,10 @@
"description": "Packs CommonJs/AMD modules for the browser. Allows to split your codebase into multiple bundles, which can be loaded on demand. Support loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.",
"license": "MIT",
"dependencies": {
"@webassemblyjs/ast": "^1.0.0",
"@webassemblyjs/wasm-edit": "^1.1.2-y.0",
"@webassemblyjs/ast": "1.1.2-y.6",
"@webassemblyjs/wasm-edit": "1.1.2-y.6",
"@webassemblyjs/wasm-parser": "^1.0.0",
"@webassemblyjs/wast-printer": "^1.1.2-y.0",
"acorn": "^5.0.0",
"acorn-dynamic-import": "^3.0.0",
"ajv": "^6.1.0",

102
yarn.lock
View File

@ -16,7 +16,7 @@
esutils "^2.0.2"
js-tokens "^3.0.0"
"@webassemblyjs/ast@1.0.0", "@webassemblyjs/ast@^1.0.0":
"@webassemblyjs/ast@1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.0.0.tgz#e6953dd785b6827ac5ce2fab479b1358f35f7df4"
dependencies:
@ -32,9 +32,17 @@
webassembly-floating-point-hex-parser "0.1.2"
webassemblyjs "1.1.2-y.0"
"@webassemblyjs/helper-buffer@1.1.2-y.0":
version "1.1.2-y.0"
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.1.2-y.0.tgz#25e8b7d133be147fe70f522263491da2b36f5259"
"@webassemblyjs/ast@1.1.2-y.6":
version "1.1.2-y.6"
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.1.2-y.6.tgz#48cd46498cbcf3ad0873c311a68ef11c6bd98ef1"
dependencies:
"@webassemblyjs/wast-parser" "1.1.2-y.6"
webassembly-floating-point-hex-parser "0.1.2"
webassemblyjs "1.1.2-y.6"
"@webassemblyjs/helper-buffer@1.1.2-y.6":
version "1.1.2-y.6"
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.1.2-y.6.tgz#1f0e88d29c61cf8e5c310e612ddfc7af41c3d53f"
"@webassemblyjs/helper-leb128@1.1.2-y.0":
version "1.1.2-y.0"
@ -42,37 +50,47 @@
dependencies:
leb "^0.3.0"
"@webassemblyjs/helper-leb128@1.1.2-y.6":
version "1.1.2-y.6"
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-leb128/-/helper-leb128-1.1.2-y.6.tgz#ad48ed8e91cd291a5daab1cf9b157ce68d4725b4"
dependencies:
leb "^0.3.0"
"@webassemblyjs/helper-wasm-bytecode@1.1.2-y.0":
version "1.1.2-y.0"
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.1.2-y.0.tgz#d50c40200fc5ab6a4ab0c080f9ff4c815c2f0302"
"@webassemblyjs/helper-wasm-section@1.1.2-y.0":
version "1.1.2-y.0"
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.1.2-y.0.tgz#28acfd9c1f1aeb3864031f15b4398f9c9ffac8dc"
dependencies:
"@webassemblyjs/ast" "1.1.2-y.0"
"@webassemblyjs/helper-buffer" "1.1.2-y.0"
"@webassemblyjs/helper-wasm-bytecode" "1.1.2-y.0"
"@webassemblyjs/wasm-gen" "1.1.2-y.0"
"@webassemblyjs/helper-wasm-bytecode@1.1.2-y.6":
version "1.1.2-y.6"
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.1.2-y.6.tgz#52f68cc36eba2f2e90ab98d602186a1feb37887c"
"@webassemblyjs/wasm-edit@^1.1.2-y.0":
version "1.1.2-y.0"
resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.1.2-y.0.tgz#9145814a40b4e1ef023a6b644dab8832d7c62531"
"@webassemblyjs/helper-wasm-section@1.1.2-y.6":
version "1.1.2-y.6"
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.1.2-y.6.tgz#9bd6fccdb8955b0f847a5f11b8672634298ea494"
dependencies:
"@webassemblyjs/ast" "1.1.2-y.0"
"@webassemblyjs/helper-buffer" "1.1.2-y.0"
"@webassemblyjs/helper-wasm-bytecode" "1.1.2-y.0"
"@webassemblyjs/helper-wasm-section" "1.1.2-y.0"
"@webassemblyjs/wasm-gen" "1.1.2-y.0"
"@webassemblyjs/wasm-parser" "1.1.2-y.0"
"@webassemblyjs/ast" "1.1.2-y.6"
"@webassemblyjs/helper-buffer" "1.1.2-y.6"
"@webassemblyjs/helper-wasm-bytecode" "1.1.2-y.6"
"@webassemblyjs/wasm-gen" "1.1.2-y.6"
"@webassemblyjs/wasm-gen@1.1.2-y.0":
version "1.1.2-y.0"
resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.1.2-y.0.tgz#38f103f25eff059b0a2c436e7e345b0bd216fff5"
"@webassemblyjs/wasm-edit@1.1.2-y.6":
version "1.1.2-y.6"
resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.1.2-y.6.tgz#8ae7646094f9aa3ae2c4cb8f5bff42ce1c2d6bba"
dependencies:
"@webassemblyjs/ast" "1.1.2-y.0"
"@webassemblyjs/helper-leb128" "1.1.2-y.0"
"@webassemblyjs/helper-wasm-bytecode" "1.1.2-y.0"
"@webassemblyjs/ast" "1.1.2-y.6"
"@webassemblyjs/helper-buffer" "1.1.2-y.6"
"@webassemblyjs/helper-wasm-bytecode" "1.1.2-y.6"
"@webassemblyjs/helper-wasm-section" "1.1.2-y.6"
"@webassemblyjs/wasm-gen" "1.1.2-y.6"
"@webassemblyjs/wasm-parser" "1.1.2-y.6"
"@webassemblyjs/wasm-gen@1.1.2-y.6":
version "1.1.2-y.6"
resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.1.2-y.6.tgz#ea960b44712303b22d6a75d176f56109ada90b00"
dependencies:
"@webassemblyjs/ast" "1.1.2-y.6"
"@webassemblyjs/helper-leb128" "1.1.2-y.6"
"@webassemblyjs/helper-wasm-bytecode" "1.1.2-y.6"
"@webassemblyjs/wasm-parser@1.0.0", "@webassemblyjs/wasm-parser@^1.0.0":
version "1.0.0"
@ -92,6 +110,16 @@
"@webassemblyjs/wasm-parser" "1.1.2-y.0"
webassemblyjs "1.1.2-y.0"
"@webassemblyjs/wasm-parser@1.1.2-y.6":
version "1.1.2-y.6"
resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.1.2-y.6.tgz#029ca09e016280cfcee7306989c32f8202a31914"
dependencies:
"@webassemblyjs/ast" "1.1.2-y.6"
"@webassemblyjs/helper-leb128" "1.1.2-y.6"
"@webassemblyjs/helper-wasm-bytecode" "1.1.2-y.6"
"@webassemblyjs/wasm-parser" "1.1.2-y.6"
webassemblyjs "1.1.2-y.6"
"@webassemblyjs/wast-parser@1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.0.0.tgz#d874e2dcb1726d31868518be7807f8f2ff358425"
@ -112,6 +140,16 @@
webassembly-floating-point-hex-parser "0.1.2"
webassemblyjs "1.1.2-y.0"
"@webassemblyjs/wast-parser@1.1.2-y.6":
version "1.1.2-y.6"
resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.1.2-y.6.tgz#e32a0f14861e9bf9c8e1a720b25f36a928dfd802"
dependencies:
"@babel/code-frame" "^7.0.0-beta.36"
"@webassemblyjs/ast" "1.1.2-y.6"
long "^3.2.0"
webassembly-floating-point-hex-parser "0.1.2"
webassemblyjs "1.1.2-y.6"
"@webassemblyjs/wast-printer@^1.1.2-y.0":
version "1.1.2-y.0"
resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.1.2-y.0.tgz#9212f81e9e8b25a7d35f51d97f43b64c1e7eb655"
@ -4783,6 +4821,16 @@ webassemblyjs@1.1.2-y.0:
long "^3.2.0"
webassembly-floating-point-hex-parser "0.1.2"
webassemblyjs@1.1.2-y.6:
version "1.1.2-y.6"
resolved "https://registry.yarnpkg.com/webassemblyjs/-/webassemblyjs-1.1.2-y.6.tgz#6cf604bf52ecf7b2449ff370f3eb37ced001689e"
dependencies:
"@webassemblyjs/ast" "1.1.2-y.6"
"@webassemblyjs/wasm-parser" "1.1.2-y.6"
"@webassemblyjs/wast-parser" "1.1.2-y.6"
long "^3.2.0"
webassembly-floating-point-hex-parser "0.1.2"
webpack-dev-middleware@^1.9.0:
version "1.12.2"
resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-1.12.2.tgz#f8fc1120ce3b4fc5680ceecb43d777966b21105e"