Fix memory leaks
This commit is contained in:
		
							parent
							
								
									7b4b827dc2
								
							
						
					
					
						commit
						8137f2b474
					
				| @ -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)) { | ||||||
|  | |||||||
| @ -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}; | ||||||
|  | |||||||
| @ -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 { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user