mirror of
https://github.com/corda/corda.git
synced 2024-12-29 09:18:58 +00:00
refactoring effort to pave the way for JIT compilation
This commit is contained in:
parent
65a3ee4277
commit
8d983c8a39
6
makefile
6
makefile
@ -93,9 +93,9 @@ interpreter-depends = \
|
||||
$(src)/system.h \
|
||||
$(src)/heap.h \
|
||||
$(src)/finder.h \
|
||||
$(src)/processor.h \
|
||||
$(src)/stream.h \
|
||||
$(src)/constants.h \
|
||||
$(src)/run.h \
|
||||
$(src)/jnienv.h \
|
||||
$(src)/machine.h
|
||||
|
||||
@ -104,7 +104,7 @@ interpreter-sources = \
|
||||
$(src)/finder.cpp \
|
||||
$(src)/machine.cpp \
|
||||
$(src)/heap.cpp \
|
||||
$(src)/run.cpp \
|
||||
$(src)/interpret.cpp \
|
||||
$(src)/builtin.cpp \
|
||||
$(src)/jnienv.cpp \
|
||||
$(src)/main.cpp
|
||||
@ -151,7 +151,7 @@ flags = -cp $(cls)
|
||||
args = $(flags) $(call class-name,$(input))
|
||||
|
||||
.PHONY: build
|
||||
build: $(executable) $(classpath-objects)
|
||||
build: $(executable) $(classpath-objects) $(test-classes)
|
||||
|
||||
$(input): $(classpath-objects)
|
||||
|
||||
|
105
src/builtin.cpp
105
src/builtin.cpp
@ -1,6 +1,6 @@
|
||||
#include "machine.h"
|
||||
#include "constants.h"
|
||||
#include "run.h"
|
||||
#include "processor.h"
|
||||
|
||||
#undef JNIEXPORT
|
||||
#define JNIEXPORT __attribute__ ((visibility("default")))
|
||||
@ -33,7 +33,7 @@ search(Thread* t, jstring name, object (*op)(Thread*, object),
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pushReference(t, r);
|
||||
return makeLocalReference(t, r);
|
||||
} else {
|
||||
t->exception = makeNullPointerException(t);
|
||||
return 0;
|
||||
@ -53,7 +53,7 @@ Java_java_lang_Object_toString(Thread* t, jobject this_)
|
||||
&byteArrayBody(t, className(t, objectClass(t, *this_)), 0),
|
||||
hash);
|
||||
|
||||
return pushReference(t, s);
|
||||
return makeLocalReference(t, s);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jclass JNICALL
|
||||
@ -61,7 +61,7 @@ Java_java_lang_Object_getClass(Thread* t, jobject this_)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
return pushReference(t, objectClass(t, *this_));
|
||||
return makeLocalReference(t, objectClass(t, *this_));
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
@ -105,7 +105,7 @@ Java_java_lang_Object_clone(Thread* t, jclass, jobject o)
|
||||
memcpy(reinterpret_cast<void**>(clone) + 1,
|
||||
reinterpret_cast<void**>(*o) + 1,
|
||||
(baseSize(t, *o, objectClass(t, *o)) - 1) * BytesPerWord);
|
||||
return pushReference(t, clone);
|
||||
return makeLocalReference(t, clone);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jclass JNICALL
|
||||
@ -114,11 +114,11 @@ Java_java_lang_ClassLoader_defineClass
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
uint8_t* buffer = static_cast<uint8_t*>(t->vm->system->allocate(length));
|
||||
uint8_t* buffer = static_cast<uint8_t*>(t->m->system->allocate(length));
|
||||
memcpy(buffer, &byteArrayBody(t, *b, offset), length);
|
||||
object c = parseClass(t, buffer, length);
|
||||
t->vm->system->free(buffer);
|
||||
return pushReference(t, c);
|
||||
t->m->system->free(buffer);
|
||||
return makeLocalReference(t, c);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jclass JNICALL
|
||||
@ -147,7 +147,7 @@ Java_java_lang_SystemClassLoader_resourceExists
|
||||
if (LIKELY(name)) {
|
||||
char n[stringLength(t, *name) + 1];
|
||||
stringChars(t, *name, n);
|
||||
return t->vm->finder->exists(n);
|
||||
return t->m->finder->exists(n);
|
||||
} else {
|
||||
t->exception = makeNullPointerException(t);
|
||||
return 0;
|
||||
@ -159,7 +159,7 @@ Java_java_io_ObjectInputStream_makeInstance(Thread* t, jclass, jclass c)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
return pushReference(t, make(t, *c));
|
||||
return makeLocalReference(t, make(t, *c));
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jclass JNICALL
|
||||
@ -169,23 +169,23 @@ Java_java_lang_Class_primitiveClass(Thread* t, jclass, jchar name)
|
||||
|
||||
switch (name) {
|
||||
case 'B':
|
||||
return pushReference(t, arrayBody(t, t->vm->types, Machine::JbyteType));
|
||||
return makeLocalReference(t, arrayBody(t, t->m->types, Machine::JbyteType));
|
||||
case 'C':
|
||||
return pushReference(t, arrayBody(t, t->vm->types, Machine::JcharType));
|
||||
return makeLocalReference(t, arrayBody(t, t->m->types, Machine::JcharType));
|
||||
case 'D':
|
||||
return pushReference(t, arrayBody(t, t->vm->types, Machine::JdoubleType));
|
||||
return makeLocalReference(t, arrayBody(t, t->m->types, Machine::JdoubleType));
|
||||
case 'F':
|
||||
return pushReference(t, arrayBody(t, t->vm->types, Machine::JfloatType));
|
||||
return makeLocalReference(t, arrayBody(t, t->m->types, Machine::JfloatType));
|
||||
case 'I':
|
||||
return pushReference(t, arrayBody(t, t->vm->types, Machine::JintType));
|
||||
return makeLocalReference(t, arrayBody(t, t->m->types, Machine::JintType));
|
||||
case 'J':
|
||||
return pushReference(t, arrayBody(t, t->vm->types, Machine::JlongType));
|
||||
return makeLocalReference(t, arrayBody(t, t->m->types, Machine::JlongType));
|
||||
case 'S':
|
||||
return pushReference(t, arrayBody(t, t->vm->types, Machine::JshortType));
|
||||
return makeLocalReference(t, arrayBody(t, t->m->types, Machine::JshortType));
|
||||
case 'V':
|
||||
return pushReference(t, arrayBody(t, t->vm->types, Machine::JvoidType));
|
||||
return makeLocalReference(t, arrayBody(t, t->m->types, Machine::JvoidType));
|
||||
case 'Z':
|
||||
return pushReference(t, arrayBody(t, t->vm->types, Machine::JbooleanType));
|
||||
return makeLocalReference(t, arrayBody(t, t->m->types, Machine::JbooleanType));
|
||||
default:
|
||||
t->exception = makeIllegalArgumentException(t);
|
||||
return 0;
|
||||
@ -247,7 +247,7 @@ Java_java_lang_reflect_Field_getObject
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
return pushReference(t, cast<object>(*instance, offset));
|
||||
return makeLocalReference(t, cast<object>(*instance, offset));
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
@ -300,7 +300,7 @@ Java_java_lang_reflect_Constructor_make(Thread* t, jclass, jclass c)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
return pushReference(t, make(t, *c));
|
||||
return makeLocalReference(t, make(t, *c));
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jobject JNICALL
|
||||
@ -308,8 +308,11 @@ Java_java_lang_reflect_Method_getCaller(Thread* t, jclass)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
return pushReference
|
||||
(t, frameMethod(t, frameNext(t, frameNext(t, t->frame))));
|
||||
FrameIterator it; t->m->processor->start(t, &it);
|
||||
t->m->processor->next(t, &it);
|
||||
t->m->processor->next(t, &it);
|
||||
|
||||
return makeLocalReference(t, it.method);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jobject JNICALL
|
||||
@ -318,11 +321,12 @@ Java_java_lang_reflect_Method_invoke
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
object v = run2(t, *method, (instance ? *instance : 0), *arguments);
|
||||
object v = t->m->processor->invoke
|
||||
(t, *method, (instance ? *instance : 0), *arguments);
|
||||
if (t->exception) {
|
||||
t->exception = makeInvocationTargetException(t, t->exception);
|
||||
}
|
||||
return pushReference(t, v);
|
||||
return makeLocalReference(t, v);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
@ -351,7 +355,7 @@ Java_java_lang_reflect_Array_makeObjectArray
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
return pushReference(t, makeObjectArray(t, *elementType, length, true));
|
||||
return makeLocalReference(t, makeObjectArray(t, *elementType, length, true));
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
@ -387,7 +391,7 @@ Java_java_lang_String_intern(Thread* t, jobject this_)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
return pushReference(t, intern(t, *this_));
|
||||
return makeLocalReference(t, intern(t, *this_));
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jstring JNICALL
|
||||
@ -401,7 +405,7 @@ Java_java_lang_System_getVMProperty(Thread* t, jclass, jint code)
|
||||
|
||||
switch (code) {
|
||||
case JavaClassPath:
|
||||
return pushReference(t, makeString(t, "%s", t->vm->finder->path()));
|
||||
return makeLocalReference(t, makeString(t, "%s", t->m->finder->path()));
|
||||
|
||||
default:
|
||||
t->exception = makeRuntimeException(t, 0);
|
||||
@ -469,12 +473,12 @@ extern "C" JNIEXPORT void JNICALL
|
||||
Java_java_lang_Runtime_load(Thread* t, jclass, jstring name, jboolean mapName)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
ACQUIRE(t, t->vm->classLock);
|
||||
ACQUIRE(t, t->m->classLock);
|
||||
|
||||
char n[stringLength(t, *name) + 1];
|
||||
stringChars(t, *name, n);
|
||||
|
||||
for (System::Library* lib = t->vm->libraries; lib; lib = lib->next())
|
||||
for (System::Library* lib = t->m->libraries; lib; lib = lib->next())
|
||||
{
|
||||
if (lib->name()
|
||||
and strcmp(lib->name(), n) == 0
|
||||
@ -486,10 +490,10 @@ Java_java_lang_Runtime_load(Thread* t, jclass, jstring name, jboolean mapName)
|
||||
}
|
||||
|
||||
System::Library* lib;
|
||||
if (LIKELY(t->vm->system->success
|
||||
(t->vm->system->load(&lib, n, mapName, t->vm->libraries))))
|
||||
if (LIKELY(t->m->system->success
|
||||
(t->m->system->load(&lib, n, mapName, t->m->libraries))))
|
||||
{
|
||||
t->vm->libraries = lib;
|
||||
t->m->libraries = lib;
|
||||
} else {
|
||||
object message = makeString(t, "library not found: %s", n);
|
||||
t->exception = makeUnsatisfiedLinkError(t, message);
|
||||
@ -510,7 +514,7 @@ Java_java_lang_Runtime_exit(Thread* t, jobject, jint code)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
t->vm->system->exit(code);
|
||||
t->m->system->exit(code);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
@ -525,24 +529,25 @@ Java_java_lang_Throwable_trace(Thread* t, jclass, jint skipCount)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
int frame = t->frame;
|
||||
while (skipCount-- and frame >= 0) {
|
||||
frame = frameNext(t, frame);
|
||||
FrameIterator it; t->m->processor->start(t, &it);
|
||||
|
||||
while (skipCount-- and it.valid()) {
|
||||
t->m->processor->next(t, &it);
|
||||
}
|
||||
|
||||
// skip Throwable constructors
|
||||
while (frame >= 0
|
||||
while (it.valid()
|
||||
and isAssignableFrom
|
||||
(t, arrayBody(t, t->vm->types, Machine::ThrowableType),
|
||||
methodClass(t, frameMethod(t, frame)))
|
||||
(t, arrayBody(t, t->m->types, Machine::ThrowableType),
|
||||
methodClass(t, it.method))
|
||||
and strcmp(reinterpret_cast<const int8_t*>("<init>"),
|
||||
&byteArrayBody(t, methodName(t, frameMethod(t, frame)), 0))
|
||||
&byteArrayBody(t, methodName(t, it.method), 0))
|
||||
== 0)
|
||||
{
|
||||
frame = frameNext(t, frame);
|
||||
t->m->processor->next(t, &it);
|
||||
}
|
||||
|
||||
return pushReference(t, makeTrace(t, frame));
|
||||
return makeLocalReference(t, makeTrace(t, &it));
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jarray JNICALL
|
||||
@ -552,7 +557,7 @@ Java_java_lang_Throwable_resolveTrace(Thread* t, jclass, jobject trace)
|
||||
|
||||
unsigned length = arrayLength(t, *trace);
|
||||
object array = makeObjectArray
|
||||
(t, arrayBody(t, t->vm->types, Machine::StackTraceElementType),
|
||||
(t, arrayBody(t, t->m->types, Machine::StackTraceElementType),
|
||||
length, true);
|
||||
PROTECT(t, array);
|
||||
|
||||
@ -578,7 +583,7 @@ Java_java_lang_Throwable_resolveTrace(Thread* t, jclass, jobject trace)
|
||||
set(t, objectArrayBody(t, array, i), ste);
|
||||
}
|
||||
|
||||
return pushReference(t, array);
|
||||
return makeLocalReference(t, array);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jobject JNICALL
|
||||
@ -586,7 +591,7 @@ Java_java_lang_Thread_currentThread(Thread* t, jclass)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
return pushReference(t, t->javaThread);
|
||||
return makeLocalReference(t, t->javaThread);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
@ -594,12 +599,12 @@ Java_java_lang_Thread_doStart(Thread* t, jobject this_)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
Thread* p = new (t->vm->system->allocate(sizeof(Thread)))
|
||||
Thread(t->vm, *this_, t);
|
||||
Thread* p = new (t->m->system->allocate(sizeof(Thread)))
|
||||
Thread(t->m, *this_, t);
|
||||
|
||||
enter(p, Thread::ActiveState);
|
||||
|
||||
if (t->vm->system->success(t->vm->system->start(&(p->runnable)))) {
|
||||
if (t->m->system->success(t->m->system->start(&(p->runnable)))) {
|
||||
return reinterpret_cast<jlong>(p);
|
||||
} else {
|
||||
p->exit();
|
||||
@ -623,7 +628,7 @@ Java_java_net_URL_00024ResourceInputStream_open
|
||||
char p[stringLength(t, *path) + 1];
|
||||
stringChars(t, *path, p);
|
||||
|
||||
return reinterpret_cast<jlong>(t->vm->finder->find(p));
|
||||
return reinterpret_cast<jlong>(t->m->finder->find(p));
|
||||
} else {
|
||||
t->exception = makeNullPointerException(t);
|
||||
return 0;
|
||||
|
@ -176,6 +176,13 @@ hash(const uint16_t* s, unsigned length)
|
||||
return h;
|
||||
}
|
||||
|
||||
class Machine;
|
||||
class Thread;
|
||||
|
||||
struct Object { };
|
||||
|
||||
typedef Object* object;
|
||||
|
||||
} // namespace vm
|
||||
|
||||
#endif//COMMON_H
|
||||
|
281
src/compile.cpp
Normal file
281
src/compile.cpp
Normal file
@ -0,0 +1,281 @@
|
||||
#include "common.h"
|
||||
#include "system.h"
|
||||
#include "constants.h"
|
||||
#include "machine.h"
|
||||
|
||||
using namespace vm;
|
||||
|
||||
namespace {
|
||||
|
||||
class Rope {
|
||||
public:
|
||||
class Node {
|
||||
public:
|
||||
static const unsigned Size = 32;
|
||||
|
||||
Node():
|
||||
next(0)
|
||||
{ }
|
||||
|
||||
Node* next;
|
||||
uint8_t data[Size];
|
||||
};
|
||||
|
||||
Rope(System* s):
|
||||
s(s),
|
||||
front(0),
|
||||
rear(0),
|
||||
count(0),
|
||||
position(Node::Size)
|
||||
{ }
|
||||
|
||||
void append(uint8_t v) {
|
||||
if (position == Node::Size) {
|
||||
Node* n = new (s->allocate(sizeof(Node))) Node;
|
||||
if (front == 0) {
|
||||
front = rear = n;
|
||||
} else {
|
||||
rear->next = n;
|
||||
rear = n;
|
||||
}
|
||||
position = 0;
|
||||
++ count;
|
||||
}
|
||||
|
||||
rear->data[position++] = v;
|
||||
}
|
||||
|
||||
unsigned length() {
|
||||
return (count * Node::Size) + position;
|
||||
}
|
||||
|
||||
void copyTo(uint8_t* b) {
|
||||
if (front) {
|
||||
Node* n = front;
|
||||
while (true) {
|
||||
if (n == rear) {
|
||||
memcpy(b, n->data, position);
|
||||
break;
|
||||
} else {
|
||||
memcpy(b, n->data, Node::Size);
|
||||
b += Node::Size;
|
||||
n = n->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System* s;
|
||||
Node* front;
|
||||
Node* rear;
|
||||
unsigned count;
|
||||
unsigned position;
|
||||
};
|
||||
|
||||
class Assembler {
|
||||
public:
|
||||
Assembler(System* s):
|
||||
rope(s)
|
||||
{ }
|
||||
|
||||
Rope rope;
|
||||
};
|
||||
|
||||
class Compiler: private Assembler {
|
||||
public:
|
||||
Compiler(System* s):
|
||||
Assembler(s)
|
||||
{ }
|
||||
|
||||
void compile(Thread* t, object method) {
|
||||
push(ebp);
|
||||
mov(esp, ebp);
|
||||
|
||||
object code = methodCode(t, method);
|
||||
|
||||
// reserve space for local variables
|
||||
sub(codeMaxLocals(t, code), esp);
|
||||
|
||||
for (unsigned i = 0; i < codeLength(t, code);) {
|
||||
switch (codeBody(t, code, i++)) {
|
||||
case iadd:
|
||||
pop(eax);
|
||||
pop(edx);
|
||||
add(eax, edx);
|
||||
push(edx);
|
||||
break;
|
||||
|
||||
case iconst_m1:
|
||||
push(-1);
|
||||
break;
|
||||
|
||||
case iconst_0:
|
||||
push(0);
|
||||
break;
|
||||
|
||||
case iconst_1:
|
||||
push(1);
|
||||
break;
|
||||
|
||||
case iconst_2:
|
||||
push(2);
|
||||
break;
|
||||
|
||||
case iconst_3:
|
||||
push(3);
|
||||
break;
|
||||
|
||||
case iconst_4:
|
||||
push(4);
|
||||
break;
|
||||
|
||||
case iconst_5:
|
||||
push(5);
|
||||
break;
|
||||
|
||||
case iload_0:
|
||||
case fload_0:
|
||||
mov(ebp, 0, eax);
|
||||
push(eax);
|
||||
break;
|
||||
|
||||
case iload_1:
|
||||
case fload_1:
|
||||
mov(ebp, -1, eax);
|
||||
push(eax);
|
||||
break;
|
||||
|
||||
case iload_2:
|
||||
case fload_2:
|
||||
mov(ebp, -2, eax);
|
||||
push(eax);
|
||||
break;
|
||||
|
||||
case iload_3:
|
||||
case fload_3:
|
||||
mov(ebp, -3, eax);
|
||||
push(eax);
|
||||
break;
|
||||
|
||||
case istore_0:
|
||||
case fstore_0:
|
||||
pop(eax);
|
||||
mov(eax, ebp, 0);
|
||||
break;
|
||||
|
||||
case istore_1:
|
||||
case fstore_1:
|
||||
pop(eax);
|
||||
mov(eax, ebp, -1);
|
||||
break;
|
||||
|
||||
case istore_2:
|
||||
case fstore_2:
|
||||
pop(eax);
|
||||
mov(eax, ebp, -2);
|
||||
break;
|
||||
|
||||
case istore_3:
|
||||
case fstore_3:
|
||||
pop(eax);
|
||||
mov(eax, ebp, -3);
|
||||
break;
|
||||
|
||||
case return_:
|
||||
mov(ebp, esp);
|
||||
pop(ebp);
|
||||
ret();
|
||||
break;
|
||||
|
||||
default:
|
||||
abort(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
object
|
||||
compile(Thread* t, object method)
|
||||
{
|
||||
Compiler c(t->vm->system);
|
||||
c.compile(t, method);
|
||||
|
||||
object r = makeByteArray(t, c.rope.length(), false);
|
||||
c.rope.copyTo(&byteArrayBody(t, r, 0));
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
class MyInvoker: public Invoker {
|
||||
public:
|
||||
MyInvoker(System* s):
|
||||
s(s)
|
||||
{ }
|
||||
|
||||
virtual object
|
||||
invokeArray(Thread* t, object method, object this_, object arguments)
|
||||
{
|
||||
assert(t, t->state == Thread::ActiveState
|
||||
or t->state == Thread::ExclusiveState);
|
||||
|
||||
assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0));
|
||||
|
||||
uintptr_t a[methodParameterCount(t, method) * 2];
|
||||
ArgumentArray array(t, a, method, this_, spec, arguments);
|
||||
|
||||
return invoke(t, method, &array);
|
||||
}
|
||||
|
||||
virtual object
|
||||
invokeList(Thread* t, object method, object this_, bool indirectObjects,
|
||||
va_list arguments)
|
||||
{
|
||||
assert(t, t->state == Thread::ActiveState
|
||||
or t->state == Thread::ExclusiveState);
|
||||
|
||||
assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0));
|
||||
|
||||
uintptr_t a[methodParameterCount(t, method) * 2];
|
||||
ArgumentArray array(t, a, method, this_, spec, indirectObjects, arguments);
|
||||
|
||||
return invoke(t, method, &array);
|
||||
}
|
||||
|
||||
virtual object
|
||||
invokeList(Thread* t, const char* className, const char* methodName,
|
||||
const char* methodSpec, object this_, va_list arguments)
|
||||
{
|
||||
assert(t, t->state == Thread::ActiveState
|
||||
or t->state == Thread::ExclusiveState);
|
||||
|
||||
uintptr_t a[methodParameterCount(t, method) * 2];
|
||||
ArgumentArray array(t, a, method, this_, methodSpec, false, arguments);
|
||||
|
||||
object method = resolveMethod(t, className, methodName, methodSpec);
|
||||
if (LIKELY(t->exception == 0)) {
|
||||
assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0));
|
||||
|
||||
return invoke(t, method, &array);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void dispose() {
|
||||
s->free(this);
|
||||
}
|
||||
|
||||
System* s;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace vm {
|
||||
|
||||
Invoker*
|
||||
makeInvoker(System* system)
|
||||
{
|
||||
return new (system->allocate(sizeof(MyInvoker))) MyInvoker(system);
|
||||
}
|
||||
|
||||
} // namespace vm
|
@ -1,16 +1,327 @@
|
||||
#include "common.h"
|
||||
#include "system.h"
|
||||
#include "heap.h"
|
||||
#include "finder.h"
|
||||
#include "constants.h"
|
||||
#include "run.h"
|
||||
#include "jnienv.h"
|
||||
#include "machine.h"
|
||||
#include "processor.h"
|
||||
|
||||
using namespace vm;
|
||||
|
||||
namespace {
|
||||
|
||||
class Thread: public vm::Thread {
|
||||
public:
|
||||
static const unsigned StackSizeInBytes = 64 * 1024;
|
||||
static const unsigned StackSizeInWords = StackSizeInBytes / BytesPerWord;
|
||||
|
||||
Thread(Machine* m, object javaThread, vm::Thread* parent):
|
||||
vm::Thread(m, javaThread, parent),
|
||||
ip(0),
|
||||
sp(0),
|
||||
frame(-1),
|
||||
code(0)
|
||||
{ }
|
||||
|
||||
unsigned ip;
|
||||
unsigned sp;
|
||||
int frame;
|
||||
object code;
|
||||
uintptr_t stack[StackSizeInWords];
|
||||
};
|
||||
|
||||
class MyProcessor: public Processor {
|
||||
public:
|
||||
MyProcessor(System* s):
|
||||
s(s)
|
||||
{ }
|
||||
|
||||
virtual vm::Thread*
|
||||
makeThread(Machine* m, object javaThread, vm::Thread* parent)
|
||||
{
|
||||
return new (s->allocate(sizeof(Thread))) Thread(m, javaThread, parent);
|
||||
}
|
||||
|
||||
virtual void
|
||||
visitObjects(vm::Thread* t, Heap::Visitor* v);
|
||||
|
||||
virtual void
|
||||
start(vm::Thread* t, FrameIterator* it);
|
||||
|
||||
virtual void
|
||||
next(vm::Thread* t, FrameIterator* it);
|
||||
|
||||
virtual object
|
||||
invokeArray(vm::Thread* t, object method, object this_, object arguments);
|
||||
|
||||
virtual object
|
||||
invokeList(vm::Thread* t, object method, object this_, bool indirectObjects,
|
||||
va_list arguments);
|
||||
|
||||
virtual object
|
||||
invokeList(vm::Thread* t, const char* className, const char* methodName,
|
||||
const char* methodSpec, object this_, va_list arguments);
|
||||
|
||||
virtual void dispose() {
|
||||
s->free(this);
|
||||
}
|
||||
|
||||
System* s;
|
||||
};
|
||||
|
||||
inline void
|
||||
pushObject(Thread* t, object o)
|
||||
{
|
||||
if (DebugStack) {
|
||||
fprintf(stderr, "push object %p at %d\n", o, t->sp);
|
||||
}
|
||||
|
||||
assert(t, t->sp + 1 < Thread::StackSizeInWords / 2);
|
||||
t->stack[(t->sp * 2) ] = ObjectTag;
|
||||
t->stack[(t->sp * 2) + 1] = reinterpret_cast<uintptr_t>(o);
|
||||
++ t->sp;
|
||||
}
|
||||
|
||||
inline void
|
||||
pushInt(Thread* t, uint32_t v)
|
||||
{
|
||||
if (DebugStack) {
|
||||
fprintf(stderr, "push int %d at %d\n", v, t->sp);
|
||||
}
|
||||
|
||||
assert(t, t->sp + 1 < Thread::StackSizeInWords / 2);
|
||||
t->stack[(t->sp * 2) ] = IntTag;
|
||||
t->stack[(t->sp * 2) + 1] = v;
|
||||
++ t->sp;
|
||||
}
|
||||
|
||||
inline void
|
||||
pushFloat(Thread* t, float v)
|
||||
{
|
||||
uint32_t a; memcpy(&a, &v, sizeof(uint32_t));
|
||||
pushInt(t, a);
|
||||
}
|
||||
|
||||
inline void
|
||||
pushLong(Thread* t, uint64_t v)
|
||||
{
|
||||
if (DebugStack) {
|
||||
fprintf(stderr, "push long %"LLD" at %d\n", v, t->sp);
|
||||
}
|
||||
|
||||
pushInt(t, v >> 32);
|
||||
pushInt(t, v & 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
inline void
|
||||
pushDouble(Thread* t, double v)
|
||||
{
|
||||
uint64_t a; memcpy(&a, &v, sizeof(uint64_t));
|
||||
pushLong(t, a);
|
||||
}
|
||||
|
||||
inline object
|
||||
popObject(Thread* t)
|
||||
{
|
||||
if (DebugStack) {
|
||||
fprintf(stderr, "pop object %p at %d\n",
|
||||
reinterpret_cast<object>(t->stack[((t->sp - 1) * 2) + 1]),
|
||||
t->sp - 1);
|
||||
}
|
||||
|
||||
assert(t, t->stack[(t->sp - 1) * 2] == ObjectTag);
|
||||
return reinterpret_cast<object>(t->stack[((-- t->sp) * 2) + 1]);
|
||||
}
|
||||
|
||||
inline uint32_t
|
||||
popInt(Thread* t)
|
||||
{
|
||||
if (DebugStack) {
|
||||
fprintf(stderr, "pop int %"ULD" at %d\n",
|
||||
t->stack[((t->sp - 1) * 2) + 1],
|
||||
t->sp - 1);
|
||||
}
|
||||
|
||||
assert(t, t->stack[(t->sp - 1) * 2] == IntTag);
|
||||
return t->stack[((-- t->sp) * 2) + 1];
|
||||
}
|
||||
|
||||
inline float
|
||||
popFloat(Thread* t)
|
||||
{
|
||||
uint32_t a = popInt(t);
|
||||
float f; memcpy(&f, &a, sizeof(float));
|
||||
return f;
|
||||
}
|
||||
|
||||
inline uint64_t
|
||||
popLong(Thread* t)
|
||||
{
|
||||
if (DebugStack) {
|
||||
fprintf(stderr, "pop long %"LLD" at %d\n",
|
||||
(static_cast<uint64_t>(t->stack[((t->sp - 2) * 2) + 1]) << 32)
|
||||
| static_cast<uint64_t>(t->stack[((t->sp - 1) * 2) + 1]),
|
||||
t->sp - 2);
|
||||
}
|
||||
|
||||
uint64_t a = popInt(t);
|
||||
uint64_t b = popInt(t);
|
||||
return (b << 32) | a;
|
||||
}
|
||||
|
||||
inline float
|
||||
popDouble(Thread* t)
|
||||
{
|
||||
uint64_t a = popLong(t);
|
||||
double d; memcpy(&d, &a, sizeof(double));
|
||||
return d;
|
||||
}
|
||||
|
||||
inline object
|
||||
peekObject(Thread* t, unsigned index)
|
||||
{
|
||||
if (DebugStack) {
|
||||
fprintf(stderr, "peek object %p at %d\n",
|
||||
reinterpret_cast<object>(t->stack[(index * 2) + 1]),
|
||||
index);
|
||||
}
|
||||
|
||||
assert(t, index < Thread::StackSizeInWords / 2);
|
||||
assert(t, t->stack[index * 2] == ObjectTag);
|
||||
return *reinterpret_cast<object*>(t->stack + (index * 2) + 1);
|
||||
}
|
||||
|
||||
inline uint32_t
|
||||
peekInt(Thread* t, unsigned index)
|
||||
{
|
||||
if (DebugStack) {
|
||||
fprintf(stderr, "peek int %"ULD" at %d\n",
|
||||
t->stack[(index * 2) + 1],
|
||||
index);
|
||||
}
|
||||
|
||||
assert(t, index < Thread::StackSizeInWords / 2);
|
||||
assert(t, t->stack[index * 2] == IntTag);
|
||||
return t->stack[(index * 2) + 1];
|
||||
}
|
||||
|
||||
inline uint64_t
|
||||
peekLong(Thread* t, unsigned index)
|
||||
{
|
||||
if (DebugStack) {
|
||||
fprintf(stderr, "peek long %"LLD" at %d\n",
|
||||
(static_cast<uint64_t>(t->stack[(index * 2) + 1]) << 32)
|
||||
| static_cast<uint64_t>(t->stack[((index + 1) * 2) + 1]),
|
||||
index);
|
||||
}
|
||||
|
||||
return (static_cast<uint64_t>(peekInt(t, index)) << 32)
|
||||
| static_cast<uint64_t>(peekInt(t, index + 1));
|
||||
}
|
||||
|
||||
inline void
|
||||
pokeObject(Thread* t, unsigned index, object value)
|
||||
{
|
||||
if (DebugStack) {
|
||||
fprintf(stderr, "poke object %p at %d\n", value, index);
|
||||
}
|
||||
|
||||
t->stack[index * 2] = ObjectTag;
|
||||
t->stack[(index * 2) + 1] = reinterpret_cast<uintptr_t>(value);
|
||||
}
|
||||
|
||||
inline void
|
||||
pokeInt(Thread* t, unsigned index, uint32_t value)
|
||||
{
|
||||
if (DebugStack) {
|
||||
fprintf(stderr, "poke int %d at %d\n", value, index);
|
||||
}
|
||||
|
||||
t->stack[index * 2] = IntTag;
|
||||
t->stack[(index * 2) + 1] = value;
|
||||
}
|
||||
|
||||
inline void
|
||||
pokeLong(Thread* t, unsigned index, uint64_t value)
|
||||
{
|
||||
if (DebugStack) {
|
||||
fprintf(stderr, "poke long %"LLD" at %d\n", value, index);
|
||||
}
|
||||
|
||||
pokeInt(t, index, value >> 32);
|
||||
pokeInt(t, index + 1, value & 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
inline object*
|
||||
pushReference(Thread* t, object o)
|
||||
{
|
||||
if (o) {
|
||||
expect(t, t->sp + 1 < Thread::StackSizeInWords / 2);
|
||||
pushObject(t, o);
|
||||
return reinterpret_cast<object*>(t->stack + ((t->sp - 1) * 2) + 1);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline int
|
||||
frameNext(Thread* t, int frame)
|
||||
{
|
||||
return peekInt(t, frame + FrameNextOffset);
|
||||
}
|
||||
|
||||
inline object
|
||||
frameMethod(Thread* t, int frame)
|
||||
{
|
||||
return peekObject(t, frame + FrameMethodOffset);
|
||||
}
|
||||
|
||||
inline unsigned
|
||||
frameIp(Thread* t, int frame)
|
||||
{
|
||||
return peekInt(t, frame + FrameIpOffset);
|
||||
}
|
||||
|
||||
inline unsigned
|
||||
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);
|
||||
}
|
||||
|
||||
void
|
||||
pushFrame(Thread* t, object method)
|
||||
{
|
||||
@ -69,7 +380,7 @@ popFrame(Thread* t)
|
||||
t->exception = makeExceptionInInitializerError(t, t->exception);
|
||||
}
|
||||
classVmFlags(t, methodClass(t, method)) &= ~(NeedInitFlag | InitFlag);
|
||||
release(t, t->vm->classLock);
|
||||
release(t, t->m->classLock);
|
||||
}
|
||||
|
||||
t->sp = frameBase(t, t->frame);
|
||||
@ -128,7 +439,7 @@ inline object
|
||||
resolveClass(Thread* t, object pool, unsigned index)
|
||||
{
|
||||
object o = arrayBody(t, pool, index);
|
||||
if (objectClass(t, o) == arrayBody(t, t->vm->types, Machine::ByteArrayType))
|
||||
if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ByteArrayType))
|
||||
{
|
||||
PROTECT(t, pool);
|
||||
|
||||
@ -141,10 +452,11 @@ resolveClass(Thread* t, object pool, unsigned index)
|
||||
}
|
||||
|
||||
inline object
|
||||
resolveClass(Thread* t, object container, object& (*class_)(Thread*, object))
|
||||
resolveClass(Thread* t, object container,
|
||||
object& (*class_)(vm::Thread*, object))
|
||||
{
|
||||
object o = class_(t, container);
|
||||
if (objectClass(t, o) == arrayBody(t, t->vm->types, Machine::ByteArrayType))
|
||||
if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ByteArrayType))
|
||||
{
|
||||
PROTECT(t, container);
|
||||
|
||||
@ -158,11 +470,11 @@ resolveClass(Thread* t, object container, object& (*class_)(Thread*, object))
|
||||
|
||||
inline object
|
||||
resolve(Thread* t, object pool, unsigned index,
|
||||
object (*find)(Thread*, object, object, object),
|
||||
object (*makeError)(Thread*, object))
|
||||
object (*find)(vm::Thread*, object, object, object),
|
||||
object (*makeError)(vm::Thread*, object))
|
||||
{
|
||||
object o = arrayBody(t, pool, index);
|
||||
if (objectClass(t, o) == arrayBody(t, t->vm->types, Machine::ReferenceType))
|
||||
if (objectClass(t, o) == arrayBody(t, t->m->types, Machine::ReferenceType))
|
||||
{
|
||||
PROTECT(t, pool);
|
||||
|
||||
@ -264,10 +576,10 @@ inline object
|
||||
resolveNativeMethodData(Thread* t, object method)
|
||||
{
|
||||
if (objectClass(t, methodCode(t, method))
|
||||
== arrayBody(t, t->vm->types, Machine::ByteArrayType))
|
||||
== arrayBody(t, t->m->types, Machine::ByteArrayType))
|
||||
{
|
||||
object data = 0;
|
||||
for (System::Library* lib = t->vm->libraries; lib; lib = lib->next()) {
|
||||
for (System::Library* lib = t->m->libraries; lib; lib = lib->next()) {
|
||||
void* p = lib->resolve(reinterpret_cast<const char*>
|
||||
(&byteArrayBody(t, methodCode(t, method), 0)));
|
||||
if (p) {
|
||||
@ -383,7 +695,7 @@ invokeNative(Thread* t, object method)
|
||||
|
||||
{ ENTER(t, Thread::IdleState);
|
||||
|
||||
result = t->vm->system->call
|
||||
result = t->m->system->call
|
||||
(function,
|
||||
args,
|
||||
&nativeMethodDataParameterTypes(t, data, 0),
|
||||
@ -451,7 +763,7 @@ bool
|
||||
classInit2(Thread* t, object class_, unsigned ipOffset)
|
||||
{
|
||||
PROTECT(t, class_);
|
||||
acquire(t, t->vm->classLock);
|
||||
acquire(t, t->m->classLock);
|
||||
if (classVmFlags(t, class_) & NeedInitFlag
|
||||
and (classVmFlags(t, class_) & InitFlag) == 0)
|
||||
{
|
||||
@ -460,7 +772,7 @@ classInit2(Thread* t, object class_, unsigned ipOffset)
|
||||
t->ip -= ipOffset;
|
||||
return true;
|
||||
} else {
|
||||
release(t, t->vm->classLock);
|
||||
release(t, t->m->classLock);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -533,7 +845,7 @@ populateMultiArray(Thread* t, object array, int32_t* counts,
|
||||
}
|
||||
|
||||
object
|
||||
run(Thread* t)
|
||||
interpret(Thread* t)
|
||||
{
|
||||
const int base = t->frame;
|
||||
|
||||
@ -717,7 +1029,7 @@ run(Thread* t)
|
||||
|
||||
if (LIKELY(array)) {
|
||||
if (objectClass(t, array)
|
||||
== arrayBody(t, t->vm->types, Machine::BooleanArrayType))
|
||||
== arrayBody(t, t->m->types, Machine::BooleanArrayType))
|
||||
{
|
||||
if (LIKELY(index >= 0 and
|
||||
static_cast<uintptr_t>(index)
|
||||
@ -756,7 +1068,7 @@ run(Thread* t)
|
||||
|
||||
if (LIKELY(array)) {
|
||||
if (objectClass(t, array)
|
||||
== arrayBody(t, t->vm->types, Machine::BooleanArrayType))
|
||||
== arrayBody(t, t->m->types, Machine::BooleanArrayType))
|
||||
{
|
||||
if (LIKELY(index >= 0 and
|
||||
static_cast<uintptr_t>(index)
|
||||
@ -1890,14 +2202,14 @@ run(Thread* t)
|
||||
|
||||
object v = arrayBody(t, codePool(t, code), index - 1);
|
||||
|
||||
if (objectClass(t, v) == arrayBody(t, t->vm->types, Machine::IntType)) {
|
||||
if (objectClass(t, v) == arrayBody(t, t->m->types, Machine::IntType)) {
|
||||
pushInt(t, intValue(t, v));
|
||||
} else if (objectClass(t, v)
|
||||
== arrayBody(t, t->vm->types, Machine::FloatType))
|
||||
== arrayBody(t, t->m->types, Machine::FloatType))
|
||||
{
|
||||
pushInt(t, floatValue(t, v));
|
||||
} else if (objectClass(t, v)
|
||||
== arrayBody(t, t->vm->types, Machine::StringType))
|
||||
== arrayBody(t, t->m->types, Machine::StringType))
|
||||
{
|
||||
pushObject(t, v);
|
||||
} else {
|
||||
@ -1914,10 +2226,10 @@ run(Thread* t)
|
||||
|
||||
object v = arrayBody(t, codePool(t, code), ((index1 << 8) | index2) - 1);
|
||||
|
||||
if (objectClass(t, v) == arrayBody(t, t->vm->types, Machine::LongType)) {
|
||||
if (objectClass(t, v) == arrayBody(t, t->m->types, Machine::LongType)) {
|
||||
pushLong(t, longValue(t, v));
|
||||
} else if (objectClass(t, v)
|
||||
== arrayBody(t, t->vm->types, Machine::DoubleType))
|
||||
== arrayBody(t, t->m->types, Machine::DoubleType))
|
||||
{
|
||||
pushLong(t, doubleValue(t, v));
|
||||
} else {
|
||||
@ -2506,24 +2818,6 @@ run(Thread* t)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
run(Thread* t, const char* className, int argc, const char** argv)
|
||||
{
|
||||
enter(t, Thread::ActiveState);
|
||||
|
||||
object args = makeObjectArray
|
||||
(t, arrayBody(t, t->vm->types, Machine::StringType), argc, true);
|
||||
|
||||
PROTECT(t, args);
|
||||
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
object arg = makeString(t, "%s", argv[i]);
|
||||
set(t, objectArrayBody(t, args, i), arg);
|
||||
}
|
||||
|
||||
run(t, className, "main", "([Ljava/lang/String;)V", 0, args);
|
||||
}
|
||||
|
||||
void
|
||||
pushArguments(Thread* t, object this_, const char* spec, bool indirectObjects,
|
||||
va_list a)
|
||||
@ -2704,7 +2998,7 @@ invoke(Thread* t, object method)
|
||||
checkStack(t, method);
|
||||
if (LIKELY(t->exception == 0)) {
|
||||
pushFrame(t, method);
|
||||
result = ::run(t);
|
||||
result = interpret(t);
|
||||
if (LIKELY(t->exception == 0)) {
|
||||
popFrame(t);
|
||||
}
|
||||
@ -2745,48 +3039,55 @@ invoke(Thread* t, object method)
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace vm {
|
||||
|
||||
object
|
||||
runv(Thread* t, object method, object this_, bool indirectObjects, va_list a)
|
||||
void
|
||||
MyProcessor::visitObjects(vm::Thread* vmt, Heap::Visitor* v)
|
||||
{
|
||||
assert(t, t->state == Thread::ActiveState
|
||||
or t->state == Thread::ExclusiveState);
|
||||
Thread* t = static_cast<Thread*>(vmt);
|
||||
|
||||
assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0));
|
||||
v->visit(&(t->code));
|
||||
|
||||
if (UNLIKELY(t->sp + methodParameterFootprint(t, method) + 1
|
||||
> Thread::StackSizeInWords / 2))
|
||||
{
|
||||
t->exception = makeStackOverflowError(t);
|
||||
return 0;
|
||||
for (unsigned i = 0; i < t->sp; ++i) {
|
||||
if (t->stack[i * 2] == ObjectTag) {
|
||||
v->visit(t->stack + (i * 2) + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char* spec = reinterpret_cast<char*>
|
||||
(&byteArrayBody(t, methodSpec(t, method), 0));
|
||||
pushArguments(t, this_, spec, indirectObjects, a);
|
||||
void
|
||||
MyProcessor::start(vm::Thread* vmt, FrameIterator* it)
|
||||
{
|
||||
Thread* t = static_cast<Thread*>(vmt);
|
||||
|
||||
return invoke(t, method);
|
||||
int f = t->frame;
|
||||
it->base = f + 1;
|
||||
if (it->valid()) {
|
||||
pokeInt(t, t->frame + FrameIpOffset, t->ip);
|
||||
it->method = frameMethod(t, f);
|
||||
it->ip = frameIp(t, f);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MyProcessor::next(vm::Thread* vmt, FrameIterator* it)
|
||||
{
|
||||
Thread* t = static_cast<Thread*>(vmt);
|
||||
|
||||
if (it->valid()) {
|
||||
int f = frameNext(t, it->base - 1);
|
||||
it->base = f + 1;
|
||||
if (it->valid()) {
|
||||
it->method = frameMethod(t, f);
|
||||
it->ip = frameIp(t, f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object
|
||||
run(Thread* t, object method, object this_, ...)
|
||||
MyProcessor::invokeArray(vm::Thread* vmt, object method, object this_,
|
||||
object arguments)
|
||||
{
|
||||
va_list a;
|
||||
va_start(a, this_);
|
||||
Thread* t = static_cast<Thread*>(vmt);
|
||||
|
||||
object r = runv(t, method, this_, false, a);
|
||||
|
||||
va_end(a);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
object
|
||||
run2(Thread* t, object method, object this_, object arguments)
|
||||
{
|
||||
assert(t, t->state == Thread::ActiveState
|
||||
or t->state == Thread::ExclusiveState);
|
||||
|
||||
@ -2803,13 +3104,41 @@ run2(Thread* t, object method, object this_, object arguments)
|
||||
(&byteArrayBody(t, methodSpec(t, method), 0));
|
||||
pushArguments(t, this_, spec, arguments);
|
||||
|
||||
return invoke(t, method);
|
||||
return ::invoke(t, method);
|
||||
}
|
||||
|
||||
object
|
||||
run(Thread* t, const char* className, const char* methodName,
|
||||
const char* methodSpec, object this_, ...)
|
||||
MyProcessor::invokeList(vm::Thread* vmt, object method, object this_,
|
||||
bool indirectObjects, va_list arguments)
|
||||
{
|
||||
Thread* t = static_cast<Thread*>(vmt);
|
||||
|
||||
assert(t, t->state == Thread::ActiveState
|
||||
or t->state == Thread::ExclusiveState);
|
||||
|
||||
assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0));
|
||||
|
||||
if (UNLIKELY(t->sp + methodParameterFootprint(t, method) + 1
|
||||
> Thread::StackSizeInWords / 2))
|
||||
{
|
||||
t->exception = makeStackOverflowError(t);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* spec = reinterpret_cast<char*>
|
||||
(&byteArrayBody(t, methodSpec(t, method), 0));
|
||||
pushArguments(t, this_, spec, indirectObjects, arguments);
|
||||
|
||||
return ::invoke(t, method);
|
||||
}
|
||||
|
||||
object
|
||||
MyProcessor::invokeList(vm::Thread* vmt, const char* className,
|
||||
const char* methodName, const char* methodSpec,
|
||||
object this_, va_list arguments)
|
||||
{
|
||||
Thread* t = static_cast<Thread*>(vmt);
|
||||
|
||||
assert(t, t->state == Thread::ActiveState
|
||||
or t->state == Thread::ExclusiveState);
|
||||
|
||||
@ -2820,55 +3149,26 @@ run(Thread* t, const char* className, const char* methodName,
|
||||
return 0;
|
||||
}
|
||||
|
||||
va_list a;
|
||||
va_start(a, this_);
|
||||
pushArguments(t, this_, methodSpec, false, arguments);
|
||||
|
||||
pushArguments(t, this_, methodSpec, false, a);
|
||||
|
||||
va_end(a);
|
||||
|
||||
object class_ = resolveClass(t, makeByteArray(t, "%s", className));
|
||||
object method = resolveMethod(t, className, methodName, methodSpec);
|
||||
if (LIKELY(t->exception == 0)) {
|
||||
PROTECT(t, class_);
|
||||
assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0));
|
||||
|
||||
object name = makeByteArray(t, methodName);
|
||||
PROTECT(t, name);
|
||||
|
||||
object spec = makeByteArray(t, methodSpec);
|
||||
object reference = makeReference(t, class_, name, spec);
|
||||
|
||||
object method = findMethodInClass(t, class_, referenceName(t, reference),
|
||||
referenceSpec(t, reference));
|
||||
if (LIKELY(t->exception == 0)) {
|
||||
assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0));
|
||||
|
||||
return invoke(t, method);
|
||||
}
|
||||
return ::invoke(t, method);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
run(System* system, Heap* heap, Finder* finder,
|
||||
const char* className, int argc, const char** argv)
|
||||
} // namespace
|
||||
|
||||
namespace vm {
|
||||
|
||||
Processor*
|
||||
makeProcessor(System* system)
|
||||
{
|
||||
Machine m(system, heap, finder);
|
||||
Thread* t = new (system->allocate(sizeof(Thread))) Thread(&m, 0, 0);
|
||||
|
||||
enter(t, Thread::ActiveState);
|
||||
|
||||
::run(t, className, argc, argv);
|
||||
|
||||
int exitCode = 0;
|
||||
if (t->exception) {
|
||||
exitCode = -1;
|
||||
printTrace(t, t->exception);
|
||||
}
|
||||
|
||||
exit(t);
|
||||
|
||||
return exitCode;
|
||||
return new (system->allocate(sizeof(MyProcessor))) MyProcessor(system);
|
||||
}
|
||||
|
||||
} // namespace vm
|
150
src/jnienv.cpp
150
src/jnienv.cpp
@ -1,6 +1,6 @@
|
||||
#include "jnienv.h"
|
||||
#include "machine.h"
|
||||
#include "run.h"
|
||||
#include "processor.h"
|
||||
#include "constants.h"
|
||||
|
||||
using namespace vm;
|
||||
@ -15,7 +15,7 @@ AttachCurrentThread(Machine* m, Thread** t, void*)
|
||||
{
|
||||
*t = static_cast<Thread*>(m->localThread->get());
|
||||
if (*t == 0) {
|
||||
*t = new (m->system->allocate(sizeof(Thread))) Thread(m, 0, m->rootThread);
|
||||
*t = m->processor->makeThread(m, 0, m->rootThread);
|
||||
|
||||
m->localThread->set(*t);
|
||||
}
|
||||
@ -63,7 +63,7 @@ GetStringUTFChars(Thread* t, jstring s, jboolean* isCopy)
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
char* chars = static_cast<char*>
|
||||
(t->vm->system->allocate(stringLength(t, *s) + 1));
|
||||
(t->m->system->allocate(stringLength(t, *s) + 1));
|
||||
stringChars(t, *s, chars);
|
||||
|
||||
if (isCopy) *isCopy = true;
|
||||
@ -73,7 +73,7 @@ GetStringUTFChars(Thread* t, jstring s, jboolean* isCopy)
|
||||
void JNICALL
|
||||
ReleaseStringUTFChars(Thread* t, jstring, const char* chars)
|
||||
{
|
||||
t->vm->system->free(chars);
|
||||
t->m->system->free(chars);
|
||||
}
|
||||
|
||||
jstring JNICALL
|
||||
@ -81,7 +81,7 @@ NewStringUTF(Thread* t, const char* chars)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
return pushReference(t, makeString(t, "%s", chars));
|
||||
return makeLocalReference(t, makeString(t, "%s", chars));
|
||||
}
|
||||
|
||||
jclass JNICALL
|
||||
@ -92,7 +92,7 @@ FindClass(Thread* t, const char* name)
|
||||
object n = makeByteArray(t, strlen(name) + 1, false);
|
||||
memcpy(&byteArrayBody(t, n, 0), name, byteArrayLength(t, n));
|
||||
|
||||
return pushReference(t, resolveClass(t, n));
|
||||
return makeLocalReference(t, resolveClass(t, n));
|
||||
}
|
||||
|
||||
jint JNICALL
|
||||
@ -122,9 +122,9 @@ ThrowNew(Thread* t, jclass c, const char* message)
|
||||
}
|
||||
|
||||
void JNICALL
|
||||
DeleteLocalRef(Thread*, jobject)
|
||||
DeleteLocalRef(Thread* t, jobject r)
|
||||
{
|
||||
// do nothing
|
||||
disposeLocalReference(t, r);
|
||||
}
|
||||
|
||||
jboolean JNICALL
|
||||
@ -138,7 +138,7 @@ GetObjectClass(Thread* t, jobject o)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
return pushReference(t, objectClass(t, *o));
|
||||
return makeLocalReference(t, objectClass(t, *o));
|
||||
}
|
||||
|
||||
jboolean JNICALL
|
||||
@ -172,18 +172,18 @@ GetMethodID(Thread* t, jclass c, const char* name, const char* spec)
|
||||
if (classFlags(t, *c) & ACC_INTERFACE) {
|
||||
PROTECT(t, method);
|
||||
|
||||
ACQUIRE(t, t->vm->referenceLock);
|
||||
ACQUIRE(t, t->m->referenceLock);
|
||||
|
||||
for (unsigned i = 0; i < vectorSize(t, t->vm->jniInterfaceTable); ++i) {
|
||||
if (method == vectorBody(t, t->vm->jniInterfaceTable, i)) {
|
||||
for (unsigned i = 0; i < vectorSize(t, t->m->jniInterfaceTable); ++i) {
|
||||
if (method == vectorBody(t, t->m->jniInterfaceTable, i)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
t->vm->jniInterfaceTable
|
||||
= vectorAppend(t, t->vm->jniInterfaceTable, method);
|
||||
t->m->jniInterfaceTable
|
||||
= vectorAppend(t, t->m->jniInterfaceTable, method);
|
||||
|
||||
return (vectorSize(t, t->vm->jniInterfaceTable) - 1) | InterfaceMethodID;
|
||||
return (vectorSize(t, t->m->jniInterfaceTable) - 1) | InterfaceMethodID;
|
||||
} else {
|
||||
return methodOffset(t, method) + 1;
|
||||
}
|
||||
@ -204,7 +204,7 @@ inline object
|
||||
getMethod(Thread* t, object o, jmethodID m)
|
||||
{
|
||||
if (m & InterfaceMethodID) {
|
||||
return vectorBody(t, t->vm->jniInterfaceTable, m & (~InterfaceMethodID));
|
||||
return vectorBody(t, t->m->jniInterfaceTable, m & (~InterfaceMethodID));
|
||||
} else {
|
||||
return arrayBody(t, classVirtualTable(t, objectClass(t, o)), m - 1);
|
||||
}
|
||||
@ -215,7 +215,8 @@ CallObjectMethodV(Thread* t, jobject o, jmethodID m, va_list a)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
return pushReference(t, runv(t, getMethod(t, *o, m), *o, true, a));
|
||||
return makeLocalReference(t, t->m->processor->invokeList
|
||||
(t, getMethod(t, *o, m), *o, true, a));
|
||||
}
|
||||
|
||||
jobject JNICALL
|
||||
@ -236,7 +237,7 @@ CallBooleanMethodV(Thread* t, jobject o, jmethodID m, va_list a)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
object r = runv(t, getMethod(t, *o, m), *o, true, a);
|
||||
object r = t->m->processor->invokeList(t, getMethod(t, *o, m), *o, true, a);
|
||||
return (t->exception ? 0 : booleanValue(t, r));
|
||||
}
|
||||
|
||||
@ -258,7 +259,7 @@ CallByteMethodV(Thread* t, jobject o, jmethodID m, va_list a)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
object r = runv(t, getMethod(t, *o, m), *o, true, a);
|
||||
object r = t->m->processor->invokeList(t, getMethod(t, *o, m), *o, true, a);
|
||||
return (t->exception ? 0 : byteValue(t, r));
|
||||
}
|
||||
|
||||
@ -280,7 +281,7 @@ CallCharMethodV(Thread* t, jobject o, jmethodID m, va_list a)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
object r = runv(t, getMethod(t, *o, m), *o, true, a);
|
||||
object r = t->m->processor->invokeList(t, getMethod(t, *o, m), *o, true, a);
|
||||
return (t->exception ? 0 : charValue(t, r));
|
||||
}
|
||||
|
||||
@ -302,7 +303,7 @@ CallShortMethodV(Thread* t, jobject o, jmethodID m, va_list a)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
object r = runv(t, getMethod(t, *o, m), *o, true, a);
|
||||
object r = t->m->processor->invokeList(t, getMethod(t, *o, m), *o, true, a);
|
||||
return (t->exception ? 0 : shortValue(t, r));
|
||||
}
|
||||
|
||||
@ -324,7 +325,7 @@ CallIntMethodV(Thread* t, jobject o, jmethodID m, va_list a)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
object r = runv(t, getMethod(t, *o, m), *o, true, a);
|
||||
object r = t->m->processor->invokeList(t, getMethod(t, *o, m), *o, true, a);
|
||||
return (t->exception ? 0 : intValue(t, r));
|
||||
}
|
||||
|
||||
@ -346,7 +347,7 @@ CallLongMethodV(Thread* t, jobject o, jmethodID m, va_list a)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
object r = runv(t, getMethod(t, *o, m), *o, true, a);
|
||||
object r = t->m->processor->invokeList(t, getMethod(t, *o, m), *o, true, a);
|
||||
return (t->exception ? 0 : longValue(t, r));
|
||||
}
|
||||
|
||||
@ -368,7 +369,7 @@ CallFloatMethodV(Thread* t, jobject o, jmethodID m, va_list a)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
object r = runv(t, getMethod(t, *o, m), *o, true, a);
|
||||
object r = t->m->processor->invokeList(t, getMethod(t, *o, m), *o, true, a);
|
||||
jint i = (t->exception ? 0 : floatValue(t, r));
|
||||
jfloat f; memcpy(&f, &i, 4);
|
||||
return f;
|
||||
@ -392,7 +393,7 @@ CallDoubleMethodV(Thread* t, jobject o, jmethodID m, va_list a)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
object r = runv(t, getMethod(t, *o, m), *o, true, a);
|
||||
object r = t->m->processor->invokeList(t, getMethod(t, *o, m), *o, true, a);
|
||||
jlong i = (t->exception ? 0 : doubleValue(t, r));
|
||||
jdouble f; memcpy(&f, &i, 4);
|
||||
return f;
|
||||
@ -416,7 +417,7 @@ CallVoidMethodV(Thread* t, jobject o, jmethodID m, va_list a)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
runv(t, getMethod(t, *o, m), *o, true, a);
|
||||
t->m->processor->invokeList(t, getMethod(t, *o, m), *o, true, a);
|
||||
}
|
||||
|
||||
void JNICALL
|
||||
@ -441,7 +442,8 @@ CallStaticObjectMethodV(Thread* t, jclass c, jmethodID m, va_list a)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
return pushReference(t, runv(t, getStaticMethod(t, *c, m), 0, true, a));
|
||||
return makeLocalReference(t, t->m->processor->invokeList
|
||||
(t, getStaticMethod(t, *c, m), 0, true, a));
|
||||
}
|
||||
|
||||
jobject JNICALL
|
||||
@ -462,7 +464,8 @@ CallStaticBooleanMethodV(Thread* t, jclass c, jmethodID m, va_list a)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
object r = runv(t, getStaticMethod(t, *c, m), 0, true, a);
|
||||
object r = t->m->processor->invokeList
|
||||
(t, getStaticMethod(t, *c, m), 0, true, a);
|
||||
return (t->exception ? 0 : booleanValue(t, r));
|
||||
}
|
||||
|
||||
@ -484,7 +487,8 @@ CallStaticByteMethodV(Thread* t, jclass c, jmethodID m, va_list a)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
object r = runv(t, getStaticMethod(t, *c, m), 0, true, a);
|
||||
object r = t->m->processor->invokeList
|
||||
(t, getStaticMethod(t, *c, m), 0, true, a);
|
||||
return (t->exception ? 0 : byteValue(t, r));
|
||||
}
|
||||
|
||||
@ -506,7 +510,8 @@ CallStaticCharMethodV(Thread* t, jclass c, jmethodID m, va_list a)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
object r = runv(t, getStaticMethod(t, *c, m), 0, true, a);
|
||||
object r = t->m->processor->invokeList
|
||||
(t, getStaticMethod(t, *c, m), 0, true, a);
|
||||
return (t->exception ? 0 : charValue(t, r));
|
||||
}
|
||||
|
||||
@ -528,7 +533,8 @@ CallStaticShortMethodV(Thread* t, jclass c, jmethodID m, va_list a)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
object r = runv(t, getStaticMethod(t, *c, m), 0, true, a);
|
||||
object r = t->m->processor->invokeList
|
||||
(t, getStaticMethod(t, *c, m), 0, true, a);
|
||||
return (t->exception ? 0 : shortValue(t, r));
|
||||
}
|
||||
|
||||
@ -550,7 +556,8 @@ CallStaticIntMethodV(Thread* t, jclass c, jmethodID m, va_list a)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
object r = runv(t, getStaticMethod(t, *c, m), 0, true, a);
|
||||
object r = t->m->processor->invokeList
|
||||
(t, getStaticMethod(t, *c, m), 0, true, a);
|
||||
return (t->exception ? 0 : intValue(t, r));
|
||||
}
|
||||
|
||||
@ -572,7 +579,8 @@ CallStaticLongMethodV(Thread* t, jclass c, jmethodID m, va_list a)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
object r = runv(t, getStaticMethod(t, *c, m), 0, true, a);
|
||||
object r = t->m->processor->invokeList
|
||||
(t, getStaticMethod(t, *c, m), 0, true, a);
|
||||
return (t->exception ? 0 : longValue(t, r));
|
||||
}
|
||||
|
||||
@ -594,7 +602,8 @@ CallStaticFloatMethodV(Thread* t, jclass c, jmethodID m, va_list a)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
object r = runv(t, getStaticMethod(t, *c, m), 0, true, a);
|
||||
object r = t->m->processor->invokeList
|
||||
(t, getStaticMethod(t, *c, m), 0, true, a);
|
||||
jint i = (t->exception ? 0 : floatValue(t, r));
|
||||
jfloat f; memcpy(&f, &i, 4);
|
||||
return f;
|
||||
@ -618,7 +627,8 @@ CallStaticDoubleMethodV(Thread* t, jclass c, jmethodID m, va_list a)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
object r = runv(t, getStaticMethod(t, *c, m), 0, true, a);
|
||||
object r = t->m->processor->invokeList
|
||||
(t, getStaticMethod(t, *c, m), 0, true, a);
|
||||
jlong i = (t->exception ? 0 : doubleValue(t, r));
|
||||
jdouble f; memcpy(&f, &i, 4);
|
||||
return f;
|
||||
@ -642,7 +652,7 @@ CallStaticVoidMethodV(Thread* t, jclass c, jmethodID m, va_list a)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
runv(t, getStaticMethod(t, *c, m), 0, true, a);
|
||||
t->m->processor->invokeList(t, getStaticMethod(t, *c, m), 0, true, a);
|
||||
}
|
||||
|
||||
void JNICALL
|
||||
@ -693,7 +703,7 @@ GetObjectField(Thread* t, jobject o, jfieldID field)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
return pushReference(t, cast<object>(*o, field));
|
||||
return makeLocalReference(t, cast<object>(*o, field));
|
||||
}
|
||||
|
||||
jboolean JNICALL
|
||||
@ -837,7 +847,7 @@ GetStaticObjectField(Thread* t, jclass c, jfieldID field)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
return pushReference(t, arrayBody(t, classStaticTable(t, *c), field));
|
||||
return makeLocalReference(t, arrayBody(t, classStaticTable(t, *c), field));
|
||||
}
|
||||
|
||||
jboolean JNICALL
|
||||
@ -1003,12 +1013,12 @@ NewGlobalRef(Thread* t, jobject o)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
ACQUIRE(t, t->vm->referenceLock);
|
||||
ACQUIRE(t, t->m->referenceLock);
|
||||
|
||||
t->vm->jniReferences = new (t->vm->system->allocate(sizeof(Reference)))
|
||||
Reference(*o, t->vm->jniReferences);
|
||||
t->m->jniReferences = new (t->m->system->allocate(sizeof(Reference)))
|
||||
Reference(*o, t->m->jniReferences);
|
||||
|
||||
return &(t->vm->jniReferences->target);
|
||||
return &(t->m->jniReferences->target);
|
||||
}
|
||||
|
||||
void JNICALL
|
||||
@ -1016,9 +1026,9 @@ DeleteGlobalRef(Thread* t, jobject o)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
ACQUIRE(t, t->vm->referenceLock);
|
||||
ACQUIRE(t, t->m->referenceLock);
|
||||
|
||||
for (Reference** r = &(t->vm->jniReferences); *r;) {
|
||||
for (Reference** r = &(t->m->jniReferences); *r;) {
|
||||
if (&((*r)->target) == o) {
|
||||
*r = (*r)->next;
|
||||
break;
|
||||
@ -1033,7 +1043,7 @@ ExceptionOccurred(Thread* t)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
return pushReference(t, t->exception);
|
||||
return makeLocalReference(t, t->exception);
|
||||
}
|
||||
|
||||
void JNICALL
|
||||
@ -1057,7 +1067,7 @@ NewBooleanArray(Thread* t, jsize length)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
return pushReference(t, makeBooleanArray(t, length, true));
|
||||
return makeLocalReference(t, makeBooleanArray(t, length, true));
|
||||
}
|
||||
|
||||
jbyteArray JNICALL
|
||||
@ -1065,7 +1075,7 @@ NewByteArray(Thread* t, jsize length)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
return pushReference(t, makeByteArray(t, length, true));
|
||||
return makeLocalReference(t, makeByteArray(t, length, true));
|
||||
}
|
||||
|
||||
jcharArray JNICALL
|
||||
@ -1073,7 +1083,7 @@ NewCharArray(Thread* t, jsize length)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
return pushReference(t, makeCharArray(t, length, true));
|
||||
return makeLocalReference(t, makeCharArray(t, length, true));
|
||||
}
|
||||
|
||||
jshortArray JNICALL
|
||||
@ -1081,7 +1091,7 @@ NewShortArray(Thread* t, jsize length)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
return pushReference(t, makeShortArray(t, length, true));
|
||||
return makeLocalReference(t, makeShortArray(t, length, true));
|
||||
}
|
||||
|
||||
jintArray JNICALL
|
||||
@ -1089,7 +1099,7 @@ NewIntArray(Thread* t, jsize length)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
return pushReference(t, makeIntArray(t, length, true));
|
||||
return makeLocalReference(t, makeIntArray(t, length, true));
|
||||
}
|
||||
|
||||
jlongArray JNICALL
|
||||
@ -1097,7 +1107,7 @@ NewLongArray(Thread* t, jsize length)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
return pushReference(t, makeLongArray(t, length, true));
|
||||
return makeLocalReference(t, makeLongArray(t, length, true));
|
||||
}
|
||||
|
||||
jfloatArray JNICALL
|
||||
@ -1105,7 +1115,7 @@ NewFloatArray(Thread* t, jsize length)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
return pushReference(t, makeFloatArray(t, length, true));
|
||||
return makeLocalReference(t, makeFloatArray(t, length, true));
|
||||
}
|
||||
|
||||
jdoubleArray JNICALL
|
||||
@ -1113,7 +1123,7 @@ NewDoubleArray(Thread* t, jsize length)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
return pushReference(t, makeDoubleArray(t, length, true));
|
||||
return makeLocalReference(t, makeDoubleArray(t, length, true));
|
||||
}
|
||||
|
||||
jboolean* JNICALL
|
||||
@ -1122,7 +1132,7 @@ GetBooleanArrayElements(Thread* t, jbooleanArray array, jboolean* isCopy)
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
unsigned size = booleanArrayLength(t, *array) * sizeof(jboolean);
|
||||
jboolean* p = static_cast<jboolean*>(t->vm->system->allocate(size));
|
||||
jboolean* p = static_cast<jboolean*>(t->m->system->allocate(size));
|
||||
if (size) {
|
||||
memcpy(p, &booleanArrayBody(t, *array, 0), size);
|
||||
}
|
||||
@ -1140,7 +1150,7 @@ GetByteArrayElements(Thread* t, jbyteArray array, jboolean* isCopy)
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
unsigned size = byteArrayLength(t, *array) * sizeof(jbyte);
|
||||
jbyte* p = static_cast<jbyte*>(t->vm->system->allocate(size));
|
||||
jbyte* p = static_cast<jbyte*>(t->m->system->allocate(size));
|
||||
if (size) {
|
||||
memcpy(p, &byteArrayBody(t, *array, 0), size);
|
||||
}
|
||||
@ -1158,7 +1168,7 @@ GetCharArrayElements(Thread* t, jcharArray array, jboolean* isCopy)
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
unsigned size = charArrayLength(t, *array) * sizeof(jchar);
|
||||
jchar* p = static_cast<jchar*>(t->vm->system->allocate(size));
|
||||
jchar* p = static_cast<jchar*>(t->m->system->allocate(size));
|
||||
if (size) {
|
||||
memcpy(p, &charArrayBody(t, *array, 0), size);
|
||||
}
|
||||
@ -1176,7 +1186,7 @@ GetShortArrayElements(Thread* t, jshortArray array, jboolean* isCopy)
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
unsigned size = shortArrayLength(t, *array) * sizeof(jshort);
|
||||
jshort* p = static_cast<jshort*>(t->vm->system->allocate(size));
|
||||
jshort* p = static_cast<jshort*>(t->m->system->allocate(size));
|
||||
if (size) {
|
||||
memcpy(p, &shortArrayBody(t, *array, 0), size);
|
||||
}
|
||||
@ -1194,7 +1204,7 @@ GetIntArrayElements(Thread* t, jintArray array, jboolean* isCopy)
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
unsigned size = intArrayLength(t, *array) * sizeof(jint);
|
||||
jint* p = static_cast<jint*>(t->vm->system->allocate(size));
|
||||
jint* p = static_cast<jint*>(t->m->system->allocate(size));
|
||||
if (size) {
|
||||
memcpy(p, &intArrayBody(t, *array, 0), size);
|
||||
}
|
||||
@ -1212,7 +1222,7 @@ GetLongArrayElements(Thread* t, jlongArray array, jboolean* isCopy)
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
unsigned size = longArrayLength(t, *array) * sizeof(jlong);
|
||||
jlong* p = static_cast<jlong*>(t->vm->system->allocate(size));
|
||||
jlong* p = static_cast<jlong*>(t->m->system->allocate(size));
|
||||
if (size) {
|
||||
memcpy(p, &longArrayBody(t, *array, 0), size);
|
||||
}
|
||||
@ -1230,7 +1240,7 @@ GetFloatArrayElements(Thread* t, jfloatArray array, jboolean* isCopy)
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
unsigned size = floatArrayLength(t, *array) * sizeof(jfloat);
|
||||
jfloat* p = static_cast<jfloat*>(t->vm->system->allocate(size));
|
||||
jfloat* p = static_cast<jfloat*>(t->m->system->allocate(size));
|
||||
if (size) {
|
||||
memcpy(p, &floatArrayBody(t, *array, 0), size);
|
||||
}
|
||||
@ -1248,7 +1258,7 @@ GetDoubleArrayElements(Thread* t, jdoubleArray array, jboolean* isCopy)
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
unsigned size = doubleArrayLength(t, *array) * sizeof(jdouble);
|
||||
jdouble* p = static_cast<jdouble*>(t->vm->system->allocate(size));
|
||||
jdouble* p = static_cast<jdouble*>(t->m->system->allocate(size));
|
||||
if (size) {
|
||||
memcpy(p, &doubleArrayBody(t, *array, 0), size);
|
||||
}
|
||||
@ -1274,7 +1284,7 @@ ReleaseBooleanArrayElements(Thread* t, jbooleanArray array, jboolean* p,
|
||||
}
|
||||
|
||||
if (mode == 0 or mode == JNI_ABORT) {
|
||||
t->vm->system->free(p);
|
||||
t->m->system->free(p);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1291,7 +1301,7 @@ ReleaseByteArrayElements(Thread* t, jbyteArray array, jbyte* p, jint mode)
|
||||
}
|
||||
|
||||
if (mode == 0 or mode == JNI_ABORT) {
|
||||
t->vm->system->free(p);
|
||||
t->m->system->free(p);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1308,7 +1318,7 @@ ReleaseCharArrayElements(Thread* t, jcharArray array, jchar* p, jint mode)
|
||||
}
|
||||
|
||||
if (mode == 0 or mode == JNI_ABORT) {
|
||||
t->vm->system->free(p);
|
||||
t->m->system->free(p);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1325,7 +1335,7 @@ ReleaseShortArrayElements(Thread* t, jshortArray array, jshort* p, jint mode)
|
||||
}
|
||||
|
||||
if (mode == 0 or mode == JNI_ABORT) {
|
||||
t->vm->system->free(p);
|
||||
t->m->system->free(p);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1342,7 +1352,7 @@ ReleaseIntArrayElements(Thread* t, jintArray array, jint* p, jint mode)
|
||||
}
|
||||
|
||||
if (mode == 0 or mode == JNI_ABORT) {
|
||||
t->vm->system->free(p);
|
||||
t->m->system->free(p);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1359,7 +1369,7 @@ ReleaseLongArrayElements(Thread* t, jlongArray array, jlong* p, jint mode)
|
||||
}
|
||||
|
||||
if (mode == 0 or mode == JNI_ABORT) {
|
||||
t->vm->system->free(p);
|
||||
t->m->system->free(p);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1376,7 +1386,7 @@ ReleaseFloatArrayElements(Thread* t, jfloatArray array, jfloat* p, jint mode)
|
||||
}
|
||||
|
||||
if (mode == 0 or mode == JNI_ABORT) {
|
||||
t->vm->system->free(p);
|
||||
t->m->system->free(p);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1394,7 +1404,7 @@ ReleaseDoubleArrayElements(Thread* t, jdoubleArray array, jdouble* p,
|
||||
}
|
||||
|
||||
if (mode == 0 or mode == JNI_ABORT) {
|
||||
t->vm->system->free(p);
|
||||
t->m->system->free(p);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1567,7 +1577,7 @@ ReleasePrimitiveArrayCritical(Thread* t, jarray, void*, jint)
|
||||
jint JNICALL
|
||||
GetJavaVM(Thread* t, Machine** m)
|
||||
{
|
||||
*m = t->vm;
|
||||
*m = t->m;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
313
src/machine.cpp
313
src/machine.cpp
@ -2,7 +2,7 @@
|
||||
#include "machine.h"
|
||||
#include "stream.h"
|
||||
#include "constants.h"
|
||||
#include "run.h"
|
||||
#include "processor.h"
|
||||
|
||||
using namespace vm;
|
||||
|
||||
@ -48,18 +48,18 @@ dispose(Thread* t, Thread* o, bool remove)
|
||||
o->parent->child = 0;
|
||||
}
|
||||
} else if (o->child) {
|
||||
t->vm->rootThread = o->child;
|
||||
t->m->rootThread = o->child;
|
||||
if (o->peer) {
|
||||
o->peer->peer = o->child->peer;
|
||||
o->child->peer = o->peer;
|
||||
}
|
||||
} else if (o->peer) {
|
||||
t->vm->rootThread = o->peer;
|
||||
t->m->rootThread = o->peer;
|
||||
} else {
|
||||
abort(t);
|
||||
}
|
||||
|
||||
assert(t, not find(t->vm->rootThread, o));
|
||||
assert(t, not find(t->m->rootThread, o));
|
||||
}
|
||||
|
||||
o->dispose();
|
||||
@ -132,14 +132,9 @@ visitRoots(Thread* t, Heap::Visitor* v)
|
||||
{
|
||||
if (t->state != Thread::ZombieState) {
|
||||
v->visit(&(t->javaThread));
|
||||
v->visit(&(t->code));
|
||||
v->visit(&(t->exception));
|
||||
|
||||
for (unsigned i = 0; i < t->sp; ++i) {
|
||||
if (t->stack[i * 2] == ObjectTag) {
|
||||
v->visit(t->stack + (i * 2) + 1);
|
||||
}
|
||||
}
|
||||
t->m->processor->visitObjects(t, v);
|
||||
|
||||
for (Thread::Protector* p = t->protector; p; p = p->next) {
|
||||
v->visit(p->p);
|
||||
@ -158,8 +153,8 @@ finalizerTargetUnreachable(Thread* t, object* p, Heap::Visitor* v)
|
||||
|
||||
object finalizer = *p;
|
||||
*p = finalizerNext(t, finalizer);
|
||||
finalizerNext(t, finalizer) = t->vm->finalizeQueue;
|
||||
t->vm->finalizeQueue = finalizer;
|
||||
finalizerNext(t, finalizer) = t->m->finalizeQueue;
|
||||
t->m->finalizeQueue = finalizer;
|
||||
}
|
||||
|
||||
void
|
||||
@ -174,7 +169,7 @@ referenceTargetUnreachable(Thread* t, object* p, Heap::Visitor* v)
|
||||
jreferenceTarget(t, *p) = 0;
|
||||
|
||||
if (jreferenceQueue(t, *p)
|
||||
and t->vm->heap->status(jreferenceQueue(t, *p)) != Heap::Unreachable)
|
||||
and t->m->heap->status(jreferenceQueue(t, *p)) != Heap::Unreachable)
|
||||
{
|
||||
// queue is reachable - add the reference
|
||||
|
||||
@ -205,7 +200,7 @@ referenceUnreachable(Thread* t, object* p, Heap::Visitor* v)
|
||||
}
|
||||
|
||||
if (jreferenceQueue(t, *p)
|
||||
and t->vm->heap->status(jreferenceQueue(t, *p)) != Heap::Unreachable)
|
||||
and t->m->heap->status(jreferenceQueue(t, *p)) != Heap::Unreachable)
|
||||
{
|
||||
// queue is reachable - add the reference
|
||||
referenceTargetUnreachable(t, p, v);
|
||||
@ -225,7 +220,7 @@ referenceTargetReachable(Thread* t, object* p, Heap::Visitor* v)
|
||||
v->visit(p);
|
||||
v->visit(&jreferenceTarget(t, *p));
|
||||
|
||||
if (t->vm->heap->status(jreferenceQueue(t, *p)) == Heap::Unreachable) {
|
||||
if (t->m->heap->status(jreferenceQueue(t, *p)) == Heap::Unreachable) {
|
||||
jreferenceQueue(t, *p) = 0;
|
||||
} else {
|
||||
v->visit(&jreferenceQueue(t, *p));
|
||||
@ -235,7 +230,7 @@ referenceTargetReachable(Thread* t, object* p, Heap::Visitor* v)
|
||||
void
|
||||
postVisit(Thread* t, Heap::Visitor* v)
|
||||
{
|
||||
Machine* m = t->vm;
|
||||
Machine* m = t->m;
|
||||
|
||||
for (object* p = &(m->finalizeQueue); *p; p = &(finalizerNext(t, *p))) {
|
||||
v->visit(p);
|
||||
@ -359,9 +354,9 @@ void
|
||||
postCollect(Thread* t)
|
||||
{
|
||||
#ifdef VM_STRESS
|
||||
t->vm->system->free(t->defaultHeap);
|
||||
t->m->system->free(t->defaultHeap);
|
||||
t->defaultHeap = static_cast<uintptr_t*>
|
||||
(t->vm->system->allocate(Thread::HeapSizeInBytes));
|
||||
(t->m->system->allocate(Thread::HeapSizeInBytes));
|
||||
#endif
|
||||
|
||||
t->heap = t->defaultHeap;
|
||||
@ -369,7 +364,7 @@ postCollect(Thread* t)
|
||||
t->heapIndex = 0;
|
||||
|
||||
if (t->large) {
|
||||
t->vm->system->free(t->large);
|
||||
t->m->system->free(t->large);
|
||||
t->large = 0;
|
||||
}
|
||||
|
||||
@ -588,7 +583,7 @@ parsePool(Thread* t, Stream& s)
|
||||
for (unsigned i = 0; i < poolCount; ++i) {
|
||||
object o = arrayBody(t, pool, i);
|
||||
if (o and objectClass(t, o)
|
||||
== arrayBody(t, t->vm->types, Machine::IntArrayType))
|
||||
== arrayBody(t, t->m->types, Machine::IntArrayType))
|
||||
{
|
||||
switch (intArrayBody(t, o, 0)) {
|
||||
case CONSTANT_Class: {
|
||||
@ -617,7 +612,7 @@ parsePool(Thread* t, Stream& s)
|
||||
for (unsigned i = 0; i < poolCount; ++i) {
|
||||
object o = arrayBody(t, pool, i);
|
||||
if (o and objectClass(t, o)
|
||||
== arrayBody(t, t->vm->types, Machine::IntArrayType))
|
||||
== arrayBody(t, t->m->types, Machine::IntArrayType))
|
||||
{
|
||||
switch (intArrayBody(t, o, 0)) {
|
||||
case CONSTANT_Fieldref:
|
||||
@ -1183,15 +1178,15 @@ makeArrayClass(Thread* t, unsigned dimensions, object spec,
|
||||
dimensions,
|
||||
2 * BytesPerWord,
|
||||
BytesPerWord,
|
||||
classObjectMask(t, arrayBody(t, t->vm->types, Machine::ArrayType)),
|
||||
classObjectMask(t, arrayBody(t, t->m->types, Machine::ArrayType)),
|
||||
spec,
|
||||
arrayBody(t, t->vm->types, Machine::JobjectType),
|
||||
arrayBody(t, t->m->types, Machine::JobjectType),
|
||||
0,
|
||||
classVirtualTable(t, arrayBody(t, t->vm->types, Machine::JobjectType)),
|
||||
classVirtualTable(t, arrayBody(t, t->m->types, Machine::JobjectType)),
|
||||
0,
|
||||
0,
|
||||
elementClass,
|
||||
t->vm->loader);
|
||||
t->m->loader);
|
||||
}
|
||||
|
||||
object
|
||||
@ -1232,7 +1227,7 @@ makeArrayClass(Thread* t, object spec)
|
||||
}
|
||||
|
||||
object elementClass = hashMapFind
|
||||
(t, t->vm->bootstrapClassMap, elementSpec, byteArrayHash, byteArrayEqual);
|
||||
(t, t->m->bootstrapClassMap, elementSpec, byteArrayHash, byteArrayEqual);
|
||||
|
||||
if (elementClass == 0) {
|
||||
elementClass = resolveClass(t, elementSpec);
|
||||
@ -1245,7 +1240,7 @@ makeArrayClass(Thread* t, object spec)
|
||||
void
|
||||
removeMonitor(Thread* t, object o)
|
||||
{
|
||||
object p = hashMapRemove(t, t->vm->monitorMap, o, objectHash, objectEqual);
|
||||
object p = hashMapRemove(t, t->m->monitorMap, o, objectHash, objectEqual);
|
||||
|
||||
assert(t, p);
|
||||
|
||||
@ -1261,18 +1256,39 @@ removeMonitor(Thread* t, object o)
|
||||
void
|
||||
removeString(Thread* t, object o)
|
||||
{
|
||||
hashMapRemove(t, t->vm->stringMap, o, stringHash, objectEqual);
|
||||
hashMapRemove(t, t->m->stringMap, o, stringHash, objectEqual);
|
||||
}
|
||||
|
||||
void
|
||||
invoke(Thread* t, const char* className, int argc, const char** argv)
|
||||
{
|
||||
enter(t, Thread::ActiveState);
|
||||
|
||||
object args = makeObjectArray
|
||||
(t, arrayBody(t, t->m->types, Machine::StringType), argc, true);
|
||||
|
||||
PROTECT(t, args);
|
||||
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
object arg = makeString(t, "%s", argv[i]);
|
||||
set(t, objectArrayBody(t, args, i), arg);
|
||||
}
|
||||
|
||||
t->m->processor->invoke
|
||||
(t, className, "main", "([Ljava/lang/String;)V", 0, args);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace vm {
|
||||
|
||||
Machine::Machine(System* system, Heap* heap, Finder* finder):
|
||||
Machine::Machine(System* system, Heap* heap, Finder* finder,
|
||||
Processor* processor):
|
||||
vtable(&javaVMVTable),
|
||||
system(system),
|
||||
heap(heap),
|
||||
finder(finder),
|
||||
processor(processor),
|
||||
rootThread(0),
|
||||
exclusive(0),
|
||||
jniReferences(0),
|
||||
@ -1333,7 +1349,7 @@ Machine::dispose()
|
||||
|
||||
Thread::Thread(Machine* m, object javaThread, Thread* parent):
|
||||
vtable(&(m->jniEnvVTable)),
|
||||
vm(m),
|
||||
m(m),
|
||||
parent(parent),
|
||||
peer((parent ? parent->child : 0)),
|
||||
child(0),
|
||||
@ -1341,12 +1357,8 @@ Thread::Thread(Machine* m, object javaThread, Thread* parent):
|
||||
criticalLevel(0),
|
||||
systemThread(0),
|
||||
javaThread(javaThread),
|
||||
code(0),
|
||||
exception(0),
|
||||
large(0),
|
||||
ip(0),
|
||||
sp(0),
|
||||
frame(-1),
|
||||
heapIndex(0),
|
||||
heapOffset(0),
|
||||
protector(0),
|
||||
@ -1370,17 +1382,17 @@ Thread::Thread(Machine* m, object javaThread, Thread* parent):
|
||||
|
||||
Thread* t = this;
|
||||
|
||||
t->vm->loader = allocate(t, sizeof(void*) * 3);
|
||||
memset(t->vm->loader, 0, sizeof(void*) * 2);
|
||||
t->m->loader = allocate(t, sizeof(void*) * 3);
|
||||
memset(t->m->loader, 0, sizeof(void*) * 2);
|
||||
|
||||
#include "type-initializations.cpp"
|
||||
|
||||
object arrayClass = arrayBody(t, t->vm->types, Machine::ArrayType);
|
||||
set(t, cast<object>(t->vm->types, 0), arrayClass);
|
||||
object arrayClass = arrayBody(t, t->m->types, Machine::ArrayType);
|
||||
set(t, cast<object>(t->m->types, 0), arrayClass);
|
||||
|
||||
object loaderClass = arrayBody
|
||||
(t, t->vm->types, Machine::SystemClassLoaderType);
|
||||
set(t, cast<object>(t->vm->loader, 0), loaderClass);
|
||||
(t, t->m->types, Machine::SystemClassLoaderType);
|
||||
set(t, cast<object>(t->m->loader, 0), loaderClass);
|
||||
|
||||
object objectClass = arrayBody(t, m->types, Machine::JobjectType);
|
||||
|
||||
@ -1453,7 +1465,7 @@ Thread::exit()
|
||||
{
|
||||
enter(this, Thread::ExclusiveState);
|
||||
|
||||
if (vm->liveCount == 1) {
|
||||
if (m->liveCount == 1) {
|
||||
vm::exit(this);
|
||||
} else {
|
||||
enter(this, Thread::ZombieState);
|
||||
@ -1465,7 +1477,7 @@ void
|
||||
Thread::dispose()
|
||||
{
|
||||
if (large) {
|
||||
vm->system->free(large);
|
||||
m->system->free(large);
|
||||
large = 0;
|
||||
}
|
||||
|
||||
@ -1475,11 +1487,11 @@ Thread::dispose()
|
||||
}
|
||||
|
||||
#ifdef VM_STRESS
|
||||
vm->system->free(heap);
|
||||
m->system->free(heap);
|
||||
heap = 0;
|
||||
#endif // VM_STRESS
|
||||
|
||||
vm->system->free(this);
|
||||
m->system->free(this);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1487,9 +1499,9 @@ exit(Thread* t)
|
||||
{
|
||||
enter(t, Thread::ExitState);
|
||||
|
||||
joinAll(t, t->vm->rootThread);
|
||||
joinAll(t, t->m->rootThread);
|
||||
|
||||
for (object* p = &(t->vm->finalizers); *p;) {
|
||||
for (object* p = &(t->m->finalizers); *p;) {
|
||||
object f = *p;
|
||||
*p = finalizerNext(t, *p);
|
||||
|
||||
@ -1497,7 +1509,7 @@ exit(Thread* t)
|
||||
(t, finalizerTarget(t, f));
|
||||
}
|
||||
|
||||
for (object* p = &(t->vm->tenuredFinalizers); *p;) {
|
||||
for (object* p = &(t->m->tenuredFinalizers); *p;) {
|
||||
object f = *p;
|
||||
*p = finalizerNext(t, *p);
|
||||
|
||||
@ -1505,7 +1517,7 @@ exit(Thread* t)
|
||||
(t, finalizerTarget(t, f));
|
||||
}
|
||||
|
||||
disposeAll(t, t->vm->rootThread);
|
||||
disposeAll(t, t->m->rootThread);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1520,22 +1532,22 @@ enter(Thread* t, Thread::State s)
|
||||
return;
|
||||
}
|
||||
|
||||
ACQUIRE_RAW(t, t->vm->stateLock);
|
||||
ACQUIRE_RAW(t, t->m->stateLock);
|
||||
|
||||
switch (s) {
|
||||
case Thread::ExclusiveState: {
|
||||
assert(t, t->state == Thread::ActiveState);
|
||||
|
||||
while (t->vm->exclusive) {
|
||||
while (t->m->exclusive) {
|
||||
// another thread got here first.
|
||||
ENTER(t, Thread::IdleState);
|
||||
}
|
||||
|
||||
t->state = Thread::ExclusiveState;
|
||||
t->vm->exclusive = t;
|
||||
t->m->exclusive = t;
|
||||
|
||||
while (t->vm->activeCount > 1) {
|
||||
t->vm->stateLock->wait(t->systemThread, 0);
|
||||
while (t->m->activeCount > 1) {
|
||||
t->m->stateLock->wait(t->systemThread, 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
@ -1543,8 +1555,8 @@ enter(Thread* t, Thread::State s)
|
||||
case Thread::ZombieState: {
|
||||
switch (t->state) {
|
||||
case Thread::ExclusiveState: {
|
||||
assert(t, t->vm->exclusive == t);
|
||||
t->vm->exclusive = 0;
|
||||
assert(t, t->m->exclusive == t);
|
||||
t->m->exclusive = 0;
|
||||
} break;
|
||||
|
||||
case Thread::ActiveState: break;
|
||||
@ -1552,38 +1564,38 @@ enter(Thread* t, Thread::State s)
|
||||
default: abort(t);
|
||||
}
|
||||
|
||||
assert(t, t->vm->activeCount > 0);
|
||||
-- t->vm->activeCount;
|
||||
assert(t, t->m->activeCount > 0);
|
||||
-- t->m->activeCount;
|
||||
|
||||
if (s == Thread::ZombieState) {
|
||||
assert(t, t->vm->liveCount > 0);
|
||||
-- t->vm->liveCount;
|
||||
assert(t, t->m->liveCount > 0);
|
||||
-- t->m->liveCount;
|
||||
}
|
||||
t->state = s;
|
||||
|
||||
t->vm->stateLock->notifyAll(t->systemThread);
|
||||
t->m->stateLock->notifyAll(t->systemThread);
|
||||
} break;
|
||||
|
||||
case Thread::ActiveState: {
|
||||
switch (t->state) {
|
||||
case Thread::ExclusiveState: {
|
||||
assert(t, t->vm->exclusive == t);
|
||||
assert(t, t->m->exclusive == t);
|
||||
|
||||
t->state = s;
|
||||
t->vm->exclusive = 0;
|
||||
t->m->exclusive = 0;
|
||||
|
||||
t->vm->stateLock->notifyAll(t->systemThread);
|
||||
t->m->stateLock->notifyAll(t->systemThread);
|
||||
} break;
|
||||
|
||||
case Thread::NoState:
|
||||
case Thread::IdleState: {
|
||||
while (t->vm->exclusive) {
|
||||
t->vm->stateLock->wait(t->systemThread, 0);
|
||||
while (t->m->exclusive) {
|
||||
t->m->stateLock->wait(t->systemThread, 0);
|
||||
}
|
||||
|
||||
++ t->vm->activeCount;
|
||||
++ t->m->activeCount;
|
||||
if (t->state == Thread::NoState) {
|
||||
++ t->vm->liveCount;
|
||||
++ t->m->liveCount;
|
||||
}
|
||||
t->state = s;
|
||||
} break;
|
||||
@ -1595,8 +1607,8 @@ enter(Thread* t, Thread::State s)
|
||||
case Thread::ExitState: {
|
||||
switch (t->state) {
|
||||
case Thread::ExclusiveState: {
|
||||
assert(t, t->vm->exclusive == t);
|
||||
t->vm->exclusive = 0;
|
||||
assert(t, t->m->exclusive == t);
|
||||
t->m->exclusive = 0;
|
||||
} break;
|
||||
|
||||
case Thread::ActiveState: break;
|
||||
@ -1604,13 +1616,13 @@ enter(Thread* t, Thread::State s)
|
||||
default: abort(t);
|
||||
}
|
||||
|
||||
assert(t, t->vm->activeCount > 0);
|
||||
-- t->vm->activeCount;
|
||||
assert(t, t->m->activeCount > 0);
|
||||
-- t->m->activeCount;
|
||||
|
||||
t->state = s;
|
||||
|
||||
while (t->vm->liveCount > 1) {
|
||||
t->vm->stateLock->wait(t->systemThread, 0);
|
||||
while (t->m->liveCount > 1) {
|
||||
t->m->stateLock->wait(t->systemThread, 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
@ -1625,9 +1637,9 @@ allocate2(Thread* t, unsigned sizeInBytes)
|
||||
return allocateLarge(t, sizeInBytes);
|
||||
}
|
||||
|
||||
ACQUIRE_RAW(t, t->vm->stateLock);
|
||||
ACQUIRE_RAW(t, t->m->stateLock);
|
||||
|
||||
while (t->vm->exclusive and t->vm->exclusive != t) {
|
||||
while (t->m->exclusive and t->m->exclusive != t) {
|
||||
// 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);
|
||||
@ -1637,11 +1649,11 @@ allocate2(Thread* t, unsigned sizeInBytes)
|
||||
>= Thread::HeapSizeInWords)
|
||||
{
|
||||
t->heap = 0;
|
||||
if (t->large == 0 and t->vm->heapPoolIndex < Machine::HeapPoolSize) {
|
||||
if (t->large == 0 and t->m->heapPoolIndex < Machine::HeapPoolSize) {
|
||||
t->heap = static_cast<uintptr_t*>
|
||||
(t->vm->system->tryAllocate(Thread::HeapSizeInBytes));
|
||||
(t->m->system->tryAllocate(Thread::HeapSizeInBytes));
|
||||
if (t->heap) {
|
||||
t->vm->heapPool[t->vm->heapPoolIndex++] = t->heap;
|
||||
t->m->heapPool[t->m->heapPoolIndex++] = t->heap;
|
||||
t->heapOffset += t->heapIndex;
|
||||
t->heapIndex = 0;
|
||||
}
|
||||
@ -1673,10 +1685,10 @@ make(Thread* t, object class_)
|
||||
if (UNLIKELY(classVmFlags(t, class_) & WeakReferenceFlag)) {
|
||||
PROTECT(t, instance);
|
||||
|
||||
ACQUIRE(t, t->vm->referenceLock);
|
||||
ACQUIRE(t, t->m->referenceLock);
|
||||
|
||||
jreferenceNextUnsafe(t, instance) = t->vm->weakReferences;
|
||||
t->vm->weakReferences = instance;
|
||||
jreferenceNextUnsafe(t, instance) = t->m->weakReferences;
|
||||
t->m->weakReferences = instance;
|
||||
}
|
||||
|
||||
return instance;
|
||||
@ -1709,7 +1721,7 @@ stringChars(Thread* t, object string, char* chars)
|
||||
{
|
||||
object data = stringData(t, string);
|
||||
if (objectClass(t, data)
|
||||
== arrayBody(t, t->vm->types, Machine::ByteArrayType))
|
||||
== arrayBody(t, t->m->types, Machine::ByteArrayType))
|
||||
{
|
||||
memcpy(chars,
|
||||
&byteArrayBody(t, data, stringOffset(t, string)),
|
||||
@ -1865,7 +1877,7 @@ hashMapFindNode(Thread* t, object map, object key,
|
||||
bool (*equal)(Thread*, object, object))
|
||||
{
|
||||
bool weak = objectClass(t, map)
|
||||
== arrayBody(t, t->vm->types, Machine::WeakHashMapType);
|
||||
== arrayBody(t, t->m->types, Machine::WeakHashMapType);
|
||||
|
||||
object array = hashMapArray(t, map);
|
||||
if (array) {
|
||||
@ -1905,7 +1917,7 @@ hashMapResize(Thread* t, object map, uint32_t (*hash)(Thread*, object),
|
||||
|
||||
if (oldArray) {
|
||||
bool weak = objectClass(t, map)
|
||||
== arrayBody(t, t->vm->types, Machine::WeakHashMapType);
|
||||
== arrayBody(t, t->m->types, Machine::WeakHashMapType);
|
||||
|
||||
for (unsigned i = 0; i < arrayLength(t, oldArray); ++i) {
|
||||
object next;
|
||||
@ -1934,7 +1946,7 @@ hashMapInsert(Thread* t, object map, object key, object value,
|
||||
uint32_t (*hash)(Thread*, object))
|
||||
{
|
||||
bool weak = objectClass(t, map)
|
||||
== arrayBody(t, t->vm->types, Machine::WeakHashMapType);
|
||||
== arrayBody(t, t->m->types, Machine::WeakHashMapType);
|
||||
|
||||
object array = hashMapArray(t, map);
|
||||
PROTECT(t, array);
|
||||
@ -1958,8 +1970,8 @@ hashMapInsert(Thread* t, object map, object key, object value,
|
||||
|
||||
object r = makeWeakReference(t, 0, 0, 0, 0);
|
||||
jreferenceTarget(t, r) = key;
|
||||
jreferenceNext(t, r) = t->vm->weakReferences;
|
||||
key = t->vm->weakReferences = r;
|
||||
jreferenceNext(t, r) = t->m->weakReferences;
|
||||
key = t->m->weakReferences = r;
|
||||
}
|
||||
|
||||
object n = makeTriple(t, key, value, arrayBody(t, array, index));
|
||||
@ -1973,7 +1985,7 @@ hashMapRemove(Thread* t, object map, object key,
|
||||
bool (*equal)(Thread*, object, object))
|
||||
{
|
||||
bool weak = objectClass(t, map)
|
||||
== arrayBody(t, t->vm->types, Machine::WeakHashMapType);
|
||||
== arrayBody(t, t->m->types, Machine::WeakHashMapType);
|
||||
|
||||
object array = hashMapArray(t, map);
|
||||
object o = 0;
|
||||
@ -2004,26 +2016,6 @@ hashMapRemove(Thread* t, object map, object key,
|
||||
return o;
|
||||
}
|
||||
|
||||
object
|
||||
makeTrace(Thread* t, int frame)
|
||||
{
|
||||
unsigned count = 0;
|
||||
for (int f = frame; f >= 0; f = frameNext(t, f)) {
|
||||
++ count;
|
||||
}
|
||||
|
||||
object trace = makeArray(t, count, true);
|
||||
PROTECT(t, trace);
|
||||
|
||||
unsigned index = 0;
|
||||
for (int f = frame; f >= 0; f = frameNext(t, f)) {
|
||||
object e = makeTraceElement(t, frameMethod(t, f), frameIp(t, f));
|
||||
set(t, arrayBody(t, trace, index++), e);
|
||||
}
|
||||
|
||||
return trace;
|
||||
}
|
||||
|
||||
object
|
||||
hashMapIterator(Thread* t, object map)
|
||||
{
|
||||
@ -2186,9 +2178,9 @@ object
|
||||
findLoadedClass(Thread* t, object spec)
|
||||
{
|
||||
PROTECT(t, spec);
|
||||
ACQUIRE(t, t->vm->classLock);
|
||||
ACQUIRE(t, t->m->classLock);
|
||||
|
||||
return hashMapFind(t, systemClassLoaderMap(t, t->vm->loader),
|
||||
return hashMapFind(t, systemClassLoaderMap(t, t->m->loader),
|
||||
spec, byteArrayHash, byteArrayEqual);
|
||||
}
|
||||
|
||||
@ -2234,7 +2226,7 @@ parseClass(Thread* t, const uint8_t* data, unsigned size)
|
||||
0, // fields
|
||||
0, // methods
|
||||
0, // static table
|
||||
t->vm->loader);
|
||||
t->m->loader);
|
||||
PROTECT(t, class_);
|
||||
|
||||
unsigned super = s.read2();
|
||||
@ -2264,14 +2256,14 @@ object
|
||||
resolveClass(Thread* t, object spec)
|
||||
{
|
||||
PROTECT(t, spec);
|
||||
ACQUIRE(t, t->vm->classLock);
|
||||
ACQUIRE(t, t->m->classLock);
|
||||
|
||||
object class_ = hashMapFind(t, systemClassLoaderMap(t, t->vm->loader),
|
||||
object class_ = hashMapFind(t, systemClassLoaderMap(t, t->m->loader),
|
||||
spec, byteArrayHash, byteArrayEqual);
|
||||
if (class_ == 0) {
|
||||
if (byteArrayBody(t, spec, 0) == '[') {
|
||||
class_ = hashMapFind
|
||||
(t, t->vm->bootstrapClassMap, spec, byteArrayHash, byteArrayEqual);
|
||||
(t, t->m->bootstrapClassMap, spec, byteArrayHash, byteArrayEqual);
|
||||
|
||||
if (class_ == 0) {
|
||||
class_ = makeArrayClass(t, spec);
|
||||
@ -2281,7 +2273,7 @@ resolveClass(Thread* t, object spec)
|
||||
memcpy(file, &byteArrayBody(t, spec, 0), byteArrayLength(t, spec) - 1);
|
||||
memcpy(file + byteArrayLength(t, spec) - 1, ".class", 7);
|
||||
|
||||
System::Region* region = t->vm->finder->find(file);
|
||||
System::Region* region = t->m->finder->find(file);
|
||||
|
||||
if (region) {
|
||||
if (Verbose) {
|
||||
@ -2298,7 +2290,7 @@ resolveClass(Thread* t, object spec)
|
||||
}
|
||||
|
||||
object bootstrapClass = hashMapFind
|
||||
(t, t->vm->bootstrapClassMap, spec, byteArrayHash, byteArrayEqual);
|
||||
(t, t->m->bootstrapClassMap, spec, byteArrayHash, byteArrayEqual);
|
||||
|
||||
if (bootstrapClass) {
|
||||
PROTECT(t, bootstrapClass);
|
||||
@ -2313,7 +2305,7 @@ resolveClass(Thread* t, object spec)
|
||||
if (class_) {
|
||||
PROTECT(t, class_);
|
||||
|
||||
hashMapInsert(t, systemClassLoaderMap(t, t->vm->loader),
|
||||
hashMapInsert(t, systemClassLoaderMap(t, t->m->loader),
|
||||
spec, class_, byteArrayHash);
|
||||
} else if (t->exception == 0) {
|
||||
object message = makeString(t, "%s", &byteArrayBody(t, spec, 0));
|
||||
@ -2324,6 +2316,27 @@ resolveClass(Thread* t, object spec)
|
||||
return class_;
|
||||
}
|
||||
|
||||
object
|
||||
resolveMethod(Thread* t, const char* className, const char* methodName,
|
||||
const char* methodSpec)
|
||||
{
|
||||
object class_ = resolveClass(t, makeByteArray(t, "%s", className));
|
||||
if (LIKELY(t->exception == 0)) {
|
||||
PROTECT(t, class_);
|
||||
|
||||
object name = makeByteArray(t, methodName);
|
||||
PROTECT(t, name);
|
||||
|
||||
object spec = makeByteArray(t, methodSpec);
|
||||
object reference = makeReference(t, class_, name, spec);
|
||||
|
||||
return findMethodInClass(t, class_, referenceName(t, reference),
|
||||
referenceSpec(t, reference));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
object
|
||||
resolveObjectArrayClass(Thread* t, object elementSpec)
|
||||
{
|
||||
@ -2444,18 +2457,18 @@ addFinalizer(Thread* t, object target, void (*finalize)(Thread*, object))
|
||||
{
|
||||
PROTECT(t, target);
|
||||
|
||||
ACQUIRE(t, t->vm->referenceLock);
|
||||
ACQUIRE(t, t->m->referenceLock);
|
||||
|
||||
object f = makeFinalizer(t, 0, reinterpret_cast<void*>(finalize), 0);
|
||||
finalizerTarget(t, f) = target;
|
||||
finalizerNext(t, f) = t->vm->finalizers;
|
||||
t->vm->finalizers = f;
|
||||
finalizerNext(t, f) = t->m->finalizers;
|
||||
t->m->finalizers = f;
|
||||
}
|
||||
|
||||
System::Monitor*
|
||||
objectMonitor(Thread* t, object o)
|
||||
{
|
||||
object p = hashMapFind(t, t->vm->monitorMap, o, objectHash, objectEqual);
|
||||
object p = hashMapFind(t, t->m->monitorMap, o, objectHash, objectEqual);
|
||||
|
||||
if (p) {
|
||||
if (DebugMonitors) {
|
||||
@ -2471,8 +2484,8 @@ objectMonitor(Thread* t, object o)
|
||||
ENTER(t, Thread::ExclusiveState);
|
||||
|
||||
System::Monitor* m;
|
||||
System::Status s = t->vm->system->make(&m);
|
||||
expect(t, t->vm->system->success(s));
|
||||
System::Status s = t->m->system->make(&m);
|
||||
expect(t, t->m->system->success(s));
|
||||
|
||||
if (DebugMonitors) {
|
||||
fprintf(stderr, "made monitor %p for object %x\n",
|
||||
@ -2481,7 +2494,7 @@ objectMonitor(Thread* t, object o)
|
||||
}
|
||||
|
||||
p = makePointer(t, m);
|
||||
hashMapInsert(t, t->vm->monitorMap, o, p, objectHash);
|
||||
hashMapInsert(t, t->m->monitorMap, o, p, objectHash);
|
||||
|
||||
addFinalizer(t, o, removeMonitor);
|
||||
|
||||
@ -2494,13 +2507,13 @@ intern(Thread* t, object s)
|
||||
{
|
||||
PROTECT(t, s);
|
||||
|
||||
ACQUIRE(t, t->vm->referenceLock);
|
||||
ACQUIRE(t, t->m->referenceLock);
|
||||
|
||||
object n = hashMapFindNode(t, t->vm->stringMap, s, stringHash, stringEqual);
|
||||
object n = hashMapFindNode(t, t->m->stringMap, s, stringHash, stringEqual);
|
||||
if (n) {
|
||||
return jreferenceTarget(t, tripleFirst(t, n));
|
||||
} else {
|
||||
hashMapInsert(t, t->vm->stringMap, s, 0, stringHash);
|
||||
hashMapInsert(t, t->m->stringMap, s, 0, stringHash);
|
||||
addFinalizer(t, s, removeString);
|
||||
return s;
|
||||
}
|
||||
@ -2509,7 +2522,7 @@ intern(Thread* t, object s)
|
||||
void
|
||||
collect(Thread* t, Heap::CollectionType type)
|
||||
{
|
||||
Machine* m = t->vm;
|
||||
Machine* m = t->m;
|
||||
|
||||
class Client: public Heap::Client {
|
||||
public:
|
||||
@ -2716,6 +2729,50 @@ printTrace(Thread* t, object exception)
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
run(System* system, Heap* heap, Finder* finder, Processor* processor,
|
||||
const char* className, int argc, const char** argv)
|
||||
{
|
||||
Machine m(system, heap, finder, processor);
|
||||
Thread* t = processor->makeThread(&m, 0, 0);
|
||||
|
||||
enter(t, Thread::ActiveState);
|
||||
|
||||
::invoke(t, className, argc, argv);
|
||||
|
||||
int exitCode = 0;
|
||||
if (t->exception) {
|
||||
exitCode = -1;
|
||||
printTrace(t, t->exception);
|
||||
}
|
||||
|
||||
exit(t);
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
object
|
||||
makeTrace(Thread* t, FrameIterator* it)
|
||||
{
|
||||
unsigned count = 0;
|
||||
FrameIterator copy(it);
|
||||
while (copy.valid()) {
|
||||
++ count;
|
||||
t->m->processor->next(t, ©);
|
||||
}
|
||||
|
||||
object trace = makeArray(t, count, true);
|
||||
PROTECT(t, trace);
|
||||
|
||||
unsigned index = 0;
|
||||
while (it->valid()) {
|
||||
object e = makeTraceElement(t, it->method, it->ip);
|
||||
set(t, arrayBody(t, trace, index++), e);
|
||||
}
|
||||
|
||||
return trace;
|
||||
}
|
||||
|
||||
void
|
||||
noop()
|
||||
{ }
|
||||
|
351
src/machine.h
351
src/machine.h
@ -5,6 +5,7 @@
|
||||
#include "system.h"
|
||||
#include "heap.h"
|
||||
#include "finder.h"
|
||||
#include "processor.h"
|
||||
|
||||
#define JNICALL
|
||||
|
||||
@ -65,13 +66,6 @@ const unsigned PrimitiveFlag = 1 << 4;
|
||||
// method flags:
|
||||
const unsigned ClassInitFlag = 1 << 0;
|
||||
|
||||
class Machine;
|
||||
class Thread;
|
||||
|
||||
struct Object { };
|
||||
|
||||
typedef Object* object;
|
||||
|
||||
typedef Machine JavaVM;
|
||||
typedef Thread JNIEnv;
|
||||
|
||||
@ -1101,7 +1095,7 @@ class Machine {
|
||||
#include "type-enums.cpp"
|
||||
};
|
||||
|
||||
Machine(System* system, Heap* heap, Finder* finder);
|
||||
Machine(System* system, Heap* heap, Finder* finder, Processor* processor);
|
||||
|
||||
~Machine() {
|
||||
dispose();
|
||||
@ -1115,6 +1109,7 @@ class Machine {
|
||||
System* system;
|
||||
Heap* heap;
|
||||
Finder* finder;
|
||||
Processor* processor;
|
||||
Thread* rootThread;
|
||||
Thread* exclusive;
|
||||
Reference* jniReferences;
|
||||
@ -1144,13 +1139,6 @@ class Machine {
|
||||
unsigned heapPoolIndex;
|
||||
};
|
||||
|
||||
object
|
||||
run(Thread* t, object method, object this_, ...);
|
||||
|
||||
object
|
||||
run(Thread* t, const char* className, const char* methodName,
|
||||
const char* methodSpec, object this_, ...);
|
||||
|
||||
void
|
||||
printTrace(Thread* t, object exception);
|
||||
|
||||
@ -1193,9 +1181,10 @@ class Thread {
|
||||
}
|
||||
|
||||
virtual void run() {
|
||||
t->vm->localThread->set(t);
|
||||
t->m->localThread->set(t);
|
||||
|
||||
vm::run(t, "java/lang/Thread", "run", "()V", t->javaThread);
|
||||
t->m->processor->invoke
|
||||
(t, "java/lang/Thread", "run", "()V", t->javaThread);
|
||||
|
||||
if (t->exception) {
|
||||
printTrace(t, t->exception);
|
||||
@ -1216,10 +1205,7 @@ class Thread {
|
||||
};
|
||||
|
||||
static const unsigned HeapSizeInBytes = 64 * 1024;
|
||||
static const unsigned StackSizeInBytes = 64 * 1024;
|
||||
|
||||
static const unsigned HeapSizeInWords = HeapSizeInBytes / BytesPerWord;
|
||||
static const unsigned StackSizeInWords = StackSizeInBytes / BytesPerWord;
|
||||
|
||||
Thread(Machine* m, object javaThread, Thread* parent);
|
||||
|
||||
@ -1227,7 +1213,7 @@ class Thread {
|
||||
void dispose();
|
||||
|
||||
JNIEnvVTable* vtable;
|
||||
Machine* vm;
|
||||
Machine* m;
|
||||
Thread* parent;
|
||||
Thread* peer;
|
||||
Thread* child;
|
||||
@ -1235,12 +1221,8 @@ class Thread {
|
||||
unsigned criticalLevel;
|
||||
System::Thread* systemThread;
|
||||
object javaThread;
|
||||
object code;
|
||||
object exception;
|
||||
object large;
|
||||
unsigned ip;
|
||||
unsigned sp;
|
||||
int frame;
|
||||
unsigned heapIndex;
|
||||
unsigned heapOffset;
|
||||
Protector* protector;
|
||||
@ -1253,7 +1235,6 @@ class Thread {
|
||||
uintptr_t* heap;
|
||||
uintptr_t defaultHeap[HeapSizeInWords];
|
||||
#endif // not VM_STRESS
|
||||
uintptr_t stack[StackSizeInWords];
|
||||
};
|
||||
|
||||
inline object
|
||||
@ -1362,27 +1343,27 @@ class RawMonitorResource {
|
||||
inline void NO_RETURN
|
||||
abort(Thread* t)
|
||||
{
|
||||
abort(t->vm->system);
|
||||
abort(t->m->system);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
inline void
|
||||
assert(Thread* t, bool v)
|
||||
{
|
||||
assert(t->vm->system, v);
|
||||
assert(t->m->system, v);
|
||||
}
|
||||
#endif // not NDEBUG
|
||||
|
||||
inline void
|
||||
expect(Thread* t, bool v)
|
||||
{
|
||||
expect(t->vm->system, v);
|
||||
expect(t->m->system, v);
|
||||
}
|
||||
|
||||
inline object
|
||||
allocateLarge(Thread* t, unsigned sizeInBytes)
|
||||
{
|
||||
return t->large = static_cast<object>(t->vm->system->allocate(sizeInBytes));
|
||||
return t->large = static_cast<object>(t->m->system->allocate(sizeInBytes));
|
||||
}
|
||||
|
||||
inline object
|
||||
@ -1403,7 +1384,7 @@ allocate(Thread* t, unsigned sizeInBytes)
|
||||
|
||||
if (UNLIKELY(t->heapIndex + ceiling(sizeInBytes, BytesPerWord)
|
||||
>= Thread::HeapSizeInWords
|
||||
or t->vm->exclusive))
|
||||
or t->m->exclusive))
|
||||
{
|
||||
return allocate2(t, sizeInBytes);
|
||||
} else {
|
||||
@ -1414,9 +1395,9 @@ allocate(Thread* t, unsigned sizeInBytes)
|
||||
inline void
|
||||
mark(Thread* t, object& target)
|
||||
{
|
||||
if (t->vm->heap->needsMark(reinterpret_cast<void**>(&target))) {
|
||||
ACQUIRE_RAW(t, t->vm->heapLock);
|
||||
t->vm->heap->mark(reinterpret_cast<void**>(&target));
|
||||
if (t->m->heap->needsMark(reinterpret_cast<void**>(&target))) {
|
||||
ACQUIRE_RAW(t, t->m->heapLock);
|
||||
t->m->heap->mark(reinterpret_cast<void**>(&target));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1442,10 +1423,14 @@ arrayBodyUnsafe(Thread*, object, unsigned);
|
||||
#include "type-declarations.cpp"
|
||||
|
||||
object
|
||||
makeTrace(Thread* t, int frame);
|
||||
makeTrace(Thread* t, FrameIterator* it);
|
||||
|
||||
object
|
||||
makeTrace(Thread* t);
|
||||
inline object
|
||||
makeTrace(Thread* t)
|
||||
{
|
||||
FrameIterator it; t->m->processor->start(t, &it);
|
||||
return makeTrace(t, &it);
|
||||
}
|
||||
|
||||
inline object
|
||||
makeRuntimeException(Thread* t, object message)
|
||||
@ -1595,268 +1580,6 @@ classInitializer(Thread* t, object class_);
|
||||
object
|
||||
frameMethod(Thread* t, int frame);
|
||||
|
||||
inline void
|
||||
pushObject(Thread* t, object o)
|
||||
{
|
||||
if (DebugStack) {
|
||||
fprintf(stderr, "push object %p at %d\n", o, t->sp);
|
||||
}
|
||||
|
||||
assert(t, t->sp + 1 < Thread::StackSizeInWords / 2);
|
||||
t->stack[(t->sp * 2) ] = ObjectTag;
|
||||
t->stack[(t->sp * 2) + 1] = reinterpret_cast<uintptr_t>(o);
|
||||
++ t->sp;
|
||||
}
|
||||
|
||||
inline void
|
||||
pushInt(Thread* t, uint32_t v)
|
||||
{
|
||||
if (DebugStack) {
|
||||
fprintf(stderr, "push int %d at %d\n", v, t->sp);
|
||||
}
|
||||
|
||||
assert(t, t->sp + 1 < Thread::StackSizeInWords / 2);
|
||||
t->stack[(t->sp * 2) ] = IntTag;
|
||||
t->stack[(t->sp * 2) + 1] = v;
|
||||
++ t->sp;
|
||||
}
|
||||
|
||||
inline void
|
||||
pushFloat(Thread* t, float v)
|
||||
{
|
||||
uint32_t a; memcpy(&a, &v, sizeof(uint32_t));
|
||||
pushInt(t, a);
|
||||
}
|
||||
|
||||
inline void
|
||||
pushLong(Thread* t, uint64_t v)
|
||||
{
|
||||
if (DebugStack) {
|
||||
fprintf(stderr, "push long %"LLD" at %d\n", v, t->sp);
|
||||
}
|
||||
|
||||
pushInt(t, v >> 32);
|
||||
pushInt(t, v & 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
inline void
|
||||
pushDouble(Thread* t, double v)
|
||||
{
|
||||
uint64_t a; memcpy(&a, &v, sizeof(uint64_t));
|
||||
pushLong(t, a);
|
||||
}
|
||||
|
||||
inline object
|
||||
popObject(Thread* t)
|
||||
{
|
||||
if (DebugStack) {
|
||||
fprintf(stderr, "pop object %p at %d\n",
|
||||
reinterpret_cast<object>(t->stack[((t->sp - 1) * 2) + 1]),
|
||||
t->sp - 1);
|
||||
}
|
||||
|
||||
assert(t, t->stack[(t->sp - 1) * 2] == ObjectTag);
|
||||
return reinterpret_cast<object>(t->stack[((-- t->sp) * 2) + 1]);
|
||||
}
|
||||
|
||||
inline uint32_t
|
||||
popInt(Thread* t)
|
||||
{
|
||||
if (DebugStack) {
|
||||
fprintf(stderr, "pop int %"ULD" at %d\n",
|
||||
t->stack[((t->sp - 1) * 2) + 1],
|
||||
t->sp - 1);
|
||||
}
|
||||
|
||||
assert(t, t->stack[(t->sp - 1) * 2] == IntTag);
|
||||
return t->stack[((-- t->sp) * 2) + 1];
|
||||
}
|
||||
|
||||
inline float
|
||||
popFloat(Thread* t)
|
||||
{
|
||||
uint32_t a = popInt(t);
|
||||
float f; memcpy(&f, &a, sizeof(float));
|
||||
return f;
|
||||
}
|
||||
|
||||
inline uint64_t
|
||||
popLong(Thread* t)
|
||||
{
|
||||
if (DebugStack) {
|
||||
fprintf(stderr, "pop long %"LLD" at %d\n",
|
||||
(static_cast<uint64_t>(t->stack[((t->sp - 2) * 2) + 1]) << 32)
|
||||
| static_cast<uint64_t>(t->stack[((t->sp - 1) * 2) + 1]),
|
||||
t->sp - 2);
|
||||
}
|
||||
|
||||
uint64_t a = popInt(t);
|
||||
uint64_t b = popInt(t);
|
||||
return (b << 32) | a;
|
||||
}
|
||||
|
||||
inline float
|
||||
popDouble(Thread* t)
|
||||
{
|
||||
uint64_t a = popLong(t);
|
||||
double d; memcpy(&d, &a, sizeof(double));
|
||||
return d;
|
||||
}
|
||||
|
||||
inline object
|
||||
peekObject(Thread* t, unsigned index)
|
||||
{
|
||||
if (DebugStack) {
|
||||
fprintf(stderr, "peek object %p at %d\n",
|
||||
reinterpret_cast<object>(t->stack[(index * 2) + 1]),
|
||||
index);
|
||||
}
|
||||
|
||||
assert(t, index < Thread::StackSizeInWords / 2);
|
||||
assert(t, t->stack[index * 2] == ObjectTag);
|
||||
return *reinterpret_cast<object*>(t->stack + (index * 2) + 1);
|
||||
}
|
||||
|
||||
inline uint32_t
|
||||
peekInt(Thread* t, unsigned index)
|
||||
{
|
||||
if (DebugStack) {
|
||||
fprintf(stderr, "peek int %"ULD" at %d\n",
|
||||
t->stack[(index * 2) + 1],
|
||||
index);
|
||||
}
|
||||
|
||||
assert(t, index < Thread::StackSizeInWords / 2);
|
||||
assert(t, t->stack[index * 2] == IntTag);
|
||||
return t->stack[(index * 2) + 1];
|
||||
}
|
||||
|
||||
inline uint64_t
|
||||
peekLong(Thread* t, unsigned index)
|
||||
{
|
||||
if (DebugStack) {
|
||||
fprintf(stderr, "peek long %"LLD" at %d\n",
|
||||
(static_cast<uint64_t>(t->stack[(index * 2) + 1]) << 32)
|
||||
| static_cast<uint64_t>(t->stack[((index + 1) * 2) + 1]),
|
||||
index);
|
||||
}
|
||||
|
||||
return (static_cast<uint64_t>(peekInt(t, index)) << 32)
|
||||
| static_cast<uint64_t>(peekInt(t, index + 1));
|
||||
}
|
||||
|
||||
inline void
|
||||
pokeObject(Thread* t, unsigned index, object value)
|
||||
{
|
||||
if (DebugStack) {
|
||||
fprintf(stderr, "poke object %p at %d\n", value, index);
|
||||
}
|
||||
|
||||
t->stack[index * 2] = ObjectTag;
|
||||
t->stack[(index * 2) + 1] = reinterpret_cast<uintptr_t>(value);
|
||||
}
|
||||
|
||||
inline void
|
||||
pokeInt(Thread* t, unsigned index, uint32_t value)
|
||||
{
|
||||
if (DebugStack) {
|
||||
fprintf(stderr, "poke int %d at %d\n", value, index);
|
||||
}
|
||||
|
||||
t->stack[index * 2] = IntTag;
|
||||
t->stack[(index * 2) + 1] = value;
|
||||
}
|
||||
|
||||
inline void
|
||||
pokeLong(Thread* t, unsigned index, uint64_t value)
|
||||
{
|
||||
if (DebugStack) {
|
||||
fprintf(stderr, "poke long %"LLD" at %d\n", value, index);
|
||||
}
|
||||
|
||||
pokeInt(t, index, value >> 32);
|
||||
pokeInt(t, index + 1, value & 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
inline object*
|
||||
pushReference(Thread* t, object o)
|
||||
{
|
||||
if (o) {
|
||||
expect(t, t->sp + 1 < Thread::StackSizeInWords / 2);
|
||||
pushObject(t, o);
|
||||
return reinterpret_cast<object*>(t->stack + ((t->sp - 1) * 2) + 1);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline int
|
||||
frameNext(Thread* t, int frame)
|
||||
{
|
||||
return peekInt(t, frame + FrameNextOffset);
|
||||
}
|
||||
|
||||
inline object
|
||||
frameMethod(Thread* t, int frame)
|
||||
{
|
||||
return peekObject(t, frame + FrameMethodOffset);
|
||||
}
|
||||
|
||||
inline unsigned
|
||||
frameIp(Thread* t, int frame)
|
||||
{
|
||||
return peekInt(t, frame + FrameIpOffset);
|
||||
}
|
||||
|
||||
inline unsigned
|
||||
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)
|
||||
{
|
||||
pokeInt(t, t->frame + FrameIpOffset, t->ip);
|
||||
return makeTrace(t, t->frame);
|
||||
}
|
||||
|
||||
inline unsigned
|
||||
baseSize(Thread* t, object o, object class_)
|
||||
{
|
||||
@ -1897,8 +1620,8 @@ markHashTaken(Thread* t, object o)
|
||||
assert(t, not objectExtended(t, o));
|
||||
cast<uintptr_t>(o, 0) |= HashTakenMark;
|
||||
|
||||
ACQUIRE_RAW(t, t->vm->heapLock);
|
||||
t->vm->heap->pad(o, 1);
|
||||
ACQUIRE_RAW(t, t->m->heapLock);
|
||||
t->m->heap->pad(o, 1);
|
||||
}
|
||||
|
||||
inline uint32_t
|
||||
@ -1951,7 +1674,7 @@ stringHash(Thread* t, object s)
|
||||
if (stringHashCode(t, s) == 0 and stringLength(t, s)) {
|
||||
object data = stringData(t, s);
|
||||
if (objectClass(t, data)
|
||||
== arrayBody(t, t->vm->types, Machine::ByteArrayType))
|
||||
== arrayBody(t, t->m->types, Machine::ByteArrayType))
|
||||
{
|
||||
stringHashCode(t, s) = hash
|
||||
(&byteArrayBody(t, data, stringOffset(t, s)), stringLength(t, s));
|
||||
@ -1968,7 +1691,7 @@ stringCharAt(Thread* t, object s, int i)
|
||||
{
|
||||
object data = stringData(t, s);
|
||||
if (objectClass(t, data)
|
||||
== arrayBody(t, t->vm->types, Machine::ByteArrayType))
|
||||
== arrayBody(t, t->m->types, Machine::ByteArrayType))
|
||||
{
|
||||
return byteArrayBody(t, data, i);
|
||||
} else {
|
||||
@ -2114,6 +1837,10 @@ parseClass(Thread* t, const uint8_t* data, unsigned length);
|
||||
object
|
||||
resolveClass(Thread* t, object spec);
|
||||
|
||||
object
|
||||
resolveMethod(Thread* t, const char* className, const char* methodName,
|
||||
const char* methodSpec);
|
||||
|
||||
object
|
||||
resolveObjectArrayClass(Thread* t, object elementSpec);
|
||||
|
||||
@ -2122,14 +1849,14 @@ initClass(Thread* t, object c)
|
||||
{
|
||||
PROTECT(t, c);
|
||||
|
||||
acquire(t, t->vm->classLock);
|
||||
acquire(t, t->m->classLock);
|
||||
if (classVmFlags(t, c) & NeedInitFlag
|
||||
and (classVmFlags(t, c) & InitFlag) == 0)
|
||||
{
|
||||
classVmFlags(t, c) |= InitFlag;
|
||||
run(t, classInitializer(t, c), 0);
|
||||
t->m->processor->invoke(t, classInitializer(t, c), 0);
|
||||
} else {
|
||||
release(t, t->vm->classLock);
|
||||
release(t, t->m->classLock);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2189,7 +1916,7 @@ objectArrayBody(Thread* t UNUSED, object array, unsigned index)
|
||||
assert(t, classArrayElementSize(t, objectClass(t, array)) == BytesPerWord);
|
||||
assert(t, classObjectMask(t, objectClass(t, array))
|
||||
== classObjectMask(t, arrayBody
|
||||
(t, t->vm->types, Machine::ArrayType)));
|
||||
(t, t->m->types, Machine::ArrayType)));
|
||||
return cast<object>(array, (2 + index) * BytesPerWord);
|
||||
}
|
||||
|
||||
@ -2323,6 +2050,16 @@ intern(Thread* t, object s);
|
||||
void
|
||||
exit(Thread* t);
|
||||
|
||||
int
|
||||
run(System* system, Heap* heap, Finder* finder, Processor* processor,
|
||||
const char* className, int argc, const char** argv);
|
||||
|
||||
jobject
|
||||
makeLocalReference(Thread* t, object o);
|
||||
|
||||
void
|
||||
disposeLocalReference(Thread* t, jobject r);
|
||||
|
||||
} // namespace vm
|
||||
|
||||
#endif//MACHINE_H
|
||||
|
@ -2,7 +2,8 @@
|
||||
#include "system.h"
|
||||
#include "heap.h"
|
||||
#include "finder.h"
|
||||
#include "run.h"
|
||||
#include "processor.h"
|
||||
#include "machine.h"
|
||||
|
||||
using namespace vm;
|
||||
|
||||
@ -15,9 +16,11 @@ run(unsigned heapSize, const char* path, const char* class_, int argc,
|
||||
System* s = makeSystem(heapSize);
|
||||
Finder* f = makeFinder(s, path);
|
||||
Heap* heap = makeHeap(s);
|
||||
Processor* p = makeProcessor(s);
|
||||
|
||||
int exitCode = run(s, heap, f, class_, argc, argv);
|
||||
int exitCode = run(s, heap, f, p, class_, argc, argv);
|
||||
|
||||
p->dispose();
|
||||
heap->dispose();
|
||||
f->dispose();
|
||||
s->dispose();
|
||||
|
96
src/processor.h
Normal file
96
src/processor.h
Normal file
@ -0,0 +1,96 @@
|
||||
#ifndef PROCESSOR_H
|
||||
#define PROCESSOR_H
|
||||
|
||||
#include "common.h"
|
||||
#include "system.h"
|
||||
#include "heap.h"
|
||||
|
||||
namespace vm {
|
||||
|
||||
class FrameIterator {
|
||||
public:
|
||||
FrameIterator():
|
||||
base(0),
|
||||
method(0),
|
||||
ip(0)
|
||||
{ }
|
||||
|
||||
FrameIterator(FrameIterator* it):
|
||||
base(it->base),
|
||||
method(it->method),
|
||||
ip(it->ip)
|
||||
{ }
|
||||
|
||||
bool valid() {
|
||||
return base != 0;
|
||||
}
|
||||
|
||||
uintptr_t base;
|
||||
object method;
|
||||
unsigned ip;
|
||||
};
|
||||
|
||||
class Processor {
|
||||
public:
|
||||
virtual ~Processor() { }
|
||||
|
||||
virtual Thread*
|
||||
makeThread(Machine* m, object javaThread, Thread* parent) = 0;
|
||||
|
||||
virtual void
|
||||
visitObjects(Thread* t, Heap::Visitor* v) = 0;
|
||||
|
||||
virtual void
|
||||
start(Thread* t, FrameIterator* it) = 0;
|
||||
|
||||
virtual void
|
||||
next(Thread* t, FrameIterator* it) = 0;
|
||||
|
||||
virtual object
|
||||
invokeArray(Thread* t, object method, object this_, object arguments) = 0;
|
||||
|
||||
virtual object
|
||||
invokeList(Thread* t, object method, object this_, bool indirectObjects,
|
||||
va_list arguments) = 0;
|
||||
|
||||
virtual object
|
||||
invokeList(Thread* t, const char* className, const char* methodName,
|
||||
const char* methodSpec, object this_, va_list arguments) = 0;
|
||||
|
||||
virtual void
|
||||
dispose() = 0;
|
||||
|
||||
object
|
||||
invoke(Thread* t, object method, object this_, ...)
|
||||
{
|
||||
va_list a;
|
||||
va_start(a, this_);
|
||||
|
||||
object r = invokeList(t, method, this_, false, a);
|
||||
|
||||
va_end(a);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
object
|
||||
invoke(Thread* t, const char* className, const char* methodName,
|
||||
const char* methodSpec, object this_, ...)
|
||||
{
|
||||
va_list a;
|
||||
va_start(a, this_);
|
||||
|
||||
object r = invokeList(t, className, methodName, methodSpec, this_, a);
|
||||
|
||||
va_end(a);
|
||||
|
||||
return r;
|
||||
}
|
||||
};
|
||||
|
||||
Processor*
|
||||
makeProcessor(System* system);
|
||||
|
||||
} // namespace vm
|
||||
|
||||
#endif//PROCESSOR_H
|
30
src/run.h
30
src/run.h
@ -1,30 +0,0 @@
|
||||
#ifndef RUN_H
|
||||
#define RUN_H
|
||||
|
||||
#include "system.h"
|
||||
#include "heap.h"
|
||||
#include "finder.h"
|
||||
#include "machine.h"
|
||||
|
||||
namespace vm {
|
||||
|
||||
object
|
||||
runv(Thread* t, object method, object this_, bool indirectObjects, va_list a);
|
||||
|
||||
object
|
||||
run(Thread* t, object method, object this_, ...);
|
||||
|
||||
object
|
||||
run2(Thread* t, object method, object this_, object arguments);
|
||||
|
||||
object
|
||||
run(Thread* t, const char* className, const char* methodName,
|
||||
const char* methodSpec, object this_, ...);
|
||||
|
||||
int
|
||||
run(System* sys, Heap* heap, Finder* finder,
|
||||
const char* className, int argc, const char** argv);
|
||||
|
||||
} // namespace vm
|
||||
|
||||
#endif//RUN_H
|
@ -1022,7 +1022,7 @@ writeSubtypeAssertions(Output* out, Object* o)
|
||||
for (Object* p = typeSubtypes(o); p; p = cdr(p)) {
|
||||
Object* st = car(p);
|
||||
out->write(" or objectClass(t, o) == arrayBodyUnsafe");
|
||||
out->write("(t, t->vm->types, Machine::");
|
||||
out->write("(t, t->m->types, Machine::");
|
||||
out->write(capitalize(typeName(st)));
|
||||
out->write("Type)");
|
||||
writeSubtypeAssertions(out, st);
|
||||
@ -1061,9 +1061,9 @@ writeAccessor(Output* out, Object* member, Object* offset, bool unsafe = false)
|
||||
if (unsafe) {
|
||||
out->write(" assert(t, true);");
|
||||
} else {
|
||||
out->write(" assert(t, t->vm->unsafe or ");
|
||||
out->write(" assert(t, t->m->unsafe or ");
|
||||
out->write("objectClass(t, o) == arrayBodyUnsafe");
|
||||
out->write("(t, t->vm->types, Machine::");
|
||||
out->write("(t, t->m->types, Machine::");
|
||||
out->write(capitalize(::typeName(memberOwner(member))));
|
||||
out->write("Type)");
|
||||
writeSubtypeAssertions(out, memberOwner(member));
|
||||
@ -1347,7 +1347,7 @@ writeConstructors(Output* out, Object* declarations)
|
||||
out->write(");\n");
|
||||
|
||||
out->write(" cast<object>(o, 0) ");
|
||||
out->write("= arrayBody(t, t->vm->types, Machine::");
|
||||
out->write("= arrayBody(t, t->m->types, Machine::");
|
||||
out->write(capitalize(typeName(o)));
|
||||
out->write("Type);\n");
|
||||
|
||||
@ -1502,7 +1502,7 @@ writeInitialization(Output* out, Object* type)
|
||||
}
|
||||
|
||||
if (typeJavaName(type) and typeSuper(type)) {
|
||||
out->write(" object super = arrayBody(t, t->vm->types, Machine::");
|
||||
out->write(" object super = arrayBody(t, t->m->types, Machine::");
|
||||
out->write(capitalize(typeName(typeSuper(type))));
|
||||
out->write("Type);\n");
|
||||
} else {
|
||||
@ -1514,9 +1514,9 @@ writeInitialization(Output* out, Object* type)
|
||||
out->write(typeFixedSize(type));
|
||||
out->write(", ");
|
||||
out->write(typeArrayElementSize(type));
|
||||
out->write(", mask, 0, super, 0, 0, 0, 0, 0, t->vm->loader);\n");
|
||||
out->write(", mask, 0, super, 0, 0, 0, 0, 0, t->m->loader);\n");
|
||||
|
||||
out->write(" set(t, arrayBody(t, t->vm->types, Machine::");
|
||||
out->write(" set(t, arrayBody(t, t->m->types, Machine::");
|
||||
out->write(capitalize(typeName(type)));
|
||||
out->write("Type), class_);\n");
|
||||
|
||||
@ -1566,14 +1566,14 @@ writeInitializations(Output* out, Object* declarations)
|
||||
{
|
||||
unsigned count = typeCount(declarations);
|
||||
|
||||
out->write("t->vm->types = allocate(t, pad((");
|
||||
out->write("t->m->types = allocate(t, pad((");
|
||||
out->write(count);
|
||||
out->write(" * sizeof(void*)) + sizeof(uintptr_t) + sizeof(void*)));\n");
|
||||
out->write("cast<object>(t->vm->types, 0) = 0;\n");
|
||||
out->write("arrayLength(t, t->vm->types) = ");
|
||||
out->write("cast<object>(t->m->types, 0) = 0;\n");
|
||||
out->write("arrayLength(t, t->m->types) = ");
|
||||
out->write(count);
|
||||
out->write(";\n");
|
||||
out->write("memset(&arrayBody(t, t->vm->types, 0), 0, ");
|
||||
out->write("memset(&arrayBody(t, t->m->types, 0), 0, ");
|
||||
out->write(count);
|
||||
out->write(" * sizeof(void*));\n\n");
|
||||
|
||||
@ -1596,13 +1596,13 @@ writeJavaInitialization(Output* out, Object* type)
|
||||
out->write(typeJavaName(type));
|
||||
out->write("\");\n");
|
||||
|
||||
out->write(" object class_ = arrayBody(t, t->vm->types, Machine::");
|
||||
out->write(" object class_ = arrayBody(t, t->m->types, Machine::");
|
||||
out->write(capitalize(typeName(type)));
|
||||
out->write("Type);\n");
|
||||
|
||||
out->write(" set(t, className(t, class_), name);\n");
|
||||
|
||||
out->write(" hashMapInsert(t, t->vm->bootstrapClassMap, ");
|
||||
out->write(" hashMapInsert(t, t->m->bootstrapClassMap, ");
|
||||
out->write("name, class_, byteArrayHash);\n");
|
||||
|
||||
out->write("}\n\n");
|
||||
|
7
test/Instructions.java
Normal file
7
test/Instructions.java
Normal file
@ -0,0 +1,7 @@
|
||||
public class Instructions {
|
||||
public static void main(String[] args) {
|
||||
int a = 2;
|
||||
int b = 2;
|
||||
int c = a + b;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user