Skip to content

Commit affda01

Browse files
committed
[Wasm64] Fix embind with addresses over 4gb
Fixes: #19968
1 parent 91641db commit affda01

File tree

4 files changed

+59
-61
lines changed

4 files changed

+59
-61
lines changed

.circleci/config.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,7 @@ jobs:
619619
wasm64_4gb.test_hello_world
620620
wasm64_4gb.test_em_asm
621621
wasm64_4gb.test_async_main
622+
wasm64_4gb.*embind*
622623
core_2gb.test_em_asm
623624
wasm64l.test_bigswitch
624625
other.test_memory64_proxies

src/embind/embind.js

Lines changed: 46 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ var LibraryEmbind = {
3434
$PureVirtualError__postset: "PureVirtualError = Module['PureVirtualError'] = extendError(Error, 'PureVirtualError');",
3535
$PureVirtualError__deps: ['$extendError'],
3636
$PureVirtualError: undefined,
37+
$GenericWireTypeSize: {{{ 2 * POINTER_SIZE }}},
3738

3839
$init_embind__deps: [
3940
'$getInheritedInstanceCount', '$getLiveInheritedInstances',
@@ -274,7 +275,7 @@ var LibraryEmbind = {
274275
});
275276
},
276277

277-
_embind_register_bool__deps: ['$readLatin1String', '$registerType'],
278+
_embind_register_bool__deps: ['$readLatin1String', '$registerType', '$GenericWireTypeSize'],
278279
_embind_register_bool: (rawType, name, trueValue, falseValue) => {
279280
name = readLatin1String(name);
280281
registerType(rawType, {
@@ -287,7 +288,7 @@ var LibraryEmbind = {
287288
'toWireType': function(destructors, o) {
288289
return o ? trueValue : falseValue;
289290
},
290-
'argPackAdvance': 8,
291+
'argPackAdvance': GenericWireTypeSize,
291292
'readValueFromPointer': function(pointer) {
292293
return this['fromWireType'](HEAPU8[pointer]);
293294
},
@@ -300,18 +301,18 @@ var LibraryEmbind = {
300301
// integers are quite common, so generate very specialized functions
301302
switch (width) {
302303
case 1: return signed ?
303-
function readS8FromPointer(pointer) { return HEAP8[pointer]; } :
304-
function readU8FromPointer(pointer) { return HEAPU8[pointer]; };
304+
(pointer) => {{{ makeGetValue('pointer', 0, 'i8') }}} :
305+
(pointer) => {{{ makeGetValue('pointer', 0, 'u8') }}};
305306
case 2: return signed ?
306-
function readS16FromPointer(pointer) { return HEAP16[pointer >> 1]; } :
307-
function readU16FromPointer(pointer) { return HEAPU16[pointer >> 1]; };
307+
(pointer) => {{{ makeGetValue('pointer', 0, 'i16') }}} :
308+
(pointer) => {{{ makeGetValue('pointer', 0, 'u16') }}}
308309
case 4: return signed ?
309-
function readS32FromPointer(pointer) { return HEAP32[pointer >> 2]; } :
310-
function readU32FromPointer(pointer) { return HEAPU32[pointer >> 2]; };
310+
(pointer) => {{{ makeGetValue('pointer', 0, 'i32') }}} :
311+
(pointer) => {{{ makeGetValue('pointer', 0, 'u32') }}}
311312
#if WASM_BIGINT
312313
case 8: return signed ?
313-
function readS64FromPointer(pointer) { return HEAP64[pointer >> 3]; } :
314-
function readU64FromPointer(pointer) { return HEAPU64[pointer >> 3]; };
314+
(pointer) => {{{ makeGetValue('pointer', 0, 'i64') }}} :
315+
(pointer) => {{{ makeGetValue('pointer', 0, 'u64') }}}
315316
#endif
316317
default:
317318
throw new TypeError(`invalid integer width (${width}): ${name}`);
@@ -321,18 +322,15 @@ var LibraryEmbind = {
321322
$enumReadValueFromPointer__deps: [],
322323
$enumReadValueFromPointer: (name, width, signed) => {
323324
switch (width) {
324-
case 1: return function(pointer) {
325-
var heap = signed ? HEAP8 : HEAPU8;
326-
return this['fromWireType'](heap[pointer]);
327-
};
328-
case 2: return function(pointer) {
329-
var heap = signed ? HEAP16 : HEAPU16;
330-
return this['fromWireType'](heap[pointer >> 1]);
331-
};
332-
case 4: return function(pointer) {
333-
var heap = signed ? HEAP32 : HEAPU32;
334-
return this['fromWireType'](heap[pointer >> 2]);
335-
};
325+
case 1: return signed ?
326+
function(pointer) { return this['fromWireType']({{{ makeGetValue('pointer', 0, 'i8') }}}) } :
327+
function(pointer) { return this['fromWireType']({{{ makeGetValue('pointer', 0, 'u8') }}}) };
328+
case 2: return signed ?
329+
function(pointer) { return this['fromWireType']({{{ makeGetValue('pointer', 0, 'i16') }}}) } :
330+
function(pointer) { return this['fromWireType']({{{ makeGetValue('pointer', 0, 'u16') }}}) };
331+
case 4: return signed ?
332+
function(pointer) { return this['fromWireType']({{{ makeGetValue('pointer', 0, 'i32') }}}) } :
333+
function(pointer) { return this['fromWireType']({{{ makeGetValue('pointer', 0, 'u32') }}}) };
336334
default:
337335
throw new TypeError(`invalid integer width (${width}): ${name}`);
338336
}
@@ -342,10 +340,10 @@ var LibraryEmbind = {
342340
$floatReadValueFromPointer: (name, width) => {
343341
switch (width) {
344342
case 4: return function(pointer) {
345-
return this['fromWireType'](HEAPF32[pointer >> 2]);
343+
return this['fromWireType']({{{ makeGetValue('pointer', 0, 'float') }}});
346344
};
347345
case 8: return function(pointer) {
348-
return this['fromWireType'](HEAPF64[pointer >> 3]);
346+
return this['fromWireType']({{{ makeGetValue('pointer', 0, 'double') }}});
349347
};
350348
default:
351349
throw new TypeError(`invalid float width (${width}): ${name}`);
@@ -401,7 +399,7 @@ var LibraryEmbind = {
401399
name,
402400
'fromWireType': fromWireType,
403401
'toWireType': toWireType,
404-
'argPackAdvance': 8,
402+
'argPackAdvance': GenericWireTypeSize,
405403
'readValueFromPointer': integerReadValueFromPointer(name, size, minRange !== 0),
406404
destructorFunction: null, // This type does not need a destructor
407405
});
@@ -432,7 +430,7 @@ var LibraryEmbind = {
432430
}
433431
return value;
434432
},
435-
'argPackAdvance': 8,
433+
'argPackAdvance': GenericWireTypeSize,
436434
'readValueFromPointer': integerReadValueFromPointer(name, size, !isUnsignedType),
437435
destructorFunction: null, // This type does not need a destructor
438436
});
@@ -460,7 +458,7 @@ var LibraryEmbind = {
460458
// https://www.w3.org/TR/wasm-js-api-1/#towebassemblyvalue
461459
return value;
462460
},
463-
'argPackAdvance': 8,
461+
'argPackAdvance': GenericWireTypeSize,
464462
'readValueFromPointer': floatReadValueFromPointer(name, size),
465463
destructorFunction: null, // This type does not need a destructor
466464
});
@@ -471,9 +469,13 @@ var LibraryEmbind = {
471469
return this['fromWireType']({{{ makeGetValue('pointer', '0', 'i32') }}});
472470
},
473471

472+
$readPointer: function(pointer) {
473+
return this['fromWireType']({{{ makeGetValue('pointer', '0', '*') }}});
474+
},
475+
474476
_embind_register_std_string__deps: [
475477
'$readLatin1String', '$registerType',
476-
'$simpleReadValueFromPointer', '$throwBindingError',
478+
'$readPointer', '$throwBindingError',
477479
'$stringToUTF8', '$lengthBytesUTF8', 'malloc', 'free'],
478480
_embind_register_std_string: (rawType, name) => {
479481
name = readLatin1String(name);
@@ -566,14 +568,14 @@ var LibraryEmbind = {
566568
}
567569
return base;
568570
},
569-
'argPackAdvance': 8,
570-
'readValueFromPointer': simpleReadValueFromPointer,
571+
'argPackAdvance': GenericWireTypeSize,
572+
'readValueFromPointer': readPointer,
571573
destructorFunction: (ptr) => _free(ptr),
572574
});
573575
},
574576

575577
_embind_register_std_wstring__deps: [
576-
'$readLatin1String', '$registerType', '$simpleReadValueFromPointer',
578+
'$readLatin1String', '$registerType', '$readPointer',
577579
'$UTF16ToString', '$stringToUTF16', '$lengthBytesUTF16',
578580
'$UTF32ToString', '$stringToUTF32', '$lengthBytesUTF32',
579581
],
@@ -597,7 +599,7 @@ var LibraryEmbind = {
597599
name,
598600
'fromWireType': (value) => {
599601
// Code mostly taken from _embind_register_std_string fromWireType
600-
var length = HEAPU32[value >> 2];
602+
var length = {{{ makeGetValue('value', 0, '*') }}};
601603
var HEAP = getHeap();
602604
var str;
603605

@@ -639,7 +641,7 @@ var LibraryEmbind = {
639641
}
640642
return ptr;
641643
},
642-
'argPackAdvance': 8,
644+
'argPackAdvance': GenericWireTypeSize,
643645
'readValueFromPointer': simpleReadValueFromPointer,
644646
destructorFunction: (ptr) => _free(ptr),
645647
});
@@ -658,7 +660,7 @@ var LibraryEmbind = {
658660
return rv;
659661
},
660662
'toWireType': (destructors, value) => Emval.toHandle(value),
661-
'argPackAdvance': 8,
663+
'argPackAdvance': GenericWireTypeSize,
662664
'readValueFromPointer': simpleReadValueFromPointer,
663665
destructorFunction: null, // This type does not need a destructor
664666

@@ -687,18 +689,16 @@ var LibraryEmbind = {
687689
var TA = typeMapping[dataTypeIndex];
688690

689691
function decodeMemoryView(handle) {
690-
handle = handle >> 2;
691-
var heap = HEAPU32;
692-
var size = heap[handle]; // in elements
693-
var data = heap[handle + 1]; // byte offset into emscripten heap
694-
return new TA(heap.buffer, data, size);
692+
var size = {{{ makeGetValue('handle', 0, '*') }}};
693+
var data = {{{ makeGetValue('handle', POINTER_SIZE, '*') }}};
694+
return new TA(HEAP8.buffer, data, size);
695695
}
696696

697697
name = readLatin1String(name);
698698
registerType(rawType, {
699699
name,
700700
'fromWireType': decodeMemoryView,
701-
'argPackAdvance': 8,
701+
'argPackAdvance': GenericWireTypeSize,
702702
'readValueFromPointer': decodeMemoryView,
703703
}, {
704704
ignoreDuplicateRegistrations: true,
@@ -1098,7 +1098,7 @@ var LibraryEmbind = {
10981098
}
10991099
return ptr;
11001100
},
1101-
'argPackAdvance': 8,
1101+
'argPackAdvance': GenericWireTypeSize,
11021102
'readValueFromPointer': simpleReadValueFromPointer,
11031103
destructorFunction: rawDestructor,
11041104
}];
@@ -1210,7 +1210,7 @@ var LibraryEmbind = {
12101210
}
12111211
return ptr;
12121212
},
1213-
'argPackAdvance': 8,
1213+
'argPackAdvance': GenericWireTypeSize,
12141214
'readValueFromPointer': simpleReadValueFromPointer,
12151215
destructorFunction: rawDestructor,
12161216
}];
@@ -1340,14 +1340,14 @@ var LibraryEmbind = {
13401340
},
13411341

