Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 50 additions & 36 deletions src/wasm2js.h
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,7 @@ Ref Wasm2JSBuilder::processWasm(Module* wasm, Name funcName) {
ret[1]->push_back(asmFunc);
ValueBuilder::appendArgumentToFunction(asmFunc, ENV);

// add memory import
if (wasm->memory.exists) {
if (wasm->memory.imported()) {
// find memory and buffer in imports
Expand Down Expand Up @@ -414,8 +415,15 @@ Ref Wasm2JSBuilder::processWasm(Module* wasm, Name funcName) {
ValueBuilder::makeName(WASM_MEMORY_GROW))));
}
} else {
// find memory as third argument
ValueBuilder::appendArgumentToFunction(asmFunc, BUFFER);
Ref theVar = ValueBuilder::makeVar();
asmFunc[3]->push_back(theVar);
ValueBuilder::appendToVar(
theVar,
BUFFER,
ValueBuilder::makeNew(ValueBuilder::makeCall(
ValueBuilder::makeName("ArrayBuffer"),
ValueBuilder::makeInt(Address::address32_t(wasm->memory.initial.addr *
Memory::kPageSize)))));
}
}

Expand All @@ -428,6 +436,7 @@ Ref Wasm2JSBuilder::processWasm(Module* wasm, Name funcName) {
FUNCTION_TABLE,
ValueBuilder::makeDot(ValueBuilder::makeName(ENV), wasm->table.base));
}

// create heaps, etc
addBasics(asmFunc[3], wasm);
ModuleUtils::iterImportedFunctions(
Expand Down Expand Up @@ -503,6 +512,12 @@ void Wasm2JSBuilder::addBasics(Ref ast, Module* wasm) {
addHeap(HEAPU32, UINT32ARRAY);
addHeap(HEAPF32, FLOAT32ARRAY);
addHeap(HEAPF64, FLOAT64ARRAY);
if ((!wasm->memory.segments.empty()) || wasm->features.hasBulkMemory()) {
ast->push_back(
ValueBuilder::makeBinary(ValueBuilder::makeName("bufferView"),
SET,
ValueBuilder::makeName(HEAPU8)));
}
}
// core asm.js imports
auto addMath = [&](IString name, IString base) {
Expand Down Expand Up @@ -2295,12 +2310,6 @@ void Wasm2JSBuilder::addMemoryGrowFunc(Ref ast, Module* wasm) {
IString("set")),
ValueBuilder::makeName(HEAP8)));

ValueBuilder::appendToBlock(
block,
ValueBuilder::makeBinary(ValueBuilder::makeName(HEAP8),
SET,
ValueBuilder::makeName(IString("newHEAP8"))));

auto setHeap = [&](IString name, IString view) {
ValueBuilder::appendToBlock(
block,
Expand Down Expand Up @@ -2335,7 +2344,15 @@ void Wasm2JSBuilder::addMemoryGrowFunc(Ref ast, Module* wasm) {
ValueBuilder::makeDot(ValueBuilder::makeName("memory"),
ValueBuilder::makeName(BUFFER)),
SET,
ValueBuilder::makeName(IString("newBuffer"))));
ValueBuilder::makeName(BUFFER)));
}

if ((!wasm->memory.segments.empty()) || wasm->features.hasBulkMemory()) {
ValueBuilder::appendToBlock(
block,
ValueBuilder::makeBinary(ValueBuilder::makeName("bufferView"),
SET,
ValueBuilder::makeName(HEAPU8)));
}

