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 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 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<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);
}
inline object&
parent(object o)
parent(Context* c, object o)
{
assert(c, wasCollected(c, o));
return cast<object>(o, BytesPerWord);
}
inline uintptr_t*
bitset(object o)
bitset(Context* c, object o)
{
assert(c, wasCollected(c, o));
return &cast<uintptr_t>(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<object>(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<object>(copy, offset * BytesPerWord),
&cast<object>(copy, offset * BytesPerWord),
offset,
copy);
bool needsVisit;
object childCopy = update
(c, &cast<object>(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;
}
if (total >= 3) {
bitsetClear(bitset, last, offset);
last = offset;
bitsetSet(bitset, offset, true);
} else if (visits == 2) {
second = offset;
}
} else {
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;
}
@ -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<object>(copy, walker.first * BytesPerWord);
cast<object>(copy, walker.first * BytesPerWord) = follow(original);
cast<object>(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<object>(copy, walker.next * BytesPerWord),
&cast<object>(copy, walker.next * BytesPerWord),
walker.next,
copy);
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;
} 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;
}
}

View File

@ -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

View File

@ -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))

View File

@ -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<uint32_t>(p, (classFixedSize(t, class_) - 1) * BytesPerWord);
n += divide(classArrayElementSize(t, class_)
* cast<uint32_t>(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<uint32_t>(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<uintptr_t>(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<uintptr_t>(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<uint32_t>(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<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");
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<int16_t>(((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<int16_t>
(((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_);