13421342
$init_RegisteredPointer__deps: [
1343-
'$simpleReadValueFromPointer',
1343+
'$readPointer',
13441344
'$RegisteredPointer_getPointee', '$RegisteredPointer_destructor',
13451345
'$RegisteredPointer_deleteObject', '$RegisteredPointer_fromWireType'],
13461346
$init_RegisteredPointer: () => {
13471347
RegisteredPointer.prototype.getPointee = RegisteredPointer_getPointee;
13481348
RegisteredPointer.prototype.destructor = RegisteredPointer_destructor;
1349-
RegisteredPointer.prototype['argPackAdvance'] = 8;
1350-
RegisteredPointer.prototype['readValueFromPointer'] = simpleReadValueFromPointer;
1349+
RegisteredPointer.prototype['argPackAdvance'] = GenericWireTypeSize;
1350+
RegisteredPointer.prototype['readValueFromPointer'] = readPointer;
13511351
RegisteredPointer.prototype['deleteObject'] = RegisteredPointer_deleteObject;
13521352
RegisteredPointer.prototype['fromWireType'] = RegisteredPointer_fromWireType;
13531353
},
@@ -2379,7 +2379,7 @@ var LibraryEmbind = {
23792379
return this.constructor.values[c];
23802380
},
23812381
'toWireType': (destructors, c) => c.value,
2382-
'argPackAdvance': 8,
2382+
'argPackAdvance': GenericWireTypeSize,
23832383
'readValueFromPointer': enumReadValueFromPointer(name, size, isSigned),
23842384
destructorFunction: null,
23852385
});