memoryGrowFunc[3]->push_back(
Expand Down Expand Up @@ -2369,8 +2386,7 @@ class Wasm2JSGlue {
void emitPostEmscripten();
void emitPostES6();

void emitMemory(std::string buffer,
std::function<std::string(std::string)> accessGlobal);
void emitMemory(std::function<std::string(std::string)> accessGlobal);
void emitSpecialSupport();
};

Expand Down Expand Up @@ -2406,7 +2422,7 @@ void Wasm2JSGlue::emitPre() {
}

void Wasm2JSGlue::emitPreEmscripten() {
out << "function instantiate(asmLibraryArg, wasmMemory) {\n";
out << "function instantiate(asmLibraryArg) {\n";
}

void Wasm2JSGlue::emitPreES6() {
Expand Down Expand Up @@ -2445,6 +2461,18 @@ void Wasm2JSGlue::emitPreES6() {
}

void Wasm2JSGlue::emitPost() {
// Create a helper bufferView to access the buffer if we need one. We use it
// for creating memory segments if we have any (we may not if the segments are
// shipped in a side .mem file, for example), and also in bulk memory
// operations.
// This will get assigned during `asmFunc` (and potentially re-assigned
// during __wasm_memory_grow).
// TODO: We should probably just share a single HEAPU8 var.
if (wasm.memory.exists &&
((!wasm.memory.segments.empty()) || wasm.features.hasBulkMemory())) {
out << "var bufferView;\n";
}

if (flags.emscripten) {
emitPostEmscripten();
} else {
Expand All @@ -2453,13 +2481,13 @@ void Wasm2JSGlue::emitPost() {
}

void Wasm2JSGlue::emitPostEmscripten() {
emitMemory("wasmMemory.buffer", [](std::string globalName) {
out << "var exports = asmFunc(asmLibraryArg);\n";

emitMemory([](std::string globalName) {
return std::string("asmLibraryArg['") + asmangle(globalName) + "']";
});

out << "return asmFunc(asmLibraryArg, wasmMemory.buffer)\n"
<< "\n"
<< "}";
out << "return exports;\n}";
}

void Wasm2JSGlue::emitPostES6() {
Expand All @@ -2469,12 +2497,9 @@ void Wasm2JSGlue::emitPostES6() {
//
// Note that the translation here expects that the lower values of this memory
// can be used for conversions, so make sure there's at least one page.
if (wasm.memory.exists) {
if (wasm.memory.exists && wasm.memory.imported()) {
out << "var mem" << moduleName.str << " = new ArrayBuffer("
<< wasm.memory.initial.addr * Memory::kPageSize << ");\n";

emitMemory(std::string("mem") + moduleName.str,
[](std::string globalName) { return globalName; });
}

// Actually invoke the `asmFunc` generated function, passing in all global
Expand Down Expand Up @@ -2510,10 +2535,10 @@ void Wasm2JSGlue::emitPostES6() {
out << ",\n " << asmangle(import->base.str);
});

if (wasm.memory.exists && !wasm.memory.imported()) {
out << "\n },\n mem" << moduleName.str << "\n);\n";
} else {
out << "\n });\n";
out << "\n });\n";

if (wasm.memory.exists) {
emitMemory([](std::string globalName) { return globalName; });
}

if (flags.allowAsserts) {
Expand Down Expand Up @@ -2546,21 +2571,10 @@ void Wasm2JSGlue::emitPostES6() {
}

void Wasm2JSGlue::emitMemory(
std::string buffer,
std::function<std::string(std::string)> accessGlobal) {
if (!wasm.memory.exists) {
return;
}
// Create a helper bufferView to access the buffer if we need one. We use it
// for creating memory segments if we have any (we may not if the segments are
// shipped in a side .mem file, for example), and also in bulk memory
// operations.
if (!wasm.memory.segments.empty() || wasm.features.hasBulkMemory()) {
out << "var bufferView = new Uint8Array(" << buffer << ");\n";
}
// If there are no memory segments, we don't need to emit any support code for
// segment creation.
if (wasm.memory.segments.empty()) {
if ((!wasm.memory.exists) || wasm.memory.segments.empty()) {
return;
}

Expand Down
13 changes: 6 additions & 7 deletions test/wasm2js/atomic_fence.2asm.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@

function asmFunc(env, buffer) {
function asmFunc(env) {
var buffer = new ArrayBuffer(1507328);
var HEAP8 = new Int8Array(buffer);
var HEAP16 = new Int16Array(buffer);
var HEAP32 = new Int32Array(buffer);
Expand All @@ -8,6 +9,7 @@ function asmFunc(env, buffer) {
var HEAPU32 = new Uint32Array(buffer);
var HEAPF32 = new Float32Array(buffer);
var HEAPF64 = new Float64Array(buffer);
bufferView = HEAPU8;
var Math_imul = Math.imul;
var Math_fround = Math.fround;
var Math_abs = Math.abs;
Expand Down Expand Up @@ -36,7 +38,6 @@ function asmFunc(env, buffer) {
var newBuffer = new ArrayBuffer(Math_imul(newPages, 65536));
var newHEAP8 = new Int8Array(newBuffer);
newHEAP8.set(HEAP8);
HEAP8 = newHEAP8;
HEAP8 = new Int8Array(newBuffer);
HEAP16 = new Int16Array(newBuffer);
HEAP32 = new Int32Array(newBuffer);
Expand All @@ -46,6 +47,7 @@ function asmFunc(env, buffer) {
HEAPF32 = new Float32Array(newBuffer);
HEAPF64 = new Float64Array(newBuffer);
buffer = newBuffer;
bufferView = HEAPU8;
}
return oldPages;
}
Expand All @@ -55,10 +57,7 @@ function asmFunc(env, buffer) {
};
}

var memasmFunc = new ArrayBuffer(1507328);
var bufferView = new Uint8Array(memasmFunc);
var bufferView;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we not remove this bufferView entirely, and just use HEAP8 which is guaranteed to exist?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my TODO: We should probably just share a single HEAPU8 var. above.

I was thinking that could be a followup. Keeping this change slightly more limited.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does make it harder to review, though, see the comment above with unconditional - it looks like the current PR is not emitting bufferView properly, but I may be missing something?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we start to share HEAPU8 with the containing scope is that going to interfere with the emscripten-side that also defines a HEAPU8 itself? I mean that should always point to the same thing anyway so maybe its fine?

Copy link
Member Author

@sbc100 sbc100 Nov 10, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it looks like the wasm2js output shares a scope with the rest of emscripten, but asmFunc currently creates it own function-local versions of HEAP8, etc. This means that in emscripten output there are two copies of all these views today.

We should possibly merge those two (i.e. have the output HEAP8 be the same as the inner HEAP8), but I'd rather not worry about that as part of this change.

var retasmFunc = asmFunc( { abort: function() { throw new Error('abort'); }
},
memasmFunc
);
});
export var atomic_fence = retasmFunc.atomic_fence;
13 changes: 6 additions & 7 deletions test/wasm2js/atomics_32.2asm.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@

var memorySegments = {};

function asmFunc(env, buffer) {
function asmFunc(env) {
var buffer = new ArrayBuffer(16777216);
var HEAP8 = new Int8Array(buffer);
var HEAP16 = new Int16Array(buffer);
var HEAP32 = new Int32Array(buffer);
Expand All @@ -76,6 +77,7 @@ function asmFunc(env, buffer) {
var HEAPU32 = new Uint32Array(buffer);
var HEAPF32 = new Float32Array(buffer);
var HEAPF64 = new Float64Array(buffer);
bufferView = HEAPU8;
var Math_imul = Math.imul;
var Math_fround = Math.fround;
var Math_abs = Math.abs;
Expand Down Expand Up @@ -128,8 +130,9 @@ function asmFunc(env, buffer) {
};
}

var memasmFunc = new ArrayBuffer(16777216);
var bufferView = new Uint8Array(memasmFunc);
var bufferView;
var retasmFunc = asmFunc( { abort: function() { throw new Error('abort'); }
});
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'
Expand All @@ -151,8 +154,4 @@ for (var base64ReverseLookup = new Uint8Array(123/*'z'+1*/), i = 25; i >= 0; --i
}
memorySegments[0] = base64DecodeToExistingUint8Array(new Uint8Array(6), 0, "aGVsbG8s");
memorySegments[1] = base64DecodeToExistingUint8Array(new Uint8Array(6), 0, "d29ybGQh");
var retasmFunc = asmFunc( { abort: function() { throw new Error('abort'); }
},
memasmFunc
);
export var test = retasmFunc.test;
13 changes: 6 additions & 7 deletions test/wasm2js/atomics_32.2asm.js.opt
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@

var memorySegments = {};

function asmFunc(env, buffer) {
function asmFunc(env) {
var buffer = new ArrayBuffer(16777216);
var HEAP8 = new Int8Array(buffer);
var HEAP16 = new Int16Array(buffer);
var HEAP32 = new Int32Array(buffer);
Expand All @@ -76,6 +77,7 @@ function asmFunc(env, buffer) {
var HEAPU32 = new Uint32Array(buffer);
var HEAPF32 = new Float32Array(buffer);
var HEAPF64 = new Float64Array(buffer);
bufferView = HEAPU8;
var Math_imul = Math.imul;
var Math_fround = Math.fround;
var Math_abs = Math.abs;
Expand Down Expand Up @@ -124,8 +126,9 @@ function asmFunc(env, buffer) {
};
}

var memasmFunc = new ArrayBuffer(16777216);
var bufferView = new Uint8Array(memasmFunc);
var bufferView;
var retasmFunc = asmFunc( { abort: function() { throw new Error('abort'); }
});
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'
Expand All @@ -147,8 +150,4 @@ for (var base64ReverseLookup = new Uint8Array(123/*'z'+1*/), i = 25; i >= 0; --i
}
memorySegments[0] = base64DecodeToExistingUint8Array(new Uint8Array(6), 0, "aGVsbG8s");
memorySegments[1] = base64DecodeToExistingUint8Array(new Uint8Array(6), 0, "d29ybGQh");
var retasmFunc = asmFunc( { abort: function() { throw new Error('abort'); }
},
memasmFunc
);
export var test = retasmFunc.test;
Loading