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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	
May be worth adding an assert to check that the VM environment heap is empty by now before calling deinit.