address review

This commit is contained in:
Meghan Denny
2025-11-19 01:18:25 +01:00
parent 3796a5112f
commit 084e728a68
27 changed files with 74 additions and 3900 deletions

View File

@@ -81,7 +81,6 @@ function getNodeParallelTestTimeout(testPath) {
return 90_000;
}
if (!isCI) return 60_000; // everything slower in debug mode
if (isASAN) return 60_000;
return 20_000;
}
@@ -175,7 +174,7 @@ startGroup("CLI Options", () => {
const cliOptions = options;
const isLSAN = options["step"]?.includes("-lsan-");
const isASAN = options["step"]?.includes("-asan-") || isLSAN;
const isASAN = options["step"]?.includes("-asan-");
if (cliOptions.junit) {
try {

View File

@@ -1,9 +1,14 @@
pub const c_allocator = basic.c_allocator;
pub const z_allocator = basic.z_allocator;
pub const freeWithoutSize = basic.freeWithoutSize;
pub const mimalloc = @import("./allocators/mimalloc.zig");
pub const MimallocArena = @import("./allocators/MimallocArena.zig");
pub const malloc = basic.malloc;
pub const realloc = basic.realloc;
pub const calloc = basic.calloc;
pub const free = basic.free;
pub const usable_size = basic.usable_size;
pub const allocation_scope = @import("./allocators/allocation_scope.zig");
pub const AllocationScope = allocation_scope.AllocationScope;
pub const AllocationScopeIn = allocation_scope.AllocationScopeIn;
@@ -916,7 +921,6 @@ pub fn unpackNullable(comptime Allocator: type, allocator: Nullable(Allocator))
pub const Default = struct {
pub fn allocator(self: Default) std.mem.Allocator {
_ = self;
if (!bun.use_mimalloc) return std.heap.c_allocator;
return c_allocator;
}

View File

@@ -139,10 +139,11 @@ const z_allocator_vtable = Allocator.VTable{
.free = &ZAllocator.free_with_z_allocator,
};
/// mimalloc can free allocations without being given their size.
pub fn freeWithoutSize(ptr: ?*anyopaque) void {
mimalloc.mi_free(ptr);
}
pub const malloc = mimalloc.mi_malloc;
pub const free = mimalloc.mi_free;
pub const realloc = mimalloc.mi_realloc;
pub const calloc = mimalloc.mi_calloc;
pub const usable_size = mimalloc.mi_usable_size;
const Environment = @import("../env.zig");
const std = @import("std");

View File

@@ -1,9 +1,16 @@
pub const c_allocator = std.heap.c_allocator;
pub const z_allocator = @import("./fallback/z.zig").allocator;
/// libc can free allocations without being given their size.
pub fn freeWithoutSize(ptr: ?*anyopaque) void {
std.c.free(ptr);
}
pub const malloc = std.c.malloc;
pub const free = std.c.free;
pub const realloc = std.c.realloc;
pub const calloc = std.c.calloc;
pub const usable_size = switch (Environment.os) {
.mac => std.c.malloc_size,
.linux => std.c.malloc_usable_size,
.windows => std.c._msize,
.wasm => @compileError("unreachable"),
};
const Environment = @import("../env.zig");
const std = @import("std");

View File

@@ -30,7 +30,7 @@ pub fn buildCommand(ctx: bun.cli.Command.Context) !void {
defer arena.deinit();
const vm = try VirtualMachine.initBake(.{
.allocator = arena.allocator(),
.allocator = bun.default_allocator,
.log = ctx.log,
.args = ctx.args,
.smol = ctx.runtime_options.smol,

View File

@@ -59,18 +59,18 @@ pub fn initClient() *boring.SSL {
// may result in deadlocks, crashes, or memory corruption.
export fn OPENSSL_memory_alloc(size: usize) ?*anyopaque {
return bun.default_malloc(size);
return bun.allocators.malloc(size);
}
// BoringSSL always expects memory to be zero'd
export fn OPENSSL_memory_free(ptr: *anyopaque) void {
const len = bun.default_malloc_usable_size(ptr);
const len = bun.allocators.usable_size(ptr);
@memset(@as([*]u8, @ptrCast(ptr))[0..len], 0);
bun.default_free(ptr);
bun.allocators.free(ptr);
}
export fn OPENSSL_memory_get_size(ptr: ?*const anyopaque) usize {
return bun.default_malloc_usable_size(ptr);
return bun.allocators.usable_size(ptr);
}
const INET6_ADDRSTRLEN = if (bun.Environment.isWindows) 65 else 46;

View File

@@ -9,7 +9,7 @@ pub const BrotliAllocator = struct {
return zone.malloc_zone_malloc(len) orelse bun.outOfMemory();
}
return bun.default_malloc(len) orelse bun.outOfMemory();
return bun.allocators.malloc(len) orelse bun.outOfMemory();
}
pub fn free(_: ?*anyopaque, data: ?*anyopaque) callconv(.c) void {
@@ -19,7 +19,7 @@ pub const BrotliAllocator = struct {
return;
}
bun.default_free(data);
bun.allocators.free(data);
}
};

View File

@@ -32,7 +32,7 @@ pub const Run = struct {
run = .{
.vm = try VirtualMachine.initWithModuleGraph(.{
.allocator = arena.allocator(),
.allocator = bun.default_allocator,
.log = ctx.log,
.args = ctx.args,
.graph = graph_ptr,
@@ -165,7 +165,7 @@ pub const Run = struct {
run = .{
.vm = try VirtualMachine.init(
.{
.allocator = arena.allocator(),
.allocator = bun.default_allocator,
.log = ctx.log,
.args = ctx.args,
.store_fd = ctx.debug.hot_reload != .none,

View File

@@ -24,6 +24,7 @@ comptime {
}
global: *JSGlobalObject,
// TODO: initialized to bun.default_allocator now. delete this later.
allocator: std.mem.Allocator,
has_loaded_constructors: bool = false,
transpiler: Transpiler,

View File

@@ -1444,7 +1444,7 @@ pub const JSZlib = struct {
reader.deinit();
}
export fn global_deallocator(_: ?*anyopaque, ctx: ?*anyopaque) void {
bun.default_free(ctx);
bun.allocators.free(ctx);
}
export fn compressor_deallocator(_: ?*anyopaque, ctx: ?*anyopaque) void {
var compressor: *zlib.ZlibCompressorArrayList = bun.cast(*zlib.ZlibCompressorArrayList, ctx.?);
@@ -1728,7 +1728,7 @@ pub const JSZlib = struct {
pub const JSZstd = struct {
export fn deallocator(_: ?*anyopaque, ctx: ?*anyopaque) void {
bun.default_free(ctx);
bun.allocators.free(ctx);
}
inline fn getOptions(globalThis: *JSGlobalObject, callframe: *jsc.CallFrame) bun.JSError!struct { jsc.Node.StringOrBuffer, ?JSValue } {

View File

@@ -23,7 +23,7 @@ pub const HPACK = extern struct {
pub const LSHPACK_MAX_HEADER_SIZE: usize = 65536;
pub fn init(max_capacity: u32) *HPACK {
return lshpack_wrapper_init(bun.default_malloc, bun.default_free, max_capacity) orelse bun.outOfMemory();
return lshpack_wrapper_init(bun.allocators.malloc, bun.allocators.free, max_capacity) orelse bun.outOfMemory();
}
/// DecodeResult name and value uses a thread_local shared buffer and should be copy/cloned before the next decode/encode call

View File

@@ -829,7 +829,7 @@ extern "C" BunString BunString__createExternalGloballyAllocatedLatin1(
{
ASSERT(length > 0);
Ref<WTF::ExternalStringImpl> impl = WTF::ExternalStringImpl::create({ bytes, length }, nullptr, [](void*, void* ptr, size_t) {
bun_free(ptr);
BUN_FREE(ptr);
});
return { BunStringTag::WTFStringImpl, { .wtf = &impl.leakRef() } };
}
@@ -840,7 +840,7 @@ extern "C" BunString BunString__createExternalGloballyAllocatedUTF16(
{
ASSERT(length > 0);
Ref<WTF::ExternalStringImpl> impl = WTF::ExternalStringImpl::create({ bytes, length }, nullptr, [](void*, void* ptr, size_t) {
bun_free(ptr);
BUN_FREE(ptr);
});
return { BunStringTag::WTFStringImpl, { .wtf = &impl.leakRef() } };
}

View File

@@ -11,7 +11,7 @@ extern "C" JSC::EncodedJSValue JSUint8Array__fromDefaultAllocator(JSC::JSGlobalO
JSC::JSUint8Array* uint8Array;
if (length > 0) [[likely]] {
auto buffer = ArrayBuffer::createFromBytes({ ptr, length }, createSharedTask<void(void*)>([](void* p) {
bun_free(p);
BUN_FREE(p);
}));
uint8Array = JSC::JSUint8Array::create(lexicalGlobalObject, lexicalGlobalObject->typedArrayStructureWithTypedArrayType<JSC::TypeUint8>(), WTFMove(buffer), 0, length);
} else {
@@ -26,7 +26,7 @@ extern "C" JSC::EncodedJSValue JSArrayBuffer__fromDefaultAllocator(JSC::JSGlobal
RefPtr<ArrayBuffer> buffer;
if (length > 0) [[likely]] {
buffer = ArrayBuffer::createFromBytes({ ptr, length }, createSharedTask<void(void*)>([](void* p) {
bun_free(p);
BUN_FREE(p);
}));
} else {
buffer = ArrayBuffer::create(0, 1);

View File

@@ -94,7 +94,7 @@ Ref<SourceProvider> SourceProvider::create(
const auto getProvider = [&]() -> Ref<SourceProvider> {
if (resolvedSource.bytecode_cache != nullptr) {
const auto destructorPtr = [](const void* ptr) {
bun_free(const_cast<void*>(ptr));
BUN_FREE(const_cast<void*>(ptr));
};
const auto destructorNoOp = [](const void* ptr) {
// no-op, for bun build --compile.

View File

@@ -843,7 +843,7 @@ export fn ZigString__freeGlobal(ptr: [*]const u8, len: usize) void {
bun.assert(Mimalloc.mi_is_in_heap_region(ptr));
}
// we must untag the string pointer
bun.default_free(untagged);
bun.allocators.free(untagged);
}
const string = []const u8;

View File

@@ -103,9 +103,9 @@
#define ZIG_NONNULL
#if USE(MIMALLOC)
#define bun_free(ptr) mi_free(ptr)
#define BUN_FREE(ptr) mi_free(ptr)
#else
#define bun_free(ptr) free(ptr)
#define BUN_FREE(ptr) free(ptr)
#endif
#endif

View File

@@ -633,7 +633,7 @@ pub const MarkedArrayBuffer = struct {
};
pub export fn MarkedArrayBuffer_deallocator(bytes_: *anyopaque, _: *anyopaque) void {
bun.default_free(bytes_);
bun.allocators.free(bytes_);
}
pub export fn BlobArrayBuffer_deallocator(_: *anyopaque, blob: *anyopaque) void {

View File

@@ -359,22 +359,18 @@ JSC_DECLARE_HOST_FUNCTION(functionCreateMemoryFootprint);
JSC_DEFINE_HOST_FUNCTION(functionCreateMemoryFootprint,
(JSGlobalObject * globalObject, CallFrame*))
{
size_t elapsed_msecs = 0;
size_t user_msecs = 0;
size_t system_msecs = 0;
size_t current_rss = 0;
size_t peak_rss = 0;
size_t current_commit = 0;
size_t peak_commit = 0;
size_t page_faults = 0;
#if USE(MIMALLOC)
#if USE(MIMALLOC)
size_t elapsed_msecs = 0;
size_t user_msecs = 0;
size_t system_msecs = 0;
mi_process_info(&elapsed_msecs, &user_msecs, &system_msecs, &current_rss,
&peak_rss, &current_commit, &peak_commit, &page_faults);
#else
(void)elapsed_msecs;
(void)user_msecs;
(void)system_msecs;
// pass the test in test/js/bun/jsc/bun-jsc.test.ts
// this is not a configuration we publish so it doesn't need to be perfectly accurate
// TODO: putting this todo here anyway so that it's searchable for the future should we decide to change our mind

View File

@@ -326,12 +326,12 @@ pub fn start(
this.arena = bun.MimallocArena.init();
var vm = try jsc.VirtualMachine.initWorker(this, .{
.allocator = this.arena.?.allocator(),
.allocator = bun.default_allocator,
.args = transform_options,
.store_fd = this.store_fd,
.graph = this.parent.standalone_module_graph,
});
vm.allocator = this.arena.?.allocator();
vm.allocator = bun.default_allocator;
vm.arena = &this.arena.?;
var b = &vm.transpiler;

View File

@@ -11,25 +11,11 @@ pub const env_var = @import("./env_var.zig");
pub const feature_flag = env_var.feature_flag;
pub const use_mimalloc = @import("build_options").use_mimalloc;
pub const default_allocator: std.mem.Allocator = (allocators.Default{}).allocator();
pub const default_allocator: std.mem.Allocator = allocators.c_allocator;
/// Zero-sized type whose `allocator` method returns `default_allocator`.
pub const DefaultAllocator = allocators.Default;
/// Zeroing memory allocator
pub const z_allocator: std.mem.Allocator = if (use_mimalloc) allocators.z_allocator else std.heap.c_allocator;
pub const default_malloc = if (use_mimalloc) mimalloc.mi_malloc else std.c.malloc;
pub const default_free = if (use_mimalloc) mimalloc.mi_free else std.c.free;
pub const default_realloc = if (use_mimalloc) mimalloc.mi_realloc else std.c.realloc;
pub const default_calloc = if (use_mimalloc) mimalloc.mi_calloc else std.c.calloc;
pub fn default_malloc_usable_size(p: ?*const anyopaque) usize {
if (use_mimalloc) return mimalloc.mi_usable_size(p);
return switch (Environment.os) {
.mac => std.c.malloc_size(p),
.linux => std.c.malloc_usable_size(p),
.windows => std.c._msize(p),
.wasm => @compileError("unreachable"),
};
}
pub const z_allocator: std.mem.Allocator = allocators.z_allocator;
pub const callmod_inline: std.builtin.CallModifier = if (builtin.mode == .Debug or Environment.enable_asan) .auto else .always_inline;
pub const callconv_inline: std.builtin.CallingConvention = if (builtin.mode == .Debug or Environment.enable_asan) .auto else .@"inline";

View File

@@ -775,9 +775,9 @@ fn libraryInit() void {
const rc = ares_library_init_mem(
ARES_LIB_INIT_ALL,
bun.default_malloc,
bun.default_free,
bun.default_realloc,
bun.allocators.malloc,
bun.allocators.free,
bun.allocators.realloc,
);
if (rc != ARES_SUCCESS) {
std.debug.panic("ares_library_init_mem failed: {d}", .{rc});

View File

@@ -14,7 +14,7 @@ pub extern fn libdeflate_gzip_compress_bound(compressor: *Compressor, in_nbytes:
pub extern fn libdeflate_free_compressor(compressor: *Compressor) void;
fn load_once() void {
libdeflate_set_memory_allocator(bun.default_malloc, bun.default_free);
libdeflate_set_memory_allocator(bun.allocators.malloc, bun.allocators.free);
}
var loaded_once = std.once(load_once);

View File

@@ -35,10 +35,10 @@ pub fn main() void {
// So it's safest to put it very early in the main function.
if (Environment.isWindows) {
_ = _bun.windows.libuv.uv_replace_allocator(
&_bun.default_malloc,
&_bun.default_realloc,
&_bun.default_calloc,
&_bun.default_free,
&_bun.allocators.malloc,
&_bun.allocators.realloc,
&_bun.allocators.calloc,
&_bun.allocators.free,
);
_bun.handleOom(_bun.windows.env.convertEnvToWTF8());
environ = @ptrCast(std.os.environ.ptr);

View File

@@ -136,7 +136,7 @@ pub fn NewZlibReader(comptime Writer: type, comptime buffer_size: usize) type {
}
pub fn free(_: *anyopaque, data: *anyopaque) callconv(.c) void {
bun.default_free(data);
bun.allocators.free(data);
}
pub fn deinit(this: *ZlibReader) void {
@@ -310,7 +310,7 @@ const ZlibAllocator = struct {
return zone.malloc_zone_calloc(items, len) orelse bun.outOfMemory();
}
return bun.default_calloc(items, len) orelse bun.outOfMemory();
return bun.allocators.calloc(items, len) orelse bun.outOfMemory();
}
pub fn free(_: *anyopaque, data: *anyopaque) callconv(.c) void {
@@ -320,7 +320,7 @@ const ZlibAllocator = struct {
return;
}
bun.default_free(data);
bun.allocators.free(data);
}
};
@@ -773,11 +773,11 @@ pub const ZlibCompressorArrayList = struct {
state: State = State.Uninitialized,
pub fn alloc(_: *anyopaque, items: uInt, len: uInt) callconv(.c) *anyopaque {
return bun.default_malloc(items * len) orelse unreachable;
return bun.allocators.malloc(items * len) orelse unreachable;
}
pub fn free(_: *anyopaque, data: *anyopaque) callconv(.c) void {
bun.default_free(data);
bun.allocators.free(data);
}
pub fn deinit(this: *ZlibCompressor) void {

View File

@@ -24,16 +24,10 @@ describe("bun", () => {
test.todo(`respects NO_COLOR=${JSON.stringify(value)} to enable color`, () => {
const { stdout } = spawnSync({
cmd: [bunExe()],
env:
value === undefined
? {
...bunEnv,
NO_COLOR: undefined,
}
: {
...bunEnv,
NO_COLOR: value,
},
env: {
...bunEnv,
NO_COLOR: value,
},
});
expect(stdout.toString()).toMatch(/\u001b\[\d+m/);
});

View File

@@ -1,123 +1,5 @@
leak:bun.js.api.server.ServerAllConnectionsClosedTask.schedule
leak:bunfig.Bunfig.parse__anon
leak:resolver.resolver.Resolver.parsePackageJSON
leak:resolver.package_json.PackageJSON.parse__anon
leak:resolver.resolver.Resolver.parseTSConfig
leak:JSC::Identifier::fromString
leak:bun.js.bindings.JSGlobalObject.JSGlobalObject.create
leak:Zig__GlobalObject__create
leak:_objc_msgSend_uncached
leak:WTF::fastMalloc
leak:WTF::AutomaticThread::start
leak:Bun__transpileFile
leak:WTF::SymbolRegistry::symbolForKey
leak:js_printer.printAst__anon
leak:Bun__resolveSync
leak:JSC::moduleLoaderParseModule
leak:JSC::ScriptExecutable::newCodeBlockFor
leak:JSC::Parser<JSC::Lexer<unsigned char>>::parseFunctionExpression
leak:JSC::Parser<JSC::Lexer<unsigned char>>::parsePrimaryExpression
leak:JSC::Parser<JSC::Lexer<unsigned char>>::parseStatement
leak:JSCInitialize
leak:getaddrinfo_send_reply
leak:start_wqthread
leak:CRYPTO_set_thread_local
leak:BIO_new
leak:_tlv_get_addr
leak:Bun::generateModule
leak:Zig::ImportMetaObject::createFromSpecifier
leak:Zig::GlobalObject::moduleLoaderResolve
leak:JSModuleLoader__import
leak:dyld::ThreadLocalVariables
leak:JSC__JSModuleLoader__loadAndEvaluateModule
leak:uws_create_app
leak:lshpack_wrapper_decode
leak:lshpack_wrapper_init
leak:bun.js.ipc.onData2
leak:bun.js.node.fs_events.InitLibrary
leak:bun.js.node.fs_events.FSEventsLoop._schedule
leak:Bun__Path__join
leak:Bun__Path__resolve
leak:Zig::GlobalObject::moduleLoaderImportModule
leak:bake.FrameworkRouter.JSFrameworkRouter.getFileIdForRouter
leak:ast.Macro.MacroContext.call
leak:bun.js.webcore.Blob.findOrCreateFileFromPath__anon
leak:BunString::toWTFString(BunString::ZeroCopyTag)
leak:bun.js.node.node_fs_binding.Bindings(.mkdtemp).runSync
leak:bun.js.ModuleLoader.fetchBuiltinModule
leak:boringssl.checkX509ServerIdentity
leak:cli.pack_command.bindings.jsReadTarball
leak:ZigString__toErrorInstance
leak:JSC::moduleLoaderModuleDeclarationInstantiation
leak:JSC::arrayProtoFuncSort
leak:bindgen_Fmt_jsFmtString
leak:bun.js.api.bun.dns.GetAddrInfoRequest.run
leak:deps.tcc.State.init__anon
leak:dynamic_library.DlDynLib.open
leak:Zig::ImportMetaObject::finishCreation
leak:uws_add_server_name_with_options
leak:bun.js.webcore.Body.Value.fromJS
leak:sys.Error.toSystemError
leak:bun.js.webcore.Blob.getNameString
leak:JSC::callIntlDateTimeFormat
leak:functionRunProfiler
leak:JSC::JSModuleLoader::evaluateNonVirtual
leak:patch.PatchFile.apply
leak:bun.js.ModuleLoader.RuntimeTranspilerStore.TranspilerJob.runFromJSThread
leak:bun.js.webcore.blob.Store.initS3WithReferencedCredentials
leak:s3.list_objects.S3ListObjectsV2Result.toJS
leak:bun.js.webcore.S3Client.S3Client.write
leak:s3.list_objects.getListObjectsOptionsFromJS
leak:bun.js.node.node_fs.NodeFS.realpathInner
leak:sys.Error.toShellSystemError
leak:lazyLoadSQLite
leak:JSC::intlAvailableLocales
leak:getaddrinfo
leak:bun.js.api.filesystem_router.FileSystemRouter.constructor
leak:JSC::intlSegmenterAvailableLocales
leak:URL__getHref
leak:bun.js.api.bun.dns.Resolver.globalLookupService
leak:jsHTTPParser_execute
leak:Resolver__nodeModulePathsJSValue
leak:URL__host
leak:bun.js.node.node_os.version
leak:bun.js.node.node_os.release
leak:JSC::stringProtoFuncReplaceUsingRegExp
leak:WebCore::parseTypeAndSubtype
leak:bun.js.node.util.parse_args.parseArgs
leak:JSC::IntlDateTimeFormat::initializeDateTimeFormat
leak:WebCore__DOMURL__fileSystemPath
leak:bun.js.node.node_fs_watcher.FSWatcher.Arguments.fromJS
leak:WebWorker__updatePtr
leak:bun.js.node.zlib.NativeZlib.Context.init
leak:sql.postgres.PostgresSQLStatement.structure
leak:sql.postgres.DataCell.parseArray__anon
leak:sql.postgres.protocol.FieldMessage.FieldMessage.init
leak:JSC::intlCollatorAvailableLocales
leak:Bun__canonicalizeIP
leak:dlopen
leak:Bun::evaluateCommonJSModuleOnce
leak:fse_run_loop
leak:Zig::NapiClass_ConstructorFunction
leak:bun.js.webcore.fetch.FetchTasklet.toResponse
leak:JSC::jsonProtoFuncStringify
leak:deps.lol-html.HTMLString.toString
leak:libarchive.libarchive-bindings.Archive.readNew
leak:Zig::SourceProvider::create
leak:fromErrorInstance
# JSC_TO_STRING_TAG_WITHOUT_TRANSITION
leak:TLSSocket__create
leak:WebCore::JSReadableStreamDefaultReaderPrototype::finishCreation
leak:WebCore::JSReadableStreamDefaultControllerPrototype::finishCreation
# file comments below are where it was first seen, not an exhaustive list
# test/js/node/tls/node-tls-cert.test.ts
leak:create_ssl_context_from_bun_options
# test/js/node/test/parallel/test-inspector-enabled.js
leak:bun.js.Debugger.startJSDebuggerThread
# test/js/sql/sqlite-sql.test.ts
leak:WebCore::jsSQLStatementOpenStatementFunction
# ci, test/js/node/test/parallel/test-dgram-unref-in-cluster.js
leak:bun.js.api.bun.udp_socket.UDPSocket.udpSocket
leak:cache.Json.parse__anon
leak:resolver.resolver.Resolver.parsePackageJSON__anon
leak:bunfig.Bunfig.parse__anon
leak:resolver.resolver.Resolver.parseTSConfig

File diff suppressed because it is too large Load Diff