Add Leak Detection to Ona Heap Allocator #15
|
@ -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
|
||||
|
||||
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 {
|
||||
|
|
Loading…
Reference in New Issue
May be worth adding an assert to check that the VM environment heap is empty by now before calling deinit.