diff --git a/src/lib/libaddfunction.js b/src/lib/libaddfunction.js index 6dcd2fdc86575..eaf93f9ef963b 100644 --- a/src/lib/libaddfunction.js +++ b/src/lib/libaddfunction.js @@ -7,19 +7,20 @@ addToLibrary({ // This gives correct answers for everything less than 2^{14} = 16384 // I hope nobody is contemplating functions with 16384 arguments... - $uleb128Encode: (n, target) => { + $uleb128EncodeWithLen__internal: true, + $uleb128EncodeWithLen: (arr) => { + const n = arr.length; #if ASSERTIONS assert(n < 16384); #endif - if (n < 128) { - target.push(n); - } else { - target.push((n % 128) | 128, n >> 7); - } + // Note: this LEB128 length encoding produces extra byte for n < 128, + // but we don't care as it's only used in a temporary representation. + return [(n % 128) | 128, n >> 7, ...arr]; }, #if WASM_JS_TYPES // Converts a signature like 'vii' into a description of the wasm types, like // { parameters: ['i32', 'i32'], results: [] }. + $sigToWasmTypes__internal: true, $sigToWasmTypes: (sig) => { #if ASSERTIONS && !WASM_BIGINT assert(!sig.includes('j'), 'i64 not permitted in function signatures when WASM_BIGINT is disabled'); @@ -49,49 +50,41 @@ addToLibrary({ return type; }, #endif - $generateFuncType__deps: ['$uleb128Encode'], - $generateFuncType: (sig, target) => { - var sigRet = sig.slice(0, 1); - var sigParam = sig.slice(1); - var typeCodes = { - 'i': 0x7f, // i32 + $wasmTypeCodes__internal: true, + // Note: using template literal here instead of plain object + // because jsify serializes objects w/o quotes and Closure will then + // incorrectly mangle the properties. + $wasmTypeCodes: `{ + 'i': 0x7f, // i32 #if MEMORY64 - 'p': 0x7e, // i64 + 'p': 0x7e, // i64 #else - 'p': 0x7f, // i32 + 'p': 0x7f, // i32 #endif - 'j': 0x7e, // i64 - 'f': 0x7d, // f32 - 'd': 0x7c, // f64 - 'e': 0x6f, // externref - }; - - // Parameters, length + signatures - target.push(0x60 /* form: func */); - uleb128Encode(sigParam.length, target); - for (var paramType of sigParam) { + 'j': 0x7e, // i64 + 'f': 0x7d, // f32 + 'd': 0x7c, // f64 + 'e': 0x6f, // externref + }`, + + $generateTypePack__internal: true, + $generateTypePack__deps: ['$uleb128EncodeWithLen', '$wasmTypeCodes'], + $generateTypePack: (types) => uleb128EncodeWithLen(Array.from(types, (type) => { + var code = wasmTypeCodes[type]; #if ASSERTIONS - assert(paramType in typeCodes, `invalid signature char: ${paramType}`); + assert(code, `invalid signature char: ${type}`); #endif - target.push(typeCodes[paramType]); - } + return code; + })), - // Return values, length + signatures - // With no multi-return in MVP, either 0 (void) or 1 (anything else) - if (sigRet == 'v') { - target.push(0x00); - } else { - target.push(0x01, typeCodes[sigRet]); - } - }, // Wraps a JS function as a wasm function with a given signature. #if !WASM2JS $convertJsFunctionToWasm__deps: [ - '$uleb128Encode', + '$uleb128EncodeWithLen', #if WASM_JS_TYPES '$sigToWasmTypes', #endif - '$generateFuncType' + '$generateTypePack' ], #endif $convertJsFunctionToWasm: (func, sig) => { @@ -111,25 +104,23 @@ addToLibrary({ return new WebAssembly.Function(sigToWasmTypes(sig), func); } #endif - // The module is static, with the exception of the type section, which is - // generated based on the signature passed in. - var typeSectionBody = [ - 0x01, // count: 1 - ]; - generateFuncType(sig, typeSectionBody); // Rest of the module is static - var bytes = [ + var bytes = Uint8Array.of( 0x00, 0x61, 0x73, 0x6d, // magic ("\0asm") 0x01, 0x00, 0x00, 0x00, // version: 1 0x01, // Type section code - ]; - // Write the overall length of the type section followed by the body - uleb128Encode(typeSectionBody.length, bytes); - bytes.push(...typeSectionBody); - - // The rest of the module is static - bytes.push( + // The module is static, with the exception of the type section, which is + // generated based on the signature passed in. + ...uleb128EncodeWithLen([ + 0x01, // count: 1 + 0x60 /* form: func */, + // param types + ...generateTypePack(sig.slice(1)), + // return types (for now only supporting [] if `void` and single [T] otherwise) + ...generateTypePack(sig[0] === 'v' ? '' : sig[0]) + ]), + // The rest of the module is static 0x02, 0x07, // import section // (import "e" "f" (func 0 (type 0))) 0x01, 0x01, 0x65, 0x01, 0x66, 0x00, 0x00, @@ -140,7 +131,7 @@ addToLibrary({ // We can compile this wasm module synchronously because it is very small. // This accepts an import (at "e.f"), that it reroutes to an export (at "f") - var module = new WebAssembly.Module(new Uint8Array(bytes)); + var module = new WebAssembly.Module(bytes); var instance = new WebAssembly.Instance(module, { 'e': { 'f': func } }); var wrappedFunc = instance.exports['f']; return wrappedFunc; @@ -158,17 +149,19 @@ addToLibrary({ if (freeTableIndexes.length) { return freeTableIndexes.pop(); } - // Grow the table +#if ASSERTIONS try { - /** @suppress {checkTypes} */ - wasmTable.grow({{{ toIndexType('1') }}}); + #endif + // Grow the table + return wasmTable['grow']({{{ toIndexType('1') }}}); +#if ASSERTIONS } catch (err) { if (!(err instanceof RangeError)) { throw err; } throw 'Unable to grow wasm table. Set ALLOW_TABLE_GROWTH.'; } - return {{{ from64Expr('wasmTable.length') }}} - 1; +#endif }, $updateTableMap__deps: ['$getWasmTableEntry'], diff --git a/src/lib/libexports.js b/src/lib/libexports.js index 062d70d2a87c0..0ccf93e436249 100644 --- a/src/lib/libexports.js +++ b/src/lib/libexports.js @@ -13,11 +13,8 @@ addToLibrary({ if (name[0] == '_') name = name.slice(1); var exportedFunc = wasmExports[name]; if (exportedFunc) { - // Record the created function pointer to each function object, - // so that if the same function pointer is obtained several times, - // the same address will be returned. - exportedFunc.ptr ||= addFunction(exportedFunc); - return exportedFunc.ptr; + // Note: addFunction automatically caches the created function pointer. + return addFunction(exportedFunc); } #if ASSERTIONS err(`No exported function found by name "{exportedFunc}"`); diff --git a/test/other/codesize/test_codesize_hello_O0.gzsize b/test/other/codesize/test_codesize_hello_O0.gzsize index 1d7bdf0051254..9c8bcfc9f63d7 100644 --- a/test/other/codesize/test_codesize_hello_O0.gzsize +++ b/test/other/codesize/test_codesize_hello_O0.gzsize @@ -1 +1 @@ -8337 +8319 diff --git a/test/other/codesize/test_codesize_hello_O0.jssize b/test/other/codesize/test_codesize_hello_O0.jssize index ae2d95929cd70..e5a981de8ef40 100644 --- a/test/other/codesize/test_codesize_hello_O0.jssize +++ b/test/other/codesize/test_codesize_hello_O0.jssize @@ -1 +1 @@ -22420 +22389 diff --git a/test/other/codesize/test_codesize_hello_dylink.gzsize b/test/other/codesize/test_codesize_hello_dylink.gzsize index b40059dff3b33..582e5b29c4c30 100644 --- a/test/other/codesize/test_codesize_hello_dylink.gzsize +++ b/test/other/codesize/test_codesize_hello_dylink.gzsize @@ -1 +1 @@ -11568 +11482 diff --git a/test/other/codesize/test_codesize_hello_dylink.jssize b/test/other/codesize/test_codesize_hello_dylink.jssize index d8a6faac5143a..47cfb062ee084 100644 --- a/test/other/codesize/test_codesize_hello_dylink.jssize +++ b/test/other/codesize/test_codesize_hello_dylink.jssize @@ -1 +1 @@ -27314 +27075 diff --git a/test/other/codesize/test_codesize_minimal_O0.expected.js b/test/other/codesize/test_codesize_minimal_O0.expected.js index f5ebe4cceb97c..3bcd46da675ff 100644 --- a/test/other/codesize/test_codesize_minimal_O0.expected.js +++ b/test/other/codesize/test_codesize_minimal_O0.expected.js @@ -925,8 +925,6 @@ Module['FS_createPreloadedFile'] = FS.createPreloadedFile; 'ASSERTIONS', 'ccall', 'cwrap', - 'uleb128Encode', - 'generateFuncType', 'convertJsFunctionToWasm', 'getEmptyTableSlot', 'updateTableMap', diff --git a/test/other/codesize/test_codesize_minimal_O0.gzsize b/test/other/codesize/test_codesize_minimal_O0.gzsize index 50b4cb68cc3dd..b411359393386 100644 --- a/test/other/codesize/test_codesize_minimal_O0.gzsize +++ b/test/other/codesize/test_codesize_minimal_O0.gzsize @@ -1 +1 @@ -6632 +6614 diff --git a/test/other/codesize/test_codesize_minimal_O0.jssize b/test/other/codesize/test_codesize_minimal_O0.jssize index 69a914f0d2d8f..8b7d4198a7095 100644 --- a/test/other/codesize/test_codesize_minimal_O0.jssize +++ b/test/other/codesize/test_codesize_minimal_O0.jssize @@ -1 +1 @@ -17683 +17652 diff --git a/test/other/test_unoptimized_code_size.js.size b/test/other/test_unoptimized_code_size.js.size index 2813a74486589..9486f81d383c6 100644 --- a/test/other/test_unoptimized_code_size.js.size +++ b/test/other/test_unoptimized_code_size.js.size @@ -1 +1 @@ -54162 +54121 diff --git a/test/other/test_unoptimized_code_size_strict.js.size b/test/other/test_unoptimized_code_size_strict.js.size index 7228df63718d7..85eb753232dcc 100644 --- a/test/other/test_unoptimized_code_size_strict.js.size +++ b/test/other/test_unoptimized_code_size_strict.js.size @@ -1 +1 @@ -52212 +52171