diff --git a/src/async/posix_event_loop.zig b/src/async/posix_event_loop.zig index aa42d1848c..491e09ce7b 100644 --- a/src/async/posix_event_loop.zig +++ b/src/async/posix_event_loop.zig @@ -537,7 +537,7 @@ pub const FilePoll = struct { } }; - const HiveArray = bun.HiveArray(FilePoll, 128).Fallback; + const HiveArray = bun.HiveArray(FilePoll, if (bun.heap_breakdown.enabled) 0 else 128).Fallback; // We defer freeing FilePoll until the end of the next event loop iteration // This ensures that we don't free a FilePoll before the next callback is called @@ -548,9 +548,9 @@ pub const FilePoll = struct { const log = Output.scoped(.FilePoll, false); - pub fn init(allocator: std.mem.Allocator) Store { + pub fn init() Store { return .{ - .hive = HiveArray.init(allocator), + .hive = HiveArray.init(bun.typedAllocator(FilePoll)), }; } diff --git a/src/async/windows_event_loop.zig b/src/async/windows_event_loop.zig index 24a2d7647c..0943d1959b 100644 --- a/src/async/windows_event_loop.zig +++ b/src/async/windows_event_loop.zig @@ -316,9 +316,9 @@ pub const FilePoll = struct { const log = Output.scoped(.FilePoll, false); - pub fn init(allocator: std.mem.Allocator) Store { + pub fn init() Store { return .{ - .hive = HiveArray.init(allocator), + .hive = HiveArray.init(bun.typedAllocator(FilePoll)), }; } diff --git a/src/bun.js/api/JSTranspiler.zig b/src/bun.js/api/JSTranspiler.zig index 966372a0d7..56390b6eb9 100644 --- a/src/bun.js/api/JSTranspiler.zig +++ b/src/bun.js/api/JSTranspiler.zig @@ -247,6 +247,9 @@ pub const TransformTask = struct { this.log.deinit(); this.input_code.deinitAndUnprotect(); this.output_code.deref(); + if (this.tsconfig) |tsconfig| { + tsconfig.destroy(); + } this.destroy(); } diff --git a/src/bun.js/api/server.zig b/src/bun.js/api/server.zig index 29df596df6..19fd82e2fc 100644 --- a/src/bun.js/api/server.zig +++ b/src/bun.js/api/server.zig @@ -1400,7 +1400,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp // This pre-allocates up to 2,048 RequestContext structs. // It costs about 655,632 bytes. - pub const RequestContextStackAllocator = bun.HiveArray(RequestContext, 2048).Fallback; + pub const RequestContextStackAllocator = bun.HiveArray(RequestContext, if (bun.heap_breakdown.enabled) 0 else 2048).Fallback; pub const name = "HTTPRequestContext" ++ (if (debug_mode) "Debug" else "") ++ (if (ThisServer.ssl_enabled) "TLS" else ""); pub const shim = JSC.Shimmer("Bun", name, @This()); @@ -1427,7 +1427,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp blob: JSC.WebCore.AnyBlob = JSC.WebCore.AnyBlob{ .Blob = .{} }, sendfile: SendfileContext = undefined, - request_body: ?*JSC.WebCore.BodyValueRef = null, + request_body: ?*JSC.BodyValueRef = null, request_body_buf: std.ArrayListUnmanaged(u8) = .{}, request_body_content_len: usize = 0, @@ -5300,6 +5300,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp pub const doRequestIP = JSC.wrapInstanceMethod(ThisServer, "requestIP", false); pub usingnamespace NamespaceType; + pub usingnamespace bun.New(@This()); pub fn constructor(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) ?*ThisServer { globalThis.throw("Server() is not a constructor", .{}); @@ -5667,7 +5668,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp existing_request = Request.init( bun.String.createUTF8(url.href), headers, - JSC.WebCore.InitRequestBodyValue(body) catch bun.outOfMemory(), + this.vm.initRequestBodyValue(body) catch bun.outOfMemory(), method, ); } else if (first_arg.as(Request)) |request_| { @@ -5684,8 +5685,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp return JSPromise.rejectedPromiseValue(ctx, err); } - var request = bun.default_allocator.create(Request) catch unreachable; - request.* = existing_request; + var request = Request.new(existing_request); const response_value = this.config.onRequest.call( this.globalThis, @@ -5977,23 +5977,26 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp this.config.deinit(); this.app.destroy(); - const allocator = this.allocator; - allocator.destroy(this); + this.destroy(); } pub fn init(config: ServerConfig, globalThis: *JSGlobalObject) *ThisServer { - var server = bun.default_allocator.create(ThisServer) catch bun.outOfMemory(); - server.* = .{ + var server = ThisServer.new(.{ .globalThis = globalThis, .config = config, .base_url_string_for_joining = bun.default_allocator.dupe(u8, strings.trim(config.base_url.href, "/")) catch unreachable, .vm = JSC.VirtualMachine.get(), .allocator = Arena.getThreadlocalDefault(), - }; + }); if (RequestContext.pool == null) { RequestContext.pool = server.allocator.create(RequestContext.RequestContextStackAllocator) catch bun.outOfMemory(); - RequestContext.pool.?.* = RequestContext.RequestContextStackAllocator.init(server.allocator); + RequestContext.pool.?.* = RequestContext.RequestContextStackAllocator.init( + if (comptime bun.heap_breakdown.enabled) + bun.typedAllocator(RequestContext) + else + bun.default_allocator, + ); } server.request_pool_allocator = RequestContext.pool.?; @@ -6236,20 +6239,19 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp var ctx = this.request_pool_allocator.tryGet() catch bun.outOfMemory(); ctx.create(this, req, resp); this.vm.jsc.reportExtraMemory(@sizeOf(RequestContext)); - var request_object = this.allocator.create(JSC.WebCore.Request) catch bun.outOfMemory(); - var body = JSC.WebCore.InitRequestBodyValue(.{ .Null = {} }) catch unreachable; + var body = this.vm.initRequestBodyValue(.{ .Null = {} }) catch unreachable; ctx.request_body = body; var signal = JSC.WebCore.AbortSignal.new(this.globalThis); ctx.signal = signal; - request_object.* = .{ + const request_object = Request.new(.{ .method = ctx.method, .request_context = AnyRequestContext.init(ctx), .https = ssl_enabled, .signal = signal.ref(), .body = body.ref(), - }; + }); if (comptime debug_mode) { ctx.flags.is_web_browser_navigation = brk: { @@ -6354,21 +6356,20 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp req.setYield(false); var ctx = this.request_pool_allocator.tryGet() catch @panic("ran out of memory"); ctx.create(this, req, resp); - var request_object = this.allocator.create(JSC.WebCore.Request) catch unreachable; - var body = JSC.WebCore.InitRequestBodyValue(.{ .Null = {} }) catch unreachable; + var body = this.vm.initRequestBodyValue(.{ .Null = {} }) catch unreachable; ctx.request_body = body; var signal = JSC.WebCore.AbortSignal.new(this.globalThis); ctx.signal = signal; - request_object.* = .{ + var request_object = Request.new(.{ .method = ctx.method, .request_context = AnyRequestContext.init(ctx), .upgrader = ctx, .https = ssl_enabled, .signal = signal.ref(), .body = body.ref(), - }; + }); ctx.upgrade_context = upgrade_ctx; // We keep the Request object alive for the duration of the request so that we can remove the pointer to the UWS request object. diff --git a/src/bun.js/bindings/bindings.zig b/src/bun.js/bindings/bindings.zig index e0cf20903a..d1aa20bf0e 100644 --- a/src/bun.js/bindings/bindings.zig +++ b/src/bun.js/bindings/bindings.zig @@ -3355,115 +3355,84 @@ pub const JSValue = enum(JSValueReprInt) { pub const name = "JSC::JSValue"; pub const namespace = "JSC"; pub const JSType = enum(u8) { - // The Cell value must come before any JS that is a JSCell. - Cell, - Structure, - String, - HeapBigInt, - Symbol, - - GetterSetter, - CustomGetterSetter, - /// For 32-bit architectures, this wraps a 64-bit JSValue - APIValueWrapper, - - NativeExecutable, - - ProgramExecutable, - ModuleProgramExecutable, - EvalExecutable, - FunctionExecutable, - - UnlinkedFunctionExecutable, - - UnlinkedProgramCodeBlock, - UnlinkedModuleProgramCodeBlock, - UnlinkedEvalCodeBlock, - UnlinkedFunctionCodeBlock, - - CodeBlock, - - JSImmutableButterfly, - JSSourceCode, - JSScriptFetcher, - JSScriptFetchParameters, - - // The Object value must come before any JS that is a subclass of JSObject. - Object, - FinalObject, - JSCallee, - JSFunction, - InternalFunction, - NullSetterFunction, - BooleanObject, - NumberObject, - ErrorInstance, - GlobalProxy, - DirectArguments, - ScopedArguments, - ClonedArguments, - - // Start JSArray s. - Array, - DerivedArray, - // End JSArray s. - - ArrayBuffer, - - // Start JSArrayBufferView s. Keep in sync with the order of FOR_EACH_D_ARRAY__EXCLUDING_DATA_VIEW. - Int8Array, - Uint8Array, - Uint8ClampedArray, - Int16Array, - Uint16Array, - Int32Array, - Uint32Array, - Float32Array, - Float64Array, - BigInt64Array, - BigUint64Array, - DataView, - // End JSArrayBufferView s. - - // JSScope <- JSWithScope - // <- StrictEvalActivation - // <- JSSymbolTableObject <- JSLexicalEnvironment <- JSModuleEnvironment - // <- JSSegmentedVariableObject <- JSGlobalLexicalEnvironment - // <- JSGlobalObject - // Start JSScope s. - // Start environment record s. - GlobalObject, - GlobalLexicalEnvironment, - LexicalEnvironment, - ModuleEnvironment, - StrictEvalActivation, - // End environment record s. - WithScope, - // End JSScope s. - - ModuleNamespaceObject, - ShadowRealm, - RegExpObject, - JSDate, - ProxyObject, - JSGenerator, - JSAsyncGenerator, - JSArrayIterator, - JSMapIterator, - JSSetIterator, - JSStringIterator, - JSPromise, - JSMap, - JSSet, - JSWeakMap, - JSWeakSet, - WebAssemblyModule, - WebAssemblyInstance, - WebAssemblyGCObject, - // Start StringObject s. - StringObject, - DerivedStringObject, - // End StringObject s. + Cell = 0, + Structure = 1, + String = 2, + HeapBigInt = 3, + Symbol = 4, + GetterSetter = 5, + CustomGetterSetter = 6, + APIValueWrapper = 7, + NativeExecutable = 8, + ProgramExecutable = 9, + ModuleProgramExecutable = 10, + EvalExecutable = 11, + FunctionExecutable = 12, + UnlinkedFunctionExecutable = 13, + UnlinkedProgramCodeBlock = 14, + UnlinkedModuleProgramCodeBlock = 15, + UnlinkedEvalCodeBlock = 16, + UnlinkedFunctionCodeBlock = 17, + CodeBlock = 18, + JSImmutableButterfly = 19, + JSSourceCode = 20, + JSScriptFetcher = 21, + JSScriptFetchParameters = 22, + Object = 23, + FinalObject = 24, + JSCallee = 25, + JSFunction = 26, + InternalFunction = 27, + NullSetterFunction = 28, + BooleanObject = 29, + NumberObject = 30, + ErrorInstance = 31, + GlobalProxy = 32, + DirectArguments = 33, + ScopedArguments = 34, + ClonedArguments = 35, + Array = 36, + DerivedArray = 37, + ArrayBuffer = 38, + Int8Array = 39, + Uint8Array = 40, + Uint8ClampedArray = 41, + Int16Array = 42, + Uint16Array = 43, + Int32Array = 44, + Uint32Array = 45, + Float32Array = 46, + Float64Array = 47, + BigInt64Array = 48, + BigUint64Array = 49, + DataView = 50, + GlobalObject = 51, + GlobalLexicalEnvironment = 52, + LexicalEnvironment = 53, + ModuleEnvironment = 54, + StrictEvalActivation = 55, + WithScope = 56, + ModuleNamespaceObject = 57, + ShadowRealm = 58, + RegExpObject = 59, + JSDate = 60, + ProxyObject = 61, + JSGenerator = 62, + JSAsyncGenerator = 63, + JSArrayIterator = 64, + JSMapIterator = 65, + JSSetIterator = 66, + JSStringIterator = 67, + JSPromise = 68, + JSMap = 69, + JSSet = 70, + JSWeakMap = 71, + JSWeakSet = 72, + WebAssemblyModule = 73, + WebAssemblyInstance = 74, + WebAssemblyGCObject = 75, + StringObject = 76, + DerivedStringObject = 77, InternalFieldTuple, diff --git a/src/bun.js/event_loop.zig b/src/bun.js/event_loop.zig index d9f8bc20ad..c280085ca2 100644 --- a/src/bun.js/event_loop.zig +++ b/src/bun.js/event_loop.zig @@ -1802,7 +1802,7 @@ pub const MiniEventLoop = struct { pub fn filePolls(this: *MiniEventLoop) *Async.FilePoll.Store { return this.file_polls_ orelse { this.file_polls_ = this.allocator.create(Async.FilePoll.Store) catch bun.outOfMemory(); - this.file_polls_.?.* = Async.FilePoll.Store.init(this.allocator); + this.file_polls_.?.* = Async.FilePoll.Store.init(); return this.file_polls_.?; }; } diff --git a/src/bun.js/javascript.zig b/src/bun.js/javascript.zig index 2b6ab6c36d..75a99bdbe4 100644 --- a/src/bun.js/javascript.zig +++ b/src/bun.js/javascript.zig @@ -646,6 +646,10 @@ export fn Bun__getVerboseFetchValue() i32 { }; } +const body_value_pool_size = if (bun.heap_breakdown.enabled) 0 else 256; +pub const BodyValueRef = bun.HiveRef(JSC.WebCore.Body.Value, body_value_pool_size); +const BodyValueHiveAllocator = bun.HiveArray(BodyValueRef, body_value_pool_size).Fallback; + /// TODO: rename this to ScriptExecutionContext /// This is the shared global state for a single JS instance execution /// Today, Bun is one VM per thread, so the name "VirtualMachine" sort of makes sense @@ -781,10 +785,16 @@ pub const VirtualMachine = struct { debug_thread_id: if (Environment.allow_assert) std.Thread.Id else void, + body_value_hive_allocator: BodyValueHiveAllocator = undefined, + pub const OnUnhandledRejection = fn (*VirtualMachine, globalObject: *JSC.JSGlobalObject, JSC.JSValue) void; pub const OnException = fn (*ZigException) void; + pub fn initRequestBodyValue(this: *VirtualMachine, body: JSC.WebCore.Body.Value) !*BodyValueRef { + return BodyValueRef.init(body, &this.body_value_hive_allocator); + } + pub fn uwsLoop(this: *const VirtualMachine) *uws.Loop { if (comptime Environment.isPosix) { if (Environment.allow_assert) { @@ -1485,7 +1495,7 @@ pub const VirtualMachine = struct { vm.* = VirtualMachine{ .global = undefined, - .transpiler_store = RuntimeTranspilerStore.init(allocator), + .transpiler_store = RuntimeTranspilerStore.init(), .allocator = allocator, .entry_point = ServerEntryPoint{}, .bundler = bundler, @@ -1555,6 +1565,7 @@ pub const VirtualMachine = struct { } vm.configureDebugger(opts.debugger); + vm.body_value_hive_allocator = BodyValueHiveAllocator.init(bun.typedAllocator(JSC.WebCore.Body.Value)); return vm; } @@ -1600,7 +1611,7 @@ pub const VirtualMachine = struct { vm.* = VirtualMachine{ .global = undefined, - .transpiler_store = RuntimeTranspilerStore.init(allocator), + .transpiler_store = RuntimeTranspilerStore.init(), .allocator = allocator, .entry_point = ServerEntryPoint{}, .bundler = bundler, @@ -1674,6 +1685,7 @@ pub const VirtualMachine = struct { } vm.configureDebugger(opts.debugger); + vm.body_value_hive_allocator = BodyValueHiveAllocator.init(bun.typedAllocator(JSC.WebCore.Body.Value)); return vm; } @@ -1748,7 +1760,7 @@ pub const VirtualMachine = struct { vm.* = VirtualMachine{ .global = undefined, .allocator = allocator, - .transpiler_store = RuntimeTranspilerStore.init(allocator), + .transpiler_store = RuntimeTranspilerStore.init(), .entry_point = ServerEntryPoint{}, .bundler = bundler, .console = console, @@ -1816,6 +1828,7 @@ pub const VirtualMachine = struct { source_code_printer.?.* = js_printer.BufferPrinter.init(writer); source_code_printer.?.ctx.append_null_byte = false; } + vm.body_value_hive_allocator = BodyValueHiveAllocator.init(bun.typedAllocator(JSC.WebCore.Body.Value)); return vm; } diff --git a/src/bun.js/module_loader.zig b/src/bun.js/module_loader.zig index c205a1a0ec..cb0fd1d4ca 100644 --- a/src/bun.js/module_loader.zig +++ b/src/bun.js/module_loader.zig @@ -266,9 +266,9 @@ pub const RuntimeTranspilerStore = struct { pub const Queue = bun.UnboundedQueue(TranspilerJob, .next); - pub fn init(allocator: std.mem.Allocator) RuntimeTranspilerStore { + pub fn init() RuntimeTranspilerStore { return RuntimeTranspilerStore{ - .store = TranspilerJob.Store.init(allocator), + .store = TranspilerJob.Store.init(bun.typedAllocator(TranspilerJob)), }; } @@ -340,7 +340,7 @@ pub const RuntimeTranspilerStore = struct { work_task: JSC.WorkPoolTask = .{ .callback = runFromWorkerThread }, next: ?*TranspilerJob = null, - pub const Store = bun.HiveArray(TranspilerJob, 64).Fallback; + pub const Store = bun.HiveArray(TranspilerJob, if (bun.heap_breakdown.enabled) 0 else 64).Fallback; pub const Fetcher = union(enum) { virtual_module: bun.String, diff --git a/src/bun.js/rare_data.zig b/src/bun.js/rare_data.zig index 1a65e3e287..b0c929ea36 100644 --- a/src/bun.js/rare_data.zig +++ b/src/bun.js/rare_data.zig @@ -156,7 +156,7 @@ pub const HotMap = struct { pub fn filePolls(this: *RareData, vm: *JSC.VirtualMachine) *Async.FilePoll.Store { return this.file_polls_ orelse { this.file_polls_ = vm.allocator.create(Async.FilePoll.Store) catch unreachable; - this.file_polls_.?.* = Async.FilePoll.Store.init(vm.allocator); + this.file_polls_.?.* = Async.FilePoll.Store.init(); return this.file_polls_.?; }; } diff --git a/src/bun.js/webcore/body.zig b/src/bun.js/webcore/body.zig index f526110ab4..ead8eb7bad 100644 --- a/src/bun.js/webcore/body.zig +++ b/src/bun.js/webcore/body.zig @@ -310,6 +310,8 @@ pub const Body = struct { Error: JSValue, Null: void, + pub const heap_breakdown_label = "BodyValue"; + pub fn toBlobIfPossible(this: *Value) void { if (this.* == .WTFStringImpl) { if (this.WTFStringImpl.toUTF8IfNeeded(bun.default_allocator)) |bytes| { diff --git a/src/bun.js/webcore/request.zig b/src/bun.js/webcore/request.zig index 64e72373d1..6d5d3a40dd 100644 --- a/src/bun.js/webcore/request.zig +++ b/src/bun.js/webcore/request.zig @@ -49,22 +49,13 @@ const Body = JSC.WebCore.Body; const Blob = JSC.WebCore.Blob; const Response = JSC.WebCore.Response; -const body_value_pool_size: u16 = 256; -pub const BodyValueRef = bun.HiveRef(Body.Value, body_value_pool_size); -const BodyValueHiveAllocator = bun.HiveArray(BodyValueRef, body_value_pool_size).Fallback; - -var body_value_hive_allocator = BodyValueHiveAllocator.init(bun.default_allocator); - -pub fn InitRequestBodyValue(value: Body.Value) !*BodyValueRef { - return try BodyValueRef.init(value, &body_value_hive_allocator); -} // https://developer.mozilla.org/en-US/docs/Web/API/Request pub const Request = struct { url: bun.String = bun.String.empty, // NOTE(@cirospaciari): renamed to _headers to avoid direct manipulation, use getFetchHeaders, setFetchHeaders, ensureFetchHeaders and hasFetchHeaders instead _headers: ?*FetchHeaders = null, signal: ?*AbortSignal = null, - body: *BodyValueRef, + body: *JSC.BodyValueRef, method: Method = Method.GET, request_context: JSC.API.AnyRequestContext = JSC.API.AnyRequestContext.Null, https: bool = false, @@ -75,6 +66,7 @@ pub const Request = struct { const RequestMixin = BodyMixin(@This()); pub usingnamespace JSC.Codegen.JSRequest; + pub usingnamespace bun.New(@This()); pub const getText = RequestMixin.getText; pub const getBytes = RequestMixin.getBytes; @@ -101,7 +93,7 @@ pub const Request = struct { pub fn init( url: bun.String, headers: ?*FetchHeaders, - body: *BodyValueRef, + body: *JSC.BodyValueRef, method: Method, ) Request { return Request{ @@ -299,10 +291,10 @@ pub const Request = struct { } } - pub fn finalize(this: *Request) callconv(.C) void { + pub fn finalize(this: *Request) void { this.finalizeWithoutDeinit(); _ = this.body.unref(); - bun.default_allocator.destroy(this); + this.destroy(); } pub fn getRedirect( @@ -477,7 +469,8 @@ pub const Request = struct { arguments: []const JSC.JSValue, ) ?Request { var success = false; - const body = InitRequestBodyValue(.{ .Null = {} }) catch { + const vm = globalThis.bunVM(); + const body = vm.initRequestBodyValue(.{ .Null = {} }) catch { return null; }; var req = Request{ @@ -709,11 +702,7 @@ pub const Request = struct { const request = constructInto(globalThis, arguments) orelse { return null; }; - const request_ = getAllocator(globalThis).create(Request) catch { - return null; - }; - request_.* = request; - return request_; + return Request.new(request); } pub fn getBodyValue( @@ -821,8 +810,8 @@ pub const Request = struct { ) void { _ = allocator; this.ensureURL() catch {}; - - const body = InitRequestBodyValue(this.body.value.clone(globalThis)) catch { + const vm = globalThis.bunVM(); + const body = vm.initRequestBodyValue(this.body.value.clone(globalThis)) catch { globalThis.throw("Failed to clone request", .{}); return; }; @@ -841,7 +830,7 @@ pub const Request = struct { } pub fn clone(this: *Request, allocator: std.mem.Allocator, globalThis: *JSGlobalObject) *Request { - const req = allocator.create(Request) catch unreachable; + const req = Request.new(undefined); this.cloneInto(req, allocator, globalThis, false); return req; } diff --git a/src/bun.zig b/src/bun.zig index 3d156f8542..3c26115796 100644 --- a/src/bun.zig +++ b/src/bun.zig @@ -43,6 +43,13 @@ pub const callconv_inline: std.builtin.CallingConvention = if (builtin.mode == . /// FileSystem is a singleton. pub const fs_allocator = default_allocator; +pub fn typedAllocator(comptime T: type) std.mem.Allocator { + if (heap_breakdown.enabled) + return heap_breakdown.allocator(comptime T); + + return default_allocator; +} + pub const C = @import("root").C; pub const sha = @import("./sha.zig"); pub const FeatureFlags = @import("feature_flags.zig"); @@ -1910,15 +1917,17 @@ pub fn Ref(comptime T: type) type { pub fn HiveRef(comptime T: type, comptime capacity: u16) type { return struct { const HiveAllocator = HiveArray(@This(), capacity).Fallback; - ref_count: u32, allocator: *HiveAllocator, value: T, + pub fn init(value: T, allocator: *HiveAllocator) !*@This() { - var this = try allocator.tryGet(); - this.allocator = allocator; - this.ref_count = 1; - this.value = value; + const this = try allocator.tryGet(); + this.* = .{ + .ref_count = 1, + .allocator = allocator, + .value = value, + }; return this; } @@ -1928,8 +1937,9 @@ pub fn HiveRef(comptime T: type, comptime capacity: u16) type { } pub fn unref(this: *@This()) ?*@This() { - this.ref_count -= 1; - if (this.ref_count == 0) { + const ref_count = this.ref_count; + this.ref_count = ref_count - 1; + if (ref_count == 1) { if (@hasDecl(T, "deinit")) { this.value.deinit(); } diff --git a/src/hive_array.zig b/src/hive_array.zig index 0f1ee8d8e5..c3479da816 100644 --- a/src/hive_array.zig +++ b/src/hive_array.zig @@ -67,7 +67,7 @@ pub fn HiveArray(comptime T: type, comptime capacity: u16) type { } pub const Fallback = struct { - hive: HiveArray(T, capacity), + hive: if (capacity > 0) HiveArray(T, capacity) else void, allocator: std.mem.Allocator, pub const This = @This(); @@ -75,37 +75,53 @@ pub fn HiveArray(comptime T: type, comptime capacity: u16) type { pub fn init(allocator: std.mem.Allocator) This { return .{ .allocator = allocator, - .hive = HiveArray(T, capacity).init(), + .hive = if (capacity > 0) HiveArray(T, capacity).init() else {}, }; } pub fn get(self: *This) *T { - if (self.hive.get()) |value| { - return value; + if (comptime capacity > 0) { + if (self.hive.get()) |value| { + return value; + } } return self.allocator.create(T) catch unreachable; } pub fn getAndSeeIfNew(self: *This, new: *bool) *T { - if (self.hive.get()) |value| { - new.* = false; - return value; + if (comptime capacity > 0) { + if (self.hive.get()) |value| { + new.* = false; + return value; + } } return self.allocator.create(T) catch unreachable; } pub fn tryGet(self: *This) !*T { - if (self.hive.get()) |value| { - return value; + if (comptime capacity > 0) { + if (self.hive.get()) |value| { + return value; + } } return try self.allocator.create(T); } + pub fn in(self: *const This, value: *const T) bool { + if (comptime capacity > 0) { + if (self.hive.in(value)) return true; + } + + return false; + } + pub fn put(self: *This, value: *T) void { - if (self.hive.put(value)) return; + if (comptime capacity > 0) { + if (self.hive.put(value)) return; + } self.allocator.destroy(value); } diff --git a/src/resolver/package_json.zig b/src/resolver/package_json.zig index 50fdd81052..a5b539403f 100644 --- a/src/resolver/package_json.zig +++ b/src/resolver/package_json.zig @@ -56,6 +56,8 @@ pub const PackageJSON = struct { production, }; + pub usingnamespace bun.New(@This()); + pub fn generateHash(package_json: *PackageJSON) void { var hashy: [1024]u8 = undefined; @memset(&hashy, 0); diff --git a/src/resolver/resolver.zig b/src/resolver/resolver.zig index f8f027e9e9..9e1a2bdec5 100644 --- a/src/resolver/resolver.zig +++ b/src/resolver/resolver.zig @@ -2499,7 +2499,7 @@ pub const Resolver = struct { const source = logger.Source.initPathString(key_path.text, entry.contents); const file_dir = source.path.sourceDir(); - var result = (try TSConfigJSON.parse(bun.fs_allocator, r.log, source, &r.caches.json)) orelse return null; + var result = (try TSConfigJSON.parse(bun.default_allocator, r.log, source, &r.caches.json)) orelse return null; if (result.hasBaseURL()) { @@ -2559,9 +2559,7 @@ pub const Resolver = struct { ) orelse return null; } - const _pkg = try bun.default_allocator.create(PackageJSON); - _pkg.* = pkg; - return _pkg; + return PackageJSON.new(pkg); } fn dirInfoCached( diff --git a/src/resolver/tsconfig_json.zig b/src/resolver/tsconfig_json.zig index f5a61a0dee..22dd62cdc6 100644 --- a/src/resolver/tsconfig_json.zig +++ b/src/resolver/tsconfig_json.zig @@ -57,6 +57,7 @@ pub const TSConfigJSON = struct { emit_decorator_metadata: bool = false, + pub usingnamespace bun.New(@This()); pub fn hasBaseURL(tsconfig: *const TSConfigJSON) bool { return tsconfig.base_url.len > 0; } @@ -323,13 +324,7 @@ pub const TSConfigJSON = struct { assert(result.base_url.len > 0); } - const _result = allocator.create(TSConfigJSON) catch unreachable; - _result.* = result; - - if (Environment.isDebug and has_base_url) { - assert(_result.base_url.len > 0); - } - return _result; + return TSConfigJSON.new(result); } pub fn isValidTSConfigPathPattern(text: string, log: *logger.Log, source: *const logger.Source, loc: logger.Loc, allocator: std.mem.Allocator) bool {