From 29f9bb84cacb63b8f780219b55c7681d064efb48 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 21 Jun 2007 12:35:24 -0600 Subject: [PATCH] snapshot --- input/Test.java | 4 +- src/heap.cpp | 128 +++++++++++++++++++++++++++--------- src/type-generator.cpp | 40 +++++++----- src/types.def | 6 +- src/vm.cpp | 145 ++++++++++++++++++++++++++++++++--------- 5 files changed, 242 insertions(+), 81 deletions(-) diff --git a/input/Test.java b/input/Test.java index 38f7f19306..bcb11c20ab 100644 --- a/input/Test.java +++ b/input/Test.java @@ -1,7 +1,9 @@ public class Test { public static void main(String[] args) { - int a = 2 + 2; + while (true) { + byte[] array = new byte[4 * 1024]; + } } } diff --git a/src/heap.cpp b/src/heap.cpp index 3e51f23dbb..105e00dbe0 100644 --- a/src/heap.cpp +++ b/src/heap.cpp @@ -19,6 +19,12 @@ System* system(Context*); void NO_RETURN abort(Context*); void assert(Context*, bool); +void +indent(unsigned i) +{ + for (; i > 0; --i) fprintf(stderr, " "); +} + class Segment { public: class Map { @@ -385,6 +391,8 @@ class Context { Segment::Map heapMap; CollectionMode mode; + + unsigned depth; }; inline System* @@ -448,21 +456,34 @@ initNextGen2(Context* c) c->gen2.map = 0; } -inline object& -follow(object o) +inline bool +wasCollected(Context* c, object o) { + return o and + (not c->nextGen1.contains(o)) and + (not c->nextGen2.contains(o)) and + (c->nextGen1.contains(cast(o, 0)) or + c->nextGen2.contains(cast(o, 0))); +} + +inline object +follow(Context* c, object o) +{ + assert(c, wasCollected(c, o)); return cast(o, 0); } inline object& -parent(object o) +parent(Context* c, object o) { + assert(c, wasCollected(c, o)); return cast(o, BytesPerWord); } inline uintptr_t* -bitset(object o) +bitset(Context* c, object o) { + assert(c, wasCollected(c, o)); return &cast(o, BytesPerWord * 2); } @@ -524,25 +545,21 @@ copy(Context* c, object 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 - follow(o) = r; + cast(o, 0) = 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 update3(Context* c, object *p, bool* needsVisit) { if (wasCollected(c, *p)) { *needsVisit = false; - return follow(*p); + return follow(c, *p); } else { *needsVisit = true; return copy(c, *p); @@ -708,13 +725,19 @@ collect(Context* c, void** p) object original = *p; object parent = 0; + indent(c->depth); + fprintf(stderr, "update %p at %p\n", *p, p); + bool needsVisit; *p = update(c, p, &needsVisit); + indent(c->depth); + fprintf(stderr, " result: %p (visit? %d)\n", *p, needsVisit); + if (not needsVisit) return; visit: { - object copy = follow(original); + object copy = follow(c, original); class Walker : public Heap::Walker { public: @@ -723,16 +746,27 @@ collect(Context* c, void** p) copy(copy), bitset(bitset), first(0), + second(0), last(0), visits(0), total(0) { } virtual bool visit(unsigned offset) { + indent(c->depth); + fprintf(stderr, " update %p at %p - offset %d from %p\n", + cast(copy, offset * BytesPerWord), + &cast(copy, offset * BytesPerWord), + offset, + copy); + bool needsVisit; object childCopy = update (c, &cast(copy, offset * BytesPerWord), &needsVisit); + indent(c->depth); + fprintf(stderr, " result: %p (visit? %d)\n", childCopy, needsVisit); + ++ total; if (total == 3) { @@ -744,18 +778,27 @@ collect(Context* c, void** p) if (visits == 1) { first = offset; + } else if (visits == 2) { + second = offset; } - - if (total >= 3) { - bitsetClear(bitset, last, offset); - last = offset; - - bitsetSet(bitset, offset, true); - } } else { cast(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; } @@ -763,31 +806,37 @@ collect(Context* c, void** p) object copy; uintptr_t* bitset; unsigned first; + unsigned second; unsigned last; unsigned visits; 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); if (walker.visits) { // descend + ++ c->depth; if (walker.visits > 1) { - ::parent(original) = parent; + ::parent(c, original) = parent; parent = original; } original = cast(copy, walker.first * BytesPerWord); - cast(copy, walker.first * BytesPerWord) = follow(original); + cast(copy, walker.first * BytesPerWord) = follow(c, original); goto visit; } else { // ascend + -- c->depth; original = parent; } } if (original) { - object copy = follow(original); + object copy = follow(c, original); class Walker : public Heap::Walker { public: @@ -820,18 +869,30 @@ collect(Context* c, void** p) uintptr_t* bitset; unsigned next; 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); - if (walker.total == 3 and bitsetHasMore(bitset(original))) { + if (walker.total == 3 and bitsetHasMore(bitset(c, original))) { parent = original; } else { - parent = ::parent(original); + parent = ::parent(c, original); } + indent(c->depth); + fprintf(stderr, " next is %p at %p - offset %d from %p\n", + cast(copy, walker.next * BytesPerWord), + &cast(copy, walker.next * BytesPerWord), + walker.next, + copy); + original = cast(copy, walker.next * BytesPerWord); - cast(copy, walker.next * BytesPerWord) = follow(original); + cast(copy, walker.next * BytesPerWord) = follow(c, original); goto visit; } else { return; @@ -1019,6 +1080,7 @@ makeHeap(System* system) } c.client = client; + c.depth = 0; ::collect(&c); } @@ -1038,8 +1100,14 @@ makeHeap(System* system) virtual void* follow(void* 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 { + //indent(c.depth); + //fprintf(stderr, "follow: %p: %p\n", p, p); + return p; } } diff --git a/src/type-generator.cpp b/src/type-generator.cpp index 4b7f6ec8d1..01308c0186 100644 --- a/src/type-generator.cpp +++ b/src/type-generator.cpp @@ -928,11 +928,15 @@ parse(Input* in) } 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)); out->write(owner); out->write(capitalize(memberName(member))); + if (unsafe) { + out->write("Unsafe"); + } if (respectHide and memberHide(member)) { out->write("0"); } @@ -988,7 +992,8 @@ writeSubtypeAssertions(Output* out, Object* o) { for (Object* p = typeSubtypes(o); p; p = cdr(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("Type)"); writeSubtypeAssertions(out, st); @@ -1009,7 +1014,7 @@ writeAccessor(Output* out, Object* member, Object* offset, bool unsafe = false) out->write("&"); } out->write("\n"); - writeAccessorName(out, member, true); + writeAccessorName(out, member, true, unsafe); if (memberOwner(member)->type == Object::Pod) { out->write("("); out->write(capitalize(::typeName(memberOwner(member)))); @@ -1027,8 +1032,9 @@ writeAccessor(Output* out, Object* member, Object* offset, bool unsafe = false) if (unsafe) { out->write(" assert(t, true);"); } else { - out->write(" assert(t, objectClass(o) == 0 or "); - out->write("objectClass(o) == arrayBody(t, t->vm->types, Machine::"); + out->write(" assert(t, t->vm->unsafe or objectClass(o) == 0 or "); + out->write("objectClass(o) == arrayBodyUnsafe"); + out->write("(t, t->vm->types, Machine::"); out->write(capitalize(::typeName(memberOwner(member)))); out->write("Type)"); writeSubtypeAssertions(out, memberOwner(member)); @@ -1155,13 +1161,19 @@ writeAccessors(Output* out, Object* declarations) switch (m->type) { case Object::Scalar: { 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); } break; case Object::Array: { 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); } break; @@ -1373,7 +1385,7 @@ typeFixedSize(Object* type) default: UNREACHABLE; } } - return length / 4; + return length; } unsigned @@ -1385,7 +1397,7 @@ typeArrayElementSize(Object* type) case Object::Scalar: break; case Object::Array: { - return memberElementSize(m) / 4; + return memberElementSize(m); } break; default: UNREACHABLE; @@ -1397,9 +1409,10 @@ typeArrayElementSize(Object* type) uint32_t 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();) { Object* m = it.next(); @@ -1442,7 +1455,7 @@ writeInitialization(Output* out, Object* type) out->write("{\n"); - if (typeObjectMask(type)) { + if (typeObjectMask(type) != 1) { out->write(" object mask = makeIntArray(t, 1);\n"); out->write(" intArrayBody(t, mask, 0) = "); @@ -1507,9 +1520,6 @@ writeInitializations(Output* out, Object* declarations) writeInitialization(out, o); } } - - out->write("set(t, objectClass(t->vm->types), "); - out->write("arrayBody(t, t->vm->types, Machine::ArrayType));\n"); } void diff --git a/src/types.def b/src/types.def index d3dd61404c..39ff95df07 100644 --- a/src/types.def +++ b/src/types.def @@ -1,3 +1,6 @@ +(type intArray + (array int32_t body)) + (type class (uint16_t flags) (uint16_t fixedSize) @@ -181,9 +184,6 @@ (type charArray (array uint16_t body)) -(type intArray - (array int32_t body)) - (type longArray (array int64_t body)) diff --git a/src/vm.cpp b/src/vm.cpp index f3a37f024a..c635650034 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -23,7 +23,7 @@ class Thread; void assert(Thread*, bool); object resolveClass(Thread*, object); object allocate(Thread*, unsigned); -object& arrayBody(Thread*, object, unsigned); +object& arrayBodyUnsafe(Thread*, object, unsigned); void set(Thread*, object&, object); object& @@ -62,6 +62,7 @@ class Machine { System::Monitor* classLock; object classMap; object types; + bool unsafe; }; class Thread { @@ -171,7 +172,8 @@ Machine::Machine(System* system, Heap* heap, ClassFinder* classFinder): heapLock(0), classLock(0), classMap(0), - types(0) + types(0), + unsafe(false) { if (not system->success(system->make(&stateLock)) or not system->success(system->make(&heapLock)) or @@ -197,12 +199,24 @@ Thread::Thread(Machine* m): { if (m->rootThread == 0) { m->rootThread = this; + m->unsafe = true; Thread* t = this; #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->unsafe = false; } } @@ -251,10 +265,12 @@ collect(Machine* m, Heap::CollectionType type) p = m->heap->follow(p); object class_ = m->heap->follow(objectClass(p)); - unsigned n = classFixedSize(t, class_); + unsigned n = divide(classFixedSize(t, class_), BytesPerWord); + if (classArrayElementSize(t, class_)) { - n += classArrayElementSize(t, class_) - * cast(p, (classFixedSize(t, class_) - 1) * BytesPerWord); + n += divide(classArrayElementSize(t, class_) + * cast(p, classFixedSize(t, class_) - 4), + BytesPerWord); } return n; } @@ -264,28 +280,63 @@ collect(Machine* m, Heap::CollectionType type) p = m->heap->follow(p); object class_ = m->heap->follow(objectClass(p)); - unsigned fixedSize = classFixedSize(t, class_); - unsigned arrayLength = cast(p, (fixedSize - 1) * BytesPerWord); - unsigned arrayElementSize = classArrayElementSize(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 (mask[wordOf(i)] & (static_cast(1) << bitOf(i))) { - if (not w->visit(i)) return; - } - } + if (objectMask) { + fprintf(stderr, "p: %p; class: %p; mask: %p; mask length: %d\n", + p, class_, objectMask, intArrayLength(t, objectMask)); - for (unsigned i = 0; i < arrayLength; ++i) { - for (unsigned j = 0; j < arrayElementSize; ++j) { - unsigned k = fixedSize + j; - if (mask[wordOf(k)] & (static_cast(1) << bitOf(k))) { - if (not w->visit(fixedSize + (i * arrayElementSize) + j)) return; + unsigned fixedSize = classFixedSize(t, class_); + unsigned arrayElementSize = classArrayElementSize(t, class_); + unsigned arrayLength + = (arrayElementSize ? cast(p, fixedSize - 4) : 0); + + 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(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(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(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"); + m->unsafe = true; m->heap->collect(type, &it); + m->unsafe = false; } void @@ -1187,15 +1240,13 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool) PROTECT(t, class_); PROTECT(t, pool); + unsigned memberOffset = BytesPerWord; + if (classSuper(t, class_)) { + memberOffset = classFixedSize(t, classSuper(t, class_)) * BytesPerWord; + } + unsigned count = s.read2(); 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; object fieldTable = makeArray(t, count); @@ -1243,6 +1294,32 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool) 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 @@ -1612,6 +1689,8 @@ run(Thread* t) if (UNLIKELY(exception)) goto throw_; loop: + //fprintf(stderr, "ip: %d; instruction: 0x%x\n", ip, codeBody(t, code, ip)); + switch (codeBody(t, code, ip++)) { case aaload: { object index = pop(t); @@ -2036,7 +2115,7 @@ run(Thread* t) uint8_t offset1 = codeBody(t, code, ip++); uint8_t offset2 = codeBody(t, code, ip++); - ip = (ip - 1) + ((offset1 << 8) | offset2); + ip = (ip - 3) + static_cast(((offset1 << 8) | offset2)); } goto loop; case goto_w: { @@ -2045,8 +2124,8 @@ run(Thread* t) uint8_t offset3 = codeBody(t, code, ip++); uint8_t offset4 = codeBody(t, code, ip++); - ip = (ip - 1) - + ((offset1 << 24) | (offset2 << 16) | (offset3 << 8) | offset4); + ip = (ip - 5) + static_cast + (((offset1 << 24) | (offset2 << 16) | (offset3 << 8) | offset4)); } goto loop; case i2b: { @@ -3044,6 +3123,8 @@ run(Thread* t) void run(Thread* t, const char* className, int argc, const char** argv) { + enter(t, Thread::ActiveState); + object class_ = resolveClass(t, makeByteArray(t, "%s", className)); if (LIKELY(t->exception == 0)) { PROTECT(t, class_);