2007-06-03 02:00:23 +00:00
|
|
|
#include "common.h"
|
|
|
|
#include "system.h"
|
|
|
|
#include "heap.h"
|
2007-06-25 02:02:24 +00:00
|
|
|
#include "class-finder.h"
|
2007-06-18 19:23:44 +00:00
|
|
|
#include "constants.h"
|
2007-07-06 23:50:26 +00:00
|
|
|
#include "run.h"
|
|
|
|
#include "jnienv.h"
|
|
|
|
#include "builtin.h"
|
|
|
|
#include "machine.h"
|
2007-07-02 01:42:35 +00:00
|
|
|
|
2007-06-18 19:23:44 +00:00
|
|
|
using namespace vm;
|
|
|
|
|
2007-05-21 15:47:44 +00:00
|
|
|
namespace {
|
|
|
|
|
2007-07-06 15:24:06 +00:00
|
|
|
void
|
|
|
|
pushFrame(Thread* t, object method)
|
2007-07-04 02:56:02 +00:00
|
|
|
{
|
2007-07-06 15:24:06 +00:00
|
|
|
if (t->frame >= 0) {
|
|
|
|
pokeInt(t, t->frame + FrameIpOffset, t->ip);
|
2007-07-04 17:58:27 +00:00
|
|
|
}
|
2007-07-06 15:24:06 +00:00
|
|
|
t->ip = 0;
|
2007-07-04 17:58:27 +00:00
|
|
|
|
2007-07-06 15:24:06 +00:00
|
|
|
unsigned parameterFootprint = methodParameterFootprint(t, method);
|
|
|
|
unsigned base = t->sp - parameterFootprint;
|
|
|
|
unsigned locals = parameterFootprint;
|
2007-07-06 01:06:06 +00:00
|
|
|
|
|
|
|
if ((methodFlags(t, method) & ACC_NATIVE) == 0) {
|
|
|
|
t->code = methodCode(t, method);
|
|
|
|
|
|
|
|
locals = codeMaxLocals(t, t->code);
|
|
|
|
|
|
|
|
memset(t->stack + ((base + parameterFootprint) * 2), 0,
|
|
|
|
(locals - parameterFootprint) * BytesPerWord * 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned frame = base + locals;
|
|
|
|
pokeInt(t, frame + FrameNextOffset, t->frame);
|
|
|
|
t->frame = frame;
|
|
|
|
|
|
|
|
t->sp = frame + FrameFootprint;
|
|
|
|
|
|
|
|
pokeInt(t, frame + FrameBaseOffset, base);
|
|
|
|
pokeObject(t, frame + FrameMethodOffset, method);
|
2007-07-07 23:47:35 +00:00
|
|
|
pokeInt(t, t->frame + FrameIpOffset, 0);
|
|
|
|
|
|
|
|
if (methodFlags(t, method) & ACC_SYNCHRONIZED) {
|
|
|
|
if (methodFlags(t, method) & ACC_STATIC) {
|
|
|
|
acquire(t, methodClass(t, method));
|
|
|
|
} else {
|
|
|
|
acquire(t, peekObject(t, base));
|
|
|
|
}
|
|
|
|
}
|
2007-07-06 01:06:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
popFrame(Thread* t)
|
|
|
|
{
|
2007-07-07 23:47:35 +00:00
|
|
|
object method = frameMethod(t, t->frame);
|
|
|
|
|
|
|
|
if (methodFlags(t, method) & ACC_SYNCHRONIZED) {
|
|
|
|
if (methodFlags(t, method) & ACC_STATIC) {
|
|
|
|
release(t, methodClass(t, method));
|
|
|
|
} else {
|
|
|
|
release(t, peekObject(t, frameBase(t, t->frame)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-07-06 01:06:06 +00:00
|
|
|
t->sp = frameBase(t, t->frame);
|
|
|
|
t->frame = frameNext(t, t->frame);
|
|
|
|
if (t->frame >= 0) {
|
|
|
|
t->code = methodCode(t, frameMethod(t, t->frame));
|
|
|
|
t->ip = frameIp(t, t->frame);
|
|
|
|
} else {
|
|
|
|
t->code = 0;
|
|
|
|
t->ip = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-06-07 00:30:16 +00:00
|
|
|
inline object
|
|
|
|
make(Thread* t, object class_)
|
|
|
|
{
|
2007-06-08 14:23:04 +00:00
|
|
|
PROTECT(t, class_);
|
2007-06-25 02:20:35 +00:00
|
|
|
unsigned sizeInBytes = pad(classFixedSize(t, class_));
|
2007-06-22 20:55:11 +00:00
|
|
|
object instance = allocate(t, sizeInBytes);
|
2007-06-07 00:30:16 +00:00
|
|
|
*static_cast<object*>(instance) = class_;
|
2007-07-07 18:09:16 +00:00
|
|
|
memset(static_cast<object*>(instance) + 1, 0,
|
2007-06-22 20:55:11 +00:00
|
|
|
sizeInBytes - sizeof(object));
|
2007-07-07 18:09:16 +00:00
|
|
|
|
2007-06-07 00:30:16 +00:00
|
|
|
return instance;
|
|
|
|
}
|
|
|
|
|
2007-06-11 23:40:24 +00:00
|
|
|
inline void
|
|
|
|
setStatic(Thread* t, object field, object value)
|
|
|
|
{
|
2007-06-18 21:13:21 +00:00
|
|
|
set(t, arrayBody(t, classStaticTable(t, fieldClass(t, field)),
|
|
|
|
fieldOffset(t, field)), value);
|
2007-06-11 23:40:24 +00:00
|
|
|
}
|
|
|
|
|
2007-06-09 02:29:56 +00:00
|
|
|
bool
|
|
|
|
instanceOf(Thread* t, object class_, object o)
|
|
|
|
{
|
|
|
|
if (o == 0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2007-07-05 02:25:25 +00:00
|
|
|
if (classFlags(t, class_) & ACC_INTERFACE) {
|
2007-07-01 21:34:22 +00:00
|
|
|
for (object oc = objectClass(t, o); oc; oc = classSuper(t, oc)) {
|
2007-06-09 02:29:56 +00:00
|
|
|
object itable = classInterfaceTable(t, oc);
|
2007-06-17 22:03:27 +00:00
|
|
|
for (unsigned i = 0; i < arrayLength(t, itable); i += 2) {
|
2007-06-18 21:13:21 +00:00
|
|
|
if (arrayBody(t, itable, i) == class_) {
|
2007-06-09 02:29:56 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2007-07-01 21:34:22 +00:00
|
|
|
for (object oc = objectClass(t, o); oc; oc = classSuper(t, oc)) {
|
2007-06-17 22:03:27 +00:00
|
|
|
if (oc == class_) {
|
2007-06-09 02:29:56 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2007-06-11 23:40:24 +00:00
|
|
|
object
|
|
|
|
findInterfaceMethod(Thread* t, object method, object o)
|
|
|
|
{
|
2007-06-17 22:03:27 +00:00
|
|
|
object interface = methodClass(t, method);
|
2007-07-01 21:34:22 +00:00
|
|
|
object itable = classInterfaceTable(t, objectClass(t, o));
|
2007-06-17 22:03:27 +00:00
|
|
|
for (unsigned i = 0; i < arrayLength(t, itable); i += 2) {
|
2007-06-18 21:13:21 +00:00
|
|
|
if (arrayBody(t, itable, i) == interface) {
|
|
|
|
return arrayBody(t, arrayBody(t, itable, i + 1),
|
|
|
|
methodOffset(t, method));
|
2007-06-11 23:40:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
abort(t);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline object
|
2007-06-13 14:03:08 +00:00
|
|
|
findMethod(Thread* t, object method, object class_)
|
2007-06-11 23:40:24 +00:00
|
|
|
{
|
2007-06-18 21:13:21 +00:00
|
|
|
return arrayBody(t, classVirtualTable(t, class_),
|
|
|
|
methodOffset(t, method));
|
2007-06-11 23:40:24 +00:00
|
|
|
}
|
|
|
|
|
2007-06-13 14:03:08 +00:00
|
|
|
bool
|
|
|
|
isSuperclass(Thread* t, object class_, object base)
|
|
|
|
{
|
|
|
|
for (object oc = classSuper(t, base); oc; oc = classSuper(t, oc)) {
|
2007-06-17 22:03:27 +00:00
|
|
|
if (oc == class_) {
|
2007-06-13 14:03:08 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool
|
|
|
|
isSpecialMethod(Thread* t, object method, object class_)
|
|
|
|
{
|
|
|
|
return (classFlags(t, class_) & ACC_SUPER)
|
2007-06-14 02:41:59 +00:00
|
|
|
and strcmp(reinterpret_cast<const int8_t*>("<init>"),
|
2007-06-18 21:13:21 +00:00
|
|
|
&byteArrayBody(t, methodName(t, method), 0)) != 0
|
2007-06-13 14:03:08 +00:00
|
|
|
and isSuperclass(t, methodClass(t, method), class_);
|
|
|
|
}
|
|
|
|
|
2007-06-14 02:12:28 +00:00
|
|
|
object
|
2007-07-12 00:06:57 +00:00
|
|
|
find(Thread* t, object table, object reference,
|
2007-06-14 02:41:59 +00:00
|
|
|
object& (*name)(Thread*, object),
|
2007-07-12 00:06:57 +00:00
|
|
|
object& (*spec)(Thread*, object))
|
2007-06-14 02:41:59 +00:00
|
|
|
{
|
|
|
|
object n = referenceName(t, reference);
|
|
|
|
object s = referenceSpec(t, reference);
|
2007-06-17 22:03:27 +00:00
|
|
|
for (unsigned i = 0; i < arrayLength(t, table); ++i) {
|
2007-06-21 01:38:02 +00:00
|
|
|
object o = arrayBody(t, table, i);
|
|
|
|
|
|
|
|
if (strcmp(&byteArrayBody(t, name(t, o), 0),
|
2007-06-18 21:13:21 +00:00
|
|
|
&byteArrayBody(t, n, 0)) == 0 and
|
2007-06-21 01:38:02 +00:00
|
|
|
strcmp(&byteArrayBody(t, spec(t, o), 0),
|
2007-06-18 21:13:21 +00:00
|
|
|
&byteArrayBody(t, s, 0)) == 0)
|
2007-06-14 02:12:28 +00:00
|
|
|
{
|
2007-06-21 01:38:02 +00:00
|
|
|
return o;
|
2007-06-14 02:12:28 +00:00
|
|
|
}
|
|
|
|
}
|
2007-06-14 02:41:59 +00:00
|
|
|
|
2007-06-14 02:12:28 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-06-14 02:41:59 +00:00
|
|
|
inline object
|
|
|
|
findFieldInClass(Thread* t, object class_, object reference)
|
|
|
|
{
|
2007-07-12 00:06:57 +00:00
|
|
|
return find(t, classFieldTable(t, class_), reference, fieldName, fieldSpec);
|
2007-06-14 02:41:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
inline object
|
|
|
|
findMethodInClass(Thread* t, object class_, object reference)
|
|
|
|
{
|
2007-07-12 00:06:57 +00:00
|
|
|
return find(t, classMethodTable(t, class_), reference, methodName,
|
|
|
|
methodSpec);
|
2007-06-14 23:55:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
inline object
|
|
|
|
resolveClass(Thread* t, object pool, unsigned index)
|
|
|
|
{
|
2007-06-18 21:13:21 +00:00
|
|
|
object o = arrayBody(t, pool, index);
|
2007-07-01 21:34:22 +00:00
|
|
|
if (objectClass(t, o) == arrayBody(t, t->vm->types, Machine::ByteArrayType))
|
|
|
|
{
|
2007-06-14 23:55:06 +00:00
|
|
|
PROTECT(t, pool);
|
|
|
|
|
|
|
|
o = resolveClass(t, o);
|
|
|
|
if (UNLIKELY(t->exception)) return 0;
|
|
|
|
|
2007-06-18 21:13:21 +00:00
|
|
|
set(t, arrayBody(t, pool, index), o);
|
2007-06-14 23:55:06 +00:00
|
|
|
}
|
|
|
|
return o;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline object
|
|
|
|
resolveClass(Thread* t, object container, object& (*class_)(Thread*, object))
|
|
|
|
{
|
|
|
|
object o = class_(t, container);
|
2007-07-01 21:34:22 +00:00
|
|
|
if (objectClass(t, o) == arrayBody(t, t->vm->types, Machine::ByteArrayType))
|
|
|
|
{
|
2007-06-14 23:55:06 +00:00
|
|
|
PROTECT(t, container);
|
|
|
|
|
|
|
|
o = resolveClass(t, o);
|
|
|
|
if (UNLIKELY(t->exception)) return 0;
|
|
|
|
|
|
|
|
set(t, class_(t, container), o);
|
|
|
|
}
|
|
|
|
return o;
|
2007-06-14 02:12:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
inline object
|
|
|
|
resolve(Thread* t, object pool, unsigned index,
|
2007-07-12 00:06:57 +00:00
|
|
|
object (*find)(Thread*, object, object),
|
|
|
|
object (*makeError)(Thread*, object))
|
2007-06-14 02:12:28 +00:00
|
|
|
{
|
2007-06-18 21:13:21 +00:00
|
|
|
object o = arrayBody(t, pool, index);
|
2007-07-01 21:34:22 +00:00
|
|
|
if (objectClass(t, o) == arrayBody(t, t->vm->types, Machine::ReferenceType))
|
|
|
|
{
|
2007-06-14 02:41:59 +00:00
|
|
|
PROTECT(t, pool);
|
2007-06-14 02:12:28 +00:00
|
|
|
|
2007-07-12 00:06:57 +00:00
|
|
|
object reference = o;
|
|
|
|
PROTECT(t, reference);
|
|
|
|
|
2007-06-14 23:55:06 +00:00
|
|
|
object class_ = resolveClass(t, o, referenceClass);
|
2007-06-14 02:12:28 +00:00
|
|
|
if (UNLIKELY(t->exception)) return 0;
|
2007-07-12 00:06:57 +00:00
|
|
|
|
|
|
|
for (o = 0; o == 0 and class_; class_ = classSuper(t, class_)) {
|
|
|
|
o = find(t, class_, arrayBody(t, pool, index));
|
|
|
|
}
|
2007-06-14 02:12:28 +00:00
|
|
|
|
2007-07-12 00:06:57 +00:00
|
|
|
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, referenceClass(t, reference), 0));
|
|
|
|
t->exception = makeError(t, message);
|
|
|
|
}
|
2007-06-14 02:12:28 +00:00
|
|
|
|
2007-06-18 21:13:21 +00:00
|
|
|
set(t, arrayBody(t, pool, index), o);
|
2007-06-14 02:12:28 +00:00
|
|
|
}
|
2007-07-12 00:06:57 +00:00
|
|
|
|
2007-06-14 02:41:59 +00:00
|
|
|
return o;
|
2007-06-14 02:12:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
inline object
|
|
|
|
resolveField(Thread* t, object pool, unsigned index)
|
|
|
|
{
|
2007-07-12 00:06:57 +00:00
|
|
|
return resolve(t, pool, index, findFieldInClass, makeNoSuchFieldError);
|
2007-06-14 02:12:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
inline object
|
|
|
|
resolveMethod(Thread* t, object pool, unsigned index)
|
|
|
|
{
|
2007-07-12 00:06:57 +00:00
|
|
|
return resolve(t, pool, index, findMethodInClass, makeNoSuchMethodError);
|
2007-06-14 02:12:28 +00:00
|
|
|
}
|
|
|
|
|
2007-06-24 21:49:04 +00:00
|
|
|
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,
|
2007-06-29 02:58:48 +00:00
|
|
|
methodParameterCount(t, method) + 1,
|
2007-06-24 21:49:04 +00:00
|
|
|
false);
|
|
|
|
|
2007-06-29 02:58:48 +00:00
|
|
|
unsigned argumentTableSize = BytesPerWord;
|
2007-06-24 21:49:04 +00:00
|
|
|
unsigned index = 0;
|
|
|
|
|
2007-06-29 02:58:48 +00:00
|
|
|
nativeMethodDataParameterTypes(t, data, index++) = POINTER_TYPE;
|
|
|
|
|
2007-06-24 21:49:04 +00:00
|
|
|
if ((methodFlags(t, method) & ACC_STATIC) == 0) {
|
2007-06-29 02:58:48 +00:00
|
|
|
nativeMethodDataParameterTypes(t, data, index++) = POINTER_TYPE;
|
|
|
|
argumentTableSize += BytesPerWord;
|
2007-06-24 21:49:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const char* s = reinterpret_cast<const char*>
|
|
|
|
(&byteArrayBody(t, methodSpec(t, method), 0));
|
|
|
|
++ s; // skip '('
|
|
|
|
while (*s and *s != ')') {
|
|
|
|
unsigned code = fieldCode(t, *s);
|
2007-06-29 02:58:48 +00:00
|
|
|
nativeMethodDataParameterTypes(t, data, index++) = fieldType(t, code);
|
2007-06-24 21:49:04 +00:00
|
|
|
|
|
|
|
switch (*s) {
|
|
|
|
case 'L':
|
2007-06-29 02:58:48 +00:00
|
|
|
argumentTableSize += BytesPerWord;
|
2007-06-24 21:49:04 +00:00
|
|
|
while (*s and *s != ';') ++ s;
|
|
|
|
++ s;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '[':
|
2007-06-29 02:58:48 +00:00
|
|
|
argumentTableSize += BytesPerWord;
|
2007-06-24 21:49:04 +00:00
|
|
|
while (*s == '[') ++ s;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2007-06-29 02:58:48 +00:00
|
|
|
argumentTableSize += pad(primitiveSize(t, code));
|
2007-06-24 21:49:04 +00:00
|
|
|
++ s;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
nativeMethodDataArgumentTableSize(t, data) = argumentTableSize;
|
|
|
|
nativeMethodDataReturnCode(t, data) = fieldCode(t, s[1]);
|
|
|
|
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
2007-06-24 01:39:49 +00:00
|
|
|
inline object
|
|
|
|
resolveNativeMethodData(Thread* t, object method)
|
|
|
|
{
|
2007-07-01 21:34:22 +00:00
|
|
|
if (objectClass(t, methodCode(t, method))
|
2007-06-24 01:39:49 +00:00
|
|
|
== arrayBody(t, t->vm->types, Machine::ByteArrayType))
|
|
|
|
{
|
2007-06-24 21:49:04 +00:00
|
|
|
object data = 0;
|
2007-06-24 19:57:00 +00:00
|
|
|
for (System::Library* lib = t->vm->libraries; lib; lib = lib->next()) {
|
2007-06-24 01:39:49 +00:00
|
|
|
void* p = lib->resolve(reinterpret_cast<const char*>
|
|
|
|
(&byteArrayBody(t, methodCode(t, method), 0)));
|
|
|
|
if (p) {
|
|
|
|
PROTECT(t, method);
|
2007-06-24 21:49:04 +00:00
|
|
|
data = makeNativeMethodData(t, method, p, false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2007-06-24 01:39:49 +00:00
|
|
|
|
2007-06-24 21:49:04 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2007-06-24 01:39:49 +00:00
|
|
|
|
2007-06-25 02:20:35 +00:00
|
|
|
if (LIKELY(data)) {
|
2007-06-24 21:49:04 +00:00
|
|
|
set(t, methodCode(t, method), data);
|
2007-06-25 02:20:35 +00:00
|
|
|
} else {
|
|
|
|
object message = makeString
|
|
|
|
(t, "%s", &byteArrayBody(t, methodCode(t, method), 0));
|
|
|
|
t->exception = makeUnsatisfiedLinkError(t, message);
|
2007-06-24 21:49:04 +00:00
|
|
|
}
|
2007-06-25 02:20:35 +00:00
|
|
|
|
2007-06-24 21:49:04 +00:00
|
|
|
return data;
|
|
|
|
} else {
|
|
|
|
return methodCode(t, method);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-07-04 17:58:27 +00:00
|
|
|
inline void
|
2007-07-07 18:09:16 +00:00
|
|
|
checkStack(Thread* t, object method)
|
|
|
|
{
|
|
|
|
unsigned parameterFootprint = methodParameterFootprint(t, method);
|
|
|
|
unsigned base = t->sp - parameterFootprint;
|
|
|
|
if (UNLIKELY(base
|
|
|
|
+ codeMaxLocals(t, methodCode(t, method))
|
|
|
|
+ FrameFootprint
|
|
|
|
+ codeMaxStack(t, methodCode(t, method))
|
|
|
|
> Thread::StackSizeInWords / 2))
|
|
|
|
{
|
|
|
|
t->exception = makeStackOverflowError(t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned
|
2007-06-24 21:49:04 +00:00
|
|
|
invokeNative(Thread* t, object method)
|
|
|
|
{
|
|
|
|
object data = resolveNativeMethodData(t, method);
|
2007-06-25 02:20:35 +00:00
|
|
|
if (UNLIKELY(t->exception)) {
|
2007-07-07 18:09:16 +00:00
|
|
|
return VoidField;
|
2007-06-24 21:49:04 +00:00
|
|
|
}
|
|
|
|
|
2007-07-06 01:06:06 +00:00
|
|
|
pushFrame(t, method);
|
|
|
|
|
2007-06-29 02:58:48 +00:00
|
|
|
unsigned count = methodParameterCount(t, method);
|
2007-06-24 01:39:49 +00:00
|
|
|
|
2007-06-29 02:58:48 +00:00
|
|
|
unsigned size = nativeMethodDataArgumentTableSize(t, data);
|
|
|
|
uintptr_t args[size / BytesPerWord];
|
2007-06-24 21:49:04 +00:00
|
|
|
unsigned offset = 0;
|
2007-06-24 01:39:49 +00:00
|
|
|
|
2007-06-29 02:58:48 +00:00
|
|
|
args[offset++] = reinterpret_cast<uintptr_t>(t);
|
2007-06-24 21:49:04 +00:00
|
|
|
|
2007-07-06 01:06:06 +00:00
|
|
|
unsigned sp = frameBase(t, t->frame);
|
2007-06-29 02:58:48 +00:00
|
|
|
for (unsigned i = 0; i < count; ++i) {
|
2007-06-30 01:37:45 +00:00
|
|
|
unsigned type = nativeMethodDataParameterTypes(t, data, i + 1);
|
2007-06-24 21:49:04 +00:00
|
|
|
|
2007-06-29 02:58:48 +00:00
|
|
|
switch (type) {
|
|
|
|
case INT8_TYPE:
|
|
|
|
case INT16_TYPE:
|
|
|
|
case INT32_TYPE:
|
|
|
|
case FLOAT_TYPE:
|
2007-07-04 17:58:27 +00:00
|
|
|
args[offset++] = peekInt(t, sp++);
|
2007-06-29 02:58:48 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case INT64_TYPE:
|
|
|
|
case DOUBLE_TYPE: {
|
2007-07-04 17:58:27 +00:00
|
|
|
uint64_t v = peekLong(t, sp);
|
2007-06-29 02:58:48 +00:00
|
|
|
memcpy(args + offset, &v, 8);
|
|
|
|
offset += (8 / BytesPerWord);
|
2007-07-04 17:58:27 +00:00
|
|
|
sp += 2;
|
2007-06-29 02:58:48 +00:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case POINTER_TYPE:
|
2007-07-04 17:58:27 +00:00
|
|
|
args[offset++] = reinterpret_cast<uintptr_t>
|
|
|
|
(t->stack + ((sp++) * 2) + 1);
|
2007-06-29 02:58:48 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default: abort(t);
|
2007-06-24 01:39:49 +00:00
|
|
|
}
|
2007-06-24 21:49:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
unsigned returnCode = nativeMethodDataReturnCode(t, data);
|
2007-06-29 02:58:48 +00:00
|
|
|
unsigned returnType = fieldType(t, returnCode);
|
2007-06-24 21:49:04 +00:00
|
|
|
void* function = nativeMethodDataFunction(t, data);
|
|
|
|
|
|
|
|
bool builtin = nativeMethodDataBuiltin(t, data);
|
2007-07-07 18:09:16 +00:00
|
|
|
Thread::State oldState = t->state;
|
|
|
|
if (not builtin) {
|
2007-06-24 21:49:04 +00:00
|
|
|
enter(t, Thread::IdleState);
|
|
|
|
}
|
|
|
|
|
2007-07-07 23:47:35 +00:00
|
|
|
if (DebugRun) {
|
|
|
|
fprintf(stderr, "invoke native method %s.%s\n",
|
|
|
|
&byteArrayBody(t, className(t, methodClass(t, method)), 0),
|
|
|
|
&byteArrayBody(t, methodName(t, method), 0));
|
|
|
|
}
|
|
|
|
|
2007-07-04 17:58:27 +00:00
|
|
|
uint64_t result = t->vm->system->call
|
2007-06-29 02:58:48 +00:00
|
|
|
(function,
|
|
|
|
args,
|
|
|
|
&nativeMethodDataParameterTypes(t, data, 0),
|
|
|
|
count + 1,
|
|
|
|
size,
|
|
|
|
returnType);
|
2007-06-24 21:49:04 +00:00
|
|
|
|
2007-07-07 23:47:35 +00:00
|
|
|
if (DebugRun) {
|
|
|
|
fprintf(stderr, "return from native method %s.%s\n",
|
|
|
|
&byteArrayBody
|
|
|
|
(t, className(t, methodClass(t, frameMethod(t, t->frame))), 0),
|
|
|
|
&byteArrayBody
|
|
|
|
(t, methodName(t, frameMethod(t, t->frame)), 0));
|
|
|
|
}
|
|
|
|
|
2007-06-24 21:49:04 +00:00
|
|
|
if (not builtin) {
|
2007-07-07 18:09:16 +00:00
|
|
|
enter(t, oldState);
|
2007-06-24 21:49:04 +00:00
|
|
|
}
|
2007-06-24 01:39:49 +00:00
|
|
|
|
2007-07-06 01:06:06 +00:00
|
|
|
popFrame(t);
|
|
|
|
|
2007-07-04 17:58:27 +00:00
|
|
|
if (UNLIKELY(t->exception)) {
|
2007-07-07 18:09:16 +00:00
|
|
|
return VoidField;
|
2007-07-04 17:58:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (returnCode) {
|
|
|
|
case ByteField:
|
|
|
|
case BooleanField:
|
|
|
|
case CharField:
|
|
|
|
case ShortField:
|
|
|
|
case FloatField:
|
|
|
|
case IntField:
|
2007-07-07 23:47:35 +00:00
|
|
|
if (DebugRun) {
|
|
|
|
fprintf(stderr, "result: " LLD "\n", result);
|
|
|
|
}
|
2007-07-04 17:58:27 +00:00
|
|
|
pushInt(t, result);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LongField:
|
|
|
|
case DoubleField:
|
2007-07-07 23:47:35 +00:00
|
|
|
if (DebugRun) {
|
|
|
|
fprintf(stderr, "result: " LLD "\n", result);
|
|
|
|
}
|
2007-07-04 17:58:27 +00:00
|
|
|
pushLong(t, result);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ObjectField:
|
2007-07-07 23:47:35 +00:00
|
|
|
if (DebugRun) {
|
|
|
|
fprintf(stderr, "result: %p at %p\n", result == 0 ? 0 :
|
|
|
|
*reinterpret_cast<object*>(static_cast<uintptr_t>(result)),
|
|
|
|
reinterpret_cast<object*>(static_cast<uintptr_t>(result)));
|
|
|
|
}
|
2007-07-04 17:58:27 +00:00
|
|
|
pushObject(t, result == 0 ? 0 :
|
|
|
|
*reinterpret_cast<object*>(static_cast<uintptr_t>(result)));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VoidField:
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
abort(t);
|
|
|
|
};
|
2007-07-07 18:09:16 +00:00
|
|
|
|
|
|
|
return returnCode;
|
2007-07-04 02:56:02 +00:00
|
|
|
}
|
|
|
|
|
2007-05-21 15:47:44 +00:00
|
|
|
object
|
|
|
|
run(Thread* t)
|
|
|
|
{
|
2007-07-04 02:56:02 +00:00
|
|
|
unsigned instruction = nop;
|
2007-06-08 14:23:04 +00:00
|
|
|
unsigned& ip = t->ip;
|
|
|
|
unsigned& sp = t->sp;
|
2007-07-06 01:06:06 +00:00
|
|
|
int& frame = t->frame;
|
2007-06-08 14:23:04 +00:00
|
|
|
object& code = t->code;
|
|
|
|
object& exception = t->exception;
|
2007-07-04 02:56:02 +00:00
|
|
|
uintptr_t* stack = t->stack;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-06-18 21:13:21 +00:00
|
|
|
if (UNLIKELY(exception)) goto throw_;
|
|
|
|
|
2007-05-21 15:47:44 +00:00
|
|
|
loop:
|
2007-07-04 02:56:02 +00:00
|
|
|
instruction = codeBody(t, code, ip++);
|
2007-07-04 17:58:27 +00:00
|
|
|
|
|
|
|
if (DebugRun) {
|
|
|
|
fprintf(stderr, "ip: %d; instruction: 0x%x in %s.%s ",
|
|
|
|
ip - 1,
|
|
|
|
instruction,
|
|
|
|
&byteArrayBody
|
|
|
|
(t, className(t, methodClass(t, frameMethod(t, frame))), 0),
|
|
|
|
&byteArrayBody
|
|
|
|
(t, methodName(t, frameMethod(t, frame)), 0));
|
|
|
|
|
|
|
|
int line = lineNumber(t, frameMethod(t, frame), ip);
|
|
|
|
switch (line) {
|
|
|
|
case NativeLine:
|
|
|
|
fprintf(stderr, "(native)\n");
|
|
|
|
break;
|
|
|
|
case UnknownLine:
|
|
|
|
fprintf(stderr, "(unknown line)\n");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
fprintf(stderr, "(line %d)\n", line);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
switch (instruction) {
|
2007-05-21 15:47:44 +00:00
|
|
|
case aaload: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t index = popInt(t);
|
|
|
|
object array = popObject(t);
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(array)) {
|
2007-07-04 02:56:02 +00:00
|
|
|
if (LIKELY(index >= 0 and
|
2007-07-14 17:31:01 +00:00
|
|
|
static_cast<uintptr_t>(index) < objectArrayLength(t, array)))
|
2007-06-08 00:23:12 +00:00
|
|
|
{
|
2007-07-04 02:56:02 +00:00
|
|
|
pushObject(t, objectArrayBody(t, array, index));
|
2007-05-21 15:47:44 +00:00
|
|
|
} else {
|
2007-07-04 02:56:02 +00:00
|
|
|
object message = makeString(t, "%d not in [0,%d]", index,
|
2007-06-08 00:23:12 +00:00
|
|
|
objectArrayLength(t, array));
|
2007-06-08 14:23:04 +00:00
|
|
|
exception = makeArrayIndexOutOfBoundsException(t, message);
|
2007-05-21 15:47:44 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} else {
|
2007-06-08 14:23:04 +00:00
|
|
|
exception = makeNullPointerException(t);
|
2007-05-21 15:47:44 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
|
|
|
case aastore: {
|
2007-07-04 02:56:02 +00:00
|
|
|
object value = popObject(t);
|
|
|
|
int32_t index = popInt(t);
|
|
|
|
object array = popObject(t);
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(array)) {
|
2007-07-04 02:56:02 +00:00
|
|
|
if (LIKELY(index >= 0 and
|
2007-07-14 17:31:01 +00:00
|
|
|
static_cast<uintptr_t>(index) < objectArrayLength(t, array)))
|
2007-06-08 00:23:12 +00:00
|
|
|
{
|
2007-07-04 02:56:02 +00:00
|
|
|
set(t, objectArrayBody(t, array, index), value);
|
2007-05-21 15:47:44 +00:00
|
|
|
} else {
|
2007-07-04 02:56:02 +00:00
|
|
|
object message = makeString(t, "%d not in [0,%d]", index,
|
2007-06-08 00:23:12 +00:00
|
|
|
objectArrayLength(t, array));
|
2007-06-08 14:23:04 +00:00
|
|
|
exception = makeArrayIndexOutOfBoundsException(t, message);
|
2007-05-21 15:47:44 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} else {
|
2007-06-08 14:23:04 +00:00
|
|
|
exception = makeNullPointerException(t);
|
2007-05-21 15:47:44 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
|
|
|
case aconst_null: {
|
2007-07-04 02:56:02 +00:00
|
|
|
pushObject(t, 0);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
case aload: {
|
2007-07-06 01:06:06 +00:00
|
|
|
pushObject(t, localObject(t, codeBody(t, code, ip++)));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
case aload_0: {
|
2007-07-06 01:06:06 +00:00
|
|
|
pushObject(t, localObject(t, 0));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
case aload_1: {
|
2007-07-06 01:06:06 +00:00
|
|
|
pushObject(t, localObject(t, 1));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
case aload_2: {
|
2007-07-06 01:06:06 +00:00
|
|
|
pushObject(t, localObject(t, 2));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
case aload_3: {
|
2007-07-06 01:06:06 +00:00
|
|
|
pushObject(t, localObject(t, 3));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
|
|
|
case anewarray: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t count = popInt(t);
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
if (LIKELY(count >= 0)) {
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t index1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t index2 = codeBody(t, code, ip++);
|
2007-05-21 15:47:44 +00:00
|
|
|
uint16_t index = (index1 << 8) | index2;
|
|
|
|
|
2007-06-21 01:38:02 +00:00
|
|
|
object class_ = resolveClass(t, codePool(t, code), index - 1);
|
2007-06-08 14:23:04 +00:00
|
|
|
if (UNLIKELY(exception)) goto throw_;
|
2007-07-14 17:31:01 +00:00
|
|
|
|
|
|
|
pushObject(t, makeObjectArray(t, class_, count, true));
|
2007-05-21 15:47:44 +00:00
|
|
|
} else {
|
2007-07-04 02:56:02 +00:00
|
|
|
object message = makeString(t, "%d", count);
|
2007-07-07 23:47:35 +00:00
|
|
|
exception = makeNegativeArraySizeException(t, message);
|
2007-05-21 15:47:44 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-07-07 23:47:35 +00:00
|
|
|
case areturn: {
|
|
|
|
object result = popObject(t);
|
2007-07-06 01:06:06 +00:00
|
|
|
popFrame(t);
|
|
|
|
if (frame >= 0) {
|
2007-07-07 23:47:35 +00:00
|
|
|
pushObject(t, result);
|
2007-05-21 15:47:44 +00:00
|
|
|
goto loop;
|
|
|
|
} else {
|
2007-07-07 23:47:35 +00:00
|
|
|
return result;
|
2007-05-21 15:47:44 +00:00
|
|
|
}
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
|
|
|
case arraylength: {
|
2007-07-04 02:56:02 +00:00
|
|
|
object array = popObject(t);
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(array)) {
|
2007-07-14 17:31:01 +00:00
|
|
|
pushInt(t, cast<uintptr_t>(array, BytesPerWord));
|
2007-05-21 15:47:44 +00:00
|
|
|
} else {
|
2007-06-08 14:23:04 +00:00
|
|
|
exception = makeNullPointerException(t);
|
2007-05-21 15:47:44 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
2007-07-07 23:47:35 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
case astore: {
|
2007-07-06 01:06:06 +00:00
|
|
|
setLocalObject(t, codeBody(t, code, ip++), popObject(t));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
case astore_0: {
|
2007-07-06 01:06:06 +00:00
|
|
|
setLocalObject(t, 0, popObject(t));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
case astore_1: {
|
2007-07-06 01:06:06 +00:00
|
|
|
setLocalObject(t, 1, popObject(t));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
case astore_2: {
|
2007-07-06 01:06:06 +00:00
|
|
|
setLocalObject(t, 2, popObject(t));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
case astore_3: {
|
2007-07-06 01:06:06 +00:00
|
|
|
setLocalObject(t, 3, popObject(t));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
|
|
|
case athrow: {
|
2007-07-04 02:56:02 +00:00
|
|
|
exception = popObject(t);
|
2007-06-08 14:23:04 +00:00
|
|
|
if (UNLIKELY(exception == 0)) {
|
|
|
|
exception = makeNullPointerException(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
2007-07-04 02:56:02 +00:00
|
|
|
} goto throw_;
|
2007-05-22 00:05:29 +00:00
|
|
|
|
|
|
|
case baload: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t index = popInt(t);
|
|
|
|
object array = popObject(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(array)) {
|
2007-07-04 02:56:02 +00:00
|
|
|
if (LIKELY(index >= 0 and
|
2007-07-14 17:31:01 +00:00
|
|
|
static_cast<uintptr_t>(index) < byteArrayLength(t, array)))
|
2007-06-08 00:23:12 +00:00
|
|
|
{
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, byteArrayBody(t, array, index));
|
2007-05-22 00:05:29 +00:00
|
|
|
} else {
|
2007-07-04 02:56:02 +00:00
|
|
|
object message = makeString(t, "%d not in [0,%d]", index,
|
2007-06-08 00:23:12 +00:00
|
|
|
byteArrayLength(t, array));
|
2007-06-08 14:23:04 +00:00
|
|
|
exception = makeArrayIndexOutOfBoundsException(t, message);
|
2007-05-22 00:05:29 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} else {
|
2007-06-08 14:23:04 +00:00
|
|
|
exception = makeNullPointerException(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case bastore: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int8_t value = popInt(t);
|
|
|
|
int32_t index = popInt(t);
|
|
|
|
object array = popObject(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(array)) {
|
2007-07-04 02:56:02 +00:00
|
|
|
if (LIKELY(index >= 0 and
|
2007-07-14 17:31:01 +00:00
|
|
|
static_cast<uintptr_t>(index) < byteArrayLength(t, array)))
|
2007-06-08 00:23:12 +00:00
|
|
|
{
|
2007-07-04 02:56:02 +00:00
|
|
|
byteArrayBody(t, array, index) = value;
|
2007-05-22 00:05:29 +00:00
|
|
|
} else {
|
2007-07-04 02:56:02 +00:00
|
|
|
object message = makeString(t, "%d not in [0,%d]", index,
|
2007-06-08 00:23:12 +00:00
|
|
|
byteArrayLength(t, array));
|
2007-06-08 14:23:04 +00:00
|
|
|
exception = makeArrayIndexOutOfBoundsException(t, message);
|
2007-05-22 00:05:29 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} else {
|
2007-06-08 14:23:04 +00:00
|
|
|
exception = makeNullPointerException(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case bipush: {
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, codeBody(t, code, ip++));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case caload: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t index = popInt(t);
|
|
|
|
object array = popObject(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(array)) {
|
2007-07-04 02:56:02 +00:00
|
|
|
if (LIKELY(index >= 0 and
|
2007-07-14 17:31:01 +00:00
|
|
|
static_cast<uintptr_t>(index) < charArrayLength(t, array)))
|
2007-06-08 00:23:12 +00:00
|
|
|
{
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, charArrayBody(t, array, index));
|
2007-05-22 00:05:29 +00:00
|
|
|
} else {
|
2007-07-04 02:56:02 +00:00
|
|
|
object message = makeString(t, "%d not in [0,%d]", index,
|
2007-06-08 00:23:12 +00:00
|
|
|
charArrayLength(t, array));
|
2007-06-08 14:23:04 +00:00
|
|
|
exception = makeArrayIndexOutOfBoundsException(t, message);
|
2007-05-22 00:05:29 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} else {
|
2007-06-08 14:23:04 +00:00
|
|
|
exception = makeNullPointerException(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case castore: {
|
2007-07-04 02:56:02 +00:00
|
|
|
uint16_t value = popInt(t);
|
|
|
|
int32_t index = popInt(t);
|
|
|
|
object array = popObject(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(array)) {
|
2007-07-04 02:56:02 +00:00
|
|
|
if (LIKELY(index >= 0 and
|
2007-07-14 17:31:01 +00:00
|
|
|
static_cast<uintptr_t>(index) < charArrayLength(t, array)))
|
2007-06-08 00:23:12 +00:00
|
|
|
{
|
2007-07-04 02:56:02 +00:00
|
|
|
charArrayBody(t, array, index) = value;
|
2007-05-22 00:05:29 +00:00
|
|
|
} else {
|
2007-07-04 02:56:02 +00:00
|
|
|
object message = makeString(t, "%d not in [0,%d]", index,
|
2007-06-08 00:23:12 +00:00
|
|
|
charArrayLength(t, array));
|
2007-06-08 14:23:04 +00:00
|
|
|
exception = makeArrayIndexOutOfBoundsException(t, message);
|
2007-05-22 00:05:29 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} else {
|
2007-06-08 14:23:04 +00:00
|
|
|
exception = makeNullPointerException(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case checkcast: {
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t index1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t index2 = codeBody(t, code, ip++);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
if (peekObject(t, sp - 1)) {
|
2007-05-22 00:05:29 +00:00
|
|
|
uint16_t index = (index1 << 8) | index2;
|
|
|
|
|
2007-06-21 01:38:02 +00:00
|
|
|
object class_ = resolveClass(t, codePool(t, code), index - 1);
|
2007-06-08 14:23:04 +00:00
|
|
|
if (UNLIKELY(exception)) goto throw_;
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
if (not instanceOf(t, class_, peekObject(t, sp - 1))) {
|
2007-06-08 00:23:12 +00:00
|
|
|
object message = makeString
|
2007-06-08 14:23:04 +00:00
|
|
|
(t, "%s as %s",
|
2007-07-04 02:56:02 +00:00
|
|
|
&byteArrayBody
|
|
|
|
(t, className(t, objectClass(t, peekObject(t, sp - 1))), 0),
|
2007-06-18 21:13:21 +00:00
|
|
|
&byteArrayBody(t, className(t, class_), 0));
|
2007-06-08 14:23:04 +00:00
|
|
|
exception = makeClassCastException(t, message);
|
2007-05-22 00:05:29 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case dup: {
|
2007-07-04 17:58:27 +00:00
|
|
|
if (DebugStack) {
|
|
|
|
fprintf(stderr, "dup\n");
|
|
|
|
}
|
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
memcpy(stack + ((sp ) * 2), stack + ((sp - 1) * 2), BytesPerWord * 2);
|
|
|
|
++ sp;
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case dup_x1: {
|
2007-07-04 17:58:27 +00:00
|
|
|
if (DebugStack) {
|
|
|
|
fprintf(stderr, "dup_x1\n");
|
|
|
|
}
|
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
memcpy(stack + ((sp ) * 2), stack + ((sp - 1) * 2), BytesPerWord * 2);
|
|
|
|
memcpy(stack + ((sp - 1) * 2), stack + ((sp - 2) * 2), BytesPerWord * 2);
|
|
|
|
memcpy(stack + ((sp - 2) * 2), stack + ((sp ) * 2), BytesPerWord * 2);
|
|
|
|
++ sp;
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case dup_x2: {
|
2007-07-04 17:58:27 +00:00
|
|
|
if (DebugStack) {
|
|
|
|
fprintf(stderr, "dup_x2\n");
|
|
|
|
}
|
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
memcpy(stack + ((sp ) * 2), stack + ((sp - 1) * 2), BytesPerWord * 2);
|
|
|
|
memcpy(stack + ((sp - 1) * 2), stack + ((sp - 2) * 2), BytesPerWord * 2);
|
|
|
|
memcpy(stack + ((sp - 2) * 2), stack + ((sp - 3) * 2), BytesPerWord * 2);
|
|
|
|
memcpy(stack + ((sp - 3) * 2), stack + ((sp ) * 2), BytesPerWord * 2);
|
|
|
|
++ sp;
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case dup2: {
|
2007-07-04 17:58:27 +00:00
|
|
|
if (DebugStack) {
|
|
|
|
fprintf(stderr, "dup2\n");
|
|
|
|
}
|
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
memcpy(stack + ((sp + 1) * 2), stack + ((sp - 2) * 2), BytesPerWord * 4);
|
|
|
|
sp += 2;
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case dup2_x1: {
|
2007-07-04 17:58:27 +00:00
|
|
|
if (DebugStack) {
|
|
|
|
fprintf(stderr, "dup2_x1\n");
|
|
|
|
}
|
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
memcpy(stack + ((sp + 1) * 2), stack + ((sp - 1) * 2), BytesPerWord * 2);
|
|
|
|
memcpy(stack + ((sp ) * 2), stack + ((sp - 2) * 2), BytesPerWord * 2);
|
|
|
|
memcpy(stack + ((sp - 1) * 2), stack + ((sp - 3) * 2), BytesPerWord * 2);
|
|
|
|
memcpy(stack + ((sp - 3) * 2), stack + ((sp ) * 2), BytesPerWord * 4);
|
|
|
|
sp += 2;
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case dup2_x2: {
|
2007-07-04 17:58:27 +00:00
|
|
|
if (DebugStack) {
|
|
|
|
fprintf(stderr, "dup2_x2\n");
|
|
|
|
}
|
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
memcpy(stack + ((sp + 1) * 2), stack + ((sp - 1) * 2), BytesPerWord * 2);
|
|
|
|
memcpy(stack + ((sp ) * 2), stack + ((sp - 2) * 2), BytesPerWord * 2);
|
|
|
|
memcpy(stack + ((sp - 1) * 2), stack + ((sp - 3) * 2), BytesPerWord * 2);
|
|
|
|
memcpy(stack + ((sp - 2) * 2), stack + ((sp - 4) * 2), BytesPerWord * 2);
|
|
|
|
memcpy(stack + ((sp - 4) * 2), stack + ((sp ) * 2), BytesPerWord * 4);
|
|
|
|
sp += 2;
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case getfield: {
|
2007-07-04 02:56:02 +00:00
|
|
|
object instance = popObject(t);
|
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(instance)) {
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t index1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t index2 = codeBody(t, code, ip++);
|
2007-05-22 00:05:29 +00:00
|
|
|
uint16_t index = (index1 << 8) | index2;
|
|
|
|
|
2007-06-21 01:38:02 +00:00
|
|
|
object field = resolveField(t, codePool(t, code), index - 1);
|
2007-06-08 14:23:04 +00:00
|
|
|
if (UNLIKELY(exception)) goto throw_;
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
switch (fieldCode(t, field)) {
|
|
|
|
case ByteField:
|
|
|
|
case BooleanField:
|
|
|
|
pushInt(t, cast<int8_t>(instance, fieldOffset(t, field)));
|
2007-07-07 18:09:16 +00:00
|
|
|
break;
|
2007-07-04 02:56:02 +00:00
|
|
|
|
|
|
|
case CharField:
|
|
|
|
case ShortField:
|
|
|
|
pushInt(t, cast<int16_t>(instance, fieldOffset(t, field)));
|
2007-07-07 18:09:16 +00:00
|
|
|
break;
|
2007-07-04 02:56:02 +00:00
|
|
|
|
|
|
|
case FloatField:
|
|
|
|
case IntField:
|
|
|
|
pushInt(t, cast<int32_t>(instance, fieldOffset(t, field)));
|
2007-07-07 18:09:16 +00:00
|
|
|
break;
|
2007-07-04 02:56:02 +00:00
|
|
|
|
|
|
|
case DoubleField:
|
|
|
|
case LongField:
|
|
|
|
pushLong(t, cast<int64_t>(instance, fieldOffset(t, field)));
|
2007-07-07 18:09:16 +00:00
|
|
|
break;
|
2007-07-04 02:56:02 +00:00
|
|
|
|
|
|
|
case ObjectField:
|
|
|
|
pushObject(t, cast<object>(instance, fieldOffset(t, field)));
|
2007-07-07 18:09:16 +00:00
|
|
|
break;
|
2007-07-04 02:56:02 +00:00
|
|
|
|
2007-07-07 18:09:16 +00:00
|
|
|
default:
|
|
|
|
abort(t);
|
2007-07-04 02:56:02 +00:00
|
|
|
}
|
2007-05-22 00:05:29 +00:00
|
|
|
} else {
|
2007-06-08 14:23:04 +00:00
|
|
|
exception = makeNullPointerException(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case getstatic: {
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t index1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t index2 = codeBody(t, code, ip++);
|
2007-05-31 00:29:07 +00:00
|
|
|
uint16_t index = (index1 << 8) | index2;
|
2007-05-25 14:48:07 +00:00
|
|
|
|
2007-06-21 01:38:02 +00:00
|
|
|
object field = resolveField(t, codePool(t, code), index - 1);
|
2007-06-08 14:23:04 +00:00
|
|
|
if (UNLIKELY(exception)) goto throw_;
|
2007-05-25 14:48:07 +00:00
|
|
|
|
2007-06-17 23:25:58 +00:00
|
|
|
object clinit = classInitializer(t, fieldClass(t, field));
|
|
|
|
if (clinit) {
|
|
|
|
set(t, classInitializer(t, fieldClass(t, field)), 0);
|
|
|
|
code = clinit;
|
2007-05-31 00:29:07 +00:00
|
|
|
ip -= 3;
|
|
|
|
goto invoke;
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
2007-07-04 02:56:02 +00:00
|
|
|
|
|
|
|
object v = arrayBody(t, classStaticTable(t, fieldClass(t, field)),
|
|
|
|
fieldOffset(t, field));
|
|
|
|
|
|
|
|
switch (fieldCode(t, field)) {
|
|
|
|
case ByteField:
|
|
|
|
case BooleanField:
|
|
|
|
case CharField:
|
|
|
|
case ShortField:
|
|
|
|
case FloatField:
|
|
|
|
case IntField:
|
|
|
|
pushInt(t, intValue(t, v));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DoubleField:
|
|
|
|
case LongField:
|
|
|
|
pushLong(t, longValue(t, v));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ObjectField:
|
|
|
|
pushObject(t, v);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default: abort(t);
|
|
|
|
}
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case goto_: {
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t offset1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t offset2 = codeBody(t, code, ip++);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-21 18:35:24 +00:00
|
|
|
ip = (ip - 3) + static_cast<int16_t>(((offset1 << 8) | offset2));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case goto_w: {
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t offset1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t offset2 = codeBody(t, code, ip++);
|
|
|
|
uint8_t offset3 = codeBody(t, code, ip++);
|
|
|
|
uint8_t offset4 = codeBody(t, code, ip++);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-21 22:50:52 +00:00
|
|
|
ip = (ip - 5) + static_cast<int32_t>
|
2007-06-21 18:35:24 +00:00
|
|
|
(((offset1 << 24) | (offset2 << 16) | (offset3 << 8) | offset4));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case i2b: {
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, static_cast<int8_t>(popInt(t)));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case i2c: {
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, static_cast<uint16_t>(popInt(t)));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case i2l: {
|
2007-07-04 02:56:02 +00:00
|
|
|
pushLong(t, popInt(t));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case i2s: {
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, static_cast<int16_t>(popInt(t)));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iadd: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t b = popInt(t);
|
|
|
|
int32_t a = popInt(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, a + b);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iaload: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t index = popInt(t);
|
|
|
|
object array = popObject(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(array)) {
|
2007-07-04 02:56:02 +00:00
|
|
|
if (LIKELY(index >= 0 and
|
2007-07-14 17:31:01 +00:00
|
|
|
static_cast<uintptr_t>(index) < intArrayLength(t, array)))
|
2007-06-08 00:23:12 +00:00
|
|
|
{
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, intArrayBody(t, array, index));
|
2007-05-22 00:05:29 +00:00
|
|
|
} else {
|
2007-07-04 02:56:02 +00:00
|
|
|
object message = makeString(t, "%d not in [0,%d]", index,
|
2007-06-08 00:23:12 +00:00
|
|
|
intArrayLength(t, array));
|
2007-06-08 14:23:04 +00:00
|
|
|
exception = makeArrayIndexOutOfBoundsException(t, message);
|
2007-05-22 00:05:29 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} else {
|
2007-06-08 14:23:04 +00:00
|
|
|
exception = makeNullPointerException(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iand: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t b = popInt(t);
|
|
|
|
int32_t a = popInt(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, a & b);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iastore: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t value = popInt(t);
|
|
|
|
int32_t index = popInt(t);
|
|
|
|
object array = popObject(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(array)) {
|
2007-07-04 02:56:02 +00:00
|
|
|
if (LIKELY(index >= 0 and
|
2007-07-14 17:31:01 +00:00
|
|
|
static_cast<uintptr_t>(index) < intArrayLength(t, array)))
|
2007-06-08 00:23:12 +00:00
|
|
|
{
|
2007-07-04 02:56:02 +00:00
|
|
|
intArrayBody(t, array, index) = value;
|
2007-05-22 00:05:29 +00:00
|
|
|
} else {
|
2007-07-04 02:56:02 +00:00
|
|
|
object message = makeString(t, "%d not in [0,%d]", index,
|
2007-06-08 00:23:12 +00:00
|
|
|
intArrayLength(t, array));
|
2007-06-08 14:23:04 +00:00
|
|
|
exception = makeArrayIndexOutOfBoundsException(t, message);
|
2007-05-22 00:05:29 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} else {
|
2007-06-08 14:23:04 +00:00
|
|
|
exception = makeNullPointerException(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iconst_0: {
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, 0);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iconst_1: {
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, 1);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iconst_2: {
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, 2);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iconst_3: {
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, 3);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iconst_4: {
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, 4);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iconst_5: {
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, 5);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case idiv: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t b = popInt(t);
|
|
|
|
int32_t a = popInt(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, a / b);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case if_acmpeq: {
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t offset1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t offset2 = codeBody(t, code, ip++);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t b = popInt(t);
|
|
|
|
int32_t a = popInt(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
|
|
|
if (a == b) {
|
2007-06-21 22:50:52 +00:00
|
|
|
ip = (ip - 3) + static_cast<int16_t>(((offset1 << 8) | offset2));
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case if_acmpne: {
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t offset1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t offset2 = codeBody(t, code, ip++);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t b = popInt(t);
|
|
|
|
int32_t a = popInt(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
|
|
|
if (a != b) {
|
2007-06-21 22:50:52 +00:00
|
|
|
ip = (ip - 3) + static_cast<int16_t>(((offset1 << 8) | offset2));
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case if_icmpeq: {
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t offset1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t offset2 = codeBody(t, code, ip++);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t b = popInt(t);
|
|
|
|
int32_t a = popInt(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
if (a == b) {
|
2007-06-21 22:50:52 +00:00
|
|
|
ip = (ip - 3) + static_cast<int16_t>(((offset1 << 8) | offset2));
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case if_icmpne: {
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t offset1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t offset2 = codeBody(t, code, ip++);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t b = popInt(t);
|
|
|
|
int32_t a = popInt(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
if (a != b) {
|
2007-06-21 22:50:52 +00:00
|
|
|
ip = (ip - 3) + static_cast<int16_t>(((offset1 << 8) | offset2));
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case if_icmpgt: {
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t offset1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t offset2 = codeBody(t, code, ip++);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t b = popInt(t);
|
|
|
|
int32_t a = popInt(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
if (a > b) {
|
2007-06-21 22:50:52 +00:00
|
|
|
ip = (ip - 3) + static_cast<int16_t>(((offset1 << 8) | offset2));
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case if_icmpge: {
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t offset1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t offset2 = codeBody(t, code, ip++);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t b = popInt(t);
|
|
|
|
int32_t a = popInt(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
if (a >= b) {
|
2007-06-21 22:50:52 +00:00
|
|
|
ip = (ip - 3) + static_cast<int16_t>(((offset1 << 8) | offset2));
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case if_icmplt: {
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t offset1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t offset2 = codeBody(t, code, ip++);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t b = popInt(t);
|
|
|
|
int32_t a = popInt(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
if (a < b) {
|
2007-06-21 22:50:52 +00:00
|
|
|
ip = (ip - 3) + static_cast<int16_t>(((offset1 << 8) | offset2));
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case if_icmple: {
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t offset1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t offset2 = codeBody(t, code, ip++);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t b = popInt(t);
|
|
|
|
int32_t a = popInt(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-07 23:47:35 +00:00
|
|
|
if (a <= b) {
|
2007-06-21 22:50:52 +00:00
|
|
|
ip = (ip - 3) + static_cast<int16_t>(((offset1 << 8) | offset2));
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ifeq: {
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t offset1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t offset2 = codeBody(t, code, ip++);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
if (popInt(t) == 0) {
|
2007-06-21 22:50:52 +00:00
|
|
|
ip = (ip - 3) + static_cast<int16_t>(((offset1 << 8) | offset2));
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ifne: {
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t offset1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t offset2 = codeBody(t, code, ip++);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
if (popInt(t)) {
|
2007-06-21 22:50:52 +00:00
|
|
|
ip = (ip - 3) + static_cast<int16_t>(((offset1 << 8) | offset2));
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ifgt: {
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t offset1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t offset2 = codeBody(t, code, ip++);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
if (static_cast<int32_t>(popInt(t)) > 0) {
|
2007-06-21 22:50:52 +00:00
|
|
|
ip = (ip - 3) + static_cast<int16_t>(((offset1 << 8) | offset2));
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ifge: {
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t offset1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t offset2 = codeBody(t, code, ip++);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
if (static_cast<int32_t>(popInt(t)) >= 0) {
|
2007-06-21 22:50:52 +00:00
|
|
|
ip = (ip - 3) + static_cast<int16_t>(((offset1 << 8) | offset2));
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iflt: {
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t offset1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t offset2 = codeBody(t, code, ip++);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
if (static_cast<int32_t>(popInt(t)) < 0) {
|
2007-06-21 22:50:52 +00:00
|
|
|
ip = (ip - 3) + static_cast<int16_t>(((offset1 << 8) | offset2));
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ifle: {
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t offset1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t offset2 = codeBody(t, code, ip++);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
if (static_cast<int32_t>(popInt(t)) <= 0) {
|
2007-06-21 22:50:52 +00:00
|
|
|
ip = (ip - 3) + static_cast<int16_t>(((offset1 << 8) | offset2));
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ifnonnull: {
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t offset1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t offset2 = codeBody(t, code, ip++);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
if (popObject(t)) {
|
2007-06-21 22:50:52 +00:00
|
|
|
ip = (ip - 3) + static_cast<int16_t>(((offset1 << 8) | offset2));
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ifnull: {
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t offset1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t offset2 = codeBody(t, code, ip++);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
if (popObject(t) == 0) {
|
2007-06-21 22:50:52 +00:00
|
|
|
ip = (ip - 3) + static_cast<int16_t>(((offset1 << 8) | offset2));
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iinc: {
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t index = codeBody(t, code, ip++);
|
|
|
|
int8_t c = codeBody(t, code, ip++);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-06 01:06:06 +00:00
|
|
|
setLocalInt(t, index, localInt(t, index) + c);
|
2007-07-04 17:58:27 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iload: {
|
2007-07-06 01:06:06 +00:00
|
|
|
pushInt(t, localInt(t, codeBody(t, code, ip++)));
|
2007-07-04 17:58:27 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iload_0: {
|
2007-07-06 01:06:06 +00:00
|
|
|
pushInt(t, localInt(t, 0));
|
2007-07-04 17:58:27 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iload_1: {
|
2007-07-06 01:06:06 +00:00
|
|
|
pushInt(t, localInt(t, 1));
|
2007-07-04 17:58:27 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iload_2: {
|
2007-07-06 01:06:06 +00:00
|
|
|
pushInt(t, localInt(t, 2));
|
2007-07-04 17:58:27 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iload_3: {
|
2007-07-06 01:06:06 +00:00
|
|
|
pushInt(t, localInt(t, 3));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case imul: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t b = popInt(t);
|
|
|
|
int32_t a = popInt(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, a * b);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ineg: {
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, - popInt(t));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case instanceof: {
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t index1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t index2 = codeBody(t, code, ip++);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
if (peekObject(t, sp - 1)) {
|
2007-05-22 00:05:29 +00:00
|
|
|
uint16_t index = (index1 << 8) | index2;
|
|
|
|
|
2007-06-21 01:38:02 +00:00
|
|
|
object class_ = resolveClass(t, codePool(t, code), index - 1);
|
2007-06-08 14:23:04 +00:00
|
|
|
if (UNLIKELY(exception)) goto throw_;
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
if (instanceOf(t, class_, peekObject(t, sp - 1))) {
|
|
|
|
pushInt(t, 1);
|
2007-05-22 00:05:29 +00:00
|
|
|
} else {
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, 0);
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
|
|
|
} else {
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, 0);
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
2007-05-25 14:48:07 +00:00
|
|
|
case invokeinterface: {
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t index1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t index2 = codeBody(t, code, ip++);
|
2007-05-30 00:08:10 +00:00
|
|
|
uint16_t index = (index1 << 8) | index2;
|
2007-07-04 02:56:02 +00:00
|
|
|
|
2007-05-30 00:08:10 +00:00
|
|
|
ip += 2;
|
|
|
|
|
2007-06-21 01:38:02 +00:00
|
|
|
object method = resolveMethod(t, codePool(t, code), index - 1);
|
2007-06-08 14:23:04 +00:00
|
|
|
if (UNLIKELY(exception)) goto throw_;
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
unsigned parameterFootprint = methodParameterFootprint(t, method);
|
|
|
|
if (LIKELY(peekObject(t, sp - parameterFootprint))) {
|
|
|
|
code = findInterfaceMethod
|
|
|
|
(t, method, peekObject(t, sp - parameterFootprint));
|
2007-06-08 14:23:04 +00:00
|
|
|
if (UNLIKELY(exception)) goto throw_;
|
2007-05-30 00:08:10 +00:00
|
|
|
|
|
|
|
goto invoke;
|
|
|
|
} else {
|
2007-06-08 14:23:04 +00:00
|
|
|
exception = makeNullPointerException(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case invokespecial: {
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t index1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t index2 = codeBody(t, code, ip++);
|
2007-05-30 00:08:10 +00:00
|
|
|
uint16_t index = (index1 << 8) | index2;
|
|
|
|
|
2007-06-21 01:38:02 +00:00
|
|
|
object method = resolveMethod(t, codePool(t, code), index - 1);
|
2007-06-08 14:23:04 +00:00
|
|
|
if (UNLIKELY(exception)) goto throw_;
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
unsigned parameterFootprint = methodParameterFootprint(t, method);
|
|
|
|
if (LIKELY(peekObject(t, sp - parameterFootprint))) {
|
2007-07-06 01:06:06 +00:00
|
|
|
object class_ = methodClass(t, frameMethod(t, frame));
|
2007-06-13 14:03:08 +00:00
|
|
|
if (isSpecialMethod(t, method, class_)) {
|
2007-07-08 01:06:32 +00:00
|
|
|
class_ = classSuper(t, class_);
|
|
|
|
|
2007-07-11 01:38:06 +00:00
|
|
|
if (classVirtualTable(t, class_) == 0) {
|
2007-07-08 01:06:32 +00:00
|
|
|
PROTECT(t, class_);
|
|
|
|
|
|
|
|
resolveClass(t, className(t, class_));
|
|
|
|
if (UNLIKELY(exception)) goto throw_;
|
|
|
|
|
|
|
|
object clinit = classInitializer(t, class_);
|
|
|
|
if (clinit) {
|
|
|
|
set(t, classInitializer(t, methodClass(t, method)), 0);
|
|
|
|
code = clinit;
|
|
|
|
ip -= 3;
|
|
|
|
goto invoke;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
code = findMethod(t, method, class_);
|
2007-05-30 00:08:10 +00:00
|
|
|
} else {
|
2007-06-08 14:23:04 +00:00
|
|
|
code = method;
|
2007-05-30 00:08:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
goto invoke;
|
|
|
|
} else {
|
2007-06-08 14:23:04 +00:00
|
|
|
exception = makeNullPointerException(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case invokestatic: {
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t index1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t index2 = codeBody(t, code, ip++);
|
2007-05-30 00:08:10 +00:00
|
|
|
uint16_t index = (index1 << 8) | index2;
|
|
|
|
|
2007-06-21 01:38:02 +00:00
|
|
|
object method = resolveMethod(t, codePool(t, code), index - 1);
|
2007-06-08 14:23:04 +00:00
|
|
|
if (UNLIKELY(exception)) goto throw_;
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-06-18 04:09:02 +00:00
|
|
|
object clinit = classInitializer(t, methodClass(t, method));
|
2007-06-17 23:25:58 +00:00
|
|
|
if (clinit) {
|
2007-06-18 04:09:02 +00:00
|
|
|
set(t, classInitializer(t, methodClass(t, method)), 0);
|
2007-06-17 23:25:58 +00:00
|
|
|
code = clinit;
|
2007-06-11 23:40:24 +00:00
|
|
|
ip -= 3;
|
2007-05-30 00:08:10 +00:00
|
|
|
goto invoke;
|
|
|
|
}
|
|
|
|
|
2007-06-08 14:23:04 +00:00
|
|
|
code = method;
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto invoke;
|
|
|
|
|
|
|
|
case invokevirtual: {
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t index1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t index2 = codeBody(t, code, ip++);
|
2007-05-30 00:08:10 +00:00
|
|
|
uint16_t index = (index1 << 8) | index2;
|
|
|
|
|
2007-06-21 01:38:02 +00:00
|
|
|
object method = resolveMethod(t, codePool(t, code), index - 1);
|
2007-06-08 14:23:04 +00:00
|
|
|
if (UNLIKELY(exception)) goto throw_;
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
unsigned parameterFootprint = methodParameterFootprint(t, method);
|
|
|
|
if (LIKELY(peekObject(t, sp - parameterFootprint))) {
|
2007-07-08 01:06:32 +00:00
|
|
|
object class_ = objectClass(t, peekObject(t, sp - parameterFootprint));
|
|
|
|
|
2007-07-11 01:38:06 +00:00
|
|
|
if (classVirtualTable(t, class_) == 0) {
|
2007-07-08 01:06:32 +00:00
|
|
|
PROTECT(t, class_);
|
|
|
|
|
|
|
|
resolveClass(t, className(t, class_));
|
|
|
|
if (UNLIKELY(exception)) goto throw_;
|
|
|
|
|
|
|
|
object clinit = classInitializer(t, class_);
|
|
|
|
if (clinit) {
|
|
|
|
set(t, classInitializer(t, methodClass(t, method)), 0);
|
|
|
|
code = clinit;
|
|
|
|
ip -= 3;
|
|
|
|
goto invoke;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
code = findMethod(t, method, class_);
|
2007-05-30 00:08:10 +00:00
|
|
|
goto invoke;
|
|
|
|
} else {
|
2007-06-08 14:23:04 +00:00
|
|
|
exception = makeNullPointerException(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ior: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t b = popInt(t);
|
|
|
|
int32_t a = popInt(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, a | b);
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case irem: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t b = popInt(t);
|
|
|
|
int32_t a = popInt(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, a % b);
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-07-07 23:47:35 +00:00
|
|
|
case ireturn: {
|
|
|
|
int32_t result = popInt(t);
|
|
|
|
popFrame(t);
|
|
|
|
if (frame >= 0) {
|
|
|
|
pushInt(t, result);
|
|
|
|
goto loop;
|
|
|
|
} else {
|
|
|
|
return makeInt(t, result);
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
2007-05-30 00:08:10 +00:00
|
|
|
case ishl: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t b = popInt(t);
|
|
|
|
int32_t a = popInt(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, a << b);
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ishr: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t b = popInt(t);
|
|
|
|
int32_t a = popInt(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, a >> b);
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case istore: {
|
2007-07-06 01:06:06 +00:00
|
|
|
setLocalInt(t, codeBody(t, code, ip++), popInt(t));
|
2007-07-04 02:56:02 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case istore_0: {
|
2007-07-06 01:06:06 +00:00
|
|
|
setLocalInt(t, 0, popInt(t));
|
2007-07-04 02:56:02 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case istore_1: {
|
2007-07-06 01:06:06 +00:00
|
|
|
setLocalInt(t, 1, popInt(t));
|
2007-07-04 02:56:02 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case istore_2: {
|
2007-07-06 01:06:06 +00:00
|
|
|
setLocalInt(t, 2, popInt(t));
|
2007-07-04 02:56:02 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case istore_3: {
|
2007-07-06 01:06:06 +00:00
|
|
|
setLocalInt(t, 3, popInt(t));
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case isub: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t b = popInt(t);
|
|
|
|
int32_t a = popInt(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, a - b);
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iushr: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t b = popInt(t);
|
|
|
|
int32_t a = popInt(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, static_cast<uint32_t>(a >> b));
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ixor: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t b = popInt(t);
|
|
|
|
int32_t a = popInt(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, a ^ b);
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case jsr: {
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t offset1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t offset2 = codeBody(t, code, ip++);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, ip);
|
2007-06-21 22:50:52 +00:00
|
|
|
ip = (ip - 3) + static_cast<int16_t>(((offset1 << 8) | offset2));
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case jsr_w: {
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t offset1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t offset2 = codeBody(t, code, ip++);
|
|
|
|
uint8_t offset3 = codeBody(t, code, ip++);
|
|
|
|
uint8_t offset4 = codeBody(t, code, ip++);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, ip);
|
2007-06-21 22:50:52 +00:00
|
|
|
ip = (ip - 3) + static_cast<int32_t>
|
|
|
|
((offset1 << 24) | (offset2 << 16) | (offset3 << 8) | offset4);
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case l2i: {
|
2007-07-07 23:47:35 +00:00
|
|
|
pushInt(t, static_cast<int32_t>(popLong(t)));
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ladd: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int64_t b = popLong(t);
|
|
|
|
int64_t a = popLong(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushLong(t, a + b);
|
2007-05-25 14:48:07 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-05-30 00:08:10 +00:00
|
|
|
case laload: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t index = popInt(t);
|
|
|
|
object array = popObject(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(array)) {
|
2007-07-04 02:56:02 +00:00
|
|
|
if (LIKELY(index >= 0 and
|
2007-07-14 17:31:01 +00:00
|
|
|
static_cast<uintptr_t>(index) < longArrayLength(t, array)))
|
2007-06-08 00:23:12 +00:00
|
|
|
{
|
2007-07-04 02:56:02 +00:00
|
|
|
pushLong(t, longArrayBody(t, array, index));
|
2007-05-30 00:08:10 +00:00
|
|
|
} else {
|
2007-07-04 02:56:02 +00:00
|
|
|
object message = makeString(t, "%d not in [0,%d]", index,
|
2007-06-08 00:23:12 +00:00
|
|
|
longArrayLength(t, array));
|
2007-06-08 14:23:04 +00:00
|
|
|
exception = makeArrayIndexOutOfBoundsException(t, message);
|
2007-05-30 00:08:10 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} else {
|
2007-06-08 14:23:04 +00:00
|
|
|
exception = makeNullPointerException(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case land: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int64_t b = popLong(t);
|
|
|
|
int64_t a = popLong(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushLong(t, a & b);
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lastore: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int64_t value = popLong(t);
|
|
|
|
int32_t index = popInt(t);
|
|
|
|
object array = popObject(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(array)) {
|
2007-07-04 02:56:02 +00:00
|
|
|
if (LIKELY(index >= 0 and
|
2007-07-14 17:31:01 +00:00
|
|
|
static_cast<uintptr_t>(index) < longArrayLength(t, array)))
|
2007-06-08 00:23:12 +00:00
|
|
|
{
|
2007-07-04 02:56:02 +00:00
|
|
|
longArrayBody(t, array, index) = value;
|
2007-05-30 00:08:10 +00:00
|
|
|
} else {
|
2007-07-04 02:56:02 +00:00
|
|
|
object message = makeString(t, "%d not in [0,%d]", index,
|
2007-06-08 00:23:12 +00:00
|
|
|
longArrayLength(t, array));
|
2007-06-08 14:23:04 +00:00
|
|
|
exception = makeArrayIndexOutOfBoundsException(t, message);
|
2007-05-30 00:08:10 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} else {
|
2007-06-08 14:23:04 +00:00
|
|
|
exception = makeNullPointerException(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lcmp: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int64_t b = popLong(t);
|
|
|
|
int64_t a = popLong(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, a > b ? 1 : a == b ? 0 : -1);
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lconst_0: {
|
2007-07-04 02:56:02 +00:00
|
|
|
pushLong(t, 0);
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lconst_1: {
|
2007-07-04 02:56:02 +00:00
|
|
|
pushLong(t, 1);
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
case ldc:
|
|
|
|
case ldc_w: {
|
|
|
|
uint16_t index;
|
|
|
|
|
|
|
|
if (instruction == ldc) {
|
|
|
|
index = codeBody(t, code, ip++);
|
|
|
|
} else {
|
|
|
|
uint8_t index1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t index2 = codeBody(t, code, ip++);
|
|
|
|
index = (index1 << 8) | index2;
|
|
|
|
}
|
|
|
|
|
|
|
|
object v = arrayBody(t, codePool(t, code), index - 1);
|
|
|
|
|
|
|
|
if (objectClass(t, v) == arrayBody(t, t->vm->types, Machine::IntType)) {
|
|
|
|
pushInt(t, intValue(t, v));
|
|
|
|
} else if (objectClass(t, v)
|
|
|
|
== arrayBody(t, t->vm->types, Machine::StringType))
|
|
|
|
{
|
|
|
|
pushObject(t, v);
|
|
|
|
} else if (objectClass(t, v)
|
|
|
|
== arrayBody(t, t->vm->types, Machine::FloatType))
|
|
|
|
{
|
|
|
|
pushInt(t, floatValue(t, v));
|
2007-07-08 01:06:32 +00:00
|
|
|
} else {
|
|
|
|
abort(t);
|
2007-07-04 02:56:02 +00:00
|
|
|
}
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ldc2_w: {
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t index1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t index2 = codeBody(t, code, ip++);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
object v = arrayBody(t, codePool(t, code), ((index1 << 8) | index2) - 1);
|
|
|
|
|
|
|
|
if (objectClass(t, v) == arrayBody(t, t->vm->types, Machine::LongType)) {
|
|
|
|
pushLong(t, longValue(t, v));
|
|
|
|
} else if (objectClass(t, v)
|
|
|
|
== arrayBody(t, t->vm->types, Machine::DoubleType))
|
|
|
|
{
|
|
|
|
pushLong(t, doubleValue(t, v));
|
2007-07-08 01:06:32 +00:00
|
|
|
} else {
|
|
|
|
abort(t);
|
2007-07-04 02:56:02 +00:00
|
|
|
}
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-06-18 19:23:44 +00:00
|
|
|
case vm::ldiv: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int64_t b = popLong(t);
|
|
|
|
int64_t a = popLong(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushLong(t, a / b);
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-07-04 17:58:27 +00:00
|
|
|
case lload: {
|
2007-07-06 01:06:06 +00:00
|
|
|
pushLong(t, localLong(t, codeBody(t, code, ip++)));
|
2007-07-04 17:58:27 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lload_0: {
|
2007-07-06 01:06:06 +00:00
|
|
|
pushLong(t, localLong(t, 0));
|
2007-07-04 17:58:27 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lload_1: {
|
2007-07-06 01:06:06 +00:00
|
|
|
pushLong(t, localLong(t, 1));
|
2007-07-04 17:58:27 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lload_2: {
|
2007-07-06 01:06:06 +00:00
|
|
|
pushLong(t, localLong(t, 2));
|
2007-07-04 17:58:27 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lload_3: {
|
2007-07-06 01:06:06 +00:00
|
|
|
pushLong(t, localLong(t, 3));
|
2007-07-04 17:58:27 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-05-30 00:08:10 +00:00
|
|
|
case lmul: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int64_t b = popLong(t);
|
|
|
|
int64_t a = popLong(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushLong(t, a * b);
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lneg: {
|
2007-07-04 02:56:02 +00:00
|
|
|
pushLong(t, - popInt(t));
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lor: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int64_t b = popLong(t);
|
|
|
|
int64_t a = popLong(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushLong(t, a | b);
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lrem: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int64_t b = popLong(t);
|
|
|
|
int64_t a = popLong(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushLong(t, a % b);
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-07-07 23:47:35 +00:00
|
|
|
case lreturn: {
|
|
|
|
int64_t result = popLong(t);
|
|
|
|
popFrame(t);
|
|
|
|
if (frame >= 0) {
|
|
|
|
pushLong(t, result);
|
|
|
|
goto loop;
|
|
|
|
} else {
|
|
|
|
return makeLong(t, result);
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
2007-05-30 00:08:10 +00:00
|
|
|
case lshl: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int64_t b = popLong(t);
|
|
|
|
int64_t a = popLong(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushLong(t, a << b);
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lshr: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int64_t b = popLong(t);
|
|
|
|
int64_t a = popLong(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushLong(t, a >> b);
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lstore: {
|
2007-07-06 01:06:06 +00:00
|
|
|
setLocalLong(t, codeBody(t, code, ip++), popLong(t));
|
2007-07-04 02:56:02 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lstore_0: {
|
2007-07-06 01:06:06 +00:00
|
|
|
setLocalLong(t, 0, popLong(t));
|
2007-07-04 02:56:02 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lstore_1: {
|
2007-07-06 01:06:06 +00:00
|
|
|
setLocalLong(t, 1, popLong(t));
|
2007-07-04 02:56:02 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lstore_2: {
|
2007-07-06 01:06:06 +00:00
|
|
|
setLocalLong(t, 2, popLong(t));
|
2007-07-04 02:56:02 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lstore_3: {
|
2007-07-06 01:06:06 +00:00
|
|
|
setLocalLong(t, 3, popLong(t));
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lsub: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int64_t b = popLong(t);
|
|
|
|
int64_t a = popLong(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushLong(t, a - b);
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lushr: {
|
2007-07-04 02:56:02 +00:00
|
|
|
uint64_t b = popLong(t);
|
|
|
|
uint64_t a = popLong(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushLong(t, a >> b);
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lxor: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int64_t b = popLong(t);
|
|
|
|
int64_t a = popLong(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushLong(t, a ^ b);
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-07-02 01:42:35 +00:00
|
|
|
case monitorenter: {
|
2007-07-04 02:56:02 +00:00
|
|
|
object o = popObject(t);
|
2007-07-02 01:42:35 +00:00
|
|
|
if (LIKELY(o)) {
|
2007-07-07 23:47:35 +00:00
|
|
|
acquire(t, o);
|
2007-07-02 01:42:35 +00:00
|
|
|
} else {
|
|
|
|
exception = makeNullPointerException(t);
|
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case monitorexit: {
|
2007-07-04 02:56:02 +00:00
|
|
|
object o = popObject(t);
|
2007-07-02 01:42:35 +00:00
|
|
|
if (LIKELY(o)) {
|
2007-07-07 23:47:35 +00:00
|
|
|
release(t, o);
|
2007-07-02 01:42:35 +00:00
|
|
|
} else {
|
|
|
|
exception = makeNullPointerException(t);
|
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} goto loop;
|
2007-07-01 21:34:22 +00:00
|
|
|
|
2007-05-31 00:29:07 +00:00
|
|
|
case new_: {
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t index1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t index2 = codeBody(t, code, ip++);
|
2007-05-31 00:29:07 +00:00
|
|
|
uint16_t index = (index1 << 8) | index2;
|
|
|
|
|
2007-06-21 01:38:02 +00:00
|
|
|
object class_ = resolveClass(t, codePool(t, code), index - 1);
|
2007-06-08 14:23:04 +00:00
|
|
|
if (UNLIKELY(exception)) goto throw_;
|
2007-06-11 23:40:24 +00:00
|
|
|
|
2007-06-18 04:09:02 +00:00
|
|
|
object clinit = classInitializer(t, class_);
|
2007-06-17 23:25:58 +00:00
|
|
|
if (clinit) {
|
2007-06-18 04:09:02 +00:00
|
|
|
set(t, classInitializer(t, class_), 0);
|
2007-06-17 23:25:58 +00:00
|
|
|
code = clinit;
|
2007-05-31 00:29:07 +00:00
|
|
|
ip -= 3;
|
|
|
|
goto invoke;
|
|
|
|
}
|
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushObject(t, make(t, class_));
|
2007-05-31 00:29:07 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case newarray: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t count = popInt(t);
|
2007-05-31 00:29:07 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
if (LIKELY(count >= 0)) {
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t type = codeBody(t, code, ip++);
|
2007-05-31 00:29:07 +00:00
|
|
|
|
|
|
|
object array;
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case T_BOOLEAN:
|
2007-07-04 02:56:02 +00:00
|
|
|
array = makeBooleanArray(t, count, true);
|
2007-05-31 00:29:07 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case T_CHAR:
|
2007-07-04 02:56:02 +00:00
|
|
|
array = makeCharArray(t, count, true);
|
2007-05-31 00:29:07 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case T_FLOAT:
|
2007-07-04 02:56:02 +00:00
|
|
|
array = makeFloatArray(t, count, true);
|
2007-05-31 00:29:07 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case T_DOUBLE:
|
2007-07-04 02:56:02 +00:00
|
|
|
array = makeDoubleArray(t, count, true);
|
2007-05-31 00:29:07 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case T_BYTE:
|
2007-07-04 02:56:02 +00:00
|
|
|
array = makeByteArray(t, count, true);
|
2007-05-31 00:29:07 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case T_SHORT:
|
2007-07-04 02:56:02 +00:00
|
|
|
array = makeShortArray(t, count, true);
|
2007-05-31 00:29:07 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case T_INT:
|
2007-07-04 02:56:02 +00:00
|
|
|
array = makeIntArray(t, count, true);
|
2007-05-31 00:29:07 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case T_LONG:
|
2007-07-04 02:56:02 +00:00
|
|
|
array = makeLongArray(t, count, true);
|
2007-05-31 00:29:07 +00:00
|
|
|
break;
|
|
|
|
|
2007-06-03 02:00:23 +00:00
|
|
|
default: abort(t);
|
2007-05-31 00:29:07 +00:00
|
|
|
}
|
2007-06-21 19:43:33 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushObject(t, array);
|
2007-05-31 00:29:07 +00:00
|
|
|
} else {
|
2007-07-04 02:56:02 +00:00
|
|
|
object message = makeString(t, "%d", count);
|
2007-07-07 23:47:35 +00:00
|
|
|
exception = makeNegativeArraySizeException(t, message);
|
2007-05-31 00:29:07 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case nop: goto loop;
|
|
|
|
|
2007-06-25 02:02:24 +00:00
|
|
|
case pop_: {
|
2007-06-08 14:23:04 +00:00
|
|
|
-- sp;
|
2007-05-31 00:29:07 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case pop2: {
|
2007-07-04 02:56:02 +00:00
|
|
|
sp -= 2;
|
2007-05-31 00:29:07 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case putfield: {
|
2007-07-04 02:56:02 +00:00
|
|
|
uint8_t index1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t index2 = codeBody(t, code, ip++);
|
|
|
|
uint16_t index = (index1 << 8) | index2;
|
2007-05-31 00:29:07 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
object field = resolveField(t, codePool(t, code), index - 1);
|
|
|
|
if (UNLIKELY(exception)) goto throw_;
|
2007-05-31 00:29:07 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
switch (fieldCode(t, field)) {
|
|
|
|
case ByteField:
|
|
|
|
case BooleanField:
|
|
|
|
case CharField:
|
|
|
|
case ShortField:
|
|
|
|
case FloatField:
|
|
|
|
case IntField: {
|
|
|
|
int32_t value = popInt(t);
|
|
|
|
object o = popObject(t);
|
|
|
|
if (LIKELY(o)) {
|
|
|
|
switch (fieldCode(t, field)) {
|
|
|
|
case ByteField:
|
|
|
|
case BooleanField:
|
|
|
|
cast<int8_t>(o, fieldOffset(t, field)) = value;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CharField:
|
|
|
|
case ShortField:
|
|
|
|
cast<int16_t>(o, fieldOffset(t, field)) = value;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FloatField:
|
|
|
|
case IntField:
|
|
|
|
cast<int32_t>(o, fieldOffset(t, field)) = value;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
exception = makeNullPointerException(t);
|
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case DoubleField:
|
|
|
|
case LongField: {
|
|
|
|
int64_t value = popLong(t);
|
|
|
|
object o = popObject(t);
|
|
|
|
if (LIKELY(o)) {
|
|
|
|
cast<int64_t>(o, fieldOffset(t, field)) = value;
|
|
|
|
} else {
|
|
|
|
exception = makeNullPointerException(t);
|
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case ObjectField: {
|
|
|
|
object value = popObject(t);
|
|
|
|
object o = popObject(t);
|
|
|
|
if (LIKELY(o)) {
|
|
|
|
set(t, cast<object>(o, fieldOffset(t, field)), value);
|
|
|
|
} else {
|
|
|
|
exception = makeNullPointerException(t);
|
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
|
|
|
default: abort(t);
|
2007-05-31 00:29:07 +00:00
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case putstatic: {
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t index1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t index2 = codeBody(t, code, ip++);
|
2007-05-31 00:29:07 +00:00
|
|
|
uint16_t index = (index1 << 8) | index2;
|
|
|
|
|
2007-06-21 01:38:02 +00:00
|
|
|
object field = resolveField(t, codePool(t, code), index - 1);
|
2007-06-08 14:23:04 +00:00
|
|
|
if (UNLIKELY(exception)) goto throw_;
|
2007-05-31 00:29:07 +00:00
|
|
|
|
2007-06-17 23:25:58 +00:00
|
|
|
object clinit = classInitializer(t, fieldClass(t, field));
|
|
|
|
if (clinit) {
|
|
|
|
set(t, classInitializer(t, fieldClass(t, field)), 0);
|
|
|
|
code = clinit;
|
2007-05-31 00:29:07 +00:00
|
|
|
ip -= 3;
|
|
|
|
goto invoke;
|
|
|
|
}
|
2007-07-04 02:56:02 +00:00
|
|
|
|
|
|
|
PROTECT(t, field);
|
2007-05-31 00:29:07 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
object v;
|
|
|
|
|
|
|
|
switch (fieldCode(t, field)) {
|
|
|
|
case ByteField:
|
|
|
|
case BooleanField:
|
|
|
|
case CharField:
|
|
|
|
case ShortField:
|
|
|
|
case FloatField:
|
|
|
|
case IntField: {
|
|
|
|
v = makeInt(t, popInt(t));
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case DoubleField:
|
|
|
|
case LongField: {
|
|
|
|
v = makeLong(t, popLong(t));
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case ObjectField:
|
|
|
|
v = popObject(t);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default: abort(t);
|
|
|
|
}
|
|
|
|
|
|
|
|
set(t, arrayBody(t, classStaticTable(t, fieldClass(t, field)),
|
|
|
|
fieldOffset(t, field)), v);
|
2007-05-31 00:29:07 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ret: {
|
2007-07-06 01:06:06 +00:00
|
|
|
ip = localInt(t, codeBody(t, code, ip));
|
2007-05-31 00:29:07 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case return_: {
|
2007-07-06 01:06:06 +00:00
|
|
|
popFrame(t);
|
|
|
|
if (frame >= 0) {
|
2007-05-31 00:29:07 +00:00
|
|
|
goto loop;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case saload: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int32_t index = popInt(t);
|
|
|
|
object array = popObject(t);
|
2007-05-31 00:29:07 +00:00
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(array)) {
|
2007-07-04 02:56:02 +00:00
|
|
|
if (LIKELY(index >= 0 and
|
2007-07-14 17:31:01 +00:00
|
|
|
static_cast<uintptr_t>(index) < shortArrayLength(t, array)))
|
2007-06-08 00:23:12 +00:00
|
|
|
{
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, shortArrayBody(t, array, index));
|
2007-05-31 00:29:07 +00:00
|
|
|
} else {
|
2007-07-04 02:56:02 +00:00
|
|
|
object message = makeString(t, "%d not in [0,%d]", index,
|
2007-06-08 00:23:12 +00:00
|
|
|
shortArrayLength(t, array));
|
2007-06-08 14:23:04 +00:00
|
|
|
exception = makeArrayIndexOutOfBoundsException(t, message);
|
2007-05-31 00:29:07 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} else {
|
2007-06-08 14:23:04 +00:00
|
|
|
exception = makeNullPointerException(t);
|
2007-05-31 00:29:07 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case sastore: {
|
2007-07-04 02:56:02 +00:00
|
|
|
int16_t value = popInt(t);
|
|
|
|
int32_t index = popInt(t);
|
|
|
|
object array = popObject(t);
|
2007-05-31 00:29:07 +00:00
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(array)) {
|
2007-07-04 02:56:02 +00:00
|
|
|
if (LIKELY(index >= 0 and
|
2007-07-14 17:31:01 +00:00
|
|
|
static_cast<uintptr_t>(index) < shortArrayLength(t, array)))
|
2007-06-08 00:23:12 +00:00
|
|
|
{
|
2007-07-04 02:56:02 +00:00
|
|
|
shortArrayBody(t, array, index) = value;
|
2007-05-31 00:29:07 +00:00
|
|
|
} else {
|
2007-07-04 02:56:02 +00:00
|
|
|
object message = makeString(t, "%d not in [0,%d]", index,
|
2007-06-08 00:23:12 +00:00
|
|
|
shortArrayLength(t, array));
|
2007-06-08 14:23:04 +00:00
|
|
|
exception = makeArrayIndexOutOfBoundsException(t, message);
|
2007-05-31 00:29:07 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} else {
|
2007-06-08 14:23:04 +00:00
|
|
|
exception = makeNullPointerException(t);
|
2007-05-31 00:29:07 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case sipush: {
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t byte1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t byte2 = codeBody(t, code, ip++);
|
2007-05-31 00:29:07 +00:00
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
pushInt(t, (byte1 << 8) | byte2);
|
2007-05-31 00:29:07 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case swap: {
|
2007-07-04 02:56:02 +00:00
|
|
|
uintptr_t tmp[2];
|
|
|
|
memcpy(tmp , stack + ((sp - 1) * 2), BytesPerWord * 2);
|
|
|
|
memcpy(stack + ((sp - 1) * 2), stack + ((sp - 2) * 2), BytesPerWord * 2);
|
|
|
|
memcpy(stack + ((sp - 2) * 2), tmp , BytesPerWord * 2);
|
2007-05-31 00:29:07 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case wide: goto wide;
|
|
|
|
|
2007-06-03 02:00:23 +00:00
|
|
|
default: abort(t);
|
2007-05-31 00:29:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
wide:
|
2007-06-18 21:13:21 +00:00
|
|
|
switch (codeBody(t, code, ip++)) {
|
2007-07-04 02:56:02 +00:00
|
|
|
case aload: {
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t index1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t index2 = codeBody(t, code, ip++);
|
2007-05-31 00:29:07 +00:00
|
|
|
|
2007-07-06 01:06:06 +00:00
|
|
|
pushObject(t, localObject(t, (index1 << 8) | index2));
|
2007-05-31 00:29:07 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-07-04 02:56:02 +00:00
|
|
|
case astore: {
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t index1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t index2 = codeBody(t, code, ip++);
|
2007-05-31 00:29:07 +00:00
|
|
|
|
2007-07-06 01:06:06 +00:00
|
|
|
setLocalObject(t, (index1 << 8) | index2, popObject(t));
|
2007-05-31 00:29:07 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iinc: {
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t index1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t index2 = codeBody(t, code, ip++);
|
2007-05-31 00:29:07 +00:00
|
|
|
uint16_t index = (index1 << 8) | index2;
|
|
|
|
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t count1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t count2 = codeBody(t, code, ip++);
|
2007-05-31 00:29:07 +00:00
|
|
|
uint16_t count = (count1 << 8) | count2;
|
|
|
|
|
2007-07-06 01:06:06 +00:00
|
|
|
setLocalInt(t, index, localInt(t, index) + count);
|
2007-07-04 02:56:02 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iload: {
|
|
|
|
uint8_t index1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t index2 = codeBody(t, code, ip++);
|
|
|
|
|
2007-07-06 01:06:06 +00:00
|
|
|
pushInt(t, localInt(t, (index1 << 8) | index2));
|
2007-07-04 02:56:02 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case istore: {
|
|
|
|
uint8_t index1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t index2 = codeBody(t, code, ip++);
|
|
|
|
|
2007-07-06 01:06:06 +00:00
|
|
|
setLocalInt(t, (index1 << 8) | index2, popInt(t));
|
2007-07-04 02:56:02 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lload: {
|
|
|
|
uint8_t index1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t index2 = codeBody(t, code, ip++);
|
|
|
|
|
2007-07-06 01:06:06 +00:00
|
|
|
pushLong(t, localLong(t, (index1 << 8) | index2));
|
2007-07-04 02:56:02 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lstore: {
|
|
|
|
uint8_t index1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t index2 = codeBody(t, code, ip++);
|
|
|
|
|
2007-07-06 01:06:06 +00:00
|
|
|
setLocalLong(t, (index1 << 8) | index2, popLong(t));
|
2007-05-31 00:29:07 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ret: {
|
2007-06-18 21:13:21 +00:00
|
|
|
uint8_t index1 = codeBody(t, code, ip++);
|
|
|
|
uint8_t index2 = codeBody(t, code, ip++);
|
2007-05-31 00:29:07 +00:00
|
|
|
|
2007-07-06 01:06:06 +00:00
|
|
|
ip = localInt(t, (index1 << 8) | index2);
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-06-03 02:00:23 +00:00
|
|
|
default: abort(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
}
|
|
|
|
|
2007-07-06 01:06:06 +00:00
|
|
|
invoke: {
|
2007-06-24 19:57:00 +00:00
|
|
|
if (methodFlags(t, code) & ACC_NATIVE) {
|
2007-07-04 17:58:27 +00:00
|
|
|
invokeNative(t, code);
|
2007-07-07 18:09:16 +00:00
|
|
|
if (UNLIKELY(exception)) goto throw_;
|
2007-06-24 01:39:49 +00:00
|
|
|
} else {
|
2007-07-07 18:09:16 +00:00
|
|
|
checkStack(t, code);
|
|
|
|
if (UNLIKELY(exception)) goto throw_;
|
2007-06-25 02:20:35 +00:00
|
|
|
|
2007-07-06 01:06:06 +00:00
|
|
|
pushFrame(t, code);
|
2007-06-24 19:57:00 +00:00
|
|
|
}
|
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
|
|
|
throw_:
|
2007-07-12 00:06:57 +00:00
|
|
|
if (DebugRun) {
|
|
|
|
fprintf(stderr, "throw\n");
|
|
|
|
}
|
|
|
|
|
2007-07-08 01:06:32 +00:00
|
|
|
pokeInt(t, t->frame + FrameIpOffset, t->ip);
|
2007-07-06 01:06:06 +00:00
|
|
|
for (; frame >= 0; frame = frameNext(t, frame)) {
|
2007-07-07 18:09:16 +00:00
|
|
|
if (methodFlags(t, frameMethod(t, frame)) & ACC_NATIVE) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-06-08 14:23:04 +00:00
|
|
|
code = methodCode(t, frameMethod(t, frame));
|
|
|
|
object eht = codeExceptionHandlerTable(t, code);
|
2007-05-25 14:48:07 +00:00
|
|
|
if (eht) {
|
2007-06-06 02:24:09 +00:00
|
|
|
for (unsigned i = 0; i < exceptionHandlerTableLength(t, eht); ++i) {
|
|
|
|
ExceptionHandler* eh = exceptionHandlerTableBody(t, eht, i);
|
2007-07-12 00:06:57 +00:00
|
|
|
|
2007-07-08 01:06:32 +00:00
|
|
|
if (frameIp(t, frame) - 1 >= exceptionHandlerStart(eh)
|
|
|
|
and frameIp(t, frame) - 1 < exceptionHandlerEnd(eh))
|
2007-05-25 14:48:07 +00:00
|
|
|
{
|
2007-07-05 02:44:01 +00:00
|
|
|
object catchType = 0;
|
|
|
|
if (exceptionHandlerCatchType(eh)) {
|
|
|
|
catchType = arrayBody
|
|
|
|
(t, codePool(t, code), exceptionHandlerCatchType(eh) - 1);
|
|
|
|
}
|
|
|
|
|
2007-07-12 00:06:57 +00:00
|
|
|
if (catchType) {
|
|
|
|
catchType = resolveClass(t, catchType);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (catchType == 0 or instanceOf(t, catchType, exception)) {
|
2007-07-10 23:32:03 +00:00
|
|
|
sp = frame + FrameFootprint;
|
2007-07-05 02:44:01 +00:00
|
|
|
ip = exceptionHandlerIp(eh);
|
|
|
|
pushObject(t, exception);
|
|
|
|
exception = 0;
|
|
|
|
goto loop;
|
|
|
|
}
|
2007-05-21 15:47:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-06-24 19:57:00 +00:00
|
|
|
for (object e = exception; e; e = throwableCause(t, e)) {
|
|
|
|
if (e == exception) {
|
|
|
|
fprintf(stderr, "uncaught exception: ");
|
|
|
|
} else {
|
|
|
|
fprintf(stderr, "caused by: ");
|
2007-06-21 01:38:02 +00:00
|
|
|
}
|
|
|
|
|
2007-06-24 19:57:00 +00:00
|
|
|
fprintf(stderr, "%s", &byteArrayBody
|
2007-07-01 21:34:22 +00:00
|
|
|
(t, className(t, objectClass(t, exception)), 0));
|
2007-06-24 19:57:00 +00:00
|
|
|
|
|
|
|
if (throwableMessage(t, exception)) {
|
2007-06-30 02:45:45 +00:00
|
|
|
object m = throwableMessage(t, exception);
|
|
|
|
char message[stringLength(t, m) + 1];
|
2007-07-08 01:06:32 +00:00
|
|
|
stringChars(t, m, message);
|
2007-06-30 02:45:45 +00:00
|
|
|
fprintf(stderr, ": %s\n", message);
|
2007-06-30 01:37:45 +00:00
|
|
|
} else {
|
|
|
|
fprintf(stderr, "\n");
|
2007-06-24 19:57:00 +00:00
|
|
|
}
|
2007-06-21 01:38:02 +00:00
|
|
|
|
2007-06-30 01:37:45 +00:00
|
|
|
object trace = throwableTrace(t, e);
|
2007-07-14 17:31:01 +00:00
|
|
|
for (unsigned i = 0; i < arrayLength(t, trace); ++i) {
|
|
|
|
object e = arrayBody(t, trace, i);
|
2007-06-30 01:37:45 +00:00
|
|
|
const int8_t* class_ = &byteArrayBody
|
2007-07-14 18:37:04 +00:00
|
|
|
(t, className(t, methodClass(t, traceElementMethod(t, e))), 0);
|
2007-06-30 01:37:45 +00:00
|
|
|
const int8_t* method = &byteArrayBody
|
2007-07-14 18:37:04 +00:00
|
|
|
(t, methodName(t, traceElementMethod(t, e)), 0);
|
|
|
|
int line = lineNumber(t, traceElementMethod(t, e), traceElementIp(t, e));
|
2007-06-30 01:37:45 +00:00
|
|
|
|
2007-07-01 21:34:22 +00:00
|
|
|
fprintf(stderr, " at %s.%s ", class_, method);
|
2007-06-30 01:37:45 +00:00
|
|
|
|
|
|
|
switch (line) {
|
|
|
|
case NativeLine:
|
|
|
|
fprintf(stderr, "(native)\n");
|
|
|
|
break;
|
|
|
|
case UnknownLine:
|
2007-07-01 21:34:22 +00:00
|
|
|
fprintf(stderr, "(unknown line)\n");
|
2007-06-30 01:37:45 +00:00
|
|
|
break;
|
|
|
|
default:
|
2007-07-01 21:34:22 +00:00
|
|
|
fprintf(stderr, "(line %d)\n", line);
|
2007-06-30 01:37:45 +00:00
|
|
|
}
|
2007-06-21 01:38:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-06-24 19:57:00 +00:00
|
|
|
return 0;
|
2007-05-21 15:47:44 +00:00
|
|
|
}
|
|
|
|
|
2007-06-18 21:13:21 +00:00
|
|
|
void
|
|
|
|
run(Thread* t, const char* className, int argc, const char** argv)
|
2007-07-07 18:09:16 +00:00
|
|
|
{
|
|
|
|
object args = makeObjectArray
|
|
|
|
(t, arrayBody(t, t->vm->types, Machine::StringType), argc, true);
|
|
|
|
|
|
|
|
PROTECT(t, args);
|
|
|
|
|
|
|
|
for (int i = 0; i < argc; ++i) {
|
|
|
|
object arg = makeString(t, "%s", argv);
|
|
|
|
set(t, objectArrayBody(t, args, i), arg);
|
|
|
|
}
|
|
|
|
|
|
|
|
run(t, className, "main", "([Ljava/lang/String;)V", args);
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
namespace vm {
|
|
|
|
|
|
|
|
object
|
|
|
|
run(Thread* t, const char* className, const char* methodName,
|
|
|
|
const char* methodSpec, ...)
|
2007-06-18 21:13:21 +00:00
|
|
|
{
|
2007-06-21 18:35:24 +00:00
|
|
|
enter(t, Thread::ActiveState);
|
|
|
|
|
2007-06-18 21:13:21 +00:00
|
|
|
object class_ = resolveClass(t, makeByteArray(t, "%s", className));
|
|
|
|
if (LIKELY(t->exception == 0)) {
|
|
|
|
PROTECT(t, class_);
|
|
|
|
|
2007-07-07 18:09:16 +00:00
|
|
|
object name = makeByteArray(t, methodName);
|
2007-06-18 21:13:21 +00:00
|
|
|
PROTECT(t, name);
|
|
|
|
|
2007-07-07 18:09:16 +00:00
|
|
|
object spec = makeByteArray(t, methodSpec);
|
2007-06-18 21:13:21 +00:00
|
|
|
object reference = makeReference(t, class_, name, spec);
|
|
|
|
|
|
|
|
object method = findMethodInClass(t, class_, reference);
|
|
|
|
if (LIKELY(t->exception == 0)) {
|
2007-07-07 18:09:16 +00:00
|
|
|
va_list a;
|
|
|
|
va_start(a, methodSpec);
|
2007-06-21 19:43:33 +00:00
|
|
|
|
2007-07-07 18:09:16 +00:00
|
|
|
if ((methodFlags(t, method) & ACC_STATIC) == 0) {
|
|
|
|
pushObject(t, va_arg(a, object));
|
|
|
|
}
|
2007-06-18 21:13:21 +00:00
|
|
|
|
2007-07-07 18:09:16 +00:00
|
|
|
const char* s = methodSpec;
|
|
|
|
++ s; // skip '('
|
|
|
|
while (*s and *s != ')') {
|
|
|
|
switch (*s) {
|
|
|
|
case 'L':
|
|
|
|
while (*s and *s != ';') ++ s;
|
|
|
|
++ s;
|
|
|
|
pushObject(t, va_arg(a, object));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '[':
|
|
|
|
while (*s == '[') ++ s;
|
|
|
|
switch (*s) {
|
|
|
|
case 'L':
|
|
|
|
while (*s and *s != ';') ++ s;
|
|
|
|
++ s;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
++ s;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
pushObject(t, va_arg(a, object));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'J':
|
|
|
|
case 'D':
|
|
|
|
++ s;
|
|
|
|
pushLong(t, va_arg(a, uint64_t));
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
++ s;
|
|
|
|
pushInt(t, va_arg(a, uint32_t));
|
|
|
|
break;
|
|
|
|
}
|
2007-06-18 21:13:21 +00:00
|
|
|
}
|
|
|
|
|
2007-07-07 18:09:16 +00:00
|
|
|
va_end(a);
|
|
|
|
|
|
|
|
if (methodFlags(t, method) & ACC_NATIVE) {
|
|
|
|
unsigned returnCode = invokeNative(t, method);
|
|
|
|
|
|
|
|
if (LIKELY(t->exception == 0)) {
|
|
|
|
switch (returnCode) {
|
|
|
|
case ByteField:
|
|
|
|
case BooleanField:
|
|
|
|
case CharField:
|
|
|
|
case ShortField:
|
|
|
|
case FloatField:
|
|
|
|
case IntField:
|
|
|
|
return makeInt(t, popInt(t));
|
|
|
|
|
|
|
|
case LongField:
|
|
|
|
case DoubleField:
|
|
|
|
return makeLong(t, popLong(t));
|
|
|
|
|
|
|
|
case ObjectField:
|
|
|
|
return popObject(t);
|
|
|
|
|
|
|
|
case VoidField:
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
default:
|
|
|
|
abort(t);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
checkStack(t, method);
|
|
|
|
if (LIKELY(t->exception == 0)) {
|
|
|
|
pushFrame(t, method);
|
|
|
|
}
|
|
|
|
}
|
2007-06-18 21:13:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-07-07 18:09:16 +00:00
|
|
|
return ::run(t);
|
2007-06-18 21:13:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2007-06-20 16:58:35 +00:00
|
|
|
run(System* system, Heap* heap, ClassFinder* classFinder,
|
2007-06-18 21:13:21 +00:00
|
|
|
const char* className, int argc, const char** argv)
|
|
|
|
{
|
2007-06-20 16:58:35 +00:00
|
|
|
Machine m(system, heap, classFinder);
|
2007-07-07 18:09:16 +00:00
|
|
|
Thread t(&m, 0, 0, 0);
|
2007-06-18 21:13:21 +00:00
|
|
|
|
2007-07-14 17:31:01 +00:00
|
|
|
enter(&t, Thread::ActiveState);
|
|
|
|
|
2007-07-06 15:24:06 +00:00
|
|
|
::run(&t, className, argc, argv);
|
2007-07-07 18:09:16 +00:00
|
|
|
|
|
|
|
exit(&t);
|
2007-06-18 21:13:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|