mirror of
https://github.com/corda/corda.git
synced 2024-12-29 09:18:58 +00:00
several things: change object typedef to Object* instead of void* to improve type safety; add JNICALL attributes to JNI functions; implement additional JavaVM methods
This commit is contained in:
parent
a4b4f36c5b
commit
bd4d9fdeb2
2
makefile
2
makefile
@ -17,7 +17,7 @@ classpath = classpath
|
|||||||
test = test
|
test = test
|
||||||
jscheme = $(HOME)/p/jscheme-7.2/src
|
jscheme = $(HOME)/p/jscheme-7.2/src
|
||||||
|
|
||||||
input = $(cls)/References.class
|
input = $(cls)/GC.class
|
||||||
|
|
||||||
cxx = g++
|
cxx = g++
|
||||||
cc = gcc
|
cc = gcc
|
||||||
|
@ -13,7 +13,7 @@ replace(char a, char b, char* c)
|
|||||||
for (; *c; ++c) if (*c == a) *c = b;
|
for (; *c; ++c) if (*c == a) *c = b;
|
||||||
}
|
}
|
||||||
|
|
||||||
jstring
|
jstring JNICALL
|
||||||
Object_toString(Thread* t, jobject this_)
|
Object_toString(Thread* t, jobject this_)
|
||||||
{
|
{
|
||||||
unsigned hash = objectHash(t, *this_);
|
unsigned hash = objectHash(t, *this_);
|
||||||
@ -25,47 +25,47 @@ Object_toString(Thread* t, jobject this_)
|
|||||||
return pushReference(t, s);
|
return pushReference(t, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
jclass
|
jclass JNICALL
|
||||||
Object_getClass(Thread* t, jobject this_)
|
Object_getClass(Thread* t, jobject this_)
|
||||||
{
|
{
|
||||||
return pushReference(t, objectClass(t, *this_));
|
return pushReference(t, objectClass(t, *this_));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void JNICALL
|
||||||
Object_wait(Thread* t, jobject this_, jlong milliseconds)
|
Object_wait(Thread* t, jobject this_, jlong milliseconds)
|
||||||
{
|
{
|
||||||
vm::wait(t, *this_, milliseconds);
|
vm::wait(t, *this_, milliseconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void JNICALL
|
||||||
Object_notify(Thread* t, jobject this_)
|
Object_notify(Thread* t, jobject this_)
|
||||||
{
|
{
|
||||||
notify(t, *this_);
|
notify(t, *this_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void JNICALL
|
||||||
Object_notifyAll(Thread* t, jobject this_)
|
Object_notifyAll(Thread* t, jobject this_)
|
||||||
{
|
{
|
||||||
notifyAll(t, *this_);
|
notifyAll(t, *this_);
|
||||||
}
|
}
|
||||||
|
|
||||||
jint
|
jint JNICALL
|
||||||
Object_hashCode(Thread* t, jobject this_)
|
Object_hashCode(Thread* t, jobject this_)
|
||||||
{
|
{
|
||||||
return objectHash(t, *this_);
|
return objectHash(t, *this_);
|
||||||
}
|
}
|
||||||
|
|
||||||
jobject
|
jobject JNICALL
|
||||||
Object_clone(Thread* t, jclass, jobject o)
|
Object_clone(Thread* t, jclass, jobject o)
|
||||||
{
|
{
|
||||||
object clone = make(t, objectClass(t, *o));
|
object clone = make(t, objectClass(t, *o));
|
||||||
memcpy(static_cast<void**>(clone) + 1,
|
memcpy(reinterpret_cast<void**>(clone) + 1,
|
||||||
static_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 pushReference(t, clone);
|
||||||
}
|
}
|
||||||
|
|
||||||
jclass
|
jclass JNICALL
|
||||||
ClassLoader_defineClass(Thread* t, jclass, jbyteArray b, jint offset,
|
ClassLoader_defineClass(Thread* t, jclass, jbyteArray b, jint offset,
|
||||||
jint length)
|
jint length)
|
||||||
{
|
{
|
||||||
@ -101,19 +101,19 @@ search(Thread* t, jstring name, object (*op)(Thread*, object),
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
jclass
|
jclass JNICALL
|
||||||
SystemClassLoader_findLoadedClass(Thread* t, jclass, jstring name)
|
SystemClassLoader_findLoadedClass(Thread* t, jclass, jstring name)
|
||||||
{
|
{
|
||||||
return search(t, name, findLoadedClass, true);
|
return search(t, name, findLoadedClass, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
jclass
|
jclass JNICALL
|
||||||
SystemClassLoader_findClass(Thread* t, jclass, jstring name)
|
SystemClassLoader_findClass(Thread* t, jclass, jstring name)
|
||||||
{
|
{
|
||||||
return search(t, name, resolveClass, true);
|
return search(t, name, resolveClass, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
jboolean
|
jboolean JNICALL
|
||||||
SystemClassLoader_resourceExists(Thread* t, jclass, jstring name)
|
SystemClassLoader_resourceExists(Thread* t, jclass, jstring name)
|
||||||
{
|
{
|
||||||
if (LIKELY(name)) {
|
if (LIKELY(name)) {
|
||||||
@ -126,13 +126,13 @@ SystemClassLoader_resourceExists(Thread* t, jclass, jstring name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
jobject
|
jobject JNICALL
|
||||||
ObjectInputStream_makeInstance(Thread* t, jclass, jclass c)
|
ObjectInputStream_makeInstance(Thread* t, jclass, jclass c)
|
||||||
{
|
{
|
||||||
return pushReference(t, make(t, *c));
|
return pushReference(t, make(t, *c));
|
||||||
}
|
}
|
||||||
|
|
||||||
jclass
|
jclass JNICALL
|
||||||
Class_primitiveClass(Thread* t, jclass, jchar name)
|
Class_primitiveClass(Thread* t, jclass, jchar name)
|
||||||
{
|
{
|
||||||
switch (name) {
|
switch (name) {
|
||||||
@ -160,13 +160,13 @@ Class_primitiveClass(Thread* t, jclass, jchar name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void JNICALL
|
||||||
Class_initialize(Thread* t, jobject this_)
|
Class_initialize(Thread* t, jobject this_)
|
||||||
{
|
{
|
||||||
initClass(t, *this_);
|
initClass(t, *this_);
|
||||||
}
|
}
|
||||||
|
|
||||||
jboolean
|
jboolean JNICALL
|
||||||
Class_isAssignableFrom(Thread* t, jobject this_, jclass that)
|
Class_isAssignableFrom(Thread* t, jobject this_, jclass that)
|
||||||
{
|
{
|
||||||
if (LIKELY(that)) {
|
if (LIKELY(that)) {
|
||||||
@ -177,7 +177,7 @@ Class_isAssignableFrom(Thread* t, jobject this_, jclass that)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
jlong
|
jlong JNICALL
|
||||||
Field_getPrimitive(Thread* t, jclass, jobject instance, jint code, jint offset)
|
Field_getPrimitive(Thread* t, jclass, jobject instance, jint code, jint offset)
|
||||||
{
|
{
|
||||||
switch (code) {
|
switch (code) {
|
||||||
@ -202,13 +202,13 @@ Field_getPrimitive(Thread* t, jclass, jobject instance, jint code, jint offset)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
jobject
|
jobject JNICALL
|
||||||
Field_getObject(Thread* t, jclass, jobject instance, jint offset)
|
Field_getObject(Thread* t, jclass, jobject instance, jint offset)
|
||||||
{
|
{
|
||||||
return pushReference(t, cast<object>(*instance, offset));
|
return pushReference(t, cast<object>(*instance, offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void JNICALL
|
||||||
Field_setPrimitive(Thread* t, jclass, jobject instance, jint code, jint offset,
|
Field_setPrimitive(Thread* t, jclass, jobject instance, jint code, jint offset,
|
||||||
jlong value)
|
jlong value)
|
||||||
{
|
{
|
||||||
@ -242,27 +242,27 @@ Field_setPrimitive(Thread* t, jclass, jobject instance, jint code, jint offset,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void JNICALL
|
||||||
Field_setObject(Thread* t, jclass, jobject instance, jint offset,
|
Field_setObject(Thread* t, jclass, jobject instance, jint offset,
|
||||||
jobject value)
|
jobject value)
|
||||||
{
|
{
|
||||||
set(t, cast<object>(*instance, offset), (value ? *value : 0));
|
set(t, cast<object>(*instance, offset), (value ? *value : 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
jobject
|
jobject JNICALL
|
||||||
Constructor_make(Thread* t, jclass, jclass c)
|
Constructor_make(Thread* t, jclass, jclass c)
|
||||||
{
|
{
|
||||||
return pushReference(t, make(t, *c));
|
return pushReference(t, make(t, *c));
|
||||||
}
|
}
|
||||||
|
|
||||||
jobject
|
jobject JNICALL
|
||||||
Method_getCaller(Thread* t, jclass)
|
Method_getCaller(Thread* t, jclass)
|
||||||
{
|
{
|
||||||
return pushReference
|
return pushReference
|
||||||
(t, frameMethod(t, frameNext(t, frameNext(t, t->frame))));
|
(t, frameMethod(t, frameNext(t, frameNext(t, t->frame))));
|
||||||
}
|
}
|
||||||
|
|
||||||
jobject
|
jobject JNICALL
|
||||||
Method_invoke(Thread* t, jclass, jobject method, jobject instance,
|
Method_invoke(Thread* t, jclass, jobject method, jobject instance,
|
||||||
jobjectArray arguments)
|
jobjectArray arguments)
|
||||||
{
|
{
|
||||||
@ -273,7 +273,7 @@ Method_invoke(Thread* t, jclass, jobject method, jobject instance,
|
|||||||
return pushReference(t, v);
|
return pushReference(t, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
jint
|
jint JNICALL
|
||||||
Array_getLength(Thread* t, jclass, jobject array)
|
Array_getLength(Thread* t, jclass, jobject array)
|
||||||
{
|
{
|
||||||
if (LIKELY(array)) {
|
if (LIKELY(array)) {
|
||||||
@ -291,47 +291,47 @@ Array_getLength(Thread* t, jclass, jobject array)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
jobject
|
jobject JNICALL
|
||||||
Array_makeObjectArray(Thread* t, jclass, jclass elementType, jint length)
|
Array_makeObjectArray(Thread* t, jclass, jclass elementType, jint length)
|
||||||
{
|
{
|
||||||
return pushReference(t, makeObjectArray(t, *elementType, length, true));
|
return pushReference(t, makeObjectArray(t, *elementType, length, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
jint
|
jint JNICALL
|
||||||
Float_floatToRawIntBits(Thread*, jclass, jfloat v)
|
Float_floatToRawIntBits(Thread*, jclass, jfloat v)
|
||||||
{
|
{
|
||||||
int32_t r; memcpy(&r, &v, 4);
|
int32_t r; memcpy(&r, &v, 4);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
jfloat
|
jfloat JNICALL
|
||||||
Float_intBitsToFloat(Thread*, jclass, jint v)
|
Float_intBitsToFloat(Thread*, jclass, jint v)
|
||||||
{
|
{
|
||||||
jfloat r; memcpy(&r, &v, 4);
|
jfloat r; memcpy(&r, &v, 4);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
jlong
|
jlong JNICALL
|
||||||
Double_doubleToRawLongBits(Thread*, jclass, jdouble v)
|
Double_doubleToRawLongBits(Thread*, jclass, jdouble v)
|
||||||
{
|
{
|
||||||
int64_t r; memcpy(&r, &v, 8);
|
int64_t r; memcpy(&r, &v, 8);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
jdouble
|
jdouble JNICALL
|
||||||
Double_longBitsToDouble(Thread*, jclass, jlong v)
|
Double_longBitsToDouble(Thread*, jclass, jlong v)
|
||||||
{
|
{
|
||||||
jdouble r; memcpy(&r, &v, 8);
|
jdouble r; memcpy(&r, &v, 8);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
jobject
|
jobject JNICALL
|
||||||
String_intern(Thread* t, jobject this_)
|
String_intern(Thread* t, jobject this_)
|
||||||
{
|
{
|
||||||
return pushReference(t, intern(t, *this_));
|
return pushReference(t, intern(t, *this_));
|
||||||
}
|
}
|
||||||
|
|
||||||
jstring
|
jstring JNICALL
|
||||||
System_getVMProperty(Thread* t, jclass, jint code)
|
System_getVMProperty(Thread* t, jclass, jint code)
|
||||||
{
|
{
|
||||||
enum {
|
enum {
|
||||||
@ -348,7 +348,7 @@ System_getVMProperty(Thread* t, jclass, jint code)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void JNICALL
|
||||||
System_arraycopy(Thread* t, jclass, jobject src, jint srcOffset, jobject dst,
|
System_arraycopy(Thread* t, jclass, jobject src, jint srcOffset, jobject dst,
|
||||||
jint dstOffset, jint length)
|
jint dstOffset, jint length)
|
||||||
{
|
{
|
||||||
@ -388,7 +388,7 @@ System_arraycopy(Thread* t, jclass, jobject src, jint srcOffset, jobject dst,
|
|||||||
t->exception = makeArrayStoreException(t);
|
t->exception = makeArrayStoreException(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
jint
|
jint JNICALL
|
||||||
System_identityHashCode(Thread* t, jclass, jobject o)
|
System_identityHashCode(Thread* t, jclass, jobject o)
|
||||||
{
|
{
|
||||||
if (LIKELY(o)) {
|
if (LIKELY(o)) {
|
||||||
@ -399,7 +399,7 @@ System_identityHashCode(Thread* t, jclass, jobject o)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void JNICALL
|
||||||
Runtime_loadLibrary(Thread* t, jobject, jstring name)
|
Runtime_loadLibrary(Thread* t, jobject, jstring name)
|
||||||
{
|
{
|
||||||
if (LIKELY(name)) {
|
if (LIKELY(name)) {
|
||||||
@ -427,7 +427,7 @@ Runtime_loadLibrary(Thread* t, jobject, jstring name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void JNICALL
|
||||||
Runtime_gc(Thread* t, jobject)
|
Runtime_gc(Thread* t, jobject)
|
||||||
{
|
{
|
||||||
ENTER(t, Thread::ExclusiveState);
|
ENTER(t, Thread::ExclusiveState);
|
||||||
@ -435,20 +435,20 @@ Runtime_gc(Thread* t, jobject)
|
|||||||
collect(t, Heap::MajorCollection);
|
collect(t, Heap::MajorCollection);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void JNICALL
|
||||||
Runtime_exit(Thread* t, jobject, jint code)
|
Runtime_exit(Thread* t, jobject, jint code)
|
||||||
{
|
{
|
||||||
t->vm->system->exit(code);
|
t->vm->system->exit(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
jlong
|
jlong JNICALL
|
||||||
Runtime_freeMemory(Thread*, jobject)
|
Runtime_freeMemory(Thread*, jobject)
|
||||||
{
|
{
|
||||||
// todo
|
// todo
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
jobject
|
jobject JNICALL
|
||||||
Throwable_trace(Thread* t, jclass, jint skipCount)
|
Throwable_trace(Thread* t, jclass, jint skipCount)
|
||||||
{
|
{
|
||||||
int frame = t->frame;
|
int frame = t->frame;
|
||||||
@ -471,7 +471,7 @@ Throwable_trace(Thread* t, jclass, jint skipCount)
|
|||||||
return pushReference(t, makeTrace(t, frame));
|
return pushReference(t, makeTrace(t, frame));
|
||||||
}
|
}
|
||||||
|
|
||||||
jarray
|
jarray JNICALL
|
||||||
Throwable_resolveTrace(Thread* t, jclass, jobject trace)
|
Throwable_resolveTrace(Thread* t, jclass, jobject trace)
|
||||||
{
|
{
|
||||||
unsigned length = arrayLength(t, *trace);
|
unsigned length = arrayLength(t, *trace);
|
||||||
@ -505,13 +505,13 @@ Throwable_resolveTrace(Thread* t, jclass, jobject trace)
|
|||||||
return pushReference(t, array);
|
return pushReference(t, array);
|
||||||
}
|
}
|
||||||
|
|
||||||
jobject
|
jobject JNICALL
|
||||||
Thread_currentThread(Thread* t, jclass)
|
Thread_currentThread(Thread* t, jclass)
|
||||||
{
|
{
|
||||||
return pushReference(t, t->javaThread);
|
return pushReference(t, t->javaThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
jlong
|
jlong JNICALL
|
||||||
Thread_doStart(Thread* t, jobject this_)
|
Thread_doStart(Thread* t, jobject this_)
|
||||||
{
|
{
|
||||||
Thread* p = new (t->vm->system->allocate(sizeof(Thread)))
|
Thread* p = new (t->vm->system->allocate(sizeof(Thread)))
|
||||||
@ -527,13 +527,13 @@ Thread_doStart(Thread* t, jobject this_)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void JNICALL
|
||||||
Thread_interrupt(Thread* t, jclass, jlong peer)
|
Thread_interrupt(Thread* t, jclass, jlong peer)
|
||||||
{
|
{
|
||||||
interrupt(t, reinterpret_cast<Thread*>(peer));
|
interrupt(t, reinterpret_cast<Thread*>(peer));
|
||||||
}
|
}
|
||||||
|
|
||||||
jlong
|
jlong JNICALL
|
||||||
ResourceInputStream_open(Thread* t, jclass, jstring path)
|
ResourceInputStream_open(Thread* t, jclass, jstring path)
|
||||||
{
|
{
|
||||||
if (LIKELY(path)) {
|
if (LIKELY(path)) {
|
||||||
@ -547,7 +547,7 @@ ResourceInputStream_open(Thread* t, jclass, jstring path)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
jint
|
jint JNICALL
|
||||||
ResourceInputStream_read(Thread*, jclass, jlong peer, jint position)
|
ResourceInputStream_read(Thread*, jclass, jlong peer, jint position)
|
||||||
{
|
{
|
||||||
Finder::Data* d = reinterpret_cast<Finder::Data*>(peer);
|
Finder::Data* d = reinterpret_cast<Finder::Data*>(peer);
|
||||||
@ -558,7 +558,7 @@ ResourceInputStream_read(Thread*, jclass, jlong peer, jint position)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
jint
|
jint JNICALL
|
||||||
ResourceInputStream_read2(Thread* t, jclass, jlong peer, jint position,
|
ResourceInputStream_read2(Thread* t, jclass, jlong peer, jint position,
|
||||||
jbyteArray b, jint offset, jint length)
|
jbyteArray b, jint offset, jint length)
|
||||||
{
|
{
|
||||||
@ -574,7 +574,7 @@ ResourceInputStream_read2(Thread* t, jclass, jlong peer, jint position,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void JNICALL
|
||||||
ResourceInputStream_close(Thread*, jclass, jlong peer)
|
ResourceInputStream_close(Thread*, jclass, jlong peer)
|
||||||
{
|
{
|
||||||
reinterpret_cast<Finder::Data*>(peer)->dispose();
|
reinterpret_cast<Finder::Data*>(peer)->dispose();
|
||||||
|
@ -33,8 +33,6 @@ inline void* operator new(size_t, void* p) throw() { return p; }
|
|||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
typedef void* object;
|
|
||||||
|
|
||||||
const unsigned BytesPerWord = sizeof(uintptr_t);
|
const unsigned BytesPerWord = sizeof(uintptr_t);
|
||||||
const unsigned BitsPerWord = BytesPerWord * 8;
|
const unsigned BitsPerWord = BytesPerWord * 8;
|
||||||
|
|
||||||
@ -118,7 +116,7 @@ indexOf(unsigned word, unsigned bit)
|
|||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline T&
|
inline T&
|
||||||
cast(object p, unsigned offset)
|
cast(void* p, unsigned offset)
|
||||||
{
|
{
|
||||||
return *reinterpret_cast<T*>(static_cast<uint8_t*>(p) + offset);
|
return *reinterpret_cast<T*>(static_cast<uint8_t*>(p) + offset);
|
||||||
}
|
}
|
||||||
|
103
src/heap.cpp
103
src/heap.cpp
@ -27,28 +27,28 @@ void assert(Context*, bool);
|
|||||||
|
|
||||||
System* system(Context*);
|
System* system(Context*);
|
||||||
|
|
||||||
inline object
|
inline void*
|
||||||
get(object o, unsigned offsetInWords)
|
get(void* o, unsigned offsetInWords)
|
||||||
{
|
{
|
||||||
return mask(cast<object>(o, offsetInWords * BytesPerWord));
|
return mask(cast<void*>(o, offsetInWords * BytesPerWord));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline object*
|
inline void**
|
||||||
getp(object o, unsigned offsetInWords)
|
getp(void* o, unsigned offsetInWords)
|
||||||
{
|
{
|
||||||
return &cast<object>(o, offsetInWords * BytesPerWord);
|
return &cast<void*>(o, offsetInWords * BytesPerWord);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
set(object* o, object value)
|
set(void** o, void* value)
|
||||||
{
|
{
|
||||||
*o = reinterpret_cast<object>
|
*o = reinterpret_cast<void*>
|
||||||
(reinterpret_cast<uintptr_t>(value)
|
(reinterpret_cast<uintptr_t>(value)
|
||||||
| reinterpret_cast<uintptr_t>(*o) & (~PointerMask));
|
| reinterpret_cast<uintptr_t>(*o) & (~PointerMask));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
set(object o, unsigned offsetInWords, object value)
|
set(void* o, unsigned offsetInWords, void* value)
|
||||||
{
|
{
|
||||||
set(getp(o, offsetInWords), value);
|
set(getp(o, offsetInWords), value);
|
||||||
}
|
}
|
||||||
@ -538,7 +538,7 @@ initNextGen2(Context* c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
fresh(Context* c, object o)
|
fresh(Context* c, void* o)
|
||||||
{
|
{
|
||||||
return c->nextGen1.contains(o)
|
return c->nextGen1.contains(o)
|
||||||
or c->nextGen2.contains(o)
|
or c->nextGen2.contains(o)
|
||||||
@ -546,43 +546,43 @@ fresh(Context* c, object o)
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
wasCollected(Context* c, object o)
|
wasCollected(Context* c, void* o)
|
||||||
{
|
{
|
||||||
return o and (not fresh(c, o)) and fresh(c, get(o, 0));
|
return o and (not fresh(c, o)) and fresh(c, get(o, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline object
|
inline void*
|
||||||
follow(Context* c UNUSED, object o)
|
follow(Context* c UNUSED, void* o)
|
||||||
{
|
{
|
||||||
assert(c, wasCollected(c, o));
|
assert(c, wasCollected(c, o));
|
||||||
return cast<object>(o, 0);
|
return cast<void*>(o, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline object&
|
inline void*&
|
||||||
parent(Context* c UNUSED, object o)
|
parent(Context* c UNUSED, void* o)
|
||||||
{
|
{
|
||||||
assert(c, wasCollected(c, o));
|
assert(c, wasCollected(c, o));
|
||||||
return cast<object>(o, BytesPerWord);
|
return cast<void*>(o, BytesPerWord);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uintptr_t*
|
inline uintptr_t*
|
||||||
bitset(Context* c UNUSED, object o)
|
bitset(Context* c UNUSED, void* o)
|
||||||
{
|
{
|
||||||
assert(c, wasCollected(c, o));
|
assert(c, wasCollected(c, o));
|
||||||
return &cast<uintptr_t>(o, BytesPerWord * 2);
|
return &cast<uintptr_t>(o, BytesPerWord * 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline object
|
inline void*
|
||||||
copyTo(Context* c, Segment* s, object o, unsigned size)
|
copyTo(Context* c, Segment* s, void* o, unsigned size)
|
||||||
{
|
{
|
||||||
assert(c, s->remaining() >= size);
|
assert(c, s->remaining() >= size);
|
||||||
object dst = s->allocate(size);
|
void* dst = s->allocate(size);
|
||||||
c->client->copy(o, dst);
|
c->client->copy(o, dst);
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
object
|
void*
|
||||||
copy2(Context* c, object o)
|
copy2(Context* c, void* o)
|
||||||
{
|
{
|
||||||
unsigned size = c->client->copiedSizeInWords(o);
|
unsigned size = c->client->copiedSizeInWords(o);
|
||||||
|
|
||||||
@ -626,10 +626,10 @@ copy2(Context* c, object o)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object
|
void*
|
||||||
copy(Context* c, object o)
|
copy(Context* c, void* o)
|
||||||
{
|
{
|
||||||
object r = copy2(c, o);
|
void* r = copy2(c, o);
|
||||||
|
|
||||||
if (Debug) {
|
if (Debug) {
|
||||||
fprintf(stderr, "copy %p (%s) to %p (%s)\n",
|
fprintf(stderr, "copy %p (%s) to %p (%s)\n",
|
||||||
@ -637,13 +637,13 @@ copy(Context* c, object o)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// leave a pointer to the copy in the original
|
// leave a pointer to the copy in the original
|
||||||
cast<object>(o, 0) = r;
|
cast<void*>(o, 0) = r;
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
object
|
void*
|
||||||
update3(Context* c, object o, bool* needsVisit)
|
update3(Context* c, void* o, bool* needsVisit)
|
||||||
{
|
{
|
||||||
if (wasCollected(c, o)) {
|
if (wasCollected(c, o)) {
|
||||||
*needsVisit = false;
|
*needsVisit = false;
|
||||||
@ -654,8 +654,8 @@ update3(Context* c, object o, bool* needsVisit)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object
|
void*
|
||||||
update2(Context* c, object o, bool* needsVisit)
|
update2(Context* c, void* o, bool* needsVisit)
|
||||||
{
|
{
|
||||||
if (c->mode == Heap::MinorCollection and c->gen2.contains(o)) {
|
if (c->mode == Heap::MinorCollection and c->gen2.contains(o)) {
|
||||||
*needsVisit = false;
|
*needsVisit = false;
|
||||||
@ -665,15 +665,15 @@ update2(Context* c, object o, bool* needsVisit)
|
|||||||
return update3(c, o, needsVisit);
|
return update3(c, o, needsVisit);
|
||||||
}
|
}
|
||||||
|
|
||||||
object
|
void*
|
||||||
update(Context* c, object* p, bool* needsVisit)
|
update(Context* c, void** p, bool* needsVisit)
|
||||||
{
|
{
|
||||||
if (mask(*p) == 0) {
|
if (mask(*p) == 0) {
|
||||||
*needsVisit = false;
|
*needsVisit = false;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
object r = update2(c, mask(*p), needsVisit);
|
void* r = update2(c, mask(*p), needsVisit);
|
||||||
|
|
||||||
// update heap map.
|
// update heap map.
|
||||||
if (r) {
|
if (r) {
|
||||||
@ -803,10 +803,10 @@ bitsetNext(Context* c, uintptr_t* p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
collect(Context* c, object* p)
|
collect(Context* c, void** p)
|
||||||
{
|
{
|
||||||
object original = mask(*p);
|
void* original = mask(*p);
|
||||||
object parent = 0;
|
void* parent = 0;
|
||||||
|
|
||||||
if (Debug) {
|
if (Debug) {
|
||||||
fprintf(stderr, "update %p (%s) at %p (%s)\n",
|
fprintf(stderr, "update %p (%s) at %p (%s)\n",
|
||||||
@ -824,11 +824,11 @@ collect(Context* c, object* p)
|
|||||||
if (not needsVisit) return;
|
if (not needsVisit) return;
|
||||||
|
|
||||||
visit: {
|
visit: {
|
||||||
object copy = follow(c, original);
|
void* copy = follow(c, original);
|
||||||
|
|
||||||
class Walker : public Heap::Walker {
|
class Walker : public Heap::Walker {
|
||||||
public:
|
public:
|
||||||
Walker(Context* c, object copy, uintptr_t* bitset):
|
Walker(Context* c, void* copy, uintptr_t* bitset):
|
||||||
c(c),
|
c(c),
|
||||||
copy(copy),
|
copy(copy),
|
||||||
bitset(bitset),
|
bitset(bitset),
|
||||||
@ -851,7 +851,7 @@ collect(Context* c, object* p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool needsVisit;
|
bool needsVisit;
|
||||||
object childCopy = update(c, getp(copy, offset), &needsVisit);
|
void* childCopy = update(c, getp(copy, offset), &needsVisit);
|
||||||
|
|
||||||
if (Debug) {
|
if (Debug) {
|
||||||
fprintf(stderr, " result: %p (%s) (visit? %d)\n",
|
fprintf(stderr, " result: %p (%s) (visit? %d)\n",
|
||||||
@ -894,7 +894,7 @@ collect(Context* c, object* p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Context* c;
|
Context* c;
|
||||||
object copy;
|
void* copy;
|
||||||
uintptr_t* bitset;
|
uintptr_t* bitset;
|
||||||
unsigned first;
|
unsigned first;
|
||||||
unsigned second;
|
unsigned second;
|
||||||
@ -926,7 +926,7 @@ collect(Context* c, object* p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (original) {
|
if (original) {
|
||||||
object copy = follow(c, original);
|
void* copy = follow(c, original);
|
||||||
|
|
||||||
class Walker : public Heap::Walker {
|
class Walker : public Heap::Walker {
|
||||||
public:
|
public:
|
||||||
@ -1014,7 +1014,7 @@ collect(Context* c, Segment::Map* map, unsigned start, unsigned end,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assert(c, map->scale == 1);
|
assert(c, map->scale == 1);
|
||||||
object* p = reinterpret_cast<object*>(map->segment->get(it.next()));
|
void** p = reinterpret_cast<void**>(map->segment->get(it.next()));
|
||||||
|
|
||||||
map->clearOnly(p);
|
map->clearOnly(p);
|
||||||
if (c->nextGen1.contains(*p)) {
|
if (c->nextGen1.contains(*p)) {
|
||||||
@ -1053,8 +1053,8 @@ collect2(Context* c)
|
|||||||
public:
|
public:
|
||||||
Visitor(Context* c): c(c) { }
|
Visitor(Context* c): c(c) { }
|
||||||
|
|
||||||
virtual void visit(void** p) {
|
virtual void visit(void* p) {
|
||||||
collect(c, p);
|
collect(c, static_cast<void**>(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
Context* c;
|
Context* c;
|
||||||
@ -1125,14 +1125,19 @@ class MyHeap: public Heap {
|
|||||||
::collect(&c, footprint);
|
::collect(&c, footprint);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool needsMark(void** p) {
|
virtual bool needsMark(void* p) {
|
||||||
return *p and c.gen2.contains(p) and not c.gen2.contains(*p);
|
return *static_cast<void**>(p)
|
||||||
|
and c.gen2.contains(p)
|
||||||
|
and not c.gen2.contains(*static_cast<void**>(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void mark(void** p) {
|
virtual void mark(void* p) {
|
||||||
if (Debug) {
|
if (Debug) {
|
||||||
fprintf(stderr, "mark %p (%s) at %p (%s)\n",
|
fprintf(stderr, "mark %p (%s) at %p (%s)\n",
|
||||||
*p, segment(&c, *p), p, segment(&c, p));
|
*static_cast<void**>(p),
|
||||||
|
segment(&c, *static_cast<void**>(p)),
|
||||||
|
p,
|
||||||
|
segment(&c, p));
|
||||||
}
|
}
|
||||||
|
|
||||||
c.heapMap.set(p);
|
c.heapMap.set(p);
|
||||||
|
@ -22,7 +22,7 @@ class Heap {
|
|||||||
class Visitor {
|
class Visitor {
|
||||||
public:
|
public:
|
||||||
virtual ~Visitor() { }
|
virtual ~Visitor() { }
|
||||||
virtual void visit(void**) = 0;
|
virtual void visit(void*) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Walker {
|
class Walker {
|
||||||
@ -44,8 +44,8 @@ class Heap {
|
|||||||
virtual ~Heap() { }
|
virtual ~Heap() { }
|
||||||
virtual void collect(CollectionType type, Client* client, unsigned footprint)
|
virtual void collect(CollectionType type, Client* client, unsigned footprint)
|
||||||
= 0;
|
= 0;
|
||||||
virtual bool needsMark(void** p) = 0;
|
virtual bool needsMark(void* p) = 0;
|
||||||
virtual void mark(void** p) = 0;
|
virtual void mark(void* p) = 0;
|
||||||
virtual void pad(void* p, unsigned extra) = 0;
|
virtual void pad(void* p, unsigned extra) = 0;
|
||||||
virtual void* follow(void* p) = 0;
|
virtual void* follow(void* p) = 0;
|
||||||
virtual Status status(void* p) = 0;
|
virtual Status status(void* p) = 0;
|
||||||
|
378
src/jnienv.cpp
378
src/jnienv.cpp
@ -5,7 +5,7 @@ using namespace vm;
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
jsize
|
jsize JNICALL
|
||||||
GetStringUTFLength(Thread* t, jstring s)
|
GetStringUTFLength(Thread* t, jstring s)
|
||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
@ -13,7 +13,7 @@ GetStringUTFLength(Thread* t, jstring s)
|
|||||||
return stringLength(t, *s);
|
return stringLength(t, *s);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char*
|
const char* JNICALL
|
||||||
GetStringUTFChars(Thread* t, jstring s, jboolean* isCopy)
|
GetStringUTFChars(Thread* t, jstring s, jboolean* isCopy)
|
||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
@ -26,13 +26,13 @@ GetStringUTFChars(Thread* t, jstring s, jboolean* isCopy)
|
|||||||
return chars;
|
return chars;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void JNICALL
|
||||||
ReleaseStringUTFChars(Thread* t, jstring, const char* chars)
|
ReleaseStringUTFChars(Thread* t, jstring, const char* chars)
|
||||||
{
|
{
|
||||||
t->vm->system->free(chars);
|
t->vm->system->free(chars);
|
||||||
}
|
}
|
||||||
|
|
||||||
jstring
|
jstring JNICALL
|
||||||
NewStringUTF(Thread* t, const char* chars)
|
NewStringUTF(Thread* t, const char* chars)
|
||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
@ -40,7 +40,7 @@ NewStringUTF(Thread* t, const char* chars)
|
|||||||
return pushReference(t, makeString(t, "%s", chars));
|
return pushReference(t, makeString(t, "%s", chars));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void JNICALL
|
||||||
GetByteArrayRegion(Thread* t, jbyteArray array, jint offset, jint length,
|
GetByteArrayRegion(Thread* t, jbyteArray array, jint offset, jint length,
|
||||||
jbyte* dst)
|
jbyte* dst)
|
||||||
{
|
{
|
||||||
@ -49,7 +49,7 @@ GetByteArrayRegion(Thread* t, jbyteArray array, jint offset, jint length,
|
|||||||
memcpy(dst, &byteArrayBody(t, *array, offset), length);
|
memcpy(dst, &byteArrayBody(t, *array, offset), length);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void JNICALL
|
||||||
SetByteArrayRegion(Thread* t, jbyteArray array, jint offset, jint length,
|
SetByteArrayRegion(Thread* t, jbyteArray array, jint offset, jint length,
|
||||||
const jbyte* src)
|
const jbyte* src)
|
||||||
{
|
{
|
||||||
@ -58,7 +58,7 @@ SetByteArrayRegion(Thread* t, jbyteArray array, jint offset, jint length,
|
|||||||
memcpy(&byteArrayBody(t, *array, offset), src, length);
|
memcpy(&byteArrayBody(t, *array, offset), src, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
jclass
|
jclass JNICALL
|
||||||
FindClass(Thread* t, const char* name)
|
FindClass(Thread* t, const char* name)
|
||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
@ -69,7 +69,7 @@ FindClass(Thread* t, const char* name)
|
|||||||
return pushReference(t, resolveClass(t, n));
|
return pushReference(t, resolveClass(t, n));
|
||||||
}
|
}
|
||||||
|
|
||||||
jint
|
jint JNICALL
|
||||||
ThrowNew(Thread* t, jclass c, const char* message)
|
ThrowNew(Thread* t, jclass c, const char* message)
|
||||||
{
|
{
|
||||||
if (t->exception) {
|
if (t->exception) {
|
||||||
@ -95,18 +95,336 @@ ThrowNew(Thread* t, jclass c, const char* message)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void JNICALL
|
||||||
DeleteLocalRef(Thread*, jobject)
|
DeleteLocalRef(Thread*, jobject)
|
||||||
{
|
{
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
jboolean
|
jboolean JNICALL
|
||||||
ExceptionCheck(Thread* t)
|
ExceptionCheck(Thread* t)
|
||||||
{
|
{
|
||||||
return t->exception != 0;
|
return t->exception != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jclass JNICALL
|
||||||
|
GetObjectClass(Thread* t, jobject o)
|
||||||
|
{
|
||||||
|
return pushReference(t, objectClass(t, *o));
|
||||||
|
}
|
||||||
|
|
||||||
|
jboolean JNICALL
|
||||||
|
IsInstanceOf(Thread* t, jobject o, jclass c)
|
||||||
|
{
|
||||||
|
return instanceOf(t, *c, *o);
|
||||||
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
findMethod(Thread* t, object class_, const char* name, const char* spec)
|
||||||
|
{
|
||||||
|
object n = makeString(t, "%s", name);
|
||||||
|
PROTECT(t, n);
|
||||||
|
|
||||||
|
object s = makeString(t, "%s", spec);
|
||||||
|
return vm::findMethod(t, class_, n, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
// jmethodID JNICALL
|
||||||
|
// GetMethodID(Thread* t, jclass c, const char* name, const char* spec)
|
||||||
|
// {
|
||||||
|
// object method = findMethod(t, *c, name, spec);
|
||||||
|
// if (UNLIKELY(t->exception)) return 0;
|
||||||
|
|
||||||
|
// if (classFlags(t, *c) & ACC_INTERFACE) {
|
||||||
|
// PROTECT(t, method);
|
||||||
|
|
||||||
|
// ACQUIRE(t, t->vm->referenceLock);
|
||||||
|
|
||||||
|
// for (unsigned i = 0; i < vectorSize(t, t->vm->jniInterfaceTable); ++i) {
|
||||||
|
// if (method == vectorBody(t, t->vm->jniInterfaceTable, i)) {
|
||||||
|
// return i;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// t->vm->jniInterfaceTable
|
||||||
|
// = vectorAppend(t, t->vm->jniInterfaceTable, method);
|
||||||
|
|
||||||
|
// return (vectorSize(t, t->vm->jniInterfaceTable) - 1) | (1 << BitsPerWord);
|
||||||
|
// } else {
|
||||||
|
// return methodOffset(t, method);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// jmethodID JNICALL
|
||||||
|
// GetStaticMethodID(Thread* t, jclass c, const char* name, const char* spec)
|
||||||
|
// {
|
||||||
|
// object method = findMethod(t, *c, name, spec);
|
||||||
|
// if (UNLIKELY(t->exception)) return 0;
|
||||||
|
|
||||||
|
// return methodOffset(t, method);
|
||||||
|
// }
|
||||||
|
|
||||||
|
object
|
||||||
|
findField(Thread* t, object class_, const char* name, const char* spec)
|
||||||
|
{
|
||||||
|
object n = makeString(t, "%s", name);
|
||||||
|
PROTECT(t, n);
|
||||||
|
|
||||||
|
object s = makeString(t, "%s", spec);
|
||||||
|
return vm::findField(t, class_, n, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
jfieldID JNICALL
|
||||||
|
GetFieldID(Thread* t, jclass c, const char* name, const char* spec)
|
||||||
|
{
|
||||||
|
object field = findField(t, *c, name, spec);
|
||||||
|
if (UNLIKELY(t->exception)) return 0;
|
||||||
|
|
||||||
|
return fieldOffset(t, field);
|
||||||
|
}
|
||||||
|
|
||||||
|
jfieldID JNICALL
|
||||||
|
GetStaticFieldID(Thread* t, jclass c, const char* name, const char* spec)
|
||||||
|
{
|
||||||
|
object field = findField(t, *c, name, spec);
|
||||||
|
if (UNLIKELY(t->exception)) return 0;
|
||||||
|
|
||||||
|
return fieldOffset(t, field);
|
||||||
|
}
|
||||||
|
|
||||||
|
jobject JNICALL
|
||||||
|
GetObjectField(Thread* t, jobject o, jfieldID field)
|
||||||
|
{
|
||||||
|
return pushReference(t, cast<object>(*o, field));
|
||||||
|
}
|
||||||
|
|
||||||
|
jboolean JNICALL
|
||||||
|
GetBooleanField(Thread*, jobject o, jfieldID field)
|
||||||
|
{
|
||||||
|
return cast<jboolean>(*o, field);
|
||||||
|
}
|
||||||
|
|
||||||
|
jbyte JNICALL
|
||||||
|
GetByteField(Thread*, jobject o, jfieldID field)
|
||||||
|
{
|
||||||
|
return cast<jbyte>(*o, field);
|
||||||
|
}
|
||||||
|
|
||||||
|
jchar JNICALL
|
||||||
|
GetCharField(Thread*, jobject o, jfieldID field)
|
||||||
|
{
|
||||||
|
return cast<jchar>(*o, field);
|
||||||
|
}
|
||||||
|
|
||||||
|
jshort JNICALL
|
||||||
|
GetShortField(Thread*, jobject o, jfieldID field)
|
||||||
|
{
|
||||||
|
return cast<jshort>(*o, field);
|
||||||
|
}
|
||||||
|
|
||||||
|
jint JNICALL
|
||||||
|
GetIntField(Thread*, jobject o, jfieldID field)
|
||||||
|
{
|
||||||
|
return cast<jint>(*o, field);
|
||||||
|
}
|
||||||
|
|
||||||
|
jlong JNICALL
|
||||||
|
GetLongField(Thread*, jobject o, jfieldID field)
|
||||||
|
{
|
||||||
|
return cast<jlong>(*o, field);
|
||||||
|
}
|
||||||
|
|
||||||
|
jfloat JNICALL
|
||||||
|
GetFloatField(Thread*, jobject o, jfieldID field)
|
||||||
|
{
|
||||||
|
return cast<jfloat>(*o, field);
|
||||||
|
}
|
||||||
|
|
||||||
|
jdouble JNICALL
|
||||||
|
GetDoubleField(Thread*, jobject o, jfieldID field)
|
||||||
|
{
|
||||||
|
return cast<jdouble>(*o, field);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JNICALL
|
||||||
|
SetObjectField(Thread* t, jobject o, jfieldID field, jobject v)
|
||||||
|
{
|
||||||
|
set(t, cast<object>(*o, field), (v ? *v : 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void JNICALL
|
||||||
|
SetBooleanField(Thread*, jobject o, jfieldID field, jboolean v)
|
||||||
|
{
|
||||||
|
cast<jboolean>(*o, field) = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JNICALL
|
||||||
|
SetByteField(Thread*, jobject o, jfieldID field, jbyte v)
|
||||||
|
{
|
||||||
|
cast<jbyte>(*o, field) = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JNICALL
|
||||||
|
SetCharField(Thread*, jobject o, jfieldID field, jchar v)
|
||||||
|
{
|
||||||
|
cast<jchar>(*o, field) = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JNICALL
|
||||||
|
SetShortField(Thread*, jobject o, jfieldID field, jshort v)
|
||||||
|
{
|
||||||
|
cast<jshort>(*o, field) = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JNICALL
|
||||||
|
SetIntField(Thread*, jobject o, jfieldID field, jint v)
|
||||||
|
{
|
||||||
|
cast<jint>(*o, field) = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JNICALL
|
||||||
|
SetLongField(Thread*, jobject o, jfieldID field, jlong v)
|
||||||
|
{
|
||||||
|
cast<jlong>(*o, field) = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JNICALL
|
||||||
|
SetFloatField(Thread*, jobject o, jfieldID field, jfloat v)
|
||||||
|
{
|
||||||
|
cast<jfloat>(*o, field) = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JNICALL
|
||||||
|
SetDoubleField(Thread*, jobject o, jfieldID field, jdouble v)
|
||||||
|
{
|
||||||
|
cast<jdouble>(*o, field) = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
jobject JNICALL
|
||||||
|
GetStaticObjectField(Thread* t, jclass c, jfieldID field)
|
||||||
|
{
|
||||||
|
return pushReference(t, arrayBody(t, classStaticTable(t, *c), field));
|
||||||
|
}
|
||||||
|
|
||||||
|
jboolean JNICALL
|
||||||
|
GetStaticBooleanField(Thread* t, jclass c, jfieldID field)
|
||||||
|
{
|
||||||
|
return intValue(t, arrayBody(t, classStaticTable(t, *c), field)) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
jbyte JNICALL
|
||||||
|
GetStaticByteField(Thread* t, jclass c, jfieldID field)
|
||||||
|
{
|
||||||
|
return static_cast<jbyte>
|
||||||
|
(intValue(t, arrayBody(t, classStaticTable(t, *c), field)));
|
||||||
|
}
|
||||||
|
|
||||||
|
jchar JNICALL
|
||||||
|
GetStaticCharField(Thread* t, jclass c, jfieldID field)
|
||||||
|
{
|
||||||
|
return static_cast<jchar>
|
||||||
|
(intValue(t, arrayBody(t, classStaticTable(t, *c), field)));
|
||||||
|
}
|
||||||
|
|
||||||
|
jshort JNICALL
|
||||||
|
GetStaticShortField(Thread* t, jclass c, jfieldID field)
|
||||||
|
{
|
||||||
|
return static_cast<jshort>
|
||||||
|
(intValue(t, arrayBody(t, classStaticTable(t, *c), field)));
|
||||||
|
}
|
||||||
|
|
||||||
|
jint JNICALL
|
||||||
|
GetStaticIntField(Thread* t, jclass c, jfieldID field)
|
||||||
|
{
|
||||||
|
return intValue(t, arrayBody(t, classStaticTable(t, *c), field));
|
||||||
|
}
|
||||||
|
|
||||||
|
jlong JNICALL
|
||||||
|
GetStaticLongField(Thread* t, jclass c, jfieldID field)
|
||||||
|
{
|
||||||
|
return longValue(t, arrayBody(t, classStaticTable(t, *c), field));
|
||||||
|
}
|
||||||
|
|
||||||
|
jfloat JNICALL
|
||||||
|
GetStaticFloatField(Thread* t, jclass c, jfieldID field)
|
||||||
|
{
|
||||||
|
jint i = intValue(t, arrayBody(t, classStaticTable(t, *c), field));
|
||||||
|
jfloat v; memcpy(&v, &i, 4);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
jdouble JNICALL
|
||||||
|
GetStaticDoubleField(Thread* t, jclass c, jfieldID field)
|
||||||
|
{
|
||||||
|
jlong i = longValue(t, arrayBody(t, classStaticTable(t, *c), field));
|
||||||
|
jdouble v; memcpy(&v, &i, 8);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JNICALL
|
||||||
|
SetStaticObjectField(Thread* t, jclass c, jfieldID field, jobject v)
|
||||||
|
{
|
||||||
|
set(t, arrayBody(t, classStaticTable(t, *c), field), (v ? *v : 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void JNICALL
|
||||||
|
SetStaticBooleanField(Thread* t, jclass c, jfieldID field, jboolean v)
|
||||||
|
{
|
||||||
|
object o = makeInt(t, v ? 1 : 0);
|
||||||
|
set(t, arrayBody(t, classStaticTable(t, *c), field), o);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JNICALL
|
||||||
|
SetStaticByteField(Thread* t, jclass c, jfieldID field, jbyte v)
|
||||||
|
{
|
||||||
|
object o = makeInt(t, v);
|
||||||
|
set(t, arrayBody(t, classStaticTable(t, *c), field), o);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JNICALL
|
||||||
|
SetStaticCharField(Thread* t, jclass c, jfieldID field, jchar v)
|
||||||
|
{
|
||||||
|
object o = makeInt(t, v);
|
||||||
|
set(t, arrayBody(t, classStaticTable(t, *c), field), o);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JNICALL
|
||||||
|
SetStaticShortField(Thread* t, jclass c, jfieldID field, jshort v)
|
||||||
|
{
|
||||||
|
object o = makeInt(t, v);
|
||||||
|
set(t, arrayBody(t, classStaticTable(t, *c), field), o);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JNICALL
|
||||||
|
SetStaticIntField(Thread* t, jclass c, jfieldID field, jint v)
|
||||||
|
{
|
||||||
|
object o = makeInt(t, v);
|
||||||
|
set(t, arrayBody(t, classStaticTable(t, *c), field), o);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JNICALL
|
||||||
|
SetStaticLongField(Thread* t, jclass c, jfieldID field, jlong v)
|
||||||
|
{
|
||||||
|
object o = makeLong(t, v);
|
||||||
|
set(t, arrayBody(t, classStaticTable(t, *c), field), o);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JNICALL
|
||||||
|
SetStaticFloatField(Thread* t, jclass c, jfieldID field, jfloat v)
|
||||||
|
{
|
||||||
|
jint i; memcpy(&i, &v, 4);
|
||||||
|
object o = makeInt(t, i);
|
||||||
|
set(t, arrayBody(t, classStaticTable(t, *c), field), o);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JNICALL
|
||||||
|
SetStaticDoubleField(Thread* t, jclass c, jfieldID field, jdouble v)
|
||||||
|
{
|
||||||
|
jlong i; memcpy(&i, &v, 8);
|
||||||
|
object o = makeLong(t, i);
|
||||||
|
set(t, arrayBody(t, classStaticTable(t, *c), field), o);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
@ -126,6 +444,46 @@ populateJNITable(JNIEnvVTable* table)
|
|||||||
table->ThrowNew = ::ThrowNew;
|
table->ThrowNew = ::ThrowNew;
|
||||||
table->ExceptionCheck = ::ExceptionCheck;
|
table->ExceptionCheck = ::ExceptionCheck;
|
||||||
table->DeleteLocalRef = ::DeleteLocalRef;
|
table->DeleteLocalRef = ::DeleteLocalRef;
|
||||||
|
table->GetObjectClass = ::GetObjectClass;
|
||||||
|
table->IsInstanceOf = ::IsInstanceOf;
|
||||||
|
table->GetFieldID = ::GetFieldID;
|
||||||
|
table->GetStaticFieldID = ::GetStaticFieldID;
|
||||||
|
table->GetObjectField = ::GetObjectField;
|
||||||
|
table->GetBooleanField = ::GetBooleanField;
|
||||||
|
table->GetByteField = ::GetByteField;
|
||||||
|
table->GetCharField = ::GetCharField;
|
||||||
|
table->GetShortField = ::GetShortField;
|
||||||
|
table->GetIntField = ::GetIntField;
|
||||||
|
table->GetLongField = ::GetLongField;
|
||||||
|
table->GetFloatField = ::GetFloatField;
|
||||||
|
table->GetDoubleField = ::GetDoubleField;
|
||||||
|
table->SetObjectField = ::SetObjectField;
|
||||||
|
table->SetBooleanField = ::SetBooleanField;
|
||||||
|
table->SetByteField = ::SetByteField;
|
||||||
|
table->SetCharField = ::SetCharField;
|
||||||
|
table->SetShortField = ::SetShortField;
|
||||||
|
table->SetIntField = ::SetIntField;
|
||||||
|
table->SetLongField = ::SetLongField;
|
||||||
|
table->SetFloatField = ::SetFloatField;
|
||||||
|
table->SetDoubleField = ::SetDoubleField;
|
||||||
|
table->GetStaticObjectField = ::GetStaticObjectField;
|
||||||
|
table->GetStaticBooleanField = ::GetStaticBooleanField;
|
||||||
|
table->GetStaticByteField = ::GetStaticByteField;
|
||||||
|
table->GetStaticCharField = ::GetStaticCharField;
|
||||||
|
table->GetStaticShortField = ::GetStaticShortField;
|
||||||
|
table->GetStaticIntField = ::GetStaticIntField;
|
||||||
|
table->GetStaticLongField = ::GetStaticLongField;
|
||||||
|
table->GetStaticFloatField = ::GetStaticFloatField;
|
||||||
|
table->GetStaticDoubleField = ::GetStaticDoubleField;
|
||||||
|
table->SetStaticObjectField = ::SetStaticObjectField;
|
||||||
|
table->SetStaticBooleanField = ::SetStaticBooleanField;
|
||||||
|
table->SetStaticByteField = ::SetStaticByteField;
|
||||||
|
table->SetStaticCharField = ::SetStaticCharField;
|
||||||
|
table->SetStaticShortField = ::SetStaticShortField;
|
||||||
|
table->SetStaticIntField = ::SetStaticIntField;
|
||||||
|
table->SetStaticLongField = ::SetStaticLongField;
|
||||||
|
table->SetStaticFloatField = ::SetStaticFloatField;
|
||||||
|
table->SetStaticDoubleField = ::SetStaticDoubleField;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
129
src/machine.cpp
129
src/machine.cpp
@ -138,7 +138,7 @@ visitRoots(Thread* t, Heap::Visitor* v)
|
|||||||
|
|
||||||
for (unsigned i = 0; i < t->sp; ++i) {
|
for (unsigned i = 0; i < t->sp; ++i) {
|
||||||
if (t->stack[i * 2] == ObjectTag) {
|
if (t->stack[i * 2] == ObjectTag) {
|
||||||
v->visit(reinterpret_cast<object*>(t->stack + (i * 2) + 1));
|
v->visit(t->stack + (i * 2) + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1620,7 +1620,7 @@ allocate2(Thread* t, unsigned sizeInBytes)
|
|||||||
{
|
{
|
||||||
t->heap = 0;
|
t->heap = 0;
|
||||||
if (t->vm->heapPoolIndex < Machine::HeapPoolSize) {
|
if (t->vm->heapPoolIndex < Machine::HeapPoolSize) {
|
||||||
t->heap = static_cast<object*>
|
t->heap = static_cast<uintptr_t*>
|
||||||
(t->vm->system->tryAllocate(Thread::HeapSizeInBytes));
|
(t->vm->system->tryAllocate(Thread::HeapSizeInBytes));
|
||||||
if (t->heap) {
|
if (t->heap) {
|
||||||
t->vm->heapPool[t->vm->heapPoolIndex++] = t->heap;
|
t->vm->heapPool[t->vm->heapPoolIndex++] = t->heap;
|
||||||
@ -1648,8 +1648,8 @@ make(Thread* t, object class_)
|
|||||||
PROTECT(t, class_);
|
PROTECT(t, class_);
|
||||||
unsigned sizeInBytes = pad(classFixedSize(t, class_));
|
unsigned sizeInBytes = pad(classFixedSize(t, class_));
|
||||||
object instance = allocate(t, sizeInBytes);
|
object instance = allocate(t, sizeInBytes);
|
||||||
*static_cast<object*>(instance) = class_;
|
cast<object>(instance, 0) = class_;
|
||||||
memset(static_cast<object*>(instance) + 1, 0,
|
memset(&cast<object>(instance, 0) + 1, 0,
|
||||||
sizeInBytes - sizeof(object));
|
sizeInBytes - sizeof(object));
|
||||||
|
|
||||||
if (UNLIKELY(classVmFlags(t, class_) & WeakReferenceFlag)) {
|
if (UNLIKELY(classVmFlags(t, class_) & WeakReferenceFlag)) {
|
||||||
@ -2056,6 +2056,34 @@ listAppend(Thread* t, object list, object value)
|
|||||||
set(t, listRear(t, list), p);
|
set(t, listRear(t, list), p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
vectorAppend(Thread* t, object vector, object value)
|
||||||
|
{
|
||||||
|
if (vectorLength(t, vector) == vectorSize(t, vector)) {
|
||||||
|
PROTECT(t, vector);
|
||||||
|
PROTECT(t, value);
|
||||||
|
|
||||||
|
object newVector = makeVector
|
||||||
|
(t, vectorSize(t, vector), max(16, vectorSize(t, vector) * 2), false);
|
||||||
|
|
||||||
|
if (vectorSize(t, vector)) {
|
||||||
|
memcpy(&vectorBody(t, newVector, 0),
|
||||||
|
&vectorBody(t, vector, 0),
|
||||||
|
vectorSize(t, vector) * BytesPerWord);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&vectorBody(t, newVector, vectorSize(t, vector) + 1),
|
||||||
|
0,
|
||||||
|
(vectorLength(t, newVector) - vectorSize(t, vector) - 1)
|
||||||
|
* BytesPerWord);
|
||||||
|
|
||||||
|
vector = newVector;
|
||||||
|
}
|
||||||
|
|
||||||
|
set(t, vectorBody(t, vector, vectorSize(t, vector)++), value);
|
||||||
|
return vector;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned
|
unsigned
|
||||||
fieldCode(Thread* t, unsigned javaCode)
|
fieldCode(Thread* t, unsigned javaCode)
|
||||||
{
|
{
|
||||||
@ -2316,6 +2344,59 @@ makeObjectArray(Thread* t, object elementClass, unsigned count, bool clear)
|
|||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
findInTable(Thread* t, object table, object name, object spec,
|
||||||
|
object& (*getName)(Thread*, object),
|
||||||
|
object& (*getSpec)(Thread*, object))
|
||||||
|
{
|
||||||
|
if (table) {
|
||||||
|
for (unsigned i = 0; i < arrayLength(t, table); ++i) {
|
||||||
|
object o = arrayBody(t, table, i);
|
||||||
|
if (strcmp(&byteArrayBody(t, getName(t, o), 0),
|
||||||
|
&byteArrayBody(t, name, 0)) == 0 and
|
||||||
|
strcmp(&byteArrayBody(t, getSpec(t, o), 0),
|
||||||
|
&byteArrayBody(t, spec, 0)) == 0)
|
||||||
|
{
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
findInHierarchy(Thread* t, object class_, object name, object spec,
|
||||||
|
object (*find)(Thread*, object, object, object),
|
||||||
|
object (*makeError)(Thread*, object))
|
||||||
|
{
|
||||||
|
object originalClass = class_;
|
||||||
|
PROTECT(t, class_);
|
||||||
|
|
||||||
|
object o = 0;
|
||||||
|
if (classFlags(t, class_) & ACC_INTERFACE) {
|
||||||
|
if (classVirtualTable(t, class_)) {
|
||||||
|
o = findInTable
|
||||||
|
(t, classVirtualTable(t, class_), name, spec, methodName, methodSpec);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (; o == 0 and class_; class_ = classSuper(t, class_)) {
|
||||||
|
o = find(t, class_, name, spec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (o == 0) {
|
||||||
|
object message = makeString
|
||||||
|
(t, "%s %s not found in %s",
|
||||||
|
&byteArrayBody(t, name, 0),
|
||||||
|
&byteArrayBody(t, spec, 0),
|
||||||
|
&byteArrayBody(t, className(t, originalClass), 0));
|
||||||
|
t->exception = makeError(t, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
lineNumber(Thread* t, object method, unsigned ip)
|
lineNumber(Thread* t, object method, unsigned ip)
|
||||||
{
|
{
|
||||||
@ -2431,21 +2512,23 @@ collect(Thread* t, Heap::CollectionType type)
|
|||||||
postVisit(m->rootThread, v);
|
postVisit(m->rootThread, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned sizeInWords(object o) {
|
virtual unsigned sizeInWords(void* p) {
|
||||||
Thread* t = m->rootThread;
|
Thread* t = m->rootThread;
|
||||||
|
|
||||||
o = m->heap->follow(mask(o));
|
object o = static_cast<object>(m->heap->follow(mask(p)));
|
||||||
|
|
||||||
return extendedSize
|
return extendedSize
|
||||||
(t, o, baseSize(t, o, m->heap->follow(objectClass(t, o))));
|
(t, o, baseSize(t, o, static_cast<object>
|
||||||
|
(m->heap->follow(objectClass(t, o)))));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned copiedSizeInWords(object o) {
|
virtual unsigned copiedSizeInWords(void* p) {
|
||||||
Thread* t = m->rootThread;
|
Thread* t = m->rootThread;
|
||||||
|
|
||||||
o = m->heap->follow(mask(o));
|
object o = static_cast<object>(m->heap->follow(mask(p)));
|
||||||
|
|
||||||
unsigned n = baseSize(t, o, m->heap->follow(objectClass(t, o)));
|
unsigned n = baseSize(t, o, static_cast<object>
|
||||||
|
(m->heap->follow(objectClass(t, o))));
|
||||||
|
|
||||||
if (objectExtended(t, o) or hashTaken(t, o)) {
|
if (objectExtended(t, o) or hashTaken(t, o)) {
|
||||||
++ n;
|
++ n;
|
||||||
@ -2454,30 +2537,34 @@ collect(Thread* t, Heap::CollectionType type)
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void copy(object o, object dst) {
|
virtual void copy(void* srcp, void* dstp) {
|
||||||
Thread* t = m->rootThread;
|
Thread* t = m->rootThread;
|
||||||
|
|
||||||
o = m->heap->follow(mask(o));
|
object src = static_cast<object>(m->heap->follow(mask(srcp)));
|
||||||
object class_ = m->heap->follow(objectClass(t, o));
|
object class_ = static_cast<object>
|
||||||
|
(m->heap->follow(objectClass(t, src)));
|
||||||
|
|
||||||
unsigned base = baseSize(t, o, class_);
|
unsigned base = baseSize(t, src, class_);
|
||||||
unsigned n = extendedSize(t, o, base);
|
unsigned n = extendedSize(t, src, base);
|
||||||
|
|
||||||
memcpy(dst, o, n * BytesPerWord);
|
object dst = static_cast<object>(dstp);
|
||||||
|
|
||||||
if (hashTaken(t, o)) {
|
memcpy(dst, src, n * BytesPerWord);
|
||||||
|
|
||||||
|
if (hashTaken(t, src)) {
|
||||||
cast<uintptr_t>(dst, 0) &= PointerMask;
|
cast<uintptr_t>(dst, 0) &= PointerMask;
|
||||||
cast<uintptr_t>(dst, 0) |= ExtendedMark;
|
cast<uintptr_t>(dst, 0) |= ExtendedMark;
|
||||||
extendedWord(t, dst, base) = takeHash(t, o);
|
extendedWord(t, dst, base) = takeHash(t, src);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void walk(void* p, Heap::Walker* w) {
|
virtual void walk(void* p, Heap::Walker* w) {
|
||||||
Thread* t = m->rootThread;
|
Thread* t = m->rootThread;
|
||||||
|
|
||||||
p = m->heap->follow(mask(p));
|
object o = static_cast<object>(m->heap->follow(mask(p)));
|
||||||
object class_ = m->heap->follow(objectClass(t, p));
|
object class_ = static_cast<object>(m->heap->follow(objectClass(t, o)));
|
||||||
object objectMask = m->heap->follow(classObjectMask(t, class_));
|
object objectMask = static_cast<object>
|
||||||
|
(m->heap->follow(classObjectMask(t, class_)));
|
||||||
|
|
||||||
if (objectMask) {
|
if (objectMask) {
|
||||||
// fprintf(stderr, "p: %p; class: %p; mask: %p; mask length: %d\n",
|
// fprintf(stderr, "p: %p; class: %p; mask: %p; mask length: %d\n",
|
||||||
|
@ -67,6 +67,10 @@ const unsigned ClassInitFlag = 1 << 0;
|
|||||||
|
|
||||||
class Thread;
|
class Thread;
|
||||||
|
|
||||||
|
struct Object { };
|
||||||
|
|
||||||
|
typedef Object* object;
|
||||||
|
|
||||||
typedef Thread JNIEnv;
|
typedef Thread JNIEnv;
|
||||||
|
|
||||||
typedef uint8_t jboolean;
|
typedef uint8_t jboolean;
|
||||||
@ -80,7 +84,7 @@ typedef double jdouble;
|
|||||||
|
|
||||||
typedef jint jsize;
|
typedef jint jsize;
|
||||||
|
|
||||||
typedef void** jobject;
|
typedef object* jobject;
|
||||||
|
|
||||||
typedef jobject jclass;
|
typedef jobject jclass;
|
||||||
typedef jobject jthrowable;
|
typedef jobject jthrowable;
|
||||||
@ -98,8 +102,8 @@ typedef jarray jfloatArray;
|
|||||||
typedef jarray jdoubleArray;
|
typedef jarray jdoubleArray;
|
||||||
typedef jarray jobjectArray;
|
typedef jarray jobjectArray;
|
||||||
|
|
||||||
typedef void** jfieldID;
|
typedef uintptr_t jfieldID;
|
||||||
typedef void** jmethodID;
|
typedef uintptr_t jmethodID;
|
||||||
|
|
||||||
union jvalue {
|
union jvalue {
|
||||||
jboolean z;
|
jboolean z;
|
||||||
@ -1127,7 +1131,7 @@ class Machine {
|
|||||||
object tenuredWeakReferences;
|
object tenuredWeakReferences;
|
||||||
bool unsafe;
|
bool unsafe;
|
||||||
JNIEnvVTable jniEnvVTable;
|
JNIEnvVTable jniEnvVTable;
|
||||||
object* heapPool[HeapPoolSize];
|
uintptr_t* heapPool[HeapPoolSize];
|
||||||
unsigned heapPoolIndex;
|
unsigned heapPoolIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1229,12 +1233,12 @@ class Thread {
|
|||||||
unsigned heapOffset;
|
unsigned heapOffset;
|
||||||
Protector* protector;
|
Protector* protector;
|
||||||
Runnable runnable;
|
Runnable runnable;
|
||||||
object* heap;
|
uintptr_t* heap;
|
||||||
#ifdef VM_STRESS
|
#ifdef VM_STRESS
|
||||||
bool stress;
|
bool stress;
|
||||||
object* defaultHeap;
|
uintptr_t* defaultHeap;
|
||||||
#else // not VM_STRESS
|
#else // not VM_STRESS
|
||||||
object defaultHeap[HeapSizeInWords];
|
uintptr_t defaultHeap[HeapSizeInWords];
|
||||||
#endif // not VM_STRESS
|
#endif // not VM_STRESS
|
||||||
uintptr_t stack[StackSizeInWords];
|
uintptr_t stack[StackSizeInWords];
|
||||||
};
|
};
|
||||||
@ -1365,13 +1369,13 @@ expect(Thread* t, bool v)
|
|||||||
inline object
|
inline object
|
||||||
allocateLarge(Thread* t, unsigned sizeInBytes)
|
allocateLarge(Thread* t, unsigned sizeInBytes)
|
||||||
{
|
{
|
||||||
return t->large = t->vm->system->allocate(sizeInBytes);
|
return t->large = static_cast<object>(t->vm->system->allocate(sizeInBytes));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline object
|
inline object
|
||||||
allocateSmall(Thread* t, unsigned sizeInBytes)
|
allocateSmall(Thread* t, unsigned sizeInBytes)
|
||||||
{
|
{
|
||||||
object o = t->heap + t->heapIndex;
|
object o = reinterpret_cast<object>(t->heap + t->heapIndex);
|
||||||
t->heapIndex += ceiling(sizeInBytes, BytesPerWord);
|
t->heapIndex += ceiling(sizeInBytes, BytesPerWord);
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
@ -1397,9 +1401,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(&target)) {
|
if (t->vm->heap->needsMark(reinterpret_cast<void**>(&target))) {
|
||||||
ACQUIRE_RAW(t, t->vm->heapLock);
|
ACQUIRE_RAW(t, t->vm->heapLock);
|
||||||
t->vm->heap->mark(&target);
|
t->vm->heap->mark(reinterpret_cast<void**>(&target));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2082,6 +2086,9 @@ hashMapIteratorNext(Thread* t, object it);
|
|||||||
void
|
void
|
||||||
listAppend(Thread* t, object list, object value);
|
listAppend(Thread* t, object list, object value);
|
||||||
|
|
||||||
|
object
|
||||||
|
vectorAppend(Thread* t, object vector, object value);
|
||||||
|
|
||||||
unsigned
|
unsigned
|
||||||
fieldCode(Thread* t, unsigned javaCode);
|
fieldCode(Thread* t, unsigned javaCode);
|
||||||
|
|
||||||
@ -2131,6 +2138,44 @@ initClass(Thread* t, object c)
|
|||||||
object
|
object
|
||||||
makeObjectArray(Thread* t, object elementClass, unsigned count, bool clear);
|
makeObjectArray(Thread* t, object elementClass, unsigned count, bool clear);
|
||||||
|
|
||||||
|
object
|
||||||
|
findInTable(Thread* t, object table, object name, object spec,
|
||||||
|
object& (*getName)(Thread*, object),
|
||||||
|
object& (*getSpec)(Thread*, object));
|
||||||
|
|
||||||
|
inline object
|
||||||
|
findFieldInClass(Thread* t, object class_, object name, object spec)
|
||||||
|
{
|
||||||
|
return findInTable
|
||||||
|
(t, classFieldTable(t, class_), name, spec, fieldName, fieldSpec);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline object
|
||||||
|
findMethodInClass(Thread* t, object class_, object name, object spec)
|
||||||
|
{
|
||||||
|
return findInTable
|
||||||
|
(t, classMethodTable(t, class_), name, spec, methodName, methodSpec);
|
||||||
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
findInHierarchy(Thread* t, object class_, object name, object spec,
|
||||||
|
object (*find)(Thread*, object, object, object),
|
||||||
|
object (*makeError)(Thread*, object));
|
||||||
|
|
||||||
|
inline object
|
||||||
|
findField(Thread* t, object class_, object name, object spec)
|
||||||
|
{
|
||||||
|
return findInHierarchy
|
||||||
|
(t, class_, name, spec, findFieldInClass, makeNoSuchFieldError);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline object
|
||||||
|
findMethod(Thread* t, object class_, object name, object spec)
|
||||||
|
{
|
||||||
|
return findInHierarchy
|
||||||
|
(t, class_, name, spec, findMethodInClass, makeNoSuchMethodError);
|
||||||
|
}
|
||||||
|
|
||||||
inline unsigned
|
inline unsigned
|
||||||
objectArrayLength(Thread* t UNUSED, object array)
|
objectArrayLength(Thread* t UNUSED, object array)
|
||||||
{
|
{
|
||||||
|
66
src/run.cpp
66
src/run.cpp
@ -125,43 +125,6 @@ isSpecialMethod(Thread* t, object method, object class_)
|
|||||||
and isSuperclass(t, methodClass(t, method), class_);
|
and isSuperclass(t, methodClass(t, method), class_);
|
||||||
}
|
}
|
||||||
|
|
||||||
object
|
|
||||||
find(Thread* t, object table, object reference,
|
|
||||||
object& (*name)(Thread*, object),
|
|
||||||
object& (*spec)(Thread*, object))
|
|
||||||
{
|
|
||||||
if (table) {
|
|
||||||
object n = referenceName(t, reference);
|
|
||||||
object s = referenceSpec(t, reference);
|
|
||||||
for (unsigned i = 0; i < arrayLength(t, table); ++i) {
|
|
||||||
object o = arrayBody(t, table, i);
|
|
||||||
|
|
||||||
if (strcmp(&byteArrayBody(t, name(t, o), 0),
|
|
||||||
&byteArrayBody(t, n, 0)) == 0 and
|
|
||||||
strcmp(&byteArrayBody(t, spec(t, o), 0),
|
|
||||||
&byteArrayBody(t, s, 0)) == 0)
|
|
||||||
{
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline object
|
|
||||||
findFieldInClass(Thread* t, object class_, object reference)
|
|
||||||
{
|
|
||||||
return find(t, classFieldTable(t, class_), reference, fieldName, fieldSpec);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline object
|
|
||||||
findMethodInClass(Thread* t, object class_, object reference)
|
|
||||||
{
|
|
||||||
return find(t, classMethodTable(t, class_), reference, methodName,
|
|
||||||
methodSpec);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline object
|
inline object
|
||||||
resolveClass(Thread* t, object pool, unsigned index)
|
resolveClass(Thread* t, object pool, unsigned index)
|
||||||
{
|
{
|
||||||
@ -196,7 +159,7 @@ 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 (*find)(Thread*, object, object, object),
|
||||||
object (*makeError)(Thread*, object))
|
object (*makeError)(Thread*, object))
|
||||||
{
|
{
|
||||||
object o = arrayBody(t, pool, index);
|
object o = arrayBody(t, pool, index);
|
||||||
@ -210,26 +173,10 @@ resolve(Thread* t, object pool, unsigned index,
|
|||||||
object class_ = resolveClass(t, o, referenceClass);
|
object class_ = resolveClass(t, o, referenceClass);
|
||||||
if (UNLIKELY(t->exception)) return 0;
|
if (UNLIKELY(t->exception)) return 0;
|
||||||
|
|
||||||
o = 0;
|
o = findInHierarchy
|
||||||
if (classFlags(t, class_) & ACC_INTERFACE) {
|
(t, class_, referenceName(t, reference), referenceSpec(t, reference),
|
||||||
if (classVirtualTable(t, class_)) {
|
find, makeError);
|
||||||
o = ::find(t, classVirtualTable(t, class_), arrayBody(t, pool, index),
|
if (UNLIKELY(t->exception)) return 0;
|
||||||
methodName, methodSpec);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (; o == 0 and class_; class_ = classSuper(t, class_)) {
|
|
||||||
o = find(t, class_, arrayBody(t, pool, index));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (o == 0) {
|
|
||||||
object message = makeString
|
|
||||||
(t, "%s %s not found in %s",
|
|
||||||
&byteArrayBody(t, referenceName(t, reference), 0),
|
|
||||||
&byteArrayBody(t, referenceSpec(t, reference), 0),
|
|
||||||
&byteArrayBody(t, className(t, referenceClass(t, reference)), 0));
|
|
||||||
t->exception = makeError(t, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
set(t, arrayBody(t, pool, index), o);
|
set(t, arrayBody(t, pool, index), o);
|
||||||
}
|
}
|
||||||
@ -2769,7 +2716,8 @@ run(Thread* t, const char* className, const char* methodName,
|
|||||||
object spec = makeByteArray(t, methodSpec);
|
object spec = makeByteArray(t, methodSpec);
|
||||||
object reference = makeReference(t, class_, name, spec);
|
object reference = makeReference(t, class_, name, spec);
|
||||||
|
|
||||||
object method = findMethodInClass(t, class_, reference);
|
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));
|
||||||
|
|
||||||
|
@ -34,6 +34,12 @@ allocate()
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
equal(const char* a, const char* b)
|
||||||
|
{
|
||||||
|
return strcmp(a, b) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
class Object {
|
class Object {
|
||||||
public:
|
public:
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -126,6 +132,7 @@ class Scalar : public Object {
|
|||||||
const char* name;
|
const char* name;
|
||||||
unsigned elementSize;
|
unsigned elementSize;
|
||||||
bool noassert;
|
bool noassert;
|
||||||
|
bool nogc;
|
||||||
bool hide;
|
bool hide;
|
||||||
|
|
||||||
static Scalar* make(Object* owner, Object* typeObject, const char* typeName,
|
static Scalar* make(Object* owner, Object* typeObject, const char* typeName,
|
||||||
@ -139,6 +146,7 @@ class Scalar : public Object {
|
|||||||
o->name = name;
|
o->name = name;
|
||||||
o->elementSize = size;
|
o->elementSize = size;
|
||||||
o->noassert = false;
|
o->noassert = false;
|
||||||
|
o->nogc = false;
|
||||||
o->hide = false;
|
o->hide = false;
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
@ -262,6 +270,25 @@ memberNoAssert(Object* o)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool&
|
||||||
|
memberNoGC(Object* o)
|
||||||
|
{
|
||||||
|
switch (o->type) {
|
||||||
|
case Object::Scalar:
|
||||||
|
case Object::Array:
|
||||||
|
return static_cast<Scalar*>(o)->nogc;
|
||||||
|
|
||||||
|
default:
|
||||||
|
UNREACHABLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
memberGC(Object* o)
|
||||||
|
{
|
||||||
|
return not memberNoGC(o) and equal(memberTypeName(o), "object");
|
||||||
|
}
|
||||||
|
|
||||||
bool&
|
bool&
|
||||||
memberHide(Object* o)
|
memberHide(Object* o)
|
||||||
{
|
{
|
||||||
@ -479,12 +506,6 @@ class Singleton : public Object {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
bool
|
|
||||||
equal(const char* a, const char* b)
|
|
||||||
{
|
|
||||||
return strcmp(a, b) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
endsWith(char c, const char* s)
|
endsWith(char c, const char* s)
|
||||||
{
|
{
|
||||||
@ -782,6 +803,10 @@ parseMember(Object* t, Object* p, Object* declarations)
|
|||||||
Object* member = parseMember(t, cdr(p), declarations);
|
Object* member = parseMember(t, cdr(p), declarations);
|
||||||
memberNoAssert(member) = true;
|
memberNoAssert(member) = true;
|
||||||
return member;
|
return member;
|
||||||
|
} else if (equal(spec, "nogc")) {
|
||||||
|
Object* member = parseMember(t, cdr(p), declarations);
|
||||||
|
memberNoGC(member) = true;
|
||||||
|
return member;
|
||||||
} else {
|
} else {
|
||||||
return Scalar::make(t, declaration(spec, declarations), spec,
|
return Scalar::make(t, declaration(spec, declarations), spec,
|
||||||
string(car(cdr(p))),
|
string(car(cdr(p))),
|
||||||
@ -822,6 +847,7 @@ memberEqual(Object* a, Object* b)
|
|||||||
case Object::Scalar:
|
case Object::Scalar:
|
||||||
return equal(memberTypeName(a), memberTypeName(b))
|
return equal(memberTypeName(a), memberTypeName(b))
|
||||||
and memberNoAssert(a) == memberNoAssert(b)
|
and memberNoAssert(a) == memberNoAssert(b)
|
||||||
|
and memberNoGC(a) == memberNoGC(b)
|
||||||
and memberHide(a) == memberHide(b);
|
and memberHide(a) == memberHide(b);
|
||||||
|
|
||||||
// todo: compare array fields
|
// todo: compare array fields
|
||||||
@ -1061,7 +1087,7 @@ writeAccessor(Output* out, Object* member, Object* offset, bool unsafe = false)
|
|||||||
if (memberOwner(member)->type == Object::Pod) {
|
if (memberOwner(member)->type == Object::Pod) {
|
||||||
out->write(">(o->body");
|
out->write(">(o->body");
|
||||||
} else {
|
} else {
|
||||||
out->write(">(static_cast<uint8_t*>(o)");
|
out->write(">(reinterpret_cast<uint8_t*>(o)");
|
||||||
}
|
}
|
||||||
if (member->type != Object::Scalar and memberTypeObject(member)) {
|
if (member->type != Object::Scalar and memberTypeObject(member)) {
|
||||||
out->write(" + ");
|
out->write(" + ");
|
||||||
@ -1433,20 +1459,20 @@ typeObjectMask(Object* type)
|
|||||||
|
|
||||||
switch (m->type) {
|
switch (m->type) {
|
||||||
case Object::Scalar: {
|
case Object::Scalar: {
|
||||||
if (equal(memberTypeName(m), "object")) {
|
if (memberGC(m)) {
|
||||||
set(&mask, offset);
|
set(&mask, offset);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Object::Array: {
|
case Object::Array: {
|
||||||
if (equal(memberTypeName(m), "object")) {
|
if (memberGC(m)) {
|
||||||
set(&mask, offset);
|
set(&mask, offset);
|
||||||
} else if (memberTypeObject(m)
|
} else if (memberTypeObject(m)
|
||||||
and memberTypeObject(m)->type == Object::Pod)
|
and memberTypeObject(m)->type == Object::Pod)
|
||||||
{
|
{
|
||||||
for (MemberIterator it(memberTypeObject(m)); it.hasMore();) {
|
for (MemberIterator it(memberTypeObject(m)); it.hasMore();) {
|
||||||
Object* m = it.next();
|
Object* m = it.next();
|
||||||
if (equal(memberTypeName(m), "object")) {
|
if (memberGC(m)) {
|
||||||
set(&mask, offset + (it.offset() / sizeof(void*)));
|
set(&mask, offset + (it.offset() / sizeof(void*)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,9 +99,9 @@
|
|||||||
(object third))
|
(object third))
|
||||||
|
|
||||||
(type finalizer
|
(type finalizer
|
||||||
(void* target)
|
(nogc object target)
|
||||||
(void* finalize)
|
(void* finalize)
|
||||||
(void* next))
|
(nogc object next))
|
||||||
|
|
||||||
(type hashMap
|
(type hashMap
|
||||||
(uint32_t size)
|
(uint32_t size)
|
||||||
@ -120,6 +120,10 @@
|
|||||||
(object front)
|
(object front)
|
||||||
(object rear))
|
(object rear))
|
||||||
|
|
||||||
|
(type vector
|
||||||
|
(uint32_t size)
|
||||||
|
(array object body))
|
||||||
|
|
||||||
(type traceElement
|
(type traceElement
|
||||||
(object method)
|
(object method)
|
||||||
(int32_t ip))
|
(int32_t ip))
|
||||||
@ -259,9 +263,9 @@
|
|||||||
|
|
||||||
(type jreference java/lang/ref/Reference
|
(type jreference java/lang/ref/Reference
|
||||||
(extends jobject)
|
(extends jobject)
|
||||||
(noassert void* next)
|
(noassert nogc object next)
|
||||||
(void* target)
|
(nogc object target)
|
||||||
(void* queue)
|
(nogc object queue)
|
||||||
(object jnext))
|
(object jnext))
|
||||||
|
|
||||||
(type weakReference java/lang/ref/WeakReference
|
(type weakReference java/lang/ref/WeakReference
|
||||||
|
Loading…
Reference in New Issue
Block a user