Skip to content

Commit

Permalink
Use GC.extend instead of GC.realloc and add assertions and memory acc…
Browse files Browse the repository at this point in the history
…ess tests to GCAllocator.

See #470.
  • Loading branch information
s-ludwig committed May 16, 2014
1 parent 7d22466 commit 151420b
Showing 1 changed file with 26 additions and 11 deletions.
37 changes: 26 additions & 11 deletions source/vibe/utils/memory.d
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ shared class MallocAllocator : Allocator {
size_t csz = min(mem.length, new_size);
auto p = extractUnalignedPointer(mem.ptr);
size_t oldmisalign = mem.ptr - p;

auto pn = cast(ubyte*).realloc(p, new_size+Allocator.alignment);
if (p == pn) return pn[oldmisalign .. new_size+oldmisalign];

Expand Down Expand Up @@ -196,25 +197,32 @@ shared class MallocAllocator : Allocator {
shared class GCAllocator : Allocator {
void[] alloc(size_t sz)
{
return adjustPointerAlignment(GC.malloc(sz+Allocator.alignment))[0 .. sz];
auto mem = GC.malloc(sz+Allocator.alignment);
auto alignedmem = adjustPointerAlignment(mem);
assert(alignedmem - mem <= Allocator.alignment);
auto ret = alignedmem[0 .. sz];
ensureValidMemory(ret);
return ret;
}
void[] realloc(void[] mem, size_t new_size)
{
size_t csz = min(mem.length, new_size);

auto p = extractUnalignedPointer(mem.ptr);
size_t misalign = mem.ptr - p;
auto pn = cast(ubyte*)GC.realloc(p, new_size+Allocator.alignment);
if (p == pn) return pn[misalign .. new_size+misalign];

auto pna = cast(ubyte*)adjustPointerAlignment(pn);
assert(misalign <= Allocator.alignment);

// account for both, possibly changed alignment and a possible
// GC bug where only part of the old memory chunk is copied to
// the new one
pna[0 .. csz] = (cast(ubyte[])mem)[0 .. csz];

return pna[0 .. new_size];
void[] ret;
auto extended = GC.extend(p, new_size - mem.length, new_size - mem.length);
if (extended) {
assert(extended >= new_size+Allocator.alignment);
ret = p[misalign .. new_size+misalign];
} else {
ret = alloc(new_size);
ret[0 .. csz] = mem[0 .. csz];
}
ensureValidMemory(ret);
return ret;
}
void free(void[] mem)
{
Expand Down Expand Up @@ -675,3 +683,10 @@ unittest {
assert(ia < i+Allocator.alignment);
}
}

private void ensureValidMemory(void[] mem)
{
auto bytes = cast(ubyte[])mem;
swap(bytes[0], bytes[$-1]);
swap(bytes[0], bytes[$-1]);
}

0 comments on commit 151420b

Please sign in to comment.