fail quickly if an object allocation cannot be satisfied

Previously, we would blithely exceed the heap ceiling and force the
next allocation to deal with the problem, including a major GC and
possible OutOfMemoryError.  As of this commit, we throw an error
immediately if we find that the allocation will push us over the
ceiling.
This commit is contained in:
Joel Dice 2013-02-03 15:53:36 -07:00
parent 23bb2e8743
commit e8f8ebdc67
4 changed files with 60 additions and 30 deletions

@ -1895,21 +1895,43 @@ class MyHeap: public Heap {
local::collect(&c);
}
virtual void* allocateFixed(Allocator* allocator, unsigned sizeInWords,
bool objectMask, unsigned* totalInBytes)
void* tryAllocateFixed(Allocator* allocator, unsigned sizeInWords,
bool objectMask, unsigned* totalInBytes,
Fixie** handle, bool immortal)
{
*totalInBytes = Fixie::totalSize(sizeInWords, objectMask);
return (new (allocator->allocate(*totalInBytes))
Fixie(&c, sizeInWords, objectMask, &(c.fixies), false))->body();
*totalInBytes = 0;
if (limitExceeded()) {
return 0;
}
unsigned total = Fixie::totalSize(sizeInWords, objectMask);
void* p = allocator->tryAllocate(total);
if (p == 0) {
return 0;
} else if (limitExceeded()) {
allocator->free(p, total);
return 0;
} else {
*totalInBytes = total;
return (new (p) Fixie(&c, sizeInWords, objectMask, handle, immortal))
->body();
}
}
virtual void* allocateImmortalFixed(Allocator* allocator,
unsigned sizeInWords, bool objectMask,
unsigned* totalInBytes)
virtual void* tryAllocateFixed(Allocator* allocator, unsigned sizeInWords,
bool objectMask, unsigned* totalInBytes)
{
*totalInBytes = Fixie::totalSize(sizeInWords, objectMask);
return (new (allocator->allocate(*totalInBytes))
Fixie(&c, sizeInWords, objectMask, 0, true))->body();
return tryAllocateFixed
(allocator, sizeInWords, objectMask, totalInBytes, &(c.fixies), false);
}
virtual void* tryAllocateImmortalFixed(Allocator* allocator,
unsigned sizeInWords, bool objectMask,
unsigned* totalInBytes)
{
return tryAllocateFixed
(allocator, sizeInWords, objectMask, totalInBytes, 0, true);
}
bool needsMark(void* p) {

@ -62,11 +62,11 @@ class Heap: public Allocator {
virtual unsigned limit() = 0;
virtual bool limitExceeded() = 0;
virtual void collect(CollectionType type, unsigned footprint) = 0;
virtual void* allocateFixed(Allocator* allocator, unsigned sizeInWords,
bool objectMask, unsigned* totalInBytes) = 0;
virtual void* allocateImmortalFixed(Allocator* allocator,
unsigned sizeInWords, bool objectMask,
unsigned* totalInBytes) = 0;
virtual void* tryAllocateFixed(Allocator* allocator, unsigned sizeInWords,
bool objectMask, unsigned* totalInBytes) = 0;
virtual void* tryAllocateImmortalFixed(Allocator* allocator,
unsigned sizeInWords, bool objectMask,
unsigned* totalInBytes) = 0;
virtual void mark(void* p, unsigned offset, unsigned count) = 0;
virtual void pad(void* p) = 0;
virtual void* follow(void* p) = 0;

@ -3531,7 +3531,7 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type,
} while (type == Machine::MovableAllocation
and t->heapIndex + ceiling(sizeInBytes, BytesPerWord)
> ThreadHeapSizeInWords);
switch (type) {
case Machine::MovableAllocation: {
return allocateSmall(t, sizeInBytes);
@ -3540,29 +3540,37 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type,
case Machine::FixedAllocation: {
unsigned total;
object o = static_cast<object>
(t->m->heap->allocateFixed
(t->m->heap->tryAllocateFixed
(allocator, ceiling(sizeInBytes, BytesPerWord), objectMask, &total));
memset(o, 0, sizeInBytes);
if (o) {
memset(o, 0, sizeInBytes);
alias(o, 0) = FixedMark;
t->m->fixedFootprint += total;
return o;
alias(o, 0) = FixedMark;
t->m->fixedFootprint += total;
return o;
} else {
throw_(t, root(t, Machine::OutOfMemoryError));
}
}
case Machine::ImmortalAllocation: {
unsigned total;
object o = static_cast<object>
(t->m->heap->allocateImmortalFixed
(t->m->heap->tryAllocateImmortalFixed
(allocator, ceiling(sizeInBytes, BytesPerWord), objectMask, &total));
memset(o, 0, sizeInBytes);
if (o) {
memset(o, 0, sizeInBytes);
alias(o, 0) = FixedMark;
alias(o, 0) = FixedMark;
return o;
return o;
} else {
throw_(t, root(t, Machine::OutOfMemoryError));
}
}
default: abort(t);

@ -1784,8 +1784,8 @@ class FixedAllocator: public Allocator {
s(s), base(base), offset(0), capacity(capacity)
{ }
virtual void* tryAllocate(unsigned) {
abort(s);
virtual void* tryAllocate(unsigned size) {
return allocate(size);
}
void* allocate(unsigned size, unsigned padAlignment) {