mirror of
https://github.com/corda/corda.git
synced 2025-04-07 19:34:41 +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:
parent
23bb2e8743
commit
e8f8ebdc67
44
src/heap.cpp
44
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) {
|
||||
|
10
src/heap.h
10
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;
|
||||
|
@ -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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user