2007-06-03 02:00:23 +00:00
|
|
|
#include "common.h"
|
|
|
|
#include "system.h"
|
|
|
|
#include "heap.h"
|
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
#define PROTECT(thread, name) \
|
|
|
|
Thread::Protector MAKE_NAME(protector_) (thread, &name);
|
2007-06-07 00:30:16 +00:00
|
|
|
|
2007-05-21 15:47:44 +00:00
|
|
|
namespace {
|
|
|
|
|
2007-06-03 02:00:23 +00:00
|
|
|
typedef void* object;
|
2007-06-05 00:28:52 +00:00
|
|
|
typedef unsigned Type;
|
|
|
|
|
2007-06-06 00:41:04 +00:00
|
|
|
#include "constants.h"
|
2007-06-05 00:28:52 +00:00
|
|
|
|
|
|
|
enum ObjectType {
|
|
|
|
NullType,
|
|
|
|
CollectedType,
|
|
|
|
|
|
|
|
#include "type-enums.h"
|
|
|
|
|
|
|
|
OtherType
|
|
|
|
};
|
2007-06-03 02:00:23 +00:00
|
|
|
|
|
|
|
class Thread;
|
|
|
|
|
2007-06-05 00:28:52 +00:00
|
|
|
Type typeOf(object);
|
|
|
|
object& objectClass(object);
|
|
|
|
void assert(Thread* t, bool v);
|
|
|
|
|
|
|
|
#include "type-header.h"
|
|
|
|
|
2007-06-03 02:00:23 +00:00
|
|
|
class Machine {
|
|
|
|
public:
|
|
|
|
System* sys;
|
|
|
|
Heap* heap;
|
|
|
|
Thread* rootThread;
|
|
|
|
Thread* exclusive;
|
|
|
|
unsigned activeCount;
|
|
|
|
unsigned liveCount;
|
|
|
|
System::Monitor* stateLock;
|
2007-06-08 14:23:04 +00:00
|
|
|
System::Monitor* heapLock;
|
2007-06-07 00:30:16 +00:00
|
|
|
object jstringClass;
|
2007-06-03 02:00:23 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class Thread {
|
|
|
|
public:
|
|
|
|
enum State {
|
|
|
|
NoState,
|
|
|
|
ActiveState,
|
|
|
|
IdleState,
|
|
|
|
ZombieState,
|
|
|
|
ExclusiveState,
|
|
|
|
ExitState
|
|
|
|
};
|
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
class Protector {
|
|
|
|
public:
|
|
|
|
Protector(Thread* t, object* p): t(t), p(p), next(t->protector) {
|
|
|
|
t->protector = this;
|
|
|
|
}
|
|
|
|
|
|
|
|
~Protector() {
|
|
|
|
t->protector = next;
|
|
|
|
}
|
|
|
|
|
|
|
|
Thread* t;
|
|
|
|
object* p;
|
|
|
|
Protector* next;
|
|
|
|
};
|
|
|
|
|
2007-06-03 02:00:23 +00:00
|
|
|
static const unsigned HeapSize = 64 * 1024;
|
|
|
|
static const unsigned StackSize = 64 * 1024;
|
|
|
|
|
|
|
|
Machine* vm;
|
|
|
|
Thread* next;
|
|
|
|
Thread* child;
|
|
|
|
State state;
|
|
|
|
object frame;
|
|
|
|
object code;
|
|
|
|
object exception;
|
2007-06-08 14:23:04 +00:00
|
|
|
unsigned ip;
|
2007-06-03 02:00:23 +00:00
|
|
|
unsigned sp;
|
|
|
|
unsigned heapIndex;
|
|
|
|
object stack[StackSize];
|
|
|
|
object heap[HeapSize];
|
2007-06-08 00:23:12 +00:00
|
|
|
Protector* protector;
|
2007-06-03 02:00:23 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
inline void NO_RETURN
|
|
|
|
abort(Thread* t)
|
|
|
|
{
|
|
|
|
t->vm->sys->abort();
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void
|
|
|
|
assert(Thread* t, bool v)
|
|
|
|
{
|
|
|
|
if (UNLIKELY(not v)) abort(t);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
init(Machine* m, System* sys, Heap* heap)
|
|
|
|
{
|
2007-06-07 00:30:16 +00:00
|
|
|
memset(m, 0, sizeof(Machine));
|
2007-06-03 02:00:23 +00:00
|
|
|
m->sys = sys;
|
|
|
|
m->heap = heap;
|
2007-06-08 14:23:04 +00:00
|
|
|
|
|
|
|
if (not sys->success(sys->make(&(m->stateLock))) or
|
|
|
|
not sys->success(sys->make(&(m->heapLock))))
|
|
|
|
{
|
2007-06-03 02:00:23 +00:00
|
|
|
sys->abort();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dispose(Machine* m)
|
|
|
|
{
|
|
|
|
m->stateLock->dispose();
|
2007-06-08 14:23:04 +00:00
|
|
|
m->heapLock->dispose();
|
2007-06-03 02:00:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
init(Thread* t, Machine* m)
|
|
|
|
{
|
2007-06-07 00:30:16 +00:00
|
|
|
memset(m, 0, sizeof(Thread));
|
2007-06-03 02:00:23 +00:00
|
|
|
t->vm = m;
|
|
|
|
m->rootThread = t;
|
|
|
|
t->state = Thread::NoState;
|
|
|
|
}
|
|
|
|
|
2007-06-02 00:06:06 +00:00
|
|
|
void
|
|
|
|
iterate(Thread* t, Heap::Visitor* v)
|
|
|
|
{
|
2007-06-03 02:00:23 +00:00
|
|
|
t->heapIndex = 0;
|
|
|
|
|
2007-06-02 00:06:06 +00:00
|
|
|
v->visit(&(t->frame));
|
|
|
|
v->visit(&(t->code));
|
|
|
|
v->visit(&(t->exception));
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < t->sp; ++i) {
|
|
|
|
v->visit(t->stack + t->sp);
|
|
|
|
}
|
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
for (Thread::Protector* p = t->protector; p; p = p->next) {
|
|
|
|
v->visit(p->p);
|
|
|
|
}
|
|
|
|
|
2007-06-02 00:06:06 +00:00
|
|
|
for (Thread* t = t->child; t; t = t->next) {
|
|
|
|
iterate(t, v);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
collect(Machine* m, Heap::CollectionType type)
|
|
|
|
{
|
2007-06-05 00:28:52 +00:00
|
|
|
class Iterator: public Heap::Iterator {
|
2007-06-02 00:06:06 +00:00
|
|
|
public:
|
|
|
|
Iterator(Machine* m): machine(m) { }
|
|
|
|
|
|
|
|
void iterate(Heap::Visitor* v) {
|
2007-06-05 00:28:52 +00:00
|
|
|
for (Thread* t = machine->rootThread; t; t = t->next) {
|
2007-06-02 00:06:06 +00:00
|
|
|
::iterate(t, v);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
Machine* machine;
|
|
|
|
} it(m);
|
|
|
|
|
2007-06-03 02:00:23 +00:00
|
|
|
m->heap->collect(type, &it);
|
2007-06-02 00:06:06 +00:00
|
|
|
}
|
|
|
|
|
2007-06-03 02:00:23 +00:00
|
|
|
void
|
|
|
|
enter(Thread* t, Thread::State s)
|
2007-06-02 00:06:06 +00:00
|
|
|
{
|
2007-06-05 00:28:52 +00:00
|
|
|
if (s == t->state) return;
|
2007-06-02 00:06:06 +00:00
|
|
|
|
2007-06-03 02:00:23 +00:00
|
|
|
ACQUIRE(t->vm->stateLock);
|
2007-06-02 00:06:06 +00:00
|
|
|
|
2007-06-03 02:00:23 +00:00
|
|
|
switch (s) {
|
2007-06-05 00:28:52 +00:00
|
|
|
case Thread::ExclusiveState: {
|
|
|
|
assert(t, t->state == Thread::ActiveState);
|
2007-06-02 00:06:06 +00:00
|
|
|
|
|
|
|
while (t->vm->exclusive) {
|
2007-06-03 02:00:23 +00:00
|
|
|
// another thread got here first.
|
|
|
|
enter(t, Thread::IdleState);
|
|
|
|
enter(t, Thread::ActiveState);
|
2007-06-02 00:06:06 +00:00
|
|
|
}
|
|
|
|
|
2007-06-05 00:28:52 +00:00
|
|
|
t->state = Thread::ExclusiveState;
|
2007-06-02 00:06:06 +00:00
|
|
|
t->vm->exclusive = t;
|
2007-06-03 02:00:23 +00:00
|
|
|
|
2007-06-02 00:06:06 +00:00
|
|
|
while (t->vm->activeCount > 1) {
|
|
|
|
t->vm->stateLock->wait();
|
|
|
|
}
|
2007-06-03 02:00:23 +00:00
|
|
|
} break;
|
2007-06-02 00:06:06 +00:00
|
|
|
|
2007-06-05 00:28:52 +00:00
|
|
|
case Thread::IdleState:
|
|
|
|
case Thread::ZombieState: {
|
|
|
|
switch (t->state) {
|
|
|
|
case Thread::ExclusiveState: {
|
2007-06-03 02:00:23 +00:00
|
|
|
assert(t, t->vm->exclusive == t);
|
|
|
|
t->vm->exclusive = 0;
|
|
|
|
} break;
|
|
|
|
|
2007-06-05 00:28:52 +00:00
|
|
|
case Thread::ActiveState: break;
|
2007-06-03 02:00:23 +00:00
|
|
|
|
|
|
|
default: abort(t);
|
|
|
|
}
|
|
|
|
|
|
|
|
-- t->vm->activeCount;
|
2007-06-05 00:28:52 +00:00
|
|
|
if (s == Thread::ZombieState) {
|
2007-06-03 02:00:23 +00:00
|
|
|
-- t->vm->liveCount;
|
|
|
|
}
|
|
|
|
t->state = s;
|
2007-06-02 00:06:06 +00:00
|
|
|
|
|
|
|
t->vm->stateLock->notifyAll();
|
2007-06-03 02:00:23 +00:00
|
|
|
} break;
|
|
|
|
|
2007-06-05 00:28:52 +00:00
|
|
|
case Thread::ActiveState: {
|
|
|
|
switch (t->state) {
|
|
|
|
case Thread::ExclusiveState: {
|
2007-06-03 02:00:23 +00:00
|
|
|
assert(t, t->vm->exclusive == t);
|
|
|
|
|
|
|
|
t->state = s;
|
|
|
|
t->vm->exclusive = 0;
|
|
|
|
|
|
|
|
t->vm->stateLock->notifyAll();
|
|
|
|
} break;
|
|
|
|
|
2007-06-05 00:28:52 +00:00
|
|
|
case Thread::NoState:
|
|
|
|
case Thread::IdleState: {
|
2007-06-03 02:00:23 +00:00
|
|
|
while (t->vm->exclusive) {
|
|
|
|
t->vm->stateLock->wait();
|
|
|
|
}
|
|
|
|
|
|
|
|
++ t->vm->activeCount;
|
2007-06-05 00:28:52 +00:00
|
|
|
if (t->state == Thread::NoState) {
|
2007-06-03 02:00:23 +00:00
|
|
|
++ t->vm->liveCount;
|
|
|
|
}
|
|
|
|
t->state = s;
|
|
|
|
} break;
|
|
|
|
|
|
|
|
default: abort(t);
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
2007-06-05 00:28:52 +00:00
|
|
|
case Thread::ExitState: {
|
|
|
|
switch (t->state) {
|
|
|
|
case Thread::ExclusiveState: {
|
2007-06-03 02:00:23 +00:00
|
|
|
assert(t, t->vm->exclusive == t);
|
|
|
|
t->vm->exclusive = 0;
|
|
|
|
} break;
|
|
|
|
|
2007-06-05 00:28:52 +00:00
|
|
|
case Thread::ActiveState: break;
|
2007-06-03 02:00:23 +00:00
|
|
|
|
|
|
|
default: abort(t);
|
|
|
|
}
|
|
|
|
|
|
|
|
-- t->vm->activeCount;
|
|
|
|
t->state = s;
|
|
|
|
|
|
|
|
while (t->vm->liveCount > 1) {
|
|
|
|
t->vm->stateLock->wait();
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
|
|
|
default: abort(t);
|
2007-06-02 00:06:06 +00:00
|
|
|
}
|
2007-06-03 02:00:23 +00:00
|
|
|
}
|
2007-06-02 00:06:06 +00:00
|
|
|
|
2007-06-03 02:00:23 +00:00
|
|
|
void
|
|
|
|
maybeYieldAndMaybeCollect(Thread* t, unsigned size)
|
|
|
|
{
|
|
|
|
if (size > Thread::HeapSize) {
|
|
|
|
// large object support not yet implemented.
|
|
|
|
abort(t);
|
|
|
|
}
|
|
|
|
|
|
|
|
ACQUIRE(t->vm->stateLock);
|
|
|
|
|
|
|
|
while (t->vm->exclusive) {
|
|
|
|
// another thread wants to enter the exclusive state, either for a
|
|
|
|
// collection or some other reason. We give it a chance here.
|
|
|
|
enter(t, Thread::IdleState);
|
|
|
|
enter(t, Thread::ActiveState);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (t->heapIndex + size >= Thread::HeapSize) {
|
|
|
|
enter(t, Thread::ExclusiveState);
|
|
|
|
collect(t->vm, Heap::MinorCollection);
|
|
|
|
enter(t, Thread::ActiveState);
|
|
|
|
}
|
2007-06-02 00:06:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
inline object
|
|
|
|
allocate(Thread* t, unsigned size)
|
|
|
|
{
|
2007-06-03 02:00:23 +00:00
|
|
|
if (UNLIKELY(t->heapIndex + size >= Thread::HeapSize
|
2007-06-02 00:06:06 +00:00
|
|
|
or t->vm->exclusive))
|
|
|
|
{
|
2007-06-03 02:00:23 +00:00
|
|
|
maybeYieldAndMaybeCollect(t, size);
|
2007-06-02 00:06:06 +00:00
|
|
|
}
|
2007-06-03 02:00:23 +00:00
|
|
|
|
|
|
|
object o = t->heap + t->heapIndex;
|
|
|
|
t->heapIndex += size;
|
|
|
|
return o;
|
2007-06-02 00:06:06 +00:00
|
|
|
}
|
|
|
|
|
2007-06-08 14:23:04 +00:00
|
|
|
inline void
|
|
|
|
set(Thread* t, object& target, object value)
|
|
|
|
{
|
|
|
|
target = value;
|
|
|
|
t->vm->heap->check(&target, t->vm->heapLock);
|
|
|
|
}
|
|
|
|
|
2007-06-04 13:12:22 +00:00
|
|
|
inline void
|
|
|
|
push(Thread* t, object o)
|
|
|
|
{
|
|
|
|
t->stack[(t->sp)++] = o;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline object
|
|
|
|
pop(Thread* t)
|
|
|
|
{
|
|
|
|
return t->stack[--(t->sp)];
|
|
|
|
}
|
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
inline object&
|
|
|
|
top(Thread* t)
|
|
|
|
{
|
|
|
|
return t->stack[t->sp - 1];
|
|
|
|
}
|
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-07 00:30:16 +00:00
|
|
|
unsigned size = classFixedSize(t, class_);
|
|
|
|
object instance = allocate(t, size);
|
|
|
|
*static_cast<object*>(instance) = class_;
|
|
|
|
memset(static_cast<object*>(instance) + sizeof(object), 0,
|
|
|
|
size - sizeof(object));
|
|
|
|
return instance;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
inline T&
|
|
|
|
cast(object p, unsigned offset)
|
|
|
|
{
|
|
|
|
return *reinterpret_cast<T*>(static_cast<uint8_t*>(p) + offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
object
|
2007-06-08 00:23:12 +00:00
|
|
|
makeString(Thread* t, const char* format, ...)
|
2007-06-07 00:30:16 +00:00
|
|
|
{
|
|
|
|
static const unsigned Size = 256;
|
|
|
|
char buffer[Size];
|
|
|
|
|
|
|
|
va_list a;
|
|
|
|
va_start(a, format);
|
2007-06-08 14:23:04 +00:00
|
|
|
vsnprintf(buffer, Size - 1, format, a);
|
2007-06-07 00:30:16 +00:00
|
|
|
va_end(a);
|
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
object s = makeByteArray(t, strlen(buffer) + 1);
|
|
|
|
memcpy(byteArrayBody(t, s), buffer, byteArrayLength(t, s));
|
|
|
|
|
|
|
|
return makeString(t, s, 0, byteArrayLength(t, s), 0);
|
|
|
|
}
|
2007-06-07 00:30:16 +00:00
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
object
|
|
|
|
makeTrace(Thread* t)
|
|
|
|
{
|
|
|
|
object trace = 0;
|
|
|
|
PROTECT(t, trace);
|
2007-06-08 14:23:04 +00:00
|
|
|
frameIp(t, t->frame) = t->ip;
|
2007-06-08 00:23:12 +00:00
|
|
|
for (; t->frame; t->frame = frameNext(t, t->frame)) {
|
|
|
|
trace = makeTrace
|
|
|
|
(t, frameMethod(t, t->frame), frameIp(t, t->frame), trace);
|
|
|
|
}
|
|
|
|
return trace;
|
|
|
|
}
|
|
|
|
|
|
|
|
object
|
|
|
|
makeArrayIndexOutOfBoundsException(Thread* t, object message)
|
|
|
|
{
|
|
|
|
PROTECT(t, message);
|
|
|
|
object trace = makeTrace(t);
|
|
|
|
return makeArrayIndexOutOfBoundsException(t, message, trace);
|
|
|
|
}
|
|
|
|
|
|
|
|
object
|
|
|
|
makeNegativeArrayStoreException(Thread* t, object message)
|
|
|
|
{
|
|
|
|
PROTECT(t, message);
|
|
|
|
object trace = makeTrace(t);
|
|
|
|
return makeNegativeArrayStoreException(t, message, trace);
|
|
|
|
}
|
|
|
|
|
|
|
|
object
|
|
|
|
makeClassCastException(Thread* t, object message)
|
|
|
|
{
|
|
|
|
PROTECT(t, message);
|
|
|
|
object trace = makeTrace(t);
|
|
|
|
return makeArrayIndexOutOfBoundsException(t, message, trace);
|
|
|
|
}
|
|
|
|
|
|
|
|
object
|
|
|
|
makeNullPointerException(Thread* t)
|
|
|
|
{
|
|
|
|
return makeNullPointerException(t, 0, makeTrace(t));
|
|
|
|
}
|
|
|
|
|
|
|
|
object
|
|
|
|
makeStackOverflowError(Thread* t)
|
|
|
|
{
|
|
|
|
return makeStackOverflowError(t, 0, makeTrace(t));
|
2007-06-07 00:30:16 +00:00
|
|
|
}
|
|
|
|
|
2007-06-09 02:29:56 +00:00
|
|
|
inline bool
|
|
|
|
isLongOrDouble(object o)
|
|
|
|
{
|
|
|
|
return typeOf(o) == LongType or typeOf(o) == DoubleType;
|
|
|
|
}
|
|
|
|
|
2007-06-11 23:40:24 +00:00
|
|
|
inline object
|
|
|
|
getField(Thread* t, object instance, object field)
|
|
|
|
{
|
|
|
|
return cast<object>(instance, fieldOffset(t, field) * sizeof(object));
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void
|
|
|
|
setField(Thread* t, object o, object field, object value)
|
|
|
|
{
|
|
|
|
set(t, cast<object>(o, fieldOffset(t, field) * sizeof(object)), value);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline object
|
|
|
|
getStatic(Thread* t, object field)
|
|
|
|
{
|
|
|
|
return rawArrayBody(t, classStaticTable(t, fieldClass(t, field)))
|
|
|
|
[fieldOffset(t, field)];
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void
|
|
|
|
setStatic(Thread* t, object field, object value)
|
|
|
|
{
|
|
|
|
set(t, rawArrayBody(t, classStaticTable(t, fieldClass(t, field)))
|
|
|
|
[fieldOffset(t, field)], value);
|
|
|
|
}
|
|
|
|
|
2007-06-09 02:29:56 +00:00
|
|
|
bool
|
|
|
|
instanceOf(Thread* t, object class_, object o)
|
|
|
|
{
|
|
|
|
if (o == 0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (typeOf(class_) == InterfaceType) {
|
|
|
|
Type id = interfaceId(t, class_);
|
|
|
|
for (object oc = objectClass(o); oc; oc = classSuper(t, oc)) {
|
|
|
|
object itable = classInterfaceTable(t, oc);
|
|
|
|
for (unsigned i = 0; i < rawArrayLength(t, itable); i += 2) {
|
|
|
|
if (interfaceId(t, rawArrayBody(t, itable)[i]) == id) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Type id = classId(t, class_);
|
|
|
|
for (object oc = objectClass(o); oc; oc = classSuper(t, oc)) {
|
|
|
|
if (classId(t, oc) == id) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2007-06-11 23:40:24 +00:00
|
|
|
object
|
|
|
|
findInterfaceMethod(Thread* t, object method, object o)
|
|
|
|
{
|
|
|
|
Type id = interfaceId(t, methodClass(t, method));
|
|
|
|
object itable = classInterfaceTable(t, objectClass(o));
|
|
|
|
for (unsigned i = 0; i < rawArrayLength(t, itable); i += 2) {
|
|
|
|
if (interfaceId(t, rawArrayBody(t, itable)[i]) == id) {
|
|
|
|
return rawArrayBody(t, rawArrayBody(t, itable)[i + 1])
|
|
|
|
[methodOffset(t, method)];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
abort(t);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline object
|
|
|
|
findVirtualMethod(Thread* t, object method, object o)
|
|
|
|
{
|
|
|
|
return rawArrayBody(t, classMethodTable(t, objectClass(o)))
|
|
|
|
[methodOffset(t, method)];
|
|
|
|
}
|
|
|
|
|
2007-05-21 15:47:44 +00:00
|
|
|
object
|
|
|
|
run(Thread* t)
|
|
|
|
{
|
2007-06-08 14:23:04 +00:00
|
|
|
unsigned& ip = t->ip;
|
|
|
|
unsigned& sp = t->sp;
|
|
|
|
object& code = t->code;
|
|
|
|
object& frame = t->frame;
|
|
|
|
object& exception = t->exception;
|
|
|
|
object* stack = t->stack;
|
2007-05-30 00:08:10 +00:00
|
|
|
unsigned parameterCount = 0;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
|
|
|
loop:
|
2007-06-08 14:23:04 +00:00
|
|
|
switch (codeBody(t, code)[ip++]) {
|
2007-05-21 15:47:44 +00:00
|
|
|
case aaload: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object index = pop(t);
|
|
|
|
object array = pop(t);
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(array)) {
|
2007-06-05 00:28:52 +00:00
|
|
|
int32_t i = intValue(t, index);
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(i >= 0 and
|
|
|
|
static_cast<uint32_t>(i) < objectArrayLength(t, array)))
|
|
|
|
{
|
2007-06-05 00:28:52 +00:00
|
|
|
push(t, objectArrayBody(t, array)[i]);
|
2007-05-21 15:47:44 +00:00
|
|
|
} else {
|
2007-06-08 00:23:12 +00:00
|
|
|
object message = makeString(t, "%d not in [0,%d]", i,
|
|
|
|
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-06-04 13:12:22 +00:00
|
|
|
object value = pop(t);
|
|
|
|
object index = pop(t);
|
|
|
|
object array = pop(t);
|
2007-06-05 00:28:52 +00:00
|
|
|
int32_t i = intValue(t, index);
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(array)) {
|
|
|
|
if (LIKELY(i >= 0 and
|
|
|
|
static_cast<uint32_t>(i) < objectArrayLength(t, array)))
|
|
|
|
{
|
2007-06-06 00:41:04 +00:00
|
|
|
set(t, objectArrayBody(t, array)[i], value);
|
2007-05-21 15:47:44 +00:00
|
|
|
} else {
|
2007-06-08 00:23:12 +00:00
|
|
|
object message = makeString(t, "%d not in [0,%d]", i,
|
|
|
|
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-06-04 13:12:22 +00:00
|
|
|
push(t, 0);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-05-31 00:29:07 +00:00
|
|
|
case aload:
|
|
|
|
case iload:
|
|
|
|
case lload: {
|
2007-06-08 14:23:04 +00:00
|
|
|
push(t, frameLocals(t, frame)[codeBody(t, code)[ip++]]);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-05-31 00:29:07 +00:00
|
|
|
case aload_0:
|
|
|
|
case iload_0:
|
|
|
|
case lload_0: {
|
2007-06-08 14:23:04 +00:00
|
|
|
push(t, frameLocals(t, frame)[0]);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-05-31 00:29:07 +00:00
|
|
|
case aload_1:
|
|
|
|
case iload_1:
|
|
|
|
case lload_1: {
|
2007-06-08 14:23:04 +00:00
|
|
|
push(t, frameLocals(t, frame)[1]);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-05-31 00:29:07 +00:00
|
|
|
case aload_2:
|
|
|
|
case iload_2:
|
|
|
|
case lload_2: {
|
2007-06-08 14:23:04 +00:00
|
|
|
push(t, frameLocals(t, frame)[2]);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-05-31 00:29:07 +00:00
|
|
|
case aload_3:
|
|
|
|
case iload_3:
|
|
|
|
case lload_3: {
|
2007-06-08 14:23:04 +00:00
|
|
|
push(t, frameLocals(t, frame)[3]);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
|
|
|
case anewarray: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object count = pop(t);
|
2007-06-05 00:28:52 +00:00
|
|
|
int32_t c = intValue(t, count);
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(c >= 0)) {
|
2007-06-08 14:23:04 +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-08 14:23:04 +00:00
|
|
|
object class_ = resolveClass(t, codePool(t, code), index);
|
|
|
|
if (UNLIKELY(exception)) goto throw_;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
|
|
|
object array = makeObjectArray(t, class_, c);
|
2007-06-07 00:30:16 +00:00
|
|
|
memset(objectArrayBody(t, array), 0, c * 4);
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-06-04 13:12:22 +00:00
|
|
|
push(t, array);
|
2007-05-21 15:47:44 +00:00
|
|
|
} else {
|
2007-06-08 00:23:12 +00:00
|
|
|
object message = makeString(t, "%d", c);
|
2007-06-08 14:23:04 +00:00
|
|
|
exception = makeNegativeArrayStoreException(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-05-30 00:08:10 +00:00
|
|
|
case areturn:
|
|
|
|
case ireturn:
|
|
|
|
case lreturn: {
|
2007-06-08 14:23:04 +00:00
|
|
|
frame = frameNext(t, frame);
|
|
|
|
if (frame) {
|
|
|
|
code = methodCode(t, frameMethod(t, frame));
|
|
|
|
ip = frameIp(t, frame);
|
2007-05-21 15:47:44 +00:00
|
|
|
goto loop;
|
|
|
|
} else {
|
2007-06-04 13:12:22 +00:00
|
|
|
object value = pop(t);
|
2007-06-08 14:23:04 +00:00
|
|
|
code = 0;
|
2007-05-21 15:47:44 +00:00
|
|
|
return value;
|
|
|
|
}
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
|
|
|
case arraylength: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object array = pop(t);
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(array)) {
|
2007-06-06 00:41:04 +00:00
|
|
|
if (typeOf(array) == ObjectArrayType) {
|
|
|
|
push(t, makeInt(t, objectArrayLength(t, array)));
|
|
|
|
} else {
|
|
|
|
// for all other array types, the length follow the class pointer.
|
2007-06-07 00:30:16 +00:00
|
|
|
push(t, makeInt(t, cast<uint32_t>(array, sizeof(void*))));
|
2007-06-06 00:41:04 +00:00
|
|
|
}
|
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-06-03 02:00:23 +00:00
|
|
|
} abort(t);
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-05-30 00:08:10 +00:00
|
|
|
case astore:
|
|
|
|
case istore:
|
|
|
|
case lstore: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object value = pop(t);
|
2007-06-08 14:23:04 +00:00
|
|
|
set(t, frameLocals(t, frame)[codeBody(t, code)[ip++]], value);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-05-30 00:08:10 +00:00
|
|
|
case astore_0:
|
|
|
|
case istore_0:
|
|
|
|
case lstore_0: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object value = pop(t);
|
2007-06-08 14:23:04 +00:00
|
|
|
set(t, frameLocals(t, frame)[0], value);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-05-30 00:08:10 +00:00
|
|
|
case astore_1:
|
|
|
|
case istore_1:
|
|
|
|
case lstore_1: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object value = pop(t);
|
2007-06-08 14:23:04 +00:00
|
|
|
set(t, frameLocals(t, frame)[1], value);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-05-30 00:08:10 +00:00
|
|
|
case astore_2:
|
|
|
|
case istore_2:
|
|
|
|
case lstore_2: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object value = pop(t);
|
2007-06-08 14:23:04 +00:00
|
|
|
set(t, frameLocals(t, frame)[2], value);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
2007-05-30 00:08:10 +00:00
|
|
|
case astore_3:
|
|
|
|
case istore_3:
|
|
|
|
case lstore_3: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object value = pop(t);
|
2007-06-08 14:23:04 +00:00
|
|
|
set(t, frameLocals(t, frame)[3], value);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
|
|
|
case athrow: {
|
2007-06-08 14:23:04 +00:00
|
|
|
exception = pop(t);
|
|
|
|
if (UNLIKELY(exception == 0)) {
|
|
|
|
exception = makeNullPointerException(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
2007-05-21 15:47:44 +00:00
|
|
|
goto throw_;
|
2007-06-03 02:00:23 +00:00
|
|
|
} abort(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
|
|
|
case baload: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object index = pop(t);
|
|
|
|
object array = pop(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(array)) {
|
2007-06-05 00:28:52 +00:00
|
|
|
int32_t i = intValue(t, index);
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(i >= 0 and
|
|
|
|
static_cast<uint32_t>(i) < byteArrayLength(t, array)))
|
|
|
|
{
|
2007-06-06 00:41:04 +00:00
|
|
|
push(t, makeByte(t, byteArrayBody(t, array)[i]));
|
2007-05-22 00:05:29 +00:00
|
|
|
} else {
|
2007-06-08 00:23:12 +00:00
|
|
|
object message = makeString(t, "%d not in [0,%d]", i,
|
|
|
|
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-06-04 13:12:22 +00:00
|
|
|
object value = pop(t);
|
|
|
|
object index = pop(t);
|
|
|
|
object array = pop(t);
|
2007-06-05 00:28:52 +00:00
|
|
|
int32_t i = intValue(t, index);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(array)) {
|
|
|
|
if (LIKELY(i >= 0 and
|
|
|
|
static_cast<uint32_t>(i) < byteArrayLength(t, array)))
|
|
|
|
{
|
2007-06-06 00:41:04 +00:00
|
|
|
byteArrayBody(t, array)[i] = intValue(t, value);
|
2007-05-22 00:05:29 +00:00
|
|
|
} else {
|
2007-06-08 00:23:12 +00:00
|
|
|
object message = makeString(t, "%d not in [0,%d]", i,
|
|
|
|
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-06-08 14:23:04 +00:00
|
|
|
push(t, makeInt(t, codeBody(t, code)[ip++]));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case caload: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object index = pop(t);
|
|
|
|
object array = pop(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(array)) {
|
2007-06-05 00:28:52 +00:00
|
|
|
int32_t i = intValue(t, index);
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(i >= 0 and
|
|
|
|
static_cast<uint32_t>(i) < charArrayLength(t, array)))
|
|
|
|
{
|
2007-06-06 00:41:04 +00:00
|
|
|
push(t, makeInt(t, charArrayBody(t, array)[i]));
|
2007-05-22 00:05:29 +00:00
|
|
|
} else {
|
2007-06-08 00:23:12 +00:00
|
|
|
object message = makeString(t, "%d not in [0,%d]", i,
|
|
|
|
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-06-04 13:12:22 +00:00
|
|
|
object value = pop(t);
|
|
|
|
object index = pop(t);
|
|
|
|
object array = pop(t);
|
2007-06-05 00:28:52 +00:00
|
|
|
int32_t i = intValue(t, index);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(array)) {
|
|
|
|
if (LIKELY(i >= 0 and
|
|
|
|
static_cast<uint32_t>(i) < charArrayLength(t, array)))
|
|
|
|
{
|
2007-06-06 00:41:04 +00:00
|
|
|
charArrayBody(t, array)[i] = intValue(t, value);
|
2007-05-22 00:05:29 +00:00
|
|
|
} else {
|
2007-06-08 00:23:12 +00:00
|
|
|
object message = makeString(t, "%d not in [0,%d]", i,
|
|
|
|
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-08 14:23:04 +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-06-08 14:23:04 +00:00
|
|
|
if (stack[sp - 1]) {
|
2007-05-22 00:05:29 +00:00
|
|
|
uint16_t index = (index1 << 8) | index2;
|
|
|
|
|
2007-06-08 14:23:04 +00:00
|
|
|
object class_ = resolveClass(t, codePool(t, code), index);
|
|
|
|
if (UNLIKELY(exception)) goto throw_;
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-08 14:23:04 +00:00
|
|
|
if (not instanceOf(t, class_, stack[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",
|
|
|
|
byteArrayBody(t, className(t, objectClass(stack[sp - 1]))),
|
|
|
|
byteArrayBody(t, className(t, class_)));
|
|
|
|
exception = makeClassCastException(t, message);
|
2007-05-22 00:05:29 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case dup: {
|
2007-06-08 14:23:04 +00:00
|
|
|
object value = stack[sp - 1];
|
2007-06-04 13:12:22 +00:00
|
|
|
push(t, value);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case dup_x1: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object first = pop(t);
|
|
|
|
object second = pop(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-04 13:12:22 +00:00
|
|
|
push(t, first);
|
|
|
|
push(t, second);
|
|
|
|
push(t, first);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case dup_x2: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object first = pop(t);
|
|
|
|
object second = pop(t);
|
|
|
|
object third = pop(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-04 13:12:22 +00:00
|
|
|
push(t, first);
|
|
|
|
push(t, third);
|
|
|
|
push(t, second);
|
|
|
|
push(t, first);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case dup2: {
|
2007-06-08 14:23:04 +00:00
|
|
|
object first = stack[sp - 1];
|
2007-05-22 00:05:29 +00:00
|
|
|
if (isLongOrDouble(first)) {
|
2007-06-04 13:12:22 +00:00
|
|
|
push(t, first);
|
2007-05-22 00:05:29 +00:00
|
|
|
} else {
|
2007-06-08 14:23:04 +00:00
|
|
|
object second = stack[sp - 2];
|
2007-06-04 13:12:22 +00:00
|
|
|
push(t, second);
|
|
|
|
push(t, first);
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case dup2_x1: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object first = pop(t);
|
|
|
|
object second = pop(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
|
|
|
if (isLongOrDouble(first)) {
|
2007-06-04 13:12:22 +00:00
|
|
|
push(t, first);
|
|
|
|
push(t, second);
|
|
|
|
push(t, first);
|
2007-05-22 00:05:29 +00:00
|
|
|
} else {
|
2007-06-04 13:12:22 +00:00
|
|
|
object third = pop(t);
|
|
|
|
push(t, second);
|
|
|
|
push(t, first);
|
|
|
|
push(t, third);
|
|
|
|
push(t, second);
|
|
|
|
push(t, first);
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case dup2_x2: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object first = pop(t);
|
|
|
|
object second = pop(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
|
|
|
if (isLongOrDouble(first)) {
|
|
|
|
if (isLongOrDouble(second)) {
|
2007-06-04 13:12:22 +00:00
|
|
|
push(t, first);
|
|
|
|
push(t, second);
|
|
|
|
push(t, first);
|
2007-05-22 00:05:29 +00:00
|
|
|
} else {
|
2007-06-04 13:12:22 +00:00
|
|
|
object third = pop(t);
|
|
|
|
push(t, first);
|
|
|
|
push(t, third);
|
|
|
|
push(t, second);
|
|
|
|
push(t, first);
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
|
|
|
} else {
|
2007-06-04 13:12:22 +00:00
|
|
|
object third = pop(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
if (isLongOrDouble(third)) {
|
2007-06-04 13:12:22 +00:00
|
|
|
push(t, second);
|
|
|
|
push(t, first);
|
|
|
|
push(t, third);
|
|
|
|
push(t, second);
|
|
|
|
push(t, first);
|
2007-05-22 00:05:29 +00:00
|
|
|
} else {
|
2007-06-04 13:12:22 +00:00
|
|
|
object fourth = pop(t);
|
|
|
|
push(t, second);
|
|
|
|
push(t, first);
|
|
|
|
push(t, fourth);
|
|
|
|
push(t, third);
|
|
|
|
push(t, second);
|
|
|
|
push(t, first);
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case getfield: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object instance = pop(t);
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(instance)) {
|
2007-06-08 14:23:04 +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-08 14:23:04 +00:00
|
|
|
object field = resolveField(t, codePool(t, code), index);
|
|
|
|
if (UNLIKELY(exception)) goto throw_;
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-11 23:40:24 +00:00
|
|
|
push(t, getField(t, instance, field));
|
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-08 14:23:04 +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-08 14:23:04 +00:00
|
|
|
object field = resolveField(t, codePool(t, code), index);
|
|
|
|
if (UNLIKELY(exception)) goto throw_;
|
2007-05-25 14:48:07 +00:00
|
|
|
|
2007-06-11 23:40:24 +00:00
|
|
|
object p = classInitializers(t, fieldClass(t, field));
|
|
|
|
if (p) {
|
|
|
|
set(t, classInitializers(t, fieldClass(t, field)), pairSecond(t, p));
|
|
|
|
code = pairFirst(t, p);
|
2007-05-31 00:29:07 +00:00
|
|
|
ip -= 3;
|
|
|
|
parameterCount = 0;
|
|
|
|
goto invoke;
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
2007-05-31 00:29:07 +00:00
|
|
|
|
2007-06-11 23:40:24 +00:00
|
|
|
push(t, getStatic(t, field));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case goto_: {
|
2007-06-08 14:23:04 +00:00
|
|
|
uint8_t offset1 = codeBody(t, code)[ip++];
|
|
|
|
uint8_t offset2 = codeBody(t, code)[ip++];
|
2007-05-22 00:05:29 +00:00
|
|
|
|
|
|
|
ip = (ip - 1) + ((offset1 << 8) | offset2);
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case goto_w: {
|
2007-06-08 14:23:04 +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
|
|
|
|
|
|
|
ip = (ip - 1)
|
|
|
|
+ ((offset1 << 24) | (offset2 << 16) | (offset3 << 8) | offset4);
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case i2b: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object v = pop(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-05 00:28:52 +00:00
|
|
|
push(t, makeInt(t, static_cast<int8_t>(intValue(t, v))));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case i2c: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object v = pop(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-05 00:28:52 +00:00
|
|
|
push(t, makeInt(t, static_cast<uint16_t>(intValue(t, v))));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case i2l: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object v = pop(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-05 00:28:52 +00:00
|
|
|
push(t, makeLong(t, intValue(t, v)));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case i2s: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object v = pop(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-05 00:28:52 +00:00
|
|
|
push(t, makeInt(t, static_cast<int16_t>(intValue(t, v))));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iadd: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object b = pop(t);
|
|
|
|
object a = pop(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-05 00:28:52 +00:00
|
|
|
push(t, makeInt(t, intValue(t, a) + intValue(t, b)));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iaload: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object index = pop(t);
|
|
|
|
object array = pop(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(array)) {
|
2007-06-05 00:28:52 +00:00
|
|
|
int32_t i = intValue(t, index);
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(i >= 0 and
|
|
|
|
static_cast<uint32_t>(i) < intArrayLength(t, array)))
|
|
|
|
{
|
2007-06-06 00:41:04 +00:00
|
|
|
push(t, makeInt(t, intArrayBody(t, array)[i]));
|
2007-05-22 00:05:29 +00:00
|
|
|
} else {
|
2007-06-08 00:23:12 +00:00
|
|
|
object message = makeString(t, "%d not in [0,%d]", i,
|
|
|
|
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-06-04 13:12:22 +00:00
|
|
|
object b = pop(t);
|
|
|
|
object a = pop(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-05 00:28:52 +00:00
|
|
|
push(t, makeInt(t, intValue(t, a) & intValue(t, b)));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iastore: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object value = pop(t);
|
|
|
|
object index = pop(t);
|
|
|
|
object array = pop(t);
|
2007-06-05 00:28:52 +00:00
|
|
|
int32_t i = intValue(t, index);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(array)) {
|
|
|
|
if (LIKELY(i >= 0 and
|
|
|
|
static_cast<uint32_t>(i) < intArrayLength(t, array)))
|
|
|
|
{
|
2007-06-06 00:41:04 +00:00
|
|
|
intArrayBody(t, array)[i] = intValue(t, value);
|
2007-05-22 00:05:29 +00:00
|
|
|
} else {
|
2007-06-08 00:23:12 +00:00
|
|
|
object message = makeString(t, "%d not in [0,%d]", i,
|
|
|
|
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-06-06 00:41:04 +00:00
|
|
|
push(t, makeInt(t, 0));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iconst_1: {
|
2007-06-06 00:41:04 +00:00
|
|
|
push(t, makeInt(t, 1));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iconst_2: {
|
2007-06-06 00:41:04 +00:00
|
|
|
push(t, makeInt(t, 2));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iconst_3: {
|
2007-06-06 00:41:04 +00:00
|
|
|
push(t, makeInt(t, 3));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iconst_4: {
|
2007-06-06 00:41:04 +00:00
|
|
|
push(t, makeInt(t, 4));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iconst_5: {
|
2007-06-06 00:41:04 +00:00
|
|
|
push(t, makeInt(t, 5));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case idiv: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object b = pop(t);
|
|
|
|
object a = pop(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-05 00:28:52 +00:00
|
|
|
push(t, makeInt(t, intValue(t, a) / intValue(t, b)));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case if_acmpeq: {
|
2007-06-08 14:23:04 +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-04 13:12:22 +00:00
|
|
|
object b = pop(t);
|
|
|
|
object a = pop(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
|
|
|
if (a == b) {
|
|
|
|
ip = (ip - 1) + ((offset1 << 8) | offset2);
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case if_acmpne: {
|
2007-06-08 14:23:04 +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-04 13:12:22 +00:00
|
|
|
object b = pop(t);
|
|
|
|
object a = pop(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
|
|
|
if (a != b) {
|
|
|
|
ip = (ip - 1) + ((offset1 << 8) | offset2);
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case if_icmpeq: {
|
2007-06-08 14:23:04 +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-04 13:12:22 +00:00
|
|
|
object b = pop(t);
|
|
|
|
object a = pop(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-05 00:28:52 +00:00
|
|
|
if (intValue(t, a) == intValue(t, b)) {
|
2007-05-22 00:05:29 +00:00
|
|
|
ip = (ip - 1) + ((offset1 << 8) | offset2);
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case if_icmpne: {
|
2007-06-08 14:23:04 +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-04 13:12:22 +00:00
|
|
|
object b = pop(t);
|
|
|
|
object a = pop(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-05 00:28:52 +00:00
|
|
|
if (intValue(t, a) != intValue(t, b)) {
|
2007-05-22 00:05:29 +00:00
|
|
|
ip = (ip - 1) + ((offset1 << 8) | offset2);
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case if_icmpgt: {
|
2007-06-08 14:23:04 +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-04 13:12:22 +00:00
|
|
|
object b = pop(t);
|
|
|
|
object a = pop(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-05 00:28:52 +00:00
|
|
|
if (intValue(t, a) > intValue(t, b)) {
|
2007-05-22 00:05:29 +00:00
|
|
|
ip = (ip - 1) + ((offset1 << 8) | offset2);
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case if_icmpge: {
|
2007-06-08 14:23:04 +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-04 13:12:22 +00:00
|
|
|
object b = pop(t);
|
|
|
|
object a = pop(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-05 00:28:52 +00:00
|
|
|
if (intValue(t, a) >= intValue(t, b)) {
|
2007-05-22 00:05:29 +00:00
|
|
|
ip = (ip - 1) + ((offset1 << 8) | offset2);
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case if_icmplt: {
|
2007-06-08 14:23:04 +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-04 13:12:22 +00:00
|
|
|
object b = pop(t);
|
|
|
|
object a = pop(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-05 00:28:52 +00:00
|
|
|
if (intValue(t, a) < intValue(t, b)) {
|
2007-05-22 00:05:29 +00:00
|
|
|
ip = (ip - 1) + ((offset1 << 8) | offset2);
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case if_icmple: {
|
2007-06-08 14:23:04 +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-04 13:12:22 +00:00
|
|
|
object b = pop(t);
|
|
|
|
object a = pop(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-05 00:28:52 +00:00
|
|
|
if (intValue(t, a) < intValue(t, b)) {
|
2007-05-22 00:05:29 +00:00
|
|
|
ip = (ip - 1) + ((offset1 << 8) | offset2);
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ifeq: {
|
2007-06-08 14:23:04 +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-04 13:12:22 +00:00
|
|
|
object v = pop(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-05 00:28:52 +00:00
|
|
|
if (intValue(t, v) == 0) {
|
2007-05-22 00:05:29 +00:00
|
|
|
ip = (ip - 1) + ((offset1 << 8) | offset2);
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ifne: {
|
2007-06-08 14:23:04 +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-04 13:12:22 +00:00
|
|
|
object v = pop(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-05 00:28:52 +00:00
|
|
|
if (intValue(t, v)) {
|
2007-05-22 00:05:29 +00:00
|
|
|
ip = (ip - 1) + ((offset1 << 8) | offset2);
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ifgt: {
|
2007-06-08 14:23:04 +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-04 13:12:22 +00:00
|
|
|
object v = pop(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-05 00:28:52 +00:00
|
|
|
if (intValue(t, v) > 0) {
|
2007-05-22 00:05:29 +00:00
|
|
|
ip = (ip - 1) + ((offset1 << 8) | offset2);
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ifge: {
|
2007-06-08 14:23:04 +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-04 13:12:22 +00:00
|
|
|
object v = pop(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-05 00:28:52 +00:00
|
|
|
if (intValue(t, v) >= 0) {
|
2007-05-22 00:05:29 +00:00
|
|
|
ip = (ip - 1) + ((offset1 << 8) | offset2);
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iflt: {
|
2007-06-08 14:23:04 +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-04 13:12:22 +00:00
|
|
|
object v = pop(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-05 00:28:52 +00:00
|
|
|
if (intValue(t, v) < 0) {
|
2007-05-22 00:05:29 +00:00
|
|
|
ip = (ip - 1) + ((offset1 << 8) | offset2);
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ifle: {
|
2007-06-08 14:23:04 +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-04 13:12:22 +00:00
|
|
|
object v = pop(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-05 00:28:52 +00:00
|
|
|
if (intValue(t, v) <= 0) {
|
2007-05-22 00:05:29 +00:00
|
|
|
ip = (ip - 1) + ((offset1 << 8) | offset2);
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ifnonnull: {
|
2007-06-08 14:23:04 +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-04 13:12:22 +00:00
|
|
|
object v = pop(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
|
|
|
if (v) {
|
|
|
|
ip = (ip - 1) + ((offset1 << 8) | offset2);
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ifnull: {
|
2007-06-08 14:23:04 +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-04 13:12:22 +00:00
|
|
|
object v = pop(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
|
|
|
if (v == 0) {
|
|
|
|
ip = (ip - 1) + ((offset1 << 8) | offset2);
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iinc: {
|
2007-06-08 14:23:04 +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-06-08 14:23:04 +00:00
|
|
|
int32_t v = intValue(t, frameLocals(t, frame)[index]);
|
|
|
|
frameLocals(t, frame)[index] = makeInt(t, v + c);
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case imul: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object b = pop(t);
|
|
|
|
object a = pop(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-05 00:28:52 +00:00
|
|
|
push(t, makeInt(t, intValue(t, a) * intValue(t, b)));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ineg: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object v = pop(t);
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-05 00:28:52 +00:00
|
|
|
push(t, makeInt(t, - intValue(t, v)));
|
2007-05-22 00:05:29 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case instanceof: {
|
2007-06-08 14:23:04 +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-06-08 14:23:04 +00:00
|
|
|
if (stack[sp - 1]) {
|
2007-05-22 00:05:29 +00:00
|
|
|
uint16_t index = (index1 << 8) | index2;
|
|
|
|
|
2007-06-08 14:23:04 +00:00
|
|
|
object class_ = resolveClass(t, codePool(t, code), index);
|
|
|
|
if (UNLIKELY(exception)) goto throw_;
|
2007-05-22 00:05:29 +00:00
|
|
|
|
2007-06-08 14:23:04 +00:00
|
|
|
if (instanceOf(t, class_, stack[sp - 1])) {
|
2007-06-04 13:12:22 +00:00
|
|
|
push(t, makeInt(t, 1));
|
2007-05-22 00:05:29 +00:00
|
|
|
} else {
|
2007-06-04 13:12:22 +00:00
|
|
|
push(t, makeInt(t, 0));
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
|
|
|
} else {
|
2007-06-04 13:12:22 +00:00
|
|
|
push(t, makeInt(t, 0));
|
2007-05-22 00:05:29 +00:00
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
2007-05-25 14:48:07 +00:00
|
|
|
case invokeinterface: {
|
2007-06-08 14:23:04 +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;
|
|
|
|
|
|
|
|
ip += 2;
|
|
|
|
|
2007-06-08 14:23:04 +00:00
|
|
|
object method = resolveMethod(t, codePool(t, code), index);
|
|
|
|
if (UNLIKELY(exception)) goto throw_;
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-06-11 23:40:24 +00:00
|
|
|
parameterCount = methodParameterCount(t, method);
|
2007-06-08 14:23:04 +00:00
|
|
|
if (LIKELY(stack[sp - parameterCount])) {
|
|
|
|
code = findInterfaceMethod(t, method, stack[sp - parameterCount]);
|
|
|
|
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-08 14:23:04 +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-08 14:23:04 +00:00
|
|
|
object method = resolveMethod(t, codePool(t, code), index);
|
|
|
|
if (UNLIKELY(exception)) goto throw_;
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-06-11 23:40:24 +00:00
|
|
|
parameterCount = methodParameterCount(t, method);
|
2007-06-08 14:23:04 +00:00
|
|
|
if (LIKELY(stack[sp - parameterCount])) {
|
|
|
|
if (isSpecialMethod(method, stack[sp - parameterCount])) {
|
|
|
|
code = findSpecialMethod(t, method, stack[sp - parameterCount]);
|
|
|
|
if (UNLIKELY(exception)) goto throw_;
|
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-08 14:23:04 +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-08 14:23:04 +00:00
|
|
|
object method = resolveMethod(t, codePool(t, code), index);
|
|
|
|
if (UNLIKELY(exception)) goto throw_;
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-06-11 23:40:24 +00:00
|
|
|
object p = classInitializers(t, methodClass(t, method));
|
|
|
|
if (p) {
|
|
|
|
set(t, classInitializers(t, methodClass(t, method)), pairSecond(t, p));
|
|
|
|
code = pairFirst(t, p);
|
|
|
|
ip -= 3;
|
2007-05-30 00:08:10 +00:00
|
|
|
parameterCount = 0;
|
|
|
|
goto invoke;
|
|
|
|
}
|
|
|
|
|
2007-06-11 23:40:24 +00:00
|
|
|
parameterCount = methodParameterCount(t, method);
|
2007-06-08 14:23:04 +00:00
|
|
|
code = method;
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto invoke;
|
|
|
|
|
|
|
|
case invokevirtual: {
|
2007-06-08 14:23:04 +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-08 14:23:04 +00:00
|
|
|
object method = resolveMethod(t, codePool(t, code), index);
|
|
|
|
if (UNLIKELY(exception)) goto throw_;
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-06-11 23:40:24 +00:00
|
|
|
parameterCount = methodParameterCount(t, method);
|
2007-06-08 14:23:04 +00:00
|
|
|
if (LIKELY(stack[sp - parameterCount])) {
|
|
|
|
code = findVirtualMethod(t, method, stack[sp - parameterCount]);
|
|
|
|
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 ior: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object b = pop(t);
|
|
|
|
object a = pop(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-06-05 00:28:52 +00:00
|
|
|
push(t, makeInt(t, intValue(t, a) | intValue(t, b)));
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case irem: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object b = pop(t);
|
|
|
|
object a = pop(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-06-05 00:28:52 +00:00
|
|
|
push(t, makeInt(t, intValue(t, a) % intValue(t, b)));
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ishl: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object b = pop(t);
|
|
|
|
object a = pop(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-06-05 00:28:52 +00:00
|
|
|
push(t, makeInt(t, intValue(t, a) << intValue(t, b)));
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ishr: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object b = pop(t);
|
|
|
|
object a = pop(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-06-05 00:28:52 +00:00
|
|
|
push(t, makeInt(t, intValue(t, a) >> intValue(t, b)));
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case isub: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object b = pop(t);
|
|
|
|
object a = pop(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-06-05 00:28:52 +00:00
|
|
|
push(t, makeInt(t, intValue(t, a) - intValue(t, b)));
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iushr: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object b = pop(t);
|
|
|
|
object a = pop(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-06-05 00:28:52 +00:00
|
|
|
push(t, makeInt(t, static_cast<uint32_t>(intValue(t, a)) >> intValue(t, b)));
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ixor: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object b = pop(t);
|
|
|
|
object a = pop(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-06-05 00:28:52 +00:00
|
|
|
push(t, makeInt(t, intValue(t, a) ^ intValue(t, b)));
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case jsr: {
|
2007-06-08 14:23:04 +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-06-06 00:41:04 +00:00
|
|
|
push(t, makeInt(t, ip));
|
2007-05-30 00:08:10 +00:00
|
|
|
ip = (ip - 1) + ((offset1 << 8) | offset2);
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case jsr_w: {
|
2007-06-08 14:23:04 +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-06-06 00:41:04 +00:00
|
|
|
push(t, makeInt(t, ip));
|
2007-05-30 00:08:10 +00:00
|
|
|
ip = (ip - 1)
|
|
|
|
+ ((offset1 << 24) | (offset2 << 16) | (offset3 << 8) | offset4);
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case l2i: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object v = pop(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-06-06 00:41:04 +00:00
|
|
|
push(t, makeInt(t, static_cast<int32_t>(longValue(t, v))));
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ladd: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object b = pop(t);
|
|
|
|
object a = pop(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-06-06 00:41:04 +00:00
|
|
|
push(t, makeLong(t, longValue(t, a) + longValue(t, b)));
|
2007-05-25 14:48:07 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-05-30 00:08:10 +00:00
|
|
|
case laload: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object index = pop(t);
|
|
|
|
object array = pop(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(array)) {
|
2007-06-05 00:28:52 +00:00
|
|
|
int32_t i = intValue(t, index);
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(i >= 0 and
|
|
|
|
static_cast<uint32_t>(i) < longArrayLength(t, array)))
|
|
|
|
{
|
2007-06-06 00:41:04 +00:00
|
|
|
push(t, makeLong(t, longArrayBody(t, array)[i]));
|
2007-05-30 00:08:10 +00:00
|
|
|
} else {
|
2007-06-08 00:23:12 +00:00
|
|
|
object message = makeString(t, "%d not in [0,%d]", i,
|
|
|
|
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-06-04 13:12:22 +00:00
|
|
|
object b = pop(t);
|
|
|
|
object a = pop(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-06-06 00:41:04 +00:00
|
|
|
push(t, makeLong(t, longValue(t, a) & longValue(t, b)));
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lastore: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object value = pop(t);
|
|
|
|
object index = pop(t);
|
|
|
|
object array = pop(t);
|
2007-06-05 00:28:52 +00:00
|
|
|
int32_t i = intValue(t, index);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(array)) {
|
|
|
|
if (LIKELY(i >= 0 and
|
|
|
|
static_cast<uint32_t>(i) < longArrayLength(t, array)))
|
|
|
|
{
|
2007-06-06 00:41:04 +00:00
|
|
|
longArrayBody(t, array)[i] = longValue(t, value);
|
2007-05-30 00:08:10 +00:00
|
|
|
} else {
|
2007-06-08 00:23:12 +00:00
|
|
|
object message = makeString(t, "%d not in [0,%d]", i,
|
|
|
|
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-06-04 13:12:22 +00:00
|
|
|
object b = pop(t);
|
|
|
|
object a = pop(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-06-06 00:41:04 +00:00
|
|
|
push(t, makeInt(t, longValue(t, a) > longValue(t, b) ? 1
|
|
|
|
: longValue(t, a) == longValue(t, b) ? 0 : -1));
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lconst_0: {
|
2007-06-06 00:41:04 +00:00
|
|
|
push(t, makeLong(t, 0));
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lconst_1: {
|
2007-06-06 00:41:04 +00:00
|
|
|
push(t, makeLong(t, 1));
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ldc: {
|
2007-06-08 14:23:04 +00:00
|
|
|
push(t, rawArrayBody(t, codePool(t, code))[codeBody(t, code)[ip++]]);
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ldc_w:
|
|
|
|
case ldc2_w: {
|
2007-06-08 14:23:04 +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-06-08 14:23:04 +00:00
|
|
|
push(t, rawArrayBody(t, codePool(t, code))[(index1 << 8) | index2]);
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ldiv: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object b = pop(t);
|
|
|
|
object a = pop(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-06-06 00:41:04 +00:00
|
|
|
push(t, makeLong(t, longValue(t, a) / longValue(t, b)));
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lmul: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object b = pop(t);
|
|
|
|
object a = pop(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-06-06 00:41:04 +00:00
|
|
|
push(t, makeLong(t, longValue(t, a) * longValue(t, b)));
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lneg: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object v = pop(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-06-06 00:41:04 +00:00
|
|
|
push(t, makeLong(t, - longValue(t, v)));
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lor: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object b = pop(t);
|
|
|
|
object a = pop(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-06-06 00:41:04 +00:00
|
|
|
push(t, makeLong(t, longValue(t, a) | longValue(t, b)));
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lrem: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object b = pop(t);
|
|
|
|
object a = pop(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-06-06 00:41:04 +00:00
|
|
|
push(t, makeLong(t, longValue(t, a) % longValue(t, b)));
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lshl: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object b = pop(t);
|
|
|
|
object a = pop(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-06-06 00:41:04 +00:00
|
|
|
push(t, makeLong(t, longValue(t, a) << longValue(t, b)));
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lshr: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object b = pop(t);
|
|
|
|
object a = pop(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-06-06 00:41:04 +00:00
|
|
|
push(t, makeLong(t, longValue(t, a) >> longValue(t, b)));
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lsub: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object b = pop(t);
|
|
|
|
object a = pop(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-06-06 00:41:04 +00:00
|
|
|
push(t, makeLong(t, longValue(t, a) - longValue(t, b)));
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lushr: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object b = pop(t);
|
|
|
|
object a = pop(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-06-06 00:41:04 +00:00
|
|
|
push(t, makeLong(t, static_cast<uint64_t>(longValue(t, a))
|
|
|
|
<< longValue(t, b)));
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case lxor: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object b = pop(t);
|
|
|
|
object a = pop(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-06-06 00:41:04 +00:00
|
|
|
push(t, makeLong(t, longValue(t, a) ^ longValue(t, b)));
|
2007-05-30 00:08:10 +00:00
|
|
|
} goto loop;
|
|
|
|
|
2007-05-31 00:29:07 +00:00
|
|
|
case new_: {
|
2007-06-08 14:23:04 +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-08 14:23:04 +00:00
|
|
|
object class_ = resolveClass(t, codePool(t, code), index);
|
|
|
|
if (UNLIKELY(exception)) goto throw_;
|
2007-06-11 23:40:24 +00:00
|
|
|
|
|
|
|
object p = classInitializers(t, class_);
|
|
|
|
if (p) {
|
|
|
|
set(t, classInitializers(t, class_), pairSecond(t, p));
|
|
|
|
code = pairFirst(t, p);
|
2007-05-31 00:29:07 +00:00
|
|
|
ip -= 3;
|
|
|
|
parameterCount = 0;
|
|
|
|
goto invoke;
|
|
|
|
}
|
|
|
|
|
2007-06-07 00:30:16 +00:00
|
|
|
push(t, make(t, class_));
|
2007-05-31 00:29:07 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case newarray: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object count = pop(t);
|
2007-06-05 00:28:52 +00:00
|
|
|
int32_t c = intValue(t, count);
|
2007-05-31 00:29:07 +00:00
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(c >= 0)) {
|
2007-06-08 14:23:04 +00:00
|
|
|
uint8_t type = codeBody(t, code)[ip++];
|
2007-05-31 00:29:07 +00:00
|
|
|
|
|
|
|
object array;
|
|
|
|
unsigned factor;
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case T_BOOLEAN:
|
|
|
|
array = makeBooleanArray(t, c);
|
|
|
|
factor = 1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case T_CHAR:
|
|
|
|
array = makeCharArray(t, c);
|
|
|
|
factor = 2;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case T_FLOAT:
|
|
|
|
array = makeFloatArray(t, c);
|
|
|
|
factor = 4;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case T_DOUBLE:
|
|
|
|
array = makeDoubleArray(t, c);
|
|
|
|
factor = 8;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case T_BYTE:
|
|
|
|
array = makeByteArray(t, c);
|
|
|
|
factor = 1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case T_SHORT:
|
|
|
|
array = makeShortArray(t, c);
|
|
|
|
factor = 2;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case T_INT:
|
|
|
|
array = makeIntArray(t, c);
|
|
|
|
factor = 4;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case T_LONG:
|
|
|
|
array = makeLongArray(t, c);
|
|
|
|
factor = 8;
|
|
|
|
break;
|
|
|
|
|
2007-06-03 02:00:23 +00:00
|
|
|
default: abort(t);
|
2007-05-31 00:29:07 +00:00
|
|
|
}
|
|
|
|
|
2007-06-09 02:33:26 +00:00
|
|
|
memset(static_cast<uint8_t*>(array) + sizeof(object) + 4, 0,
|
2007-06-07 00:30:16 +00:00
|
|
|
c * factor);
|
2007-05-31 00:29:07 +00:00
|
|
|
|
2007-06-04 13:12:22 +00:00
|
|
|
push(t, array);
|
2007-05-31 00:29:07 +00:00
|
|
|
} else {
|
2007-06-08 00:23:12 +00:00
|
|
|
object message = makeString(t, "%d", c);
|
2007-06-08 14:23:04 +00:00
|
|
|
exception = makeNegativeArrayStoreException(t, message);
|
2007-05-31 00:29:07 +00:00
|
|
|
goto throw_;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case nop: goto loop;
|
|
|
|
|
2007-06-05 00:28:52 +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-06-08 14:23:04 +00:00
|
|
|
object top = stack[sp - 1];
|
2007-05-31 00:29:07 +00:00
|
|
|
if (isLongOrDouble(top)) {
|
2007-06-08 14:23:04 +00:00
|
|
|
-- sp;
|
2007-05-31 00:29:07 +00:00
|
|
|
} else {
|
2007-06-08 14:23:04 +00:00
|
|
|
sp -= 2;
|
2007-05-31 00:29:07 +00:00
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case putfield: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object instance = pop(t);
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(instance)) {
|
2007-06-08 14:23:04 +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-08 14:23:04 +00:00
|
|
|
object field = resolveField(t, codePool(t, code), index);
|
|
|
|
if (UNLIKELY(exception)) goto throw_;
|
2007-05-31 00:29:07 +00:00
|
|
|
|
2007-06-04 13:12:22 +00:00
|
|
|
object value = pop(t);
|
2007-05-31 00:29:07 +00:00
|
|
|
setField(t, instance, field, value);
|
|
|
|
} 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 putstatic: {
|
2007-06-08 14:23:04 +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-08 14:23:04 +00:00
|
|
|
object field = resolveField(t, codePool(t, code), index);
|
|
|
|
if (UNLIKELY(exception)) goto throw_;
|
2007-05-31 00:29:07 +00:00
|
|
|
|
2007-06-11 23:40:24 +00:00
|
|
|
object p = classInitializers(t, fieldClass(t, field));
|
|
|
|
if (p) {
|
|
|
|
set(t, classInitializers(t, fieldClass(t, field)), pairSecond(t, p));
|
|
|
|
code = pairFirst(t, p);
|
2007-05-31 00:29:07 +00:00
|
|
|
ip -= 3;
|
|
|
|
parameterCount = 0;
|
|
|
|
goto invoke;
|
|
|
|
}
|
|
|
|
|
2007-06-04 13:12:22 +00:00
|
|
|
object value = pop(t);
|
2007-05-31 00:29:07 +00:00
|
|
|
setStatic(t, field, value);
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ret: {
|
2007-06-08 14:23:04 +00:00
|
|
|
ip = intValue(t, frameLocals(t, frame)[codeBody(t, code)[ip]]);
|
2007-05-31 00:29:07 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case return_: {
|
2007-06-08 14:23:04 +00:00
|
|
|
frame = frameNext(t, frame);
|
|
|
|
if (frame) {
|
|
|
|
code = methodCode(t, frameMethod(t, frame));
|
|
|
|
ip = frameIp(t, frame);
|
2007-05-31 00:29:07 +00:00
|
|
|
goto loop;
|
|
|
|
} else {
|
2007-06-08 14:23:04 +00:00
|
|
|
code = 0;
|
2007-05-31 00:29:07 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case saload: {
|
2007-06-04 13:12:22 +00:00
|
|
|
object index = pop(t);
|
|
|
|
object array = pop(t);
|
2007-05-31 00:29:07 +00:00
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(array)) {
|
2007-06-05 00:28:52 +00:00
|
|
|
int32_t i = intValue(t, index);
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(i >= 0 and
|
|
|
|
static_cast<uint32_t>(i) < shortArrayLength(t, array)))
|
|
|
|
{
|
2007-06-06 00:41:04 +00:00
|
|
|
push(t, makeShort(t, shortArrayBody(t, array)[i]));
|
2007-05-31 00:29:07 +00:00
|
|
|
} else {
|
2007-06-08 00:23:12 +00:00
|
|
|
object message = makeString(t, "%d not in [0,%d]", i,
|
|
|
|
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-06-04 13:12:22 +00:00
|
|
|
object value = pop(t);
|
|
|
|
object index = pop(t);
|
|
|
|
object array = pop(t);
|
2007-06-05 00:28:52 +00:00
|
|
|
int32_t i = intValue(t, index);
|
2007-05-31 00:29:07 +00:00
|
|
|
|
2007-06-08 00:23:12 +00:00
|
|
|
if (LIKELY(array)) {
|
|
|
|
if (LIKELY(i >= 0 and
|
|
|
|
static_cast<uint32_t>(i) < shortArrayLength(t, array)))
|
|
|
|
{
|
2007-06-06 00:41:04 +00:00
|
|
|
shortArrayBody(t, array)[i] = intValue(t, value);
|
2007-05-31 00:29:07 +00:00
|
|
|
} else {
|
2007-06-08 00:23:12 +00:00
|
|
|
object message = makeString(t, "%d not in [0,%d]", i,
|
|
|
|
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-08 14:23:04 +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-06-04 13:12:22 +00:00
|
|
|
push(t, makeInt(t, (byte1 << 8) | byte2));
|
2007-05-31 00:29:07 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case swap: {
|
2007-06-08 14:23:04 +00:00
|
|
|
object tmp = stack[sp - 1];
|
|
|
|
stack[sp - 1] = stack[sp - 2];
|
|
|
|
stack[sp - 2] = tmp;
|
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-08 14:23:04 +00:00
|
|
|
switch (codeBody(t, code)[ip++]) {
|
2007-05-31 00:29:07 +00:00
|
|
|
case aload:
|
|
|
|
case iload:
|
|
|
|
case lload: {
|
2007-06-08 14:23:04 +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-06-08 14:23:04 +00:00
|
|
|
push(t, frameLocals(t, frame)[(index1 << 8) | index2]);
|
2007-05-31 00:29:07 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case astore:
|
|
|
|
case istore:
|
|
|
|
case lstore: {
|
2007-06-08 14:23:04 +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-06-04 13:12:22 +00:00
|
|
|
object value = pop(t);
|
2007-06-08 14:23:04 +00:00
|
|
|
set(t, frameLocals(t, frame)[(index1 << 8) | index2], value);
|
2007-05-31 00:29:07 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case iinc: {
|
2007-06-08 14:23:04 +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-08 14:23:04 +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-06-08 14:23:04 +00:00
|
|
|
int32_t v = intValue(t, frameLocals(t, frame)[index]);
|
|
|
|
frameLocals(t, frame)[index] = makeInt(t, v + count);
|
2007-05-31 00:29:07 +00:00
|
|
|
} goto loop;
|
|
|
|
|
|
|
|
case ret: {
|
2007-06-08 14:23:04 +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-06-08 14:23:04 +00:00
|
|
|
ip = intValue(t, frameLocals(t, frame)[(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
|
|
|
}
|
|
|
|
|
|
|
|
invoke:
|
2007-06-08 14:23:04 +00:00
|
|
|
if (UNLIKELY(codeMaxStack(t, methodCode(t, code)) + sp - parameterCount
|
2007-06-08 00:23:12 +00:00
|
|
|
> Thread::StackSize))
|
2007-06-06 02:24:09 +00:00
|
|
|
{
|
2007-06-08 14:23:04 +00:00
|
|
|
exception = makeStackOverflowError(t);
|
2007-05-30 00:08:10 +00:00
|
|
|
goto throw_;
|
2007-05-21 15:47:44 +00:00
|
|
|
}
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-06-08 14:23:04 +00:00
|
|
|
frameIp(t, frame) = ip;
|
2007-05-30 00:08:10 +00:00
|
|
|
|
2007-06-08 14:23:04 +00:00
|
|
|
sp -= parameterCount;
|
|
|
|
frame = makeFrame(t, code, frame, 0, sp,
|
|
|
|
codeMaxLocals(t, methodCode(t, code)));
|
|
|
|
memcpy(frameLocals(t, frame), stack + sp, parameterCount);
|
2007-05-30 00:08:10 +00:00
|
|
|
ip = 0;
|
|
|
|
goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
|
|
|
|
throw_:
|
2007-06-08 14:23:04 +00:00
|
|
|
for (; frame; frame = frameNext(t, frame)) {
|
|
|
|
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-05-25 14:48:07 +00:00
|
|
|
uint16_t catchType = exceptionHandlerCatchType(eh);
|
|
|
|
if (catchType == 0 or
|
2007-06-09 02:29:56 +00:00
|
|
|
instanceOf(t,
|
|
|
|
rawArrayBody(t, codePool(t, code))[catchType],
|
2007-06-08 14:23:04 +00:00
|
|
|
exception))
|
2007-05-25 14:48:07 +00:00
|
|
|
{
|
2007-06-08 14:23:04 +00:00
|
|
|
sp = frameStackBase(t, frame);
|
2007-05-25 14:48:07 +00:00
|
|
|
ip = exceptionHandlerIp(eh);
|
2007-06-08 14:23:04 +00:00
|
|
|
push(t, exception);
|
|
|
|
exception = 0;
|
2007-05-25 14:48:07 +00:00
|
|
|
goto loop;
|
2007-05-21 15:47:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-06-06 02:24:09 +00:00
|
|
|
object method = defaultExceptionHandler(t);
|
2007-06-08 14:23:04 +00:00
|
|
|
code = methodCode(t, method);
|
|
|
|
frame = makeFrame(t, method, 0, 0, 0, codeMaxLocals(t, code));
|
|
|
|
sp = 0;
|
2007-05-21 15:47:44 +00:00
|
|
|
ip = 0;
|
2007-06-08 14:23:04 +00:00
|
|
|
push(t, exception);
|
|
|
|
exception = 0;
|
2007-05-21 15:47:44 +00:00
|
|
|
goto loop;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace
|