feature. See also
. The project being documented here (as the example) is the Zig library itself.
SafeAllocator.remap
fn remap(ctx: *anyopaque, memory: []u8, alignment: Alignment, new_len: usize, ra: usize) ?[*]u8
File
Code
fn remap(ctx: *anyopaque, memory: []u8, alignment: Alignment, new_len: usize, ra: usize) ?[*]u8 {
assert(new_len != 0);
const s: *SafeAllocator = @ptrCast(@alignCast(ctx));
const f: *AllocFooter = .of(memory);
f.startModify(.remaped, s, .{ .memory = memory, .alignment = alignment });
// done after the above so that it is still checked that valid memory is passed and there
// is no double modify.
const from_large_alloc = s.isLarge(memory.len, alignment);
const to_large_alloc = s.isLargeOrOom(new_len, alignment) catch {
f.modify.setNone();
return null;
};
if (from_large_alloc != to_large_alloc) {
@branchHint(.unlikely);
f.modify.setNone();
return null;
}
if (from_large_alloc) {
@branchHint(.unlikely);
const entry = f.extended().container.large_entry;
const new_alloc_len = AllocFooter.allocLenLarge(s, new_len);
const new_memory = s.backing.rawRemap(
memory.ptr[0..AllocFooter.allocLenLarge(s, memory.len)],
AllocFooter.allocAlign(alignment),
new_alloc_len,
ra,
) orelse {
f.modify.setNone();
return null;
};
const new_footer = AllocFooter.populate(
@alignCast(new_memory[0..new_alloc_len]),
new_len,
alignment,
ra,
true,
false,
.{ .large_entry = entry },
s,
);
assert(entry.kind == .large_alloc);
entry.* = .fromLargeAlloc(new_footer);
return new_memory;
}
if (new_len < memory.len) {
const fixed_start = Bucket.fillAt(s, @ptrCast(f)) - AllocFooter.allocOffset(new_len);
const moved_start = alignment.forward(fixed_start);
if (moved_start != fixed_start or !f.isExtended()) {
@branchHint(.unlikely);
// maintain the correct allocOffset.
//
// For `!f.isExtended()`: since the memory will no longer be directly after the
// previous footer, the footer needs promoted to an extended one to encode the
// location of the previous footer.
if (!s.advanceBucketAlloc(f, @intCast(moved_start), true, alignment, new_len, ra)) {
@branchHint(.unlikely);
f.modify.setNone();
return null;
}
const new_memory = Bucket.bytes(.of(s, @ptrCast(f)), s)[moved_start..][0..new_len];
@memmove(new_memory, memory[0..new_memory.len]);
return new_memory.ptr;
}
const b: *Bucket = .of(s, @ptrCast(f));
f.extended().len = new_len;
f.checksum = f.actualChecksum(s) ^ s.canary;
captureStackTrace(f.allocTrace(s), ra);
f.modify.setNone();
b.alloc_count.fenceAcqRel();
const new_memory = f.userMemory();
@memmove(new_memory, memory[0..new_memory.len]);
return new_memory.ptr;
}
if (s.growingResizeBucket(f, memory, alignment, new_len, ra)) {
@branchHint(.likely);
return memory.ptr;
} else {
f.modify.setNone();
return null;
}
}