mirror of
https://github.com/corda/corda.git
synced 2024-12-29 09:18:58 +00:00
factor a lot of code out of vm.cpp, since it was becoming unwieldy
This commit is contained in:
parent
6678d31d5c
commit
427dbedd0f
7
makefile
7
makefile
@ -63,9 +63,14 @@ interpreter-depends = \
|
|||||||
$(src)/class-finder.h \
|
$(src)/class-finder.h \
|
||||||
$(src)/stream.h \
|
$(src)/stream.h \
|
||||||
$(src)/constants.h \
|
$(src)/constants.h \
|
||||||
$(src)/vm.h
|
$(src)/vm.h \
|
||||||
|
$(src)/vm-jni.h \
|
||||||
|
$(src)/vm-builtin.h \
|
||||||
|
$(src)/vm-declarations.h
|
||||||
interpreter-sources = \
|
interpreter-sources = \
|
||||||
$(src)/vm.cpp \
|
$(src)/vm.cpp \
|
||||||
|
$(src)/vm-jni.cpp \
|
||||||
|
$(src)/vm-builtin.cpp \
|
||||||
$(src)/heap.cpp \
|
$(src)/heap.cpp \
|
||||||
$(src)/main.cpp
|
$(src)/main.cpp
|
||||||
|
|
||||||
|
@ -1479,7 +1479,7 @@ writeInitialization(Output* out, Object* type)
|
|||||||
if (typeObjectMask(type) != 1) {
|
if (typeObjectMask(type) != 1) {
|
||||||
out->write(" PROTECT(t, mask);\n");
|
out->write(" PROTECT(t, mask);\n");
|
||||||
}
|
}
|
||||||
out->write(" object name = makeByteArray(t, \"");
|
out->write(" object name = ::makeByteArray(t, \"");
|
||||||
out->write(typeJavaName(type));
|
out->write(typeJavaName(type));
|
||||||
out->write("\");\n");
|
out->write("\");\n");
|
||||||
|
|
||||||
|
97
src/vm-builtin.cpp
Normal file
97
src/vm-builtin.cpp
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
#include "vm-builtin.h"
|
||||||
|
|
||||||
|
namespace vm {
|
||||||
|
namespace builtin {
|
||||||
|
|
||||||
|
void
|
||||||
|
loadLibrary(JNIEnv* e, jstring nameString)
|
||||||
|
{
|
||||||
|
Thread* t = static_cast<Thread*>(e);
|
||||||
|
|
||||||
|
if (LIKELY(nameString)) {
|
||||||
|
object n = *nameString;
|
||||||
|
char name[stringLength(t, n) + 1];
|
||||||
|
memcpy(name,
|
||||||
|
&byteArrayBody(t, stringBytes(t, n), stringOffset(t, n)),
|
||||||
|
stringLength(t, n));
|
||||||
|
name[stringLength(t, n)] = 0;
|
||||||
|
|
||||||
|
System::Library* lib;
|
||||||
|
if (LIKELY(t->vm->system->success
|
||||||
|
(t->vm->system->load(&lib, name, t->vm->libraries))))
|
||||||
|
{
|
||||||
|
t->vm->libraries = lib;
|
||||||
|
} else {
|
||||||
|
object message = makeString(t, "library not found: %s", name);
|
||||||
|
t->exception = makeRuntimeException(t, message);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
t->exception = makeNullPointerException(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jstring
|
||||||
|
toString(JNIEnv* e, jobject this_)
|
||||||
|
{
|
||||||
|
Thread* t = static_cast<Thread*>(e);
|
||||||
|
|
||||||
|
object s = makeString
|
||||||
|
(t, "%s@%p",
|
||||||
|
&byteArrayBody(t, className(t, objectClass(t, *this_)), 0),
|
||||||
|
*this_);
|
||||||
|
|
||||||
|
return pushReference(t, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
jarray
|
||||||
|
trace(JNIEnv* e, jint skipCount)
|
||||||
|
{
|
||||||
|
Thread* t = static_cast<Thread*>(e);
|
||||||
|
|
||||||
|
int frame = t->frame;
|
||||||
|
while (skipCount-- and frame >= 0) {
|
||||||
|
frame = frameNext(t, frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (methodClass(t, frameMethod(t, frame))
|
||||||
|
== arrayBody(t, t->vm->types, Machine::ThrowableType))
|
||||||
|
{
|
||||||
|
// skip Throwable constructors
|
||||||
|
while (strcmp(reinterpret_cast<const int8_t*>("<init>"),
|
||||||
|
&byteArrayBody(t, methodName(t, frameMethod(t, frame)), 0))
|
||||||
|
== 0)
|
||||||
|
{
|
||||||
|
frame = frameNext(t, frame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pushReference(t, makeTrace(t, frame));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
populate(Thread* t, object map)
|
||||||
|
{
|
||||||
|
struct {
|
||||||
|
const char* key;
|
||||||
|
void* value;
|
||||||
|
} builtins[] = {
|
||||||
|
{ "Java_java_lang_Object_toString",
|
||||||
|
reinterpret_cast<void*>(toString) },
|
||||||
|
{ "Java_java_lang_System_loadLibrary",
|
||||||
|
reinterpret_cast<void*>(loadLibrary) },
|
||||||
|
{ "Java_java_lang_Throwable_trace",
|
||||||
|
reinterpret_cast<void*>(trace) },
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
for (unsigned i = 0; builtins[i].key; ++i) {
|
||||||
|
object key = makeByteArray(t, builtins[i].key);
|
||||||
|
PROTECT(t, key);
|
||||||
|
object value = makePointer(t, builtins[i].value);
|
||||||
|
|
||||||
|
hashMapInsert(t, map, key, value, byteArrayHash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace builtin
|
||||||
|
} // namespace vm
|
15
src/vm-builtin.h
Normal file
15
src/vm-builtin.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#ifndef VM_BUITLIN_H
|
||||||
|
#define VM_BUITLIN_H
|
||||||
|
|
||||||
|
#include "vm-declarations.h"
|
||||||
|
|
||||||
|
namespace vm {
|
||||||
|
namespace builtin {
|
||||||
|
|
||||||
|
void
|
||||||
|
populate(Thread* t, object map);
|
||||||
|
|
||||||
|
} // namespace builtin
|
||||||
|
} // namespace vm
|
||||||
|
|
||||||
|
#endif//VM_BUILTIN_H
|
@ -1,15 +1,67 @@
|
|||||||
#ifndef JNI_VM_H
|
#ifndef VM_DECLARATIONS_H
|
||||||
#define JNI_VM_H
|
#define VM_DECLARATIONS_H
|
||||||
|
|
||||||
#include "stdint.h"
|
#include "common.h"
|
||||||
#include "stdarg.h"
|
#include "system.h"
|
||||||
|
#include "heap.h"
|
||||||
|
#include "class-finder.h"
|
||||||
|
|
||||||
#define JNIEXPORT
|
#define JNIEXPORT __attribute__ ((visibility("default")))
|
||||||
#define JNIIMPORT
|
#define JNIIMPORT __attribute__ ((visibility("hidden")))
|
||||||
#define JNICALL
|
#define JNICALL
|
||||||
|
|
||||||
|
#define PROTECT(thread, name) \
|
||||||
|
Thread::Protector MAKE_NAME(protector_) (thread, &name);
|
||||||
|
|
||||||
|
#define ACQUIRE(t, x) MonitorResource MAKE_NAME(monitorResource_) (t, x)
|
||||||
|
|
||||||
|
#define ACQUIRE_RAW(t, x) RawMonitorResource MAKE_NAME(monitorResource_) (t, x)
|
||||||
|
|
||||||
|
#define ENTER(t, state) StateResource MAKE_NAME(stateResource_) (t, state)
|
||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
|
const bool Verbose = false;
|
||||||
|
const bool Debug = false;
|
||||||
|
const bool DebugRun = false;
|
||||||
|
const bool DebugStack = false;
|
||||||
|
|
||||||
|
const uintptr_t HashTakenMark = 1;
|
||||||
|
const uintptr_t ExtendedMark = 2;
|
||||||
|
|
||||||
|
const unsigned FrameBaseOffset = 0;
|
||||||
|
const unsigned FrameNextOffset = 1;
|
||||||
|
const unsigned FrameMethodOffset = 2;
|
||||||
|
const unsigned FrameIpOffset = 3;
|
||||||
|
const unsigned FrameFootprint = 4;
|
||||||
|
|
||||||
|
enum FieldCode {
|
||||||
|
VoidField,
|
||||||
|
ByteField,
|
||||||
|
CharField,
|
||||||
|
DoubleField,
|
||||||
|
FloatField,
|
||||||
|
IntField,
|
||||||
|
LongField,
|
||||||
|
ShortField,
|
||||||
|
BooleanField,
|
||||||
|
ObjectField
|
||||||
|
};
|
||||||
|
|
||||||
|
enum StackTag {
|
||||||
|
IntTag, // must be zero
|
||||||
|
ObjectTag
|
||||||
|
};
|
||||||
|
|
||||||
|
const int NativeLine = -1;
|
||||||
|
const int UnknownLine = -2;
|
||||||
|
|
||||||
|
const unsigned WeakReferenceFlag = 1 << 0;
|
||||||
|
|
||||||
|
class Thread;
|
||||||
|
|
||||||
|
typedef Thread JNIEnv;
|
||||||
|
|
||||||
typedef uint8_t jboolean;
|
typedef uint8_t jboolean;
|
||||||
typedef int8_t jbyte;
|
typedef int8_t jbyte;
|
||||||
typedef uint16_t jchar;
|
typedef uint16_t jchar;
|
||||||
@ -94,14 +146,6 @@ struct JavaVMVTable {
|
|||||||
(JavaVM*, void**, void*);
|
(JavaVM*, void**, void*);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct JNIEnvVTable;
|
|
||||||
|
|
||||||
struct JNIEnv {
|
|
||||||
JNIEnv(JNIEnvVTable* vtable): vtable(vtable) { }
|
|
||||||
|
|
||||||
JNIEnvVTable* vtable;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct JNIEnvVTable {
|
struct JNIEnvVTable {
|
||||||
void* reserved0;
|
void* reserved0;
|
||||||
void* reserved1;
|
void* reserved1;
|
||||||
@ -1025,6 +1069,687 @@ struct JNIEnvVTable {
|
|||||||
(JNIEnv*, jobject);
|
(JNIEnv*, jobject);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline int
|
||||||
|
strcmp(const int8_t* a, const int8_t* b)
|
||||||
|
{
|
||||||
|
return ::strcmp(reinterpret_cast<const char*>(a),
|
||||||
|
reinterpret_cast<const char*>(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
class Machine {
|
||||||
|
public:
|
||||||
|
enum {
|
||||||
|
#include "type-enums.cpp"
|
||||||
|
} Type;
|
||||||
|
|
||||||
|
Machine(System* system, Heap* heap, ClassFinder* classFinder);
|
||||||
|
|
||||||
|
~Machine() {
|
||||||
|
dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
void dispose();
|
||||||
|
|
||||||
|
System* system;
|
||||||
|
Heap* heap;
|
||||||
|
ClassFinder* classFinder;
|
||||||
|
Thread* rootThread;
|
||||||
|
Thread* exclusive;
|
||||||
|
unsigned activeCount;
|
||||||
|
unsigned liveCount;
|
||||||
|
System::Monitor* stateLock;
|
||||||
|
System::Monitor* heapLock;
|
||||||
|
System::Monitor* classLock;
|
||||||
|
System::Monitor* finalizerLock;
|
||||||
|
System::Library* libraries;
|
||||||
|
object classMap;
|
||||||
|
object bootstrapClassMap;
|
||||||
|
object builtinMap;
|
||||||
|
object monitorMap;
|
||||||
|
object types;
|
||||||
|
object finalizers;
|
||||||
|
object doomed;
|
||||||
|
object weakReferences;
|
||||||
|
bool unsafe;
|
||||||
|
JNIEnvVTable jniEnvVTable;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Chain {
|
||||||
|
public:
|
||||||
|
Chain(Chain* next): next(next) { }
|
||||||
|
|
||||||
|
static unsigned footprint(unsigned sizeInBytes) {
|
||||||
|
return sizeof(Chain) + sizeInBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t* data() {
|
||||||
|
return reinterpret_cast<uint8_t*>(this) + sizeof(Chain);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dispose(System* s, Chain* c) {
|
||||||
|
if (c) {
|
||||||
|
if (c->next) dispose(s, c->next);
|
||||||
|
s->free(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Chain* next;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Thread {
|
||||||
|
public:
|
||||||
|
enum State {
|
||||||
|
NoState,
|
||||||
|
ActiveState,
|
||||||
|
IdleState,
|
||||||
|
ZombieState,
|
||||||
|
ExclusiveState,
|
||||||
|
ExitState
|
||||||
|
};
|
||||||
|
|
||||||
|
class Protector {
|
||||||
|
public:
|
||||||
|
Protector(Thread* t, object* p): t(t), p(p), next(t->protector) {
|
||||||
|
t->protector = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
~Protector() {
|
||||||
|
t->protector = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread* t;
|
||||||
|
object* p;
|
||||||
|
Protector* next;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const unsigned HeapSizeInBytes = 64 * 1024;
|
||||||
|
static const unsigned StackSizeInBytes = 64 * 1024;
|
||||||
|
|
||||||
|
static const unsigned HeapSizeInWords = HeapSizeInBytes / BytesPerWord;
|
||||||
|
static const unsigned StackSizeInWords = StackSizeInBytes / BytesPerWord;
|
||||||
|
|
||||||
|
Thread(Machine* m);
|
||||||
|
|
||||||
|
void dispose();
|
||||||
|
|
||||||
|
JNIEnvVTable* vtable;
|
||||||
|
Machine* vm;
|
||||||
|
Thread* next;
|
||||||
|
Thread* child;
|
||||||
|
State state;
|
||||||
|
object thread;
|
||||||
|
object code;
|
||||||
|
object exception;
|
||||||
|
unsigned ip;
|
||||||
|
unsigned sp;
|
||||||
|
int frame;
|
||||||
|
unsigned heapIndex;
|
||||||
|
Protector* protector;
|
||||||
|
Chain* chain;
|
||||||
|
uintptr_t stack[StackSizeInWords];
|
||||||
|
object heap[HeapSizeInWords];
|
||||||
|
};
|
||||||
|
|
||||||
|
inline object
|
||||||
|
objectClass(Thread*, object o)
|
||||||
|
{
|
||||||
|
return mask(cast<object>(o, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void enter(Thread* t, Thread::State state);
|
||||||
|
|
||||||
|
class StateResource {
|
||||||
|
public:
|
||||||
|
StateResource(Thread* t, Thread::State state): t(t), oldState(t->state) {
|
||||||
|
enter(t, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
~StateResource() { enter(t, oldState); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Thread* t;
|
||||||
|
Thread::State oldState;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MonitorResource {
|
||||||
|
public:
|
||||||
|
MonitorResource(Thread* t, System::Monitor* m): t(t), m(m) {
|
||||||
|
if (not m->tryAcquire(t)) {
|
||||||
|
ENTER(t, Thread::IdleState);
|
||||||
|
m->acquire(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~MonitorResource() { m->release(t); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Thread* t;
|
||||||
|
System::Monitor* m;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RawMonitorResource {
|
||||||
|
public:
|
||||||
|
RawMonitorResource(Thread* t, System::Monitor* m): t(t), m(m) {
|
||||||
|
m->acquire(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
~RawMonitorResource() { m->release(t); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Thread* t;
|
||||||
|
System::Monitor* m;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline void NO_RETURN
|
||||||
|
abort(Thread* t)
|
||||||
|
{
|
||||||
|
abort(t->vm->system);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
assert(Thread* t, bool v)
|
||||||
|
{
|
||||||
|
assert(t->vm->system, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
expect(Thread* t, bool v)
|
||||||
|
{
|
||||||
|
expect(t->vm->system, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline object
|
||||||
|
allocateLarge(Thread* t, unsigned sizeInBytes)
|
||||||
|
{
|
||||||
|
void* p = t->vm->system->allocate(Chain::footprint(sizeInBytes));
|
||||||
|
t->chain = new (p) Chain(t->chain);
|
||||||
|
return t->chain->data();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline object
|
||||||
|
allocateSmall(Thread* t, unsigned sizeInBytes)
|
||||||
|
{
|
||||||
|
object o = t->heap + t->heapIndex;
|
||||||
|
t->heapIndex += divide(sizeInBytes, BytesPerWord);
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
allocate2(Thread* t, unsigned sizeInBytes);
|
||||||
|
|
||||||
|
inline object
|
||||||
|
allocate(Thread* t, unsigned sizeInBytes)
|
||||||
|
{
|
||||||
|
if (UNLIKELY(t->heapIndex + divide(sizeInBytes, BytesPerWord)
|
||||||
|
>= Thread::HeapSizeInWords
|
||||||
|
or t->vm->exclusive))
|
||||||
|
{
|
||||||
|
return allocate2(t, sizeInBytes);
|
||||||
|
} else {
|
||||||
|
return allocateSmall(t, sizeInBytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
set(Thread* t, object& target, object value)
|
||||||
|
{
|
||||||
|
target = value;
|
||||||
|
if (t->vm->heap->needsMark(&target)) {
|
||||||
|
ACQUIRE_RAW(t, t->vm->heapLock);
|
||||||
|
t->vm->heap->mark(&target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object&
|
||||||
|
arrayBodyUnsafe(Thread*, object, unsigned);
|
||||||
|
|
||||||
|
#include "type-declarations.cpp"
|
||||||
|
|
||||||
|
object
|
||||||
|
makeTrace(Thread* t, int frame);
|
||||||
|
|
||||||
|
object
|
||||||
|
makeTrace(Thread* t);
|
||||||
|
|
||||||
|
inline object
|
||||||
|
makeRuntimeException(Thread* t, object message)
|
||||||
|
{
|
||||||
|
PROTECT(t, message);
|
||||||
|
object trace = makeTrace(t);
|
||||||
|
return makeRuntimeException(t, message, trace, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline object
|
||||||
|
makeArrayIndexOutOfBoundsException(Thread* t, object message)
|
||||||
|
{
|
||||||
|
PROTECT(t, message);
|
||||||
|
object trace = makeTrace(t);
|
||||||
|
return makeArrayIndexOutOfBoundsException(t, message, trace, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline object
|
||||||
|
makeNegativeArrayStoreException(Thread* t, object message)
|
||||||
|
{
|
||||||
|
PROTECT(t, message);
|
||||||
|
object trace = makeTrace(t);
|
||||||
|
return makeNegativeArrayStoreException(t, message, trace, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline object
|
||||||
|
makeClassCastException(Thread* t, object message)
|
||||||
|
{
|
||||||
|
PROTECT(t, message);
|
||||||
|
object trace = makeTrace(t);
|
||||||
|
return makeClassCastException(t, message, trace, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline object
|
||||||
|
makeClassNotFoundException(Thread* t, object message)
|
||||||
|
{
|
||||||
|
PROTECT(t, message);
|
||||||
|
object trace = makeTrace(t);
|
||||||
|
return makeClassNotFoundException(t, message, trace, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline object
|
||||||
|
makeNullPointerException(Thread* t)
|
||||||
|
{
|
||||||
|
return makeNullPointerException(t, 0, makeTrace(t), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline object
|
||||||
|
makeStackOverflowError(Thread* t)
|
||||||
|
{
|
||||||
|
return makeStackOverflowError(t, 0, makeTrace(t), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline object
|
||||||
|
makeNoSuchFieldError(Thread* t, object message)
|
||||||
|
{
|
||||||
|
PROTECT(t, message);
|
||||||
|
object trace = makeTrace(t);
|
||||||
|
return makeNoSuchFieldError(t, message, trace, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline object
|
||||||
|
makeNoSuchMethodError(Thread* t, object message)
|
||||||
|
{
|
||||||
|
PROTECT(t, message);
|
||||||
|
object trace = makeTrace(t);
|
||||||
|
return makeNoSuchMethodError(t, message, trace, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline object
|
||||||
|
makeUnsatisfiedLinkError(Thread* t, object message)
|
||||||
|
{
|
||||||
|
PROTECT(t, message);
|
||||||
|
object trace = makeTrace(t);
|
||||||
|
return makeUnsatisfiedLinkError(t, message, trace, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
makeByteArray(Thread* t, const char* format, ...);
|
||||||
|
|
||||||
|
object
|
||||||
|
makeString(Thread* t, const char* format, ...);
|
||||||
|
|
||||||
|
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
|
||||||
|
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 & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 " LD " 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 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 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 " LD " 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 + 2, value & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline object*
|
||||||
|
pushReference(Thread* t, object o)
|
||||||
|
{
|
||||||
|
expect(t, t->sp + 1 < Thread::StackSizeInWords / 2);
|
||||||
|
pushObject(t, o);
|
||||||
|
return reinterpret_cast<object*>(t->stack + ((t->sp - 1) * 2) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
makeTrace(Thread* t)
|
||||||
|
{
|
||||||
|
pokeInt(t, t->frame + FrameIpOffset, t->ip);
|
||||||
|
return makeTrace(t, t->frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint32_t
|
||||||
|
hash(const int8_t* s, unsigned length)
|
||||||
|
{
|
||||||
|
uint32_t h = 0;
|
||||||
|
for (unsigned i = 0; i < length; ++i) h = (h * 31) + s[i];
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline unsigned
|
||||||
|
baseSize(Thread* t, object o, object class_)
|
||||||
|
{
|
||||||
|
return divide(classFixedSize(t, class_), BytesPerWord)
|
||||||
|
+ divide(classArrayElementSize(t, class_)
|
||||||
|
* cast<uint32_t>(o, classFixedSize(t, class_) - 4),
|
||||||
|
BytesPerWord);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
objectExtended(Thread*, object o)
|
||||||
|
{
|
||||||
|
return (cast<uintptr_t>(o, 0) & (~PointerMask)) == ExtendedMark;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uintptr_t&
|
||||||
|
extendedWord(Thread* t, object o, unsigned baseSize)
|
||||||
|
{
|
||||||
|
assert(t, objectExtended(t, o));
|
||||||
|
return cast<uintptr_t>(o, baseSize * BytesPerWord);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline unsigned
|
||||||
|
extendedSize(Thread* t, object o, unsigned baseSize)
|
||||||
|
{
|
||||||
|
return baseSize + objectExtended(t, o);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
hashTaken(Thread*, object o)
|
||||||
|
{
|
||||||
|
return (cast<uintptr_t>(o, 0) & (~PointerMask)) == HashTakenMark;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
markHashTaken(Thread* t, object o)
|
||||||
|
{
|
||||||
|
assert(t, not objectExtended(t, o));
|
||||||
|
cast<uintptr_t>(o, 0) |= HashTakenMark;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint32_t
|
||||||
|
takeHash(Thread*, object o)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<uintptr_t>(o) / BytesPerWord;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint32_t
|
||||||
|
objectHash(Thread* t, object o)
|
||||||
|
{
|
||||||
|
if (objectExtended(t, o)) {
|
||||||
|
return extendedWord(t, o, baseSize(t, o, objectClass(t, o)));
|
||||||
|
} else {
|
||||||
|
markHashTaken(t, o);
|
||||||
|
return takeHash(t, o);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
objectEqual(Thread*, object a, object b)
|
||||||
|
{
|
||||||
|
return a == b;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint32_t
|
||||||
|
referenceHash(Thread* t, object o)
|
||||||
|
{
|
||||||
|
return objectHash(t, jreferenceTarget(t, o));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
referenceEqual(Thread* t, object a, object b)
|
||||||
|
{
|
||||||
|
return a == jreferenceTarget(t, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint32_t
|
||||||
|
byteArrayHash(Thread* t, object array)
|
||||||
|
{
|
||||||
|
return hash(&byteArrayBody(t, array, 0), byteArrayLength(t, array));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
byteArrayEqual(Thread* t, object a, object b)
|
||||||
|
{
|
||||||
|
return a == b or
|
||||||
|
((byteArrayLength(t, a) == byteArrayLength(t, b)) and
|
||||||
|
memcmp(&byteArrayBody(t, a, 0), &byteArrayBody(t, b, 0),
|
||||||
|
byteArrayLength(t, a)) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
intArrayEqual(Thread* t, object a, object b)
|
||||||
|
{
|
||||||
|
return a == b or
|
||||||
|
((intArrayLength(t, a) == intArrayLength(t, b)) and
|
||||||
|
memcmp(&intArrayBody(t, a, 0), &intArrayBody(t, b, 0),
|
||||||
|
intArrayLength(t, a) * 4) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint32_t
|
||||||
|
methodHash(Thread* t, object method)
|
||||||
|
{
|
||||||
|
return byteArrayHash(t, methodName(t, method))
|
||||||
|
^ byteArrayHash(t, methodSpec(t, method));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
methodEqual(Thread* t, object a, object b)
|
||||||
|
{
|
||||||
|
return a == b or
|
||||||
|
(byteArrayEqual(t, methodName(t, a), methodName(t, b)) and
|
||||||
|
byteArrayEqual(t, methodSpec(t, a), methodSpec(t, b)));
|
||||||
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
hashMapFindNode(Thread* t, object map, object key,
|
||||||
|
uint32_t (*hash)(Thread*, object),
|
||||||
|
bool (*equal)(Thread*, object, object));
|
||||||
|
|
||||||
|
inline object
|
||||||
|
hashMapFind(Thread* t, object map, object key,
|
||||||
|
uint32_t (*hash)(Thread*, object),
|
||||||
|
bool (*equal)(Thread*, object, object))
|
||||||
|
{
|
||||||
|
object n = hashMapFindNode(t, map, key, hash, equal);
|
||||||
|
return (n ? tripleSecond(t, n) : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
hashMapResize(Thread* t, object map, uint32_t (*hash)(Thread*, object),
|
||||||
|
unsigned size);
|
||||||
|
|
||||||
|
void
|
||||||
|
hashMapInsert(Thread* t, object map, object key, object value,
|
||||||
|
uint32_t (*hash)(Thread*, object));
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
hashMapInsertOrReplace(Thread* t, object map, object key, object value,
|
||||||
|
uint32_t (*hash)(Thread*, object),
|
||||||
|
bool (*equal)(Thread*, object, object))
|
||||||
|
{
|
||||||
|
object n = hashMapFindNode(t, map, key, hash, equal);
|
||||||
|
if (n == 0) {
|
||||||
|
hashMapInsert(t, map, key, value, hash);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
set(t, tripleSecond(t, n), value);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
hashMapRemove(Thread* t, object map, object key,
|
||||||
|
uint32_t (*hash)(Thread*, object),
|
||||||
|
bool (*equal)(Thread*, object, object));
|
||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
|
||||||
#endif//JNI_VM_H
|
#endif//VM_DECLARATIONS_H
|
66
src/vm-jni.cpp
Normal file
66
src/vm-jni.cpp
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#include "vm-jni.h"
|
||||||
|
#include "vm-declarations.h"
|
||||||
|
|
||||||
|
namespace vm {
|
||||||
|
namespace jni {
|
||||||
|
|
||||||
|
jsize
|
||||||
|
GetStringUTFLength(JNIEnv* e, jstring s)
|
||||||
|
{
|
||||||
|
Thread* t = static_cast<Thread*>(e);
|
||||||
|
|
||||||
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
|
jsize length = 0;
|
||||||
|
if (LIKELY(s)) {
|
||||||
|
length = stringLength(t, *s);
|
||||||
|
} else {
|
||||||
|
t->exception = makeNullPointerException(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char*
|
||||||
|
GetStringUTFChars(JNIEnv* e, jstring s, jboolean* isCopy)
|
||||||
|
{
|
||||||
|
Thread* t = static_cast<Thread*>(e);
|
||||||
|
|
||||||
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
|
char* chars = 0;
|
||||||
|
if (LIKELY(s)) {
|
||||||
|
chars = static_cast<char*>
|
||||||
|
(t->vm->system->allocate(stringLength(t, *s) + 1));
|
||||||
|
|
||||||
|
memcpy(chars,
|
||||||
|
&byteArrayBody(t, stringBytes(t, *s), stringOffset(t, *s)),
|
||||||
|
stringLength(t, *s));
|
||||||
|
|
||||||
|
chars[stringLength(t, *s)] = 0;
|
||||||
|
} else {
|
||||||
|
t->exception = makeNullPointerException(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isCopy) *isCopy = true;
|
||||||
|
return chars;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ReleaseStringUTFChars(JNIEnv* e, jstring, const char* chars)
|
||||||
|
{
|
||||||
|
static_cast<Thread*>(e)->vm->system->free(chars);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
populate(JNIEnvVTable* table)
|
||||||
|
{
|
||||||
|
memset(table, 0, sizeof(JNIEnvVTable));
|
||||||
|
|
||||||
|
table->GetStringUTFLength = jni::GetStringUTFLength;
|
||||||
|
table->GetStringUTFChars = jni::GetStringUTFChars;
|
||||||
|
table->ReleaseStringUTFChars = jni::ReleaseStringUTFChars;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace jni
|
||||||
|
} // namespace vm
|
15
src/vm-jni.h
Normal file
15
src/vm-jni.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#ifndef VM_JNI_H
|
||||||
|
#define VM_JNI_H
|
||||||
|
|
||||||
|
#include "vm-declarations.h"
|
||||||
|
|
||||||
|
namespace vm {
|
||||||
|
namespace jni {
|
||||||
|
|
||||||
|
void
|
||||||
|
populate(JNIEnvVTable* table);
|
||||||
|
|
||||||
|
} // namespace jni
|
||||||
|
} // namespace vm
|
||||||
|
|
||||||
|
#endif//VM_JNI_H
|
1647
src/vm.cpp
1647
src/vm.cpp
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user