Compare commits

...

3 Commits

Author SHA1 Message Date
Jarred Sumner
09c899ea24 Comment out usages of arena 2023-07-29 05:54:54 -07:00
Jarred Sumner
aca48ee3f5 Update wtf-bindings.cpp 2023-07-29 04:25:37 -07:00
Jarred Sumner
c708cd8f26 experiment: use bmalloc/libpas instead of mimalloc in most places 2023-07-29 04:24:08 -07:00
18 changed files with 174 additions and 103 deletions

66
src/bmalloc_allocator.zig Normal file
View File

@@ -0,0 +1,66 @@
const mem = @import("std").mem;
const builtin = @import("std").builtin;
const std = @import("std");
pub const bmalloc = struct {
pub fn memalign(alignment: usize, size: usize) ?*anyopaque {
return bun__bmalloc__memalign(alignment, size);
}
pub fn free(ptr: *anyopaque) void {
return bun__bmalloc__free(ptr);
}
pub fn realloc(ptr: *anyopaque, size: usize) ?*anyopaque {
return bun__bmalloc__realloc(ptr, size);
}
pub fn allocatedSize(ptr: *anyopaque) usize {
return bun__bmalloc__size(ptr);
}
extern fn bun__bmalloc__memalign(alignment: usize, size: usize) ?*anyopaque;
extern fn bun__bmalloc__free(*anyopaque) void;
extern fn bun__bmalloc__realloc(*anyopaque, usize) ?*anyopaque;
extern fn bun__bmalloc__size(*anyopaque) usize;
pub extern fn bmalloc_try_allocate_zeroed(size: usize) ?*anyopaque;
pub extern fn bmalloc_deallocate(*anyopaque) void;
pub extern fn bmalloc_get_allocation_size(?*const anyopaque) usize;
};
pub const free = bmalloc.free;
const Allocator = mem.Allocator;
const assert = std.debug.assert;
const CAllocator = struct {
pub const supports_posix_memalign = true;
fn alloc(_: *anyopaque, len: usize, log2_align: u8, _: usize) ?[*]u8 {
const alignment = @as(usize, 1) << @as(Allocator.Log2Align, @intCast(log2_align));
// The posix_memalign only accepts alignment values that are a
// multiple of the pointer size
const eff_alignment = @max(alignment, @sizeOf(usize));
return @ptrCast(bmalloc.memalign(eff_alignment, len));
}
fn resize(_: *anyopaque, buf: []u8, _: u8, new_len: usize, _: usize) bool {
return bmalloc.realloc(buf.ptr, new_len) != null;
}
fn free(
_: *anyopaque,
buf: []u8,
_: u8,
_: usize,
) void {
bmalloc.free(buf.ptr);
}
pub const VTable = Allocator.VTable{
.alloc = &alloc,
.resize = &resize,
.free = &CAllocator.free,
};
};
pub const c_allocator = Allocator{
.ptr = undefined,
.vtable = &CAllocator.VTable,
};

View File

@@ -60,18 +60,16 @@ pub fn initClient() *boring.SSL {
// may result in deadlocks, crashes, or memory corruption.
export fn OPENSSL_memory_alloc(size: usize) ?*anyopaque {
return bun.Mimalloc.mi_malloc(size);
return bun.bmalloc.bmalloc_try_allocate_zeroed(size);
}
// 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);
bun.bmalloc.bmalloc_deallocate(ptr);
}
export fn OPENSSL_memory_get_size(ptr: ?*const anyopaque) usize {
return bun.Mimalloc.mi_usable_size(ptr);
return bun.bmalloc.bmalloc_get_allocation_size(ptr);
}
test "load" {

View File

@@ -1375,7 +1375,8 @@ fn dump_mimalloc(
_: []const JSC.C.JSValueRef,
_: JSC.C.ExceptionRef,
) JSC.C.JSValueRef {
globalThis.bunVM().arena.dumpStats();
_ = globalThis;
// globalThis.bunVM().arena.dumpStats();
return JSC.JSValue.jsUndefined().asObjectRef();
}

View File

@@ -1372,8 +1372,8 @@ pub const Subprocess = struct {
return .zero;
},
// stdout and stderr only uses allocator and default_max_buffer_size if they are pipes and not a array buffer
.stdout = Readable.init(stdio[std.os.STDOUT_FILENO], stdout_pipe[0], jsc_vm.allocator, default_max_buffer_size),
.stderr = Readable.init(stdio[std.os.STDERR_FILENO], stderr_pipe[0], jsc_vm.allocator, default_max_buffer_size),
.stdout = Readable.init(stdio[std.os.STDOUT_FILENO], stdout_pipe[0], bun.default_allocator, default_max_buffer_size),
.stderr = Readable.init(stdio[std.os.STDERR_FILENO], stderr_pipe[0], bun.default_allocator, default_max_buffer_size),
.on_exit_callback = if (on_exit_callback != .zero) JSC.Strong.create(on_exit_callback, globalThis) else .{},
.is_sync = is_sync,
};

