Files
bun.sh/src/allocators/MemoryReportingAllocator.zig

91 lines
3.0 KiB
Zig

const MemoryReportingAllocator = @This();
const log = bun.Output.scoped(.MEM, false);
child_allocator: std.mem.Allocator,
memory_cost: std.atomic.Value(usize) = std.atomic.Value(usize).init(0),
fn alloc(context: *anyopaque, n: usize, alignment: std.mem.Alignment, return_address: usize) ?[*]u8 {
const this: *MemoryReportingAllocator = @alignCast(@ptrCast(context));
const result = this.child_allocator.rawAlloc(n, alignment, return_address) orelse return null;
_ = this.memory_cost.fetchAdd(n, .monotonic);
if (comptime Environment.allow_assert)
log("malloc({d}) = {d}", .{ n, this.memory_cost.raw });
return result;
}
pub fn discard(this: *MemoryReportingAllocator, buf: []const u8) void {
_ = this.memory_cost.fetchSub(buf.len, .monotonic);
if (comptime Environment.allow_assert)
log("discard({d}) = {d}", .{ buf.len, this.memory_cost.raw });
}
fn resize(context: *anyopaque, buf: []u8, alignment: std.mem.Alignment, new_len: usize, ret_addr: usize) bool {
const this: *MemoryReportingAllocator = @alignCast(@ptrCast(context));
if (this.child_allocator.rawResize(buf, alignment, new_len, ret_addr)) {
_ = this.memory_cost.fetchAdd(new_len -| buf.len, .monotonic);
if (comptime Environment.allow_assert)
log("resize() = {d}", .{this.memory_cost.raw});
return true;
} else {
return false;
}
}
fn free(context: *anyopaque, buf: []u8, alignment: std.mem.Alignment, ret_addr: usize) void {
const this: *MemoryReportingAllocator = @alignCast(@ptrCast(context));
this.child_allocator.rawFree(buf, alignment, ret_addr);
if (comptime Environment.allow_assert) {
_ = this.memory_cost.fetchSub(buf.len, .monotonic);
log("free({d}) = {d}", .{ buf.len, this.memory_cost.raw });
}
}
pub fn wrap(this: *MemoryReportingAllocator, allocator_: std.mem.Allocator) std.mem.Allocator {
this.* = .{
.child_allocator = allocator_,
};
return this.allocator();
}
pub fn allocator(this: *MemoryReportingAllocator) std.mem.Allocator {
return std.mem.Allocator{
.ptr = this,
.vtable = &MemoryReportingAllocator.VTable,
};
}
pub fn report(this: *MemoryReportingAllocator, vm: *jsc.VM) void {
const mem = this.memory_cost.load(.monotonic);
if (mem > 0) {
vm.reportExtraMemory(mem);
if (comptime Environment.allow_assert)
log("report({d})", .{mem});
}
}
pub inline fn assert(this: *const MemoryReportingAllocator) void {
if (comptime !Environment.allow_assert) {
return;
}
const memory_cost = this.memory_cost.load(.monotonic);
if (memory_cost > 0) {
Output.panic("MemoryReportingAllocator still has {d} bytes allocated", .{memory_cost});
}
}
pub const VTable = std.mem.Allocator.VTable{
.alloc = &alloc,
.resize = &resize,
.remap = &std.mem.Allocator.noRemap,
.free = &free,
};
const std = @import("std");
const bun = @import("bun");
const jsc = bun.jsc;
const Environment = bun.Environment;
const Output = bun.Output;