Add Leak Detection to Ona Heap Allocator #15
| @ -69,21 +69,6 @@ const Object = struct { | |||||||
| 
 | 
 | ||||||
| 		self.ref_count += 1; | 		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 { | 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 { | pub fn deinit(self: *Self) void { | ||||||
| 	var global_data = self.heap.fetch(self.global_object); | 	self.discard(.{.object = self.global_object}); | ||||||
| 
 |  | ||||||
| 	if (global_data.release(self)) { |  | ||||||
| 		self.heap.remove(self.global_object); |  | ||||||
| 	} else { |  | ||||||
| 		self.heap.assign(self.global_object, global_data); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	self.values.deinit(self.allocator); | 	self.values.deinit(self.allocator); | ||||||
| 	self.calls.deinit(self.allocator); | 	self.calls.deinit(self.allocator); | ||||||
| 	self.heap.deinit(self.allocator); | 	self.heap.deinit(self.allocator); | ||||||
| @ -203,7 +181,19 @@ pub fn discard(self: *Self, val: types.Val) void { | |||||||
| 		.object => |object| { | 		.object => |object| { | ||||||
| 			var data = self.heap.fetch(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); | 				self.heap.remove(object); | ||||||
| 			} else { | 			} else { | ||||||
| 				self.heap.assign(object, data); | 				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| { | 		chunk.compile(source.data) catch |compile_error| { | ||||||
| 		self.reporter.invoke(chunk.error_details()); | 			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, | 		.identity = typeid, | ||||||
| 		.deinitializer = Behaviors.deinitialize, | 		.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"); | 	try self.check(castable == .object, "invalid type conversion: object"); | ||||||
| 
 | 
 | ||||||
| 	const object = self.heap.fetch(castable.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 == @sizeOf(Type)); | ||||||
| 	const is_expected_type = (object.state.info.identity == id) and (object.state.userdata.len == alignment); |  | ||||||
| 
 | 
 | ||||||
| 	try self.check(is_expected_type, "invalid object cast: native 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 { | 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.