-
Notifications
You must be signed in to change notification settings - Fork 3.5k
[Memory64] Core JS runtime changes for 64-bit #15219
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -197,10 +197,20 @@ function isStructPointerType(type) { | |
| return !Compiletime.isNumberType(type) && type[0] == '%'; | ||
| } | ||
|
|
||
| const POINTER_SIZE = MEMORY64 ? 8 : 4; | ||
| const POINTER_BITS = POINTER_SIZE * 8; | ||
| const POINTER_TYPE = 'i' + POINTER_BITS; | ||
|
|
||
| const SIZE_TYPE = POINTER_TYPE; | ||
|
|
||
| function isPointerType(type) { | ||
| return type[type.length - 1] == '*'; | ||
| } | ||
|
|
||
| function sizeT(x) { | ||
| return MEMORY64 ? `BigInt(${x})` : x; | ||
| } | ||
|
|
||
| function isArrayType(type) { | ||
| return /^\[\d+\ x\ (.*)\]/.test(type); | ||
| } | ||
|
|
@@ -235,7 +245,7 @@ function isIntImplemented(type) { | |
|
|
||
| // Note: works for iX types and structure types, not pointers (even though they are implemented as ints) | ||
| function getBits(type, allowPointers) { | ||
| if (allowPointers && isPointerType(type)) return 32; | ||
| if (allowPointers && isPointerType(type)) return POINTER_SIZE; | ||
| if (!type) return 0; | ||
| if (type[0] == 'i') { | ||
| const left = type.substr(1); | ||
|
|
@@ -480,7 +490,7 @@ function checkSafeHeap() { | |
| } | ||
|
|
||
| function getHeapOffset(offset, type) { | ||
| if (type == 'i64') { | ||
| if (!WASM_BIGINT && Runtime.getNativeFieldSize(type) > 4 && type == 'i64') { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are we sure this will be no-op for wasm32 users of
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. according to the test, yes :) |
||
| // we emulate 64-bit integer values as 32 in asmjs-unknown-emscripten, but not double | ||
| type = 'i32'; | ||
| } | ||
|
|
@@ -623,7 +633,16 @@ function makeGetValue(ptr, pos, type, noNeedFirst, unsigned, ignore, align, noSa | |
| return asmCoercion('SAFE_HEAP_LOAD' + ((type in Compiletime.FLOAT_TYPES) ? '_D' : '') + '(' + asmCoercion(offset, 'i32') + ', ' + Runtime.getNativeTypeSize(type) + ', ' + (!!unsigned + 0) + ')', type, unsigned ? 'u' : undefined); | ||
| } | ||
| } | ||
| return getHeapForType(type, unsigned) + '[' + getHeapOffset(offset, type) + ']'; | ||
|
|
||
| const slab = getHeapForType(type, unsigned); | ||
| let ret = slab + '[' + getHeapOffset(offset, type) + ']'; | ||
| if (slab.substr(slab.length - 2) == '64') { | ||
| ret = `Number(${ret})`; | ||
| } | ||
| if (forceAsm) { | ||
| ret = asmCoercion(ret, type); | ||
| } | ||
| return ret; | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -665,7 +684,7 @@ function makeSetValue(ptr, pos, value, type, noNeedFirst, ignore, align, noSafe, | |
| return '(' + makeSetTempDouble(0, 'double', value) + ',' + | ||
| makeSetValue(ptr, pos, makeGetTempDouble(0, 'i32'), 'i32', noNeedFirst, ignore, align, noSafe, ',') + ',' + | ||
| makeSetValue(ptr, getFastValue(pos, '+', Runtime.getNativeTypeSize('i32')), makeGetTempDouble(1, 'i32'), 'i32', noNeedFirst, ignore, align, noSafe, ',') + ')'; | ||
| } else if (type == 'i64') { | ||
| } else if (!WASM_BIGINT && type == 'i64') { | ||
| return '(tempI64 = [' + splitI64(value) + '],' + | ||
| makeSetValue(ptr, pos, 'tempI64[0]', 'i32', noNeedFirst, ignore, align, noSafe, ',') + ',' + | ||
| makeSetValue(ptr, getFastValue(pos, '+', Runtime.getNativeTypeSize('i32')), 'tempI64[1]', 'i32', noNeedFirst, ignore, align, noSafe, ',') + ')'; | ||
|
|
@@ -705,7 +724,12 @@ function makeSetValue(ptr, pos, value, type, noNeedFirst, ignore, align, noSafe, | |
| return 'SAFE_HEAP_STORE' + ((type in Compiletime.FLOAT_TYPES) ? '_D' : '') + '(' + asmCoercion(offset, 'i32') + ', ' + asmCoercion(value, type) + ', ' + Runtime.getNativeTypeSize(type) + ')'; | ||
| } | ||
| } | ||
| return getHeapForType(type) + '[' + getHeapOffset(offset, type) + '] = ' + value; | ||
|
|
||
| const slab = getHeapForType(type); | ||
| if (slab == 'HEAPU64' || slab == 'HEAP64') { | ||
| value = `BigInt(${value})`; | ||
| } | ||
| return slab + '[' + getHeapOffset(offset, type) + '] = ' + value; | ||
| } | ||
|
|
||
| const UNROLL_LOOP_MAX = 8; | ||
|
|
@@ -862,23 +886,29 @@ function getFastValue(a, op, b, type) { | |
|
|
||
| function calcFastOffset(ptr, pos, noNeedFirst) { | ||
| assert(!noNeedFirst); | ||
| if (typeof ptr == 'bigint') ptr = Number(ptr); | ||
| if (typeof pos == 'bigint') pos = Number(pos); | ||
| return getFastValue(ptr, '+', pos, 'i32'); | ||
| } | ||
|
|
||
| function getHeapForType(type, unsigned) { | ||
| assert(type); | ||
| if (isPointerType(type)) { | ||
| type = 'i32'; // Hardcoded 32-bit | ||
| type = POINTER_TYPE; | ||
| } | ||
| switch (type) { | ||
| case 'i1': | ||
| case 'i8': | ||
| return unsigned ? 'HEAPU8' : 'HEAP8'; | ||
| case 'i16': | ||
| return unsigned ? 'HEAPU16' : 'HEAP16'; | ||
| case 'i64': | ||
| if (WASM_BIGINT) { | ||
| return unsigned ? 'HEAPU64' : 'HEAP64'; | ||
| } | ||
| // fall through | ||
| case '<4 x i32>': | ||
| case 'i32': | ||
| case 'i64': | ||
| return unsigned ? 'HEAPU32' : 'HEAP32'; | ||
| case 'double': | ||
| return 'HEAPF64'; | ||
|
|
@@ -908,10 +938,7 @@ function makeThrow(what) { | |
| } | ||
|
|
||
| function makeSignOp(value, type, op, force, ignore) { | ||
| if (type == 'i64') { | ||
| return value; // these are always assumed to be two 32-bit unsigneds. | ||
| } | ||
| if (isPointerType(type)) type = 'i32'; // Pointers are treated as 32-bit ints | ||
| if (isPointerType(type)) type = POINTER_TYPE; | ||
| if (!value) return value; | ||
| let bits; | ||
| let full; | ||
|
|
@@ -1292,6 +1319,26 @@ function sendI64Argument(low, high) { | |
| return low + ', ' + high; | ||
| } | ||
|
|
||
| // Any function called from wasm64 may have bigint args, this function takes | ||
| // a list of variable names to convert to number. | ||
| function from64(x) { | ||
| if (!MEMORY64) { | ||
| return ''; | ||
| } | ||
| if (Array.isArray(x)) { | ||
| let ret = ''; | ||
| for (e of x) ret += from64(e); | ||
| return ret; | ||
| } else { | ||
| return `${x} = Number(${x});`; | ||
| } | ||
| } | ||
|
|
||
| function to64(x) { | ||
| if (!MEMORY64) return x; | ||
| return `BigInt(${x})`; | ||
| } | ||
|
|
||
| // Add assertions to catch common errors when using the Promise object we | ||
| // create on Module.ready() and return from MODULARIZE Module() invocations. | ||
| function addReadyPromiseAssertions(promise) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -237,6 +237,7 @@ var MEMORY_GROWTH_LINEAR_STEP = -1; | |
| // the full end-to-end wasm64 mode, and 2 is wasm64 for clang/lld but lowered to | ||
| // wasm32 in Binaryen (such that it can run on wasm32 engines, while internally | ||
| // using i64 pointers). | ||
| // Assumes WASM_BIGINT. | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we automatically set this? Maybe
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes we do, elsewhere. |
||
| // [compile+link] | ||
| var MEMORY64 = 0; | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not obvious to me what this is. Is it for
size_t? Why do we need it? (It's not used anywhere)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There were 10 occurrences in the big PR, so presumably those are used in the other small PRs.