try harder in low memory situations in Zone::allocate

Instead of giving up when the backing allocator's tryAllocate method
returns null, we switch to the allocate method to show we mean
business.  This makes use of zones more robust under low memory
situations since it allows us to exceed the soft memory ceiling when
the only alternative is to abort.
This commit is contained in:
Joel Dice 2011-03-25 18:14:34 -06:00
parent 61552b6b8a
commit d928d695ff

View File

@ -49,21 +49,23 @@ class Zone: public Allocator {
segment = 0;
}
bool ensure(unsigned space) {
if (segment == 0 or position + space > segment->size) {
unsigned size = max
(space, max
(minimumFootprint, segment == 0 ? 0 : segment->size * 2))
+ sizeof(Segment);
static unsigned padToPage(unsigned size) {
return (size + (LikelyPageSizeInBytes - 1))
& ~(LikelyPageSizeInBytes - 1);
}
// pad to page size
size = (size + (LikelyPageSizeInBytes - 1))
& ~(LikelyPageSizeInBytes - 1);
bool tryEnsure(unsigned space) {
if (segment == 0 or position + space > segment->size) {
unsigned size = padToPage
(max
(space, max
(minimumFootprint, segment == 0 ? 0 : segment->size * 2))
+ sizeof(Segment));
void* p = allocator->tryAllocate(size);
if (p == 0) {
size = space + sizeof(Segment);
void* p = allocator->tryAllocate(size);
size = padToPage(space + sizeof(Segment));
p = allocator->tryAllocate(size);
if (p == 0) {
return false;
}
@ -75,9 +77,19 @@ class Zone: public Allocator {
return true;
}
void ensure(unsigned space) {
if (segment == 0 or position + space > segment->size) {
unsigned size = padToPage(space + sizeof(Segment));
segment = new (allocator->allocate(size))
Segment(segment, size - sizeof(Segment));
position = 0;
}
}
virtual void* tryAllocate(unsigned size) {
size = pad(size);
if (ensure(size)) {
if (tryEnsure(size)) {
void* r = segment->data + position;
position += size;
return r;
@ -88,8 +100,14 @@ class Zone: public Allocator {
virtual void* allocate(unsigned size) {
void* p = tryAllocate(size);
expect(s, p);
return p;
if (p) {
return p;
} else {
ensure(size);
void* r = segment->data + position;
position += size;
return r;
}
}
virtual void free(const void*, unsigned) {