snapshot (broken)

This commit is contained in:
Joel Dice 2007-07-01 19:42:35 -06:00
parent f698d347ac
commit bb16d8e62b
5 changed files with 409 additions and 87 deletions

View File

@ -5,9 +5,7 @@ public class TestExceptions {
}
private static void moreDangerous() {
// synchronized (TestExceptions.class) {
evenMoreDangerous();
// }
evenMoreDangerous();
}
private static void dangerous() {

View File

@ -483,12 +483,6 @@ class Segment {
return p;
}
void* add(void* p, unsigned size) {
void* target = allocate(size);
memcpy(target, p, size * BytesPerWord);
return target;
}
void ensure(unsigned minimum) {
if (remaining() < minimum) {
assert(context, rear->position);
@ -713,40 +707,48 @@ bitset(Context* c, object o)
}
inline object
copyTo(Context* c, Segment* s, object o, unsigned size)
copyTo(Context* c, Segment* s, object o)
{
if (s->remaining() < size) {
s->ensure(size);
class Allocator: public Heap::Allocator {
public:
Allocator(Segment* s): s(s) { }
if (Verbose) {
if (s == &(c->gen2)) {
fprintf(stderr, "grow gen2 to %d bytes\n",
c->gen2.capacity() * BytesPerWord);
} else if (s == &(c->nextGen1)) {
fprintf(stderr, "grow nextGen1 to %d bytes\n",
c->nextGen1.capacity() * BytesPerWord);
} else if (s == &(c->nextGen2)) {
fprintf(stderr, "grow nextGen2 to %d bytes\n",
c->nextGen2.capacity() * BytesPerWord);
} else {
abort(c);
virtual void* allocate(unsigned size) {
if (s->remaining() < size) {
s->ensure(size);
if (Verbose) {
if (s == &(c->gen2)) {
fprintf(stderr, "grow gen2 to %d bytes\n",
c->gen2.capacity() * BytesPerWord);
} else if (s == &(c->nextGen1)) {
fprintf(stderr, "grow nextGen1 to %d bytes\n",
c->nextGen1.capacity() * BytesPerWord);
} else if (s == &(c->nextGen2)) {
fprintf(stderr, "grow nextGen2 to %d bytes\n",
c->nextGen2.capacity() * BytesPerWord);
} else {
abort(c);
}
}
}
}
}
return static_cast<object>(s->add(o, size));
return s->allocate(size);
}
} allocator(s);
c->client->copy(o, &allocator);
return p;
}
object
copy2(Context* c, object o)
{
unsigned size = c->client->sizeInWords(o);
if (c->gen2.contains(o)) {
assert(c, c->mode == MajorCollection
or c->mode == Gen2Collection);
return copyTo(c, &(c->nextGen2), o, size);
return copyTo(c, &(c->nextGen2), o);
} else if (c->gen1.contains(o)) {
unsigned age = c->ageMap.get(o);
if (age == TenureThreshold) {
@ -758,7 +760,7 @@ copy2(Context* c, object o)
c->gen2Base = c->gen2.position();
}
return copyTo(c, &(c->gen2), o, size);
return copyTo(c, &(c->gen2), o);
} else {
if (Verbose) {
fprintf(stderr, "overflow collection\n");
@ -766,13 +768,13 @@ copy2(Context* c, object o)
c->mode = OverflowCollection;
initNextGen2(c);
return copyTo(c, &(c->nextGen2), o, size);
return copyTo(c, &(c->nextGen2), o);
}
} else {
return copyTo(c, &(c->nextGen2), o, size);
return copyTo(c, &(c->nextGen2), o);
}
} else {
o = copyTo(c, &(c->nextGen1), o, size);
o = copyTo(c, &(c->nextGen1), o);
c->nextAgeMap.setOnly(o, age + 1);
return o;
}
@ -780,7 +782,7 @@ copy2(Context* c, object o)
assert(c, not c->nextGen1.contains(o));
assert(c, not c->nextGen2.contains(o));
o = copyTo(c, &(c->nextGen1), o, size);
o = copyTo(c, &(c->nextGen1), o);
c->nextAgeMap.clear(o);

View File

@ -24,11 +24,18 @@ class Heap {
virtual bool visit(unsigned) = 0;
};
class Allocator {
public:
virtual ~Allocator() { }
virtual void* allocate(unsigned sizeInWords) = 0;
};
class Client {
public:
virtual ~Client() { }
virtual void visitRoots(Visitor*) = 0;
virtual unsigned sizeInWords(void*) = 0;
virtual void copy(void*, Allocator*) = 0;
virtual void walk(void*, Walker*) = 0;
};

View File

@ -18,15 +18,101 @@ class System {
class Monitor {
public:
virtual ~Monitor() { }
virtual bool tryAcquire(void* id) = 0;
virtual void acquire(void* id) = 0;
virtual void release(void* id) = 0;
virtual void wait(void* id, int64_t time) = 0;
virtual void notify(void* id) = 0;
virtual void notifyAll(void* id) = 0;
virtual bool tryAcquire(void* context) = 0;
virtual void acquire(void* context) = 0;
virtual void release(void* context) = 0;
virtual void wait(void* context, int64_t time) = 0;
virtual void notify(void* context) = 0;
virtual void notifyAll(void* context) = 0;
virtual void dispose() = 0;
};
class ReadWriteLock {
public:
ReadWriteLock(System* s): s(s), m(0), readers(0), writer(0) {
if (not s->success(s->make(&m))) {
s->abort();
}
}
~ReadWriteLock() {
if (readers or writer) {
s->abort();
}
m->dispose();
}
bool tryAcquireRead(void* context) {
bool result;
m->acquire(context);
if (writer) {
result = false;
} else {
result = true;
++ readers;
}
m->release(context);
return result;
}
void acquireRead(void* context) {
m->acquire(context);
while (writer) {
m->wait(context, 0);
}
++ readers;
m->release(context);
}
void releaseRead(void* context) {
m->acquire(context);
if (-- readers == 0) {
m->notify(context);
}
m->release(context);
}
bool tryAcquireWrite(void* context) {
bool result;
m->acquire(context);
if (readers or writer) {
result = false;
} else {
result = true;
writer = context;
}
m->release(context);
return result;
}
void acquireWrite(void* context) {
m->acquire(context);
while (readers or writer) {
m->wait(context, 0);
}
writer = context;
m->release(context);
}
void releaseWrite(void* context) {
if (writer != context) {
s->abort();
}
m->acquire(context);
writer = 0;
m->notifyAll(context);
m->release(context);
}
private:
System* s;
Monitor* m;
unsigned readers;
void* writer;
};
class Library {
public:
virtual ~Library() { }

View File

@ -11,14 +11,26 @@
Thread::Protector MAKE_NAME(protector_) (thread, &name);
#define ACQUIRE(t, x) MonitorResource MAKE_NAME(monitorResource_) (t, x)
#define ACQUIRE_RAW(t, x) RawMonitorResource MAKE_NAME(monitorResource_) (t, x)
#define ACQUIRE_READ(t, x) ReadResource MAKE_NAME(readResource_) (t, x)
#define ACQUIRE_WRITE(t, x) WriteResource MAKE_NAME(writeResource_) (t, x)
#define ENTER(t, state) StateResource MAKE_NAME(stateResource_) (t, state)
using namespace vm;
namespace {
static const bool Verbose = false;
static const bool Debug = false;
const bool Verbose = false;
const bool Debug = false;
const uintptr_t HashTakenMark = 1;
const uintptr_t ExtendedMark = 2;
const uintptr_t MonitorFlag
= static_cast<uintptr_t>(1) << ((BytesPerWord * 8) - 1);
class Thread;
@ -73,10 +85,12 @@ class Machine {
System::Monitor* stateLock;
System::Monitor* heapLock;
System::Monitor* classLock;
System::ReadWriteLock monitorMapLock;
System::Library* libraries;
object classMap;
object bootstrapClassMap;
object builtinMap;
object monitorMap;
object types;
bool unsafe;
JNIEnvVTable jniEnvVTable;
@ -168,13 +182,57 @@ objectClass(Thread*, object o)
void enter(Thread* t, Thread::State state);
class StateResource {
public:
StateResource(Thread* t, Thread::State state): t(t), oldState(t->state) {
enter(t, state);
}
~StateResource() { enter(t, oldState); }
private:
Thread* t;
Thread::State oldState;
};
class ReadResource {
public:
ReadResource(Thread* t, System::ReadWriteLock& lock): t(t), lock(lock) {
if (not lock.tryAcquireRead(t)) {
ENTER(t, Thread::IdleState);
lock.acquireRead(t);
}
}
~ReadResource() { lock.releaseRead(t); }
private:
Thread* t;
System::ReadWriteLock& lock;
};
class WriteResource {
public:
WriteResource(Thread* t, System::ReadWriteLock& lock): t(t), lock(lock) {
if (not lock.tryAcquireWrite(t)) {
ENTER(t, Thread::IdleState);
lock.acquireWrite(t);
}
}
~WriteResource() { lock.releaseWrite(t); }
private:
Thread* t;
System::ReadWriteLock& lock;
};
class MonitorResource {
public:
MonitorResource(Thread* t, System::Monitor* m): t(t), m(m) {
if (not m->tryAcquire(t)) {
enter(t, Thread::IdleState);
ENTER(t, Thread::IdleState);
m->acquire(t);
enter(t, Thread::ActiveState);
}
}
@ -224,6 +282,105 @@ hash(const int8_t* s, unsigned length)
return h;
}
inline bool
objectExtended(Thread*, object o)
{
return (cast<uintptr_t>(o, 0) & (~PointerMask)) == ExtendedMark;
}
inline uintptr_t&
extendedWord(Thread* t, object o, unsigned baseSize)
{
assert(t, objectExtended(t, o));
return cast<uintptr_t>(o, baseSize * BytesPerWord);
}
unsigned
baseSize(Thread* t, object o, object class_)
{
return divide(classFixedSize(t, class_), BytesPerWord)
+ divide(classArrayElementSize(t, class_)
* cast<uint32_t>(o, classFixedSize(t, class_) - 4),
BytesPerWord);
}
inline unsigned
baseSize(Thread* t, object o)
{
return baseSize(t, o, objectClass(t, o));
}
unsigned
extendedSize(Thread* t, object o, unsigned baseSize)
{
unsigned n = baseSize;
if (objectExtended(t, o)) {
if (extendedWord(t, o, n) & MonitorFlag) {
n += BytesPerWord;
}
n += BytesPerWord;
}
return n;
}
inline unsigned
extendedSize(Thread* t, object o)
{
return extendedSize(t, o, baseSize(t, o));
}
inline bool
monitorAttached(Thread* t, object o, unsigned baseSize)
{
return objectExtended(t, o)
and (extendedWord(t, o, baseSize) & MonitorFlag);
}
inline System::Monitor*&
attachedMonitor(Thread* t, object o, unsigned baseSize)
{
assert(t, monitorAttached(t, o, baseSize));
return cast<System::Monitor*>(o, (baseSize + 1) * BytesPerWord);
}
inline bool
hashTaken(Thread*, object o)
{
return (cast<uintptr_t>(o, 0) & (~PointerMask)) == HashTakenMark;
}
inline void
markHashTaken(Thread* t, object o)
{
assert(t, not objectExtended(t, o));
cast<uintptr_t>(o, 0) |= HashTakenMark;
}
inline uint32_t
takeHash(Thread*, object o)
{
return reinterpret_cast<uintptr_t>(o) / BytesPerWord;
}
inline uint32_t
objectHash(Thread* t, object o)
{
if (objectExtended(t, o)) {
return extendedWord(t, o, baseSize(t, o)) & PointerMask;
} else {
markHashTaken(t, o);
return takeHash(t, o);
}
}
inline bool
objectEqual(Thread*, object a, object b)
{
return a == b;
}
inline uint32_t
byteArrayHash(Thread* t, object array)
{
@ -479,6 +636,7 @@ collect(Machine* m, Heap::CollectionType type)
v->visit(&(m->classMap));
v->visit(&(m->bootstrapClassMap));
v->visit(&(m->builtinMap));
v->visit(&(m->monitorMap));
v->visit(&(m->types));
for (Thread* t = m->rootThread; t; t = t->next) {
@ -486,16 +644,64 @@ collect(Machine* m, Heap::CollectionType type)
}
}
virtual unsigned sizeInWords(void* p) {
virtual unsigned sizeInWords(object o) {
Thread* t = m->rootThread;
p = m->heap->follow(mask(p));
object class_ = m->heap->follow(objectClass(t, p));
o = m->heap->follow(mask(o));
return divide(classFixedSize(t, class_), BytesPerWord)
+ divide(classArrayElementSize(t, class_)
* cast<uint32_t>(p, classFixedSize(t, class_) - 4),
BytesPerWord);
return extendedSize
(t, o, baseSize(t, o, m->heap->follow(objectClass(t, o))));
}
virtual void copy(object o, Heap::Allocator* allocator) {
Thread* t = m->rootThread;
o = m->heap->follow(mask(o));
unsigned base = baseSize(t, o, m->heap->follow(objectClass(t, o)));
unsigned copyCount = base;
unsigned allocateCount = base;
System::Monitor* monitor = 0;
if (objectExtended(t, o)) {
copyCount += BytesPerWord;
allocateCount += BytesPerWord;
if (extendedWord(t, o, base) & MonitorFlag) {
copyCount += BytesPerWord;
allocateCount += BytesPerWord;
} else {
monitor = gcHashMapRemove
(t, m->monitorMap, o, gcObjectHash, gcObjectEqual);
if (monitor) {
allocateCount += BytesPerWord;
}
}
} else if (hashTaken(t, o)) {
allocateCount += BytesPerWord;
monitor = gcHashMapRemove
(t, m->monitorMap, o, gcObjectHash, gcObjectEqual);
if (monitor) {
allocateCount += BytesPerWord;
}
}
object dst = allocator->allocate(allocateCount);
memcpy(o, dst, copyCount * BytesPerWord);
if (hashTaken(t, o)) {
extendedWord(t, dst, base) = takeHash(t, o);
cast<uintptr_t>(dst, 0) &= PointerMask;
cast<uintptr_t>(dst, 0) |= ExtendedMark;
}
if (monitor) {
attachedMonitor(t, dst, base) = monitor;
}
}
virtual void walk(void* p, Heap::Walker* w) {
@ -755,15 +961,41 @@ make(Thread* t, object class_)
return instance;
}
unsigned
objectSize(Thread* t, object o)
System::Monitor*
mappedMonitor(Thread* t, object o)
{
object class_ = objectClass(t, o);
PROTECT(t, o);
return divide(classFixedSize(t, class_), BytesPerWord)
+ divide(classArrayElementSize(t, class_)
* cast<uint32_t>(o, classFixedSize(t, class_) - 4),
BytesPerWord);
System::Monitor* m = 0;
{ ACQUIRE_READ(t, t->vm->monitorMapLock);
object p = hashMapFind(t, t->vm->monitorMap, o, objectHash, objectEqual);
if (p) {
m = static_cast<System::Monitor*>(pointerValue(t, p));
}
}
if (m == 0) {
System::Status s = t->vm->system->make(&m);
expect(t, t->vm->system->success(s));
object pointer = makePointer(t, m);
PROTECT(t, pointer);
ACQUIRE_WRITE(t, t->vm->monitorMapLock);
hashMapInsert(t, t->vm->monitorMap, o, pointer, objectHash);
}
}
inline System::Monitor*
objectMonitor(Thread* t, object o)
{
unsigned base = baseSize(t, o);
if (monitorAttached(t, o, base)) {
return attachedMonitor(t, o, base);
} else {
return mappedMonitor(t, o);
}
}
object
@ -1985,9 +2217,9 @@ updateBootstrapClass(Thread* t, object bootstrapClass, object class_)
PROTECT(t, bootstrapClass);
PROTECT(t, class_);
enter(t, Thread::ExclusiveState);
ENTER(t, Thread::ExclusiveState);
memcpy(bootstrapClass, class_, objectSize(t, class_) * BytesPerWord);
memcpy(bootstrapClass, class_, extendedSize(t, class_) * BytesPerWord);
object fieldTable = classFieldTable(t, class_);
if (fieldTable) {
@ -2002,8 +2234,6 @@ updateBootstrapClass(Thread* t, object bootstrapClass, object class_)
set(t, methodClass(t, arrayBody(t, methodTable, i)), bootstrapClass);
}
}
enter(t, Thread::ActiveState);
}
object
@ -2369,7 +2599,7 @@ GetStringUTFLength(JNIEnv* e, jstring s)
{
Thread* t = static_cast<Thread*>(e);
enter(t, Thread::ActiveState);
ENTER(t, Thread::ActiveState);
jsize length = 0;
if (LIKELY(s)) {
@ -2378,8 +2608,6 @@ GetStringUTFLength(JNIEnv* e, jstring s)
t->exception = makeNullPointerException(t);
}
enter(t, Thread::IdleState);
return length;
}
@ -2388,7 +2616,7 @@ GetStringUTFChars(JNIEnv* e, jstring s, jboolean* isCopy)
{
Thread* t = static_cast<Thread*>(e);
enter(t, Thread::ActiveState);
ENTER(t, Thread::ActiveState);
char* chars = 0;
if (LIKELY(s)) {
@ -2403,8 +2631,6 @@ GetStringUTFChars(JNIEnv* e, jstring s, jboolean* isCopy)
t->exception = makeNullPointerException(t);
}
enter(t, Thread::IdleState);
if (isCopy) *isCopy = true;
return chars;
}
@ -2428,10 +2654,12 @@ Machine::Machine(System* system, Heap* heap, ClassFinder* classFinder):
stateLock(0),
heapLock(0),
classLock(0),
monitorMapLock(system),
libraries(0),
classMap(0),
bootstrapClassMap(0),
builtinMap(0),
monitorMap(0),
types(0),
unsafe(false)
{
@ -2505,6 +2733,7 @@ Thread::Thread(Machine* m):
m->classMap = makeHashMap(this, 0, 0);
m->builtinMap = makeHashMap(this, 0, 0);
m->monitorMap = makeHashMap(this, 0, 0);
struct {
const char* key;
@ -3635,25 +3864,25 @@ run(Thread* t)
push(t, makeLong(t, longValue(t, a) ^ longValue(t, b)));
} goto loop;
// case monitorenter: {
// object o = pop(t);
// if (LIKELY(o)) {
// objectMonitor(t, o)->acquire(t);
// } else {
// exception = makeNullPointerException(t);
// goto throw_;
// }
// } goto loop;
case monitorenter: {
object o = pop(t);
if (LIKELY(o)) {
objectMonitor(t, o)->acquire(t);
} else {
exception = makeNullPointerException(t);
goto throw_;
}
} goto loop;
// case monitorexit: {
// object o = pop(t);
// if (LIKELY(o)) {
// objectMonitor(t, o)->release(t);
// } else {
// exception = makeNullPointerException(t);
// goto throw_;
// }
// } goto loop;
case monitorexit: {
object o = pop(t);
if (LIKELY(o)) {
objectMonitor(t, o)->release(t);
} else {
exception = makeNullPointerException(t);
goto throw_;
}
} goto loop;
case new_: {
uint8_t index1 = codeBody(t, code, ip++);