Skip to content

Commit aa0cffb

Browse files
authored
Merge pull request odin-lang#5328 from laytan/compat-allocator-improvements
mem: compat allocator improvements
2 parents f03484e + 67a8b03 commit aa0cffb

File tree

1 file changed

+56
-20
lines changed

1 file changed

+56
-20
lines changed

core/mem/allocators.odin

Lines changed: 56 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2296,7 +2296,7 @@ buddy_allocator_proc :: proc(
22962296
// on the old size to work.
22972297
//
22982298
// The overhead of this allocator is an extra max(alignment, size_of(Header)) bytes allocated for each allocation, these bytes are
2299-
// used to store the size and original pointer.
2299+
// used to store the size and alignment.
23002300
Compat_Allocator :: struct {
23012301
parent: Allocator,
23022302
}
@@ -2316,52 +2316,88 @@ compat_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
23162316
size, alignment: int,
23172317
old_memory: rawptr, old_size: int,
23182318
location := #caller_location) -> (data: []byte, err: Allocator_Error) {
2319-
size, old_size := size, old_size
2320-
23212319
Header :: struct {
2322-
size: int,
2323-
ptr: rawptr,
2320+
size: int,
2321+
alignment: int,
2322+
}
2323+
2324+
@(no_sanitize_address)
2325+
get_unpoisoned_header :: #force_inline proc(ptr: rawptr) -> Header {
2326+
header := ([^]Header)(ptr)[-1]
2327+
a := max(header.alignment, size_of(Header))
2328+
sanitizer.address_unpoison(rawptr(uintptr(ptr)-uintptr(a)), a)
2329+
return header
23242330
}
23252331

23262332
rra := (^Compat_Allocator)(allocator_data)
23272333
switch mode {
23282334
case .Alloc, .Alloc_Non_Zeroed:
2329-
a := max(alignment, size_of(Header))
2330-
size += a
2331-
assert(size >= 0, "overflow")
2335+
a := max(alignment, size_of(Header))
2336+
req_size := size + a
2337+
assert(req_size >= 0, "overflow")
23322338

2333-
allocation := rra.parent.procedure(rra.parent.data, mode, size, alignment, old_memory, old_size, location) or_return
2339+
allocation := rra.parent.procedure(rra.parent.data, mode, req_size, alignment, old_memory, old_size, location) or_return
23342340
#no_bounds_check data = allocation[a:]
23352341

23362342
([^]Header)(raw_data(data))[-1] = {
2337-
size = size,
2338-
ptr = raw_data(allocation),
2343+
size = size,
2344+
alignment = alignment,
23392345
}
2346+
2347+
sanitizer.address_poison(raw_data(allocation), a)
23402348
return
23412349

23422350
case .Free:
2343-
header := ([^]Header)(old_memory)[-1]
2344-
return rra.parent.procedure(rra.parent.data, mode, size, alignment, header.ptr, header.size, location)
2351+
header := get_unpoisoned_header(old_memory)
2352+
a := max(header.alignment, size_of(Header))
2353+
orig_ptr := rawptr(uintptr(old_memory)-uintptr(a))
2354+
orig_size := header.size + a
2355+
2356+
return rra.parent.procedure(rra.parent.data, mode, orig_size, header.alignment, orig_ptr, orig_size, location)
23452357

23462358
case .Resize, .Resize_Non_Zeroed:
2347-
header := ([^]Header)(old_memory)[-1]
2359+
header := get_unpoisoned_header(old_memory)
2360+
orig_a := max(header.alignment, size_of(Header))
2361+
orig_ptr := rawptr(uintptr(old_memory)-uintptr(orig_a))
2362+
orig_size := header.size + orig_a
2363+
2364+
new_alignment := max(header.alignment, alignment)
23482365

2349-
a := max(alignment, size_of(header))
2350-
size += a
2366+
a := max(new_alignment, size_of(header))
2367+
req_size := size + a
23512368
assert(size >= 0, "overflow")
23522369

2353-
allocation := rra.parent.procedure(rra.parent.data, mode, size, alignment, header.ptr, header.size, location) or_return
2370+
allocation := rra.parent.procedure(rra.parent.data, mode, req_size, new_alignment, orig_ptr, orig_size, location) or_return
23542371
#no_bounds_check data = allocation[a:]
23552372

23562373
([^]Header)(raw_data(data))[-1] = {
2357-
size = size,
2358-
ptr = raw_data(allocation),
2374+
size = size,
2375+
alignment = new_alignment,
23592376
}
2377+
2378+
sanitizer.address_poison(raw_data(allocation), a)
23602379
return
23612380

2362-
case .Free_All, .Query_Info, .Query_Features:
2381+
case .Free_All:
23632382
return rra.parent.procedure(rra.parent.data, mode, size, alignment, old_memory, old_size, location)
23642383

2384+
case .Query_Info:
2385+
info := (^Allocator_Query_Info)(old_memory)
2386+
if info != nil && info.pointer != nil {
2387+
header := get_unpoisoned_header(info.pointer)
2388+
info.size = header.size
2389+
info.alignment = header.alignment
2390+
}
2391+
return
2392+
2393+
case .Query_Features:
2394+
data, err = rra.parent.procedure(rra.parent.data, mode, size, alignment, old_memory, old_size, location)
2395+
if err != nil {
2396+
set := (^Allocator_Mode_Set)(old_memory)
2397+
set^ += {.Query_Info}
2398+
}
2399+
return
2400+
23652401
case: unreachable()
23662402
}
23672403
}

0 commit comments

Comments
 (0)