diff options
Diffstat (limited to 'src/wasm2js.h')
-rw-r--r-- | src/wasm2js.h | 48 |
1 files changed, 26 insertions, 22 deletions
diff --git a/src/wasm2js.h b/src/wasm2js.h index 802765b1a..b91056ae8 100644 --- a/src/wasm2js.h +++ b/src/wasm2js.h @@ -2247,26 +2247,28 @@ void Wasm2JSGlue::emitMemory( return; } - auto expr = R"( - function(mem) { - var _mem = new Uint8Array(mem); - return function(offset, s) { - var bytes, i; - if (typeof Buffer === 'undefined') { - bytes = atob(s); - for (i = 0; i < bytes.length; i++) - _mem[offset + i] = bytes.charCodeAt(i); - } else { - bytes = Buffer.from(s, 'base64'); - for (i = 0; i < bytes.length; i++) - _mem[offset + i] = bytes[i]; - } - } - } - )"; - - // var assign$name = ($expr)(mem$name); - out << "var " << segmentWriter << " = (" << expr << ")(" << buffer << ");\n"; + auto expr = + R"(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; // '/' + /** @noinline Inlining this function would mean expanding the base64 string 4x times in the source code, which Closure seems to be happy to do. */ + function base64DecodeToExistingUint8Array(uint8Array, offset, b64) { + var b1, b2, i = 0, j = offset, bLength = b64.length, end = offset + (bLength*3>>2); + if (b64[bLength-2] == '=') --end; + if (b64[bLength-1] == '=') --end; + for (; i < bLength; i += 4, j += 3) { + b1 = base64ReverseLookup[b64.charCodeAt(i+1)]; + b2 = base64ReverseLookup[b64.charCodeAt(i+2)]; + uint8Array[j] = base64ReverseLookup[b64.charCodeAt(i)] << 2 | b1 >> 4; + if (j+1 < end) uint8Array[j+1] = b1 << 4 | b2 >> 2; + if (j+2 < end) uint8Array[j+2] = b2 << 6 | base64ReverseLookup[b64.charCodeAt(i+3)]; + } + })"; + out << expr << '\n'; auto globalOffset = [&](const Memory::Segment& segment) { if (auto* c = segment.offset->dynCast<Const>()) { @@ -2280,10 +2282,12 @@ void Wasm2JSGlue::emitMemory( Fatal() << "non-constant offsets aren't supported yet\n"; }; + out << "var bufferView = new Uint8Array(" << buffer << ");\n"; + for (auto& seg : wasm.memory.segments) { assert(!seg.isPassive && "passive segments not implemented yet"); - out << segmentWriter << "(" << globalOffset(seg) << ", \"" - << base64Encode(seg.data) << "\");\n"; + out << "base64DecodeToExistingUint8Array(bufferView, " << globalOffset(seg) + << ", \"" << base64Encode(seg.data) << "\");\n"; } } |