diff --git a/src/boringssl.zig b/src/boringssl.zig index 16e2d500d7..d08d2d2383 100644 --- a/src/boringssl.zig +++ b/src/boringssl.zig @@ -12,12 +12,6 @@ pub fn load() void { boring.SSL_load_error_strings(); boring.ERR_load_BIO_strings(); boring.OpenSSL_add_all_algorithms(); - - if (!builtin.is_test) { - std.mem.doNotOptimizeAway(&OPENSSL_memory_alloc); - std.mem.doNotOptimizeAway(&OPENSSL_memory_get_size); - std.mem.doNotOptimizeAway(&OPENSSL_memory_free); - } } var ctx_store: ?*boring.SSL_CTX = null; @@ -58,19 +52,29 @@ pub fn initClient() *boring.SSL { // into the process, including pthreads locks. Failing to meet these constraints // may result in deadlocks, crashes, or memory corruption. -export fn OPENSSL_memory_alloc(size: usize) ?*anyopaque { - return bun.mimalloc.mi_malloc(size); -} +comptime { + if (bun.use_mimalloc) { + @export(&struct { + pub fn alloc(size: usize) callconv(.C) ?*anyopaque { + return bun.mimalloc.mi_malloc(size); + } + }.alloc, .{ .name = "OPENSSL_memory_alloc" }); -// BoringSSL always expects memory to be zero'd -export fn OPENSSL_memory_free(ptr: *anyopaque) void { - const len = bun.mimalloc.mi_usable_size(ptr); - @memset(@as([*]u8, @ptrCast(ptr))[0..len], 0); - bun.mimalloc.mi_free(ptr); -} + // BoringSSL always expects memory to be zero'd + @export(&struct { + pub fn free(ptr: *anyopaque) callconv(.C) void { + const len = bun.mimalloc.mi_usable_size(ptr); + @memset(@as([*]u8, @ptrCast(ptr))[0..len], 0); + bun.mimalloc.mi_free(ptr); + } + }.free, .{ .name = "OPENSSL_memory_free" }); -export fn OPENSSL_memory_get_size(ptr: ?*const anyopaque) usize { - return bun.mimalloc.mi_usable_size(ptr); + @export(&struct { + pub fn get_size(ptr: ?*const anyopaque) callconv(.C) usize { + return bun.mimalloc.mi_usable_size(ptr); + } + }.get_size, .{ .name = "OPENSSL_memory_get_size" }); + } } const INET6_ADDRSTRLEN = if (bun.Environment.isWindows) 65 else 46; diff --git a/src/brotli.zig b/src/brotli.zig index 29619839cb..f32c9ad056 100644 --- a/src/brotli.zig +++ b/src/brotli.zig @@ -19,7 +19,11 @@ pub const BrotliAllocator = struct { return; } - mimalloc.mi_free(data); + if (comptime bun.use_mimalloc) { + mimalloc.mi_free(data); + } else { + std.c.free(data); + } } }; diff --git a/src/bun.js/api/BunObject.zig b/src/bun.js/api/BunObject.zig index 62713db2a3..caa22fd12b 100644 --- a/src/bun.js/api/BunObject.zig +++ b/src/bun.js/api/BunObject.zig @@ -1468,8 +1468,11 @@ pub const JSZlib = struct { reader.deinit(); } export fn global_deallocator(_: ?*anyopaque, ctx: ?*anyopaque) void { - comptime assert(bun.use_mimalloc); - bun.mimalloc.mi_free(ctx); + if (bun.use_mimalloc) { + bun.mimalloc.mi_free(ctx); + } else { + std.c.free(ctx); + } } export fn compressor_deallocator(_: ?*anyopaque, ctx: ?*anyopaque) void { var compressor: *zlib.ZlibCompressorArrayList = bun.cast(*zlib.ZlibCompressorArrayList, ctx.?); @@ -1752,11 +1755,6 @@ pub const JSZlib = struct { }; pub const JSZstd = struct { - export fn deallocator(_: ?*anyopaque, ctx: ?*anyopaque) void { - comptime assert(bun.use_mimalloc); - bun.mimalloc.mi_free(ctx); - } - inline fn getOptions(globalThis: *JSGlobalObject, callframe: *jsc.CallFrame) bun.JSError!struct { jsc.Node.StringOrBuffer, ?JSValue } { const arguments = callframe.arguments(); const buffer_value: JSValue = if (arguments.len > 0) arguments[0] else .js_undefined; diff --git a/src/bun.js/api/filesystem_router.zig b/src/bun.js/api/filesystem_router.zig index 1d2d52a139..e9bea8b59d 100644 --- a/src/bun.js/api/filesystem_router.zig +++ b/src/bun.js/api/filesystem_router.zig @@ -440,7 +440,11 @@ pub const MatchedRoute = struct { } if (this.needs_deinit) { if (this.route.pathname.len > 0 and bun.mimalloc.mi_is_in_heap_region(this.route.pathname.ptr)) { - bun.mimalloc.mi_free(@constCast(this.route.pathname.ptr)); + if (comptime bun.use_mimalloc) { + bun.mimalloc.mi_free(@constCast(this.route.pathname.ptr)); + } else { + std.c.free(@constCast(this.route.pathname.ptr)); + } } this.params_list_holder.deinit(bun.default_allocator); diff --git a/src/bun.js/bindings/BunString.cpp b/src/bun.js/bindings/BunString.cpp index e35e456dc0..c1550da29d 100644 --- a/src/bun.js/bindings/BunString.cpp +++ b/src/bun.js/bindings/BunString.cpp @@ -714,7 +714,12 @@ extern "C" BunString BunString__createExternalGloballyAllocatedLatin1( { ASSERT(length > 0); Ref impl = WTF::ExternalStringImpl::create({ bytes, length }, nullptr, [](void*, void* ptr, size_t) { +#if __has_feature(address_sanitizer) + // mimalloc is disabled in ASAN builds + free(ptr); +#else mi_free(ptr); +#endif }); return { BunStringTag::WTFStringImpl, { .wtf = &impl.leakRef() } }; } @@ -725,7 +730,12 @@ extern "C" BunString BunString__createExternalGloballyAllocatedUTF16( { ASSERT(length > 0); Ref impl = WTF::ExternalStringImpl::create({ bytes, length }, nullptr, [](void*, void* ptr, size_t) { +#if __has_feature(address_sanitizer) + // mimalloc is disabled in ASAN builds + free(ptr); +#else mi_free(ptr); +#endif }); return { BunStringTag::WTFStringImpl, { .wtf = &impl.leakRef() } }; } diff --git a/src/bun.js/bindings/Uint8Array.cpp b/src/bun.js/bindings/Uint8Array.cpp index 9e37d9225f..699e5435a5 100644 --- a/src/bun.js/bindings/Uint8Array.cpp +++ b/src/bun.js/bindings/Uint8Array.cpp @@ -12,7 +12,12 @@ extern "C" JSC::EncodedJSValue JSUint8Array__fromDefaultAllocator(JSC::JSGlobalO if (length > 0) [[likely]] { auto buffer = ArrayBuffer::createFromBytes({ ptr, length }, createSharedTask([](void* p) { +#if __has_feature(address_sanitizer) + // mimalloc is disabled in ASAN builds + free(p); +#else mi_free(p); +#endif })); uint8Array = JSC::JSUint8Array::create(lexicalGlobalObject, lexicalGlobalObject->typedArrayStructureWithTypedArrayType(), WTFMove(buffer), 0, length); @@ -30,7 +35,12 @@ extern "C" JSC::EncodedJSValue JSArrayBuffer__fromDefaultAllocator(JSC::JSGlobal if (length > 0) [[likely]] { buffer = ArrayBuffer::createFromBytes({ ptr, length }, createSharedTask([](void* p) { +#if __has_feature(address_sanitizer) + // mimalloc is disabled in ASAN builds + free(p); +#else mi_free(p); +#endif })); } else { buffer = ArrayBuffer::create(0, 1); diff --git a/src/bun.js/bindings/ZigSourceProvider.cpp b/src/bun.js/bindings/ZigSourceProvider.cpp index 3ec0fcb9f6..b707f34bd9 100644 --- a/src/bun.js/bindings/ZigSourceProvider.cpp +++ b/src/bun.js/bindings/ZigSourceProvider.cpp @@ -94,7 +94,12 @@ Ref SourceProvider::create( const auto getProvider = [&]() -> Ref { if (resolvedSource.bytecode_cache != nullptr) { const auto destructorPtr = [](const void* ptr) { +#if __has_feature(address_sanitizer) + // mimalloc is disabled in ASAN builds + free(const_cast(ptr)); +#else mi_free(const_cast(ptr)); +#endif }; const auto destructorNoOp = [](const void* ptr) { // no-op, for bun build --compile. diff --git a/src/bun.js/bindings/ZigString.zig b/src/bun.js/bindings/ZigString.zig index 3bf4704818..83a49c21c9 100644 --- a/src/bun.js/bindings/ZigString.zig +++ b/src/bun.js/bindings/ZigString.zig @@ -743,7 +743,7 @@ pub const ZigString = extern struct { } inline fn assertGlobal(this: *const ZigString) void { - if (comptime bun.Environment.allow_assert) { + if (comptime bun.Environment.allow_assert and bun.use_mimalloc) { bun.assert(this.len == 0 or bun.mimalloc.mi_is_in_heap_region(untagged(this._unsafe_ptr_do_not_use)) or bun.mimalloc.mi_check_owned(untagged(this._unsafe_ptr_do_not_use))); @@ -852,7 +852,7 @@ pub const StringPointer = struct { export fn ZigString__free(raw: [*]const u8, len: usize, allocator_: ?*anyopaque) void { var allocator: std.mem.Allocator = @as(*std.mem.Allocator, @ptrCast(@alignCast(allocator_ orelse return))).*; var ptr = ZigString.init(raw[0..len]).slice().ptr; - if (comptime Environment.allow_assert) { + if (comptime Environment.allow_assert and bun.use_mimalloc) { bun.assert(Mimalloc.mi_is_in_heap_region(ptr)); } const str = ptr[0..len]; @@ -862,11 +862,15 @@ export fn ZigString__free(raw: [*]const u8, len: usize, allocator_: ?*anyopaque) export fn ZigString__freeGlobal(ptr: [*]const u8, len: usize) void { const untagged = @as(*anyopaque, @ptrFromInt(@intFromPtr(ZigString.init(ptr[0..len]).slice().ptr))); - if (comptime Environment.allow_assert) { - bun.assert(Mimalloc.mi_is_in_heap_region(ptr)); + if (comptime bun.use_mimalloc) { + if (comptime Environment.allow_assert) { + bun.assert(Mimalloc.mi_is_in_heap_region(ptr)); + } + // we must untag the string pointer + Mimalloc.mi_free(untagged); + } else { + std.c.free(untagged); } - // we must untag the string pointer - Mimalloc.mi_free(untagged); } const string = []const u8; diff --git a/src/bun.js/jsc/array_buffer.zig b/src/bun.js/jsc/array_buffer.zig index 0af270dbca..7f3816e762 100644 --- a/src/bun.js/jsc/array_buffer.zig +++ b/src/bun.js/jsc/array_buffer.zig @@ -628,7 +628,11 @@ pub export fn MarkedArrayBuffer_deallocator(bytes_: *anyopaque, _: *anyopaque) v // mimalloc.mi_heap_check_owned(jsc.VirtualMachine.get().arena.heap.?, bytes_)); // } - mimalloc.mi_free(bytes_); + if (comptime bun.use_mimalloc) { + mimalloc.mi_free(bytes_); + } else { + std.c.free(bytes_); + } } pub export fn BlobArrayBuffer_deallocator(_: *anyopaque, blob: *anyopaque) void { diff --git a/src/bun.zig b/src/bun.zig index 6af7762060..3072bb8c88 100644 --- a/src/bun.zig +++ b/src/bun.zig @@ -8,7 +8,7 @@ const bun = @This(); pub const Environment = @import("./env.zig"); -pub const use_mimalloc = true; +pub const use_mimalloc = !Environment.enable_asan; pub const default_allocator: std.mem.Allocator = if (use_mimalloc) allocators.c_allocator diff --git a/src/zlib.zig b/src/zlib.zig index b869a5ebdf..e41356d554 100644 --- a/src/zlib.zig +++ b/src/zlib.zig @@ -136,7 +136,11 @@ pub fn NewZlibReader(comptime Writer: type, comptime buffer_size: usize) type { } pub fn free(_: *anyopaque, data: *anyopaque) callconv(.C) void { - mimalloc.mi_free(data); + if (comptime bun.use_mimalloc) { + mimalloc.mi_free(data); + } else { + std.c.free(data); + } } pub fn deinit(this: *ZlibReader) void { @@ -310,7 +314,11 @@ const ZlibAllocator = struct { return; } - mimalloc.mi_free(data); + if (comptime bun.use_mimalloc) { + mimalloc.mi_free(data); + } else { + std.c.free(data); + } } }; @@ -757,7 +765,11 @@ pub const ZlibCompressorArrayList = struct { } pub fn free(_: *anyopaque, data: *anyopaque) callconv(.C) void { - mimalloc.mi_free(data); + if (comptime bun.use_mimalloc) { + mimalloc.mi_free(data); + } else { + std.c.free(data); + } } pub fn deinit(this: *ZlibCompressor) void {