Skip to content

Commit

Permalink
Merge base64Decode.js and base64Utils.js into library_base64.js
Browse files Browse the repository at this point in the history
The optimized base64Decode was only being using by minimal runtime.
After this change it used in the regular runtime too which should speed
up decoding.
  • Loading branch information
sbc100 committed Feb 27, 2024
1 parent a3b9509 commit 576f2a0
Show file tree
Hide file tree
Showing 13 changed files with 89 additions and 133 deletions.
2 changes: 0 additions & 2 deletions .eslintrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,6 @@ ignorePatterns:
- "src/settings_internal.js"
- "src/arrayUtils.js"
- "src/deterministic.js"
- "src/base64Utils.js"
- "src/base64Decode.js"
- "src/proxyWorker.js"
- "src/proxyClient.js"
- "src/IDBStore.js"
Expand Down
60 changes: 0 additions & 60 deletions src/base64Decode.js

This file was deleted.

36 changes: 0 additions & 36 deletions src/base64Utils.js

This file was deleted.

57 changes: 57 additions & 0 deletions src/library_base64.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/**
* @license
* Copyright 2020 The Emscripten Authors
* SPDX-License-Identifier: MIT
*/

addToLibrary({
// Decodes a _known valid_ base64 string (without validation) and returns it as a new Uint8Array.
// Benchmarked to be around 5x faster compared to a simple
// "Uint8Array.from(atob(b64), c => c.charCodeAt(0))" (TODO: perhaps use this form in -Oz builds?)
$base64Decode__postset: `
// Precreate a reverse lookup table from chars
// "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" back to
// bytes to make decoding fast.
for (var base64ReverseLookup = new Uint8Array(123/*'z'+1*/), i = 25; i >= 0; --i) {
base64ReverseLookup[48+i] = 52+i; // '0-9'
base64ReverseLookup[65+i] = i; // 'A-Z'
base64ReverseLookup[97+i] = 26+i; // 'a-z'
}
base64ReverseLookup[43] = 62; // '+'
base64ReverseLookup[47] = 63; // '/'
`,
$base64Decode__docs: '/** @noinline */',
$base64Decode: (b64) => {
#if ENVIRONMENT_MAY_BE_NODE
if (ENVIRONMENT_IS_NODE) {
var buf = Buffer.from(b64, 'base64');
return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
}
#endif

#if ASSERTIONS
assert(b64.length % 4 == 0);
#endif
var b1, b2, i = 0, j = 0, bLength = b64.length;
var output = new Uint8Array((bLength*3>>2) - (b64[bLength-2] == '=') - (b64[bLength-1] == '='));
for (; i < bLength; i += 4, j += 3) {
b1 = base64ReverseLookup[b64.charCodeAt(i+1)];
b2 = base64ReverseLookup[b64.charCodeAt(i+2)];
output[j] = base64ReverseLookup[b64.charCodeAt(i)] << 2 | b1 >> 4;
output[j+1] = b1 << 4 | b2 >> 2;
output[j+2] = b2 << 6 | base64ReverseLookup[b64.charCodeAt(i+3)];
}
return output;
},

// If filename is a base64 data URI, parses and returns data (Buffer on node,
// Uint8Array otherwise). If filename is not a base64 data URI, returns
// undefined.
$tryParseAsDataURI: (filename) => {
if (isDataURI(filename)) {
return base64Decode(filename.slice(dataURIPrefix.length));
}
},

$intArrayFromBase64: 'intArrayFromBase64',
});
9 changes: 4 additions & 5 deletions src/modules.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ globalThis.LibraryManager = {
libraries.push('library_memoryprofiler.js');
}

if (SUPPORT_BASE64_EMBEDDING) {
libraries.push('library_base64.js');
}

if (AUTODEBUG) {
libraries.push('library_autodebug.js');
}
Expand Down Expand Up @@ -416,11 +420,6 @@ function exportRuntime() {
runtimeElements.push('checkStackCookie');
}

if (SUPPORT_BASE64_EMBEDDING) {
runtimeElements.push('intArrayFromBase64');
runtimeElements.push('tryParseAsDataURI');
}

