mirror of
https://github.com/corda/corda.git
synced 2025-06-12 12:18:20 +00:00
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:
40
src/heap.cpp
40
src/heap.cpp
@ -1895,21 +1895,43 @@ class MyHeap: public Heap {
|
|||||||
local::collect(&c);
|
local::collect(&c);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void* allocateFixed(Allocator* allocator, unsigned sizeInWords,
|
void* tryAllocateFixed(Allocator* allocator, unsigned sizeInWords,
|
||||||
bool objectMask, unsigned* totalInBytes)
|
bool objectMask, unsigned* totalInBytes,
|
||||||
|
Fixie** handle, bool immortal)
|
||||||
{
|
{
|
||||||
*totalInBytes = Fixie::totalSize(sizeInWords, objectMask);
|
*totalInBytes = 0;
|
||||||
return (new (allocator->allocate(*totalInBytes))
|
|
||||||
Fixie(&c, sizeInWords, objectMask, &(c.fixies), false))->body();
|
if (limitExceeded()) {
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void* allocateImmortalFixed(Allocator* allocator,
|
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* tryAllocateFixed(Allocator* allocator, unsigned sizeInWords,
|
||||||
|
bool objectMask, unsigned* totalInBytes)
|
||||||
|
{
|
||||||
|
return tryAllocateFixed
|
||||||
|
(allocator, sizeInWords, objectMask, totalInBytes, &(c.fixies), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void* tryAllocateImmortalFixed(Allocator* allocator,
|
||||||
unsigned sizeInWords, bool objectMask,
|
unsigned sizeInWords, bool objectMask,
|
||||||
unsigned* totalInBytes)
|
unsigned* totalInBytes)
|
||||||
{
|
{
|
||||||
*totalInBytes = Fixie::totalSize(sizeInWords, objectMask);
|
return tryAllocateFixed
|
||||||
return (new (allocator->allocate(*totalInBytes))
|
(allocator, sizeInWords, objectMask, totalInBytes, 0, true);
|
||||||
Fixie(&c, sizeInWords, objectMask, 0, true))->body();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool needsMark(void* p) {
|
bool needsMark(void* p) {
|
||||||
|
@ -62,9 +62,9 @@ class Heap: public Allocator {
|
|||||||
virtual unsigned limit() = 0;
|
virtual unsigned limit() = 0;
|
||||||
virtual bool limitExceeded() = 0;
|
virtual bool limitExceeded() = 0;
|
||||||
virtual void collect(CollectionType type, unsigned footprint) = 0;
|
virtual void collect(CollectionType type, unsigned footprint) = 0;
|
||||||
virtual void* allocateFixed(Allocator* allocator, unsigned sizeInWords,
|
virtual void* tryAllocateFixed(Allocator* allocator, unsigned sizeInWords,
|
||||||
bool objectMask, unsigned* totalInBytes) = 0;
|
bool objectMask, unsigned* totalInBytes) = 0;
|
||||||
virtual void* allocateImmortalFixed(Allocator* allocator,
|
virtual void* tryAllocateImmortalFixed(Allocator* allocator,
|
||||||
unsigned sizeInWords, bool objectMask,
|
unsigned sizeInWords, bool objectMask,
|
||||||
unsigned* totalInBytes) = 0;
|
unsigned* totalInBytes) = 0;
|
||||||
virtual void mark(void* p, unsigned offset, unsigned count) = 0;
|
virtual void mark(void* p, unsigned offset, unsigned count) = 0;
|
||||||
|
@ -3540,9 +3540,10 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type,
|
|||||||
case Machine::FixedAllocation: {
|
case Machine::FixedAllocation: {
|
||||||
unsigned total;
|
unsigned total;
|
||||||
object o = static_cast<object>
|
object o = static_cast<object>
|
||||||
(t->m->heap->allocateFixed
|
(t->m->heap->tryAllocateFixed
|
||||||
(allocator, ceiling(sizeInBytes, BytesPerWord), objectMask, &total));
|
(allocator, ceiling(sizeInBytes, BytesPerWord), objectMask, &total));
|
||||||
|
|
||||||
|
if (o) {
|
||||||
memset(o, 0, sizeInBytes);
|
memset(o, 0, sizeInBytes);
|
||||||
|
|
||||||
alias(o, 0) = FixedMark;
|
alias(o, 0) = FixedMark;
|
||||||
@ -3550,19 +3551,26 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type,
|
|||||||
t->m->fixedFootprint += total;
|
t->m->fixedFootprint += total;
|
||||||
|
|
||||||
return o;
|
return o;
|
||||||
|
} else {
|
||||||
|
throw_(t, root(t, Machine::OutOfMemoryError));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case Machine::ImmortalAllocation: {
|
case Machine::ImmortalAllocation: {
|
||||||
unsigned total;
|
unsigned total;
|
||||||
object o = static_cast<object>
|
object o = static_cast<object>
|
||||||
(t->m->heap->allocateImmortalFixed
|
(t->m->heap->tryAllocateImmortalFixed
|
||||||
(allocator, ceiling(sizeInBytes, BytesPerWord), objectMask, &total));
|
(allocator, ceiling(sizeInBytes, BytesPerWord), objectMask, &total));
|
||||||
|
|
||||||
|
if (o) {
|
||||||
memset(o, 0, sizeInBytes);
|
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);
|
default: abort(t);
|
||||||
|
@ -1784,8 +1784,8 @@ class FixedAllocator: public Allocator {
|
|||||||
s(s), base(base), offset(0), capacity(capacity)
|
s(s), base(base), offset(0), capacity(capacity)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual void* tryAllocate(unsigned) {
|
virtual void* tryAllocate(unsigned size) {
|
||||||
abort(s);
|
return allocate(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* allocate(unsigned size, unsigned padAlignment) {
|
void* allocate(unsigned size, unsigned padAlignment) {
|
||||||
|
Reference in New Issue
Block a user