From bbf2f5d71648407cb268c59cbb1f5d427a9831fa Mon Sep 17 00:00:00 2001 From: Jarred Sumner Date: Sun, 21 Jul 2024 21:32:52 -0700 Subject: [PATCH] Experiment: disable C++ static destructors (#12652) Co-authored-by: Jarred-Sumner --- CMakeLists.txt | 9 ++++++--- packages/bun-uws/src/Loop.h | 9 ++++++++- scripts/env.sh | 18 ++++++++++++++++-- src/bun.js/web_worker.zig | 1 + src/deps/libuwsockets.cpp | 5 +++++ src/deps/uws.zig | 5 +++++ src/generated_versions_list.zig | 2 +- test/regression/issue/12650.test.js | 22 +++++++++++----------- 8 files changed, 53 insertions(+), 18 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e68cbf3939..70b8f52b67 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ cmake_policy(SET CMP0067 NEW) set(CMAKE_POLICY_DEFAULT_CMP0069 NEW) set(Bun_VERSION "1.1.21") -set(WEBKIT_TAG dac47fbd5444cbd4e3568267099ae276c547e897) +set(WEBKIT_TAG 2be773eeea48c03a4fa92c170934eb2220666809) set(BUN_WORKDIR "${CMAKE_CURRENT_BINARY_DIR}") message(STATUS "Configuring Bun ${Bun_VERSION} in ${BUN_WORKDIR}") @@ -1080,7 +1080,7 @@ elseif(CMAKE_BUILD_TYPE STREQUAL "Release") if(NOT WIN32) if(USE_LTO) - list(APPEND LTO_FLAG "-flto=full" "-emit-llvm") + list(APPEND LTO_FLAG "-flto=full" "-emit-llvm" "-fwhole-program-vtables" "-fforce-emit-vtables") endif() # Leave -Werror=unused off in release builds so we avoid errors from being used in ASSERT @@ -1169,7 +1169,7 @@ if(WIN32) # set_property(TARGET ${bun} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") set_property(TARGET ${bun} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded") - target_compile_options(${bun} PUBLIC "/EHsc" "/GR-") + target_compile_options(${bun} PUBLIC "/EHsc" "/GR-" -Xclang -fno-c++-static-destructors) target_link_options(${bun} PUBLIC "/STACK:0x1200000,0x100000" "/DEF:${BUN_SRC}/symbols.def" "/errorlimit:0") else() @@ -1178,6 +1178,9 @@ else() -fconstexpr-steps=2542484 -fconstexpr-depth=54 -fno-exceptions + -fno-asynchronous-unwind-tables + -fno-unwind-tables + -fno-c++-static-destructors -fvisibility=hidden -fvisibility-inlines-hidden -fno-rtti diff --git a/packages/bun-uws/src/Loop.h b/packages/bun-uws/src/Loop.h index ce4f3da95a..f8ea7f6e3a 100644 --- a/packages/bun-uws/src/Loop.h +++ b/packages/bun-uws/src/Loop.h @@ -95,13 +95,14 @@ private: // This is both a performance thing, and also to prevent freeing some things which are not meant to be freed // such as uv_tty_t if(loop && cleanMe && !bun_is_exiting()) { + cleanMe = false; loop->free(); } } Loop *loop = nullptr; bool cleanMe = false; }; - + static LoopCleaner &getLazyLoop() { static thread_local LoopCleaner lazyLoop; return lazyLoop; @@ -126,6 +127,12 @@ public: return getLazyLoop().loop; } + static void clearLoopAtThreadExit() { + if (getLazyLoop().cleanMe) { + getLazyLoop().loop->free(); + } + } + /* Freeing the default loop should be done once */ void free() { LoopData *loopData = (LoopData *) us_loop_ext((us_loop_t *) this); diff --git a/scripts/env.sh b/scripts/env.sh index 071ce4f989..e86241c515 100755 --- a/scripts/env.sh +++ b/scripts/env.sh @@ -23,17 +23,31 @@ export CC=${CC:-$(which clang-16 || which clang || which cc)} export CXX=${CXX:-$(which clang++-16 || which clang++ || which c++)} export AR=${AR:-$(which llvm-ar || which ar)} export CPUS=${CPUS:-$(nproc || sysctl -n hw.ncpu || echo 1)} +export RANLIB=${RANLIB:-$(which llvm-ranlib-16 || which llvm-ranlib || which ranlib)} + +# on Linux, force using lld as the linker +if [[ $(uname -s) == 'Linux' ]]; then + export LD=${LD:-$(which ld.lld-16 || which ld.lld || which ld)} + export LDFLAGS="${LDFLAGS} -fuse-ld=lld " +fi export CMAKE_CXX_COMPILER=${CXX} export CMAKE_C_COMPILER=${CC} export CFLAGS='-O3 -fno-exceptions -fvisibility=hidden -fvisibility-inlines-hidden -mno-omit-leaf-frame-pointer -fno-omit-frame-pointer -fno-asynchronous-unwind-tables -fno-unwind-tables -faddrsig ' -export CXXFLAGS='-O3 -fno-exceptions -fno-rtti -fvisibility=hidden -fvisibility-inlines-hidden -mno-omit-leaf-frame-pointer -fno-omit-frame-pointer -fno-asynchronous-unwind-tables -fno-unwind-tables -faddrsig ' +export CXXFLAGS='-O3 -fno-exceptions -fno-rtti -fvisibility=hidden -fvisibility-inlines-hidden -mno-omit-leaf-frame-pointer -fno-omit-frame-pointer -fno-asynchronous-unwind-tables -fno-unwind-tables -faddrsig -fno-c++-static-destructors ' + +# Add flags for LTO +if [ "$BUN_ENABLE_LTO" == "1" ]; then + export CFLAGS="$CFLAGS -flto=full " + export CXXFLAGS="$CXXFLAGS -flto=full -fwhole-program-vtables -fforce-emit-vtables " + export LDFLAGS="$LDFLAGS -flto=full -fwhole-program-vtables -fforce-emit-vtables " +fi if [[ $(uname -s) == 'Linux' ]]; then export CFLAGS="$CFLAGS -ffunction-sections -fdata-sections" export CXXFLAGS="$CXXFLAGS -ffunction-sections -fdata-sections" - export LDFLAGS="${LDFLAGS} -Wl,-z,norelro " + export LDFLAGS="${LDFLAGS} -Wl,-z,norelro" fi # libarchive needs position-independent executables to compile successfully diff --git a/src/bun.js/web_worker.zig b/src/bun.js/web_worker.zig index 28a5dbdf6d..ae0a6ac0f0 100644 --- a/src/bun.js/web_worker.zig +++ b/src/bun.js/web_worker.zig @@ -421,6 +421,7 @@ pub const WebWorker = struct { var arena = this.arena; WebWorker__dispatchExit(globalObject, cpp_worker, exit_code); + bun.uws.onThreadExit(); this.deinit(); if (vm_to_deinit) |vm| { diff --git a/src/deps/libuwsockets.cpp b/src/deps/libuwsockets.cpp index c1af335cd7..2741bfca8d 100644 --- a/src/deps/libuwsockets.cpp +++ b/src/deps/libuwsockets.cpp @@ -1632,4 +1632,9 @@ extern "C" return strlen(*dest); } } + + // we need to manually call this at thread exit + extern "C" void bun_clear_loop_at_thread_exit() { + uWS::Loop::clearLoopAtThreadExit(); + } } diff --git a/src/deps/uws.zig b/src/deps/uws.zig index c630dbaf93..eab7032d31 100644 --- a/src/deps/uws.zig +++ b/src/deps/uws.zig @@ -3090,3 +3090,8 @@ pub const udp = struct { extern fn us_udp_packet_buffer_payload(buf: ?*PacketBuffer, index: c_int) [*]u8; extern fn us_udp_packet_buffer_payload_length(buf: ?*PacketBuffer, index: c_int) c_int; }; + +extern fn bun_clear_loop_at_thread_exit() void; +pub fn onThreadExit() void { + bun_clear_loop_at_thread_exit(); +} diff --git a/src/generated_versions_list.zig b/src/generated_versions_list.zig index 6a28038a88..3e17ae8ad3 100644 --- a/src/generated_versions_list.zig +++ b/src/generated_versions_list.zig @@ -4,7 +4,7 @@ pub const boringssl = "29a2cd359458c9384694b75456026e4b57e3e567"; pub const libarchive = "898dc8319355b7e985f68a9819f182aaed61b53a"; pub const mimalloc = "4c283af60cdae205df5a872530c77e2a6a307d43"; pub const picohttpparser = "066d2b1e9ab820703db0837a7255d92d30f0c9f5"; -pub const webkit = "dac47fbd5444cbd4e3568267099ae276c547e897"; +pub const webkit = "2be773eeea48c03a4fa92c170934eb2220666809"; pub const zig = @import("std").fmt.comptimePrint("{}", .{@import("builtin").zig_version}); pub const zlib = "886098f3f339617b4243b286f5ed364b9989e245"; pub const tinycc = "ab631362d839333660a265d3084d8ff060b96753"; diff --git a/test/regression/issue/12650.test.js b/test/regression/issue/12650.test.js index 873bd0eca7..eab73865d2 100644 --- a/test/regression/issue/12650.test.js +++ b/test/regression/issue/12650.test.js @@ -1,4 +1,4 @@ -import {expect, describe, it} from "bun:test"; +import { expect, describe, it } from "bun:test"; // Custom class for testing class CustomException extends Error { @@ -8,16 +8,16 @@ class CustomException extends Error { } } -describe('Test expect.toThrow(expect.any())', () => { - it('should throw an error', () => { +describe("Test expect.toThrow(expect.any())", () => { + it("should throw an error", () => { expect(() => { - throw new CustomException("Custom error message") - }).toThrow(expect.any(Error)) - }) + throw new CustomException("Custom error message"); + }).toThrow(expect.any(Error)); + }); - it('should throw a CustomException', () => { + it("should throw a CustomException", () => { expect(() => { - throw new CustomException("Custom error message") - }).toThrow(expect.any(CustomException)) - }) -}) + throw new CustomException("Custom error message"); + }).toThrow(expect.any(CustomException)); + }); +});