if (RETAIN_COMPILER_SETTINGS) {
runtimeElements.push('getCompilerSetting')
}
Expand Down
4 changes: 4 additions & 0 deletions src/postamble_minimal.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ function initRuntime(wasmExports) {

// Initialize wasm (asynchronous)

#if SINGLE_FILE && WASM == 1 && !WASM2JS
Module['wasm'] = base64Decode('<<< WASM_BINARY_DATA >>>');
#endif

var imports = {
#if MINIFY_WASM_IMPORTED_MODULES
'a': wasmImports,
Expand Down
4 changes: 0 additions & 4 deletions src/preamble.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,6 @@ if (typeof WebAssembly != 'object') {
#include "runtime_asan.js"
#endif

#if SUPPORT_BASE64_EMBEDDING || FORCE_FILESYSTEM
#include "base64Utils.js"
#endif

// Wasm globals

var wasmMemory;
Expand Down
5 changes: 0 additions & 5 deletions src/preamble_minimal.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,6 @@ if (Module['doWasm2JS']) {
#endif
#endif

#if SINGLE_FILE && WASM == 1 && !WASM2JS
#include "base64Decode.js"
Module['wasm'] = base64Decode('<<< WASM_BINARY_DATA >>>');
#endif

var HEAP8, HEAP16, HEAP32, HEAPU8, HEAPU16, HEAPU32, HEAPF32, HEAPF64,
#if WASM_BIGINT
HEAP64, HEAPU64,
Expand Down
2 changes: 1 addition & 1 deletion src/settings_internal.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ var SOURCE_MAP_BASE = '';
// this setting will always be true.
var MEM_INIT_IN_WASM = true;

// If set to 1, src/base64Utils.js will be included in the bundle.
// If set to 1 then base64 decoding functions will be included in the bundle.
// This is set internally when needed (SINGLE_FILE)
var SUPPORT_BASE64_EMBEDDING = false;

Expand Down
4 changes: 4 additions & 0 deletions src/shell.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ var Module = typeof {{{ EXPORT_NAME }}} != 'undefined' ? {{{ EXPORT_NAME }}} : {
// See https://caniuse.com/mdn-javascript_builtins_bigint64array
#include "polyfill/bigint64array.js"
#endif

#if SUPPORT_BASE64_EMBEDDING && (ENVIRONMENT_MAY_BE_SHELL || (ENVIRONMENT_MAY_BE_NODE && MIN_NODE_VERSION < 160000))
#include "polyfill/atob.js"
#endif
#endif // POLYFILL

#if MODULARIZE
Expand Down
8 changes: 4 additions & 4 deletions test/code_size/random_printf_wasm.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"a.html": 12734,
"a.html.gz": 6968,
"total": 12734,
"total_gz": 6968
"a.html": 12723,
"a.html.gz": 6958,
"total": 12723,
"total_gz": 6958
}
8 changes: 4 additions & 4 deletions test/code_size/random_printf_wasm2js.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"a.html": 17275,
"a.html.gz": 7537,
"total": 17275,
"total_gz": 7537
"a.html": 17371,
"a.html.gz": 7580,
"total": 17371,
"total_gz": 7580
}
23 changes: 11 additions & 12 deletions tools/link.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,14 +193,6 @@ def setup_environment_settings():
exit_with_error('when building with multithreading enabled and a "-sENVIRONMENT=" directive is specified, it must include "worker" as a target! (Try e.g. -sENVIRONMENT=web,worker)')


def embed_memfile(options):
return (settings.SINGLE_FILE or
(settings.WASM2JS and not options.memory_init_file and
(not settings.MAIN_MODULE and
not settings.SIDE_MODULE and
not settings.GENERATE_SOURCE_MAP)))


def generate_js_sym_info():
# Runs the js compiler to generate a list of all symbols available in the JS
# libraries. This must be done separately for each linker invocation since the
Expand Down Expand Up @@ -1796,6 +1788,15 @@ def get_full_import_name(name):
if settings.USE_CLOSURE_COMPILER or not settings.MINIFY_WHITESPACE:
settings.MAYBE_CLOSURE_COMPILER = 1

if (settings.SINGLE_FILE or (settings.WASM2JS and not options.memory_init_file and
(not settings.MAIN_MODULE and
not settings.SIDE_MODULE and
not settings.GENERATE_SOURCE_MAP))):
settings.SUPPORT_BASE64_EMBEDDING = 1
settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE.append('$base64Decode')
if not settings.MINIMAL_RUNTIME:
settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE.append('$tryParseAsDataURI')

return target, wasm_target


Expand Down Expand Up @@ -1870,8 +1871,6 @@ def phase_emscript(options, in_wasm, wasm_target, js_syms):
# Emscripten
logger.debug('emscript')

settings.SUPPORT_BASE64_EMBEDDING = embed_memfile(options)

if shared.SKIP_SUBPROCS:
return

Expand Down Expand Up @@ -2080,7 +2079,7 @@ def phase_final_emitting(options, state, target, wasm_target, memfile):
elif settings.PROXY_TO_WORKER:
generate_worker_js(target, js_target, target_basename)

if embed_memfile(options) and memfile:
if memfile and (settings.SINGLE_FILE or (settings.WASM2JS and not options.memory_init_file)):
delete_file(memfile)

if settings.SPLIT_MODULE:
Expand Down Expand Up @@ -2446,7 +2445,7 @@ def generate_traditional_runtime_html(target, options, js_target, target_basenam
}
'''
# add required helper functions such as tryParseAsDataURI
for filename in ('arrayUtils.js', 'base64Utils.js', 'URIUtils.js'):
for filename in ('arrayUtils.js', 'URIUtils.js'):
content = shared.read_and_preprocess(utils.path_from_root('src', filename))
script.inline = content + script.inline

Expand Down

0 comments on commit 576f2a0

Please sign in to comment.