mirror of
https://github.com/corda/corda.git
synced 2024-12-29 09:18:58 +00:00
snapshot
This commit is contained in:
parent
95c4bff51b
commit
29f9bb84ca
@ -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];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
128
src/heap.cpp
128
src/heap.cpp
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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))
|
||||||
|
|
||||||
|
145
src/vm.cpp
145
src/vm.cpp
@ -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_);
|
||||||
|
Loading…
Reference in New Issue
Block a user