2007-07-06 23:50:26 +00:00
|
|
|
#include "builtin.h"
|
|
|
|
#include "machine.h"
|
2007-07-24 01:44:20 +00:00
|
|
|
#include "constants.h"
|
2007-07-07 18:09:16 +00:00
|
|
|
#include "run.h"
|
2007-07-06 15:24:06 +00:00
|
|
|
|
2007-07-24 01:44:20 +00:00
|
|
|
using namespace vm;
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
object
|
|
|
|
doInvoke(Thread* t, object this_, object instance, object arguments)
|
|
|
|
{
|
|
|
|
object v = pushReference(t, run2(t, this_, instance, arguments));
|
|
|
|
if (t->exception) {
|
|
|
|
t->exception = makeInvocationTargetException(t, t->exception);
|
|
|
|
}
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void
|
|
|
|
replace(char a, char b, char* c)
|
|
|
|
{
|
|
|
|
for (; *c; ++c) if (*c == a) *c = b;
|
|
|
|
}
|
|
|
|
|
2007-07-07 23:47:35 +00:00
|
|
|
jstring
|
2007-07-27 00:06:05 +00:00
|
|
|
Object_toString(Thread* t, jobject this_)
|
2007-07-07 23:47:35 +00:00
|
|
|
{
|
|
|
|
object s = makeString
|
|
|
|
(t, "%s@%p",
|
|
|
|
&byteArrayBody(t, className(t, objectClass(t, *this_)), 0),
|
|
|
|
*this_);
|
|
|
|
|
|
|
|
return pushReference(t, s);
|
|
|
|
}
|
|
|
|
|
2007-07-12 23:46:08 +00:00
|
|
|
jclass
|
2007-07-27 00:06:05 +00:00
|
|
|
Object_getClass(Thread* t, jobject this_)
|
2007-07-12 23:46:08 +00:00
|
|
|
{
|
|
|
|
return pushReference(t, objectClass(t, *this_));
|
|
|
|
}
|
|
|
|
|
2007-07-07 23:47:35 +00:00
|
|
|
void
|
2007-07-27 00:06:05 +00:00
|
|
|
Object_wait(Thread* t, jobject this_, jlong milliseconds)
|
2007-07-07 23:47:35 +00:00
|
|
|
{
|
|
|
|
vm::wait(t, *this_, milliseconds);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2007-07-27 00:06:05 +00:00
|
|
|
Object_notify(Thread* t, jobject this_)
|
2007-07-07 23:47:35 +00:00
|
|
|
{
|
2007-08-13 00:50:25 +00:00
|
|
|
notify(t, *this_);
|
2007-07-07 23:47:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2007-07-27 00:06:05 +00:00
|
|
|
Object_notifyAll(Thread* t, jobject this_)
|
2007-07-07 23:47:35 +00:00
|
|
|
{
|
2007-08-13 00:50:25 +00:00
|
|
|
notifyAll(t, *this_);
|
|
|
|
}
|
|
|
|
|
|
|
|
jint
|
|
|
|
Object_hashCode(Thread* t, jobject this_)
|
|
|
|
{
|
|
|
|
return objectHash(t, *this_);
|
2007-07-07 23:47:35 +00:00
|
|
|
}
|
|
|
|
|
2007-07-24 01:44:20 +00:00
|
|
|
jclass
|
2007-08-10 23:45:47 +00:00
|
|
|
ClassLoader_defineClass(Thread* t, jclass, jbyteArray b, jint offset,
|
|
|
|
jint length)
|
|
|
|
{
|
|
|
|
uint8_t* buffer = static_cast<uint8_t*>(t->vm->system->allocate(length));
|
|
|
|
memcpy(buffer, &byteArrayBody(t, *b, offset), length);
|
|
|
|
object c = parseClass(t, buffer, length);
|
|
|
|
t->vm->system->free(buffer);
|
|
|
|
return pushReference(t, c);
|
|
|
|
}
|
|
|
|
|
|
|
|
jclass
|
|
|
|
search(Thread* t, jstring name, object (*op)(Thread*, object),
|
|
|
|
bool replaceDots)
|
2007-07-24 01:44:20 +00:00
|
|
|
{
|
|
|
|
if (LIKELY(name)) {
|
|
|
|
object n = makeByteArray(t, stringLength(t, *name) + 1, false);
|
|
|
|
char* s = reinterpret_cast<char*>(&byteArrayBody(t, n, 0));
|
|
|
|
stringChars(t, *name, s);
|
|
|
|
|
2007-08-10 23:45:47 +00:00
|
|
|
if (replaceDots) {
|
|
|
|
replace('.', '/', s);
|
|
|
|
}
|
2007-07-24 01:44:20 +00:00
|
|
|
|
2007-08-10 23:45:47 +00:00
|
|
|
object r = op(t, n);
|
2007-07-24 01:44:20 +00:00
|
|
|
if (t->exception) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-08-10 23:45:47 +00:00
|
|
|
return pushReference(t, r);
|
2007-07-24 01:44:20 +00:00
|
|
|
} else {
|
|
|
|
t->exception = makeNullPointerException(t);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-07-30 23:19:05 +00:00
|
|
|
jclass
|
2007-08-10 23:45:47 +00:00
|
|
|
SystemClassLoader_findLoadedClass(Thread* t, jclass, jstring name)
|
2007-07-30 23:19:05 +00:00
|
|
|
{
|
2007-08-10 23:45:47 +00:00
|
|
|
return search(t, name, findLoadedClass, true);
|
2007-07-30 23:19:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
jclass
|
2007-08-10 23:45:47 +00:00
|
|
|
SystemClassLoader_findClass(Thread* t, jclass, jstring name)
|
2007-07-30 23:19:05 +00:00
|
|
|
{
|
2007-08-10 23:45:47 +00:00
|
|
|
return search(t, name, resolveClass, true);
|
2007-07-30 23:19:05 +00:00
|
|
|
}
|
|
|
|
|
2007-08-10 23:45:47 +00:00
|
|
|
jboolean
|
|
|
|
SystemClassLoader_resourceExists(Thread* t, jclass, jstring name)
|
2007-07-30 23:19:05 +00:00
|
|
|
{
|
2007-08-10 23:45:47 +00:00
|
|
|
if (LIKELY(name)) {
|
|
|
|
char n[stringLength(t, *name) + 1];
|
|
|
|
stringChars(t, *name, n);
|
|
|
|
return t->vm->finder->exists(n);
|
|
|
|
} else {
|
|
|
|
t->exception = makeNullPointerException(t);
|
|
|
|
return 0;
|
|
|
|
}
|
2007-07-30 23:19:05 +00:00
|
|
|
}
|
|
|
|
|
2007-08-13 00:50:25 +00:00
|
|
|
jobject
|
|
|
|
ObjectInputStream_makeInstance(Thread* t, jclass, jclass c)
|
|
|
|
{
|
|
|
|
return pushReference(t, make(t, *c));
|
|
|
|
}
|
|
|
|
|
2007-07-28 16:55:24 +00:00
|
|
|
jclass
|
|
|
|
Class_primitiveClass(Thread* t, jclass, jchar name)
|
|
|
|
{
|
|
|
|
switch (name) {
|
|
|
|
case 'B':
|
|
|
|
return pushReference(t, arrayBody(t, t->vm->types, Machine::JbyteType));
|
|
|
|
case 'C':
|
|
|
|
return pushReference(t, arrayBody(t, t->vm->types, Machine::JcharType));
|
|
|
|
case 'D':
|
|
|
|
return pushReference(t, arrayBody(t, t->vm->types, Machine::JdoubleType));
|
|
|
|
case 'F':
|
|
|
|
return pushReference(t, arrayBody(t, t->vm->types, Machine::JfloatType));
|
|
|
|
case 'I':
|
|
|
|
return pushReference(t, arrayBody(t, t->vm->types, Machine::JintType));
|
2007-07-29 23:32:23 +00:00
|
|
|
case 'J':
|
2007-07-28 16:55:24 +00:00
|
|
|
return pushReference(t, arrayBody(t, t->vm->types, Machine::JlongType));
|
|
|
|
case 'S':
|
|
|
|
return pushReference(t, arrayBody(t, t->vm->types, Machine::JshortType));
|
|
|
|
case 'V':
|
|
|
|
return pushReference(t, arrayBody(t, t->vm->types, Machine::JvoidType));
|
2007-07-29 23:32:23 +00:00
|
|
|
case 'Z':
|
|
|
|
return pushReference(t, arrayBody(t, t->vm->types, Machine::JbooleanType));
|
2007-07-28 16:55:24 +00:00
|
|
|
default:
|
|
|
|
t->exception = makeIllegalArgumentException(t);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-08-01 23:48:36 +00:00
|
|
|
void
|
|
|
|
Class_initialize(Thread* t, jobject this_)
|
|
|
|
{
|
|
|
|
acquire(t, t->vm->classLock);
|
|
|
|
object c = *this_;
|
|
|
|
if (classVmFlags(t, c) & NeedInitFlag
|
|
|
|
and (classVmFlags(t, c) & InitFlag) == 0)
|
|
|
|
{
|
|
|
|
classVmFlags(t, c) |= InitFlag;
|
|
|
|
run(t, classInitializer(t, c), 0);
|
|
|
|
} else {
|
|
|
|
release(t, t->vm->classLock);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-07-24 01:44:20 +00:00
|
|
|
jboolean
|
2007-07-27 00:06:05 +00:00
|
|
|
Class_isAssignableFrom(Thread* t, jobject this_, jclass that)
|
2007-07-24 01:44:20 +00:00
|
|
|
{
|
|
|
|
if (LIKELY(that)) {
|
|
|
|
return vm::isAssignableFrom(t, *this_, *that);
|
|
|
|
} else {
|
|
|
|
t->exception = makeNullPointerException(t);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
jobject
|
2007-07-27 00:06:05 +00:00
|
|
|
Field_get(Thread* t, jobject this_, jobject instancep)
|
2007-07-24 01:44:20 +00:00
|
|
|
{
|
|
|
|
object field = *this_;
|
|
|
|
|
|
|
|
if (fieldFlags(t, field) & ACC_STATIC) {
|
2007-07-28 16:10:13 +00:00
|
|
|
object v = arrayBody(t, classStaticTable(t, fieldClass(t, field)),
|
|
|
|
fieldOffset(t, field));
|
|
|
|
|
|
|
|
switch (fieldCode(t, field)) {
|
|
|
|
case ByteField:
|
|
|
|
return pushReference(t, makeByte(t, intValue(t, v)));
|
|
|
|
|
|
|
|
case BooleanField:
|
|
|
|
return pushReference(t, makeBoolean(t, intValue(t, v)));
|
|
|
|
|
|
|
|
case CharField:
|
|
|
|
return pushReference(t, makeChar(t, intValue(t, v)));
|
|
|
|
|
|
|
|
case ShortField:
|
|
|
|
return pushReference(t, makeShort(t, intValue(t, v)));
|
|
|
|
|
|
|
|
case FloatField:
|
|
|
|
return pushReference(t, makeFloat(t, intValue(t, v)));
|
|
|
|
|
|
|
|
case DoubleField:
|
|
|
|
return pushReference(t, makeDouble(t, longValue(t, v)));
|
|
|
|
|
|
|
|
case IntField:
|
|
|
|
case LongField:
|
|
|
|
case ObjectField:
|
|
|
|
return pushReference(t, v);
|
|
|
|
|
|
|
|
default:
|
|
|
|
abort(t);
|
|
|
|
}
|
2007-07-24 01:44:20 +00:00
|
|
|
} else if (instancep) {
|
|
|
|
object instance = *instancep;
|
|
|
|
|
|
|
|
if (instanceOf(t, fieldClass(t, this_), instance)) {
|
|
|
|
switch (fieldCode(t, field)) {
|
|
|
|
case ByteField:
|
|
|
|
return pushReference
|
|
|
|
(t, makeByte(t, cast<int8_t>(instance, fieldOffset(t, field))));
|
|
|
|
|
|
|
|
case BooleanField:
|
|
|
|
return pushReference
|
|
|
|
(t, makeBoolean(t, cast<uint8_t>(instance, fieldOffset(t, field))));
|
|
|
|
|
|
|
|
case CharField:
|
|
|
|
return pushReference
|
|
|
|
(t, makeChar(t, cast<uint16_t>(instance, fieldOffset(t, field))));
|
|
|
|
|
|
|
|
case ShortField:
|
|
|
|
return pushReference
|
|
|
|
(t, makeShort(t, cast<int16_t>(instance, fieldOffset(t, field))));
|
|
|
|
|
|
|
|
case FloatField:
|
|
|
|
return pushReference
|
|
|
|
(t, makeFloat(t, cast<uint32_t>(instance, fieldOffset(t, field))));
|
|
|
|
|
|
|
|
case IntField:
|
|
|
|
return pushReference
|
|
|
|
(t, makeInt(t, cast<int32_t>(instance, fieldOffset(t, field))));
|
|
|
|
|
|
|
|
case DoubleField:
|
|
|
|
return pushReference
|
|
|
|
(t, makeDouble(t, cast<uint64_t>(instance, fieldOffset(t, field))));
|
|
|
|
|
|
|
|
case LongField:
|
|
|
|
return pushReference
|
|
|
|
(t, makeLong(t, cast<int64_t>(instance, fieldOffset(t, field))));
|
|
|
|
|
|
|
|
case ObjectField:
|
|
|
|
return pushReference
|
|
|
|
(t, cast<object>(instance, fieldOffset(t, field)));
|
|
|
|
|
|
|
|
default:
|
|
|
|
abort(t);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
t->exception = makeIllegalArgumentException(t);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
t->exception = makeNullPointerException(t);
|
2007-07-27 23:56:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Field_set(Thread* t, jobject this_, jobject instancep, jobject value)
|
|
|
|
{
|
|
|
|
object field = *this_;
|
|
|
|
object v = (value ? *value : 0);
|
|
|
|
|
|
|
|
if (fieldFlags(t, field) & ACC_STATIC) {
|
2007-07-28 16:10:13 +00:00
|
|
|
object* p = &arrayBody(t, classStaticTable(t, fieldClass(t, field)),
|
|
|
|
fieldOffset(t, field));
|
|
|
|
|
2007-07-27 23:56:19 +00:00
|
|
|
if (fieldCode(t, field) == ObjectField or v) {
|
2007-07-28 16:10:13 +00:00
|
|
|
switch (fieldCode(t, field)) {
|
|
|
|
case ByteField:
|
|
|
|
set(t, *p, makeInt(t, byteValue(t, v)));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case BooleanField:
|
|
|
|
set(t, *p, makeInt(t, booleanValue(t, v)));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CharField:
|
|
|
|
set(t, *p, makeInt(t, charValue(t, v)));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ShortField:
|
|
|
|
set(t, *p, makeInt(t, shortValue(t, v)));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FloatField:
|
|
|
|
set(t, *p, makeInt(t, floatValue(t, v)));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DoubleField:
|
|
|
|
set(t, *p, makeLong(t, longValue(t, v)));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IntField:
|
|
|
|
case LongField:
|
|
|
|
case ObjectField:
|
|
|
|
set(t, *p, v);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
abort(t);
|
|
|
|
}
|
2007-07-27 23:56:19 +00:00
|
|
|
} else {
|
|
|
|
t->exception = makeNullPointerException(t);
|
|
|
|
}
|
|
|
|
} else if (instancep) {
|
|
|
|
object instance = *instancep;
|
|
|
|
|
|
|
|
if (instanceOf(t, fieldClass(t, this_), instance)) {
|
|
|
|
switch (fieldCode(t, field)) {
|
|
|
|
case ObjectField:
|
|
|
|
set(t, cast<object>(instance, fieldOffset(t, field)), v);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default: {
|
|
|
|
uint8_t* body = &cast<uint8_t>(instance, fieldOffset(t, field));
|
|
|
|
if (v) {
|
|
|
|
memcpy(body, &cast<uint8_t>(v, BytesPerWord),
|
|
|
|
primitiveSize(t, fieldCode(t, field)));
|
|
|
|
} else {
|
|
|
|
t->exception = makeNullPointerException(t);
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
t->exception = makeIllegalArgumentException(t);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
t->exception = makeNullPointerException(t);
|
2007-07-24 01:44:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-07-27 02:39:53 +00:00
|
|
|
jobject
|
|
|
|
Constructor_make(Thread* t, jclass, jclass c)
|
|
|
|
{
|
|
|
|
return pushReference(t, make(t, c));
|
|
|
|
}
|
|
|
|
|
2007-07-30 23:19:05 +00:00
|
|
|
jobject
|
|
|
|
Method_getCaller(Thread* t, jclass)
|
|
|
|
{
|
|
|
|
return pushReference
|
|
|
|
(t, frameMethod(t, frameNext(t, frameNext(t, t->frame))));
|
|
|
|
}
|
|
|
|
|
2007-07-24 01:44:20 +00:00
|
|
|
jobject
|
2007-07-27 00:06:05 +00:00
|
|
|
Method_invoke(Thread* t, jobject this_, jobject instancep,
|
|
|
|
jobjectArray argumentsp)
|
2007-07-24 01:44:20 +00:00
|
|
|
{
|
|
|
|
object method = *this_;
|
|
|
|
|
2007-07-24 03:16:59 +00:00
|
|
|
if (argumentsp) {
|
|
|
|
object arguments = *argumentsp;
|
|
|
|
|
2007-07-24 01:44:20 +00:00
|
|
|
if (methodFlags(t, method) & ACC_STATIC) {
|
2007-07-24 03:16:59 +00:00
|
|
|
if (objectArrayLength(t, arguments)
|
|
|
|
== methodParameterCount(t, method))
|
|
|
|
{
|
|
|
|
return pushReference(t, doInvoke(t, method, 0, arguments));
|
2007-07-24 01:44:20 +00:00
|
|
|
} else {
|
|
|
|
t->exception = makeArrayIndexOutOfBoundsException(t, 0);
|
|
|
|
}
|
2007-07-24 03:16:59 +00:00
|
|
|
} else if (instancep) {
|
|
|
|
object instance = *instancep;
|
|
|
|
|
2007-07-24 01:44:20 +00:00
|
|
|
if (instanceOf(t, methodClass(t, method), instance)) {
|
|
|
|
if (objectArrayLength(t, arguments)
|
|
|
|
== static_cast<unsigned>(methodParameterCount(t, method) - 1))
|
|
|
|
{
|
2007-07-24 03:16:59 +00:00
|
|
|
return pushReference(t, doInvoke(t, method, instance, arguments));
|
2007-07-24 01:44:20 +00:00
|
|
|
} else {
|
|
|
|
t->exception = makeArrayIndexOutOfBoundsException(t, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
t->exception = makeNullPointerException(t);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
t->exception = makeNullPointerException(t);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-07-27 02:39:53 +00:00
|
|
|
jobject
|
|
|
|
Array_get(Thread* t, jobject array, int index)
|
|
|
|
{
|
|
|
|
if (LIKELY(array)) {
|
|
|
|
object a = *array;
|
|
|
|
unsigned elementSize = classArrayElementSize(t, objectClass(t, a));
|
|
|
|
|
|
|
|
if (LIKELY(elementSize)) {
|
|
|
|
intptr_t length = cast<uintptr_t>(a, BytesPerWord);
|
|
|
|
|
|
|
|
if (LIKELY(index >= 0 and index < length)) {
|
|
|
|
switch (byteArrayBody(t, className(t, objectClass(t, a)), 1)) {
|
|
|
|
case 'B':
|
|
|
|
return pushReference(t, makeByte(t, byteArrayBody(t, a, index)));
|
|
|
|
case 'C':
|
|
|
|
return pushReference(t, makeChar(t, charArrayBody(t, a, index)));
|
|
|
|
case 'D':
|
|
|
|
return pushReference(t, makeDouble(t, doubleArrayBody(t, a, index)));
|
|
|
|
case 'F':
|
|
|
|
return pushReference(t, makeFloat(t, floatArrayBody(t, a, index)));
|
|
|
|
case 'I':
|
|
|
|
return pushReference(t, makeInt(t, intArrayBody(t, a, index)));
|
|
|
|
case 'J':
|
|
|
|
return pushReference(t, makeLong(t, longArrayBody(t, a, index)));
|
|
|
|
case 'S':
|
|
|
|
return pushReference(t, makeShort(t, shortArrayBody(t, a, index)));
|
|
|
|
case 'Z':
|
|
|
|
return pushReference
|
|
|
|
(t, makeBoolean(t, booleanArrayBody(t, a, index)));
|
|
|
|
case 'L':
|
|
|
|
case '[':
|
|
|
|
return pushReference(t, objectArrayBody(t, a, index));
|
|
|
|
|
|
|
|
default: abort(t);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
t->exception = makeArrayIndexOutOfBoundsException(t, 0);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
t->exception = makeIllegalArgumentException(t);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
t->exception = makeNullPointerException(t);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-07-27 23:56:19 +00:00
|
|
|
void
|
|
|
|
Array_set(Thread* t, jobject array, int index, jobject value)
|
|
|
|
{
|
|
|
|
if (LIKELY(array)) {
|
|
|
|
object a = *array;
|
|
|
|
object v = (value ? *value : 0);
|
|
|
|
unsigned elementSize = classArrayElementSize(t, objectClass(t, a));
|
|
|
|
|
|
|
|
if (LIKELY(elementSize)) {
|
|
|
|
intptr_t length = cast<uintptr_t>(a, BytesPerWord);
|
|
|
|
|
|
|
|
if (LIKELY(index >= 0 and index < length)) {
|
|
|
|
switch (byteArrayBody(t, className(t, objectClass(t, a)), 1)) {
|
|
|
|
case 'L':
|
|
|
|
case '[':
|
|
|
|
set(t, objectArrayBody(t, a, index), v);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default: {
|
|
|
|
uint8_t* p = &cast<uint8_t>
|
|
|
|
(a, (2 * BytesPerWord) + (index * elementSize));
|
|
|
|
if (v) {
|
|
|
|
memcpy(p, &cast<uint8_t>(v, BytesPerWord), elementSize);
|
|
|
|
} else {
|
|
|
|
t->exception = makeNullPointerException(t);
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
t->exception = makeArrayIndexOutOfBoundsException(t, 0);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
t->exception = makeIllegalArgumentException(t);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
t->exception = makeNullPointerException(t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-07-27 02:39:53 +00:00
|
|
|
jint
|
|
|
|
Array_getLength(Thread* t, jobject array)
|
|
|
|
{
|
|
|
|
if (LIKELY(array)) {
|
|
|
|
object a = *array;
|
|
|
|
unsigned elementSize = classArrayElementSize(t, objectClass(t, a));
|
|
|
|
|
|
|
|
if (LIKELY(elementSize)) {
|
|
|
|
return cast<uintptr_t>(a, BytesPerWord);
|
|
|
|
} else {
|
|
|
|
t->exception = makeIllegalArgumentException(t);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
t->exception = makeNullPointerException(t);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
jobject
|
|
|
|
Array_makeObjectArray(Thread* t, jclass, jclass elementType, jint length)
|
|
|
|
{
|
|
|
|
return pushReference(t, makeObjectArray(t, *elementType, length, true));
|
|
|
|
}
|
|
|
|
|
2007-07-29 00:02:32 +00:00
|
|
|
jobject
|
|
|
|
String_intern(Thread* t, jobject this_)
|
|
|
|
{
|
|
|
|
return pushReference(t, intern(t, *this_));
|
|
|
|
}
|
|
|
|
|
2007-07-07 23:47:35 +00:00
|
|
|
void
|
2007-07-27 00:06:05 +00:00
|
|
|
System_arraycopy(Thread* t, jclass, jobject src, jint srcOffset, jobject dst,
|
|
|
|
jint dstOffset, jint length)
|
2007-07-06 15:24:06 +00:00
|
|
|
{
|
2007-07-07 23:47:35 +00:00
|
|
|
if (LIKELY(src and dst)) {
|
|
|
|
object s = *src;
|
|
|
|
object d = *dst;
|
|
|
|
|
|
|
|
if (LIKELY(objectClass(t, s) == objectClass(t, d))) {
|
|
|
|
unsigned elementSize = classArrayElementSize(t, objectClass(t, s));
|
|
|
|
|
|
|
|
if (LIKELY(elementSize)) {
|
2007-07-14 17:31:01 +00:00
|
|
|
intptr_t sl = cast<uintptr_t>(s, BytesPerWord);
|
|
|
|
intptr_t dl = cast<uintptr_t>(d, BytesPerWord);
|
2007-07-07 23:47:35 +00:00
|
|
|
if (LIKELY(srcOffset >= 0 and srcOffset + length <= sl and
|
2007-07-11 01:38:06 +00:00
|
|
|
dstOffset >= 0 and dstOffset + length <= dl))
|
2007-07-07 23:47:35 +00:00
|
|
|
{
|
2007-07-14 17:31:01 +00:00
|
|
|
uint8_t* sbody = &cast<uint8_t>(s, 2 * BytesPerWord);
|
|
|
|
uint8_t* dbody = &cast<uint8_t>(d, 2 * BytesPerWord);
|
2007-07-22 03:47:08 +00:00
|
|
|
if (src == dst) {
|
|
|
|
memmove(dbody + (dstOffset * elementSize),
|
|
|
|
sbody + (srcOffset * elementSize),
|
|
|
|
length * elementSize);
|
|
|
|
} else {
|
|
|
|
memcpy(dbody + (dstOffset * elementSize),
|
|
|
|
sbody + (srcOffset * elementSize),
|
|
|
|
length * elementSize);
|
|
|
|
}
|
2007-07-07 23:47:35 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
t->exception = makeNullPointerException(t);
|
|
|
|
return;
|
|
|
|
}
|
2007-07-06 15:24:06 +00:00
|
|
|
|
2007-07-07 23:47:35 +00:00
|
|
|
t->exception = makeArrayStoreException(t);
|
2007-07-06 15:24:06 +00:00
|
|
|
}
|
|
|
|
|
2007-08-13 00:50:25 +00:00
|
|
|
jint
|
|
|
|
System_identityHashCode(Thread* t, jclass, jobject o)
|
|
|
|
{
|
|
|
|
if (LIKELY(o)) {
|
|
|
|
return objectHash(t, *o);
|
|
|
|
} else {
|
|
|
|
t->exception = makeNullPointerException(t);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-07-20 03:18:25 +00:00
|
|
|
void
|
2007-07-27 00:06:05 +00:00
|
|
|
Runtime_loadLibrary(Thread* t, jobject, jstring name)
|
2007-07-21 17:50:26 +00:00
|
|
|
{
|
2007-07-24 01:44:20 +00:00
|
|
|
if (LIKELY(name)) {
|
|
|
|
char n[stringLength(t, *name) + 1];
|
|
|
|
stringChars(t, *name, n);
|
2007-07-21 17:50:26 +00:00
|
|
|
|
|
|
|
for (System::Library* lib = t->vm->libraries; lib; lib = lib->next()) {
|
2007-07-24 01:44:20 +00:00
|
|
|
if (::strcmp(lib->name(), n) == 0) {
|
2007-07-21 17:50:26 +00:00
|
|
|
// already loaded
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
System::Library* lib;
|
|
|
|
if (LIKELY(t->vm->system->success
|
2007-07-24 01:44:20 +00:00
|
|
|
(t->vm->system->load(&lib, n, t->vm->libraries))))
|
2007-07-21 17:50:26 +00:00
|
|
|
{
|
|
|
|
t->vm->libraries = lib;
|
|
|
|
} else {
|
2007-07-24 01:44:20 +00:00
|
|
|
object message = makeString(t, "library not found: %s", n);
|
2007-07-21 17:50:26 +00:00
|
|
|
t->exception = makeRuntimeException(t, message);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
t->exception = makeNullPointerException(t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2007-07-27 00:06:05 +00:00
|
|
|
Runtime_gc(Thread* t, jobject)
|
2007-07-20 03:18:25 +00:00
|
|
|
{
|
|
|
|
ENTER(t, Thread::ExclusiveState);
|
|
|
|
|
|
|
|
collect(t, Heap::MajorCollection);
|
|
|
|
}
|
|
|
|
|
2007-07-21 17:50:26 +00:00
|
|
|
void
|
2007-07-27 00:06:05 +00:00
|
|
|
Runtime_exit(Thread* t, jobject, jint code)
|
2007-07-21 17:50:26 +00:00
|
|
|
{
|
|
|
|
t->vm->system->exit(code);
|
|
|
|
}
|
|
|
|
|
2007-07-27 02:39:53 +00:00
|
|
|
jlong
|
|
|
|
Runtime_freeMemory(Thread*, jobject)
|
|
|
|
{
|
|
|
|
// todo
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-07-14 17:31:01 +00:00
|
|
|
jobject
|
2007-07-27 00:06:05 +00:00
|
|
|
Throwable_trace(Thread* t, jclass, jint skipCount)
|
2007-07-06 15:24:06 +00:00
|
|
|
{
|
|
|
|
int frame = t->frame;
|
|
|
|
while (skipCount-- and frame >= 0) {
|
|
|
|
frame = frameNext(t, frame);
|
|
|
|
}
|
|
|
|
|
2007-08-14 01:44:47 +00:00
|
|
|
// skip Throwable constructors
|
|
|
|
while (frame >= 0
|
|
|
|
and isAssignableFrom
|
|
|
|
(t, arrayBody(t, t->vm->types, Machine::ThrowableType),
|
|
|
|
methodClass(t, frameMethod(t, frame)))
|
|
|
|
and strcmp(reinterpret_cast<const int8_t*>("<init>"),
|
|
|
|
&byteArrayBody(t, methodName(t, frameMethod(t, frame)), 0))
|
|
|
|
== 0)
|
2007-07-06 15:24:06 +00:00
|
|
|
{
|
2007-08-14 01:44:47 +00:00
|
|
|
frame = frameNext(t, frame);
|
2007-07-06 15:24:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return pushReference(t, makeTrace(t, frame));
|
|
|
|
}
|
|
|
|
|
2007-07-14 17:31:01 +00:00
|
|
|
jarray
|
2007-07-27 00:06:05 +00:00
|
|
|
Throwable_resolveTrace(Thread* t, jclass, jobject trace)
|
2007-07-14 17:31:01 +00:00
|
|
|
{
|
2007-07-14 18:37:04 +00:00
|
|
|
unsigned length = arrayLength(t, *trace);
|
|
|
|
object array = makeObjectArray
|
|
|
|
(t, arrayBody(t, t->vm->types, Machine::StackTraceElementType),
|
|
|
|
length, true);
|
|
|
|
PROTECT(t, array);
|
|
|
|
|
|
|
|
object e = 0;
|
|
|
|
PROTECT(t, e);
|
|
|
|
|
|
|
|
object class_ = 0;
|
|
|
|
PROTECT(t, class_);
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < length; ++i) {
|
|
|
|
e = arrayBody(t, *trace, i);
|
|
|
|
|
|
|
|
class_ = className(t, methodClass(t, traceElementMethod(t, e)));
|
|
|
|
class_ = makeString(t, class_, 0, byteArrayLength(t, class_) - 1, 0);
|
|
|
|
|
|
|
|
object method = methodName(t, traceElementMethod(t, e));
|
|
|
|
method = makeString(t, method, 0, byteArrayLength(t, method) - 1, 0);
|
|
|
|
|
|
|
|
unsigned line = lineNumber
|
|
|
|
(t, traceElementMethod(t, e), traceElementIp(t, e));
|
|
|
|
|
|
|
|
object ste = makeStackTraceElement(t, class_, method, 0, line);
|
|
|
|
set(t, objectArrayBody(t, array, i), ste);
|
|
|
|
}
|
|
|
|
|
|
|
|
return pushReference(t, array);
|
2007-07-14 17:31:01 +00:00
|
|
|
}
|
|
|
|
|
2007-07-27 00:06:05 +00:00
|
|
|
jobject
|
|
|
|
Thread_currentThread(Thread* t, jclass)
|
|
|
|
{
|
|
|
|
return pushReference(t, t->javaThread);
|
|
|
|
}
|
|
|
|
|
2007-07-30 01:27:42 +00:00
|
|
|
jlong
|
2007-07-28 21:28:25 +00:00
|
|
|
Thread_doStart(Thread* t, jobject this_)
|
2007-07-07 18:09:16 +00:00
|
|
|
{
|
2007-07-28 21:28:25 +00:00
|
|
|
Thread* p = new (t->vm->system->allocate(sizeof(Thread)))
|
|
|
|
Thread(t->vm, *this_, t);
|
2007-07-07 18:09:16 +00:00
|
|
|
|
2007-07-28 21:28:25 +00:00
|
|
|
enter(p, Thread::ActiveState);
|
2007-07-07 18:09:16 +00:00
|
|
|
|
2007-07-30 01:27:42 +00:00
|
|
|
if (t->vm->system->success(t->vm->system->start(&(p->runnable)))) {
|
|
|
|
return reinterpret_cast<jlong>(p);
|
|
|
|
} else {
|
2007-07-28 21:28:25 +00:00
|
|
|
p->exit();
|
2007-07-30 01:27:42 +00:00
|
|
|
return 0;
|
2007-07-07 18:09:16 +00:00
|
|
|
}
|
|
|
|
}
|
2007-07-16 23:58:37 +00:00
|
|
|
|
2007-07-28 21:28:25 +00:00
|
|
|
void
|
|
|
|
Thread_interrupt(Thread* t, jclass, jlong peer)
|
|
|
|
{
|
|
|
|
interrupt(t, reinterpret_cast<Thread*>(peer));
|
|
|
|
}
|
|
|
|
|
2007-08-10 23:45:47 +00:00
|
|
|
jlong
|
|
|
|
ResourceInputStream_open(Thread* t, jclass, jstring path)
|
|
|
|
{
|
|
|
|
if (LIKELY(path)) {
|
|
|
|
char p[stringLength(t, *path) + 1];
|
|
|
|
stringChars(t, *path, p);
|
|
|
|
|
|
|
|
return reinterpret_cast<jlong>(t->vm->finder->find(p));
|
|
|
|
} else {
|
|
|
|
t->exception = makeNullPointerException(t);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
jint
|
|
|
|
ResourceInputStream_read(Thread*, jclass, jlong peer, jint position)
|
|
|
|
{
|
|
|
|
Finder::Data* d = reinterpret_cast<Finder::Data*>(peer);
|
|
|
|
if (position >= static_cast<jint>(d->length())) {
|
|
|
|
return -1;
|
|
|
|
} else {
|
|
|
|
return d->start()[position];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
jint
|
|
|
|
ResourceInputStream_read2(Thread* t, jclass, jlong peer, jint position,
|
|
|
|
jbyteArray b, jint offset, jint length)
|
|
|
|
{
|
|
|
|
Finder::Data* d = reinterpret_cast<Finder::Data*>(peer);
|
|
|
|
if (length > static_cast<jint>(d->length()) - position) {
|
|
|
|
length = static_cast<jint>(d->length()) - position;
|
|
|
|
}
|
|
|
|
if (length < 0) {
|
|
|
|
return -1;
|
|
|
|
} else {
|
|
|
|
memcpy(&byteArrayBody(t, *b, offset), d->start() + position, length);
|
|
|
|
return length;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ResourceInputStream_close(Thread*, jclass, jlong peer)
|
|
|
|
{
|
|
|
|
reinterpret_cast<Finder::Data*>(peer)->dispose();
|
|
|
|
}
|
|
|
|
|
2007-07-27 00:06:05 +00:00
|
|
|
} // namespace
|
|
|
|
|
|
|
|
namespace vm {
|
|
|
|
|
2007-07-06 15:24:06 +00:00
|
|
|
void
|
2007-07-27 00:06:05 +00:00
|
|
|
populateBuiltinMap(Thread* t, object map)
|
2007-07-06 15:24:06 +00:00
|
|
|
{
|
|
|
|
struct {
|
|
|
|
const char* key;
|
|
|
|
void* value;
|
|
|
|
} builtins[] = {
|
2007-07-24 03:16:59 +00:00
|
|
|
{ "Java_java_lang_Class_isAssignableFrom",
|
2007-07-27 00:06:05 +00:00
|
|
|
reinterpret_cast<void*>(::Class_isAssignableFrom) },
|
2007-07-29 23:32:23 +00:00
|
|
|
{ "Java_java_lang_Class_primitiveClass",
|
|
|
|
reinterpret_cast<void*>(::Class_primitiveClass) },
|
2007-08-01 23:48:36 +00:00
|
|
|
{ "Java_java_lang_Class_initialize",
|
|
|
|
reinterpret_cast<void*>(::Class_initialize) },
|
2007-07-24 01:44:20 +00:00
|
|
|
|
2007-07-30 23:19:05 +00:00
|
|
|
{ "Java_java_lang_ClassLoader_defineClass",
|
|
|
|
reinterpret_cast<void*>(::ClassLoader_defineClass) },
|
|
|
|
|
2007-07-16 23:58:37 +00:00
|
|
|
{ "Java_java_lang_System_arraycopy",
|
2007-07-27 00:06:05 +00:00
|
|
|
reinterpret_cast<void*>(::System_arraycopy) },
|
2007-07-21 17:50:26 +00:00
|
|
|
|
2007-07-30 23:19:05 +00:00
|
|
|
{ "Java_java_lang_SystemClassLoader_findClass",
|
|
|
|
reinterpret_cast<void*>(::SystemClassLoader_findClass) },
|
|
|
|
{ "Java_java_lang_SystemClassLoader_findLoadedClass",
|
|
|
|
reinterpret_cast<void*>(::SystemClassLoader_findLoadedClass) },
|
2007-08-10 23:45:47 +00:00
|
|
|
{ "Java_java_lang_SystemClassLoader_resourceExists",
|
|
|
|
reinterpret_cast<void*>(::SystemClassLoader_resourceExists) },
|
2007-07-30 23:19:05 +00:00
|
|
|
|
2007-07-21 17:50:26 +00:00
|
|
|
{ "Java_java_lang_Runtime_loadLibrary",
|
2007-07-27 00:06:05 +00:00
|
|
|
reinterpret_cast<void*>(::Runtime_loadLibrary) },
|
2007-07-21 17:50:26 +00:00
|
|
|
{ "Java_java_lang_Runtime_gc",
|
2007-07-27 00:06:05 +00:00
|
|
|
reinterpret_cast<void*>(::Runtime_gc) },
|
2007-07-21 17:50:26 +00:00
|
|
|
{ "Java_java_lang_Runtiime_exit",
|
2007-07-27 00:06:05 +00:00
|
|
|
reinterpret_cast<void*>(::Runtime_exit) },
|
2007-07-16 23:58:37 +00:00
|
|
|
|
2007-07-29 00:02:32 +00:00
|
|
|
{ "Java_java_lang_String_intern",
|
|
|
|
reinterpret_cast<void*>(::String_intern) },
|
|
|
|
|
2007-07-21 22:36:51 +00:00
|
|
|
{ "Java_java_lang_Thread_doStart",
|
2007-07-28 21:28:25 +00:00
|
|
|
reinterpret_cast<void*>(::Thread_doStart) },
|
|
|
|
{ "Java_java_lang_Thread_interrupt",
|
|
|
|
reinterpret_cast<void*>(::Thread_interrupt) },
|
2007-07-21 20:44:39 +00:00
|
|
|
{ "Java_java_lang_Thread_currentThread",
|
2007-07-27 00:06:05 +00:00
|
|
|
reinterpret_cast<void*>(::Thread_currentThread) },
|
2007-07-16 23:58:37 +00:00
|
|
|
|
|
|
|
{ "Java_java_lang_Throwable_resolveTrace",
|
2007-07-27 00:06:05 +00:00
|
|
|
reinterpret_cast<void*>(::Throwable_resolveTrace) },
|
2007-07-16 23:58:37 +00:00
|
|
|
{ "Java_java_lang_Throwable_trace",
|
2007-07-27 00:06:05 +00:00
|
|
|
reinterpret_cast<void*>(::Throwable_trace) },
|
2007-07-16 23:58:37 +00:00
|
|
|
|
2007-07-12 23:46:08 +00:00
|
|
|
{ "Java_java_lang_Object_getClass",
|
2007-07-27 00:06:05 +00:00
|
|
|
reinterpret_cast<void*>(::Object_getClass) },
|
2007-07-07 23:47:35 +00:00
|
|
|
{ "Java_java_lang_Object_notify",
|
2007-07-27 00:06:05 +00:00
|
|
|
reinterpret_cast<void*>(::Object_notify) },
|
2007-07-07 23:47:35 +00:00
|
|
|
{ "Java_java_lang_Object_notifyAll",
|
2007-07-27 00:06:05 +00:00
|
|
|
reinterpret_cast<void*>(::Object_notifyAll) },
|
2007-07-16 23:58:37 +00:00
|
|
|
{ "Java_java_lang_Object_toString",
|
2007-07-27 00:06:05 +00:00
|
|
|
reinterpret_cast<void*>(::Object_toString) },
|
2007-07-16 23:58:37 +00:00
|
|
|
{ "Java_java_lang_Object_wait",
|
2007-07-27 00:06:05 +00:00
|
|
|
reinterpret_cast<void*>(::Object_wait) },
|
2007-08-13 00:50:25 +00:00
|
|
|
{ "Java_java_lang_Object_hashCode",
|
|
|
|
reinterpret_cast<void*>(::Object_hashCode) },
|
2007-07-16 23:58:37 +00:00
|
|
|
|
2007-07-27 02:39:53 +00:00
|
|
|
{ "Java_java_lang_reflect_Array_get",
|
|
|
|
reinterpret_cast<void*>(::Array_get) },
|
2007-07-27 23:56:19 +00:00
|
|
|
{ "Java_java_lang_reflect_Array_set",
|
|
|
|
reinterpret_cast<void*>(::Array_set) },
|
2007-07-27 02:39:53 +00:00
|
|
|
{ "Java_java_lang_reflect_Array_getLength",
|
|
|
|
reinterpret_cast<void*>(::Array_getLength) },
|
|
|
|
{ "Java_java_lang_reflect_Array_makeObjectArray",
|
|
|
|
reinterpret_cast<void*>(::Array_makeObjectArray) },
|
|
|
|
|
|
|
|
{ "Java_java_lang_reflect_Constructor_make",
|
|
|
|
reinterpret_cast<void*>(::Constructor_make) },
|
|
|
|
|
2007-07-24 03:16:59 +00:00
|
|
|
{ "Java_java_lang_reflect_Field_get",
|
2007-07-27 00:06:05 +00:00
|
|
|
reinterpret_cast<void*>(::Field_get) },
|
2007-07-27 23:56:19 +00:00
|
|
|
{ "Java_java_lang_reflect_Field_set",
|
|
|
|
reinterpret_cast<void*>(::Field_set) },
|
2007-07-24 03:16:59 +00:00
|
|
|
|
2007-07-30 23:19:05 +00:00
|
|
|
{ "Java_java_lang_reflect_Method_getCaller",
|
|
|
|
reinterpret_cast<void*>(::Method_getCaller) },
|
2007-07-24 03:16:59 +00:00
|
|
|
{ "Java_java_lang_reflect_Method_invoke",
|
2007-07-27 00:06:05 +00:00
|
|
|
reinterpret_cast<void*>(::Method_invoke) },
|
2007-07-24 03:16:59 +00:00
|
|
|
|
2007-08-10 23:45:47 +00:00
|
|
|
{ "Java_java_net_URL_00024ResourceInputStream_open",
|
|
|
|
reinterpret_cast<void*>(::ResourceInputStream_open) },
|
|
|
|
{ "Java_java_net_URL_00024ResourceInputStream_read_JI",
|
|
|
|
reinterpret_cast<void*>(::ResourceInputStream_read) },
|
|
|
|
{ "Java_java_net_URL_00024ResourceInputStream_read_JI_3BII",
|
|
|
|
reinterpret_cast<void*>(::ResourceInputStream_read2) },
|
|
|
|
{ "Java_java_net_URL_00024ResourceInputStream_close",
|
|
|
|
reinterpret_cast<void*>(::ResourceInputStream_close) },
|
|
|
|
|
2007-08-13 00:50:25 +00:00
|
|
|
{ "Java_java_io_ObjectInputStream_makeInstance",
|
|
|
|
reinterpret_cast<void*>(::ObjectInputStream_makeInstance) },
|
|
|
|
|
2007-07-06 15:24:06 +00:00
|
|
|
{ 0, 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
for (unsigned i = 0; builtins[i].key; ++i) {
|
|
|
|
object key = makeByteArray(t, builtins[i].key);
|
|
|
|
PROTECT(t, key);
|
|
|
|
object value = makePointer(t, builtins[i].value);
|
|
|
|
|
|
|
|
hashMapInsert(t, map, key, value, byteArrayHash);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace vm
|