diff --git a/.circleci/config.yml b/.circleci/config.yml index 48c46bb7c24cb..7f65817c7e6d1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -75,24 +75,38 @@ commands: node_version: description: "version of node to install" type: string + canary: + description: "install a canary version of node" + type: boolean + default: false steps: - run: name: setup node v<< parameters.node_version >> command: | cd $HOME version=<< parameters.node_version >> - wget https://nodejs.org/dist/v${version}/node-v${version}-linux-x64.tar.xz + if [[ << parameters.canary >> == "true" ]]; then + wget https://nodejs.org/download/v8-canary/v${version}/node-v${version}-linux-x64.tar.xz + else + wget https://nodejs.org/dist/v${version}/node-v${version}-linux-x64.tar.xz + fi tar xf node-v${version}-linux-x64.tar.xz echo "NODE_JS = [os.path.expanduser('~/node-v${version}-linux-x64/bin/node')]" >> ~/emsdk/.emscripten echo "JS_ENGINES = [NODE_JS]" >> ~/emsdk/.emscripten echo "if os.path.exists(V8_ENGINE[0]): JS_ENGINES.append(V8_ENGINE)" >> ~/emsdk/.emscripten cat ~/emsdk/.emscripten echo "export PATH=\"$HOME/node-v${version}-linux-x64/bin:\$PATH\"" >> $BASH_ENV - install-latest-node: + install-node-latest: description: "install latest version of node" steps: - install-node-version: node_version: "19.0.0" + install-node-canary: + description: "install canary version of node" + steps: + - install-node-version: + node_version: "20.0.0-v8-canary202302081604228b65" + canary: true install-v8: description: "install v8 using jsvu" steps: @@ -532,7 +546,7 @@ jobs: - run-tests: title: "wasm64l" test_targets: "wasm64l" - - install-latest-node + - install-node-canary - run-tests: title: "wasm64" test_targets: "wasm64" @@ -548,6 +562,14 @@ jobs: command: git submodule update --init - pip-install - build + - install-node-canary + - run-tests: + title: "selected subset" + test_targets: " + other.test_gen_struct_info + other.test_native_call_before_init + other.test_node_unhandled_rejection + core2.test_hello_world" # Run some basic tests with the minimum version of node that we currently # support. - install-node-version: @@ -562,7 +584,7 @@ jobs: # Run a few test with the most recent version of node # In particular we have some tests that require node flags on older # versions of node but not with the most recent version. - - install-latest-node + - install-node-latest - run-tests: # Run tests that on older versions of node would require flags, but # those flags should not be injected on newer versions. diff --git a/emscripten.py b/emscripten.py index 34d4cf3e2ce27..b336b633e5ec6 100644 --- a/emscripten.py +++ b/emscripten.py @@ -865,6 +865,13 @@ def create_wasm64_wrappers(metadata): '__cxa_can_catch': '_ppp', '_wasmfs_write_file': '_ppp', '__dl_seterr': '_pp', + '_emscripten_run_in_main_runtime_thread_js': '___p_', + '_emscripten_proxy_execute_task_queue': '_p', + '_emscripten_thread_exit': '_p', + '_emscripten_thread_init': '_p____', + '_emscripten_thread_free_data': '_p', + '_emscripten_dlsync_self_async': '_p', + '_emscripten_proxy_dlsync_async': '_pp', } wasm64_wrappers = ''' diff --git a/src/library_dylink.js b/src/library_dylink.js index 2070703665e11..862d952af166b 100644 --- a/src/library_dylink.js +++ b/src/library_dylink.js @@ -1081,11 +1081,11 @@ var LibraryDylink = { var filename = UTF8ToString({{{ makeGetValue('handle', C_STRUCTS.dso.name, '*') }}}); dlSetError('Could not load dynamic lib: ' + filename + '\n' + e); {{{ runtimeKeepalivePop() }}} - callUserCallback(function () { {{{ makeDynCall('vii', 'onerror') }}}(handle, user_data); }); + callUserCallback(function () { {{{ makeDynCall('vpp', 'onerror') }}}(handle, user_data); }); } function successCallback() { {{{ runtimeKeepalivePop() }}} - callUserCallback(function () { {{{ makeDynCall('vii', 'onsuccess') }}}(handle, user_data); }); + callUserCallback(function () { {{{ makeDynCall('vpp', 'onsuccess') }}}(handle, user_data); }); } {{{ runtimeKeepalivePush() }}} @@ -1115,7 +1115,7 @@ var LibraryDylink = { // void* dlsym(void* handle, const char* symbol); _dlsym_js__deps: ['$dlSetError', '$getFunctionAddress', '$addFunction'], - _dlsym_js__sig: 'ppp', + _dlsym_js__sig: 'pppp', _dlsym_js: function(handle, symbol, symbolIndex) { // void *dlsym(void *restrict handle, const char *restrict name); // http://pubs.opengroup.org/onlinepubs/009695399/functions/dlsym.html diff --git a/src/library_pthread.js b/src/library_pthread.js index 9d5f8332fe131..c0eb5a6d24f36 100644 --- a/src/library_pthread.js +++ b/src/library_pthread.js @@ -539,6 +539,7 @@ var LibraryPThread = { worker.pthread_ptr = 0; }, + __emscripten_thread_cleanup__sig: 'vp', __emscripten_thread_cleanup: function(thread) { // Called when a thread needs to be cleaned up so it can be reused. // A thread is considered reusable when it either returns from its @@ -708,7 +709,7 @@ var LibraryPThread = { // allocations from __pthread_create_js we could also remove this. __pthread_create_js__noleakcheck: true, #endif - __pthread_create_js__sig: 'iiiii', + __pthread_create_js__sig: 'ipppp', __pthread_create_js__deps: ['$spawnThread', 'pthread_self', '$pthreadCreateProxied', #if OFFSCREENCANVAS_SUPPORT 'malloc', @@ -975,6 +976,7 @@ var LibraryPThread = { emscripten_receive_on_main_thread_js_callArgs: '=[]', + emscripten_receive_on_main_thread_js__sig: 'diip', emscripten_receive_on_main_thread_js__deps: [ 'emscripten_proxy_to_main_thread_js', 'emscripten_receive_on_main_thread_js_callArgs'], @@ -1078,7 +1080,7 @@ var LibraryPThread = { // *ThreadMain(void *arg) form, or try linking with the Emscripten linker // flag -sEMULATE_FUNCTION_POINTER_CASTS to add in emulation for this x86 // ABI extension. - var result = {{{ makeDynCall('ii', 'ptr') }}}(arg); + var result = {{{ makeDynCall('pp', 'ptr') }}}(arg); #if STACK_OVERFLOW_CHECK checkStackCookie(); #endif @@ -1097,6 +1099,7 @@ var LibraryPThread = { }, #if MAIN_MODULE + _emscripten_thread_exit_joinable__sig: 'vp', _emscripten_thread_exit_joinable: function(thread) { // Called when a thread exits and is joinable. We mark these threads // as finished, which means that are in state where are no longer actually @@ -1207,6 +1210,7 @@ var LibraryPThread = { }, _emscripten_notify_task_queue__deps: ['$executeNotifiedProxyingQueue'], + _emscripten_notify_task_queue__sig: 'vpppp', _emscripten_notify_task_queue: function(targetThreadId, currThreadId, mainThreadId, queue) { if (targetThreadId == currThreadId) { setTimeout(() => executeNotifiedProxyingQueue(queue)); diff --git a/system/lib/compiler-rt/stack_limits.S b/system/lib/compiler-rt/stack_limits.S index f5865e7c8e526..1171afa8174fc 100644 --- a/system/lib/compiler-rt/stack_limits.S +++ b/system/lib/compiler-rt/stack_limits.S @@ -89,9 +89,6 @@ emscripten_wasm_worker_initialize: local.get 0 .globaltype __tls_size, PTR, immutable global.get __tls_size -#ifdef __wasm64__ - i64.extend_i32_u -#endif PTR.add PTR.const 0xf PTR.add diff --git a/system/lib/libc/musl/arch/emscripten/bits/alltypes.h b/system/lib/libc/musl/arch/emscripten/bits/alltypes.h index 1f7a6718233bc..9b423b21dda24 100644 --- a/system/lib/libc/musl/arch/emscripten/bits/alltypes.h +++ b/system/lib/libc/musl/arch/emscripten/bits/alltypes.h @@ -93,7 +93,7 @@ typedef struct { union { int __i[10]; volatile int __vi[10]; - unsigned __s[10]; + unsigned long __s[10]; } __u; #ifdef __EMSCRIPTEN__ // For canvas transfer implementation in Emscripten, use an extra control field diff --git a/system/lib/pthread/library_pthread.c b/system/lib/pthread/library_pthread.c index 3e80e6f6c30a9..b17854da3ff3d 100644 --- a/system/lib/pthread/library_pthread.c +++ b/system/lib/pthread/library_pthread.c @@ -190,7 +190,7 @@ static void _do_call(void* arg) { break; case EM_PROXIED_JS_FUNCTION: q->returnValue.d = - emscripten_receive_on_main_thread_js((int)(size_t)q->functionPtr, q->args[0].i, &q->args[1].d); + emscripten_receive_on_main_thread_js((intptr_t)q->functionPtr, q->args[0].i, &q->args[1].d); break; case EM_FUNC_SIG_V: ((em_func_v)q->functionPtr)(); @@ -435,7 +435,7 @@ double _emscripten_run_in_main_runtime_thread_js(int index, int num_args, int64_ c->calleeDelete = 1-sync; c->functionEnum = EM_PROXIED_JS_FUNCTION; // Index not needed to ever be more than 32-bit. - c->functionPtr = (void*)(size_t)index; + c->functionPtr = (void*)(intptr_t)index; assert(num_args+1 <= EM_QUEUED_JS_CALL_MAX_ARGS); // The types are only known at runtime in these calls, so we store values that // must be able to contain any valid JS value, including a 64-bit BigInt if diff --git a/test/common.py b/test/common.py index 95fec83642f13..d1ec26c32c96f 100644 --- a/test/common.py +++ b/test/common.py @@ -513,8 +513,6 @@ def setup_node_pthreads(self): self.require_node() self.set_setting('USE_PTHREADS') self.emcc_args += ['-Wno-pthreads-mem-growth'] - if self.get_setting('MEMORY64'): - self.skipTest('node pthreads not yet supported with MEMORY64') if self.get_setting('MINIMAL_RUNTIME'): self.skipTest('node pthreads not yet supported with MINIMAL_RUNTIME') self.js_engines = [config.NODE_JS] diff --git a/test/core/pthread/exceptions.cpp b/test/core/pthread/exceptions.cpp index e9d403ec99e30..d75e43b9c3a96 100644 --- a/test/core/pthread/exceptions.cpp +++ b/test/core/pthread/exceptions.cpp @@ -43,7 +43,7 @@ pthread_t thread[NUM_THREADS]; void CreateThread(int i) { - int rc = pthread_create(&thread[i], nullptr, ThreadMain, (void*)i); + int rc = pthread_create(&thread[i], nullptr, ThreadMain, (void*)(intptr_t)i); assert(rc == 0); } diff --git a/test/core/pthread/test_pthread_dlopen_many.c b/test/core/pthread/test_pthread_dlopen_many.c index 50fa475a292c0..4d853cc8e1da2 100644 --- a/test/core/pthread/test_pthread_dlopen_many.c +++ b/test/core/pthread/test_pthread_dlopen_many.c @@ -59,7 +59,7 @@ int main() { // start a bunch of threads while holding the lock pthread_t threads[NUM_THREADS]; for (int i = 0; i < NUM_THREADS; i++) { - pthread_create(&threads[i], NULL, thread_main, (void*)i); + pthread_create(&threads[i], NULL, thread_main, (void*)(intptr_t)i); } // busy wait until all threads are running diff --git a/test/pthread/test_pthread_cleanup.cpp b/test/pthread/test_pthread_cleanup.cpp index ed9a536000358..9d07817f641d0 100644 --- a/test/pthread/test_pthread_cleanup.cpp +++ b/test/pthread/test_pthread_cleanup.cpp @@ -10,25 +10,22 @@ #include #include #include -#include // Stores/encodes the results of calling to cleanup handlers. -long cleanupState = 1; +int32_t cleanup_state = 1; static void cleanup_handler1(void *arg) { - cleanupState <<= 2; + cleanup_state <<= 2; // Perform non-commutative arithmetic to a global var that encodes the cleanup stack order ops. - cleanupState *= (long)arg; - EM_ASM(console.log('Called clean-up handler 1 with arg ' + $0), arg); - //printf("Called clean-up handler 1 with arg %d\n", (long)arg); + cleanup_state *= (intptr_t)arg; + printf("Called clean-up handler 1 with arg %p (state=%d)\n", arg, cleanup_state); } static void cleanup_handler2(void *arg) { - cleanupState <<= 3; + cleanup_state <<= 3; // Perform non-commutative arithmetic to a global var that encodes the cleanup stack order ops. - cleanupState *= (long)arg; - EM_ASM(console.log('Called clean-up handler 2 with arg ' + $0), arg); - //printf("Called clean-up handler 2 with arg %d\n", (long)arg); + cleanup_state *= (intptr_t)arg; + printf("Called clean-up handler 2 with arg %p (state=%d)\n", arg, cleanup_state); } static void *thread_start1(void *arg) { @@ -83,8 +80,8 @@ int main() { // s = pthread_cancel(thr[3]); // assert(s == 0); pthread_cleanup_pop(1); - printf("Cleanup state variable: %ld\n", cleanupState); - assert(cleanupState == 907640832); + printf("Cleanup state variable: %d\n", cleanup_state); + assert(cleanup_state == 907640832); pthread_cleanup_pop(1); exit(EXIT_SUCCESS); diff --git a/test/pthread/test_pthread_thread_local_storage.cpp b/test/pthread/test_pthread_thread_local_storage.cpp index 39ec50ed3fc6b..6496f5c3aead3 100644 --- a/test/pthread/test_pthread_thread_local_storage.cpp +++ b/test/pthread/test_pthread_thread_local_storage.cpp @@ -83,10 +83,10 @@ int main() { if (thread[i]) { - int status; + intptr_t status; int rc = pthread_join(thread[i], (void**)&status); assert(rc == 0); - printf("Main: Joined thread idx %ld with status %d\n", i, status); + printf("Main: Joined thread idx %ld with status %lu\n", i, status); assert(status == 0); thread[i] = 0; if (numThreadsToCreate > 0) @@ -102,10 +102,10 @@ int main() { if (thread[i]) { - int status = 1; + intptr_t status = 1; int rc = pthread_join(thread[i], (void**)&status); assert(rc == 0); - printf("Main: Joined thread idx %d with status %d\n", i, status); + printf("Main: Joined thread idx %d with status %lu\n", i, status); assert(status == 0); } } diff --git a/test/test_core.py b/test/test_core.py index 03d350a26e295..23c160de2e159 100644 --- a/test/test_core.py +++ b/test/test_core.py @@ -9284,6 +9284,7 @@ def test_pthread_create_embind_stack_check(self): self.do_run_in_out_file_test('core/pthread/create.cpp') @node_pthreads + @no_wasm64('MEMORY64 does not yet support exceptions') def test_pthread_exceptions(self): self.set_setting('PTHREAD_POOL_SIZE', 2) self.set_setting('EXIT_RUNTIME') @@ -9395,6 +9396,7 @@ def test_pthread_dylink_entry_point(self, args): @needs_dylink @node_pthreads + @no_wasm64('MEMORY64 does not yet support exceptions') def test_pthread_dylink_exceptions(self): self.emcc_args.append('-Wno-experimental') self.set_setting('USE_PTHREADS') diff --git a/tools/extract_metadata.py b/tools/extract_metadata.py index 67f90b08e9208..3838a569e96be 100644 --- a/tools/extract_metadata.py +++ b/tools/extract_metadata.py @@ -90,7 +90,7 @@ def parse_function_for_memory_inits(module, func_index, offset_map): call_targets = [] while module.tell() != end: opcode = OpCode(module.read_byte()) - if opcode in (OpCode.END, OpCode.NOP, OpCode.DROP, OpCode.I32_ADD): + if opcode in (OpCode.END, OpCode.NOP, OpCode.DROP, OpCode.I32_ADD, OpCode.I64_ADD): pass elif opcode in (OpCode.BLOCK,): module.read_type() diff --git a/tools/webassembly.py b/tools/webassembly.py index 26e36a4812017..6ee0bbfe513df 100644 --- a/tools/webassembly.py +++ b/tools/webassembly.py @@ -109,7 +109,7 @@ class OpCode(IntEnum): F32_CONST = 0x43 F64_CONST = 0x44 I32_ADD = 0x6a - I64_ADD = 0x6b + I64_ADD = 0x7c REF_NULL = 0xd0 ATOMIC_PREFIX = 0xfe MEMORY_PREFIX = 0xfc