This commit is contained in:
Joel Dice 2007-06-21 12:35:24 -06:00
parent 95c4bff51b
commit 29f9bb84ca
5 changed files with 242 additions and 81 deletions

View File

@ -1,7 +1,9 @@
public class Test { public class Test {
public static void main(String[] args) { public static void main(String[] args) {
int a = 2 + 2; while (true) {
byte[] array = new byte[4 * 1024];
}
} }
} }

View File

@ -19,6 +19,12 @@ System* system(Context*);
void NO_RETURN abort(Context*); void NO_RETURN abort(Context*);
void assert(Context*, bool); void assert(Context*, bool);
void
indent(unsigned i)
{
for (; i > 0; --i) fprintf(stderr, " ");
}
class Segment { class Segment {
public: public:
class Map { class Map {
@ -385,6 +391,8 @@ class Context {
Segment::Map heapMap; Segment::Map heapMap;
CollectionMode mode; CollectionMode mode;
unsigned depth;
}; };
inline System* inline System*
@ -448,21 +456,34 @@ initNextGen2(Context* c)
c->gen2.map = 0; c->gen2.map = 0;
} }
inline object& inline bool
follow(object o) wasCollected(Context* c, object o)
{ {
return o and
(not c->nextGen1.contains(o)) and
(not c->nextGen2.contains(o)) and
(c->nextGen1.contains(cast<object>(o, 0)) or
c->nextGen2.contains(cast<object>(o, 0)));
}
inline object
follow(Context* c, object o)
{
assert(c, wasCollected(c, o));
return cast<object>(o, 0); return cast<object>(o, 0);
} }
inline object& inline object&
parent(object o) parent(Context* c, object o)
{ {
assert(c, wasCollected(c, o));
return cast<object>(o, BytesPerWord); return cast<object>(o, BytesPerWord);
} }
inline uintptr_t* inline uintptr_t*
bitset(object o) bitset(Context* c, object o)
{ {
assert(c, wasCollected(c, o));
return &cast<uintptr_t>(o, BytesPerWord * 2); return &cast<uintptr_t>(o, BytesPerWord * 2);
} }
@ -524,25 +545,21 @@ copy(Context* c, object o)
{ {
object r = copy2(c, o); object r = copy2(c, o);
indent(c->depth);
fprintf(stderr, "copy %p to %p\n", o, r);
// leave a pointer to the copy in the original // leave a pointer to the copy in the original
follow(o) = r; cast<object>(o, 0) = r;
return r; return r;
} }
inline bool
wasCollected(Context* c, object o)
{
return o and (c->nextGen1.contains(follow(o)) or
c->nextGen2.contains(follow(o)));
}
object object
update3(Context* c, object *p, bool* needsVisit) update3(Context* c, object *p, bool* needsVisit)
{ {
if (wasCollected(c, *p)) { if (wasCollected(c, *p)) {
*needsVisit = false; *needsVisit = false;
return follow(*p); return follow(c, *p);
} else { } else {
*needsVisit = true; *needsVisit = true;
return copy(c, *p); return copy(c, *p);
@ -708,13 +725,19 @@ collect(Context* c, void** p)
object original = *p; object original = *p;
object parent = 0; object parent = 0;
indent(c->depth);
fprintf(stderr, "update %p at %p\n", *p, p);
bool needsVisit; bool needsVisit;
*p = update(c, p, &needsVisit); *p = update(c, p, &needsVisit);
indent(c->depth);
fprintf(stderr, " result: %p (visit? %d)\n", *p, needsVisit);
if (not needsVisit) return; if (not needsVisit) return;
visit: { visit: {
object copy = follow(original); object copy = follow(c, original);
class Walker : public Heap::Walker { class Walker : public Heap::Walker {
public: public:
@ -723,16 +746,27 @@ collect(Context* c, void** p)
copy(copy), copy(copy),
bitset(bitset), bitset(bitset),
first(0), first(0),
second(0),
last(0), last(0),
visits(0), visits(0),
total(0) total(0)
{ } { }
virtual bool visit(unsigned offset) { virtual bool visit(unsigned offset) {
indent(c->depth);
fprintf(stderr, " update %p at %p - offset %d from %p\n",
cast<object>(copy, offset * BytesPerWord),
&cast<object>(copy, offset * BytesPerWord),
offset,
copy);
bool needsVisit; bool needsVisit;
object childCopy = update object childCopy = update
(c, &cast<object>(copy, offset * BytesPerWord), &needsVisit); (c, &cast<object>(copy, offset * BytesPerWord), &needsVisit);
indent(c->depth);
fprintf(stderr, " result: %p (visit? %d)\n", childCopy, needsVisit);
++ total; ++ total;
if (total == 3) { if (total == 3) {
@ -744,18 +778,27 @@ collect(Context* c, void** p)
if (visits == 1) { if (visits == 1) {
first = offset; first = offset;
} else if (visits == 2) {
second = offset;
} }
if (total >= 3) {
bitsetClear(bitset, last, offset);
last = offset;
bitsetSet(bitset, offset, true);
}
} else { } else {
cast<object>(copy, offset * BytesPerWord) = childCopy; cast<object>(copy, offset * BytesPerWord) = childCopy;
} }
if (total >= 3 and (second or needsVisit)) {
bitsetClear(bitset, last, offset);
last = offset;
if (second) {
bitsetSet(bitset, second, true);
second = 0;
}
if (needsVisit) {
bitsetSet(bitset, offset, true);
}
}
return true; return true;
} }
@ -763,31 +806,37 @@ collect(Context* c, void** p)
object copy; object copy;
uintptr_t* bitset; uintptr_t* bitset;
unsigned first; unsigned first;
unsigned second;
unsigned last; unsigned last;
unsigned visits; unsigned visits;
unsigned total; unsigned total;
} walker(c, copy, bitset(original)); } walker(c, copy, bitset(c, original));
indent(c->depth);
fprintf(stderr, "walk %p\n", copy);
c->client->walk(copy, &walker); c->client->walk(copy, &walker);
if (walker.visits) { if (walker.visits) {
// descend // descend
++ c->depth;
if (walker.visits > 1) { if (walker.visits > 1) {
::parent(original) = parent; ::parent(c, original) = parent;
parent = original; parent = original;
} }
original = cast<object>(copy, walker.first * BytesPerWord); original = cast<object>(copy, walker.first * BytesPerWord);
cast<object>(copy, walker.first * BytesPerWord) = follow(original); cast<object>(copy, walker.first * BytesPerWord) = follow(c, original);
goto visit; goto visit;
} else { } else {
// ascend // ascend
-- c->depth;
original = parent; original = parent;
} }
} }
if (original) { if (original) {
object copy = follow(original); object copy = follow(c, original);
class Walker : public Heap::Walker { class Walker : public Heap::Walker {
public: public:
@ -820,18 +869,30 @@ collect(Context* c, void** p)
uintptr_t* bitset; uintptr_t* bitset;
unsigned next; unsigned next;
unsigned total; unsigned total;
} walker(c, bitset(original)); } walker(c, bitset(c, original));
indent(c->depth);
fprintf(stderr, "scan %p\n", copy);
c->client->walk(copy, &walker);
assert(c, walker.total > 1); assert(c, walker.total > 1);
if (walker.total == 3 and bitsetHasMore(bitset(original))) { if (walker.total == 3 and bitsetHasMore(bitset(c, original))) {
parent = original; parent = original;
} else { } else {
parent = ::parent(original); parent = ::parent(c, original);
} }
indent(c->depth);
fprintf(stderr, " next is %p at %p - offset %d from %p\n",
cast<object>(copy, walker.next * BytesPerWord),
&cast<object>(copy, walker.next * BytesPerWord),
walker.next,
copy);
original = cast<object>(copy, walker.next * BytesPerWord); original = cast<object>(copy, walker.next * BytesPerWord);
cast<object>(copy, walker.next * BytesPerWord) = follow(original); cast<object>(copy, walker.next * BytesPerWord) = follow(c, original);
goto visit; goto visit;
} else { } else {
return; return;
@ -1019,6 +1080,7 @@ makeHeap(System* system)
} }
c.client = client; c.client = client;
c.depth = 0;
::collect(&c); ::collect(&c);
} }
@ -1038,8 +1100,14 @@ makeHeap(System* system)
virtual void* follow(void* p) { virtual void* follow(void* p) {
if (wasCollected(&c, p)) { if (wasCollected(&c, p)) {
return ::follow(p); indent(c.depth);
fprintf(stderr, "follow: %p: %p\n", p, ::follow(&c, p));
return ::follow(&c, p);
} else { } else {
//indent(c.depth);
//fprintf(stderr, "follow: %p: %p\n", p, p);
return p; return p;
} }
} }

View File

@ -928,11 +928,15 @@ parse(Input* in)
} }
void void
writeAccessorName(Output* out, Object* member, bool respectHide = false) writeAccessorName(Output* out, Object* member, bool respectHide = false,
bool unsafe = false)
{ {
const char* owner = typeShortName(memberOwner(member)); const char* owner = typeShortName(memberOwner(member));
out->write(owner); out->write(owner);
out->write(capitalize(memberName(member))); out->write(capitalize(memberName(member)));
if (unsafe) {
out->write("Unsafe");
}
if (respectHide and memberHide(member)) { if (respectHide and memberHide(member)) {
out->write("0"); out->write("0");
} }
@ -988,7 +992,8 @@ writeSubtypeAssertions(Output* out, Object* o)
{ {
for (Object* p = typeSubtypes(o); p; p = cdr(p)) { for (Object* p = typeSubtypes(o); p; p = cdr(p)) {
Object* st = car(p); Object* st = car(p);
out->write(" or objectClass(o) == arrayBody(t, t->vm->types, Machine::"); out->write(" or objectClass(o) == arrayBodyUnsafe");
out->write("(t, t->vm->types, Machine::");
out->write(capitalize(typeName(st))); out->write(capitalize(typeName(st)));
out->write("Type)"); out->write("Type)");
writeSubtypeAssertions(out, st); writeSubtypeAssertions(out, st);
@ -1009,7 +1014,7 @@ writeAccessor(Output* out, Object* member, Object* offset, bool unsafe = false)
out->write("&"); out->write("&");
} }
out->write("\n"); out->write("\n");
writeAccessorName(out, member, true); writeAccessorName(out, member, true, unsafe);
if (memberOwner(member)->type == Object::Pod) { if (memberOwner(member)->type == Object::Pod) {
out->write("("); out->write("(");
out->write(capitalize(::typeName(memberOwner(member)))); out->write(capitalize(::typeName(memberOwner(member))));
@ -1027,8 +1032,9 @@ writeAccessor(Output* out, Object* member, Object* offset, bool unsafe = false)
if (unsafe) { if (unsafe) {
out->write(" assert(t, true);"); out->write(" assert(t, true);");
} else { } else {
out->write(" assert(t, objectClass(o) == 0 or "); out->write(" assert(t, t->vm->unsafe or objectClass(o) == 0 or ");
out->write("objectClass(o) == arrayBody(t, t->vm->types, Machine::"); out->write("objectClass(o) == arrayBodyUnsafe");
out->write("(t, t->vm->types, Machine::");
out->write(capitalize(::typeName(memberOwner(member)))); out->write(capitalize(::typeName(memberOwner(member))));
out->write("Type)"); out->write("Type)");
writeSubtypeAssertions(out, memberOwner(member)); writeSubtypeAssertions(out, memberOwner(member));
@ -1155,13 +1161,19 @@ writeAccessors(Output* out, Object* declarations)
switch (m->type) { switch (m->type) {
case Object::Scalar: { case Object::Scalar: {
if (it.padding()) offset = cons(Number::make(it.padding()), offset); if (it.padding()) offset = cons(Number::make(it.padding()), offset);
writeAccessor(out, m, offset, memberNoAssert(m)); writeAccessor(out, m, offset);
if (memberNoAssert(m)) {
writeAccessor(out, m, offset, true);
}
offset = cons(Number::make(it.size()), offset); offset = cons(Number::make(it.size()), offset);
} break; } break;
case Object::Array: { case Object::Array: {
if (it.padding()) offset = cons(Number::make(it.padding()), offset); if (it.padding()) offset = cons(Number::make(it.padding()), offset);
writeAccessor(out, m, offset, memberNoAssert(m)); writeAccessor(out, m, offset);
if (memberNoAssert(m)) {
writeAccessor(out, m, offset, true);
}
offset = cons(m, offset); offset = cons(m, offset);
} break; } break;
@ -1373,7 +1385,7 @@ typeFixedSize(Object* type)
default: UNREACHABLE; default: UNREACHABLE;
} }
} }
return length / 4; return length;
} }
unsigned unsigned
@ -1385,7 +1397,7 @@ typeArrayElementSize(Object* type)
case Object::Scalar: break; case Object::Scalar: break;
case Object::Array: { case Object::Array: {
return memberElementSize(m) / 4; return memberElementSize(m);
} break; } break;
default: UNREACHABLE; default: UNREACHABLE;
@ -1397,9 +1409,10 @@ typeArrayElementSize(Object* type)
uint32_t uint32_t
typeObjectMask(Object* type) typeObjectMask(Object* type)
{ {
assert(typeFixedSize(type) + typeArrayElementSize(type) < 32); assert(typeFixedSize(type) + typeArrayElementSize(type)
< 32 * sizeof(void*));
uint32_t mask = 0; uint32_t mask = 1;
for (MemberIterator it(type); it.hasMore();) { for (MemberIterator it(type); it.hasMore();) {
Object* m = it.next(); Object* m = it.next();
@ -1442,7 +1455,7 @@ writeInitialization(Output* out, Object* type)
out->write("{\n"); out->write("{\n");
if (typeObjectMask(type)) { if (typeObjectMask(type) != 1) {
out->write(" object mask = makeIntArray(t, 1);\n"); out->write(" object mask = makeIntArray(t, 1);\n");
out->write(" intArrayBody(t, mask, 0) = "); out->write(" intArrayBody(t, mask, 0) = ");
@ -1507,9 +1520,6 @@ writeInitializations(Output* out, Object* declarations)
writeInitialization(out, o); writeInitialization(out, o);
} }
} }
out->write("set(t, objectClass(t->vm->types), ");
out->write("arrayBody(t, t->vm->types, Machine::ArrayType));\n");
} }
void void

View File

@ -1,3 +1,6 @@
(type intArray
(array int32_t body))
(type class (type class
(uint16_t flags) (uint16_t flags)
(uint16_t fixedSize) (uint16_t fixedSize)
@ -181,9 +184,6 @@
(type charArray (type charArray
(array uint16_t body)) (array uint16_t body))
(type intArray
(array int32_t body))
(type longArray (type longArray
(array int64_t body)) (array int64_t body))

View File

@ -23,7 +23,7 @@ class Thread;
void assert(Thread*, bool); void assert(Thread*, bool);
object resolveClass(Thread*, object); object resolveClass(Thread*, object);
object allocate(Thread*, unsigned); object allocate(Thread*, unsigned);
object& arrayBody(Thread*, object, unsigned); object& arrayBodyUnsafe(Thread*, object, unsigned);
void set(Thread*, object&, object); void set(Thread*, object&, object);
object& object&
@ -62,6 +62,7 @@ class Machine {
System::Monitor* classLock; System::Monitor* classLock;
object classMap; object classMap;
object types; object types;
bool unsafe;
}; };
class Thread { class Thread {
@ -171,7 +172,8 @@ Machine::Machine(System* system, Heap* heap, ClassFinder* classFinder):
heapLock(0), heapLock(0),
classLock(0), classLock(0),
classMap(0), classMap(0),
types(0) types(0),
unsafe(false)
{ {
if (not system->success(system->make(&stateLock)) or if (not system->success(system->make(&stateLock)) or
not system->success(system->make(&heapLock)) or not system->success(system->make(&heapLock)) or
@ -197,12 +199,24 @@ Thread::Thread(Machine* m):
{ {
if (m->rootThread == 0) { if (m->rootThread == 0) {
m->rootThread = this; m->rootThread = this;
m->unsafe = true;
Thread* t = this; Thread* t = this;
#include "type-initializations.cpp" #include "type-initializations.cpp"
object arrayClass = arrayBody(t, t->vm->types, Machine::ArrayType);
set(t, objectClass(t->vm->types), arrayClass);
object classClass = arrayBody(t, m->types, Machine::ClassType);
set(t, objectClass(classClass), classClass);
object intArrayClass = arrayBody(t, m->types, Machine::IntArrayType);
set(t, objectClass(intArrayClass), classClass);
m->classMap = makeHashMap(this, 0, 0); m->classMap = makeHashMap(this, 0, 0);
m->unsafe = false;
} }
} }
@ -251,10 +265,12 @@ collect(Machine* m, Heap::CollectionType type)
p = m->heap->follow(p); p = m->heap->follow(p);
object class_ = m->heap->follow(objectClass(p)); object class_ = m->heap->follow(objectClass(p));
unsigned n = classFixedSize(t, class_); unsigned n = divide(classFixedSize(t, class_), BytesPerWord);
if (classArrayElementSize(t, class_)) { if (classArrayElementSize(t, class_)) {
n += classArrayElementSize(t, class_) n += divide(classArrayElementSize(t, class_)
* cast<uint32_t>(p, (classFixedSize(t, class_) - 1) * BytesPerWord); * cast<uint32_t>(p, classFixedSize(t, class_) - 4),
BytesPerWord);
} }
return n; return n;
} }
@ -264,28 +280,63 @@ collect(Machine* m, Heap::CollectionType type)
p = m->heap->follow(p); p = m->heap->follow(p);
object class_ = m->heap->follow(objectClass(p)); object class_ = m->heap->follow(objectClass(p));
unsigned fixedSize = classFixedSize(t, class_);
unsigned arrayLength = cast<uint32_t>(p, (fixedSize - 1) * BytesPerWord);
unsigned arrayElementSize = classArrayElementSize(t, class_);
object objectMask = m->heap->follow(classObjectMask(t, class_)); object objectMask = m->heap->follow(classObjectMask(t, class_));
int mask[intArrayLength(t, objectMask)];
memcpy(mask, &intArrayBody(t, objectMask, 0),
intArrayLength(t, objectMask) * 4);
for (unsigned i = 0; i < fixedSize; ++i) { if (objectMask) {
if (mask[wordOf(i)] & (static_cast<uintptr_t>(1) << bitOf(i))) { fprintf(stderr, "p: %p; class: %p; mask: %p; mask length: %d\n",
if (not w->visit(i)) return; p, class_, objectMask, intArrayLength(t, objectMask));
}
}
for (unsigned i = 0; i < arrayLength; ++i) { unsigned fixedSize = classFixedSize(t, class_);
for (unsigned j = 0; j < arrayElementSize; ++j) { unsigned arrayElementSize = classArrayElementSize(t, class_);
unsigned k = fixedSize + j; unsigned arrayLength
if (mask[wordOf(k)] & (static_cast<uintptr_t>(1) << bitOf(k))) { = (arrayElementSize ? cast<uint32_t>(p, fixedSize - 4) : 0);
if (not w->visit(fixedSize + (i * arrayElementSize) + j)) return;
int mask[intArrayLength(t, objectMask)];
memcpy(mask, &intArrayBody(t, objectMask, 0),
intArrayLength(t, objectMask) * 4);
// fprintf
// (stderr,
// "fixed size: %d; array length: %d; element size: %d; mask: %x\n",
// fixedSize, arrayLength, arrayElementSize, mask[0]);
unsigned fixedSizeInWords = divide(fixedSize, BytesPerWord);
unsigned arrayElementSizeInWords
= divide(arrayElementSize, BytesPerWord);
for (unsigned i = 0; i < fixedSizeInWords; ++i) {
if (mask[wordOf(i)] & (static_cast<uintptr_t>(1) << bitOf(i))) {
if (not w->visit(i)) {
return;
}
} }
} }
bool arrayObjectElements = false;
for (unsigned j = 0; j < arrayElementSizeInWords; ++j) {
unsigned k = fixedSizeInWords + j;
if (mask[wordOf(k)] & (static_cast<uintptr_t>(1) << bitOf(k))) {
arrayObjectElements = true;
break;
}
}
if (arrayObjectElements) {
for (unsigned i = 0; i < arrayLength; ++i) {
for (unsigned j = 0; j < arrayElementSizeInWords; ++j) {
unsigned k = fixedSizeInWords + j;
if (mask[wordOf(k)] & (static_cast<uintptr_t>(1) << bitOf(k))) {
if (not w->visit
(fixedSizeInWords + (i * arrayElementSizeInWords) + j))
{
return;
}
}
}
}
}
} else {
w->visit(0);
} }
} }
@ -295,7 +346,9 @@ collect(Machine* m, Heap::CollectionType type)
fprintf(stderr, "collection time!\n"); fprintf(stderr, "collection time!\n");
m->unsafe = true;
m->heap->collect(type, &it); m->heap->collect(type, &it);
m->unsafe = false;
} }
void void
@ -1187,15 +1240,13 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool)
PROTECT(t, class_); PROTECT(t, class_);
PROTECT(t, pool); PROTECT(t, pool);
unsigned memberOffset = BytesPerWord;
if (classSuper(t, class_)) {
memberOffset = classFixedSize(t, classSuper(t, class_)) * BytesPerWord;
}
unsigned count = s.read2(); unsigned count = s.read2();
if (count) { if (count) {
fprintf(stderr, "%d fields\n", count);
unsigned memberOffset = BytesPerWord;
if (classSuper(t, class_)) {
memberOffset= classFixedSize(t, classSuper(t, class_)) * BytesPerWord;
}
unsigned staticOffset = 0; unsigned staticOffset = 0;
object fieldTable = makeArray(t, count); object fieldTable = makeArray(t, count);
@ -1243,6 +1294,32 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool)
set(t, classStaticTable(t, class_), staticTable); set(t, classStaticTable(t, class_), staticTable);
} }
} }
classFixedSize(t, class_) = divide(memberOffset, BytesPerWord);
object mask = makeIntArray
(t, divide(classFixedSize(t, class_), BitsPerWord));
memset(&intArrayBody(t, mask, 0), 0, intArrayLength(t, mask) * 4);
bool sawReferenceField = false;
for (object c = class_; c; c = classSuper(t, c)) {
object fieldTable = classFieldTable(t, c);
if (fieldTable) {
for (int i = arrayLength(t, fieldTable) - 1; i >= 0; --i) {
object field = arrayBody(t, fieldTable, i);
if (isReferenceField(t, field)) {
unsigned index = fieldOffset(t, field) / BytesPerWord;
intArrayBody(t, mask, (index / 32)) |= 1 << (index % 32);
sawReferenceField = true;
}
}
}
}
if (sawReferenceField) {
set(t, classObjectMask(t, class_), mask);
}
} }
object object
@ -1612,6 +1689,8 @@ run(Thread* t)
if (UNLIKELY(exception)) goto throw_; if (UNLIKELY(exception)) goto throw_;
loop: loop:
//fprintf(stderr, "ip: %d; instruction: 0x%x\n", ip, codeBody(t, code, ip));
switch (codeBody(t, code, ip++)) { switch (codeBody(t, code, ip++)) {
case aaload: { case aaload: {
object index = pop(t); object index = pop(t);
@ -2036,7 +2115,7 @@ run(Thread* t)
uint8_t offset1 = codeBody(t, code, ip++); uint8_t offset1 = codeBody(t, code, ip++);
uint8_t offset2 = codeBody(t, code, ip++); uint8_t offset2 = codeBody(t, code, ip++);
ip = (ip - 1) + ((offset1 << 8) | offset2); ip = (ip - 3) + static_cast<int16_t>(((offset1 << 8) | offset2));
} goto loop; } goto loop;
case goto_w: { case goto_w: {
@ -2045,8 +2124,8 @@ run(Thread* t)
uint8_t offset3 = codeBody(t, code, ip++); uint8_t offset3 = codeBody(t, code, ip++);
uint8_t offset4 = codeBody(t, code, ip++); uint8_t offset4 = codeBody(t, code, ip++);
ip = (ip - 1) ip = (ip - 5) + static_cast<int16_t>
+ ((offset1 << 24) | (offset2 << 16) | (offset3 << 8) | offset4); (((offset1 << 24) | (offset2 << 16) | (offset3 << 8) | offset4));
} goto loop; } goto loop;
case i2b: { case i2b: {
@ -3044,6 +3123,8 @@ run(Thread* t)
void void
run(Thread* t, const char* className, int argc, const char** argv) run(Thread* t, const char* className, int argc, const char** argv)
{ {
enter(t, Thread::ActiveState);
object class_ = resolveClass(t, makeByteArray(t, "%s", className)); object class_ = resolveClass(t, makeByteArray(t, "%s", className));
if (LIKELY(t->exception == 0)) { if (LIKELY(t->exception == 0)) {
PROTECT(t, class_); PROTECT(t, class_);