Skip to content

Commit 32171f1

Browse files
authored
wasm2js: Support for exported memory (WebAssembly#3323)
The asmFunc now sets the outer scope's `bufferView` variable as well as its own internal views.
1 parent bb124f9 commit 32171f1

30 files changed

Lines changed: 247 additions & 242 deletions

src/wasm2js.h

Lines changed: 50 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,7 @@ Ref Wasm2JSBuilder::processWasm(Module* wasm, Name funcName) {
383383
ret[1]->push_back(asmFunc);
384384
ValueBuilder::appendArgumentToFunction(asmFunc, ENV);
385385

386+
// add memory import
386387
if (wasm->memory.exists) {
387388
if (wasm->memory.imported()) {
388389
// find memory and buffer in imports
@@ -414,8 +415,15 @@ Ref Wasm2JSBuilder::processWasm(Module* wasm, Name funcName) {
414415
ValueBuilder::makeName(WASM_MEMORY_GROW))));
415416
}
416417
} else {
417-
// find memory as third argument
418-
ValueBuilder::appendArgumentToFunction(asmFunc, BUFFER);
418+
Ref theVar = ValueBuilder::makeVar();
419+
asmFunc[3]->push_back(theVar);
420+
ValueBuilder::appendToVar(
421+
theVar,
422+
BUFFER,
423+
ValueBuilder::makeNew(ValueBuilder::makeCall(
424+
ValueBuilder::makeName("ArrayBuffer"),
425+
ValueBuilder::makeInt(Address::address32_t(wasm->memory.initial.addr *
426+
Memory::kPageSize)))));
419427
}
420428
}
421429

@@ -428,6 +436,7 @@ Ref Wasm2JSBuilder::processWasm(Module* wasm, Name funcName) {
428436
FUNCTION_TABLE,
429437
ValueBuilder::makeDot(ValueBuilder::makeName(ENV), wasm->table.base));
430438
}
439+
431440
// create heaps, etc
432441
addBasics(asmFunc[3], wasm);
433442
ModuleUtils::iterImportedFunctions(
@@ -503,6 +512,12 @@ void Wasm2JSBuilder::addBasics(Ref ast, Module* wasm) {
503512
addHeap(HEAPU32, UINT32ARRAY);
504513
addHeap(HEAPF32, FLOAT32ARRAY);
505514
addHeap(HEAPF64, FLOAT64ARRAY);
515+
if ((!wasm->memory.segments.empty()) || wasm->features.hasBulkMemory()) {
516+
ast->push_back(
517+
ValueBuilder::makeBinary(ValueBuilder::makeName("bufferView"),
518+
SET,
519+
ValueBuilder::makeName(HEAPU8)));
520+
}
506521
}
507522
// core asm.js imports
508523
auto addMath = [&](IString name, IString base) {
@@ -2299,12 +2314,6 @@ void Wasm2JSBuilder::addMemoryGrowFunc(Ref ast, Module* wasm) {
22992314
IString("set")),
23002315
ValueBuilder::makeName(HEAP8)));
23012316

2302-
ValueBuilder::appendToBlock(
2303-
block,
2304-
ValueBuilder::makeBinary(ValueBuilder::makeName(HEAP8),
2305-
SET,
2306-
ValueBuilder::makeName(IString("newHEAP8"))));
2307-
23082317
auto setHeap = [&](IString name, IString view) {
23092318
ValueBuilder::appendToBlock(
23102319
block,
@@ -2339,7 +2348,15 @@ void Wasm2JSBuilder::addMemoryGrowFunc(Ref ast, Module* wasm) {
23392348
ValueBuilder::makeDot(ValueBuilder::makeName("memory"),
23402349
ValueBuilder::makeName(BUFFER)),
23412350
SET,
2342-
ValueBuilder::makeName(IString("newBuffer"))));
2351+
ValueBuilder::makeName(BUFFER)));
2352+
}
2353+
2354+
if ((!wasm->memory.segments.empty()) || wasm->features.hasBulkMemory()) {
2355+
ValueBuilder::appendToBlock(
2356+
block,
2357+
ValueBuilder::makeBinary(ValueBuilder::makeName("bufferView"),
2358+
SET,
2359+
ValueBuilder::makeName(HEAPU8)));
23432360
}
23442361

