diff --git a/src/heap.cpp b/src/heap.cpp index 2dc23e904e..0cc13ba7dc 100644 --- a/src/heap.cpp +++ b/src/heap.cpp @@ -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) { diff --git a/src/heap.h b/src/heap.h index 0ee4699914..2a6734438d 100644 --- a/src/heap.h +++ b/src/heap.h @@ -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; diff --git a/src/machine.cpp b/src/machine.cpp index 7986a5be78..c06d8c8159 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -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 - (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 - (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); diff --git a/src/machine.h b/src/machine.h index 08eab4c894..2924a13fb7 100644 --- a/src/machine.h +++ b/src/machine.h @@ -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) {