system/include/emscripten/val.h

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -191,17 +191,14 @@ struct PackSize<Arg, Args...> {
191191
union GenericWireType {
192192
union {
193193
unsigned u;
194+
size_t s;
194195
float f;
195-
// Use uint32_t for pointer values. This limits us, for now, to 32-bit
196-
// address ranges even on wasm64. This is enforced by assertions below.
197-
// TODO(sbc): Allow full 64-bit address range here under wasm64, most
198-
// likely by increasing the size of GenericWireType on wasm64.
199-
uint32_t p;
196+
void* p;
200197
} w[2];
201-
double d;
202-
uint64_t u;
198+
double d;
199+
uint64_t u;
203200
};
204-
static_assert(sizeof(GenericWireType) == 8, "GenericWireType must be 8 bytes");
201+
static_assert(sizeof(GenericWireType) == 2*sizeof(void*), "GenericWireType must be size of 2 pointers");
205202
static_assert(alignof(GenericWireType) == 8, "GenericWireType must be 8-byte-aligned");
206203

207204
inline void writeGenericWireType(GenericWireType*& cursor, float wt) {
@@ -226,18 +223,14 @@ inline void writeGenericWireType(GenericWireType*& cursor, uint64_t wt) {
226223

227224
template<typename T>
228225
void writeGenericWireType(GenericWireType*& cursor, T* wt) {
229-
uintptr_t short_ptr = reinterpret_cast<uintptr_t>(wt);
230-
assert(short_ptr <= UINT32_MAX);
231-
cursor->w[0].p = short_ptr;
226+
cursor->w[0].p = wt;
232227
++cursor;
233228
}
234229

235230
template<typename ElementType>
236231
inline void writeGenericWireType(GenericWireType*& cursor, const memory_view<ElementType>& wt) {
237-
uintptr_t short_ptr = reinterpret_cast<uintptr_t>(wt.data);
238-
assert(short_ptr <= UINT32_MAX);
239-
cursor->w[0].u = wt.size;
240-
cursor->w[1].p = short_ptr;
232+
cursor->w[0].s = wt.size;
233+
cursor->w[1].p = (void*)wt.data;
241234
++cursor;
242235
}
243236

test/common.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,10 @@ def setup_node_pthreads(self):
705705
self.emcc_args += ['-Wno-pthreads-mem-growth', '-pthread']
706706
if self.get_setting('MINIMAL_RUNTIME'):
707707
self.skipTest('node pthreads not yet supported with MINIMAL_RUNTIME')
708+
# Pthread support requires IMPORTED_MEMORY which depends on the JS API
709+
# for creating 64-bit memories.
710+
if self.get_setting('GLOBAL_BASE') == '4gb':
711+
self.skipTest('no support for IMPORTED_MEMORY over 4gb yet')
708712
self.js_engines = [config.NODE_JS]
709713
self.node_args += shared.node_pthread_flags()
710714

0 commit comments

Comments
 (0)