Fix leaks and double-frees in Kym VM environment
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details

This commit is contained in:
kayomn 2023-06-04 02:39:57 +00:00
parent 08785b5b54
commit 331d862246
1 changed files with 26 additions and 33 deletions

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;
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,6 +213,7 @@ pub fn execute_data(self: *Self, source: DataSource) types.RuntimeError!types.Va
}
};
var compiled_chunk = init_compiled_chunk: {
var chunk = try Chunk.init(self, source.name);
errdefer chunk.deinit();
@ -233,7 +224,10 @@ pub fn execute_data(self: *Self, source: DataSource) types.RuntimeError!types.Va
return compile_error;
};
const script = try self.new_object(coral.io.bytes_of(&chunk), .{
break: init_compiled_chunk 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 {