Skip to content

Commit

Permalink
fix(gc): Avoid adding obj being collected in gray stack
Browse files Browse the repository at this point in the history
Could happen while running `collect` method
  • Loading branch information
giann committed Sep 1, 2023
1 parent 2c222e4 commit 9c31d9b
Showing 1 changed file with 10 additions and 9 deletions.
19 changes: 10 additions & 9 deletions src/memory.zig
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,8 @@ pub const GarbageCollector = struct {
objects: std.TailQueue(*Obj) = .{},
gray_stack: std.ArrayList(*Obj),
active_vms: std.AutoHashMap(*VM, void),
collecting: bool = false,
// Obj being collected, useful to avoid setting object instance dirty while running its collector method
obj_collected: ?*Obj = null,

debugger: ?GarbageCollectorDebugger,
where: ?Token = null,
Expand Down Expand Up @@ -385,7 +386,7 @@ pub const GarbageCollector = struct {
}

pub fn markObjDirty(self: *Self, obj: *Obj) !void {
if (!obj.is_dirty) {
if (!obj.is_dirty and self.obj_collected != obj) {
obj.is_dirty = true;

// std.debug.print(
Expand All @@ -406,7 +407,7 @@ pub const GarbageCollector = struct {
}

pub fn markObj(self: *Self, obj: *Obj) !void {
if (obj.is_marked) {
if (obj.is_marked or self.obj_collected == obj) {
if (BuildOptions.gc_debug) {
std.debug.print(
"{*} {s} already marked or old\n",
Expand Down Expand Up @@ -497,6 +498,8 @@ pub const GarbageCollector = struct {
self.debugger.?.collected(obj, self.where.?);
}

self.obj_collected = obj;

self.allocator.destroy(obj.node.?);

switch (obj.obj_type) {
Expand Down Expand Up @@ -641,6 +644,8 @@ pub const GarbageCollector = struct {
free(self, ObjForeignStruct, obj_foreignstruct);
},
}

self.obj_collected = null;
}

pub fn markValue(self: *Self, value: Value) !void {
Expand Down Expand Up @@ -857,13 +862,11 @@ pub const GarbageCollector = struct {
return;
}

if (self.collecting) {
// Avoid triggering another sweep while running collectors
if (self.obj_collected != null) {
return;
}

// Avoid triggering another sweep while running collectors
self.collecting = true;

const mode: Mode = if (self.bytes_allocated > self.next_full_gc and self.last_gc != null) .Full else .Young;

if (BuildOptions.gc_debug or BuildOptions.gc_debug_light) {
Expand Down Expand Up @@ -911,8 +914,6 @@ pub const GarbageCollector = struct {
}
// std.debug.print("gc took {}ms\n", .{timer.read() / 1000000});

self.collecting = false;

self.gc_time += timer.read();
}
};
Expand Down

0 comments on commit 9c31d9b

Please sign in to comment.