View File

@@ -550,7 +550,7 @@ 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(bun.constStrToU8(this.route.pathname).ptr);
bun.default_allocator.free(bun.constStrToU8(this.route.pathname));
}
this.params_list_holder.deinit(bun.default_allocator);

View File

@@ -5104,7 +5104,7 @@ pub fn NewServer(comptime ssl_enabled_: bool, comptime debug_mode_: bool) type {
.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(),
.allocator = bun.default_allocator,
};
if (RequestContext.pool == null) {

View File

@@ -1824,31 +1824,31 @@ pub const ArrayBuffer = extern struct {
return this.value;
}
// If it's not a mimalloc heap buffer, we're not going to call a deallocator
if (this.len > 0 and !bun.Mimalloc.mi_is_in_heap_region(this.ptr)) {
log("toJS but will never free: {d} bytes", .{this.len});
// // If it's not a mimalloc heap buffer, we're not going to call a deallocator
// if (this.len > 0 and !bun.Mimalloc.mi_is_in_heap_region(this.ptr)) {
// log("toJS but will never free: {d} bytes", .{this.len});
if (this.typed_array_type == .ArrayBuffer) {
return JSC.JSValue.fromRef(JSC.C.JSObjectMakeArrayBufferWithBytesNoCopy(
ctx,
this.ptr,
this.byte_len,
null,
null,
exception,
));
}
// if (this.typed_array_type == .ArrayBuffer) {
// return JSC.JSValue.fromRef(JSC.C.JSObjectMakeArrayBufferWithBytesNoCopy(
// ctx,
// this.ptr,
// this.byte_len,
// null,
// null,
// exception,
// ));
// }
return JSC.JSValue.fromRef(JSC.C.JSObjectMakeTypedArrayWithBytesNoCopy(
ctx,
this.typed_array_type.toC(),
this.ptr,
this.byte_len,
null,
null,
exception,
));
}
// return JSC.JSValue.fromRef(JSC.C.JSObjectMakeTypedArrayWithBytesNoCopy(
// ctx,
// this.typed_array_type.toC(),
// this.ptr,
// this.byte_len,
// null,
// null,
// exception,
// ));
// }
return this.toJSUnchecked(ctx, exception);
}

View File

