mirror of
https://github.com/corda/corda.git
synced 2025-01-23 12:58:35 +00:00
fix GC bugs involving old fixed objects pointing to new objects
This commit is contained in:
parent
1d7931a654
commit
e797a8f1ca
144
src/heap.cpp
144
src/heap.cpp
@ -416,6 +416,10 @@ class Fixie {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void move(Fixie** handle) {
|
void move(Fixie** handle) {
|
||||||
|
if (DebugFixies) {
|
||||||
|
fprintf(stderr, "move fixie %p\n", this);
|
||||||
|
}
|
||||||
|
|
||||||
remove();
|
remove();
|
||||||
add(handle);
|
add(handle);
|
||||||
}
|
}
|
||||||
@ -716,14 +720,13 @@ sweepFixies(Context* c)
|
|||||||
|
|
||||||
if (f->age == FixieTenureThreshold) {
|
if (f->age == FixieTenureThreshold) {
|
||||||
if (DebugFixies) {
|
if (DebugFixies) {
|
||||||
fprintf(stderr, "tenure fixie %p\n", f);
|
fprintf(stderr, "tenure fixie %p (dirty: %d)\n", f, f->dirty);
|
||||||
}
|
}
|
||||||
f->move(&(c->tenuredFixies));
|
|
||||||
|
|
||||||
if (f->dirty) {
|
if (f->dirty) {
|
||||||
uintptr_t* mask = f->mask(size);
|
f->move(&(c->dirtyFixies));
|
||||||
memset(mask, 0, ceiling(size, BytesPerWord) * BytesPerWord);
|
} else {
|
||||||
f->dirty = false;
|
f->move(&(c->tenuredFixies));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
f->move(&(c->fixies));
|
f->move(&(c->fixies));
|
||||||
@ -848,32 +851,67 @@ update(Context* c, void** p, bool* needsVisit)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* r = update2(c, mask(*p), needsVisit);
|
return update2(c, mask(*p), needsVisit);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
updateHeapMap(Context* c, void* p, void* target, unsigned offset, void* result)
|
||||||
|
{
|
||||||
|
Segment* seg;
|
||||||
|
Segment::Map* map;
|
||||||
|
|
||||||
// update heap map.
|
|
||||||
if (r) {
|
|
||||||
if (c->mode == Heap::MinorCollection) {
|
if (c->mode == Heap::MinorCollection) {
|
||||||
if (c->gen2.contains(p) and not c->gen2.contains(r)) {
|
seg = &(c->gen2);
|
||||||
if (Debug) {
|
map = &(c->heapMap);
|
||||||
fprintf(stderr, "mark %p (%s) at %p (%s)\n",
|
|
||||||
r, segment(c, r), p, segment(c, p));
|
|
||||||
}
|
|
||||||
|
|
||||||
c->heapMap.set(p);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (c->nextGen2.contains(p) and not c->nextGen2.contains(r)) {
|
seg = &(c->nextGen2);
|
||||||
|
map = &(c->nextHeapMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not (c->client->isFixed(result)
|
||||||
|
and fixie(result)->age == FixieTenureThreshold)
|
||||||
|
and not seg->contains(result))
|
||||||
|
{
|
||||||
|
if (target and c->client->isFixed(target)) {
|
||||||
|
Fixie* f = fixie(target);
|
||||||
|
assert(c, f->hasMask);
|
||||||
|
|
||||||
|
if (static_cast<unsigned>(f->age + 1) >= FixieTenureThreshold) {
|
||||||
|
unsigned size = c->client->sizeInWords(f->body());
|
||||||
|
|
||||||
|
if (DebugFixies) {
|
||||||
|
fprintf(stderr, "dirty fixie %p at %d\n", f, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
f->dirty = true;
|
||||||
|
markBit(f->mask(size), offset);
|
||||||
|
}
|
||||||
|
} else if (seg->contains(p)) {
|
||||||
if (Debug) {
|
if (Debug) {
|
||||||
fprintf(stderr, "mark %p (%s) at %p (%s)\n",
|
fprintf(stderr, "mark %p (%s) at %p (%s)\n",
|
||||||
r, segment(c, r), p, segment(c, p));
|
result, segment(c, result), p, segment(c, p));
|
||||||
}
|
}
|
||||||
|
|
||||||
c->nextHeapMap.set(p);
|
map->set(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return r;
|
void*
|
||||||
|
update(Context* c, void** p, void* target, unsigned offset, bool* needsVisit)
|
||||||
|
{
|
||||||
|
if (mask(*p) == 0) {
|
||||||
|
*needsVisit = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* result = update2(c, mask(*p), needsVisit);
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
updateHeapMap(c, p, target, offset, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uintptr_t BitsetExtensionBit
|
const uintptr_t BitsetExtensionBit
|
||||||
@ -978,7 +1016,7 @@ bitsetNext(Context* c, uintptr_t* p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
collect(Context* c, void** p)
|
collect(Context* c, void** p, void* target, unsigned offset)
|
||||||
{
|
{
|
||||||
void* original = mask(*p);
|
void* original = mask(*p);
|
||||||
void* parent = 0;
|
void* parent = 0;
|
||||||
@ -989,7 +1027,7 @@ collect(Context* c, void** p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool needsVisit;
|
bool needsVisit;
|
||||||
set(p, update(c, mask(p), &needsVisit));
|
set(p, update(c, mask(p), target, offset, &needsVisit));
|
||||||
|
|
||||||
if (Debug) {
|
if (Debug) {
|
||||||
fprintf(stderr, " result: %p (%s) (visit? %d)\n",
|
fprintf(stderr, " result: %p (%s) (visit? %d)\n",
|
||||||
@ -1026,7 +1064,8 @@ collect(Context* c, void** p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool needsVisit;
|
bool needsVisit;
|
||||||
void* childCopy = update(c, getp(copy, offset), &needsVisit);
|
void* childCopy = update
|
||||||
|
(c, getp(copy, offset), copy, offset, &needsVisit);
|
||||||
|
|
||||||
if (Debug) {
|
if (Debug) {
|
||||||
fprintf(stderr, " result: %p (%s) (visit? %d)\n",
|
fprintf(stderr, " result: %p (%s) (visit? %d)\n",
|
||||||
@ -1168,31 +1207,72 @@ collect(Context* c, void** p)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
collect(Context* c, void** p)
|
||||||
|
{
|
||||||
|
collect(c, p, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
collect(Context* c, void* target, unsigned offset)
|
||||||
|
{
|
||||||
|
collect(c, getp(target, offset), target, offset);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
visitDirtyFixies(Context* c)
|
visitDirtyFixies(Context* c)
|
||||||
{
|
{
|
||||||
for (Fixie** p = &(c->dirtyFixies); *p;) {
|
for (Fixie** p = &(c->dirtyFixies); *p;) {
|
||||||
Fixie* f = *p;
|
Fixie* f = *p;
|
||||||
*p = f->next;
|
|
||||||
|
|
||||||
|
bool wasDirty = false;
|
||||||
|
bool stillDirty = false;
|
||||||
unsigned size = c->client->sizeInWords(f->body());
|
unsigned size = c->client->sizeInWords(f->body());
|
||||||
uintptr_t* mask = f->mask(size);
|
uintptr_t* mask = f->mask(size);
|
||||||
for (unsigned word = 0; word < wordOf(size); ++ word) {
|
|
||||||
|
unsigned word = 0;
|
||||||
|
unsigned bit = 0;
|
||||||
|
unsigned wordLimit = wordOf(size);
|
||||||
|
unsigned bitLimit = bitOf(size);
|
||||||
|
|
||||||
|
for (; word <= wordLimit and (word < wordLimit or bit < bitLimit);
|
||||||
|
++ word)
|
||||||
|
{
|
||||||
if (mask[word]) {
|
if (mask[word]) {
|
||||||
for (unsigned bit = 0; bit < bitOf(size); ++ bit) {
|
for (; bit < BitsPerWord and (word < wordLimit or bit < bitLimit);
|
||||||
|
++ bit)
|
||||||
|
{
|
||||||
unsigned index = indexOf(word, bit);
|
unsigned index = indexOf(word, bit);
|
||||||
if (getBit(mask, index)) {
|
if (getBit(mask, index)) {
|
||||||
collect(c, f->body() + index);
|
wasDirty = true;
|
||||||
|
|
||||||
|
clearBit(mask, index);
|
||||||
|
|
||||||
|
if (DebugFixies) {
|
||||||
|
fprintf(stderr, "clean fixie %p at %d\n", f, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
collect(c, f->body(), index);
|
||||||
|
|
||||||
|
if (getBit(mask, index)) {
|
||||||
|
stillDirty = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(mask, 0, ceiling(size, BytesPerWord) * BytesPerWord);
|
assert(c, wasDirty);
|
||||||
|
|
||||||
|
if (stillDirty) {
|
||||||
|
p = &(f->next);
|
||||||
|
} else {
|
||||||
f->dirty = false;
|
f->dirty = false;
|
||||||
|
*p = f->next;
|
||||||
f->move(&(c->tenuredFixies));
|
f->move(&(c->tenuredFixies));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
visitMarkedFixies(Context* c)
|
visitMarkedFixies(Context* c)
|
||||||
@ -1212,7 +1292,7 @@ visitMarkedFixies(Context* c)
|
|||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual bool visit(unsigned offset) {
|
virtual bool visit(unsigned offset) {
|
||||||
collect(c, p + offset);
|
collect(c, p, offset);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1403,11 +1483,15 @@ class MyHeap: public Heap {
|
|||||||
Fixie* f = fixie(p);
|
Fixie* f = fixie(p);
|
||||||
assert(&c, f->hasMask);
|
assert(&c, f->hasMask);
|
||||||
|
|
||||||
unsigned size = c.client->sizeInWords(p);
|
unsigned size = c.client->sizeInWords(f->body());
|
||||||
|
|
||||||
for (unsigned i = 0; i < count; ++i) {
|
for (unsigned i = 0; i < count; ++i) {
|
||||||
void** target = static_cast<void**>(p) + offset + i;
|
void** target = static_cast<void**>(p) + offset + i;
|
||||||
if (targetNeedsMark(*target)) {
|
if (targetNeedsMark(*target)) {
|
||||||
|
if (DebugFixies) {
|
||||||
|
fprintf(stderr, "dirty fixie %p at %d\n", f, offset + i);
|
||||||
|
}
|
||||||
|
|
||||||
f->dirty = true;
|
f->dirty = true;
|
||||||
markBit(f->mask(size), offset + i);
|
markBit(f->mask(size), offset + i);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user