mirror of
https://github.com/corda/corda.git
synced 2025-01-19 11:16:54 +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)/system.h \
|
||||||
$(src)/heap.h \
|
$(src)/heap.h \
|
||||||
$(src)/finder.h \
|
$(src)/finder.h \
|
||||||
|
$(src)/processor.h \
|
||||||
$(src)/stream.h \
|
$(src)/stream.h \
|
||||||
$(src)/constants.h \
|
$(src)/constants.h \
|
||||||
$(src)/run.h \
|
|
||||||
$(src)/jnienv.h \
|
$(src)/jnienv.h \
|
||||||
$(src)/machine.h
|
$(src)/machine.h
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ interpreter-sources = \
|
|||||||
$(src)/finder.cpp \
|
$(src)/finder.cpp \
|
||||||
$(src)/machine.cpp \
|
$(src)/machine.cpp \
|
||||||
$(src)/heap.cpp \
|
$(src)/heap.cpp \
|
||||||
$(src)/run.cpp \
|
$(src)/interpret.cpp \
|
||||||
$(src)/builtin.cpp \
|
$(src)/builtin.cpp \
|
||||||
$(src)/jnienv.cpp \
|
$(src)/jnienv.cpp \
|
||||||
$(src)/main.cpp
|
$(src)/main.cpp
|
||||||
@ -151,7 +151,7 @@ flags = -cp $(cls)
|
|||||||
args = $(flags) $(call class-name,$(input))
|
args = $(flags) $(call class-name,$(input))
|
||||||
|
|
||||||
.PHONY: build
|
.PHONY: build
|
||||||
build: $(executable) $(classpath-objects)
|
build: $(executable) $(classpath-objects) $(test-classes)
|
||||||
|
|
||||||
$(input): $(classpath-objects)
|
$(input): $(classpath-objects)
|
||||||
|
|
||||||
|
105
src/builtin.cpp
105
src/builtin.cpp
@ -1,6 +1,6 @@
|
|||||||
#include "machine.h"
|
#include "machine.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "run.h"
|
#include "processor.h"
|
||||||
|
|
||||||
#undef JNIEXPORT
|
#undef JNIEXPORT
|
||||||
#define JNIEXPORT __attribute__ ((visibility("default")))
|
#define JNIEXPORT __attribute__ ((visibility("default")))
|
||||||
@ -33,7 +33,7 @@ search(Thread* t, jstring name, object (*op)(Thread*, object),
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return pushReference(t, r);
|
return makeLocalReference(t, r);
|
||||||
} else {
|
} else {
|
||||||
t->exception = makeNullPointerException(t);
|
t->exception = makeNullPointerException(t);
|
||||||
return 0;
|
return 0;
|
||||||
@ -53,7 +53,7 @@ Java_java_lang_Object_toString(Thread* t, jobject this_)
|
|||||||
&byteArrayBody(t, className(t, objectClass(t, *this_)), 0),
|
&byteArrayBody(t, className(t, objectClass(t, *this_)), 0),
|
||||||
hash);
|
hash);
|
||||||
|
|
||||||
return pushReference(t, s);
|
return makeLocalReference(t, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jclass JNICALL
|
extern "C" JNIEXPORT jclass JNICALL
|
||||||
@ -61,7 +61,7 @@ Java_java_lang_Object_getClass(Thread* t, jobject this_)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
return pushReference(t, objectClass(t, *this_));
|
return makeLocalReference(t, objectClass(t, *this_));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
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,
|
memcpy(reinterpret_cast<void**>(clone) + 1,
|
||||||
reinterpret_cast<void**>(*o) + 1,
|
reinterpret_cast<void**>(*o) + 1,
|
||||||
(baseSize(t, *o, objectClass(t, *o)) - 1) * BytesPerWord);
|
(baseSize(t, *o, objectClass(t, *o)) - 1) * BytesPerWord);
|
||||||
return pushReference(t, clone);
|
return makeLocalReference(t, clone);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jclass JNICALL
|
extern "C" JNIEXPORT jclass JNICALL
|
||||||
@ -114,11 +114,11 @@ Java_java_lang_ClassLoader_defineClass
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
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);
|
memcpy(buffer, &byteArrayBody(t, *b, offset), length);
|
||||||
object c = parseClass(t, buffer, length);
|
object c = parseClass(t, buffer, length);
|
||||||
t->vm->system->free(buffer);
|
t->m->system->free(buffer);
|
||||||
return pushReference(t, c);
|
return makeLocalReference(t, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jclass JNICALL
|
extern "C" JNIEXPORT jclass JNICALL
|
||||||
@ -147,7 +147,7 @@ Java_java_lang_SystemClassLoader_resourceExists
|
|||||||
if (LIKELY(name)) {
|
if (LIKELY(name)) {
|
||||||
char n[stringLength(t, *name) + 1];
|
char n[stringLength(t, *name) + 1];
|
||||||
stringChars(t, *name, n);
|
stringChars(t, *name, n);
|
||||||
return t->vm->finder->exists(n);
|
return t->m->finder->exists(n);
|
||||||
} else {
|
} else {
|
||||||
t->exception = makeNullPointerException(t);
|
t->exception = makeNullPointerException(t);
|
||||||
return 0;
|
return 0;
|
||||||
@ -159,7 +159,7 @@ Java_java_io_ObjectInputStream_makeInstance(Thread* t, jclass, jclass c)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
return pushReference(t, make(t, *c));
|
return makeLocalReference(t, make(t, *c));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jclass JNICALL
|
extern "C" JNIEXPORT jclass JNICALL
|
||||||
@ -169,23 +169,23 @@ Java_java_lang_Class_primitiveClass(Thread* t, jclass, jchar name)
|
|||||||
|
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case 'B':
|
case 'B':
|
||||||
return pushReference(t, arrayBody(t, t->vm->types, Machine::JbyteType));
|
return makeLocalReference(t, arrayBody(t, t->m->types, Machine::JbyteType));
|
||||||
case 'C':
|
case 'C':
|
||||||
return pushReference(t, arrayBody(t, t->vm->types, Machine::JcharType));
|
return makeLocalReference(t, arrayBody(t, t->m->types, Machine::JcharType));
|
||||||
case 'D':
|
case 'D':
|
||||||
return pushReference(t, arrayBody(t, t->vm->types, Machine::JdoubleType));
|
return makeLocalReference(t, arrayBody(t, t->m->types, Machine::JdoubleType));
|
||||||
case 'F':
|
case 'F':
|
||||||
return pushReference(t, arrayBody(t, t->vm->types, Machine::JfloatType));
|
return makeLocalReference(t, arrayBody(t, t->m->types, Machine::JfloatType));
|
||||||
case 'I':
|
case 'I':
|
||||||
return pushReference(t, arrayBody(t, t->vm->types, Machine::JintType));
|
return makeLocalReference(t, arrayBody(t, t->m->types, Machine::JintType));
|
||||||
case 'J':
|
case 'J':
|
||||||
return pushReference(t, arrayBody(t, t->vm->types, Machine::JlongType));
|
return makeLocalReference(t, arrayBody(t, t->m->types, Machine::JlongType));
|
||||||
case 'S':
|
case 'S':
|
||||||
return pushReference(t, arrayBody(t, t->vm->types, Machine::JshortType));
|
return makeLocalReference(t, arrayBody(t, t->m->types, Machine::JshortType));
|
||||||
case 'V':
|
case 'V':
|
||||||
return pushReference(t, arrayBody(t, t->vm->types, Machine::JvoidType));
|
return makeLocalReference(t, arrayBody(t, t->m->types, Machine::JvoidType));
|
||||||
case 'Z':
|
case 'Z':
|
||||||
return pushReference(t, arrayBody(t, t->vm->types, Machine::JbooleanType));
|
return makeLocalReference(t, arrayBody(t, t->m->types, Machine::JbooleanType));
|
||||||
default:
|
default:
|
||||||
t->exception = makeIllegalArgumentException(t);
|
t->exception = makeIllegalArgumentException(t);
|
||||||
return 0;
|
return 0;
|
||||||
@ -247,7 +247,7 @@ Java_java_lang_reflect_Field_getObject
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
return pushReference(t, cast<object>(*instance, offset));
|
return makeLocalReference(t, cast<object>(*instance, offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
@ -300,7 +300,7 @@ Java_java_lang_reflect_Constructor_make(Thread* t, jclass, jclass c)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
return pushReference(t, make(t, *c));
|
return makeLocalReference(t, make(t, *c));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jobject JNICALL
|
extern "C" JNIEXPORT jobject JNICALL
|
||||||
@ -308,8 +308,11 @@ Java_java_lang_reflect_Method_getCaller(Thread* t, jclass)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
return pushReference
|
FrameIterator it; t->m->processor->start(t, &it);
|
||||||
(t, frameMethod(t, frameNext(t, frameNext(t, t->frame))));
|
t->m->processor->next(t, &it);
|
||||||
|
t->m->processor->next(t, &it);
|
||||||
|
|
||||||
|
return makeLocalReference(t, it.method);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jobject JNICALL
|
extern "C" JNIEXPORT jobject JNICALL
|
||||||
@ -318,11 +321,12 @@ Java_java_lang_reflect_Method_invoke
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
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) {
|
if (t->exception) {
|
||||||
t->exception = makeInvocationTargetException(t, t->exception);
|
t->exception = makeInvocationTargetException(t, t->exception);
|
||||||
}
|
}
|
||||||
return pushReference(t, v);
|
return makeLocalReference(t, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jint JNICALL
|
extern "C" JNIEXPORT jint JNICALL
|
||||||
@ -351,7 +355,7 @@ Java_java_lang_reflect_Array_makeObjectArray
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
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
|
extern "C" JNIEXPORT jint JNICALL
|
||||||
@ -387,7 +391,7 @@ Java_java_lang_String_intern(Thread* t, jobject this_)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
return pushReference(t, intern(t, *this_));
|
return makeLocalReference(t, intern(t, *this_));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jstring JNICALL
|
extern "C" JNIEXPORT jstring JNICALL
|
||||||
@ -401,7 +405,7 @@ Java_java_lang_System_getVMProperty(Thread* t, jclass, jint code)
|
|||||||
|
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case JavaClassPath:
|
case JavaClassPath:
|
||||||
return pushReference(t, makeString(t, "%s", t->vm->finder->path()));
|
return makeLocalReference(t, makeString(t, "%s", t->m->finder->path()));
|
||||||
|
|
||||||
default:
|
default:
|
||||||
t->exception = makeRuntimeException(t, 0);
|
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)
|
Java_java_lang_Runtime_load(Thread* t, jclass, jstring name, jboolean mapName)
|
||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
ACQUIRE(t, t->vm->classLock);
|
ACQUIRE(t, t->m->classLock);
|
||||||
|
|
||||||
char n[stringLength(t, *name) + 1];
|
char n[stringLength(t, *name) + 1];
|
||||||
stringChars(t, *name, n);
|
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()
|
if (lib->name()
|
||||||
and strcmp(lib->name(), n) == 0
|
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;
|
System::Library* lib;
|
||||||
if (LIKELY(t->vm->system->success
|
if (LIKELY(t->m->system->success
|
||||||
(t->vm->system->load(&lib, n, mapName, t->vm->libraries))))
|
(t->m->system->load(&lib, n, mapName, t->m->libraries))))
|
||||||
{
|
{
|
||||||
t->vm->libraries = lib;
|
t->m->libraries = lib;
|
||||||
} else {
|
} else {
|
||||||
object message = makeString(t, "library not found: %s", n);
|
object message = makeString(t, "library not found: %s", n);
|
||||||
t->exception = makeUnsatisfiedLinkError(t, message);
|
t->exception = makeUnsatisfiedLinkError(t, message);
|
||||||
@ -510,7 +514,7 @@ Java_java_lang_Runtime_exit(Thread* t, jobject, jint code)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
t->vm->system->exit(code);
|
t->m->system->exit(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jlong JNICALL
|
extern "C" JNIEXPORT jlong JNICALL
|
||||||
@ -525,24 +529,25 @@ Java_java_lang_Throwable_trace(Thread* t, jclass, jint skipCount)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
int frame = t->frame;
|
FrameIterator it; t->m->processor->start(t, &it);
|
||||||
while (skipCount-- and frame >= 0) {
|
|
||||||
frame = frameNext(t, frame);
|
while (skipCount-- and it.valid()) {
|
||||||
|
t->m->processor->next(t, &it);
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip Throwable constructors
|
// skip Throwable constructors
|
||||||
while (frame >= 0
|
while (it.valid()
|
||||||
and isAssignableFrom
|
and isAssignableFrom
|
||||||
(t, arrayBody(t, t->vm->types, Machine::ThrowableType),
|
(t, arrayBody(t, t->m->types, Machine::ThrowableType),
|
||||||
methodClass(t, frameMethod(t, frame)))
|
methodClass(t, it.method))
|
||||||
and strcmp(reinterpret_cast<const int8_t*>("<init>"),
|
and strcmp(reinterpret_cast<const int8_t*>("<init>"),
|
||||||
&byteArrayBody(t, methodName(t, frameMethod(t, frame)), 0))
|
&byteArrayBody(t, methodName(t, it.method), 0))
|
||||||
== 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
|
extern "C" JNIEXPORT jarray JNICALL
|
||||||
@ -552,7 +557,7 @@ Java_java_lang_Throwable_resolveTrace(Thread* t, jclass, jobject trace)
|
|||||||
|
|
||||||
unsigned length = arrayLength(t, *trace);
|
unsigned length = arrayLength(t, *trace);
|
||||||
object array = makeObjectArray
|
object array = makeObjectArray
|
||||||
(t, arrayBody(t, t->vm->types, Machine::StackTraceElementType),
|
(t, arrayBody(t, t->m->types, Machine::StackTraceElementType),
|
||||||
length, true);
|
length, true);
|
||||||
PROTECT(t, array);
|
PROTECT(t, array);
|
||||||
|
|
||||||
@ -578,7 +583,7 @@ Java_java_lang_Throwable_resolveTrace(Thread* t, jclass, jobject trace)
|
|||||||
set(t, objectArrayBody(t, array, i), ste);
|
set(t, objectArrayBody(t, array, i), ste);
|
||||||
}
|
}
|
||||||
|
|
||||||
return pushReference(t, array);
|
return makeLocalReference(t, array);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jobject JNICALL
|
extern "C" JNIEXPORT jobject JNICALL
|
||||||
@ -586,7 +591,7 @@ Java_java_lang_Thread_currentThread(Thread* t, jclass)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
return pushReference(t, t->javaThread);
|
return makeLocalReference(t, t->javaThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jlong JNICALL
|
extern "C" JNIEXPORT jlong JNICALL
|
||||||
@ -594,12 +599,12 @@ Java_java_lang_Thread_doStart(Thread* t, jobject this_)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
Thread* p = new (t->vm->system->allocate(sizeof(Thread)))
|
Thread* p = new (t->m->system->allocate(sizeof(Thread)))
|
||||||
Thread(t->vm, *this_, t);
|
Thread(t->m, *this_, t);
|
||||||
|
|
||||||
enter(p, Thread::ActiveState);
|
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);
|
return reinterpret_cast<jlong>(p);
|
||||||
} else {
|
} else {
|
||||||
p->exit();
|
p->exit();
|
||||||
@ -623,7 +628,7 @@ Java_java_net_URL_00024ResourceInputStream_open
|
|||||||
char p[stringLength(t, *path) + 1];
|
char p[stringLength(t, *path) + 1];
|
||||||
stringChars(t, *path, p);
|
stringChars(t, *path, p);
|
||||||
|
|
||||||
return reinterpret_cast<jlong>(t->vm->finder->find(p));
|
return reinterpret_cast<jlong>(t->m->finder->find(p));
|
||||||
} else {
|
} else {
|
||||||
t->exception = makeNullPointerException(t);
|
t->exception = makeNullPointerException(t);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -176,6 +176,13 @@ hash(const uint16_t* s, unsigned length)
|
|||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Machine;
|
||||||
|
class Thread;
|
||||||
|
|
||||||
|
struct Object { };
|
||||||
|
|
||||||
|
typedef Object* object;
|
||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
|
||||||
#endif//COMMON_H
|
#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 "common.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "heap.h"
|
|
||||||
#include "finder.h"
|
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "run.h"
|
|
||||||
#include "jnienv.h"
|
|
||||||
#include "machine.h"
|
#include "machine.h"
|
||||||
|
#include "processor.h"
|
||||||
|
|
||||||
using namespace vm;
|
using namespace vm;
|
||||||
|
|
||||||
namespace {
|
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
|
void
|
||||||
pushFrame(Thread* t, object method)
|
pushFrame(Thread* t, object method)
|
||||||
{
|
{
|
||||||
@ -69,7 +380,7 @@ popFrame(Thread* t)
|
|||||||
t->exception = makeExceptionInInitializerError(t, t->exception);
|
t->exception = makeExceptionInInitializerError(t, t->exception);
|
||||||
}
|
}
|
||||||
classVmFlags(t, methodClass(t, method)) &= ~(NeedInitFlag | InitFlag);
|
classVmFlags(t, methodClass(t, method)) &= ~(NeedInitFlag | InitFlag);
|
||||||
release(t, t->vm->classLock);
|
release(t, t->m->classLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
t->sp = frameBase(t, t->frame);
|
t->sp = frameBase(t, t->frame);
|
||||||
@ -128,7 +439,7 @@ inline object
|
|||||||
resolveClass(Thread* t, object pool, unsigned index)
|
resolveClass(Thread* t, object pool, unsigned index)
|
||||||
{
|
{
|
||||||
object o = arrayBody(t, pool, 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);
|
PROTECT(t, pool);
|
||||||
|
|
||||||
@ -141,10 +452,11 @@ resolveClass(Thread* t, object pool, unsigned index)
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline object
|
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);
|
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);
|
PROTECT(t, container);
|
||||||
|
|
||||||
@ -158,11 +470,11 @@ resolveClass(Thread* t, object container, object& (*class_)(Thread*, object))
|
|||||||
|
|
||||||
inline object
|
inline object
|
||||||
resolve(Thread* t, object pool, unsigned index,
|
resolve(Thread* t, object pool, unsigned index,
|
||||||
object (*find)(Thread*, object, object, object),
|
object (*find)(vm::Thread*, object, object, object),
|
||||||
object (*makeError)(Thread*, object))
|
object (*makeError)(vm::Thread*, object))
|
||||||
{
|
{
|
||||||
object o = arrayBody(t, pool, index);
|
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);
|
PROTECT(t, pool);
|
||||||
|
|
||||||
@ -264,10 +576,10 @@ inline object
|
|||||||
resolveNativeMethodData(Thread* t, object method)
|
resolveNativeMethodData(Thread* t, object method)
|
||||||
{
|
{
|
||||||
if (objectClass(t, methodCode(t, method))
|
if (objectClass(t, methodCode(t, method))
|
||||||
== arrayBody(t, t->vm->types, Machine::ByteArrayType))
|
== arrayBody(t, t->m->types, Machine::ByteArrayType))
|
||||||
{
|
{
|
||||||
object data = 0;
|
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*>
|
void* p = lib->resolve(reinterpret_cast<const char*>
|
||||||
(&byteArrayBody(t, methodCode(t, method), 0)));
|
(&byteArrayBody(t, methodCode(t, method), 0)));
|
||||||
if (p) {
|
if (p) {
|
||||||
@ -383,7 +695,7 @@ invokeNative(Thread* t, object method)
|
|||||||
|
|
||||||
{ ENTER(t, Thread::IdleState);
|
{ ENTER(t, Thread::IdleState);
|
||||||
|
|
||||||
result = t->vm->system->call
|
result = t->m->system->call
|
||||||
(function,
|
(function,
|
||||||
args,
|
args,
|
||||||
&nativeMethodDataParameterTypes(t, data, 0),
|
&nativeMethodDataParameterTypes(t, data, 0),
|
||||||
@ -451,7 +763,7 @@ bool
|
|||||||
classInit2(Thread* t, object class_, unsigned ipOffset)
|
classInit2(Thread* t, object class_, unsigned ipOffset)
|
||||||
{
|
{
|
||||||
PROTECT(t, class_);
|
PROTECT(t, class_);
|
||||||
acquire(t, t->vm->classLock);
|
acquire(t, t->m->classLock);
|
||||||
if (classVmFlags(t, class_) & NeedInitFlag
|
if (classVmFlags(t, class_) & NeedInitFlag
|
||||||
and (classVmFlags(t, class_) & InitFlag) == 0)
|
and (classVmFlags(t, class_) & InitFlag) == 0)
|
||||||
{
|
{
|
||||||
@ -460,7 +772,7 @@ classInit2(Thread* t, object class_, unsigned ipOffset)
|
|||||||
t->ip -= ipOffset;
|
t->ip -= ipOffset;
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
release(t, t->vm->classLock);
|
release(t, t->m->classLock);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -533,7 +845,7 @@ populateMultiArray(Thread* t, object array, int32_t* counts,
|
|||||||
}
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
run(Thread* t)
|
interpret(Thread* t)
|
||||||
{
|
{
|
||||||
const int base = t->frame;
|
const int base = t->frame;
|
||||||
|
|
||||||
@ -717,7 +1029,7 @@ run(Thread* t)
|
|||||||
|
|
||||||
if (LIKELY(array)) {
|
if (LIKELY(array)) {
|
||||||
if (objectClass(t, array)
|
if (objectClass(t, array)
|
||||||
== arrayBody(t, t->vm->types, Machine::BooleanArrayType))
|
== arrayBody(t, t->m->types, Machine::BooleanArrayType))
|
||||||
{
|
{
|
||||||
if (LIKELY(index >= 0 and
|
if (LIKELY(index >= 0 and
|
||||||
static_cast<uintptr_t>(index)
|
static_cast<uintptr_t>(index)
|
||||||
@ -756,7 +1068,7 @@ run(Thread* t)
|
|||||||
|
|
||||||
if (LIKELY(array)) {
|
if (LIKELY(array)) {
|
||||||
if (objectClass(t, array)
|
if (objectClass(t, array)
|
||||||
== arrayBody(t, t->vm->types, Machine::BooleanArrayType))
|
== arrayBody(t, t->m->types, Machine::BooleanArrayType))
|
||||||
{
|
{
|
||||||
if (LIKELY(index >= 0 and
|
if (LIKELY(index >= 0 and
|
||||||
static_cast<uintptr_t>(index)
|
static_cast<uintptr_t>(index)
|
||||||
@ -1890,14 +2202,14 @@ run(Thread* t)
|
|||||||
|
|
||||||
object v = arrayBody(t, codePool(t, code), index - 1);
|
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));
|
pushInt(t, intValue(t, v));
|
||||||
} else if (objectClass(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));
|
pushInt(t, floatValue(t, v));
|
||||||
} else if (objectClass(t, v)
|
} else if (objectClass(t, v)
|
||||||
== arrayBody(t, t->vm->types, Machine::StringType))
|
== arrayBody(t, t->m->types, Machine::StringType))
|
||||||
{
|
{
|
||||||
pushObject(t, v);
|
pushObject(t, v);
|
||||||
} else {
|
} else {
|
||||||
@ -1914,10 +2226,10 @@ run(Thread* t)
|
|||||||
|
|
||||||
object v = arrayBody(t, codePool(t, code), ((index1 << 8) | index2) - 1);
|
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));
|
pushLong(t, longValue(t, v));
|
||||||
} else if (objectClass(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));
|
pushLong(t, doubleValue(t, v));
|
||||||
} else {
|
} else {
|
||||||
@ -2506,24 +2818,6 @@ run(Thread* t)
|
|||||||
return 0;
|
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
|
void
|
||||||
pushArguments(Thread* t, object this_, const char* spec, bool indirectObjects,
|
pushArguments(Thread* t, object this_, const char* spec, bool indirectObjects,
|
||||||
va_list a)
|
va_list a)
|
||||||
@ -2704,7 +2998,7 @@ invoke(Thread* t, object method)
|
|||||||
checkStack(t, method);
|
checkStack(t, method);
|
||||||
if (LIKELY(t->exception == 0)) {
|
if (LIKELY(t->exception == 0)) {
|
||||||
pushFrame(t, method);
|
pushFrame(t, method);
|
||||||
result = ::run(t);
|
result = interpret(t);
|
||||||
if (LIKELY(t->exception == 0)) {
|
if (LIKELY(t->exception == 0)) {
|
||||||
popFrame(t);
|
popFrame(t);
|
||||||
}
|
}
|
||||||
@ -2745,48 +3039,55 @@ invoke(Thread* t, object method)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
void
|
||||||
|
MyProcessor::visitObjects(vm::Thread* vmt, Heap::Visitor* v)
|
||||||
namespace vm {
|
|
||||||
|
|
||||||
object
|
|
||||||
runv(Thread* t, object method, object this_, bool indirectObjects, va_list a)
|
|
||||||
{
|
{
|
||||||
assert(t, t->state == Thread::ActiveState
|
Thread* t = static_cast<Thread*>(vmt);
|
||||||
or t->state == Thread::ExclusiveState);
|
|
||||||
|
|
||||||
assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0));
|
v->visit(&(t->code));
|
||||||
|
|
||||||
if (UNLIKELY(t->sp + methodParameterFootprint(t, method) + 1
|
for (unsigned i = 0; i < t->sp; ++i) {
|
||||||
> Thread::StackSizeInWords / 2))
|
if (t->stack[i * 2] == ObjectTag) {
|
||||||
{
|
v->visit(t->stack + (i * 2) + 1);
|
||||||
t->exception = makeStackOverflowError(t);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const char* spec = reinterpret_cast<char*>
|
void
|
||||||
(&byteArrayBody(t, methodSpec(t, method), 0));
|
MyProcessor::start(vm::Thread* vmt, FrameIterator* it)
|
||||||
pushArguments(t, this_, spec, indirectObjects, a);
|
{
|
||||||
|
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
|
object
|
||||||
run(Thread* t, object method, object this_, ...)
|
MyProcessor::invokeArray(vm::Thread* vmt, object method, object this_,
|
||||||
|
object arguments)
|
||||||
{
|
{
|
||||||
va_list a;
|
Thread* t = static_cast<Thread*>(vmt);
|
||||||
va_start(a, this_);
|
|
||||||
|
|
||||||
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
|
assert(t, t->state == Thread::ActiveState
|
||||||
or t->state == Thread::ExclusiveState);
|
or t->state == Thread::ExclusiveState);
|
||||||
|
|
||||||
@ -2803,13 +3104,41 @@ run2(Thread* t, object method, object this_, object arguments)
|
|||||||
(&byteArrayBody(t, methodSpec(t, method), 0));
|
(&byteArrayBody(t, methodSpec(t, method), 0));
|
||||||
pushArguments(t, this_, spec, arguments);
|
pushArguments(t, this_, spec, arguments);
|
||||||
|
|
||||||
return invoke(t, method);
|
return ::invoke(t, method);
|
||||||
}
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
run(Thread* t, const char* className, const char* methodName,
|
MyProcessor::invokeList(vm::Thread* vmt, object method, object this_,
|
||||||
const char* methodSpec, 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
|
assert(t, t->state == Thread::ActiveState
|
||||||
or t->state == Thread::ExclusiveState);
|
or t->state == Thread::ExclusiveState);
|
||||||
|
|
||||||
@ -2820,55 +3149,26 @@ run(Thread* t, const char* className, const char* methodName,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
va_list a;
|
pushArguments(t, this_, methodSpec, false, arguments);
|
||||||
va_start(a, this_);
|
|
||||||
|
|
||||||
pushArguments(t, this_, methodSpec, false, a);
|
object method = resolveMethod(t, className, methodName, methodSpec);
|
||||||
|
|
||||||
va_end(a);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
object method = findMethodInClass(t, class_, referenceName(t, reference),
|
|
||||||
referenceSpec(t, reference));
|
|
||||||
if (LIKELY(t->exception == 0)) {
|
if (LIKELY(t->exception == 0)) {
|
||||||
assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 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
|
} // namespace
|
||||||
run(System* system, Heap* heap, Finder* finder,
|
|
||||||
const char* className, int argc, const char** argv)
|
namespace vm {
|
||||||
|
|
||||||
|
Processor*
|
||||||
|
makeProcessor(System* system)
|
||||||
{
|
{
|
||||||
Machine m(system, heap, finder);
|
return new (system->allocate(sizeof(MyProcessor))) MyProcessor(system);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
150
src/jnienv.cpp
150
src/jnienv.cpp
@ -1,6 +1,6 @@
|
|||||||
#include "jnienv.h"
|
#include "jnienv.h"
|
||||||
#include "machine.h"
|
#include "machine.h"
|
||||||
#include "run.h"
|
#include "processor.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
|
|
||||||
using namespace vm;
|
using namespace vm;
|
||||||
@ -15,7 +15,7 @@ AttachCurrentThread(Machine* m, Thread** t, void*)
|
|||||||
{
|
{
|
||||||
*t = static_cast<Thread*>(m->localThread->get());
|
*t = static_cast<Thread*>(m->localThread->get());
|
||||||
if (*t == 0) {
|
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);
|
m->localThread->set(*t);
|
||||||
}
|
}
|
||||||
@ -63,7 +63,7 @@ GetStringUTFChars(Thread* t, jstring s, jboolean* isCopy)
|
|||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
char* chars = static_cast<char*>
|
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);
|
stringChars(t, *s, chars);
|
||||||
|
|
||||||
if (isCopy) *isCopy = true;
|
if (isCopy) *isCopy = true;
|
||||||
@ -73,7 +73,7 @@ GetStringUTFChars(Thread* t, jstring s, jboolean* isCopy)
|
|||||||
void JNICALL
|
void JNICALL
|
||||||
ReleaseStringUTFChars(Thread* t, jstring, const char* chars)
|
ReleaseStringUTFChars(Thread* t, jstring, const char* chars)
|
||||||
{
|
{
|
||||||
t->vm->system->free(chars);
|
t->m->system->free(chars);
|
||||||
}
|
}
|
||||||
|
|
||||||
jstring JNICALL
|
jstring JNICALL
|
||||||
@ -81,7 +81,7 @@ NewStringUTF(Thread* t, const char* chars)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
return pushReference(t, makeString(t, "%s", chars));
|
return makeLocalReference(t, makeString(t, "%s", chars));
|
||||||
}
|
}
|
||||||
|
|
||||||
jclass JNICALL
|
jclass JNICALL
|
||||||
@ -92,7 +92,7 @@ FindClass(Thread* t, const char* name)
|
|||||||
object n = makeByteArray(t, strlen(name) + 1, false);
|
object n = makeByteArray(t, strlen(name) + 1, false);
|
||||||
memcpy(&byteArrayBody(t, n, 0), name, byteArrayLength(t, n));
|
memcpy(&byteArrayBody(t, n, 0), name, byteArrayLength(t, n));
|
||||||
|
|
||||||
return pushReference(t, resolveClass(t, n));
|
return makeLocalReference(t, resolveClass(t, n));
|
||||||
}
|
}
|
||||||
|
|
||||||
jint JNICALL
|
jint JNICALL
|
||||||
@ -122,9 +122,9 @@ ThrowNew(Thread* t, jclass c, const char* message)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void JNICALL
|
void JNICALL
|
||||||
DeleteLocalRef(Thread*, jobject)
|
DeleteLocalRef(Thread* t, jobject r)
|
||||||
{
|
{
|
||||||
// do nothing
|
disposeLocalReference(t, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
jboolean JNICALL
|
jboolean JNICALL
|
||||||
@ -138,7 +138,7 @@ GetObjectClass(Thread* t, jobject o)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
return pushReference(t, objectClass(t, *o));
|
return makeLocalReference(t, objectClass(t, *o));
|
||||||
}
|
}
|
||||||
|
|
||||||
jboolean JNICALL
|
jboolean JNICALL
|
||||||
@ -172,18 +172,18 @@ GetMethodID(Thread* t, jclass c, const char* name, const char* spec)
|
|||||||
if (classFlags(t, *c) & ACC_INTERFACE) {
|
if (classFlags(t, *c) & ACC_INTERFACE) {
|
||||||
PROTECT(t, method);
|
PROTECT(t, method);
|
||||||
|
|
||||||
ACQUIRE(t, t->vm->referenceLock);
|
ACQUIRE(t, t->m->referenceLock);
|
||||||
|
|
||||||
for (unsigned i = 0; i < vectorSize(t, t->vm->jniInterfaceTable); ++i) {
|
for (unsigned i = 0; i < vectorSize(t, t->m->jniInterfaceTable); ++i) {
|
||||||
if (method == vectorBody(t, t->vm->jniInterfaceTable, i)) {
|
if (method == vectorBody(t, t->m->jniInterfaceTable, i)) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
t->vm->jniInterfaceTable
|
t->m->jniInterfaceTable
|
||||||
= vectorAppend(t, t->vm->jniInterfaceTable, method);
|
= vectorAppend(t, t->m->jniInterfaceTable, method);
|
||||||
|
|
||||||
return (vectorSize(t, t->vm->jniInterfaceTable) - 1) | InterfaceMethodID;
|
return (vectorSize(t, t->m->jniInterfaceTable) - 1) | InterfaceMethodID;
|
||||||
} else {
|
} else {
|
||||||
return methodOffset(t, method) + 1;
|
return methodOffset(t, method) + 1;
|
||||||
}
|
}
|
||||||
@ -204,7 +204,7 @@ inline object
|
|||||||
getMethod(Thread* t, object o, jmethodID m)
|
getMethod(Thread* t, object o, jmethodID m)
|
||||||
{
|
{
|
||||||
if (m & InterfaceMethodID) {
|
if (m & InterfaceMethodID) {
|
||||||
return vectorBody(t, t->vm->jniInterfaceTable, m & (~InterfaceMethodID));
|
return vectorBody(t, t->m->jniInterfaceTable, m & (~InterfaceMethodID));
|
||||||
} else {
|
} else {
|
||||||
return arrayBody(t, classVirtualTable(t, objectClass(t, o)), m - 1);
|
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);
|
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
|
jobject JNICALL
|
||||||
@ -236,7 +237,7 @@ CallBooleanMethodV(Thread* t, jobject o, jmethodID m, va_list a)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
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));
|
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);
|
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));
|
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);
|
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));
|
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);
|
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));
|
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);
|
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));
|
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);
|
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));
|
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);
|
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));
|
jint i = (t->exception ? 0 : floatValue(t, r));
|
||||||
jfloat f; memcpy(&f, &i, 4);
|
jfloat f; memcpy(&f, &i, 4);
|
||||||
return f;
|
return f;
|
||||||
@ -392,7 +393,7 @@ CallDoubleMethodV(Thread* t, jobject o, jmethodID m, va_list a)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
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));
|
jlong i = (t->exception ? 0 : doubleValue(t, r));
|
||||||
jdouble f; memcpy(&f, &i, 4);
|
jdouble f; memcpy(&f, &i, 4);
|
||||||
return f;
|
return f;
|
||||||
@ -416,7 +417,7 @@ CallVoidMethodV(Thread* t, jobject o, jmethodID m, va_list a)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
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
|
void JNICALL
|
||||||
@ -441,7 +442,8 @@ CallStaticObjectMethodV(Thread* t, jclass c, jmethodID m, va_list a)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
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
|
jobject JNICALL
|
||||||
@ -462,7 +464,8 @@ CallStaticBooleanMethodV(Thread* t, jclass c, jmethodID m, va_list a)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
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));
|
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);
|
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));
|
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);
|
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));
|
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);
|
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));
|
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);
|
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));
|
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);
|
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));
|
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);
|
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));
|
jint i = (t->exception ? 0 : floatValue(t, r));
|
||||||
jfloat f; memcpy(&f, &i, 4);
|
jfloat f; memcpy(&f, &i, 4);
|
||||||
return f;
|
return f;
|
||||||
@ -618,7 +627,8 @@ CallStaticDoubleMethodV(Thread* t, jclass c, jmethodID m, va_list a)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
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));
|
jlong i = (t->exception ? 0 : doubleValue(t, r));
|
||||||
jdouble f; memcpy(&f, &i, 4);
|
jdouble f; memcpy(&f, &i, 4);
|
||||||
return f;
|
return f;
|
||||||
@ -642,7 +652,7 @@ CallStaticVoidMethodV(Thread* t, jclass c, jmethodID m, va_list a)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
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
|
void JNICALL
|
||||||
@ -693,7 +703,7 @@ GetObjectField(Thread* t, jobject o, jfieldID field)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
return pushReference(t, cast<object>(*o, field));
|
return makeLocalReference(t, cast<object>(*o, field));
|
||||||
}
|
}
|
||||||
|
|
||||||
jboolean JNICALL
|
jboolean JNICALL
|
||||||
@ -837,7 +847,7 @@ GetStaticObjectField(Thread* t, jclass c, jfieldID field)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
return pushReference(t, arrayBody(t, classStaticTable(t, *c), field));
|
return makeLocalReference(t, arrayBody(t, classStaticTable(t, *c), field));
|
||||||
}
|
}
|
||||||
|
|
||||||
jboolean JNICALL
|
jboolean JNICALL
|
||||||
@ -1003,12 +1013,12 @@ NewGlobalRef(Thread* t, jobject o)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
ACQUIRE(t, t->vm->referenceLock);
|
ACQUIRE(t, t->m->referenceLock);
|
||||||
|
|
||||||
t->vm->jniReferences = new (t->vm->system->allocate(sizeof(Reference)))
|
t->m->jniReferences = new (t->m->system->allocate(sizeof(Reference)))
|
||||||
Reference(*o, t->vm->jniReferences);
|
Reference(*o, t->m->jniReferences);
|
||||||
|
|
||||||
return &(t->vm->jniReferences->target);
|
return &(t->m->jniReferences->target);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JNICALL
|
void JNICALL
|
||||||
@ -1016,9 +1026,9 @@ DeleteGlobalRef(Thread* t, jobject o)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
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) {
|
if (&((*r)->target) == o) {
|
||||||
*r = (*r)->next;
|
*r = (*r)->next;
|
||||||
break;
|
break;
|
||||||
@ -1033,7 +1043,7 @@ ExceptionOccurred(Thread* t)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
return pushReference(t, t->exception);
|
return makeLocalReference(t, t->exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JNICALL
|
void JNICALL
|
||||||
@ -1057,7 +1067,7 @@ NewBooleanArray(Thread* t, jsize length)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
return pushReference(t, makeBooleanArray(t, length, true));
|
return makeLocalReference(t, makeBooleanArray(t, length, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
jbyteArray JNICALL
|
jbyteArray JNICALL
|
||||||
@ -1065,7 +1075,7 @@ NewByteArray(Thread* t, jsize length)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
return pushReference(t, makeByteArray(t, length, true));
|
return makeLocalReference(t, makeByteArray(t, length, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
jcharArray JNICALL
|
jcharArray JNICALL
|
||||||
@ -1073,7 +1083,7 @@ NewCharArray(Thread* t, jsize length)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
return pushReference(t, makeCharArray(t, length, true));
|
return makeLocalReference(t, makeCharArray(t, length, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
jshortArray JNICALL
|
jshortArray JNICALL
|
||||||
@ -1081,7 +1091,7 @@ NewShortArray(Thread* t, jsize length)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
return pushReference(t, makeShortArray(t, length, true));
|
return makeLocalReference(t, makeShortArray(t, length, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
jintArray JNICALL
|
jintArray JNICALL
|
||||||
@ -1089,7 +1099,7 @@ NewIntArray(Thread* t, jsize length)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
return pushReference(t, makeIntArray(t, length, true));
|
return makeLocalReference(t, makeIntArray(t, length, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
jlongArray JNICALL
|
jlongArray JNICALL
|
||||||
@ -1097,7 +1107,7 @@ NewLongArray(Thread* t, jsize length)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
return pushReference(t, makeLongArray(t, length, true));
|
return makeLocalReference(t, makeLongArray(t, length, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
jfloatArray JNICALL
|
jfloatArray JNICALL
|
||||||
@ -1105,7 +1115,7 @@ NewFloatArray(Thread* t, jsize length)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
return pushReference(t, makeFloatArray(t, length, true));
|
return makeLocalReference(t, makeFloatArray(t, length, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
jdoubleArray JNICALL
|
jdoubleArray JNICALL
|
||||||
@ -1113,7 +1123,7 @@ NewDoubleArray(Thread* t, jsize length)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
return pushReference(t, makeDoubleArray(t, length, true));
|
return makeLocalReference(t, makeDoubleArray(t, length, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
jboolean* JNICALL
|
jboolean* JNICALL
|
||||||
@ -1122,7 +1132,7 @@ GetBooleanArrayElements(Thread* t, jbooleanArray array, jboolean* isCopy)
|
|||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
unsigned size = booleanArrayLength(t, *array) * sizeof(jboolean);
|
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) {
|
if (size) {
|
||||||
memcpy(p, &booleanArrayBody(t, *array, 0), size);
|
memcpy(p, &booleanArrayBody(t, *array, 0), size);
|
||||||
}
|
}
|
||||||
@ -1140,7 +1150,7 @@ GetByteArrayElements(Thread* t, jbyteArray array, jboolean* isCopy)
|
|||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
unsigned size = byteArrayLength(t, *array) * sizeof(jbyte);
|
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) {
|
if (size) {
|
||||||
memcpy(p, &byteArrayBody(t, *array, 0), size);
|
memcpy(p, &byteArrayBody(t, *array, 0), size);
|
||||||
}
|
}
|
||||||
@ -1158,7 +1168,7 @@ GetCharArrayElements(Thread* t, jcharArray array, jboolean* isCopy)
|
|||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
unsigned size = charArrayLength(t, *array) * sizeof(jchar);
|
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) {
|
if (size) {
|
||||||
memcpy(p, &charArrayBody(t, *array, 0), size);
|
memcpy(p, &charArrayBody(t, *array, 0), size);
|
||||||
}
|
}
|
||||||
@ -1176,7 +1186,7 @@ GetShortArrayElements(Thread* t, jshortArray array, jboolean* isCopy)
|
|||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
unsigned size = shortArrayLength(t, *array) * sizeof(jshort);
|
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) {
|
if (size) {
|
||||||
memcpy(p, &shortArrayBody(t, *array, 0), size);
|
memcpy(p, &shortArrayBody(t, *array, 0), size);
|
||||||
}
|
}
|
||||||
@ -1194,7 +1204,7 @@ GetIntArrayElements(Thread* t, jintArray array, jboolean* isCopy)
|
|||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
unsigned size = intArrayLength(t, *array) * sizeof(jint);
|
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) {
|
if (size) {
|
||||||
memcpy(p, &intArrayBody(t, *array, 0), size);
|
memcpy(p, &intArrayBody(t, *array, 0), size);
|
||||||
}
|
}
|
||||||
@ -1212,7 +1222,7 @@ GetLongArrayElements(Thread* t, jlongArray array, jboolean* isCopy)
|
|||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
unsigned size = longArrayLength(t, *array) * sizeof(jlong);
|
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) {
|
if (size) {
|
||||||
memcpy(p, &longArrayBody(t, *array, 0), size);
|
memcpy(p, &longArrayBody(t, *array, 0), size);
|
||||||
}
|
}
|
||||||
@ -1230,7 +1240,7 @@ GetFloatArrayElements(Thread* t, jfloatArray array, jboolean* isCopy)
|
|||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
unsigned size = floatArrayLength(t, *array) * sizeof(jfloat);
|
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) {
|
if (size) {
|
||||||
memcpy(p, &floatArrayBody(t, *array, 0), size);
|
memcpy(p, &floatArrayBody(t, *array, 0), size);
|
||||||
}
|
}
|
||||||
@ -1248,7 +1258,7 @@ GetDoubleArrayElements(Thread* t, jdoubleArray array, jboolean* isCopy)
|
|||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
unsigned size = doubleArrayLength(t, *array) * sizeof(jdouble);
|
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) {
|
if (size) {
|
||||||
memcpy(p, &doubleArrayBody(t, *array, 0), 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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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
|
jint JNICALL
|
||||||
GetJavaVM(Thread* t, Machine** m)
|
GetJavaVM(Thread* t, Machine** m)
|
||||||
{
|
{
|
||||||
*m = t->vm;
|
*m = t->m;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
313
src/machine.cpp
313
src/machine.cpp
@ -2,7 +2,7 @@
|
|||||||
#include "machine.h"
|
#include "machine.h"
|
||||||
#include "stream.h"
|
#include "stream.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "run.h"
|
#include "processor.h"
|
||||||
|
|
||||||
using namespace vm;
|
using namespace vm;
|
||||||
|
|
||||||
@ -48,18 +48,18 @@ dispose(Thread* t, Thread* o, bool remove)
|
|||||||
o->parent->child = 0;
|
o->parent->child = 0;
|
||||||
}
|
}
|
||||||
} else if (o->child) {
|
} else if (o->child) {
|
||||||
t->vm->rootThread = o->child;
|
t->m->rootThread = o->child;
|
||||||
if (o->peer) {
|
if (o->peer) {
|
||||||
o->peer->peer = o->child->peer;
|
o->peer->peer = o->child->peer;
|
||||||
o->child->peer = o->peer;
|
o->child->peer = o->peer;
|
||||||
}
|
}
|
||||||
} else if (o->peer) {
|
} else if (o->peer) {
|
||||||
t->vm->rootThread = o->peer;
|
t->m->rootThread = o->peer;
|
||||||
} else {
|
} else {
|
||||||
abort(t);
|
abort(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(t, not find(t->vm->rootThread, o));
|
assert(t, not find(t->m->rootThread, o));
|
||||||
}
|
}
|
||||||
|
|
||||||
o->dispose();
|
o->dispose();
|
||||||
@ -132,14 +132,9 @@ visitRoots(Thread* t, Heap::Visitor* v)
|
|||||||
{
|
{
|
||||||
if (t->state != Thread::ZombieState) {
|
if (t->state != Thread::ZombieState) {
|
||||||
v->visit(&(t->javaThread));
|
v->visit(&(t->javaThread));
|
||||||
v->visit(&(t->code));
|
|
||||||
v->visit(&(t->exception));
|
v->visit(&(t->exception));
|
||||||
|
|
||||||
for (unsigned i = 0; i < t->sp; ++i) {
|
t->m->processor->visitObjects(t, v);
|
||||||
if (t->stack[i * 2] == ObjectTag) {
|
|
||||||
v->visit(t->stack + (i * 2) + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Thread::Protector* p = t->protector; p; p = p->next) {
|
for (Thread::Protector* p = t->protector; p; p = p->next) {
|
||||||
v->visit(p->p);
|
v->visit(p->p);
|
||||||
@ -158,8 +153,8 @@ finalizerTargetUnreachable(Thread* t, object* p, Heap::Visitor* v)
|
|||||||
|
|
||||||
object finalizer = *p;
|
object finalizer = *p;
|
||||||
*p = finalizerNext(t, finalizer);
|
*p = finalizerNext(t, finalizer);
|
||||||
finalizerNext(t, finalizer) = t->vm->finalizeQueue;
|
finalizerNext(t, finalizer) = t->m->finalizeQueue;
|
||||||
t->vm->finalizeQueue = finalizer;
|
t->m->finalizeQueue = finalizer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -174,7 +169,7 @@ referenceTargetUnreachable(Thread* t, object* p, Heap::Visitor* v)
|
|||||||
jreferenceTarget(t, *p) = 0;
|
jreferenceTarget(t, *p) = 0;
|
||||||
|
|
||||||
if (jreferenceQueue(t, *p)
|
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
|
// queue is reachable - add the reference
|
||||||
|
|
||||||
@ -205,7 +200,7 @@ referenceUnreachable(Thread* t, object* p, Heap::Visitor* v)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (jreferenceQueue(t, *p)
|
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
|
// queue is reachable - add the reference
|
||||||
referenceTargetUnreachable(t, p, v);
|
referenceTargetUnreachable(t, p, v);
|
||||||
@ -225,7 +220,7 @@ referenceTargetReachable(Thread* t, object* p, Heap::Visitor* v)
|
|||||||
v->visit(p);
|
v->visit(p);
|
||||||
v->visit(&jreferenceTarget(t, *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;
|
jreferenceQueue(t, *p) = 0;
|
||||||
} else {
|
} else {
|
||||||
v->visit(&jreferenceQueue(t, *p));
|
v->visit(&jreferenceQueue(t, *p));
|
||||||
@ -235,7 +230,7 @@ referenceTargetReachable(Thread* t, object* p, Heap::Visitor* v)
|
|||||||
void
|
void
|
||||||
postVisit(Thread* t, Heap::Visitor* v)
|
postVisit(Thread* t, Heap::Visitor* v)
|
||||||
{
|
{
|
||||||
Machine* m = t->vm;
|
Machine* m = t->m;
|
||||||
|
|
||||||
for (object* p = &(m->finalizeQueue); *p; p = &(finalizerNext(t, *p))) {
|
for (object* p = &(m->finalizeQueue); *p; p = &(finalizerNext(t, *p))) {
|
||||||
v->visit(p);
|
v->visit(p);
|
||||||
@ -359,9 +354,9 @@ void
|
|||||||
postCollect(Thread* t)
|
postCollect(Thread* t)
|
||||||
{
|
{
|
||||||
#ifdef VM_STRESS
|
#ifdef VM_STRESS
|
||||||
t->vm->system->free(t->defaultHeap);
|
t->m->system->free(t->defaultHeap);
|
||||||
t->defaultHeap = static_cast<uintptr_t*>
|
t->defaultHeap = static_cast<uintptr_t*>
|
||||||
(t->vm->system->allocate(Thread::HeapSizeInBytes));
|
(t->m->system->allocate(Thread::HeapSizeInBytes));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
t->heap = t->defaultHeap;
|
t->heap = t->defaultHeap;
|
||||||
@ -369,7 +364,7 @@ postCollect(Thread* t)
|
|||||||
t->heapIndex = 0;
|
t->heapIndex = 0;
|
||||||
|
|
||||||
if (t->large) {
|
if (t->large) {
|
||||||
t->vm->system->free(t->large);
|
t->m->system->free(t->large);
|
||||||
t->large = 0;
|
t->large = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -588,7 +583,7 @@ parsePool(Thread* t, Stream& s)
|
|||||||
for (unsigned i = 0; i < poolCount; ++i) {
|
for (unsigned i = 0; i < poolCount; ++i) {
|
||||||
object o = arrayBody(t, pool, i);
|
object o = arrayBody(t, pool, i);
|
||||||
if (o and objectClass(t, o)
|
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)) {
|
switch (intArrayBody(t, o, 0)) {
|
||||||
case CONSTANT_Class: {
|
case CONSTANT_Class: {
|
||||||
@ -617,7 +612,7 @@ parsePool(Thread* t, Stream& s)
|
|||||||
for (unsigned i = 0; i < poolCount; ++i) {
|
for (unsigned i = 0; i < poolCount; ++i) {
|
||||||
object o = arrayBody(t, pool, i);
|
object o = arrayBody(t, pool, i);
|
||||||
if (o and objectClass(t, o)
|
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)) {
|
switch (intArrayBody(t, o, 0)) {
|
||||||
case CONSTANT_Fieldref:
|
case CONSTANT_Fieldref:
|
||||||
@ -1183,15 +1178,15 @@ makeArrayClass(Thread* t, unsigned dimensions, object spec,
|
|||||||
dimensions,
|
dimensions,
|
||||||
2 * BytesPerWord,
|
2 * BytesPerWord,
|
||||||
BytesPerWord,
|
BytesPerWord,
|
||||||
classObjectMask(t, arrayBody(t, t->vm->types, Machine::ArrayType)),
|
classObjectMask(t, arrayBody(t, t->m->types, Machine::ArrayType)),
|
||||||
spec,
|
spec,
|
||||||
arrayBody(t, t->vm->types, Machine::JobjectType),
|
arrayBody(t, t->m->types, Machine::JobjectType),
|
||||||
0,
|
0,
|
||||||
classVirtualTable(t, arrayBody(t, t->vm->types, Machine::JobjectType)),
|
classVirtualTable(t, arrayBody(t, t->m->types, Machine::JobjectType)),
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
elementClass,
|
elementClass,
|
||||||
t->vm->loader);
|
t->m->loader);
|
||||||
}
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
@ -1232,7 +1227,7 @@ makeArrayClass(Thread* t, object spec)
|
|||||||
}
|
}
|
||||||
|
|
||||||
object elementClass = hashMapFind
|
object elementClass = hashMapFind
|
||||||
(t, t->vm->bootstrapClassMap, elementSpec, byteArrayHash, byteArrayEqual);
|
(t, t->m->bootstrapClassMap, elementSpec, byteArrayHash, byteArrayEqual);
|
||||||
|
|
||||||
if (elementClass == 0) {
|
if (elementClass == 0) {
|
||||||
elementClass = resolveClass(t, elementSpec);
|
elementClass = resolveClass(t, elementSpec);
|
||||||
@ -1245,7 +1240,7 @@ makeArrayClass(Thread* t, object spec)
|
|||||||
void
|
void
|
||||||
removeMonitor(Thread* t, object o)
|
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);
|
assert(t, p);
|
||||||
|
|
||||||
@ -1261,18 +1256,39 @@ removeMonitor(Thread* t, object o)
|
|||||||
void
|
void
|
||||||
removeString(Thread* t, object o)
|
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
|
||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
Machine::Machine(System* system, Heap* heap, Finder* finder):
|
Machine::Machine(System* system, Heap* heap, Finder* finder,
|
||||||
|
Processor* processor):
|
||||||
vtable(&javaVMVTable),
|
vtable(&javaVMVTable),
|
||||||
system(system),
|
system(system),
|
||||||
heap(heap),
|
heap(heap),
|
||||||
finder(finder),
|
finder(finder),
|
||||||
|
processor(processor),
|
||||||
rootThread(0),
|
rootThread(0),
|
||||||
exclusive(0),
|
exclusive(0),
|
||||||
jniReferences(0),
|
jniReferences(0),
|
||||||
@ -1333,7 +1349,7 @@ Machine::dispose()
|
|||||||
|
|
||||||
Thread::Thread(Machine* m, object javaThread, Thread* parent):
|
Thread::Thread(Machine* m, object javaThread, Thread* parent):
|
||||||
vtable(&(m->jniEnvVTable)),
|
vtable(&(m->jniEnvVTable)),
|
||||||
vm(m),
|
m(m),
|
||||||
parent(parent),
|
parent(parent),
|
||||||
peer((parent ? parent->child : 0)),
|
peer((parent ? parent->child : 0)),
|
||||||
child(0),
|
child(0),
|
||||||
@ -1341,12 +1357,8 @@ Thread::Thread(Machine* m, object javaThread, Thread* parent):
|
|||||||
criticalLevel(0),
|
criticalLevel(0),
|
||||||
systemThread(0),
|
systemThread(0),
|
||||||
javaThread(javaThread),
|
javaThread(javaThread),
|
||||||
code(0),
|
|
||||||
exception(0),
|
exception(0),
|
||||||
large(0),
|
large(0),
|
||||||
ip(0),
|
|
||||||
sp(0),
|
|
||||||
frame(-1),
|
|
||||||
heapIndex(0),
|
heapIndex(0),
|
||||||
heapOffset(0),
|
heapOffset(0),
|
||||||
protector(0),
|
protector(0),
|
||||||
@ -1370,17 +1382,17 @@ Thread::Thread(Machine* m, object javaThread, Thread* parent):
|
|||||||
|
|
||||||
Thread* t = this;
|
Thread* t = this;
|
||||||
|
|
||||||
t->vm->loader = allocate(t, sizeof(void*) * 3);
|
t->m->loader = allocate(t, sizeof(void*) * 3);
|
||||||
memset(t->vm->loader, 0, sizeof(void*) * 2);
|
memset(t->m->loader, 0, sizeof(void*) * 2);
|
||||||
|
|
||||||
#include "type-initializations.cpp"
|
#include "type-initializations.cpp"
|
||||||
|
|
||||||
object arrayClass = arrayBody(t, t->vm->types, Machine::ArrayType);
|
object arrayClass = arrayBody(t, t->m->types, Machine::ArrayType);
|
||||||
set(t, cast<object>(t->vm->types, 0), arrayClass);
|
set(t, cast<object>(t->m->types, 0), arrayClass);
|
||||||
|
|
||||||
object loaderClass = arrayBody
|
object loaderClass = arrayBody
|
||||||
(t, t->vm->types, Machine::SystemClassLoaderType);
|
(t, t->m->types, Machine::SystemClassLoaderType);
|
||||||
set(t, cast<object>(t->vm->loader, 0), loaderClass);
|
set(t, cast<object>(t->m->loader, 0), loaderClass);
|
||||||
|
|
||||||
object objectClass = arrayBody(t, m->types, Machine::JobjectType);
|
object objectClass = arrayBody(t, m->types, Machine::JobjectType);
|
||||||
|
|
||||||
@ -1453,7 +1465,7 @@ Thread::exit()
|
|||||||
{
|
{
|
||||||
enter(this, Thread::ExclusiveState);
|
enter(this, Thread::ExclusiveState);
|
||||||
|
|
||||||
if (vm->liveCount == 1) {
|
if (m->liveCount == 1) {
|
||||||
vm::exit(this);
|
vm::exit(this);
|
||||||
} else {
|
} else {
|
||||||
enter(this, Thread::ZombieState);
|
enter(this, Thread::ZombieState);
|
||||||
@ -1465,7 +1477,7 @@ void
|
|||||||
Thread::dispose()
|
Thread::dispose()
|
||||||
{
|
{
|
||||||
if (large) {
|
if (large) {
|
||||||
vm->system->free(large);
|
m->system->free(large);
|
||||||
large = 0;
|
large = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1475,11 +1487,11 @@ Thread::dispose()
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef VM_STRESS
|
#ifdef VM_STRESS
|
||||||
vm->system->free(heap);
|
m->system->free(heap);
|
||||||
heap = 0;
|
heap = 0;
|
||||||
#endif // VM_STRESS
|
#endif // VM_STRESS
|
||||||
|
|
||||||
vm->system->free(this);
|
m->system->free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1487,9 +1499,9 @@ exit(Thread* t)
|
|||||||
{
|
{
|
||||||
enter(t, Thread::ExitState);
|
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;
|
object f = *p;
|
||||||
*p = finalizerNext(t, *p);
|
*p = finalizerNext(t, *p);
|
||||||
|
|
||||||
@ -1497,7 +1509,7 @@ exit(Thread* t)
|
|||||||
(t, finalizerTarget(t, f));
|
(t, finalizerTarget(t, f));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (object* p = &(t->vm->tenuredFinalizers); *p;) {
|
for (object* p = &(t->m->tenuredFinalizers); *p;) {
|
||||||
object f = *p;
|
object f = *p;
|
||||||
*p = finalizerNext(t, *p);
|
*p = finalizerNext(t, *p);
|
||||||
|
|
||||||
@ -1505,7 +1517,7 @@ exit(Thread* t)
|
|||||||
(t, finalizerTarget(t, f));
|
(t, finalizerTarget(t, f));
|
||||||
}
|
}
|
||||||
|
|
||||||
disposeAll(t, t->vm->rootThread);
|
disposeAll(t, t->m->rootThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1520,22 +1532,22 @@ enter(Thread* t, Thread::State s)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ACQUIRE_RAW(t, t->vm->stateLock);
|
ACQUIRE_RAW(t, t->m->stateLock);
|
||||||
|
|
||||||
switch (s) {
|
switch (s) {
|
||||||
case Thread::ExclusiveState: {
|
case Thread::ExclusiveState: {
|
||||||
assert(t, t->state == Thread::ActiveState);
|
assert(t, t->state == Thread::ActiveState);
|
||||||
|
|
||||||
while (t->vm->exclusive) {
|
while (t->m->exclusive) {
|
||||||
// another thread got here first.
|
// another thread got here first.
|
||||||
ENTER(t, Thread::IdleState);
|
ENTER(t, Thread::IdleState);
|
||||||
}
|
}
|
||||||
|
|
||||||
t->state = Thread::ExclusiveState;
|
t->state = Thread::ExclusiveState;
|
||||||
t->vm->exclusive = t;
|
t->m->exclusive = t;
|
||||||
|
|
||||||
while (t->vm->activeCount > 1) {
|
while (t->m->activeCount > 1) {
|
||||||
t->vm->stateLock->wait(t->systemThread, 0);
|
t->m->stateLock->wait(t->systemThread, 0);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
@ -1543,8 +1555,8 @@ enter(Thread* t, Thread::State s)
|
|||||||
case Thread::ZombieState: {
|
case Thread::ZombieState: {
|
||||||
switch (t->state) {
|
switch (t->state) {
|
||||||
case Thread::ExclusiveState: {
|
case Thread::ExclusiveState: {
|
||||||
assert(t, t->vm->exclusive == t);
|
assert(t, t->m->exclusive == t);
|
||||||
t->vm->exclusive = 0;
|
t->m->exclusive = 0;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Thread::ActiveState: break;
|
case Thread::ActiveState: break;
|
||||||
@ -1552,38 +1564,38 @@ enter(Thread* t, Thread::State s)
|
|||||||
default: abort(t);
|
default: abort(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(t, t->vm->activeCount > 0);
|
assert(t, t->m->activeCount > 0);
|
||||||
-- t->vm->activeCount;
|
-- t->m->activeCount;
|
||||||
|
|
||||||
if (s == Thread::ZombieState) {
|
if (s == Thread::ZombieState) {
|
||||||
assert(t, t->vm->liveCount > 0);
|
assert(t, t->m->liveCount > 0);
|
||||||
-- t->vm->liveCount;
|
-- t->m->liveCount;
|
||||||
}
|
}
|
||||||
t->state = s;
|
t->state = s;
|
||||||
|
|
||||||
t->vm->stateLock->notifyAll(t->systemThread);
|
t->m->stateLock->notifyAll(t->systemThread);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Thread::ActiveState: {
|
case Thread::ActiveState: {
|
||||||
switch (t->state) {
|
switch (t->state) {
|
||||||
case Thread::ExclusiveState: {
|
case Thread::ExclusiveState: {
|
||||||
assert(t, t->vm->exclusive == t);
|
assert(t, t->m->exclusive == t);
|
||||||
|
|
||||||
t->state = s;
|
t->state = s;
|
||||||
t->vm->exclusive = 0;
|
t->m->exclusive = 0;
|
||||||
|
|
||||||
t->vm->stateLock->notifyAll(t->systemThread);
|
t->m->stateLock->notifyAll(t->systemThread);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Thread::NoState:
|
case Thread::NoState:
|
||||||
case Thread::IdleState: {
|
case Thread::IdleState: {
|
||||||
while (t->vm->exclusive) {
|
while (t->m->exclusive) {
|
||||||
t->vm->stateLock->wait(t->systemThread, 0);
|
t->m->stateLock->wait(t->systemThread, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
++ t->vm->activeCount;
|
++ t->m->activeCount;
|
||||||
if (t->state == Thread::NoState) {
|
if (t->state == Thread::NoState) {
|
||||||
++ t->vm->liveCount;
|
++ t->m->liveCount;
|
||||||
}
|
}
|
||||||
t->state = s;
|
t->state = s;
|
||||||
} break;
|
} break;
|
||||||
@ -1595,8 +1607,8 @@ enter(Thread* t, Thread::State s)
|
|||||||
case Thread::ExitState: {
|
case Thread::ExitState: {
|
||||||
switch (t->state) {
|
switch (t->state) {
|
||||||
case Thread::ExclusiveState: {
|
case Thread::ExclusiveState: {
|
||||||
assert(t, t->vm->exclusive == t);
|
assert(t, t->m->exclusive == t);
|
||||||
t->vm->exclusive = 0;
|
t->m->exclusive = 0;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Thread::ActiveState: break;
|
case Thread::ActiveState: break;
|
||||||
@ -1604,13 +1616,13 @@ enter(Thread* t, Thread::State s)
|
|||||||
default: abort(t);
|
default: abort(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(t, t->vm->activeCount > 0);
|
assert(t, t->m->activeCount > 0);
|
||||||
-- t->vm->activeCount;
|
-- t->m->activeCount;
|
||||||
|
|
||||||
t->state = s;
|
t->state = s;
|
||||||
|
|
||||||
while (t->vm->liveCount > 1) {
|
while (t->m->liveCount > 1) {
|
||||||
t->vm->stateLock->wait(t->systemThread, 0);
|
t->m->stateLock->wait(t->systemThread, 0);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
@ -1625,9 +1637,9 @@ allocate2(Thread* t, unsigned sizeInBytes)
|
|||||||
return allocateLarge(t, 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
|
// another thread wants to enter the exclusive state, either for a
|
||||||
// collection or some other reason. We give it a chance here.
|
// collection or some other reason. We give it a chance here.
|
||||||
ENTER(t, Thread::IdleState);
|
ENTER(t, Thread::IdleState);
|
||||||
@ -1637,11 +1649,11 @@ allocate2(Thread* t, unsigned sizeInBytes)
|
|||||||
>= Thread::HeapSizeInWords)
|
>= Thread::HeapSizeInWords)
|
||||||
{
|
{
|
||||||
t->heap = 0;
|
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->heap = static_cast<uintptr_t*>
|
||||||
(t->vm->system->tryAllocate(Thread::HeapSizeInBytes));
|
(t->m->system->tryAllocate(Thread::HeapSizeInBytes));
|
||||||
if (t->heap) {
|
if (t->heap) {
|
||||||
t->vm->heapPool[t->vm->heapPoolIndex++] = t->heap;
|
t->m->heapPool[t->m->heapPoolIndex++] = t->heap;
|
||||||
t->heapOffset += t->heapIndex;
|
t->heapOffset += t->heapIndex;
|
||||||
t->heapIndex = 0;
|
t->heapIndex = 0;
|
||||||
}
|
}
|
||||||
@ -1673,10 +1685,10 @@ make(Thread* t, object class_)
|
|||||||
if (UNLIKELY(classVmFlags(t, class_) & WeakReferenceFlag)) {
|
if (UNLIKELY(classVmFlags(t, class_) & WeakReferenceFlag)) {
|
||||||
PROTECT(t, instance);
|
PROTECT(t, instance);
|
||||||
|
|
||||||
ACQUIRE(t, t->vm->referenceLock);
|
ACQUIRE(t, t->m->referenceLock);
|
||||||
|
|
||||||
jreferenceNextUnsafe(t, instance) = t->vm->weakReferences;
|
jreferenceNextUnsafe(t, instance) = t->m->weakReferences;
|
||||||
t->vm->weakReferences = instance;
|
t->m->weakReferences = instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
@ -1709,7 +1721,7 @@ stringChars(Thread* t, object string, char* chars)
|
|||||||
{
|
{
|
||||||
object data = stringData(t, string);
|
object data = stringData(t, string);
|
||||||
if (objectClass(t, data)
|
if (objectClass(t, data)
|
||||||
== arrayBody(t, t->vm->types, Machine::ByteArrayType))
|
== arrayBody(t, t->m->types, Machine::ByteArrayType))
|
||||||
{
|
{
|
||||||
memcpy(chars,
|
memcpy(chars,
|
||||||
&byteArrayBody(t, data, stringOffset(t, string)),
|
&byteArrayBody(t, data, stringOffset(t, string)),
|
||||||
@ -1865,7 +1877,7 @@ hashMapFindNode(Thread* t, object map, object key,
|
|||||||
bool (*equal)(Thread*, object, object))
|
bool (*equal)(Thread*, object, object))
|
||||||
{
|
{
|
||||||
bool weak = objectClass(t, map)
|
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 array = hashMapArray(t, map);
|
||||||
if (array) {
|
if (array) {
|
||||||
@ -1905,7 +1917,7 @@ hashMapResize(Thread* t, object map, uint32_t (*hash)(Thread*, object),
|
|||||||
|
|
||||||
if (oldArray) {
|
if (oldArray) {
|
||||||
bool weak = objectClass(t, map)
|
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) {
|
for (unsigned i = 0; i < arrayLength(t, oldArray); ++i) {
|
||||||
object next;
|
object next;
|
||||||
@ -1934,7 +1946,7 @@ hashMapInsert(Thread* t, object map, object key, object value,
|
|||||||
uint32_t (*hash)(Thread*, object))
|
uint32_t (*hash)(Thread*, object))
|
||||||
{
|
{
|
||||||
bool weak = objectClass(t, map)
|
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 array = hashMapArray(t, map);
|
||||||
PROTECT(t, array);
|
PROTECT(t, array);
|
||||||
@ -1958,8 +1970,8 @@ hashMapInsert(Thread* t, object map, object key, object value,
|
|||||||
|
|
||||||
object r = makeWeakReference(t, 0, 0, 0, 0);
|
object r = makeWeakReference(t, 0, 0, 0, 0);
|
||||||
jreferenceTarget(t, r) = key;
|
jreferenceTarget(t, r) = key;
|
||||||
jreferenceNext(t, r) = t->vm->weakReferences;
|
jreferenceNext(t, r) = t->m->weakReferences;
|
||||||
key = t->vm->weakReferences = r;
|
key = t->m->weakReferences = r;
|
||||||
}
|
}
|
||||||
|
|
||||||
object n = makeTriple(t, key, value, arrayBody(t, array, index));
|
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 (*equal)(Thread*, object, object))
|
||||||
{
|
{
|
||||||
bool weak = objectClass(t, map)
|
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 array = hashMapArray(t, map);
|
||||||
object o = 0;
|
object o = 0;
|
||||||
@ -2004,26 +2016,6 @@ hashMapRemove(Thread* t, object map, object key,
|
|||||||
return o;
|
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
|
object
|
||||||
hashMapIterator(Thread* t, object map)
|
hashMapIterator(Thread* t, object map)
|
||||||
{
|
{
|
||||||
@ -2186,9 +2178,9 @@ object
|
|||||||
findLoadedClass(Thread* t, object spec)
|
findLoadedClass(Thread* t, object spec)
|
||||||
{
|
{
|
||||||
PROTECT(t, 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);
|
spec, byteArrayHash, byteArrayEqual);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2234,7 +2226,7 @@ parseClass(Thread* t, const uint8_t* data, unsigned size)
|
|||||||
0, // fields
|
0, // fields
|
||||||
0, // methods
|
0, // methods
|
||||||
0, // static table
|
0, // static table
|
||||||
t->vm->loader);
|
t->m->loader);
|
||||||
PROTECT(t, class_);
|
PROTECT(t, class_);
|
||||||
|
|
||||||
unsigned super = s.read2();
|
unsigned super = s.read2();
|
||||||
@ -2264,14 +2256,14 @@ object
|
|||||||
resolveClass(Thread* t, object spec)
|
resolveClass(Thread* t, object spec)
|
||||||
{
|
{
|
||||||
PROTECT(t, 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);
|
spec, byteArrayHash, byteArrayEqual);
|
||||||
if (class_ == 0) {
|
if (class_ == 0) {
|
||||||
if (byteArrayBody(t, spec, 0) == '[') {
|
if (byteArrayBody(t, spec, 0) == '[') {
|
||||||
class_ = hashMapFind
|
class_ = hashMapFind
|
||||||
(t, t->vm->bootstrapClassMap, spec, byteArrayHash, byteArrayEqual);
|
(t, t->m->bootstrapClassMap, spec, byteArrayHash, byteArrayEqual);
|
||||||
|
|
||||||
if (class_ == 0) {
|
if (class_ == 0) {
|
||||||
class_ = makeArrayClass(t, spec);
|
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, &byteArrayBody(t, spec, 0), byteArrayLength(t, spec) - 1);
|
||||||
memcpy(file + byteArrayLength(t, spec) - 1, ".class", 7);
|
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 (region) {
|
||||||
if (Verbose) {
|
if (Verbose) {
|
||||||
@ -2298,7 +2290,7 @@ resolveClass(Thread* t, object spec)
|
|||||||
}
|
}
|
||||||
|
|
||||||
object bootstrapClass = hashMapFind
|
object bootstrapClass = hashMapFind
|
||||||
(t, t->vm->bootstrapClassMap, spec, byteArrayHash, byteArrayEqual);
|
(t, t->m->bootstrapClassMap, spec, byteArrayHash, byteArrayEqual);
|
||||||
|
|
||||||
if (bootstrapClass) {
|
if (bootstrapClass) {
|
||||||
PROTECT(t, bootstrapClass);
|
PROTECT(t, bootstrapClass);
|
||||||
@ -2313,7 +2305,7 @@ resolveClass(Thread* t, object spec)
|
|||||||
if (class_) {
|
if (class_) {
|
||||||
PROTECT(t, class_);
|
PROTECT(t, class_);
|
||||||
|
|
||||||
hashMapInsert(t, systemClassLoaderMap(t, t->vm->loader),
|
hashMapInsert(t, systemClassLoaderMap(t, t->m->loader),
|
||||||
spec, class_, byteArrayHash);
|
spec, class_, byteArrayHash);
|
||||||
} else if (t->exception == 0) {
|
} else if (t->exception == 0) {
|
||||||
object message = makeString(t, "%s", &byteArrayBody(t, spec, 0));
|
object message = makeString(t, "%s", &byteArrayBody(t, spec, 0));
|
||||||
@ -2324,6 +2316,27 @@ resolveClass(Thread* t, object spec)
|
|||||||
return class_;
|
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
|
object
|
||||||
resolveObjectArrayClass(Thread* t, object elementSpec)
|
resolveObjectArrayClass(Thread* t, object elementSpec)
|
||||||
{
|
{
|
||||||
@ -2444,18 +2457,18 @@ addFinalizer(Thread* t, object target, void (*finalize)(Thread*, object))
|
|||||||
{
|
{
|
||||||
PROTECT(t, target);
|
PROTECT(t, target);
|
||||||
|
|
||||||
ACQUIRE(t, t->vm->referenceLock);
|
ACQUIRE(t, t->m->referenceLock);
|
||||||
|
|
||||||
object f = makeFinalizer(t, 0, reinterpret_cast<void*>(finalize), 0);
|
object f = makeFinalizer(t, 0, reinterpret_cast<void*>(finalize), 0);
|
||||||
finalizerTarget(t, f) = target;
|
finalizerTarget(t, f) = target;
|
||||||
finalizerNext(t, f) = t->vm->finalizers;
|
finalizerNext(t, f) = t->m->finalizers;
|
||||||
t->vm->finalizers = f;
|
t->m->finalizers = f;
|
||||||
}
|
}
|
||||||
|
|
||||||
System::Monitor*
|
System::Monitor*
|
||||||
objectMonitor(Thread* t, object o)
|
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 (p) {
|
||||||
if (DebugMonitors) {
|
if (DebugMonitors) {
|
||||||
@ -2471,8 +2484,8 @@ objectMonitor(Thread* t, object o)
|
|||||||
ENTER(t, Thread::ExclusiveState);
|
ENTER(t, Thread::ExclusiveState);
|
||||||
|
|
||||||
System::Monitor* m;
|
System::Monitor* m;
|
||||||
System::Status s = t->vm->system->make(&m);
|
System::Status s = t->m->system->make(&m);
|
||||||
expect(t, t->vm->system->success(s));
|
expect(t, t->m->system->success(s));
|
||||||
|
|
||||||
if (DebugMonitors) {
|
if (DebugMonitors) {
|
||||||
fprintf(stderr, "made monitor %p for object %x\n",
|
fprintf(stderr, "made monitor %p for object %x\n",
|
||||||
@ -2481,7 +2494,7 @@ objectMonitor(Thread* t, object o)
|
|||||||
}
|
}
|
||||||
|
|
||||||
p = makePointer(t, m);
|
p = makePointer(t, m);
|
||||||
hashMapInsert(t, t->vm->monitorMap, o, p, objectHash);
|
hashMapInsert(t, t->m->monitorMap, o, p, objectHash);
|
||||||
|
|
||||||
addFinalizer(t, o, removeMonitor);
|
addFinalizer(t, o, removeMonitor);
|
||||||
|
|
||||||
@ -2494,13 +2507,13 @@ intern(Thread* t, object s)
|
|||||||
{
|
{
|
||||||
PROTECT(t, 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) {
|
if (n) {
|
||||||
return jreferenceTarget(t, tripleFirst(t, n));
|
return jreferenceTarget(t, tripleFirst(t, n));
|
||||||
} else {
|
} else {
|
||||||
hashMapInsert(t, t->vm->stringMap, s, 0, stringHash);
|
hashMapInsert(t, t->m->stringMap, s, 0, stringHash);
|
||||||
addFinalizer(t, s, removeString);
|
addFinalizer(t, s, removeString);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@ -2509,7 +2522,7 @@ intern(Thread* t, object s)
|
|||||||
void
|
void
|
||||||
collect(Thread* t, Heap::CollectionType type)
|
collect(Thread* t, Heap::CollectionType type)
|
||||||
{
|
{
|
||||||
Machine* m = t->vm;
|
Machine* m = t->m;
|
||||||
|
|
||||||
class Client: public Heap::Client {
|
class Client: public Heap::Client {
|
||||||
public:
|
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
|
void
|
||||||
noop()
|
noop()
|
||||||
{ }
|
{ }
|
||||||
|
351
src/machine.h
351
src/machine.h
@ -5,6 +5,7 @@
|
|||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "heap.h"
|
#include "heap.h"
|
||||||
#include "finder.h"
|
#include "finder.h"
|
||||||
|
#include "processor.h"
|
||||||
|
|
||||||
#define JNICALL
|
#define JNICALL
|
||||||
|
|
||||||
@ -65,13 +66,6 @@ const unsigned PrimitiveFlag = 1 << 4;
|
|||||||
// method flags:
|
// method flags:
|
||||||
const unsigned ClassInitFlag = 1 << 0;
|
const unsigned ClassInitFlag = 1 << 0;
|
||||||
|
|
||||||
class Machine;
|
|
||||||
class Thread;
|
|
||||||
|
|
||||||
struct Object { };
|
|
||||||
|
|
||||||
typedef Object* object;
|
|
||||||
|
|
||||||
typedef Machine JavaVM;
|
typedef Machine JavaVM;
|
||||||
typedef Thread JNIEnv;
|
typedef Thread JNIEnv;
|
||||||
|
|
||||||
@ -1101,7 +1095,7 @@ class Machine {
|
|||||||
#include "type-enums.cpp"
|
#include "type-enums.cpp"
|
||||||
};
|
};
|
||||||
|
|
||||||
Machine(System* system, Heap* heap, Finder* finder);
|
Machine(System* system, Heap* heap, Finder* finder, Processor* processor);
|
||||||
|
|
||||||
~Machine() {
|
~Machine() {
|
||||||
dispose();
|
dispose();
|
||||||
@ -1115,6 +1109,7 @@ class Machine {
|
|||||||
System* system;
|
System* system;
|
||||||
Heap* heap;
|
Heap* heap;
|
||||||
Finder* finder;
|
Finder* finder;
|
||||||
|
Processor* processor;
|
||||||
Thread* rootThread;
|
Thread* rootThread;
|
||||||
Thread* exclusive;
|
Thread* exclusive;
|
||||||
Reference* jniReferences;
|
Reference* jniReferences;
|
||||||
@ -1144,13 +1139,6 @@ class Machine {
|
|||||||
unsigned heapPoolIndex;
|
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
|
void
|
||||||
printTrace(Thread* t, object exception);
|
printTrace(Thread* t, object exception);
|
||||||
|
|
||||||
@ -1193,9 +1181,10 @@ class Thread {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void run() {
|
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) {
|
if (t->exception) {
|
||||||
printTrace(t, t->exception);
|
printTrace(t, t->exception);
|
||||||
@ -1216,10 +1205,7 @@ class Thread {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const unsigned HeapSizeInBytes = 64 * 1024;
|
static const unsigned HeapSizeInBytes = 64 * 1024;
|
||||||
static const unsigned StackSizeInBytes = 64 * 1024;
|
|
||||||
|
|
||||||
static const unsigned HeapSizeInWords = HeapSizeInBytes / BytesPerWord;
|
static const unsigned HeapSizeInWords = HeapSizeInBytes / BytesPerWord;
|
||||||
static const unsigned StackSizeInWords = StackSizeInBytes / BytesPerWord;
|
|
||||||
|
|
||||||
Thread(Machine* m, object javaThread, Thread* parent);
|
Thread(Machine* m, object javaThread, Thread* parent);
|
||||||
|
|
||||||
@ -1227,7 +1213,7 @@ class Thread {
|
|||||||
void dispose();
|
void dispose();
|
||||||
|
|
||||||
JNIEnvVTable* vtable;
|
JNIEnvVTable* vtable;
|
||||||
Machine* vm;
|
Machine* m;
|
||||||
Thread* parent;
|
Thread* parent;
|
||||||
Thread* peer;
|
Thread* peer;
|
||||||
Thread* child;
|
Thread* child;
|
||||||
@ -1235,12 +1221,8 @@ class Thread {
|
|||||||
unsigned criticalLevel;
|
unsigned criticalLevel;
|
||||||
System::Thread* systemThread;
|
System::Thread* systemThread;
|
||||||
object javaThread;
|
object javaThread;
|
||||||
object code;
|
|
||||||
object exception;
|
object exception;
|
||||||
object large;
|
object large;
|
||||||
unsigned ip;
|
|
||||||
unsigned sp;
|
|
||||||
int frame;
|
|
||||||
unsigned heapIndex;
|
unsigned heapIndex;
|
||||||
unsigned heapOffset;
|
unsigned heapOffset;
|
||||||
Protector* protector;
|
Protector* protector;
|
||||||
@ -1253,7 +1235,6 @@ class Thread {
|
|||||||
uintptr_t* heap;
|
uintptr_t* heap;
|
||||||
uintptr_t defaultHeap[HeapSizeInWords];
|
uintptr_t defaultHeap[HeapSizeInWords];
|
||||||
#endif // not VM_STRESS
|
#endif // not VM_STRESS
|
||||||
uintptr_t stack[StackSizeInWords];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline object
|
inline object
|
||||||
@ -1362,27 +1343,27 @@ class RawMonitorResource {
|
|||||||
inline void NO_RETURN
|
inline void NO_RETURN
|
||||||
abort(Thread* t)
|
abort(Thread* t)
|
||||||
{
|
{
|
||||||
abort(t->vm->system);
|
abort(t->m->system);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
inline void
|
inline void
|
||||||
assert(Thread* t, bool v)
|
assert(Thread* t, bool v)
|
||||||
{
|
{
|
||||||
assert(t->vm->system, v);
|
assert(t->m->system, v);
|
||||||
}
|
}
|
||||||
#endif // not NDEBUG
|
#endif // not NDEBUG
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
expect(Thread* t, bool v)
|
expect(Thread* t, bool v)
|
||||||
{
|
{
|
||||||
expect(t->vm->system, v);
|
expect(t->m->system, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline object
|
inline object
|
||||||
allocateLarge(Thread* t, unsigned sizeInBytes)
|
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
|
inline object
|
||||||
@ -1403,7 +1384,7 @@ allocate(Thread* t, unsigned sizeInBytes)
|
|||||||
|
|
||||||
if (UNLIKELY(t->heapIndex + ceiling(sizeInBytes, BytesPerWord)
|
if (UNLIKELY(t->heapIndex + ceiling(sizeInBytes, BytesPerWord)
|
||||||
>= Thread::HeapSizeInWords
|
>= Thread::HeapSizeInWords
|
||||||
or t->vm->exclusive))
|
or t->m->exclusive))
|
||||||
{
|
{
|
||||||
return allocate2(t, sizeInBytes);
|
return allocate2(t, sizeInBytes);
|
||||||
} else {
|
} else {
|
||||||
@ -1414,9 +1395,9 @@ allocate(Thread* t, unsigned sizeInBytes)
|
|||||||
inline void
|
inline void
|
||||||
mark(Thread* t, object& target)
|
mark(Thread* t, object& target)
|
||||||
{
|
{
|
||||||
if (t->vm->heap->needsMark(reinterpret_cast<void**>(&target))) {
|
if (t->m->heap->needsMark(reinterpret_cast<void**>(&target))) {
|
||||||
ACQUIRE_RAW(t, t->vm->heapLock);
|
ACQUIRE_RAW(t, t->m->heapLock);
|
||||||
t->vm->heap->mark(reinterpret_cast<void**>(&target));
|
t->m->heap->mark(reinterpret_cast<void**>(&target));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1442,10 +1423,14 @@ arrayBodyUnsafe(Thread*, object, unsigned);
|
|||||||
#include "type-declarations.cpp"
|
#include "type-declarations.cpp"
|
||||||
|
|
||||||
object
|
object
|
||||||
makeTrace(Thread* t, int frame);
|
makeTrace(Thread* t, FrameIterator* it);
|
||||||
|
|
||||||
object
|
inline object
|
||||||
makeTrace(Thread* t);
|
makeTrace(Thread* t)
|
||||||
|
{
|
||||||
|
FrameIterator it; t->m->processor->start(t, &it);
|
||||||
|
return makeTrace(t, &it);
|
||||||
|
}
|
||||||
|
|
||||||
inline object
|
inline object
|
||||||
makeRuntimeException(Thread* t, object message)
|
makeRuntimeException(Thread* t, object message)
|
||||||
@ -1595,268 +1580,6 @@ classInitializer(Thread* t, object class_);
|
|||||||
object
|
object
|
||||||
frameMethod(Thread* t, int frame);
|
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
|
inline unsigned
|
||||||
baseSize(Thread* t, object o, object class_)
|
baseSize(Thread* t, object o, object class_)
|
||||||
{
|
{
|
||||||
@ -1897,8 +1620,8 @@ markHashTaken(Thread* t, object o)
|
|||||||
assert(t, not objectExtended(t, o));
|
assert(t, not objectExtended(t, o));
|
||||||
cast<uintptr_t>(o, 0) |= HashTakenMark;
|
cast<uintptr_t>(o, 0) |= HashTakenMark;
|
||||||
|
|
||||||
ACQUIRE_RAW(t, t->vm->heapLock);
|
ACQUIRE_RAW(t, t->m->heapLock);
|
||||||
t->vm->heap->pad(o, 1);
|
t->m->heap->pad(o, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint32_t
|
inline uint32_t
|
||||||
@ -1951,7 +1674,7 @@ stringHash(Thread* t, object s)
|
|||||||
if (stringHashCode(t, s) == 0 and stringLength(t, s)) {
|
if (stringHashCode(t, s) == 0 and stringLength(t, s)) {
|
||||||
object data = stringData(t, s);
|
object data = stringData(t, s);
|
||||||
if (objectClass(t, data)
|
if (objectClass(t, data)
|
||||||
== arrayBody(t, t->vm->types, Machine::ByteArrayType))
|
== arrayBody(t, t->m->types, Machine::ByteArrayType))
|
||||||
{
|
{
|
||||||
stringHashCode(t, s) = hash
|
stringHashCode(t, s) = hash
|
||||||
(&byteArrayBody(t, data, stringOffset(t, s)), stringLength(t, s));
|
(&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);
|
object data = stringData(t, s);
|
||||||
if (objectClass(t, data)
|
if (objectClass(t, data)
|
||||||
== arrayBody(t, t->vm->types, Machine::ByteArrayType))
|
== arrayBody(t, t->m->types, Machine::ByteArrayType))
|
||||||
{
|
{
|
||||||
return byteArrayBody(t, data, i);
|
return byteArrayBody(t, data, i);
|
||||||
} else {
|
} else {
|
||||||
@ -2114,6 +1837,10 @@ parseClass(Thread* t, const uint8_t* data, unsigned length);
|
|||||||
object
|
object
|
||||||
resolveClass(Thread* t, object spec);
|
resolveClass(Thread* t, object spec);
|
||||||
|
|
||||||
|
object
|
||||||
|
resolveMethod(Thread* t, const char* className, const char* methodName,
|
||||||
|
const char* methodSpec);
|
||||||
|
|
||||||
object
|
object
|
||||||
resolveObjectArrayClass(Thread* t, object elementSpec);
|
resolveObjectArrayClass(Thread* t, object elementSpec);
|
||||||
|
|
||||||
@ -2122,14 +1849,14 @@ initClass(Thread* t, object c)
|
|||||||
{
|
{
|
||||||
PROTECT(t, c);
|
PROTECT(t, c);
|
||||||
|
|
||||||
acquire(t, t->vm->classLock);
|
acquire(t, t->m->classLock);
|
||||||
if (classVmFlags(t, c) & NeedInitFlag
|
if (classVmFlags(t, c) & NeedInitFlag
|
||||||
and (classVmFlags(t, c) & InitFlag) == 0)
|
and (classVmFlags(t, c) & InitFlag) == 0)
|
||||||
{
|
{
|
||||||
classVmFlags(t, c) |= InitFlag;
|
classVmFlags(t, c) |= InitFlag;
|
||||||
run(t, classInitializer(t, c), 0);
|
t->m->processor->invoke(t, classInitializer(t, c), 0);
|
||||||
} else {
|
} 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, classArrayElementSize(t, objectClass(t, array)) == BytesPerWord);
|
||||||
assert(t, classObjectMask(t, objectClass(t, array))
|
assert(t, classObjectMask(t, objectClass(t, array))
|
||||||
== classObjectMask(t, arrayBody
|
== classObjectMask(t, arrayBody
|
||||||
(t, t->vm->types, Machine::ArrayType)));
|
(t, t->m->types, Machine::ArrayType)));
|
||||||
return cast<object>(array, (2 + index) * BytesPerWord);
|
return cast<object>(array, (2 + index) * BytesPerWord);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2323,6 +2050,16 @@ intern(Thread* t, object s);
|
|||||||
void
|
void
|
||||||
exit(Thread* t);
|
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
|
} // namespace vm
|
||||||
|
|
||||||
#endif//MACHINE_H
|
#endif//MACHINE_H
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "heap.h"
|
#include "heap.h"
|
||||||
#include "finder.h"
|
#include "finder.h"
|
||||||
#include "run.h"
|
#include "processor.h"
|
||||||
|
#include "machine.h"
|
||||||
|
|
||||||
using namespace vm;
|
using namespace vm;
|
||||||
|
|
||||||
@ -15,9 +16,11 @@ run(unsigned heapSize, const char* path, const char* class_, int argc,
|
|||||||
System* s = makeSystem(heapSize);
|
System* s = makeSystem(heapSize);
|
||||||
Finder* f = makeFinder(s, path);
|
Finder* f = makeFinder(s, path);
|
||||||
Heap* heap = makeHeap(s);
|
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();
|
heap->dispose();
|
||||||
f->dispose();
|
f->dispose();
|
||||||
s->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)) {
|
for (Object* p = typeSubtypes(o); p; p = cdr(p)) {
|
||||||
Object* st = car(p);
|
Object* st = car(p);
|
||||||
out->write(" or objectClass(t, o) == arrayBodyUnsafe");
|
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(capitalize(typeName(st)));
|
||||||
out->write("Type)");
|
out->write("Type)");
|
||||||
writeSubtypeAssertions(out, st);
|
writeSubtypeAssertions(out, st);
|
||||||
@ -1061,9 +1061,9 @@ writeAccessor(Output* out, Object* member, Object* offset, bool unsafe = false)
|
|||||||
if (unsafe) {
|
if (unsafe) {
|
||||||
out->write(" assert(t, true);");
|
out->write(" assert(t, true);");
|
||||||
} else {
|
} else {
|
||||||
out->write(" assert(t, t->vm->unsafe or ");
|
out->write(" assert(t, t->m->unsafe or ");
|
||||||
out->write("objectClass(t, o) == arrayBodyUnsafe");
|
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(capitalize(::typeName(memberOwner(member))));
|
||||||
out->write("Type)");
|
out->write("Type)");
|
||||||
writeSubtypeAssertions(out, memberOwner(member));
|
writeSubtypeAssertions(out, memberOwner(member));
|
||||||
@ -1347,7 +1347,7 @@ writeConstructors(Output* out, Object* declarations)
|
|||||||
out->write(");\n");
|
out->write(");\n");
|
||||||
|
|
||||||
out->write(" cast<object>(o, 0) ");
|
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(capitalize(typeName(o)));
|
||||||
out->write("Type);\n");
|
out->write("Type);\n");
|
||||||
|
|
||||||
@ -1502,7 +1502,7 @@ writeInitialization(Output* out, Object* type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (typeJavaName(type) and typeSuper(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(capitalize(typeName(typeSuper(type))));
|
||||||
out->write("Type);\n");
|
out->write("Type);\n");
|
||||||
} else {
|
} else {
|
||||||
@ -1514,9 +1514,9 @@ writeInitialization(Output* out, Object* type)
|
|||||||
out->write(typeFixedSize(type));
|
out->write(typeFixedSize(type));
|
||||||
out->write(", ");
|
out->write(", ");
|
||||||
out->write(typeArrayElementSize(type));
|
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(capitalize(typeName(type)));
|
||||||
out->write("Type), class_);\n");
|
out->write("Type), class_);\n");
|
||||||
|
|
||||||
@ -1566,14 +1566,14 @@ writeInitializations(Output* out, Object* declarations)
|
|||||||
{
|
{
|
||||||
unsigned count = typeCount(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(count);
|
||||||
out->write(" * sizeof(void*)) + sizeof(uintptr_t) + sizeof(void*)));\n");
|
out->write(" * sizeof(void*)) + sizeof(uintptr_t) + sizeof(void*)));\n");
|
||||||
out->write("cast<object>(t->vm->types, 0) = 0;\n");
|
out->write("cast<object>(t->m->types, 0) = 0;\n");
|
||||||
out->write("arrayLength(t, t->vm->types) = ");
|
out->write("arrayLength(t, t->m->types) = ");
|
||||||
out->write(count);
|
out->write(count);
|
||||||
out->write(";\n");
|
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(count);
|
||||||
out->write(" * sizeof(void*));\n\n");
|
out->write(" * sizeof(void*));\n\n");
|
||||||
|
|
||||||
@ -1596,13 +1596,13 @@ writeJavaInitialization(Output* out, Object* type)
|
|||||||
out->write(typeJavaName(type));
|
out->write(typeJavaName(type));
|
||||||
out->write("\");\n");
|
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(capitalize(typeName(type)));
|
||||||
out->write("Type);\n");
|
out->write("Type);\n");
|
||||||
|
|
||||||
out->write(" set(t, className(t, class_), name);\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("name, class_, byteArrayHash);\n");
|
||||||
|
|
||||||
out->write("}\n\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