@@ -727,6 +727,10 @@ pub const ZigString = extern struct {
return untagged(this._unsafe_ptr_do_not_use)[0..@min(this.len, std.math.maxInt(u32))];
}
pub fn untaggedPtr(this: *const ZigString) [*]const u8 {
return untagged(this._unsafe_ptr_do_not_use);
}
pub fn dupe(this: ZigString, allocator: std.mem.Allocator) ![]const u8 {
return try allocator.dupe(u8, this.slice());
}
@@ -837,11 +841,12 @@ pub const ZigString = extern struct {
}
inline fn assertGlobal(this: *const ZigString) void {
if (comptime bun.Environment.allow_assert) {
std.debug.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)));
}
_ = this;
// if (comptime bun.Environment.allow_assert) {
// std.debug.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)));
// }
}
pub fn toValue(this: *const ZigString, global: *JSGlobalObject) JSValue {

View File

@@ -243,22 +243,17 @@ const Mimalloc = @import("../../allocators/mimalloc.zig");
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) {
std.debug.assert(Mimalloc.mi_is_in_heap_region(ptr));
}
var ptr = ZigString.init(raw[0..len]).untaggedPtr();
// if (comptime Environment.allow_assert) {
// std.debug.assert(Mimalloc.mi_is_in_heap_region(ptr));
// }
var str = ptr[0..len];
allocator.free(str);
}
export fn ZigString__free_global(ptr: [*]const u8, len: usize) void {
var untagged = @as(*anyopaque, @ptrFromInt(@intFromPtr(ZigString.init(ptr[0..len]).slice().ptr)));
if (comptime Environment.allow_assert) {
std.debug.assert(Mimalloc.mi_is_in_heap_region(ptr));
}
// we must untag the string pointer
Mimalloc.mi_free(untagged);
bun.free(@constCast(ZigString.init(ptr[0..len]).untaggedPtr()));
}
export fn Zig__getAPIGlobals(count: *usize) [*]JSC.C.JSClassRef {

View File

@@ -2,7 +2,35 @@
#include "wtf/text/Base64.h"
#include "wtf/StackTrace.h"
#include "wtf/dtoa.h"
#include "bmalloc/bmalloc.h"
extern "C" void bun__bmalloc__init()
{
WTF::initializeMainThread();
}
extern "C" void* bun__bmalloc__memalign(size_t alignment, size_t size)
{
return bmalloc::api::tryMemalign(alignment, size);
}
extern "C" void bun__bmalloc__free(void* ptr)
{
bmalloc::api::free(ptr);
}
extern "C" void* bun__bmalloc__realloc(void* ptr, size_t size)
{
if (bmalloc_get_allocation_size(ptr) >= size)
return (void*)ptr;
return nullptr;
}
extern "C" size_t bun__bmalloc__size(void* ptr)
{
return bmalloc_get_allocation_size(ptr);
}
extern "C" double WTF__parseDouble(const LChar* string, size_t length, size_t* position)
{

View File

@@ -424,7 +424,6 @@ pub const VirtualMachine = struct {
/// source_mappings
saved_source_map_table: SavedSourceMap.HashTable = undefined,
arena: *Arena = undefined,
has_loaded: bool = false,
transpiled_count: usize = 0,

View File

@@ -169,7 +169,7 @@ pub const WebWorker = struct {
std.debug.assert(this.status == .start);
std.debug.assert(this.vm == null);
this.arena = try bun.MimallocArena.init();
// this.arena = try bun.MimallocArena.init();
var vm = try JSC.VirtualMachine.initWorker(
this.arena.allocator(),
this.parent.bundler.options.transform_options,
@@ -179,7 +179,7 @@ pub const WebWorker = struct {
this,
);
vm.allocator = this.arena.allocator();
vm.arena = &this.arena;
// vm.arena = &this.arena;
var b = &vm.bundler;
@@ -296,7 +296,7 @@ pub const WebWorker = struct {
vm.eventLoop().tickConcurrentWithCount() > 0)
{
vm.global.vm().releaseWeakRefs();
_ = vm.arena.gc(false);
// _ = vm.arena.gc(false);
_ = vm.global.vm().runGC(false);
}

View File

@@ -3,10 +3,7 @@ pub const Environment = @import("env.zig");
pub const use_mimalloc = !Environment.isTest;
pub const default_allocator: std.mem.Allocator = if (!use_mimalloc)
std.heap.c_allocator
else
@import("./memory_allocator.zig").c_allocator;
pub const default_allocator: std.mem.Allocator = @import("./bmalloc_allocator.zig").c_allocator;
pub const huge_allocator: std.mem.Allocator = if (!use_mimalloc)
std.heap.c_allocator
@@ -667,18 +664,8 @@ pub fn once(comptime function: anytype, comptime ReturnType: type) ReturnType {
return Result.execute();
}
pub fn isHeapMemory(memory: anytype) bool {
if (comptime use_mimalloc) {
const Memory = @TypeOf(memory);
if (comptime std.meta.trait.isSingleItemPtr(Memory)) {
return Mimalloc.mi_is_in_heap_region(memory);
}
return Mimalloc.mi_is_in_heap_region(std.mem.sliceAsBytes(memory).ptr);
}
return false;
}
pub const free = @import("./bmalloc_allocator.zig").free;
pub const bmalloc = @import("./bmalloc_allocator.zig").bmalloc;
pub const Mimalloc = @import("./allocators/mimalloc.zig");
pub inline fn isSliceInBuffer(slice: []const u8, buffer: []const u8) bool {

View File

@@ -53,15 +53,14 @@ pub const Run = struct {
js_ast.Expr.Data.Store.create(default_allocator);
js_ast.Stmt.Data.Store.create(default_allocator);
var arena = try Arena.init();
// var arena = try Arena.init();
if (!ctx.debug.loaded_bunfig) {
try bun.CLI.Arguments.loadConfigPath(ctx.allocator, true, "bunfig.toml", &ctx, .RunCommand);
}
run = .{
.vm = try VirtualMachine.initWithModuleGraph(arena.allocator(), ctx.log, graph_ptr),
.arena = arena,
.vm = try VirtualMachine.initWithModuleGraph(bun.default_allocator, ctx.log, graph_ptr),
.ctx = ctx,
.entry_path = entry_path,
};
@@ -70,8 +69,8 @@ pub const Run = struct {
var b = &vm.bundler;
vm.preload = ctx.preloads;
vm.argv = ctx.passthrough;
vm.arena = &run.arena;
vm.allocator = arena.allocator();
// vm.arena = &run.arena;
vm.allocator = bun.default_allocator;
b.options.install = ctx.install;
b.resolver.opts.install = ctx.install;
@@ -137,7 +136,7 @@ pub const Run = struct {
js_ast.Expr.Data.Store.create(default_allocator);
js_ast.Stmt.Data.Store.create(default_allocator);
var arena = try Arena.init();
// var arena = try Arena.init();
if (!ctx.debug.loaded_bunfig) {
try bun.CLI.Arguments.loadConfigPath(ctx.allocator, true, "bunfig.toml", &ctx, .RunCommand);
@@ -145,7 +144,7 @@ pub const Run = struct {
run = .{
.vm = try VirtualMachine.init(
arena.allocator(),
bun.default_allocator,
ctx.args,
null,
ctx.log,
@@ -153,7 +152,7 @@ pub const Run = struct {
ctx.debug.hot_reload != .none,
ctx.runtime_options.smol,
),
.arena = arena,
// .arena = arena,
.ctx = ctx,
.entry_path = entry_path,
};
@@ -162,8 +161,8 @@ pub const Run = struct {
var b = &vm.bundler;
vm.preload = ctx.preloads;
vm.argv = ctx.passthrough;
vm.arena = &run.arena;
vm.allocator = arena.allocator();
// vm.arena = &run.arena;
vm.allocator = bun.default_allocator;
b.options.install = ctx.install;
b.resolver.opts.install = ctx.install;
@@ -294,7 +293,7 @@ pub const Run = struct {
vm.eventLoop().tickConcurrentWithCount() > 0)
{
vm.global.vm().releaseWeakRefs();
_ = vm.arena.gc(false);
// _ = vm.arena.gc(false);
_ = vm.global.vm().runGC(false);
vm.tick();
}

View File

@@ -1030,6 +1030,7 @@ pub const Command = struct {
}
};
extern fn bun__bmalloc__init() void;
pub fn which() Tag {
var args_iter = ArgsIterator{ .buf = std.os.argv };
// first one is the executable name
@@ -1153,6 +1154,8 @@ pub const Command = struct {
// _ = BunxCommand;
}
bun__bmalloc__init();
if (try bun.StandaloneModuleGraph.fromExecutable(bun.default_allocator)) |graph| {
var ctx = Command.Context{
.args = std.mem.zeroes(Api.TransformOptions),

View File

@@ -720,10 +720,11 @@ pub const TestCommand = struct {
}
};
var arena = bun.MimallocArena.init() catch @panic("Unexpected error in mimalloc");
// var arena = bun.MimallocArena.init() catch @panic("Unexpected error in mimalloc");
// _ = arena;
vm_.eventLoop().ensureWaker();
vm_.arena = &arena;
vm_.allocator = arena.allocator();
// vm_.arena = &arena;
vm_.allocator = bun.default_allocator;
var ctx = Context{ .reporter = reporter_, .vm = vm_, .files = files_, .allocator = allocator_ };
vm_.runWithAPILock(Context, &ctx, Context.begin);
}

View File

@@ -1537,7 +1537,7 @@ pub const RequestContext = struct {
vm.global.vm().holdAPILock(handler, JavaScript.OpaqueWrap(HandlerThread, startJavaScript));
}
var __arena: ThreadlocalArena = undefined;
// var __arena: ThreadlocalArena = undefined;
pub fn runLoop(vm: *JavaScript.VirtualMachine, thread: *HandlerThread) !void {
var module_map = JavaScript.ZigGlobalObject.getModuleRegistryMap(vm.global);
@@ -1550,8 +1550,8 @@ pub const RequestContext = struct {
}
while (true) {
__arena = ThreadlocalArena.init() catch unreachable;
JavaScript.VirtualMachine.get().arena = &__arena;
// __arena = ThreadlocalArena.init() catch unreachable;
// JavaScript.VirtualMachine.get().arena = &__arena;
JavaScript.VirtualMachine.get().has_loaded = true;
JavaScript.VirtualMachine.get().tick();
defer {
@@ -1563,7 +1563,7 @@ pub const RequestContext = struct {
js_ast.Expr.Data.Store.reset();
JavaScript.API.Bun.flushCSSImports();
Output.flush();
JavaScript.VirtualMachine.get().arena.deinit();
// JavaScript.VirtualMachine.get().arena.deinit();
JavaScript.VirtualMachine.get().has_loaded = false;
}
@@ -1573,8 +1573,8 @@ pub const RequestContext = struct {
const original_origin = vm.origin;
vm.origin = handler.ctx.origin;
defer vm.origin = original_origin;
handler.ctx.arena = __arena;
handler.ctx.allocator = __arena.allocator();
// handler.ctx.arena = __arena;
// handler.ctx.allocator = __arena.allocator();
var req_body = handler.ctx.req_body_node;
JavaScript.EventListenerMixin.emitFetchEvent(
vm,

View File

@@ -35,8 +35,7 @@ const uws = bun.uws;
pub const MimeType = @import("./http/mime_type.zig");
pub const URLPath = @import("./http/url_path.zig");
// This becomes Arena.allocator
pub var default_allocator: std.mem.Allocator = undefined;
var default_arena: Arena = undefined;
pub const default_allocator = bun.default_allocator;
pub var http_thread: HTTPThread = undefined;
const HiveArray = @import("./hive_array.zig").HiveArray;
const Batch = NetworkThread.Batch;
@@ -627,8 +626,7 @@ pub const HTTPThread = struct {
pub fn onStart(_: FakeStruct) void {
Output.Source.configureNamedThread("HTTP Client");
default_arena = Arena.init() catch unreachable;
default_allocator = default_arena.allocator();
var loop = uws.Loop.create(struct {
pub fn wakeup(_: *uws.Loop) callconv(.C) void {
http_thread.drainEvents();
@@ -869,7 +867,7 @@ pub inline fn getAllocator() std.mem.Allocator {
}
pub inline fn cleanup(force: bool) void {
default_arena.gc(force);
_ = force;
}
pub const Headers = @import("./http/headers.zig");
@@ -2475,15 +2473,6 @@ pub fn done(this: *HTTPClient, comptime is_ssl: bool, ctx: *NewHTTPContext(is_ss
this.state.request_stage = .done;
this.state.stage = .done;
this.proxy_tunneling = false;
if (comptime print_every > 0) {
print_every_i += 1;
if (print_every_i % print_every == 0) {
Output.prettyln("Heap stats for HTTP thread\n", .{});
Output.flush();
default_arena.dumpThreadStats();
print_every_i = 0;
}
}
callback.run(result);
}
}