23452362
memoryGrowFunc[3]->push_back(
@@ -2373,8 +2390,7 @@ class Wasm2JSGlue {
23732390
void emitPostEmscripten();
23742391
void emitPostES6();
23752392

2376-
void emitMemory(std::string buffer,
2377-
std::function<std::string(std::string)> accessGlobal);
2393+
void emitMemory(std::function<std::string(std::string)> accessGlobal);
23782394
void emitSpecialSupport();
23792395
};
23802396

@@ -2410,7 +2426,7 @@ void Wasm2JSGlue::emitPre() {
24102426
}
24112427

24122428
void Wasm2JSGlue::emitPreEmscripten() {
2413-
out << "function instantiate(asmLibraryArg, wasmMemory) {\n";
2429+
out << "function instantiate(asmLibraryArg) {\n";
24142430
}
24152431

24162432
void Wasm2JSGlue::emitPreES6() {
@@ -2449,6 +2465,18 @@ void Wasm2JSGlue::emitPreES6() {
24492465
}
24502466

24512467
void Wasm2JSGlue::emitPost() {
2468+
// Create a helper bufferView to access the buffer if we need one. We use it
2469+
// for creating memory segments if we have any (we may not if the segments are
2470+
// shipped in a side .mem file, for example), and also in bulk memory
2471+
// operations.
2472+
// This will get assigned during `asmFunc` (and potentially re-assigned
2473+
// during __wasm_memory_grow).
2474+
// TODO: We should probably just share a single HEAPU8 var.
2475+
if (wasm.memory.exists &&
2476+
((!wasm.memory.segments.empty()) || wasm.features.hasBulkMemory())) {
2477+
out << "var bufferView;\n";
2478+
}
2479+
24522480
if (flags.emscripten) {
24532481
emitPostEmscripten();
24542482
} else {
@@ -2457,13 +2485,13 @@ void Wasm2JSGlue::emitPost() {
24572485
}
24582486

24592487
void Wasm2JSGlue::emitPostEmscripten() {
2460-
emitMemory("wasmMemory.buffer", [](std::string globalName) {
2488+
out << "var exports = asmFunc(asmLibraryArg);\n";
2489+
2490+
emitMemory([](std::string globalName) {
24612491
return std::string("asmLibraryArg['") + asmangle(globalName) + "']";
24622492
});
24632493

2464-
out << "return asmFunc(asmLibraryArg, wasmMemory.buffer)\n"
2465-
<< "\n"
2466-
<< "}";
2494+
out << "return exports;\n}";
24672495
}
24682496

24692497
void Wasm2JSGlue::emitPostES6() {
@@ -2473,12 +2501,9 @@ void Wasm2JSGlue::emitPostES6() {
24732501
//
24742502
// Note that the translation here expects that the lower values of this memory
24752503
// can be used for conversions, so make sure there's at least one page.
2476-
if (wasm.memory.exists) {
2504+
if (wasm.memory.exists && wasm.memory.imported()) {
24772505
out << "var mem" << moduleName.str << " = new ArrayBuffer("
24782506
<< wasm.memory.initial.addr * Memory::kPageSize << ");\n";
2479-
2480-
emitMemory(std::string("mem") + moduleName.str,
2481-
[](std::string globalName) { return globalName; });
24822507
}
24832508

24842509
// Actually invoke the `asmFunc` generated function, passing in all global
@@ -2514,10 +2539,10 @@ void Wasm2JSGlue::emitPostES6() {
25142539
out << ",\n " << asmangle(import->base.str);
25152540
});
25162541

2517-
if (wasm.memory.exists && !wasm.memory.imported()) {
2518-
out << "\n },\n mem" << moduleName.str << "\n);\n";
2519-
} else {
2520-
out << "\n });\n";
2542+
out << "\n });\n";
2543+
2544+
if (wasm.memory.exists) {
2545+
emitMemory([](std::string globalName) { return globalName; });
25212546
}
25222547

25232548
if (flags.allowAsserts) {
@@ -2550,21 +2575,10 @@ void Wasm2JSGlue::emitPostES6() {
25502575
}
25512576

25522577
void Wasm2JSGlue::emitMemory(
2553-
std::string buffer,
25542578
std::function<std::string(std::string)> accessGlobal) {
2555-
if (!wasm.memory.exists) {
2556-
return;
2557-
}
2558-
// Create a helper bufferView to access the buffer if we need one. We use it
2559-
// for creating memory segments if we have any (we may not if the segments are
2560-
// shipped in a side .mem file, for example), and also in bulk memory
2561-
// operations.
2562-
if (!wasm.memory.segments.empty() || wasm.features.hasBulkMemory()) {
2563-
out << "var bufferView = new Uint8Array(" << buffer << ");\n";
2564-
}
25652579
// If there are no memory segments, we don't need to emit any support code for
25662580
// segment creation.
2567-
if (wasm.memory.segments.empty()) {
2581+
if ((!wasm.memory.exists) || wasm.memory.segments.empty()) {
25682582
return;
25692583
}
25702584

test/wasm2js/atomic_fence.2asm.js

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11

2-
function asmFunc(env, buffer) {
2+
function asmFunc(env) {
3+
var buffer = new ArrayBuffer(1507328);
34
var HEAP8 = new Int8Array(buffer);
45
var HEAP16 = new Int16Array(buffer);
56
var HEAP32 = new Int32Array(buffer);
@@ -8,6 +9,7 @@ function asmFunc(env, buffer) {
89
var HEAPU32 = new Uint32Array(buffer);
910
var HEAPF32 = new Float32Array(buffer);
1011
var HEAPF64 = new Float64Array(buffer);
12+
bufferView = HEAPU8;
1113
var Math_imul = Math.imul;
1214
var Math_fround = Math.fround;
1315
var Math_abs = Math.abs;
@@ -37,7 +39,6 @@ function asmFunc(env, buffer) {
3739
var newBuffer = new ArrayBuffer(Math_imul(newPages, 65536));
3840
var newHEAP8 = new Int8Array(newBuffer);
3941
newHEAP8.set(HEAP8);
40-
HEAP8 = newHEAP8;
4142
HEAP8 = new Int8Array(newBuffer);
4243
HEAP16 = new Int16Array(newBuffer);
4344
HEAP32 = new Int32Array(newBuffer);
@@ -47,6 +48,7 @@ function asmFunc(env, buffer) {
4748
HEAPF32 = new Float32Array(newBuffer);
4849
HEAPF64 = new Float64Array(newBuffer);
4950
buffer = newBuffer;
51+
bufferView = HEAPU8;
5052
}
5153
return oldPages;
5254
}
@@ -56,10 +58,7 @@ function asmFunc(env, buffer) {
5658
};
5759
}
5860

59-
var memasmFunc = new ArrayBuffer(1507328);
60-
var bufferView = new Uint8Array(memasmFunc);
61+
var bufferView;
6162
var retasmFunc = asmFunc( { abort: function() { throw new Error('abort'); }
62-
},
63-
memasmFunc
64-
);
63+
});
6564
export var atomic_fence = retasmFunc.atomic_fence;

test/wasm2js/atomics_32.2asm.js

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@
6767

6868
var memorySegments = {};
6969

70-
function asmFunc(env, buffer) {
70+
function asmFunc(env) {
71+
var buffer = new ArrayBuffer(16777216);
7172
var HEAP8 = new Int8Array(buffer);
7273
var HEAP16 = new Int16Array(buffer);
7374
var HEAP32 = new Int32Array(buffer);
@@ -76,6 +77,7 @@ function asmFunc(env, buffer) {
7677
var HEAPU32 = new Uint32Array(buffer);
7778
var HEAPF32 = new Float32Array(buffer);
7879
var HEAPF64 = new Float64Array(buffer);
80+
bufferView = HEAPU8;
7981
var Math_imul = Math.imul;
8082
var Math_fround = Math.fround;
8183
var Math_abs = Math.abs;
@@ -129,8 +131,9 @@ function asmFunc(env, buffer) {
129131
};
130132
}
131133

132-
var memasmFunc = new ArrayBuffer(16777216);
133-
var bufferView = new Uint8Array(memasmFunc);
134+
var bufferView;
135+
var retasmFunc = asmFunc( { abort: function() { throw new Error('abort'); }
136+
});
134137
for (var base64ReverseLookup = new Uint8Array(123/*'z'+1*/), i = 25; i >= 0; --i) {
135138
base64ReverseLookup[48+i] = 52+i; // '0-9'
136139
base64ReverseLookup[65+i] = i; // 'A-Z'
@@ -152,8 +155,4 @@ for (var base64ReverseLookup = new Uint8Array(123/*'z'+1*/), i = 25; i >= 0; --i
152155
}
153156
memorySegments[0] = base64DecodeToExistingUint8Array(new Uint8Array(6), 0, "aGVsbG8s");
154157
memorySegments[1] = base64DecodeToExistingUint8Array(new Uint8Array(6), 0, "d29ybGQh");
155-
var retasmFunc = asmFunc( { abort: function() { throw new Error('abort'); }
156-
},
157-
memasmFunc
158-
);
159158
export var test = retasmFunc.test;

test/wasm2js/atomics_32.2asm.js.opt

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@
6767

6868
var memorySegments = {};
6969

70-
function asmFunc(env, buffer) {
70+
function asmFunc(env) {
71+
var buffer = new ArrayBuffer(16777216);
7172
var HEAP8 = new Int8Array(buffer);
7273
var HEAP16 = new Int16Array(buffer);
7374
var HEAP32 = new Int32Array(buffer);
@@ -76,6 +77,7 @@ function asmFunc(env, buffer) {
7677
var HEAPU32 = new Uint32Array(buffer);
7778
var HEAPF32 = new Float32Array(buffer);
7879
var HEAPF64 = new Float64Array(buffer);
80+
bufferView = HEAPU8;
7981
var Math_imul = Math.imul;
8082
var Math_fround = Math.fround;
8183
var Math_abs = Math.abs;
@@ -125,8 +127,9 @@ function asmFunc(env, buffer) {
125127
};
126128
}
127129

128-
var memasmFunc = new ArrayBuffer(16777216);
129-
var bufferView = new Uint8Array(memasmFunc);
130+
var bufferView;
131+
var retasmFunc = asmFunc( { abort: function() { throw new Error('abort'); }
132+
});
130133
for (var base64ReverseLookup = new Uint8Array(123/*'z'+1*/), i = 25; i >= 0; --i) {
131134
base64ReverseLookup[48+i] = 52+i; // '0-9'
132135
base64ReverseLookup[65+i] = i; // 'A-Z'
@@ -148,8 +151,4 @@ for (var base64ReverseLookup = new Uint8Array(123/*'z'+1*/), i = 25; i >= 0; --i
148151
}
149152
memorySegments[0] = base64DecodeToExistingUint8Array(new Uint8Array(6), 0, "aGVsbG8s");
150153
memorySegments[1] = base64DecodeToExistingUint8Array(new Uint8Array(6), 0, "d29ybGQh");
151-
var retasmFunc = asmFunc( { abort: function() { throw new Error('abort'); }
152-
},
153-
memasmFunc
154-
);
155154
export var test = retasmFunc.test;

0 commit comments

Comments
 (0)