Add Leak Detection to Ona Heap Allocator #15

Merged
kayomn merged 12 commits from ona-allocator-safety-tracker into main 2023-06-04 16:07:47 +02:00
1 changed files with 26 additions and 33 deletions
Showing only changes of commit 331d862246 - Show all commits

View File

@ -69,21 +69,6 @@ const Object = struct {
self.ref_count += 1;
}
pub fn release(self: *Object, env: *Self) bool {
coral.debug.assert(self.ref_count != 0);
self.ref_count -= 1;
if (self.ref_count == 0) {
coral.io.deallocate(env.allocator, self.state.userdata);
self.state.fields.deinit(env.allocator);
return false;
}
return true;
}
};
pub const ObjectInfo = struct {
@ -185,14 +170,7 @@ pub fn check(self: *Self, condition: bool, failure_message: []const u8) !void {
}
pub fn deinit(self: *Self) void {
var global_data = self.heap.fetch(self.global_object);
if (global_data.release(self)) {
self.heap.remove(self.global_object);
} else {
self.heap.assign(self.global_object, global_data);
}
self.discard(.{.object = self.global_object});
self.values.deinit(self.allocator);
self.calls.deinit(self.allocator);
self.heap.deinit(self.allocator);
@ -203,7 +181,19 @@ pub fn discard(self: *Self, val: types.Val) void {
.object => |object| {
var data = self.heap.fetch(object);
if (data.release(self)) {
coral.debug.assert(data.ref_count != 0);
data.ref_count -= 1;
kayomn marked this conversation as resolved Outdated

May be worth adding an assert to check that the VM environment heap is empty by now before calling deinit.

May be worth adding an assert to check that the VM environment heap is empty by now before calling deinit.
if (data.ref_count == 0) {
data.state.info.deinitializer(.{
.env = self,
.obj = val.as_ref(),
});
coral.io.deallocate(self.allocator, data.state.userdata);
data.state.fields.deinit(self.allocator);
self.heap.remove(object);
} else {
self.heap.assign(object, data);
@ -223,17 +213,21 @@ pub fn execute_data(self: *Self, source: DataSource) types.RuntimeError!types.Va
}
};
var chunk = try Chunk.init(self, source.name);
var compiled_chunk = init_compiled_chunk: {
var chunk = try Chunk.init(self, source.name);
errdefer chunk.deinit();
errdefer chunk.deinit();
chunk.compile(source.data) catch |compile_error| {
self.reporter.invoke(chunk.error_details());
chunk.compile(source.data) catch |compile_error| {
self.reporter.invoke(chunk.error_details());
return compile_error;
return compile_error;
};
break: init_compiled_chunk chunk;
};
const script = try self.new_object(coral.io.bytes_of(&chunk), .{
const script = try self.new_object(coral.io.bytes_of(&compiled_chunk), .{
.identity = typeid,
.deinitializer = Behaviors.deinitialize,
});
@ -355,12 +349,11 @@ pub fn native_cast(self: *Self, castable: types.Ref, id: *const anyopaque, compt
try self.check(castable == .object, "invalid type conversion: object");
const object = self.heap.fetch(castable.object);
const alignment = @alignOf(Type);
const is_expected_type = (object.state.info.identity == id) and (object.state.userdata.len == alignment);
const is_expected_type = (object.state.info.identity == id) and (object.state.userdata.len == @sizeOf(Type));
try self.check(is_expected_type, "invalid object cast: native type");
return @ptrCast(*Type, @alignCast(alignment, object.state.userdata));
return @ptrCast(*Type, @alignCast(@alignOf(Type), object.state.userdata));
}
pub fn new_array(self: *Self) coral.io.AllocationError!types.Val {