diff --git a/.circleci/config.yml b/.circleci/config.yml index ea13f903a84d8..73d44bd5bab92 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -619,6 +619,7 @@ jobs: wasm64_4gb.test_hello_world wasm64_4gb.test_em_asm wasm64_4gb.test_async_main + wasm64_4gb.*embind* core_2gb.test_em_asm wasm64l.test_bigswitch other.test_memory64_proxies diff --git a/src/embind/embind.js b/src/embind/embind.js index 85ec3fc4737d7..3efd922caef13 100644 --- a/src/embind/embind.js +++ b/src/embind/embind.js @@ -34,6 +34,7 @@ var LibraryEmbind = { $PureVirtualError__postset: "PureVirtualError = Module['PureVirtualError'] = extendError(Error, 'PureVirtualError');", $PureVirtualError__deps: ['$extendError'], $PureVirtualError: undefined, + $GenericWireTypeSize: {{{ 2 * POINTER_SIZE }}}, $init_embind__deps: [ '$getInheritedInstanceCount', '$getLiveInheritedInstances', @@ -274,7 +275,7 @@ var LibraryEmbind = { }); }, - _embind_register_bool__deps: ['$readLatin1String', '$registerType'], + _embind_register_bool__deps: ['$readLatin1String', '$registerType', '$GenericWireTypeSize'], _embind_register_bool: (rawType, name, trueValue, falseValue) => { name = readLatin1String(name); registerType(rawType, { @@ -287,7 +288,7 @@ var LibraryEmbind = { 'toWireType': function(destructors, o) { return o ? trueValue : falseValue; }, - 'argPackAdvance': 8, + 'argPackAdvance': GenericWireTypeSize, 'readValueFromPointer': function(pointer) { return this['fromWireType'](HEAPU8[pointer]); }, @@ -300,18 +301,18 @@ var LibraryEmbind = { // integers are quite common, so generate very specialized functions switch (width) { case 1: return signed ? - function readS8FromPointer(pointer) { return HEAP8[pointer]; } : - function readU8FromPointer(pointer) { return HEAPU8[pointer]; }; + (pointer) => {{{ makeGetValue('pointer', 0, 'i8') }}} : + (pointer) => {{{ makeGetValue('pointer', 0, 'u8') }}}; case 2: return signed ? - function readS16FromPointer(pointer) { return HEAP16[pointer >> 1]; } : - function readU16FromPointer(pointer) { return HEAPU16[pointer >> 1]; }; + (pointer) => {{{ makeGetValue('pointer', 0, 'i16') }}} : + (pointer) => {{{ makeGetValue('pointer', 0, 'u16') }}} case 4: return signed ? - function readS32FromPointer(pointer) { return HEAP32[pointer >> 2]; } : - function readU32FromPointer(pointer) { return HEAPU32[pointer >> 2]; }; + (pointer) => {{{ makeGetValue('pointer', 0, 'i32') }}} : + (pointer) => {{{ makeGetValue('pointer', 0, 'u32') }}} #if WASM_BIGINT case 8: return signed ? - function readS64FromPointer(pointer) { return HEAP64[pointer >> 3]; } : - function readU64FromPointer(pointer) { return HEAPU64[pointer >> 3]; }; + (pointer) => {{{ makeGetValue('pointer', 0, 'i64') }}} : + (pointer) => {{{ makeGetValue('pointer', 0, 'u64') }}} #endif default: throw new TypeError(`invalid integer width (${width}): ${name}`); @@ -321,18 +322,15 @@ var LibraryEmbind = { $enumReadValueFromPointer__deps: [], $enumReadValueFromPointer: (name, width, signed) => { switch (width) { - case 1: return function(pointer) { - var heap = signed ? HEAP8 : HEAPU8; - return this['fromWireType'](heap[pointer]); - }; - case 2: return function(pointer) { - var heap = signed ? HEAP16 : HEAPU16; - return this['fromWireType'](heap[pointer >> 1]); - }; - case 4: return function(pointer) { - var heap = signed ? HEAP32 : HEAPU32; - return this['fromWireType'](heap[pointer >> 2]); - }; + case 1: return signed ? + function(pointer) { return this['fromWireType']({{{ makeGetValue('pointer', 0, 'i8') }}}) } : + function(pointer) { return this['fromWireType']({{{ makeGetValue('pointer', 0, 'u8') }}}) }; + case 2: return signed ? + function(pointer) { return this['fromWireType']({{{ makeGetValue('pointer', 0, 'i16') }}}) } : + function(pointer) { return this['fromWireType']({{{ makeGetValue('pointer', 0, 'u16') }}}) }; + case 4: return signed ? + function(pointer) { return this['fromWireType']({{{ makeGetValue('pointer', 0, 'i32') }}}) } : + function(pointer) { return this['fromWireType']({{{ makeGetValue('pointer', 0, 'u32') }}}) }; default: throw new TypeError(`invalid integer width (${width}): ${name}`); } @@ -342,10 +340,10 @@ var LibraryEmbind = { $floatReadValueFromPointer: (name, width) => { switch (width) { case 4: return function(pointer) { - return this['fromWireType'](HEAPF32[pointer >> 2]); + return this['fromWireType']({{{ makeGetValue('pointer', 0, 'float') }}}); }; case 8: return function(pointer) { - return this['fromWireType'](HEAPF64[pointer >> 3]); + return this['fromWireType']({{{ makeGetValue('pointer', 0, 'double') }}}); }; default: throw new TypeError(`invalid float width (${width}): ${name}`); @@ -401,7 +399,7 @@ var LibraryEmbind = { name, 'fromWireType': fromWireType, 'toWireType': toWireType, - 'argPackAdvance': 8, + 'argPackAdvance': GenericWireTypeSize, 'readValueFromPointer': integerReadValueFromPointer(name, size, minRange !== 0), destructorFunction: null, // This type does not need a destructor }); @@ -432,7 +430,7 @@ var LibraryEmbind = { } return value; }, - 'argPackAdvance': 8, + 'argPackAdvance': GenericWireTypeSize, 'readValueFromPointer': integerReadValueFromPointer(name, size, !isUnsignedType), destructorFunction: null, // This type does not need a destructor }); @@ -460,7 +458,7 @@ var LibraryEmbind = { // https://www.w3.org/TR/wasm-js-api-1/#towebassemblyvalue return value; }, - 'argPackAdvance': 8, + 'argPackAdvance': GenericWireTypeSize, 'readValueFromPointer': floatReadValueFromPointer(name, size), destructorFunction: null, // This type does not need a destructor }); @@ -471,9 +469,13 @@ var LibraryEmbind = { return this['fromWireType']({{{ makeGetValue('pointer', '0', 'i32') }}}); }, + $readPointer: function(pointer) { + return this['fromWireType']({{{ makeGetValue('pointer', '0', '*') }}}); + }, + _embind_register_std_string__deps: [ '$readLatin1String', '$registerType', - '$simpleReadValueFromPointer', '$throwBindingError', + '$readPointer', '$throwBindingError', '$stringToUTF8', '$lengthBytesUTF8', 'malloc', 'free'], _embind_register_std_string: (rawType, name) => { name = readLatin1String(name); @@ -566,14 +568,14 @@ var LibraryEmbind = { } return base; }, - 'argPackAdvance': 8, - 'readValueFromPointer': simpleReadValueFromPointer, + 'argPackAdvance': GenericWireTypeSize, + 'readValueFromPointer': readPointer, destructorFunction: (ptr) => _free(ptr), }); }, _embind_register_std_wstring__deps: [ - '$readLatin1String', '$registerType', '$simpleReadValueFromPointer', + '$readLatin1String', '$registerType', '$readPointer', '$UTF16ToString', '$stringToUTF16', '$lengthBytesUTF16', '$UTF32ToString', '$stringToUTF32', '$lengthBytesUTF32', ], @@ -597,7 +599,7 @@ var LibraryEmbind = { name, 'fromWireType': (value) => { // Code mostly taken from _embind_register_std_string fromWireType - var length = HEAPU32[value >> 2]; + var length = {{{ makeGetValue('value', 0, '*') }}}; var HEAP = getHeap(); var str; @@ -639,7 +641,7 @@ var LibraryEmbind = { } return ptr; }, - 'argPackAdvance': 8, + 'argPackAdvance': GenericWireTypeSize, 'readValueFromPointer': simpleReadValueFromPointer, destructorFunction: (ptr) => _free(ptr), }); @@ -658,7 +660,7 @@ var LibraryEmbind = { return rv; }, 'toWireType': (destructors, value) => Emval.toHandle(value), - 'argPackAdvance': 8, + 'argPackAdvance': GenericWireTypeSize, 'readValueFromPointer': simpleReadValueFromPointer, destructorFunction: null, // This type does not need a destructor @@ -687,18 +689,16 @@ var LibraryEmbind = { var TA = typeMapping[dataTypeIndex]; function decodeMemoryView(handle) { - handle = handle >> 2; - var heap = HEAPU32; - var size = heap[handle]; // in elements - var data = heap[handle + 1]; // byte offset into emscripten heap - return new TA(heap.buffer, data, size); + var size = {{{ makeGetValue('handle', 0, '*') }}}; + var data = {{{ makeGetValue('handle', POINTER_SIZE, '*') }}}; + return new TA(HEAP8.buffer, data, size); } name = readLatin1String(name); registerType(rawType, { name, 'fromWireType': decodeMemoryView, - 'argPackAdvance': 8, + 'argPackAdvance': GenericWireTypeSize, 'readValueFromPointer': decodeMemoryView, }, { ignoreDuplicateRegistrations: true, @@ -1098,7 +1098,7 @@ var LibraryEmbind = { } return ptr; }, - 'argPackAdvance': 8, + 'argPackAdvance': GenericWireTypeSize, 'readValueFromPointer': simpleReadValueFromPointer, destructorFunction: rawDestructor, }]; @@ -1210,7 +1210,7 @@ var LibraryEmbind = { } return ptr; }, - 'argPackAdvance': 8, + 'argPackAdvance': GenericWireTypeSize, 'readValueFromPointer': simpleReadValueFromPointer, destructorFunction: rawDestructor, }]; @@ -1340,14 +1340,14 @@ var LibraryEmbind = { }, $init_RegisteredPointer__deps: [ - '$simpleReadValueFromPointer', + '$readPointer', '$RegisteredPointer_getPointee', '$RegisteredPointer_destructor', '$RegisteredPointer_deleteObject', '$RegisteredPointer_fromWireType'], $init_RegisteredPointer: () => { RegisteredPointer.prototype.getPointee = RegisteredPointer_getPointee; RegisteredPointer.prototype.destructor = RegisteredPointer_destructor; - RegisteredPointer.prototype['argPackAdvance'] = 8; - RegisteredPointer.prototype['readValueFromPointer'] = simpleReadValueFromPointer; + RegisteredPointer.prototype['argPackAdvance'] = GenericWireTypeSize; + RegisteredPointer.prototype['readValueFromPointer'] = readPointer; RegisteredPointer.prototype['deleteObject'] = RegisteredPointer_deleteObject; RegisteredPointer.prototype['fromWireType'] = RegisteredPointer_fromWireType; }, @@ -2379,7 +2379,7 @@ var LibraryEmbind = { return this.constructor.values[c]; }, 'toWireType': (destructors, c) => c.value, - 'argPackAdvance': 8, + 'argPackAdvance': GenericWireTypeSize, 'readValueFromPointer': enumReadValueFromPointer(name, size, isSigned), destructorFunction: null, }); diff --git a/system/include/emscripten/val.h b/system/include/emscripten/val.h index 15b768c261c7f..cc226d1479012 100644 --- a/system/include/emscripten/val.h +++ b/system/include/emscripten/val.h @@ -191,17 +191,14 @@ struct PackSize { union GenericWireType { union { unsigned u; + size_t s; float f; - // Use uint32_t for pointer values. This limits us, for now, to 32-bit - // address ranges even on wasm64. This is enforced by assertions below. - // TODO(sbc): Allow full 64-bit address range here under wasm64, most - // likely by increasing the size of GenericWireType on wasm64. - uint32_t p; + void* p; } w[2]; - double d; - uint64_t u; + double d; + uint64_t u; }; -static_assert(sizeof(GenericWireType) == 8, "GenericWireType must be 8 bytes"); +static_assert(sizeof(GenericWireType) == 2*sizeof(void*), "GenericWireType must be size of 2 pointers"); static_assert(alignof(GenericWireType) == 8, "GenericWireType must be 8-byte-aligned"); inline void writeGenericWireType(GenericWireType*& cursor, float wt) { @@ -226,18 +223,14 @@ inline void writeGenericWireType(GenericWireType*& cursor, uint64_t wt) { template void writeGenericWireType(GenericWireType*& cursor, T* wt) { - uintptr_t short_ptr = reinterpret_cast(wt); - assert(short_ptr <= UINT32_MAX); - cursor->w[0].p = short_ptr; + cursor->w[0].p = wt; ++cursor; } template inline void writeGenericWireType(GenericWireType*& cursor, const memory_view& wt) { - uintptr_t short_ptr = reinterpret_cast(wt.data); - assert(short_ptr <= UINT32_MAX); - cursor->w[0].u = wt.size; - cursor->w[1].p = short_ptr; + cursor->w[0].s = wt.size; + cursor->w[1].p = (void*)wt.data; ++cursor; } diff --git a/test/common.py b/test/common.py index d51d013fdcac2..2d2776c07917d 100644 --- a/test/common.py +++ b/test/common.py @@ -705,6 +705,10 @@ def setup_node_pthreads(self): self.emcc_args += ['-Wno-pthreads-mem-growth', '-pthread'] if self.get_setting('MINIMAL_RUNTIME'): self.skipTest('node pthreads not yet supported with MINIMAL_RUNTIME') + # Pthread support requires IMPORTED_MEMORY which depends on the JS API + # for creating 64-bit memories. + if self.get_setting('GLOBAL_BASE') == '4gb': + self.skipTest('no support for IMPORTED_MEMORY over 4gb yet') self.js_engines = [config.NODE_JS] self.node_args += shared.node_pthread_flags()