mirror of
https://github.com/corda/corda.git
synced 2025-02-10 12:51:37 +00:00
more progress on JNI
This commit is contained in:
parent
ef806e73f0
commit
f606f2d30a
@ -1,11 +1,7 @@
|
|||||||
package java.lang;
|
package java.lang;
|
||||||
|
|
||||||
import vm.VM;
|
|
||||||
|
|
||||||
public class Object {
|
public class Object {
|
||||||
protected Object clone() {
|
protected native Object clone();
|
||||||
return VM.clone(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
return this == o;
|
return this == o;
|
||||||
@ -13,35 +9,19 @@ public class Object {
|
|||||||
|
|
||||||
protected void finalize() { }
|
protected void finalize() { }
|
||||||
|
|
||||||
public final Class<? extends Object> getClass() {
|
public native final Class<? extends Object> getClass();
|
||||||
return VM.getClass(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int hashCode() {
|
public native int hashCode();
|
||||||
return VM.hashCode(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void notify() {
|
public native final void notify();
|
||||||
VM.notify(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void notifyAll() {
|
public native final void notifyAll();
|
||||||
VM.notifyAll(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
public native String toString();
|
||||||
return VM.toString(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void wait() {
|
public native final void wait();
|
||||||
VM.wait(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void wait(long timeout) {
|
public native final void wait(long timeout);
|
||||||
VM.wait(this, timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void wait(long timeout, int nanos) {
|
public native final void wait(long timeout, int nanos);
|
||||||
VM.wait(this, timeout, nanos);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
package vm;
|
|
||||||
|
|
||||||
public class VM {
|
|
||||||
public static native Object clone(Object o);
|
|
||||||
|
|
||||||
public static native Class<? extends Object> getClass(Object o);
|
|
||||||
|
|
||||||
public static native int hashCode(Object o);
|
|
||||||
|
|
||||||
public static native void notify(Object o);
|
|
||||||
|
|
||||||
public static native void notifyAll(Object o);
|
|
||||||
|
|
||||||
public static native String toString(Object o);
|
|
||||||
|
|
||||||
public static native void wait(Object o);
|
|
||||||
|
|
||||||
public static native void wait(Object o, long timeout);
|
|
||||||
|
|
||||||
public static native void wait(Object o, long timeout, int nanos);
|
|
||||||
}
|
|
47
src/main.cpp
47
src/main.cpp
@ -2,6 +2,7 @@
|
|||||||
#include "sys/types.h"
|
#include "sys/types.h"
|
||||||
#include "sys/stat.h"
|
#include "sys/stat.h"
|
||||||
#include "fcntl.h"
|
#include "fcntl.h"
|
||||||
|
#include "dlfcn.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "heap.h"
|
#include "heap.h"
|
||||||
@ -30,6 +31,34 @@ class System: public vm::System {
|
|||||||
vm::System* s;
|
vm::System* s;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Library: public vm::System::Library {
|
||||||
|
public:
|
||||||
|
Library(vm::System* s, void* p, vm::System::Library* next):
|
||||||
|
s(s),
|
||||||
|
p(p),
|
||||||
|
next_(next)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
virtual void* resolve(const char* function) {
|
||||||
|
return dlsym(p, function);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual vm::System::Library* next() {
|
||||||
|
return next_;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void dispose() {
|
||||||
|
if (next_) {
|
||||||
|
next_->dispose();
|
||||||
|
}
|
||||||
|
s->free(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
vm::System* s;
|
||||||
|
void* p;
|
||||||
|
vm::System::Library* next_;
|
||||||
|
};
|
||||||
|
|
||||||
System(unsigned limit): limit(limit), count(0) { }
|
System(unsigned limit): limit(limit), count(0) { }
|
||||||
|
|
||||||
virtual bool success(Status s) {
|
virtual bool success(Status s) {
|
||||||
@ -81,6 +110,24 @@ class System: public vm::System {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual uint64_t call(void* function, unsigned argumentCount,
|
||||||
|
uint32_t* argumentTable, uint8_t* argumentSizeTable,
|
||||||
|
unsigned returnSize)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual Status load(Library** lib, const char* name, Library* next) {
|
||||||
|
void* p = dlopen(name, RTLD_LAZY);
|
||||||
|
if (p) {
|
||||||
|
*lib = new (vm::System::allocate(sizeof(Library)))
|
||||||
|
Library(this, p, next);
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
virtual void abort() {
|
virtual void abort() {
|
||||||
::abort();
|
::abort();
|
||||||
}
|
}
|
||||||
|
@ -33,11 +33,15 @@
|
|||||||
(object code))
|
(object code))
|
||||||
|
|
||||||
(type nativeMethodData
|
(type nativeMethodData
|
||||||
(void* pointer)
|
(void* function)
|
||||||
(uint16_t argumentTableSize)
|
(uint16_t argumentTableSize)
|
||||||
(uint8_t returnCode)
|
(uint8_t returnCode)
|
||||||
|
(uint8_t builtin)
|
||||||
(array uint8_t parameterCodes))
|
(array uint8_t parameterCodes))
|
||||||
|
|
||||||
|
(type pointer
|
||||||
|
(void* value))
|
||||||
|
|
||||||
(pod exceptionHandler
|
(pod exceptionHandler
|
||||||
(uint16_t start)
|
(uint16_t start)
|
||||||
(uint16_t end)
|
(uint16_t end)
|
||||||
|
388
src/vm.cpp
388
src/vm.cpp
@ -28,6 +28,7 @@ object resolveClass(Thread*, object);
|
|||||||
object allocate(Thread*, unsigned);
|
object allocate(Thread*, unsigned);
|
||||||
object& arrayBodyUnsafe(Thread*, object, unsigned);
|
object& arrayBodyUnsafe(Thread*, object, unsigned);
|
||||||
void set(Thread*, object&, object);
|
void set(Thread*, object&, object);
|
||||||
|
object makeString(Thread*, const char*, ...);
|
||||||
object makeByteArray(Thread*, const char*, ...);
|
object makeByteArray(Thread*, const char*, ...);
|
||||||
unsigned objectSize(Thread* t, object o);
|
unsigned objectSize(Thread* t, object o);
|
||||||
|
|
||||||
@ -38,6 +39,7 @@ objectClass(object o)
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum FieldCode {
|
enum FieldCode {
|
||||||
|
VoidField,
|
||||||
ByteField,
|
ByteField,
|
||||||
CharField,
|
CharField,
|
||||||
DoubleField,
|
DoubleField,
|
||||||
@ -76,6 +78,7 @@ class Machine {
|
|||||||
System::Library* libraries;
|
System::Library* libraries;
|
||||||
object classMap;
|
object classMap;
|
||||||
object bootstrapClassMap;
|
object bootstrapClassMap;
|
||||||
|
object builtinMap;
|
||||||
object types;
|
object types;
|
||||||
bool unsafe;
|
bool unsafe;
|
||||||
};
|
};
|
||||||
@ -222,6 +225,7 @@ Machine::Machine(System* system, Heap* heap, ClassFinder* classFinder):
|
|||||||
libraries(0),
|
libraries(0),
|
||||||
classMap(0),
|
classMap(0),
|
||||||
bootstrapClassMap(0),
|
bootstrapClassMap(0),
|
||||||
|
builtinMap(0),
|
||||||
types(0),
|
types(0),
|
||||||
unsafe(false)
|
unsafe(false)
|
||||||
{
|
{
|
||||||
@ -429,6 +433,42 @@ listAppend(Thread* t, object list, object value)
|
|||||||
set(t, listRear(t, list), p);
|
set(t, listRear(t, list), p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
push(Thread* t, object o)
|
||||||
|
{
|
||||||
|
t->stack[(t->sp)++] = o;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
pushSafe(Thread* t, object o)
|
||||||
|
{
|
||||||
|
expect(t, t->sp + 1 < Thread::StackSizeInWords);
|
||||||
|
push(t, o);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline object
|
||||||
|
pop(Thread* t)
|
||||||
|
{
|
||||||
|
return t->stack[--(t->sp)];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline object&
|
||||||
|
top(Thread* t)
|
||||||
|
{
|
||||||
|
return t->stack[t->sp - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t
|
||||||
|
builtinToString(Thread* t, int32_t this_)
|
||||||
|
{
|
||||||
|
object o = t->stack[this_ - 1];
|
||||||
|
object s = makeString(t, "%s@%p",
|
||||||
|
&byteArrayBody(t, className(t, objectClass(o)), 0),
|
||||||
|
o);
|
||||||
|
pushSafe(t, s);
|
||||||
|
return t->sp;
|
||||||
|
}
|
||||||
|
|
||||||
Thread::Thread(Machine* m):
|
Thread::Thread(Machine* m):
|
||||||
vm(m),
|
vm(m),
|
||||||
next(0),
|
next(0),
|
||||||
@ -463,10 +503,29 @@ Thread::Thread(Machine* m):
|
|||||||
|
|
||||||
m->unsafe = false;
|
m->unsafe = false;
|
||||||
|
|
||||||
m->classMap = makeHashMap(this, 0, 0);
|
|
||||||
m->bootstrapClassMap = makeHashMap(this, 0, 0);
|
m->bootstrapClassMap = makeHashMap(this, 0, 0);
|
||||||
|
|
||||||
#include "type-java-initializations.cpp"
|
#include "type-java-initializations.cpp"
|
||||||
|
|
||||||
|
m->classMap = makeHashMap(this, 0, 0);
|
||||||
|
m->builtinMap = makeHashMap(this, 0, 0);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
const char* key;
|
||||||
|
void* value;
|
||||||
|
} builtins[] = {
|
||||||
|
{ "Java_java_lang_Object_toString",
|
||||||
|
reinterpret_cast<void*>(builtinToString) },
|
||||||
|
{ 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, m->builtinMap, key, value, byteArrayHash);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -524,6 +583,7 @@ collect(Machine* m, Heap::CollectionType type)
|
|||||||
virtual void visitRoots(Heap::Visitor* v) {
|
virtual void visitRoots(Heap::Visitor* v) {
|
||||||
v->visit(&(m->classMap));
|
v->visit(&(m->classMap));
|
||||||
v->visit(&(m->bootstrapClassMap));
|
v->visit(&(m->bootstrapClassMap));
|
||||||
|
v->visit(&(m->builtinMap));
|
||||||
v->visit(&(m->types));
|
v->visit(&(m->types));
|
||||||
|
|
||||||
for (Thread* t = m->rootThread; t; t = t->next) {
|
for (Thread* t = m->rootThread; t; t = t->next) {
|
||||||
@ -792,24 +852,6 @@ set(Thread* t, object& target, object value)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
|
||||||
push(Thread* t, object o)
|
|
||||||
{
|
|
||||||
t->stack[(t->sp)++] = o;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline object
|
|
||||||
pop(Thread* t)
|
|
||||||
{
|
|
||||||
return t->stack[--(t->sp)];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline object&
|
|
||||||
top(Thread* t)
|
|
||||||
{
|
|
||||||
return t->stack[t->sp - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline object
|
inline object
|
||||||
make(Thread* t, object class_)
|
make(Thread* t, object class_)
|
||||||
{
|
{
|
||||||
@ -1586,9 +1628,23 @@ parameterCount(Thread* t, object spec)
|
|||||||
}
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
makeJNIName(Thread* t, object method, bool decorate)
|
makeJNIName(Thread* t, object method, bool /*decorate*/)
|
||||||
{
|
{
|
||||||
// todo
|
object name = makeByteArray
|
||||||
|
(t, "Java_%s_%s",
|
||||||
|
&byteArrayBody(t, className(t, methodClass(t, method)), 0),
|
||||||
|
&byteArrayBody(t, methodName(t, method), 0));
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < byteArrayLength(t, name) - 1; ++i) {
|
||||||
|
switch (byteArrayBody(t, name, i)) {
|
||||||
|
case '/':
|
||||||
|
byteArrayBody(t, name, i) = '_';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo: decorate and translate as needed
|
||||||
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1648,15 +1704,21 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object method = makeMethod
|
unsigned parameterCount = ::parameterCount
|
||||||
(t,
|
(t, arrayBody(t, pool, spec - 1));
|
||||||
flags,
|
|
||||||
0, // offset
|
if ((flags & ACC_STATIC) == 0) {
|
||||||
parameterCount(t, arrayBody(t, pool, spec - 1)),
|
++ parameterCount;
|
||||||
arrayBody(t, pool, name - 1),
|
}
|
||||||
arrayBody(t, pool, spec - 1),
|
|
||||||
class_,
|
object method = makeMethod(t,
|
||||||
code);
|
flags,
|
||||||
|
0, // offset
|
||||||
|
parameterCount,
|
||||||
|
arrayBody(t, pool, name - 1),
|
||||||
|
arrayBody(t, pool, spec - 1),
|
||||||
|
class_,
|
||||||
|
code);
|
||||||
PROTECT(t, method);
|
PROTECT(t, method);
|
||||||
|
|
||||||
if (flags & ACC_STATIC) {
|
if (flags & ACC_STATIC) {
|
||||||
@ -1938,67 +2000,179 @@ resolveMethod(Thread* t, object pool, unsigned index)
|
|||||||
return resolve(t, pool, index, findMethodInClass);
|
return resolve(t, pool, index, findMethodInClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
makeNativeMethodData(Thread* t, object method, void* function, bool builtin)
|
||||||
|
{
|
||||||
|
PROTECT(t, method);
|
||||||
|
|
||||||
|
object data = makeNativeMethodData(t,
|
||||||
|
function,
|
||||||
|
0, // argument table size
|
||||||
|
0, // return code,
|
||||||
|
builtin,
|
||||||
|
methodParameterCount(t, method),
|
||||||
|
false);
|
||||||
|
|
||||||
|
unsigned argumentTableSize = sizeof(void*) / 4;
|
||||||
|
unsigned index = 0;
|
||||||
|
|
||||||
|
if ((methodFlags(t, method) & ACC_STATIC) == 0) {
|
||||||
|
nativeMethodDataParameterCodes(t, data, index++) = ObjectField;
|
||||||
|
argumentTableSize += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* s = reinterpret_cast<const char*>
|
||||||
|
(&byteArrayBody(t, methodSpec(t, method), 0));
|
||||||
|
++ s; // skip '('
|
||||||
|
while (*s and *s != ')') {
|
||||||
|
unsigned code = fieldCode(t, *s);
|
||||||
|
nativeMethodDataParameterCodes(t, data, index++) = code;
|
||||||
|
|
||||||
|
switch (*s) {
|
||||||
|
case 'L':
|
||||||
|
argumentTableSize += 1;
|
||||||
|
while (*s and *s != ';') ++ s;
|
||||||
|
++ s;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '[':
|
||||||
|
argumentTableSize += 1;
|
||||||
|
while (*s == '[') ++ s;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
argumentTableSize += divide(primitiveSize(t, code), 4);
|
||||||
|
++ s;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nativeMethodDataArgumentTableSize(t, data) = argumentTableSize;
|
||||||
|
nativeMethodDataReturnCode(t, data) = fieldCode(t, s[1]);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
inline object
|
inline object
|
||||||
resolveNativeMethodData(Thread* t, object method)
|
resolveNativeMethodData(Thread* t, object method)
|
||||||
{
|
{
|
||||||
if (objectClass(methodCode(t, method))
|
if (objectClass(methodCode(t, method))
|
||||||
== arrayBody(t, t->vm->types, Machine::ByteArrayType))
|
== arrayBody(t, t->vm->types, Machine::ByteArrayType))
|
||||||
{
|
{
|
||||||
|
object data = 0;
|
||||||
for (System::Library* lib = t->vm->libraries; lib; lib = lib->next()) {
|
for (System::Library* lib = t->vm->libraries; lib; lib = lib->next()) {
|
||||||
void* p = lib->resolve(reinterpret_cast<const char*>
|
void* p = lib->resolve(reinterpret_cast<const char*>
|
||||||
(&byteArrayBody(t, methodCode(t, method), 0)));
|
(&byteArrayBody(t, methodCode(t, method), 0)));
|
||||||
if (p) {
|
if (p) {
|
||||||
PROTECT(t, method);
|
PROTECT(t, method);
|
||||||
|
data = makeNativeMethodData(t, method, p, false);
|
||||||
object data = makeNativeMethodData(t,
|
break;
|
||||||
p,
|
|
||||||
0, // argument table size
|
|
||||||
0, // return code
|
|
||||||
methodParameterCount(t, method),
|
|
||||||
false);
|
|
||||||
|
|
||||||
unsigned argumentTableSize = 0;
|
|
||||||
unsigned index = 0;
|
|
||||||
const char* s = reinterpret_cast<const char*>
|
|
||||||
(&byteArrayBody(t, methodSpec(t, method), 0));
|
|
||||||
++ s; // skip '('
|
|
||||||
while (*s and *s != ')') {
|
|
||||||
unsigned code = fieldCode(t, *s);
|
|
||||||
nativeMethodDataParameterCodes(t, data, index++) = code;
|
|
||||||
|
|
||||||
switch (*s) {
|
|
||||||
case 'L':
|
|
||||||
argumentTableSize += 1;
|
|
||||||
while (*s and *s != ';') ++ s;
|
|
||||||
++ s;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '[':
|
|
||||||
argumentTableSize += 1;
|
|
||||||
while (*s == '[') ++ s;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
argumentTableSize += divide(primitiveSize(t, code), 4);
|
|
||||||
++ s;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nativeMethodDataArgumentTableSize(t, data) = argumentTableSize;
|
|
||||||
nativeMethodDataReturnCode(t, data) = fieldCode(t, s[1]);
|
|
||||||
|
|
||||||
set(t, methodCode(t, method), data);
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
if (data == 0) {
|
||||||
|
object p = hashMapFind(t, t->vm->builtinMap, methodCode(t, method),
|
||||||
|
byteArrayHash, byteArrayEqual);
|
||||||
|
if (p) {
|
||||||
|
PROTECT(t, method);
|
||||||
|
data = makeNativeMethodData(t, method, pointerValue(t, p), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
set(t, methodCode(t, method), data);
|
||||||
|
}
|
||||||
|
return data;
|
||||||
} else {
|
} else {
|
||||||
return methodCode(t, method);
|
return methodCode(t, method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline object
|
||||||
|
invokeNative(Thread* t, object method)
|
||||||
|
{
|
||||||
|
object data = resolveNativeMethodData(t, method);
|
||||||
|
if (UNLIKELY(data == 0)) {
|
||||||
|
object message = makeString
|
||||||
|
(t, "%s.%s:%s",
|
||||||
|
&byteArrayBody(t, className(t, methodClass(t, method)), 0),
|
||||||
|
&byteArrayBody(t, methodName(t, method), 0),
|
||||||
|
&byteArrayBody(t, methodSpec(t, method), 0));
|
||||||
|
t->exception = makeUnsatisfiedLinkError(t, message);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned parameterCount = methodParameterCount(t, method);
|
||||||
|
|
||||||
|
uint32_t args[nativeMethodDataArgumentTableSize(t, data)];
|
||||||
|
uint8_t sizes[parameterCount + 1];
|
||||||
|
unsigned offset = 0;
|
||||||
|
|
||||||
|
switch (sizeof(uintptr_t)) {
|
||||||
|
case 4: {
|
||||||
|
sizes[0] = 4;
|
||||||
|
args[offset++] = reinterpret_cast<uintptr_t>(t);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case 8: {
|
||||||
|
sizes[0] = 8;
|
||||||
|
uint64_t v = reinterpret_cast<uint64_t>(t);
|
||||||
|
args[offset++] = static_cast<uint32_t>(v >> 32);
|
||||||
|
args[offset++] = static_cast<uint32_t>(v & 0xFFFFFFFF);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
abort(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < parameterCount; ++i) {
|
||||||
|
unsigned code = nativeMethodDataParameterCodes(t, data, i);
|
||||||
|
|
||||||
|
if (code == ObjectField) {
|
||||||
|
sizes[i + 1] = 4;
|
||||||
|
args[offset++] = t->sp + i + 1;
|
||||||
|
} else {
|
||||||
|
sizes[i + 1] = primitiveSize(t, code);
|
||||||
|
uint64_t v = primitiveValue(t, code, t->stack[t->sp + i]);
|
||||||
|
if (sizes[i + 1] == 8) {
|
||||||
|
args[offset++] = static_cast<uint32_t>(v >> 32);
|
||||||
|
args[offset++] = static_cast<uint32_t>(v & 0xFFFFFFFF);
|
||||||
|
} else {
|
||||||
|
args[offset++] = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned returnCode = nativeMethodDataReturnCode(t, data);
|
||||||
|
unsigned returnSize
|
||||||
|
= (returnCode == ObjectField ? 4 : primitiveSize(t, returnCode));
|
||||||
|
|
||||||
|
void* function = nativeMethodDataFunction(t, data);
|
||||||
|
|
||||||
|
bool builtin = nativeMethodDataBuiltin(t, data);
|
||||||
|
if (not builtin) {
|
||||||
|
enter(t, Thread::IdleState);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t rv = t->vm->system->call(function,
|
||||||
|
parameterCount,
|
||||||
|
args,
|
||||||
|
sizes,
|
||||||
|
returnSize);
|
||||||
|
|
||||||
|
if (not builtin) {
|
||||||
|
enter(t, Thread::ActiveState);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UNLIKELY(t->exception) or returnCode == VoidField) {
|
||||||
|
return 0;
|
||||||
|
} else if (returnCode == ObjectField) {
|
||||||
|
return (rv == 0 ? 0 : t->stack[rv - 1]);
|
||||||
|
} else {
|
||||||
|
return makePrimitive(t, returnCode, rv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
run(Thread* t)
|
run(Thread* t)
|
||||||
{
|
{
|
||||||
@ -2008,7 +2182,6 @@ run(Thread* t)
|
|||||||
object& frame = t->frame;
|
object& frame = t->frame;
|
||||||
object& exception = t->exception;
|
object& exception = t->exception;
|
||||||
object* stack = t->stack;
|
object* stack = t->stack;
|
||||||
unsigned parameterCount = 0;
|
|
||||||
|
|
||||||
if (UNLIKELY(exception)) goto throw_;
|
if (UNLIKELY(exception)) goto throw_;
|
||||||
|
|
||||||
@ -2427,7 +2600,6 @@ run(Thread* t)
|
|||||||
set(t, classInitializer(t, fieldClass(t, field)), 0);
|
set(t, classInitializer(t, fieldClass(t, field)), 0);
|
||||||
code = clinit;
|
code = clinit;
|
||||||
ip -= 3;
|
ip -= 3;
|
||||||
parameterCount = 0;
|
|
||||||
goto invoke;
|
goto invoke;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2800,7 +2972,7 @@ run(Thread* t)
|
|||||||
object method = resolveMethod(t, codePool(t, code), index - 1);
|
object method = resolveMethod(t, codePool(t, code), index - 1);
|
||||||
if (UNLIKELY(exception)) goto throw_;
|
if (UNLIKELY(exception)) goto throw_;
|
||||||
|
|
||||||
parameterCount = methodParameterCount(t, method);
|
unsigned parameterCount = methodParameterCount(t, method);
|
||||||
if (LIKELY(stack[sp - parameterCount])) {
|
if (LIKELY(stack[sp - parameterCount])) {
|
||||||
code = findInterfaceMethod(t, method, stack[sp - parameterCount]);
|
code = findInterfaceMethod(t, method, stack[sp - parameterCount]);
|
||||||
if (UNLIKELY(exception)) goto throw_;
|
if (UNLIKELY(exception)) goto throw_;
|
||||||
@ -2820,7 +2992,7 @@ run(Thread* t)
|
|||||||
object method = resolveMethod(t, codePool(t, code), index - 1);
|
object method = resolveMethod(t, codePool(t, code), index - 1);
|
||||||
if (UNLIKELY(exception)) goto throw_;
|
if (UNLIKELY(exception)) goto throw_;
|
||||||
|
|
||||||
parameterCount = methodParameterCount(t, method);
|
unsigned parameterCount = methodParameterCount(t, method);
|
||||||
if (LIKELY(stack[sp - parameterCount])) {
|
if (LIKELY(stack[sp - parameterCount])) {
|
||||||
object class_ = methodClass(t, frameMethod(t, t->frame));
|
object class_ = methodClass(t, frameMethod(t, t->frame));
|
||||||
if (isSpecialMethod(t, method, class_)) {
|
if (isSpecialMethod(t, method, class_)) {
|
||||||
@ -2850,11 +3022,9 @@ run(Thread* t)
|
|||||||
set(t, classInitializer(t, methodClass(t, method)), 0);
|
set(t, classInitializer(t, methodClass(t, method)), 0);
|
||||||
code = clinit;
|
code = clinit;
|
||||||
ip -= 3;
|
ip -= 3;
|
||||||
parameterCount = 0;
|
|
||||||
goto invoke;
|
goto invoke;
|
||||||
}
|
}
|
||||||
|
|
||||||
parameterCount = methodParameterCount(t, method);
|
|
||||||
code = method;
|
code = method;
|
||||||
} goto invoke;
|
} goto invoke;
|
||||||
|
|
||||||
@ -2866,7 +3036,7 @@ run(Thread* t)
|
|||||||
object method = resolveMethod(t, codePool(t, code), index - 1);
|
object method = resolveMethod(t, codePool(t, code), index - 1);
|
||||||
if (UNLIKELY(exception)) goto throw_;
|
if (UNLIKELY(exception)) goto throw_;
|
||||||
|
|
||||||
parameterCount = methodParameterCount(t, method);
|
unsigned parameterCount = methodParameterCount(t, method);
|
||||||
if (LIKELY(stack[sp - parameterCount])) {
|
if (LIKELY(stack[sp - parameterCount])) {
|
||||||
code = findVirtualMethod(t, method, stack[sp - parameterCount]);
|
code = findVirtualMethod(t, method, stack[sp - parameterCount]);
|
||||||
if (UNLIKELY(exception)) goto throw_;
|
if (UNLIKELY(exception)) goto throw_;
|
||||||
@ -3122,7 +3292,6 @@ run(Thread* t)
|
|||||||
set(t, classInitializer(t, class_), 0);
|
set(t, classInitializer(t, class_), 0);
|
||||||
code = clinit;
|
code = clinit;
|
||||||
ip -= 3;
|
ip -= 3;
|
||||||
parameterCount = 0;
|
|
||||||
goto invoke;
|
goto invoke;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3228,7 +3397,6 @@ run(Thread* t)
|
|||||||
set(t, classInitializer(t, fieldClass(t, field)), 0);
|
set(t, classInitializer(t, fieldClass(t, field)), 0);
|
||||||
code = clinit;
|
code = clinit;
|
||||||
ip -= 3;
|
ip -= 3;
|
||||||
parameterCount = 0;
|
|
||||||
goto invoke;
|
goto invoke;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3359,65 +3527,27 @@ run(Thread* t)
|
|||||||
default: abort(t);
|
default: abort(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
invoke: {
|
invoke: {
|
||||||
if (UNLIKELY(codeMaxStack(t, methodCode(t, code)) + sp - parameterCount
|
unsigned parameterCount = methodParameterCount(t, code);
|
||||||
|
unsigned base = sp - parameterCount;
|
||||||
|
|
||||||
|
if (UNLIKELY(codeMaxStack(t, methodCode(t, code)) + base
|
||||||
> Thread::StackSizeInWords))
|
> Thread::StackSizeInWords))
|
||||||
{
|
{
|
||||||
exception = makeStackOverflowError(t);
|
exception = makeStackOverflowError(t);
|
||||||
goto throw_;
|
goto throw_;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned base = sp - parameterCount;
|
|
||||||
|
|
||||||
if (methodFlags(t, code) & ACC_NATIVE) {
|
if (methodFlags(t, code) & ACC_NATIVE) {
|
||||||
object data = resolveNativeMethodData(t, code);
|
object r = invokeNative(t, code);
|
||||||
if (UNLIKELY(data == 0)) {
|
|
||||||
object message = makeString
|
if (UNLIKELY(exception)) {
|
||||||
(t, "%s.%s:%s",
|
|
||||||
&byteArrayBody(t, className(t, methodClass(t, code)), 0),
|
|
||||||
&byteArrayBody(t, methodName(t, code), 0),
|
|
||||||
&byteArrayBody(t, methodSpec(t, code), 0));
|
|
||||||
exception = makeUnsatisfiedLinkError(t, message);
|
|
||||||
goto throw_;
|
goto throw_;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t args[nativeMethodDataArgumentTableSize(t, data)];
|
|
||||||
uint8_t sizes[parameterCount];
|
|
||||||
unsigned offset = 0;
|
|
||||||
for (unsigned i = 0; i < parameterCount; ++i) {
|
|
||||||
unsigned code = nativeMethodDataParameterCodes(t, data, i);
|
|
||||||
|
|
||||||
if (code == ObjectField) {
|
|
||||||
sizes[i] = 4;
|
|
||||||
args[offset++] = sp + i + 1;
|
|
||||||
} else {
|
|
||||||
sizes[i] = primitiveSize(t, code);
|
|
||||||
uint64_t v = primitiveValue(t, code, stack[sp + i]);
|
|
||||||
if (sizes[i] == 8) {
|
|
||||||
args[offset++] = static_cast<uint32_t>(v & 0xFFFFFFFF);
|
|
||||||
args[offset++] = static_cast<uint32_t>(v >> 32);
|
|
||||||
} else {
|
|
||||||
args[offset++] = v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned returnCode = nativeMethodDataReturnCode(t, data);
|
|
||||||
unsigned returnSize
|
|
||||||
= (returnCode == ObjectField ? 4 : primitiveSize(t, returnCode));
|
|
||||||
|
|
||||||
uint64_t rv = t->vm->system->call(nativeMethodDataPointer(t, data),
|
|
||||||
parameterCount,
|
|
||||||
args,
|
|
||||||
sizes,
|
|
||||||
returnSize);
|
|
||||||
|
|
||||||
sp = base;
|
sp = base;
|
||||||
|
if (nativeMethodDataReturnCode(t, methodCode(t, code)) != VoidField) {
|
||||||
if (returnCode == ObjectField) {
|
push(t, r);
|
||||||
push(t, (rv == 0 ? 0 : stack[rv - 1]));
|
|
||||||
} else {
|
|
||||||
push(t, makePrimitive(t, returnCode, rv));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
frameIp(t, frame) = ip;
|
frameIp(t, frame) = ip;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user