| ... | @@ -363,127 +363,6 @@ pub const wasm_allocator: Allocator = .{ | ... | @@ -363,127 +363,6 @@ pub const wasm_allocator: Allocator = .{ |
| 363 | .vtable = &WasmAllocator.vtable, | 363 | .vtable = &WasmAllocator.vtable, |
| 364 | }; | 364 | }; |
| 365 | | 365 | |
| 366 | pub const HeapAllocator = switch (builtin.os.tag) { | | |
| 367 | .windows => struct { | | |
| 368 | heap_handle: ?HeapHandle, | | |
| 369 | | | |
| 370 | const HeapHandle = windows.HANDLE; | | |
| 371 | | | |
| 372 | pub fn init() HeapAllocator { | | |
| 373 | return HeapAllocator{ | | |
| 374 | .heap_handle = null, | | |
| 375 | }; | | |
| 376 | } | | |
| 377 | | | |
| 378 | pub fn allocator(self: *HeapAllocator) Allocator { | | |
| 379 | return .{ | | |
| 380 | .ptr = self, | | |
| 381 | .vtable = &.{ | | |
| 382 | .alloc = alloc, | | |
| 383 | .resize = resize, | | |
| 384 | .remap = remap, | | |
| 385 | .free = free, | | |
| 386 | }, | | |
| 387 | }; | | |
| 388 | } | | |
| 389 | | | |
| 390 | pub fn deinit(self: *HeapAllocator) void { | | |
| 391 | if (self.heap_handle) |heap_handle| { | | |
| 392 | windows.HeapDestroy(heap_handle); | | |
| 393 | } | | |
| 394 | } | | |
| 395 | | | |
| 396 | fn getRecordPtr(buf: []u8) *align(1) usize { | | |
| 397 | return @as(*align(1) usize, @ptrFromInt(@intFromPtr(buf.ptr) + buf.len)); | | |
| 398 | } | | |
| 399 | | | |
| 400 | fn alloc( | | |
| 401 | ctx: *anyopaque, | | |
| 402 | n: usize, | | |
| 403 | alignment: mem.Alignment, | | |
| 404 | return_address: usize, | | |
| 405 | ) ?[*]u8 { | | |
| 406 | _ = return_address; | | |
| 407 | const self: *HeapAllocator = @ptrCast(@alignCast(ctx)); | | |
| 408 | | | |
| 409 | const ptr_align = alignment.toByteUnits(); | | |
| 410 | const amt = n + ptr_align - 1 + @sizeOf(usize); | | |
| 411 | const optional_heap_handle = @atomicLoad(?HeapHandle, &self.heap_handle, .seq_cst); | | |
| 412 | const heap_handle = optional_heap_handle orelse blk: { | | |
| 413 | const options = if (builtin.single_threaded) windows.HEAP_NO_SERIALIZE else 0; | | |
| 414 | const hh = windows.kernel32.HeapCreate(options, amt, 0) orelse return null; | | |
| 415 | const other_hh = @cmpxchgStrong(?HeapHandle, &self.heap_handle, null, hh, .seq_cst, .seq_cst) orelse break :blk hh; | | |
| 416 | windows.HeapDestroy(hh); | | |
| 417 | break :blk other_hh.?; // can't be null because of the cmpxchg | | |
| 418 | }; | | |
| 419 | const ptr = windows.kernel32.HeapAlloc(heap_handle, 0, amt) orelse return null; | | |
| 420 | const root_addr = @intFromPtr(ptr); | | |
| 421 | const aligned_addr = mem.alignForward(usize, root_addr, ptr_align); | | |
| 422 | const buf = @as([*]u8, @ptrFromInt(aligned_addr))[0..n]; | | |
| 423 | getRecordPtr(buf).* = root_addr; | | |
| 424 | return buf.ptr; | | |
| 425 | } | | |
| 426 | | | |
| 427 | fn resize( | | |
| 428 | ctx: *anyopaque, | | |
| 429 | buf: []u8, | | |
| 430 | alignment: mem.Alignment, | | |
| 431 | new_size: usize, | | |
| 432 | return_address: usize, | | |
| 433 | ) bool { | | |
| 434 | _ = alignment; | | |
| 435 | _ = return_address; | | |
| 436 | const self: *HeapAllocator = @ptrCast(@alignCast(ctx)); | | |
| 437 | | | |
| 438 | const root_addr = getRecordPtr(buf).*; | | |
| 439 | const align_offset = @intFromPtr(buf.ptr) - root_addr; | | |
| 440 | const amt = align_offset + new_size + @sizeOf(usize); | | |
| 441 | const new_ptr = windows.kernel32.HeapReAlloc( | | |
| 442 | self.heap_handle.?, | | |
| 443 | windows.HEAP_REALLOC_IN_PLACE_ONLY, | | |
| 444 | @as(*anyopaque, @ptrFromInt(root_addr)), | | |
| 445 | amt, | | |
| 446 | ) orelse return false; | | |
| 447 | assert(new_ptr == @as(*anyopaque, @ptrFromInt(root_addr))); | | |
| 448 | getRecordPtr(buf.ptr[0..new_size]).* = root_addr; | | |
| 449 | return true; | | |
| 450 | } | | |
| 451 | | | |
| 452 | fn remap( | | |
| 453 | ctx: *anyopaque, | | |
| 454 | buf: []u8, | | |
| 455 | alignment: mem.Alignment, | | |
| 456 | new_size: usize, | | |
| 457 | return_address: usize, | | |
| 458 | ) ?[*]u8 { | | |
| 459 | _ = alignment; | | |
| 460 | _ = return_address; | | |
| 461 | const self: *HeapAllocator = @ptrCast(@alignCast(ctx)); | | |
| 462 | | | |
| 463 | const root_addr = getRecordPtr(buf).*; | | |
| 464 | const align_offset = @intFromPtr(buf.ptr) - root_addr; | | |
| 465 | const amt = align_offset + new_size + @sizeOf(usize); | | |
| 466 | const new_ptr = windows.kernel32.HeapReAlloc(self.heap_handle.?, 0, @ptrFromInt(root_addr), amt) orelse return null; | | |
| 467 | assert(new_ptr == @as(*anyopaque, @ptrFromInt(root_addr))); | | |
| 468 | getRecordPtr(buf.ptr[0..new_size]).* = root_addr; | | |
| 469 | return @ptrCast(new_ptr); | | |
| 470 | } | | |
| 471 | | | |
| 472 | fn free( | | |
| 473 | ctx: *anyopaque, | | |
| 474 | buf: []u8, | | |
| 475 | alignment: mem.Alignment, | | |
| 476 | return_address: usize, | | |
| 477 | ) void { | | |
| 478 | _ = alignment; | | |
| 479 | _ = return_address; | | |
| 480 | const self: *HeapAllocator = @ptrCast(@alignCast(ctx)); | | |
| 481 | windows.HeapFree(self.heap_handle.?, 0, @as(*anyopaque, @ptrFromInt(getRecordPtr(buf).*))); | | |
| 482 | } | | |
| 483 | }, | | |
| 484 | else => @compileError("Unsupported OS"), | | |
| 485 | }; | | |
| 486 | | | |
| 487 | /// Returns a `StackFallbackAllocator` allocating using either a | 366 | /// Returns a `StackFallbackAllocator` allocating using either a |
| 488 | /// `FixedBufferAllocator` on an array of size `size` and falling back to | 367 | /// `FixedBufferAllocator` on an array of size `size` and falling back to |
| 489 | /// `fallback_allocator` if that fails. | 368 | /// `fallback_allocator` if that fails. |
| ... | @@ -628,22 +507,6 @@ test PageAllocator { | ... | @@ -628,22 +507,6 @@ test PageAllocator { |
| 628 | } | 507 | } |
| 629 | } | 508 | } |
| 630 | | 509 | |
| 631 | test HeapAllocator { | | |
| 632 | if (builtin.os.tag == .windows) { | | |
| 633 | // https://github.com/ziglang/zig/issues/13702 | | |
| 634 | if (builtin.cpu.arch == .aarch64) return error.SkipZigTest; | | |
| 635 | | | |
| 636 | var heap_allocator = HeapAllocator.init(); | | |
| 637 | defer heap_allocator.deinit(); | | |
| 638 | const allocator = heap_allocator.allocator(); | | |
| 639 | | | |
| 640 | try testAllocator(allocator); | | |
| 641 | try testAllocatorAligned(allocator); | | |
| 642 | try testAllocatorLargeAlignment(allocator); | | |
| 643 | try testAllocatorAlignedShrink(allocator); | | |
| 644 | } | | |
| 645 | } | | |
| 646 | | | |
| 647 | test ArenaAllocator { | 510 | test ArenaAllocator { |
| 648 | var arena_allocator = ArenaAllocator.init(page_allocator); | 511 | var arena_allocator = ArenaAllocator.init(page_allocator); |
| 649 | defer arena_allocator.deinit(); | 512 | defer arena_allocator.deinit(); |