mirror of
https://github.com/corda/corda.git
synced 2024-12-28 16:58:55 +00:00
more refactoring
This commit is contained in:
parent
96000a7c67
commit
3bd267b47a
19
makefile
19
makefile
@ -1,4 +1,4 @@
|
|||||||
#MAKEFLAGS = -s
|
MAKEFLAGS = -s
|
||||||
|
|
||||||
arch = $(shell uname -m)
|
arch = $(shell uname -m)
|
||||||
ifeq ($(arch),i586)
|
ifeq ($(arch),i586)
|
||||||
@ -55,6 +55,7 @@ generated-code = \
|
|||||||
$(bld)/type-constructors.cpp \
|
$(bld)/type-constructors.cpp \
|
||||||
$(bld)/type-initializations.cpp \
|
$(bld)/type-initializations.cpp \
|
||||||
$(bld)/type-java-initializations.cpp
|
$(bld)/type-java-initializations.cpp
|
||||||
|
|
||||||
interpreter-depends = \
|
interpreter-depends = \
|
||||||
$(generated-code) \
|
$(generated-code) \
|
||||||
$(src)/common.h \
|
$(src)/common.h \
|
||||||
@ -63,14 +64,16 @@ interpreter-depends = \
|
|||||||
$(src)/class-finder.h \
|
$(src)/class-finder.h \
|
||||||
$(src)/stream.h \
|
$(src)/stream.h \
|
||||||
$(src)/constants.h \
|
$(src)/constants.h \
|
||||||
$(src)/vm.h \
|
$(src)/run.h \
|
||||||
$(src)/vm-jni.h \
|
$(src)/jnienv.h \
|
||||||
$(src)/vm-builtin.h \
|
$(src)/builtin.h \
|
||||||
$(src)/vm-declarations.h
|
$(src)/machine.h
|
||||||
|
|
||||||
interpreter-sources = \
|
interpreter-sources = \
|
||||||
$(src)/vm.cpp \
|
$(src)/run.cpp \
|
||||||
$(src)/vm-jni.cpp \
|
$(src)/machine.cpp \
|
||||||
$(src)/vm-builtin.cpp \
|
$(src)/jnienv.cpp \
|
||||||
|
$(src)/builtin.cpp \
|
||||||
$(src)/heap.cpp \
|
$(src)/heap.cpp \
|
||||||
$(src)/main.cpp
|
$(src)/main.cpp
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "vm-builtin.h"
|
#include "builtin.h"
|
||||||
|
#include "machine.h"
|
||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
namespace builtin {
|
namespace builtin {
|
@ -1,7 +1,7 @@
|
|||||||
#ifndef VM_BUITLIN_H
|
#ifndef BUITLIN_H
|
||||||
#define VM_BUITLIN_H
|
#define BUITLIN_H
|
||||||
|
|
||||||
#include "vm-declarations.h"
|
#include "machine.h"
|
||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
namespace builtin {
|
namespace builtin {
|
||||||
@ -12,4 +12,4 @@ populate(Thread* t, object map);
|
|||||||
} // namespace builtin
|
} // namespace builtin
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
|
||||||
#endif//VM_BUILTIN_H
|
#endif//BUILTIN_H
|
@ -1,5 +1,5 @@
|
|||||||
#include "vm-jni.h"
|
#include "jnienv.h"
|
||||||
#include "vm-declarations.h"
|
#include "machine.h"
|
||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
namespace jni {
|
namespace jni {
|
@ -1,7 +1,7 @@
|
|||||||
#ifndef VM_JNI_H
|
#ifndef JNIENV_H
|
||||||
#define VM_JNI_H
|
#define JNIENV_H
|
||||||
|
|
||||||
#include "vm-declarations.h"
|
#include "machine.h"
|
||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
namespace jni {
|
namespace jni {
|
||||||
@ -12,4 +12,4 @@ populate(JNIEnvVTable* table);
|
|||||||
} // namespace jni
|
} // namespace jni
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
|
||||||
#endif//VM_JNI_H
|
#endif//JNIENV_H
|
746
src/machine.cpp
Normal file
746
src/machine.cpp
Normal file
@ -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<object*>(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<uintptr_t>(dst, 0) &= PointerMask;
|
||||||
|
cast<uintptr_t>(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<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 ((i != 1 or (vmFlags & WeakReferenceFlag) == 0)
|
||||||
|
and 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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<void (*)(Thread*, object)>(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<object>(t->vm->types, 0), arrayClass);
|
||||||
|
|
||||||
|
object classClass = arrayBody(t, m->types, Machine::ClassType);
|
||||||
|
set(t, cast<object>(classClass, 0), classClass);
|
||||||
|
|
||||||
|
object intArrayClass = arrayBody(t, m->types, Machine::IntArrayType);
|
||||||
|
set(t, cast<object>(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<void*>(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<System::Monitor*>(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
|
@ -1,5 +1,5 @@
|
|||||||
#ifndef VM_DECLARATIONS_H
|
#ifndef MACHINE_H
|
||||||
#define VM_DECLARATIONS_H
|
#define MACHINE_H
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
@ -1578,6 +1578,42 @@ frameBase(Thread* t, int frame)
|
|||||||
return peekInt(t, frame + FrameBaseOffset);
|
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
|
inline object
|
||||||
makeTrace(Thread* t)
|
makeTrace(Thread* t)
|
||||||
{
|
{
|
||||||
@ -1759,6 +1795,12 @@ hashMapIteratorNext(Thread* t, object it);
|
|||||||
void
|
void
|
||||||
listAppend(Thread* t, object list, object value);
|
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
|
} // namespace vm
|
||||||
|
|
||||||
#endif//VM_DECLARATIONS_H
|
#endif//MACHINE_H
|
@ -1,17 +1,18 @@
|
|||||||
#include "sys/mman.h"
|
#include "sys/mman.h"
|
||||||
#include "sys/types.h"
|
#include "sys/types.h"
|
||||||
#include "sys/stat.h"
|
#include "sys/stat.h"
|
||||||
#include <sys/time.h>
|
#include "sys/time.h"
|
||||||
#include <time.h>
|
#include "time.h"
|
||||||
#include "fcntl.h"
|
#include "fcntl.h"
|
||||||
#include "dlfcn.h"
|
#include "dlfcn.h"
|
||||||
#include "errno.h"
|
#include "errno.h"
|
||||||
#include "pthread.h"
|
#include "pthread.h"
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "heap.h"
|
#include "heap.h"
|
||||||
#include "class-finder.h"
|
#include "class-finder.h"
|
||||||
#include "vm.h"
|
#include "run.h"
|
||||||
|
|
||||||
using namespace vm;
|
using namespace vm;
|
||||||
|
|
||||||
|
@ -4,10 +4,10 @@
|
|||||||
#include "class-finder.h"
|
#include "class-finder.h"
|
||||||
#include "stream.h"
|
#include "stream.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "vm.h"
|
#include "run.h"
|
||||||
#include "vm-jni.h"
|
#include "jnienv.h"
|
||||||
#include "vm-builtin.h"
|
#include "builtin.h"
|
||||||
#include "vm-declarations.h"
|
#include "machine.h"
|
||||||
|
|
||||||
using namespace vm;
|
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<object*>(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<uintptr_t>(dst, 0) &= PointerMask;
|
|
||||||
cast<uintptr_t>(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<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 ((i != 1 or (vmFlags & WeakReferenceFlag) == 0)
|
|
||||||
and 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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<void (*)(Thread*, object)>(finalizerFinalize(t, f))
|
|
||||||
(t, finalizerTarget(t, f));
|
|
||||||
}
|
|
||||||
m->doomed = 0;
|
|
||||||
|
|
||||||
m->weakReferences = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline object
|
inline object
|
||||||
make(Thread* t, object class_)
|
make(Thread* t, object class_)
|
||||||
{
|
{
|
||||||
@ -295,66 +70,6 @@ make(Thread* t, object class_)
|
|||||||
return instance;
|
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<void*>(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<System::Monitor*>(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
|
unsigned
|
||||||
fieldCode(Thread* t, unsigned javaCode)
|
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
|
object
|
||||||
run(Thread* t)
|
run(Thread* t)
|
||||||
{
|
{
|
||||||
@ -3488,454 +3167,6 @@ run(Thread* t, const char* className, int argc, const char** argv)
|
|||||||
|
|
||||||
namespace vm {
|
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<object>(t->vm->types, 0), arrayClass);
|
|
||||||
|
|
||||||
object classClass = arrayBody(t, m->types, Machine::ClassType);
|
|
||||||
set(t, cast<object>(classClass, 0), classClass);
|
|
||||||
|
|
||||||
object intArrayClass = arrayBody(t, m->types, Machine::IntArrayType);
|
|
||||||
set(t, cast<object>(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
|
void
|
||||||
run(System* system, Heap* heap, ClassFinder* classFinder,
|
run(System* system, Heap* heap, ClassFinder* classFinder,
|
||||||
const char* className, int argc, const char** argv)
|
const char* className, int argc, const char** argv)
|
@ -1,5 +1,5 @@
|
|||||||
#ifndef VM_H
|
#ifndef RUN_H
|
||||||
#define VM_H
|
#define RUN_H
|
||||||
|
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "heap.h"
|
#include "heap.h"
|
||||||
@ -13,4 +13,4 @@ run(System* sys, Heap* heap, ClassFinder* classFinder,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif//VM_H
|
#endif//RUN_H
|
Loading…
Reference in New Issue
Block a user