diff --git a/makefile b/makefile index 611b3ba49b..9834f52854 100644 --- a/makefile +++ b/makefile @@ -1,4 +1,4 @@ -#MAKEFLAGS = -s +MAKEFLAGS = -s arch = $(shell uname -m) ifeq ($(arch),i586) @@ -55,6 +55,7 @@ generated-code = \ $(bld)/type-constructors.cpp \ $(bld)/type-initializations.cpp \ $(bld)/type-java-initializations.cpp + interpreter-depends = \ $(generated-code) \ $(src)/common.h \ @@ -63,14 +64,16 @@ interpreter-depends = \ $(src)/class-finder.h \ $(src)/stream.h \ $(src)/constants.h \ - $(src)/vm.h \ - $(src)/vm-jni.h \ - $(src)/vm-builtin.h \ - $(src)/vm-declarations.h + $(src)/run.h \ + $(src)/jnienv.h \ + $(src)/builtin.h \ + $(src)/machine.h + interpreter-sources = \ - $(src)/vm.cpp \ - $(src)/vm-jni.cpp \ - $(src)/vm-builtin.cpp \ + $(src)/run.cpp \ + $(src)/machine.cpp \ + $(src)/jnienv.cpp \ + $(src)/builtin.cpp \ $(src)/heap.cpp \ $(src)/main.cpp diff --git a/src/vm-builtin.cpp b/src/builtin.cpp similarity index 98% rename from src/vm-builtin.cpp rename to src/builtin.cpp index 87ace354c0..5f254dfd52 100644 --- a/src/vm-builtin.cpp +++ b/src/builtin.cpp @@ -1,4 +1,5 @@ -#include "vm-builtin.h" +#include "builtin.h" +#include "machine.h" namespace vm { namespace builtin { diff --git a/src/vm-builtin.h b/src/builtin.h similarity index 56% rename from src/vm-builtin.h rename to src/builtin.h index e96c6e6b89..b8fee910e4 100644 --- a/src/vm-builtin.h +++ b/src/builtin.h @@ -1,7 +1,7 @@ -#ifndef VM_BUITLIN_H -#define VM_BUITLIN_H +#ifndef BUITLIN_H +#define BUITLIN_H -#include "vm-declarations.h" +#include "machine.h" namespace vm { namespace builtin { @@ -12,4 +12,4 @@ populate(Thread* t, object map); } // namespace builtin } // namespace vm -#endif//VM_BUILTIN_H +#endif//BUILTIN_H diff --git a/src/vm-jni.cpp b/src/jnienv.cpp similarity index 94% rename from src/vm-jni.cpp rename to src/jnienv.cpp index b97fcef9bd..b499a08502 100644 --- a/src/vm-jni.cpp +++ b/src/jnienv.cpp @@ -1,5 +1,5 @@ -#include "vm-jni.h" -#include "vm-declarations.h" +#include "jnienv.h" +#include "machine.h" namespace vm { namespace jni { diff --git a/src/vm-jni.h b/src/jnienv.h similarity index 57% rename from src/vm-jni.h rename to src/jnienv.h index 2b66389ef1..6632b0510d 100644 --- a/src/vm-jni.h +++ b/src/jnienv.h @@ -1,7 +1,7 @@ -#ifndef VM_JNI_H -#define VM_JNI_H +#ifndef JNIENV_H +#define JNIENV_H -#include "vm-declarations.h" +#include "machine.h" namespace vm { namespace jni { @@ -12,4 +12,4 @@ populate(JNIEnvVTable* table); } // namespace jni } // namespace vm -#endif//VM_JNI_H +#endif//JNIENV_H diff --git a/src/machine.cpp b/src/machine.cpp new file mode 100644 index 0000000000..f038c9f8a5 --- /dev/null +++ b/src/machine.cpp @@ -0,0 +1,746 @@ +#include "jnienv.h" +#include "builtin.h" +#include "machine.h" + +using namespace vm; + +namespace { + +void +visitRoots(Thread* t, Heap::Visitor* v) +{ + t->heapIndex = 0; + + v->visit(&(t->thread)); + v->visit(&(t->code)); + v->visit(&(t->exception)); + + for (unsigned i = 0; i < t->sp; ++i) { + if (t->stack[i * 2] == ObjectTag) { + v->visit(reinterpret_cast(t->stack + (i * 2) + 1)); + } + } + + for (Thread::Protector* p = t->protector; p; p = p->next) { + v->visit(p->p); + } + + for (Thread* c = t->child; c; c = c->next) { + visitRoots(c, v); + } +} + +void +postCollect(Thread* t) +{ + Chain::dispose(t->vm->system, t->chain); + t->chain = 0; + + for (Thread* c = t->child; c; c = c->next) { + postCollect(c); + } +} + +void +collect(Machine* m, Heap::CollectionType type) +{ + class Client: public Heap::Client { + public: + Client(Machine* m): m(m) { } + + virtual void visitRoots(Heap::Visitor* v) { + 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) { + ::visitRoots(t, v); + } + + Thread* t = m->rootThread; + for (object* f = &(m->finalizers); *f;) { + object o = finalizerTarget(t, *f); + if (m->heap->follow(o) == o) { + // object has not been collected + object x = *f; + *f = finalizerNext(t, x); + finalizerNext(t, x) = m->doomed; + m->doomed = x; + } else { + f = &finalizerNext(t, *f); + } + } + + for (object* f = &(m->finalizers); *f; f = &finalizerNext(t, *f)) { + v->visit(f); + } + + for (object* f = &(m->doomed); *f; f = &finalizerNext(t, *f)) { + v->visit(f); + } + + for (object p = m->weakReferences; p;) { + object o = jreferenceTarget(t, p); + object followed = m->heap->follow(o); + if (followed == o) { + // object has not been collected + jreferenceTarget(t, p) = 0; + } else { + jreferenceTarget(t, p) = followed; + } + + object last = p; + p = weakReferenceNext(t, p); + weakReferenceNext(t, last) = 0; + } + } + + virtual unsigned sizeInWords(object o) { + Thread* t = m->rootThread; + + o = m->heap->follow(mask(o)); + + return extendedSize + (t, o, baseSize(t, o, m->heap->follow(objectClass(t, o)))); + } + + virtual unsigned copiedSizeInWords(object o) { + Thread* t = m->rootThread; + + o = m->heap->follow(mask(o)); + + unsigned n = baseSize(t, o, m->heap->follow(objectClass(t, o))); + + if (objectExtended(t, o) or hashTaken(t, o)) { + ++ n; + } + + return n; + } + + virtual void copy(object o, object dst) { + Thread* t = m->rootThread; + + o = m->heap->follow(mask(o)); + object class_ = m->heap->follow(objectClass(t, o)); + + unsigned base = baseSize(t, o, class_); + unsigned n = extendedSize(t, o, base); + + memcpy(dst, o, n * BytesPerWord); + + if (hashTaken(t, o)) { + extendedWord(t, dst, base) = takeHash(t, o); + cast(dst, 0) &= PointerMask; + cast(dst, 0) |= ExtendedMark; + } + + if (classVmFlags(t, class_) & WeakReferenceFlag) { + weakReferenceNext(t, dst) = m->weakReferences; + m->weakReferences = dst; + } + } + + virtual void walk(void* p, Heap::Walker* w) { + Thread* t = m->rootThread; + + p = m->heap->follow(mask(p)); + object class_ = m->heap->follow(objectClass(t, p)); + object objectMask = m->heap->follow(classObjectMask(t, class_)); + + if (objectMask) { +// fprintf(stderr, "p: %p; class: %p; mask: %p; mask length: %d\n", +// p, class_, objectMask, intArrayLength(t, objectMask)); + + unsigned vmFlags = classVmFlags(t, class_); + 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 ((i != 1 or (vmFlags & WeakReferenceFlag) == 0) + and 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); + } + } + + private: + Machine* m; + } it(m); + + m->unsafe = true; + m->heap->collect(type, &it); + m->unsafe = false; + + postCollect(m->rootThread); + + Thread* t = m->rootThread; + for (object f = m->doomed; f; f = tripleThird(t, f)) { + reinterpret_cast(finalizerFinalize(t, f)) + (t, finalizerTarget(t, f)); + } + m->doomed = 0; + + m->weakReferences = 0; +} + +void +removeMonitor(Thread* t, object o) +{ + hashMapRemove(t, t->vm->monitorMap, o, objectHash, referenceEqual); +} + +object +makeByteArray(Thread* t, const char* format, va_list a) +{ + static const unsigned Size = 256; + char buffer[Size]; + + vsnprintf(buffer, Size - 1, format, a); + + object s = makeByteArray(t, strlen(buffer) + 1, false); + memcpy(&byteArrayBody(t, s, 0), buffer, byteArrayLength(t, s)); + + return s; +} + +} // namespace + +namespace vm { + +Machine::Machine(System* system, Heap* heap, ClassFinder* classFinder): + system(system), + heap(heap), + classFinder(classFinder), + rootThread(0), + exclusive(0), + activeCount(0), + liveCount(0), + stateLock(0), + heapLock(0), + classLock(0), + finalizerLock(0), + libraries(0), + classMap(0), + bootstrapClassMap(0), + builtinMap(0), + monitorMap(0), + types(0), + finalizers(0), + doomed(0), + weakReferences(0), + unsafe(false) +{ + jni::populate(&jniEnvVTable); + + if (not system->success(system->make(&stateLock)) or + not system->success(system->make(&heapLock)) or + not system->success(system->make(&classLock)) or + not system->success(system->make(&finalizerLock))) + { + system->abort(); + } +} + +void +Machine::dispose() +{ + stateLock->dispose(); + heapLock->dispose(); + classLock->dispose(); + finalizerLock->dispose(); + + if (libraries) { + libraries->dispose(); + } + + if (rootThread) { + rootThread->dispose(); + } +} + +Thread::Thread(Machine* m): + vtable(&(m->jniEnvVTable)), + vm(m), + next(0), + child(0), + state(NoState), + thread(0), + code(0), + exception(0), + ip(0), + sp(0), + frame(-1), + heapIndex(0), + protector(0), + chain(0) +{ + 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, cast(t->vm->types, 0), arrayClass); + + object classClass = arrayBody(t, m->types, Machine::ClassType); + set(t, cast(classClass, 0), classClass); + + object intArrayClass = arrayBody(t, m->types, Machine::IntArrayType); + set(t, cast(intArrayClass, 0), classClass); + + m->unsafe = false; + + m->bootstrapClassMap = makeHashMap(this, 0, 0); + +#include "type-java-initializations.cpp" + + classVmFlags(t, arrayBody(t, m->types, Machine::WeakReferenceType)) + |= WeakReferenceFlag; + + m->classMap = makeHashMap(this, 0, 0); + m->builtinMap = makeHashMap(this, 0, 0); + m->monitorMap = makeHashMap(this, 0, 0); + + builtin::populate(t, m->builtinMap); + } +} + +void +Thread::dispose() +{ + Chain::dispose(vm->system, chain); + + for (Thread* c = child; c; c = c->next) { + c->dispose(); + } +} + +void +enter(Thread* t, Thread::State s) +{ + if (s == t->state) return; + + ACQUIRE_RAW(t, t->vm->stateLock); + + switch (s) { + case Thread::ExclusiveState: { + assert(t, t->state == Thread::ActiveState); + + while (t->vm->exclusive) { + // another thread got here first. + enter(t, Thread::IdleState); + enter(t, Thread::ActiveState); + } + + t->state = Thread::ExclusiveState; + t->vm->exclusive = t; + + while (t->vm->activeCount > 1) { + t->vm->stateLock->wait(t, 0); + } + } break; + + case Thread::IdleState: + case Thread::ZombieState: { + switch (t->state) { + case Thread::ExclusiveState: { + assert(t, t->vm->exclusive == t); + t->vm->exclusive = 0; + } break; + + case Thread::ActiveState: break; + + default: abort(t); + } + + -- t->vm->activeCount; + if (s == Thread::ZombieState) { + -- t->vm->liveCount; + } + t->state = s; + + t->vm->stateLock->notifyAll(t); + } break; + + case Thread::ActiveState: { + switch (t->state) { + case Thread::ExclusiveState: { + assert(t, t->vm->exclusive == t); + + t->state = s; + t->vm->exclusive = 0; + + t->vm->stateLock->notifyAll(t); + } break; + + case Thread::NoState: + case Thread::IdleState: { + while (t->vm->exclusive) { + t->vm->stateLock->wait(t, 0); + } + + ++ t->vm->activeCount; + if (t->state == Thread::NoState) { + ++ t->vm->liveCount; + } + t->state = s; + } break; + + default: abort(t); + } + } break; + + case Thread::ExitState: { + switch (t->state) { + case Thread::ExclusiveState: { + assert(t, t->vm->exclusive == t); + t->vm->exclusive = 0; + } break; + + case Thread::ActiveState: break; + + default: abort(t); + } + + -- t->vm->activeCount; + t->state = s; + + while (t->vm->liveCount > 1) { + t->vm->stateLock->wait(t, 0); + } + } break; + + default: abort(t); + } +} + +object +allocate2(Thread* t, unsigned sizeInBytes) +{ + if (sizeInBytes > Thread::HeapSizeInBytes and t->chain == 0) { + return allocateLarge(t, sizeInBytes); + } + + ACQUIRE_RAW(t, t->vm->stateLock); + + while (t->vm->exclusive) { + // another thread wants to enter the exclusive state, either for a + // collection or some other reason. We give it a chance here. + enter(t, Thread::IdleState); + enter(t, Thread::ActiveState); + } + + if (t->heapIndex + divide(sizeInBytes, BytesPerWord) + >= Thread::HeapSizeInWords) + { + enter(t, Thread::ExclusiveState); + collect(t->vm, Heap::MinorCollection); + enter(t, Thread::ActiveState); + } + + if (sizeInBytes > Thread::HeapSizeInBytes) { + return allocateLarge(t, sizeInBytes); + } else { + return allocateSmall(t, sizeInBytes); + } +} + +object +makeByteArray(Thread* t, const char* format, ...) +{ + va_list a; + va_start(a, format); + object s = ::makeByteArray(t, format, a); + va_end(a); + + return s; +} + +object +makeString(Thread* t, const char* format, ...) +{ + va_list a; + va_start(a, format); + object s = ::makeByteArray(t, format, a); + va_end(a); + + return makeString(t, s, 0, byteArrayLength(t, s), 0); +} + +object +hashMapFindNode(Thread* t, object map, object key, + uint32_t (*hash)(Thread*, object), + bool (*equal)(Thread*, object, object)) +{ + object array = hashMapArray(t, map); + if (array) { + unsigned index = hash(t, key) & (arrayLength(t, array) - 1); + object n = arrayBody(t, array, index); + while (n) { + if (equal(t, key, tripleFirst(t, n))) { + return n; + } + + n = tripleThird(t, n); + } + } + return 0; +} + +void +hashMapResize(Thread* t, object map, uint32_t (*hash)(Thread*, object), + unsigned size) +{ + PROTECT(t, map); + + object oldArray = hashMapArray(t, map); + unsigned oldLength = (oldArray ? arrayLength(t, oldArray) : 0); + PROTECT(t, oldArray); + + unsigned newLength = nextPowerOfTwo(size); + object newArray = makeArray(t, newLength, true); + + if (oldArray) { + for (unsigned i = 0; i < oldLength; ++i) { + object next; + for (object p = arrayBody(t, oldArray, i); p; p = next) { + next = tripleThird(t, p); + + object key = tripleFirst(t, p); + unsigned index = hash(t, key) & (newLength - 1); + object n = arrayBody(t, newArray, index); + + set(t, tripleThird(t, p), n); + set(t, arrayBody(t, newArray, index), p); + } + } + } + + set(t, hashMapArray(t, map), newArray); +} + +void +hashMapInsert(Thread* t, object map, object key, object value, + uint32_t (*hash)(Thread*, object)) +{ + object array = hashMapArray(t, map); + PROTECT(t, array); + + ++ hashMapSize(t, map); + + if (array == 0 or hashMapSize(t, map) >= arrayLength(t, array) * 2) { + PROTECT(t, map); + PROTECT(t, key); + PROTECT(t, value); + + hashMapResize(t, map, hash, array ? arrayLength(t, array) * 2 : 16); + array = hashMapArray(t, map); + } + + unsigned index = hash(t, key) & (arrayLength(t, array) - 1); + object n = arrayBody(t, array, index); + + n = makeTriple(t, key, value, n); + + set(t, arrayBody(t, array, index), n); +} + +object +hashMapRemove(Thread* t, object map, object key, + uint32_t (*hash)(Thread*, object), + bool (*equal)(Thread*, object, object)) +{ + object array = hashMapArray(t, map); + object o = 0; + if (array) { + unsigned index = hash(t, key) & (arrayLength(t, array) - 1); + object n = arrayBody(t, array, index); + object p = 0; + while (n) { + if (equal(t, key, tripleFirst(t, n))) { + o = tripleFirst(t, n); + if (p) { + set(t, tripleThird(t, p), tripleThird(t, n)); + } else { + set(t, arrayBody(t, array, index), tripleThird(t, n)); + } + } + + p = n; + n = tripleThird(t, n); + } + } + + if (hashMapSize(t, map) <= arrayLength(t, array) / 3) { + hashMapResize(t, map, hash, arrayLength(t, array) / 2); + } + + return o; +} + +object +makeTrace(Thread* t, int frame) +{ + unsigned count = 0; + for (int f = frame; f >= 0; f = frameNext(t, f)) { + ++ count; + } + + object trace = makeObjectArray + (t, arrayBody(t, t->vm->types, Machine::StackTraceElementType), + count, true); + PROTECT(t, trace); + + unsigned index = 0; + for (int f = frame; f >= 0; f = frameNext(t, f)) { + object e = makeStackTraceElement(t, frameMethod(t, f), frameIp(t, f)); + set(t, objectArrayBody(t, trace, index++), e); + } + + return trace; +} + +object +hashMapIterator(Thread* t, object map) +{ + object array = hashMapArray(t, map); + if (array) { + for (unsigned i = 0; i < arrayLength(t, array); ++i) { + if (arrayBody(t, array, i)) { + return makeHashMapIterator(t, map, arrayBody(t, array, i), i + 1); + } + } + } + return 0; +} + +object +hashMapIteratorNext(Thread* t, object it) +{ + object map = hashMapIteratorMap(t, it); + object node = hashMapIteratorNode(t, it); + unsigned index = hashMapIteratorIndex(t, it); + + if (tripleThird(t, node)) { + return makeHashMapIterator(t, map, tripleThird(t, node), index + 1); + } else { + object array = hashMapArray(t, map); + for (unsigned i = index; i < arrayLength(t, array); ++i) { + if (arrayBody(t, array, i)) { + return makeHashMapIterator(t, map, arrayBody(t, array, i), i + 1); + } + } + return 0; + } +} + +void +listAppend(Thread* t, object list, object value) +{ + PROTECT(t, list); + + ++ listSize(t, list); + + object p = makePair(t, value, 0); + if (listFront(t, list)) { + set(t, pairSecond(t, listRear(t, list)), p); + } else { + set(t, listFront(t, list), p); + } + set(t, listRear(t, list), p); +} + +void +addFinalizer(Thread* t, object target, void (*finalize)(Thread*, object)) +{ + PROTECT(t, target); + + ACQUIRE(t, t->vm->finalizerLock); + + object p = makePointer(t, reinterpret_cast(finalize)); + t->vm->finalizers = makeTriple(t, target, p, t->vm->finalizers); +} + +System::Monitor* +objectMonitor(Thread* t, object o) +{ + object p = hashMapFind(t, t->vm->monitorMap, o, objectHash, referenceEqual); + + if (p) { + return static_cast(pointerValue(t, p)); + } else { + PROTECT(t, o); + + ENTER(t, Thread::ExclusiveState); + + System::Monitor* m; + System::Status s = t->vm->system->make(&m); + expect(t, t->vm->system->success(s)); + + p = makePointer(t, m); + PROTECT(t, p); + + object wr = makeWeakReference(t, o, 0); + + hashMapInsert(t, t->vm->monitorMap, wr, p, referenceHash); + + addFinalizer(t, o, removeMonitor); + + return m; + } +} + +#include "type-constructors.cpp" + +} // namespace vm diff --git a/src/vm-declarations.h b/src/machine.h similarity index 97% rename from src/vm-declarations.h rename to src/machine.h index 303c2a11fa..5c31d209f1 100644 --- a/src/vm-declarations.h +++ b/src/machine.h @@ -1,5 +1,5 @@ -#ifndef VM_DECLARATIONS_H -#define VM_DECLARATIONS_H +#ifndef MACHINE_H +#define MACHINE_H #include "common.h" #include "system.h" @@ -1578,6 +1578,42 @@ frameBase(Thread* t, int frame) return peekInt(t, frame + FrameBaseOffset); } +inline object +localObject(Thread* t, unsigned index) +{ + return peekObject(t, frameBase(t, t->frame) + index); +} + +inline uint32_t +localInt(Thread* t, unsigned index) +{ + return peekInt(t, frameBase(t, t->frame) + index); +} + +inline uint64_t +localLong(Thread* t, unsigned index) +{ + return peekLong(t, frameBase(t, t->frame) + index); +} + +inline void +setLocalObject(Thread* t, unsigned index, object value) +{ + pokeObject(t, frameBase(t, t->frame) + index, value); +} + +inline void +setLocalInt(Thread* t, unsigned index, uint32_t value) +{ + pokeInt(t, frameBase(t, t->frame) + index, value); +} + +inline void +setLocalLong(Thread* t, unsigned index, uint64_t value) +{ + pokeLong(t, frameBase(t, t->frame) + index, value); +} + inline object makeTrace(Thread* t) { @@ -1759,6 +1795,12 @@ hashMapIteratorNext(Thread* t, object it); void listAppend(Thread* t, object list, object value); +void +addFinalizer(Thread* t, object target, void (*finalize)(Thread*, object)); + +System::Monitor* +objectMonitor(Thread* t, object o); + } // namespace vm -#endif//VM_DECLARATIONS_H +#endif//MACHINE_H diff --git a/src/main.cpp b/src/main.cpp index c49969137f..1ba2bfcc22 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,17 +1,18 @@ #include "sys/mman.h" #include "sys/types.h" #include "sys/stat.h" -#include -#include +#include "sys/time.h" +#include "time.h" #include "fcntl.h" #include "dlfcn.h" #include "errno.h" #include "pthread.h" + #include "common.h" #include "system.h" #include "heap.h" #include "class-finder.h" -#include "vm.h" +#include "run.h" using namespace vm; diff --git a/src/vm.cpp b/src/run.cpp similarity index 81% rename from src/vm.cpp rename to src/run.cpp index 0dc1fc8b08..ac67ed272c 100644 --- a/src/vm.cpp +++ b/src/run.cpp @@ -4,10 +4,10 @@ #include "class-finder.h" #include "stream.h" #include "constants.h" -#include "vm.h" -#include "vm-jni.h" -#include "vm-builtin.h" -#include "vm-declarations.h" +#include "run.h" +#include "jnienv.h" +#include "builtin.h" +#include "machine.h" using namespace vm; @@ -58,231 +58,6 @@ popFrame(Thread* t) } } -void -visitRoots(Thread* t, Heap::Visitor* v) -{ - t->heapIndex = 0; - - v->visit(&(t->thread)); - v->visit(&(t->code)); - v->visit(&(t->exception)); - - for (unsigned i = 0; i < t->sp; ++i) { - if (t->stack[i * 2] == ObjectTag) { - v->visit(reinterpret_cast(t->stack + (i * 2) + 1)); - } - } - - for (Thread::Protector* p = t->protector; p; p = p->next) { - v->visit(p->p); - } - - for (Thread* c = t->child; c; c = c->next) { - visitRoots(c, v); - } -} - -void -postCollect(Thread* t) -{ - Chain::dispose(t->vm->system, t->chain); - t->chain = 0; - - for (Thread* c = t->child; c; c = c->next) { - postCollect(c); - } -} - -void -collect(Machine* m, Heap::CollectionType type) -{ - class Client: public Heap::Client { - public: - Client(Machine* m): m(m) { } - - virtual void visitRoots(Heap::Visitor* v) { - 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) { - ::visitRoots(t, v); - } - - Thread* t = m->rootThread; - for (object* f = &(m->finalizers); *f;) { - object o = finalizerTarget(t, *f); - if (m->heap->follow(o) == o) { - // object has not been collected - object x = *f; - *f = finalizerNext(t, x); - finalizerNext(t, x) = m->doomed; - m->doomed = x; - } else { - f = &finalizerNext(t, *f); - } - } - - for (object* f = &(m->finalizers); *f; f = &finalizerNext(t, *f)) { - v->visit(f); - } - - for (object* f = &(m->doomed); *f; f = &finalizerNext(t, *f)) { - v->visit(f); - } - - for (object p = m->weakReferences; p;) { - object o = jreferenceTarget(t, p); - object followed = m->heap->follow(o); - if (followed == o) { - // object has not been collected - jreferenceTarget(t, p) = 0; - } else { - jreferenceTarget(t, p) = followed; - } - - object last = p; - p = weakReferenceNext(t, p); - weakReferenceNext(t, last) = 0; - } - } - - virtual unsigned sizeInWords(object o) { - Thread* t = m->rootThread; - - o = m->heap->follow(mask(o)); - - return extendedSize - (t, o, baseSize(t, o, m->heap->follow(objectClass(t, o)))); - } - - virtual unsigned copiedSizeInWords(object o) { - Thread* t = m->rootThread; - - o = m->heap->follow(mask(o)); - - unsigned n = baseSize(t, o, m->heap->follow(objectClass(t, o))); - - if (objectExtended(t, o) or hashTaken(t, o)) { - ++ n; - } - - return n; - } - - virtual void copy(object o, object dst) { - Thread* t = m->rootThread; - - o = m->heap->follow(mask(o)); - object class_ = m->heap->follow(objectClass(t, o)); - - unsigned base = baseSize(t, o, class_); - unsigned n = extendedSize(t, o, base); - - memcpy(dst, o, n * BytesPerWord); - - if (hashTaken(t, o)) { - extendedWord(t, dst, base) = takeHash(t, o); - cast(dst, 0) &= PointerMask; - cast(dst, 0) |= ExtendedMark; - } - - if (classVmFlags(t, class_) & WeakReferenceFlag) { - weakReferenceNext(t, dst) = m->weakReferences; - m->weakReferences = dst; - } - } - - virtual void walk(void* p, Heap::Walker* w) { - Thread* t = m->rootThread; - - p = m->heap->follow(mask(p)); - object class_ = m->heap->follow(objectClass(t, p)); - object objectMask = m->heap->follow(classObjectMask(t, class_)); - - if (objectMask) { -// fprintf(stderr, "p: %p; class: %p; mask: %p; mask length: %d\n", -// p, class_, objectMask, intArrayLength(t, objectMask)); - - unsigned vmFlags = classVmFlags(t, class_); - 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 ((i != 1 or (vmFlags & WeakReferenceFlag) == 0) - and 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); - } - } - - private: - Machine* m; - } it(m); - - m->unsafe = true; - m->heap->collect(type, &it); - m->unsafe = false; - - postCollect(m->rootThread); - - Thread* t = m->rootThread; - for (object f = m->doomed; f; f = tripleThird(t, f)) { - reinterpret_cast(finalizerFinalize(t, f)) - (t, finalizerTarget(t, f)); - } - m->doomed = 0; - - m->weakReferences = 0; -} - inline object make(Thread* t, object class_) { @@ -295,66 +70,6 @@ make(Thread* t, object class_) return instance; } -void -addFinalizer(Thread* t, object target, void (*finalize)(Thread*, object)) -{ - PROTECT(t, target); - - ACQUIRE(t, t->vm->finalizerLock); - - object p = makePointer(t, reinterpret_cast(finalize)); - t->vm->finalizers = makeTriple(t, target, p, t->vm->finalizers); -} - -void -removeMonitor(Thread* t, object o) -{ - hashMapRemove(t, t->vm->monitorMap, o, objectHash, referenceEqual); -} - -System::Monitor* -objectMonitor(Thread* t, object o) -{ - object p = hashMapFind(t, t->vm->monitorMap, o, objectHash, referenceEqual); - - if (p) { - return static_cast(pointerValue(t, p)); - } else { - PROTECT(t, o); - - ENTER(t, Thread::ExclusiveState); - - System::Monitor* m; - System::Status s = t->vm->system->make(&m); - expect(t, t->vm->system->success(s)); - - p = makePointer(t, m); - PROTECT(t, p); - - object wr = makeWeakReference(t, o, 0); - - hashMapInsert(t, t->vm->monitorMap, wr, p, referenceHash); - - addFinalizer(t, o, removeMonitor); - - return m; - } -} - -object -makeByteArray(Thread* t, const char* format, va_list a) -{ - static const unsigned Size = 256; - char buffer[Size]; - - vsnprintf(buffer, Size - 1, format, a); - - object s = makeByteArray(t, strlen(buffer) + 1, false); - memcpy(&byteArrayBody(t, s, 0), buffer, byteArrayLength(t, s)); - - return s; -} - unsigned fieldCode(Thread* t, unsigned javaCode) { @@ -1754,42 +1469,6 @@ invokeNative(Thread* t, object method) }; } -inline object -localObject(Thread* t, unsigned index) -{ - return peekObject(t, frameBase(t, t->frame) + index); -} - -inline uint32_t -localInt(Thread* t, unsigned index) -{ - return peekInt(t, frameBase(t, t->frame) + index); -} - -inline uint64_t -localLong(Thread* t, unsigned index) -{ - return peekLong(t, frameBase(t, t->frame) + index); -} - -inline void -setLocalObject(Thread* t, unsigned index, object value) -{ - pokeObject(t, frameBase(t, t->frame) + index, value); -} - -inline void -setLocalInt(Thread* t, unsigned index, uint32_t value) -{ - pokeInt(t, frameBase(t, t->frame) + index, value); -} - -inline void -setLocalLong(Thread* t, unsigned index, uint64_t value) -{ - pokeLong(t, frameBase(t, t->frame) + index, value); -} - object run(Thread* t) { @@ -3488,454 +3167,6 @@ run(Thread* t, const char* className, int argc, const char** argv) namespace vm { -Machine::Machine(System* system, Heap* heap, ClassFinder* classFinder): - system(system), - heap(heap), - classFinder(classFinder), - rootThread(0), - exclusive(0), - activeCount(0), - liveCount(0), - stateLock(0), - heapLock(0), - classLock(0), - finalizerLock(0), - libraries(0), - classMap(0), - bootstrapClassMap(0), - builtinMap(0), - monitorMap(0), - types(0), - finalizers(0), - doomed(0), - weakReferences(0), - unsafe(false) -{ - jni::populate(&jniEnvVTable); - - if (not system->success(system->make(&stateLock)) or - not system->success(system->make(&heapLock)) or - not system->success(system->make(&classLock)) or - not system->success(system->make(&finalizerLock))) - { - system->abort(); - } -} - -void -Machine::dispose() -{ - stateLock->dispose(); - heapLock->dispose(); - classLock->dispose(); - finalizerLock->dispose(); - - if (libraries) { - libraries->dispose(); - } - - if (rootThread) { - rootThread->dispose(); - } -} - -Thread::Thread(Machine* m): - vtable(&(m->jniEnvVTable)), - vm(m), - next(0), - child(0), - state(NoState), - thread(0), - code(0), - exception(0), - ip(0), - sp(0), - frame(-1), - heapIndex(0), - protector(0), - chain(0) -{ - 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, cast(t->vm->types, 0), arrayClass); - - object classClass = arrayBody(t, m->types, Machine::ClassType); - set(t, cast(classClass, 0), classClass); - - object intArrayClass = arrayBody(t, m->types, Machine::IntArrayType); - set(t, cast(intArrayClass, 0), classClass); - - m->unsafe = false; - - m->bootstrapClassMap = makeHashMap(this, 0, 0); - -#include "type-java-initializations.cpp" - - classVmFlags(t, arrayBody(t, m->types, Machine::WeakReferenceType)) - |= WeakReferenceFlag; - - m->classMap = makeHashMap(this, 0, 0); - m->builtinMap = makeHashMap(this, 0, 0); - m->monitorMap = makeHashMap(this, 0, 0); - - builtin::populate(t, m->builtinMap); - } -} - -void -Thread::dispose() -{ - Chain::dispose(vm->system, chain); - - for (Thread* c = child; c; c = c->next) { - c->dispose(); - } -} - -void -enter(Thread* t, Thread::State s) -{ - if (s == t->state) return; - - ACQUIRE_RAW(t, t->vm->stateLock); - - switch (s) { - case Thread::ExclusiveState: { - assert(t, t->state == Thread::ActiveState); - - while (t->vm->exclusive) { - // another thread got here first. - enter(t, Thread::IdleState); - enter(t, Thread::ActiveState); - } - - t->state = Thread::ExclusiveState; - t->vm->exclusive = t; - - while (t->vm->activeCount > 1) { - t->vm->stateLock->wait(t, 0); - } - } break; - - case Thread::IdleState: - case Thread::ZombieState: { - switch (t->state) { - case Thread::ExclusiveState: { - assert(t, t->vm->exclusive == t); - t->vm->exclusive = 0; - } break; - - case Thread::ActiveState: break; - - default: abort(t); - } - - -- t->vm->activeCount; - if (s == Thread::ZombieState) { - -- t->vm->liveCount; - } - t->state = s; - - t->vm->stateLock->notifyAll(t); - } break; - - case Thread::ActiveState: { - switch (t->state) { - case Thread::ExclusiveState: { - assert(t, t->vm->exclusive == t); - - t->state = s; - t->vm->exclusive = 0; - - t->vm->stateLock->notifyAll(t); - } break; - - case Thread::NoState: - case Thread::IdleState: { - while (t->vm->exclusive) { - t->vm->stateLock->wait(t, 0); - } - - ++ t->vm->activeCount; - if (t->state == Thread::NoState) { - ++ t->vm->liveCount; - } - t->state = s; - } break; - - default: abort(t); - } - } break; - - case Thread::ExitState: { - switch (t->state) { - case Thread::ExclusiveState: { - assert(t, t->vm->exclusive == t); - t->vm->exclusive = 0; - } break; - - case Thread::ActiveState: break; - - default: abort(t); - } - - -- t->vm->activeCount; - t->state = s; - - while (t->vm->liveCount > 1) { - t->vm->stateLock->wait(t, 0); - } - } break; - - default: abort(t); - } -} - -object -allocate2(Thread* t, unsigned sizeInBytes) -{ - if (sizeInBytes > Thread::HeapSizeInBytes and t->chain == 0) { - return allocateLarge(t, sizeInBytes); - } - - ACQUIRE_RAW(t, t->vm->stateLock); - - while (t->vm->exclusive) { - // another thread wants to enter the exclusive state, either for a - // collection or some other reason. We give it a chance here. - enter(t, Thread::IdleState); - enter(t, Thread::ActiveState); - } - - if (t->heapIndex + divide(sizeInBytes, BytesPerWord) - >= Thread::HeapSizeInWords) - { - enter(t, Thread::ExclusiveState); - collect(t->vm, Heap::MinorCollection); - enter(t, Thread::ActiveState); - } - - if (sizeInBytes > Thread::HeapSizeInBytes) { - return allocateLarge(t, sizeInBytes); - } else { - return allocateSmall(t, sizeInBytes); - } -} - -object -makeByteArray(Thread* t, const char* format, ...) -{ - va_list a; - va_start(a, format); - object s = ::makeByteArray(t, format, a); - va_end(a); - - return s; -} - -object -makeString(Thread* t, const char* format, ...) -{ - va_list a; - va_start(a, format); - object s = ::makeByteArray(t, format, a); - va_end(a); - - return makeString(t, s, 0, byteArrayLength(t, s), 0); -} - -object -hashMapFindNode(Thread* t, object map, object key, - uint32_t (*hash)(Thread*, object), - bool (*equal)(Thread*, object, object)) -{ - object array = hashMapArray(t, map); - if (array) { - unsigned index = hash(t, key) & (arrayLength(t, array) - 1); - object n = arrayBody(t, array, index); - while (n) { - if (equal(t, key, tripleFirst(t, n))) { - return n; - } - - n = tripleThird(t, n); - } - } - return 0; -} - -void -hashMapResize(Thread* t, object map, uint32_t (*hash)(Thread*, object), - unsigned size) -{ - PROTECT(t, map); - - object oldArray = hashMapArray(t, map); - unsigned oldLength = (oldArray ? arrayLength(t, oldArray) : 0); - PROTECT(t, oldArray); - - unsigned newLength = nextPowerOfTwo(size); - object newArray = makeArray(t, newLength, true); - - if (oldArray) { - for (unsigned i = 0; i < oldLength; ++i) { - object next; - for (object p = arrayBody(t, oldArray, i); p; p = next) { - next = tripleThird(t, p); - - object key = tripleFirst(t, p); - unsigned index = hash(t, key) & (newLength - 1); - object n = arrayBody(t, newArray, index); - - set(t, tripleThird(t, p), n); - set(t, arrayBody(t, newArray, index), p); - } - } - } - - set(t, hashMapArray(t, map), newArray); -} - -void -hashMapInsert(Thread* t, object map, object key, object value, - uint32_t (*hash)(Thread*, object)) -{ - object array = hashMapArray(t, map); - PROTECT(t, array); - - ++ hashMapSize(t, map); - - if (array == 0 or hashMapSize(t, map) >= arrayLength(t, array) * 2) { - PROTECT(t, map); - PROTECT(t, key); - PROTECT(t, value); - - hashMapResize(t, map, hash, array ? arrayLength(t, array) * 2 : 16); - array = hashMapArray(t, map); - } - - unsigned index = hash(t, key) & (arrayLength(t, array) - 1); - object n = arrayBody(t, array, index); - - n = makeTriple(t, key, value, n); - - set(t, arrayBody(t, array, index), n); -} - -object -hashMapRemove(Thread* t, object map, object key, - uint32_t (*hash)(Thread*, object), - bool (*equal)(Thread*, object, object)) -{ - object array = hashMapArray(t, map); - object o = 0; - if (array) { - unsigned index = hash(t, key) & (arrayLength(t, array) - 1); - object n = arrayBody(t, array, index); - object p = 0; - while (n) { - if (equal(t, key, tripleFirst(t, n))) { - o = tripleFirst(t, n); - if (p) { - set(t, tripleThird(t, p), tripleThird(t, n)); - } else { - set(t, arrayBody(t, array, index), tripleThird(t, n)); - } - } - - p = n; - n = tripleThird(t, n); - } - } - - if (hashMapSize(t, map) <= arrayLength(t, array) / 3) { - hashMapResize(t, map, hash, arrayLength(t, array) / 2); - } - - return o; -} - -object -makeTrace(Thread* t, int frame) -{ - unsigned count = 0; - for (int f = frame; f >= 0; f = frameNext(t, f)) { - ++ count; - } - - object trace = makeObjectArray - (t, arrayBody(t, t->vm->types, Machine::StackTraceElementType), - count, true); - PROTECT(t, trace); - - unsigned index = 0; - for (int f = frame; f >= 0; f = frameNext(t, f)) { - object e = makeStackTraceElement(t, frameMethod(t, f), frameIp(t, f)); - set(t, objectArrayBody(t, trace, index++), e); - } - - return trace; -} - -object -hashMapIterator(Thread* t, object map) -{ - object array = hashMapArray(t, map); - if (array) { - for (unsigned i = 0; i < arrayLength(t, array); ++i) { - if (arrayBody(t, array, i)) { - return makeHashMapIterator(t, map, arrayBody(t, array, i), i + 1); - } - } - } - return 0; -} - -object -hashMapIteratorNext(Thread* t, object it) -{ - object map = hashMapIteratorMap(t, it); - object node = hashMapIteratorNode(t, it); - unsigned index = hashMapIteratorIndex(t, it); - - if (tripleThird(t, node)) { - return makeHashMapIterator(t, map, tripleThird(t, node), index + 1); - } else { - object array = hashMapArray(t, map); - for (unsigned i = index; i < arrayLength(t, array); ++i) { - if (arrayBody(t, array, i)) { - return makeHashMapIterator(t, map, arrayBody(t, array, i), i + 1); - } - } - return 0; - } -} - -void -listAppend(Thread* t, object list, object value) -{ - PROTECT(t, list); - - ++ listSize(t, list); - - object p = makePair(t, value, 0); - if (listFront(t, list)) { - set(t, pairSecond(t, listRear(t, list)), p); - } else { - set(t, listFront(t, list), p); - } - set(t, listRear(t, list), p); -} - -#include "type-constructors.cpp" - void run(System* system, Heap* heap, ClassFinder* classFinder, const char* className, int argc, const char** argv) diff --git a/src/vm.h b/src/run.h similarity index 82% rename from src/vm.h rename to src/run.h index ecb81bf02c..75bcbfe04a 100644 --- a/src/vm.h +++ b/src/run.h @@ -1,5 +1,5 @@ -#ifndef VM_H -#define VM_H +#ifndef RUN_H +#define RUN_H #include "system.h" #include "heap.h" @@ -13,4 +13,4 @@ run(System* sys, Heap* heap, ClassFinder* classFinder, } -#endif//VM_H +#endif//RUN_H