mirror of
https://github.com/corda/corda.git
synced 2024-12-28 00:38:55 +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)/stream.h \
|
||||
$(src)/constants.h \
|
||||
$(src)/vm.h
|
||||
$(src)/vm.h \
|
||||
$(src)/vm-jni.h \
|
||||
$(src)/vm-builtin.h \
|
||||
$(src)/vm-declarations.h
|
||||
interpreter-sources = \
|
||||
$(src)/vm.cpp \
|
||||
$(src)/vm-jni.cpp \
|
||||
$(src)/vm-builtin.cpp \
|
||||
$(src)/heap.cpp \
|
||||
$(src)/main.cpp
|
||||
|
||||
|
@ -1479,7 +1479,7 @@ writeInitialization(Output* out, Object* type)
|
||||
if (typeObjectMask(type) != 1) {
|
||||
out->write(" PROTECT(t, mask);\n");
|
||||
}
|
||||
out->write(" object name = makeByteArray(t, \"");
|
||||
out->write(" object name = ::makeByteArray(t, \"");
|
||||
out->write(typeJavaName(type));
|
||||
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
|
||||
#define JNI_VM_H
|
||||
#ifndef VM_DECLARATIONS_H
|
||||
#define VM_DECLARATIONS_H
|
||||
|
||||
#include "stdint.h"
|
||||
#include "stdarg.h"
|
||||
#include "common.h"
|
||||
#include "system.h"
|
||||
#include "heap.h"
|
||||
#include "class-finder.h"
|
||||
|
||||
#define JNIEXPORT
|
||||
#define JNIIMPORT
|
||||
#define JNIEXPORT __attribute__ ((visibility("default")))
|
||||
#define JNIIMPORT __attribute__ ((visibility("hidden")))
|
||||
#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 {
|
||||
|
||||
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 int8_t jbyte;
|
||||
typedef uint16_t jchar;
|
||||
@ -94,14 +146,6 @@ struct JavaVMVTable {
|
||||
(JavaVM*, void**, void*);
|
||||
};
|
||||
|
||||
struct JNIEnvVTable;
|
||||
|
||||
struct JNIEnv {
|
||||
JNIEnv(JNIEnvVTable* vtable): vtable(vtable) { }
|
||||
|
||||
JNIEnvVTable* vtable;
|
||||
};
|
||||
|
||||
struct JNIEnvVTable {
|
||||
void* reserved0;
|
||||
void* reserved1;
|
||||
@ -1025,6 +1069,687 @@ struct JNIEnvVTable {
|
||||
(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
|
||||
|
||||
#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