Fix memory leaks
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/pr Build is passing Details

This commit is contained in:
kayomn 2023-07-22 12:36:47 +01:00
parent 7b4b827dc2
commit 8137f2b474
3 changed files with 48 additions and 22 deletions

View File

@ -142,8 +142,17 @@ pub const RuntimeEnv = struct {
coral.debug.assert(frame != null); coral.debug.assert(frame != null);
coral.debug.assert(self.local_refs.drop( {
(self.local_refs.values.len - frame.?.locals_top) + frame.?.arg_count)); var pops_remaining = (self.local_refs.values.len - frame.?.locals_top) + frame.?.arg_count;
while (pops_remaining != 0) : (pops_remaining -= 1) {
const local = self.local_refs.pop();
coral.debug.assert(local != null);
self.discard(local.?);
}
}
} }
return caller.invoke(self); return caller.invoke(self);
@ -160,7 +169,13 @@ pub const RuntimeEnv = struct {
if (ref_data.ref_count == 0) { if (ref_data.ref_count == 0) {
switch (ref_data.object) { switch (ref_data.object) {
.string => |string| self.allocator.deallocate(string), .string => |string| self.allocator.deallocate(string),
.dynamic => |virtual| self.allocator.deallocate(virtual),
.dynamic => |dynamic| {
dynamic.typeinfo.clean(self, dynamic.userdata);
self.allocator.deallocate(dynamic.userdata);
self.allocator.deallocate(dynamic);
},
else => {}, else => {},
} }
} else { } else {
@ -208,6 +223,12 @@ pub const RuntimeEnv = struct {
} }
pub fn free(self: *RuntimeEnv) void { pub fn free(self: *RuntimeEnv) void {
for (self.local_refs.values) |ref| {
self.discard(ref);
}
self.frames.free();
self.syscallers.free();
self.local_refs.free(); self.local_refs.free();
self.ref_values.free(); self.ref_values.free();
} }
@ -362,7 +383,7 @@ pub const TestContext = struct {
pub const Typeinfo = struct { pub const Typeinfo = struct {
name: []const coral.io.Byte, name: []const coral.io.Byte,
call: *const fn (env: *RuntimeEnv) RuntimeError!?*RuntimeRef = default_call, call: *const fn (env: *RuntimeEnv) RuntimeError!?*RuntimeRef = default_call,
clean: *const fn (userdata: []coral.io.Byte) void = default_clean, clean: *const fn (env: *RuntimeEnv, userdata: []coral.io.Byte) void = default_clean,
get: *const fn (context: IndexContext) RuntimeError!?*RuntimeRef = default_get, get: *const fn (context: IndexContext) RuntimeError!?*RuntimeRef = default_get,
set: *const fn (context: IndexContext, value: ?*const RuntimeRef) RuntimeError!void = default_set, set: *const fn (context: IndexContext, value: ?*const RuntimeRef) RuntimeError!void = default_set,
test_difference: *const fn (context: TestContext) RuntimeError!Float = default_test_difference, test_difference: *const fn (context: TestContext) RuntimeError!Float = default_test_difference,
@ -372,7 +393,7 @@ pub const Typeinfo = struct {
return env.raise(error.TypeMismatch, "object is not callable"); return env.raise(error.TypeMismatch, "object is not callable");
} }
fn default_clean(_: []coral.io.Byte) void { fn default_clean(_: *RuntimeEnv, _: []coral.io.Byte) void {
// Nothing to clean by default. // Nothing to clean by default.
} }
@ -473,13 +494,7 @@ pub fn set_field(
return set(env, indexable_ref, field_name_ref, value_ref); return set(env, indexable_ref, field_name_ref, value_ref);
} }
pub fn new_table(env: *RuntimeEnv) RuntimeError!?*RuntimeRef { pub const new_table = Table.new;
var table = Table.make(env);
errdefer table.free();
return try env.new_dynamic(coral.io.bytes_of(&table), &Table.typeinfo);
}
pub fn test_difference(env: *RuntimeEnv, lhs_ref: ?*const RuntimeRef, rhs_ref: ?*const RuntimeRef) RuntimeError!Float { pub fn test_difference(env: *RuntimeEnv, lhs_ref: ?*const RuntimeRef, rhs_ref: ?*const RuntimeRef) RuntimeError!Float {
return switch (env.unbox(lhs_ref)) { return switch (env.unbox(lhs_ref)) {

View File

@ -211,8 +211,6 @@ pub fn as_caller(self: *Self) kym.Caller {
} }
pub fn compile_ast(self: *Self, ast: Ast) kym.RuntimeError!void { pub fn compile_ast(self: *Self, ast: Ast) kym.RuntimeError!void {
self.free();
try self.constant_refs.grow(coral.math.max_int(@typeInfo(u16).Int)); try self.constant_refs.grow(coral.math.max_int(@typeInfo(u16).Int));
var compiler = AstCompiler{.chunk = self}; var compiler = AstCompiler{.chunk = self};

View File

@ -11,14 +11,16 @@ const FieldTable = coral.map.StringTable(struct {
const Self = @This(); const Self = @This();
pub fn free(self: *Self) void { pub fn new(env: *kym.RuntimeEnv) kym.RuntimeError!?*kym.RuntimeRef {
var self = Self{
.fields = FieldTable.make(env.allocator),
};
errdefer {
self.fields.free(); self.fields.free();
} }
pub fn make(env: *kym.RuntimeEnv) Self { return try env.new_dynamic(coral.io.bytes_of(&self), &typeinfo);
return .{
.fields = FieldTable.make(env.allocator),
};
} }
pub const typeinfo = kym.Typeinfo{ pub const typeinfo = kym.Typeinfo{
@ -28,8 +30,19 @@ pub const typeinfo = kym.Typeinfo{
.set = typeinfo_set, .set = typeinfo_set,
}; };
fn typeinfo_clean(userdata: []u8) void { fn typeinfo_clean(env: *kym.RuntimeEnv, userdata: []coral.io.Byte) void {
@as(*Self, @ptrCast(@alignCast(userdata.ptr))).free(); const table = @as(*Self, @ptrCast(@alignCast(userdata.ptr)));
{
var field_iterable = table.fields.as_iterable();
while (field_iterable.next()) |entry| {
env.discard(entry.value.key_ref);
env.discard(entry.value.value_ref);
}
}
table.fields.free();
} }
fn typeinfo_get(context: kym.IndexContext) kym.RuntimeError!?*kym.RuntimeRef { fn typeinfo_get(context: kym.IndexContext) kym.RuntimeError!?*kym.RuntimeRef {