aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/bun-usockets/src/eventing/epoll_kqueue.c15
-rw-r--r--src/bun.js/api/server.zig3
-rw-r--r--src/bun.js/bindings/JSCUSocketsLoopIntegration.cpp12
-rw-r--r--src/bun.js/event_loop.zig35
-rw-r--r--src/deps/uws.zig10
5 files changed, 50 insertions, 25 deletions
diff --git a/packages/bun-usockets/src/eventing/epoll_kqueue.c b/packages/bun-usockets/src/eventing/epoll_kqueue.c
index df694dd04..44212d3be 100644
--- a/packages/bun-usockets/src/eventing/epoll_kqueue.c
+++ b/packages/bun-usockets/src/eventing/epoll_kqueue.c
@@ -30,7 +30,7 @@ void Bun__internal_dispatch_ready_poll(void* loop, void* poll);
#include <stdint.h>
#endif
-void us_loop_run_bun_tick(struct us_loop_t *loop, int64_t timeoutMs);
+void us_loop_run_bun_tick(struct us_loop_t *loop, int64_t timeoutMs, void*);
/* Pointer tags are used to indicate a Bun pointer versus a uSockets pointer */
#define UNSET_BITS_49_UNTIL_64 0x0000FFFFFFFFFFFF
@@ -174,13 +174,20 @@ void us_loop_run(struct us_loop_t *loop) {
}
}
+void bun_on_tick_before(void* ctx);
+void bun_on_tick_after(void* ctx);
-void us_loop_run_bun_tick(struct us_loop_t *loop, int64_t timeoutMs) {
+
+void us_loop_run_bun_tick(struct us_loop_t *loop, int64_t timeoutMs, void* tickCallbackContext) {
us_loop_integrate(loop);
if (loop->num_polls == 0)
return;
+ if (tickCallbackContext) {
+ bun_on_tick_before(tickCallbackContext);
+ }
+
/* Emit pre callback */
us_internal_loop_pre(loop);
@@ -202,6 +209,10 @@ void us_loop_run_bun_tick(struct us_loop_t *loop, int64_t timeoutMs) {
}
#endif
+ if (tickCallbackContext) {
+ bun_on_tick_after(tickCallbackContext);
+ }
+
/* Iterate ready polls, dispatching them by type */
for (loop->current_ready_poll = 0; loop->current_ready_poll < loop->num_ready_polls; loop->current_ready_poll++) {
struct us_poll_t *poll = GET_READY_POLL(loop, loop->current_ready_poll);
diff --git a/src/bun.js/api/server.zig b/src/bun.js/api/server.zig
index 685267bfd..fd6cc1f2b 100644
--- a/src/bun.js/api/server.zig
+++ b/src/bun.js/api/server.zig
@@ -5118,7 +5118,7 @@ pub fn NewServer(comptime NamespaceType: type, comptime ssl_enabled_: bool, comp
return JSPromise.rejectedPromiseValue(ctx, err);
}
- var request = ctx.bunVM().allocator.create(Request) catch unreachable;
+ var request = bun.default_allocator.create(Request) catch unreachable;
request.* = existing_request;
const response_value = this.config.onRequest.callWithThis(
@@ -5538,6 +5538,7 @@ 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);
+ this.vm.jsc.reportExtraMemory(@sizeOf(RequestContext));
var request_object = this.allocator.create(JSC.WebCore.Request) catch unreachable;
var body = JSC.WebCore.InitRequestBodyValue(.{ .Null = {} }) catch unreachable;
diff --git a/src/bun.js/bindings/JSCUSocketsLoopIntegration.cpp b/src/bun.js/bindings/JSCUSocketsLoopIntegration.cpp
new file mode 100644
index 000000000..f607d586a
--- /dev/null
+++ b/src/bun.js/bindings/JSCUSocketsLoopIntegration.cpp
@@ -0,0 +1,12 @@
+#include "root.h"
+#include "JavaScriptCore/VM.h"
+
+extern "C" void bun_on_tick_before(JSC::VM* vm)
+{
+ // Let the GC do some work while we are idle
+ vm->heap.releaseAccess();
+}
+extern "C" void bun_on_tick_after(JSC::VM* vm)
+{
+ vm->heap.acquireAccess();
+} \ No newline at end of file
diff --git a/src/bun.js/event_loop.zig b/src/bun.js/event_loop.zig
index 7f175a1a1..278e62327 100644
--- a/src/bun.js/event_loop.zig
+++ b/src/bun.js/event_loop.zig
@@ -535,7 +535,7 @@ pub const GarbageCollectionController = struct {
pub fn processGCTimer(this: *GarbageCollectionController) void {
if (this.disabled) return;
- var vm = this.bunVM().global.vm();
+ var vm = this.bunVM().jsc;
this.processGCTimerWithHeapSize(vm, vm.blockBytesAllocated());
}
@@ -576,7 +576,7 @@ pub const GarbageCollectionController = struct {
pub fn performGC(this: *GarbageCollectionController) void {
if (this.disabled) return;
- var vm = this.bunVM().global.vm();
+ var vm = this.bunVM().jsc;
vm.collectAsync();
this.gc_last_heap_size = vm.blockBytesAllocated();
}
@@ -616,7 +616,7 @@ pub const EventLoop = struct {
pub fn tickWhilePaused(this: *EventLoop, done: *bool) void {
while (!done.*) {
- this.virtual_machine.event_loop_handle.?.tick();
+ this.virtual_machine.event_loop_handle.?.tick(this.virtual_machine.jsc);
}
}
extern fn JSC__JSGlobalObject__drainMicrotasks(*JSC.JSGlobalObject) void;
@@ -982,8 +982,9 @@ pub const EventLoop = struct {
}
if (loop.num_polls > 0 or loop.active > 0) {
- loop.tick();
this.processGCTimer();
+ loop.tick(ctx.jsc);
+
ctx.onAfterEventLoop();
// this.afterUSocketsTick();
}
@@ -1006,8 +1007,8 @@ pub const EventLoop = struct {
}
if (loop.num_polls > 0 or loop.active > 0) {
- loop.tickWithTimeout(timeoutMs);
this.processGCTimer();
+ loop.tickWithTimeout(timeoutMs, ctx.jsc);
ctx.onAfterEventLoop();
// this.afterUSocketsTick();
}
@@ -1031,8 +1032,8 @@ pub const EventLoop = struct {
}
}
- loop.tick();
this.processGCTimer();
+ loop.tick(ctx.jsc);
ctx.onAfterEventLoop();
this.tickConcurrent();
this.tick();
@@ -1054,8 +1055,8 @@ pub const EventLoop = struct {
}
if (loop.active > 0) {
- loop.tick();
this.processGCTimer();
+ loop.tick(ctx.jsc);
ctx.onAfterEventLoop();
// this.afterUSocketsTick();
}
@@ -1072,7 +1073,7 @@ pub const EventLoop = struct {
this.processGCTimer();
var global = ctx.global;
- var global_vm = global.vm();
+ var global_vm = ctx.jsc;
while (true) {
while (this.tickWithCount() > 0) : (this.global.handleRejectedPromises()) {
this.tickConcurrent();
@@ -1093,12 +1094,12 @@ pub const EventLoop = struct {
}
pub fn waitForPromise(this: *EventLoop, promise: JSC.AnyPromise) void {
- switch (promise.status(this.global.vm())) {
+ switch (promise.status(this.virtual_machine.jsc)) {
JSC.JSPromise.Status.Pending => {
- while (promise.status(this.global.vm()) == .Pending) {
+ while (promise.status(this.virtual_machine.jsc) == .Pending) {
this.tick();
- if (promise.status(this.global.vm()) == .Pending) {
+ if (promise.status(this.virtual_machine.jsc) == .Pending) {
this.autoTick();
}
}
@@ -1110,16 +1111,16 @@ pub const EventLoop = struct {
// TODO: this implementation is terrible
// we should not be checking the millitimestamp every time
pub fn waitForPromiseWithTimeout(this: *EventLoop, promise: JSC.AnyPromise, timeout: u32) bool {
- return switch (promise.status(this.global.vm())) {
+ return switch (promise.status(this.virtual_machine.jsc)) {
JSC.JSPromise.Status.Pending => {
if (timeout == 0) {
return false;
}
var start_time = std.time.milliTimestamp();
- while (promise.status(this.global.vm()) == .Pending) {
+ while (promise.status(this.virtual_machine.jsc) == .Pending) {
this.tick();
- if (promise.status(this.global.vm()) == .Pending) {
+ if (promise.status(this.virtual_machine.jsc) == .Pending) {
const remaining = std.time.milliTimestamp() - start_time;
if (remaining >= timeout) {
return false;
@@ -1159,7 +1160,7 @@ pub const EventLoop = struct {
this.virtual_machine.event_loop_handle = actual;
this.virtual_machine.gc_controller.init(this.virtual_machine);
// _ = actual.addPostHandler(*JSC.EventLoop, this, JSC.EventLoop.afterUSocketsTick);
- // _ = actual.addPreHandler(*JSC.VM, this.virtual_machine.global.vm(), JSC.VM.drainMicrotasks);
+ // _ = actual.addPreHandler(*JSC.VM, this.virtual_machine.jsc, JSC.VM.drainMicrotasks);
}
}
@@ -1238,7 +1239,7 @@ pub const MiniEventLoop = struct {
while (!isDone(context)) {
if (this.tickConcurrentWithCount() == 0 and this.tasks.count == 0) {
this.loop.num_polls += 1;
- this.loop.tick();
+ this.loop.tick(null);
this.loop.num_polls -= 1;
}
@@ -1329,7 +1330,7 @@ pub const AnyEventLoop = union(enum) {
// var concurrent = bun.default_allocator.create(ConcurrentTask) catch unreachable;
// _ = concurrent.from(JSC.Task.init(&@field(ctx, field)));
// concurrent.auto_delete = true;
- // this.jsc.enqueueTaskConcurrent(concurrent);
+ // this.virtual_machine.jsc.enqueueTaskConcurrent(concurrent);
},
.mini => {
this.mini.enqueueTaskConcurrent(Context, ParentContext, ctx, Callback, field);
diff --git a/src/deps/uws.zig b/src/deps/uws.zig
index b8016a6b7..a565bd47a 100644
--- a/src/deps/uws.zig
+++ b/src/deps/uws.zig
@@ -835,12 +835,12 @@ pub const Loop = extern struct {
return us_wakeup_loop(this);
}
- pub fn tick(this: *Loop) void {
- us_loop_run_bun_tick(this, 0);
+ pub fn tick(this: *Loop, ctx: ?*anyopaque) void {
+ us_loop_run_bun_tick(this, 0, ctx);
}
- pub fn tickWithTimeout(this: *Loop, timeoutMs: i64) void {
- us_loop_run_bun_tick(this, timeoutMs);
+ pub fn tickWithTimeout(this: *Loop, timeoutMs: i64, ctx: ?*anyopaque) void {
+ us_loop_run_bun_tick(this, timeoutMs, ctx);
}
pub fn nextTick(this: *Loop, comptime UserType: type, user_data: UserType, comptime deferCallback: fn (ctx: UserType) void) void {
@@ -902,7 +902,7 @@ pub const Loop = extern struct {
extern fn us_loop_free(loop: ?*Loop) void;
extern fn us_loop_ext(loop: ?*Loop) ?*anyopaque;
extern fn us_loop_run(loop: ?*Loop) void;
- extern fn us_loop_run_bun_tick(loop: ?*Loop, timouetMs: i64) void;
+ extern fn us_loop_run_bun_tick(loop: ?*Loop, timouetMs: i64, ?*anyopaque) void;
extern fn us_wakeup_loop(loop: ?*Loop) void;
extern fn us_loop_integrate(loop: ?*Loop) void;
extern fn us_loop_iteration_number(loop: ?*Loop) c_longlong;