corda/src/vm.cpp

1677 lines
38 KiB
C++
Raw Normal View History

#include "common.h"
#include "system.h"
#include "heap.h"
2007-05-21 15:47:44 +00:00
namespace {
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
};
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"
class Machine {
public:
System* sys;
Heap* heap;
Thread* rootThread;
Thread* exclusive;
unsigned activeCount;
unsigned liveCount;
System::Monitor* stateLock;
};
class Thread {
public:
enum State {
NoState,
ActiveState,
IdleState,
ZombieState,
ExclusiveState,
ExitState
};
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;
unsigned sp;
unsigned heapIndex;
object stack[StackSize];
object heap[HeapSize];
};
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)
{
sys->zero(m, sizeof(Machine));
m->sys = sys;
m->heap = heap;
if (not sys->success(sys->make(&(m->stateLock)))) {
sys->abort();
}
}
void
dispose(Machine* m)
{
m->stateLock->dispose();
}
void
init(Thread* t, Machine* m)
{
m->sys->zero(m, sizeof(Thread));
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)
{
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);
}
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);
m->heap->collect(type, &it);
2007-06-02 00:06:06 +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
ACQUIRE(t->vm->stateLock);
2007-06-02 00:06:06 +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) {
// 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-02 00:06:06 +00:00
while (t->vm->activeCount > 1) {
t->vm->stateLock->wait();
}
} 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: {
assert(t, t->vm->exclusive == t);
t->vm->exclusive = 0;
} break;
2007-06-05 00:28:52 +00:00
case Thread::ActiveState: break;
default: abort(t);
}
-- t->vm->activeCount;
2007-06-05 00:28:52 +00:00
if (s == Thread::ZombieState) {
-- t->vm->liveCount;
}
t->state = s;
2007-06-02 00:06:06 +00:00
t->vm->stateLock->notifyAll();
} break;
2007-06-05 00:28:52 +00:00
case Thread::ActiveState: {
switch (t->state) {
case Thread::ExclusiveState: {
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: {
while (t->vm->exclusive) {
t->vm->stateLock->wait();
}
++ t->vm->activeCount;
2007-06-05 00:28:52 +00:00
if (t->state == Thread::NoState) {
++ 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: {
assert(t, t->vm->exclusive == t);
t->vm->exclusive = 0;
} break;
2007-06-05 00:28:52 +00:00
case Thread::ActiveState: break;
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-02 00:06:06 +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)
{
if (UNLIKELY(t->heapIndex + size >= Thread::HeapSize
2007-06-02 00:06:06 +00:00
or t->vm->exclusive))
{
maybeYieldAndMaybeCollect(t, size);
2007-06-02 00:06:06 +00:00
}
object o = t->heap + t->heapIndex;
t->heapIndex += size;
return o;
2007-06-02 00:06:06 +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-05-21 15:47:44 +00:00
object
run(Thread* t)
{
unsigned ip = 0;
2007-05-30 00:08:10 +00:00
unsigned parameterCount = 0;
2007-05-21 15:47:44 +00:00
loop:
2007-06-05 00:28:52 +00:00
switch (codeBody(t, t->code)[ip++]) {
2007-05-21 15:47:44 +00:00
case aaload: {
object index = pop(t);
object array = pop(t);
2007-05-21 15:47:44 +00:00
if (array) {
2007-06-05 00:28:52 +00:00
int32_t i = intValue(t, index);
2007-06-06 00:41:04 +00:00
if (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-06 00:41:04 +00:00
object message = makeJString(t, "%d not in [0,%d]", i,
objectArrayLength(t, array));
2007-05-25 14:48:07 +00:00
t->exception = makeArrayIndexOutOfBoundsException(t, message);
2007-05-21 15:47:44 +00:00
goto throw_;
}
} else {
2007-05-25 14:48:07 +00:00
t->exception = makeNullPointerException(t, 0);
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: {
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
if (array) {
2007-06-06 00:41:04 +00:00
if (i >= 0 and static_cast<uint32_t>(i) < objectArrayLength(t, array)) {
set(t, objectArrayBody(t, array)[i], value);
2007-05-21 15:47:44 +00:00
} else {
2007-06-06 00:41:04 +00:00
object message = makeJString(t, "%d not in [0,%d]", i,
objectArrayLength(t, array));
2007-05-25 14:48:07 +00:00
t->exception = makeArrayIndexOutOfBoundsException(t, message);
2007-05-21 15:47:44 +00:00
goto throw_;
}
} else {
2007-05-25 14:48:07 +00:00
t->exception = makeNullPointerException(t, 0);
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: {
push(t, 0);
2007-05-22 00:05:29 +00:00
} goto loop;
2007-05-21 15:47:44 +00:00
case aload:
case iload:
case lload: {
2007-06-06 00:41:04 +00:00
push(t, frameLocals(t, t->frame)[codeBody(t, t->code)[ip++]]);
2007-05-22 00:05:29 +00:00
} goto loop;
2007-05-21 15:47:44 +00:00
case aload_0:
case iload_0:
case lload_0: {
2007-06-06 00:41:04 +00:00
push(t, frameLocals(t, t->frame)[0]);
2007-05-22 00:05:29 +00:00
} goto loop;
2007-05-21 15:47:44 +00:00
case aload_1:
case iload_1:
case lload_1: {
2007-06-06 00:41:04 +00:00
push(t, frameLocals(t, t->frame)[1]);
2007-05-22 00:05:29 +00:00
} goto loop;
2007-05-21 15:47:44 +00:00
case aload_2:
case iload_2:
case lload_2: {
2007-06-06 00:41:04 +00:00
push(t, frameLocals(t, t->frame)[2]);
2007-05-22 00:05:29 +00:00
} goto loop;
2007-05-21 15:47:44 +00:00
case aload_3:
case iload_3:
case lload_3: {
2007-06-06 00:41:04 +00:00
push(t, frameLocals(t, t->frame)[3]);
2007-05-22 00:05:29 +00:00
} goto loop;
2007-05-21 15:47:44 +00:00
case anewarray: {
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
if (c >= 0) {
2007-06-05 00:28:52 +00:00
uint8_t index1 = codeBody(t, t->code)[ip++];
uint8_t index2 = codeBody(t, t->code)[ip++];
2007-05-21 15:47:44 +00:00
uint16_t index = (index1 << 8) | index2;
2007-06-06 00:41:04 +00:00
object class_ = resolveClass(t, codePool(t, t->code), index);
2007-05-21 15:47:44 +00:00
if (t->exception) goto throw_;
object array = makeObjectArray(t, class_, c);
2007-06-06 00:41:04 +00:00
t->vm->sys->zero(objectArrayBody(t, array), c * 4);
2007-05-21 15:47:44 +00:00
push(t, array);
2007-05-21 15:47:44 +00:00
} else {
2007-06-06 00:41:04 +00:00
object message = makeJString(t, "%d", c);
2007-05-25 14:48:07 +00:00
t->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-06 00:41:04 +00:00
t->frame = frameNext(t, t->frame);
2007-05-30 00:08:10 +00:00
if (t->frame) {
2007-06-06 00:41:04 +00:00
t->code = methodCode(t, frameMethod(t, t->frame));
ip = frameIp(t, t->frame);
2007-05-21 15:47:44 +00:00
goto loop;
} else {
object value = pop(t);
2007-05-30 00:08:10 +00:00
t->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: {
object array = pop(t);
2007-05-21 15:47:44 +00:00
if (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.
push(t, makeInt(t, reinterpret_cast<uint32_t&>
(static_cast<uintptr_t*>(array)[1])));
}
2007-05-21 15:47:44 +00:00
} else {
2007-05-25 14:48:07 +00:00
t->exception = makeNullPointerException(t, 0);
2007-05-21 15:47:44 +00:00
goto throw_;
}
} abort(t);
2007-05-21 15:47:44 +00:00
2007-05-30 00:08:10 +00:00
case astore:
case istore:
case lstore: {
object value = pop(t);
2007-06-06 00:41:04 +00:00
set(t, frameLocals(t, t->frame)[codeBody(t, 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: {
object value = pop(t);
2007-06-06 00:41:04 +00:00
set(t, frameLocals(t, 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: {
object value = pop(t);
2007-06-06 00:41:04 +00:00
set(t, frameLocals(t, 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: {
object value = pop(t);
2007-06-06 00:41:04 +00:00
set(t, frameLocals(t, 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: {
object value = pop(t);
2007-06-06 00:41:04 +00:00
set(t, frameLocals(t, t->frame)[3], value);
2007-05-22 00:05:29 +00:00
} goto loop;
2007-05-21 15:47:44 +00:00
case athrow: {
t->exception = pop(t);
2007-05-22 00:05:29 +00:00
if (t->exception == 0) {
2007-05-25 14:48:07 +00:00
t->exception = makeNullPointerException(t, 0);
2007-05-22 00:05:29 +00:00
}
2007-05-21 15:47:44 +00:00
goto throw_;
} abort(t);
2007-05-22 00:05:29 +00:00
case baload: {
object index = pop(t);
object array = pop(t);
2007-05-22 00:05:29 +00:00
if (array) {
2007-06-05 00:28:52 +00:00
int32_t i = intValue(t, index);
2007-06-06 00:41:04 +00:00
if (i >= 0 and static_cast<uint32_t>(i) < byteArrayLength(t, array)) {
push(t, makeByte(t, byteArrayBody(t, array)[i]));
2007-05-22 00:05:29 +00:00
} else {
2007-06-06 00:41:04 +00:00
object message = makeJString(t, "%d not in [0,%d]", i,
byteArrayLength(t, array));
2007-05-25 14:48:07 +00:00
t->exception = makeArrayIndexOutOfBoundsException(t, message);
2007-05-22 00:05:29 +00:00
goto throw_;
}
} else {
2007-05-25 14:48:07 +00:00
t->exception = makeNullPointerException(t, 0);
2007-05-22 00:05:29 +00:00
goto throw_;
}
} goto loop;
case bastore: {
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
if (array) {
2007-06-06 00:41:04 +00:00
if (i >= 0 and static_cast<uint32_t>(i) < byteArrayLength(t, array)) {
byteArrayBody(t, array)[i] = intValue(t, value);
2007-05-22 00:05:29 +00:00
} else {
2007-06-06 00:41:04 +00:00
object message = makeJString(t, "%d not in [0,%d]", i,
byteArrayLength(t, array));
2007-05-25 14:48:07 +00:00
t->exception = makeArrayIndexOutOfBoundsException(t, message);
2007-05-22 00:05:29 +00:00
goto throw_;
}
} else {
2007-05-25 14:48:07 +00:00
t->exception = makeNullPointerException(t, 0);
2007-05-22 00:05:29 +00:00
goto throw_;
}
} goto loop;
case bipush: {
2007-06-05 00:28:52 +00:00
push(t, makeInt(t, codeBody(t, t->code)[ip++]));
2007-05-22 00:05:29 +00:00
} goto loop;
case caload: {
object index = pop(t);
object array = pop(t);
2007-05-22 00:05:29 +00:00
if (array) {
2007-06-05 00:28:52 +00:00
int32_t i = intValue(t, index);
2007-06-06 00:41:04 +00:00
if (i >= 0 and static_cast<uint32_t>(i) < charArrayLength(t, array)) {
push(t, makeInt(t, charArrayBody(t, array)[i]));
2007-05-22 00:05:29 +00:00
} else {
2007-06-06 00:41:04 +00:00
object message = makeJString(t, "%d not in [0,%d]", i,
charArrayLength(t, array));
2007-05-25 14:48:07 +00:00
t->exception = makeArrayIndexOutOfBoundsException(t, message);
2007-05-22 00:05:29 +00:00
goto throw_;
}
} else {
2007-05-25 14:48:07 +00:00
t->exception = makeNullPointerException(t, 0);
2007-05-22 00:05:29 +00:00
goto throw_;
}
} goto loop;
case castore: {
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
if (array) {
2007-06-06 00:41:04 +00:00
if (i >= 0 and static_cast<uint32_t>(i) < charArrayLength(t, array)) {
charArrayBody(t, array)[i] = intValue(t, value);
2007-05-22 00:05:29 +00:00
} else {
2007-06-06 00:41:04 +00:00
object message = makeJString(t, "%d not in [0,%d]", i,
charArrayLength(t, array));
2007-05-25 14:48:07 +00:00
t->exception = makeArrayIndexOutOfBoundsException(t, message);
2007-05-22 00:05:29 +00:00
goto throw_;
}
} else {
2007-05-25 14:48:07 +00:00
t->exception = makeNullPointerException(t, 0);
2007-05-22 00:05:29 +00:00
goto throw_;
}
} goto loop;
case checkcast: {
2007-06-05 00:28:52 +00:00
uint8_t index1 = codeBody(t, t->code)[ip++];
uint8_t index2 = codeBody(t, t->code)[ip++];
2007-05-22 00:05:29 +00:00
if (t->stack[t->sp - 1]) {
uint16_t index = (index1 << 8) | index2;
2007-06-06 00:41:04 +00:00
object class_ = resolveClass(t, codePool(t, t->code), index);
2007-05-22 00:05:29 +00:00
if (t->exception) goto throw_;
if (not instanceOf(t, class_, t->stack[t->sp - 1])) {
2007-05-25 14:48:07 +00:00
t->exception = makeClassCastException(t, 0);
2007-05-22 00:05:29 +00:00
goto throw_;
}
}
} goto loop;
case dup: {
object value = t->stack[t->sp - 1];
push(t, value);
2007-05-22 00:05:29 +00:00
} goto loop;
case dup_x1: {
object first = pop(t);
object second = pop(t);
2007-05-22 00:05:29 +00:00
push(t, first);
push(t, second);
push(t, first);
2007-05-22 00:05:29 +00:00
} goto loop;
case dup_x2: {
object first = pop(t);
object second = pop(t);
object third = pop(t);
2007-05-22 00:05:29 +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: {
object first = t->stack[t->sp - 1];
if (isLongOrDouble(first)) {
push(t, first);
2007-05-22 00:05:29 +00:00
} else {
object second = t->stack[t->sp - 2];
push(t, second);
push(t, first);
2007-05-22 00:05:29 +00:00
}
} goto loop;
case dup2_x1: {
object first = pop(t);
object second = pop(t);
2007-05-22 00:05:29 +00:00
if (isLongOrDouble(first)) {
push(t, first);
push(t, second);
push(t, first);
2007-05-22 00:05:29 +00:00
} else {
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: {
object first = pop(t);
object second = pop(t);
2007-05-22 00:05:29 +00:00
if (isLongOrDouble(first)) {
if (isLongOrDouble(second)) {
push(t, first);
push(t, second);
push(t, first);
2007-05-22 00:05:29 +00:00
} else {
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 {
object third = pop(t);
2007-05-22 00:05:29 +00:00
if (isLongOrDouble(third)) {
push(t, second);
push(t, first);
push(t, third);
push(t, second);
push(t, first);
2007-05-22 00:05:29 +00:00
} else {
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: {
object instance = pop(t);
2007-05-22 00:05:29 +00:00
if (instance) {
2007-06-05 00:28:52 +00:00
uint8_t index1 = codeBody(t, t->code)[ip++];
uint8_t index2 = codeBody(t, t->code)[ip++];
2007-05-22 00:05:29 +00:00
uint16_t index = (index1 << 8) | index2;
2007-06-06 00:41:04 +00:00
object field = resolveField(t, codePool(t, t->code), index);
2007-05-22 00:05:29 +00:00
if (t->exception) goto throw_;
push(t, getField(instance, field));
2007-05-22 00:05:29 +00:00
} else {
2007-05-25 14:48:07 +00:00
t->exception = makeNullPointerException(t, 0);
2007-05-22 00:05:29 +00:00
goto throw_;
}
} goto loop;
case getstatic: {
2007-06-05 00:28:52 +00:00
uint8_t index1 = codeBody(t, t->code)[ip++];
uint8_t index2 = codeBody(t, t->code)[ip++];
uint16_t index = (index1 << 8) | index2;
2007-05-25 14:48:07 +00:00
2007-06-06 00:41:04 +00:00
object field = resolveField(t, codePool(t, t->code), index);
if (t->exception) goto throw_;
2007-05-25 14:48:07 +00:00
2007-06-06 00:41:04 +00:00
if (not classInitialized(fieldClass(t, field))) {
t->code = classInitializer(fieldClass(t, field));
ip -= 3;
parameterCount = 0;
goto invoke;
2007-05-22 00:05:29 +00:00
}
push(t, getStatic(field));
2007-05-22 00:05:29 +00:00
} goto loop;
case goto_: {
2007-06-05 00:28:52 +00:00
uint8_t offset1 = codeBody(t, t->code)[ip++];
uint8_t offset2 = codeBody(t, t->code)[ip++];
2007-05-22 00:05:29 +00:00
ip = (ip - 1) + ((offset1 << 8) | offset2);
} goto loop;
case goto_w: {
2007-06-05 00:28:52 +00:00
uint8_t offset1 = codeBody(t, t->code)[ip++];
uint8_t offset2 = codeBody(t, t->code)[ip++];
uint8_t offset3 = codeBody(t, t->code)[ip++];
uint8_t offset4 = codeBody(t, 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: {
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: {
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: {
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: {
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: {
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: {
object index = pop(t);
object array = pop(t);
2007-05-22 00:05:29 +00:00
if (array) {
2007-06-05 00:28:52 +00:00
int32_t i = intValue(t, index);
2007-06-06 00:41:04 +00:00
if (i >= 0 and static_cast<uint32_t>(i) < intArrayLength(t, array)) {
push(t, makeInt(t, intArrayBody(t, array)[i]));
2007-05-22 00:05:29 +00:00
} else {
2007-06-06 00:41:04 +00:00
object message = makeJString(t, "%d not in [0,%d]", i,
intArrayLength(t, array));
2007-05-25 14:48:07 +00:00
t->exception = makeArrayIndexOutOfBoundsException(t, message);
2007-05-22 00:05:29 +00:00
goto throw_;
}
} else {
2007-05-25 14:48:07 +00:00
t->exception = makeNullPointerException(t, 0);
2007-05-22 00:05:29 +00:00
goto throw_;
}
} goto loop;
case iand: {
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: {
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
if (array) {
2007-06-06 00:41:04 +00:00
if (i >= 0 and static_cast<uint32_t>(i) < intArrayLength(t, array)) {
intArrayBody(t, array)[i] = intValue(t, value);
2007-05-22 00:05:29 +00:00
} else {
2007-06-06 00:41:04 +00:00
object message = makeJString(t, "%d not in [0,%d]", i,
intArrayLength(t, array));
2007-05-25 14:48:07 +00:00
t->exception = makeArrayIndexOutOfBoundsException(t, message);
2007-05-22 00:05:29 +00:00
goto throw_;
}
} else {
2007-05-25 14:48:07 +00:00
t->exception = makeNullPointerException(t, 0);
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: {
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-05 00:28:52 +00:00
uint8_t offset1 = codeBody(t, t->code)[ip++];
uint8_t offset2 = codeBody(t, t->code)[ip++];
2007-05-22 00:05:29 +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-05 00:28:52 +00:00
uint8_t offset1 = codeBody(t, t->code)[ip++];
uint8_t offset2 = codeBody(t, t->code)[ip++];
2007-05-22 00:05:29 +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-05 00:28:52 +00:00
uint8_t offset1 = codeBody(t, t->code)[ip++];
uint8_t offset2 = codeBody(t, t->code)[ip++];
2007-05-22 00:05:29 +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-05 00:28:52 +00:00
uint8_t offset1 = codeBody(t, t->code)[ip++];
uint8_t offset2 = codeBody(t, t->code)[ip++];
2007-05-22 00:05:29 +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-05 00:28:52 +00:00
uint8_t offset1 = codeBody(t, t->code)[ip++];
uint8_t offset2 = codeBody(t, t->code)[ip++];
2007-05-22 00:05:29 +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-05 00:28:52 +00:00
uint8_t offset1 = codeBody(t, t->code)[ip++];
uint8_t offset2 = codeBody(t, t->code)[ip++];
2007-05-22 00:05:29 +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-05 00:28:52 +00:00
uint8_t offset1 = codeBody(t, t->code)[ip++];
uint8_t offset2 = codeBody(t, t->code)[ip++];
2007-05-22 00:05:29 +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-05 00:28:52 +00:00
uint8_t offset1 = codeBody(t, t->code)[ip++];
uint8_t offset2 = codeBody(t, t->code)[ip++];
2007-05-22 00:05:29 +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-05 00:28:52 +00:00
uint8_t offset1 = codeBody(t, t->code)[ip++];
uint8_t offset2 = codeBody(t, t->code)[ip++];
2007-05-22 00:05:29 +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-05 00:28:52 +00:00
uint8_t offset1 = codeBody(t, t->code)[ip++];
uint8_t offset2 = codeBody(t, t->code)[ip++];
2007-05-22 00:05:29 +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-05 00:28:52 +00:00
uint8_t offset1 = codeBody(t, t->code)[ip++];
uint8_t offset2 = codeBody(t, t->code)[ip++];
2007-05-22 00:05:29 +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-05 00:28:52 +00:00
uint8_t offset1 = codeBody(t, t->code)[ip++];
uint8_t offset2 = codeBody(t, t->code)[ip++];
2007-05-22 00:05:29 +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-05 00:28:52 +00:00
uint8_t offset1 = codeBody(t, t->code)[ip++];
uint8_t offset2 = codeBody(t, t->code)[ip++];
2007-05-22 00:05:29 +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-05 00:28:52 +00:00
uint8_t offset1 = codeBody(t, t->code)[ip++];
uint8_t offset2 = codeBody(t, t->code)[ip++];
2007-05-22 00:05:29 +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-05 00:28:52 +00:00
uint8_t offset1 = codeBody(t, t->code)[ip++];
uint8_t offset2 = codeBody(t, t->code)[ip++];
2007-05-22 00:05:29 +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-05 00:28:52 +00:00
uint8_t offset1 = codeBody(t, t->code)[ip++];
uint8_t offset2 = codeBody(t, t->code)[ip++];
2007-05-22 00:05:29 +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-05 00:28:52 +00:00
uint8_t index = codeBody(t, t->code)[ip++];
int8_t c = codeBody(t, t->code)[ip++];
2007-05-22 00:05:29 +00:00
2007-06-06 00:41:04 +00:00
int32_t v = intValue(t, frameLocals(t, t->frame)[index]);
frameLocals(t, t->frame)[index] = makeInt(t, v + c);
2007-05-22 00:05:29 +00:00
} goto loop;
case imul: {
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: {
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-05 00:28:52 +00:00
uint8_t index1 = codeBody(t, t->code)[ip++];
uint8_t index2 = codeBody(t, t->code)[ip++];
2007-05-22 00:05:29 +00:00
if (t->stack[t->sp - 1]) {
uint16_t index = (index1 << 8) | index2;
2007-06-06 00:41:04 +00:00
object class_ = resolveClass(t, codePool(t, t->code), index);
2007-05-22 00:05:29 +00:00
if (t->exception) goto throw_;
if (instanceOf(t, class_, t->stack[t->sp - 1])) {
push(t, makeInt(t, 1));
2007-05-22 00:05:29 +00:00
} else {
push(t, makeInt(t, 0));
2007-05-22 00:05:29 +00:00
}
} else {
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-05 00:28:52 +00:00
uint8_t index1 = codeBody(t, t->code)[ip++];
uint8_t index2 = codeBody(t, t->code)[ip++];
2007-05-30 00:08:10 +00:00
uint16_t index = (index1 << 8) | index2;
ip += 2;
2007-06-06 00:41:04 +00:00
object method = resolveMethod(t, codePool(t, t->code), index);
2007-05-30 00:08:10 +00:00
if (t->exception) goto throw_;
parameterCount = methodParameterCount(method);
if (t->stack[t->sp - parameterCount]) {
2007-06-06 02:24:09 +00:00
t->code = findInterfaceMethod
(t, method, t->stack[t->sp - parameterCount]);
2007-05-30 00:08:10 +00:00
if (t->exception) goto throw_;
goto invoke;
} else {
t->exception = makeNullPointerException(t, 0);
goto throw_;
}
} goto loop;
case invokespecial: {
2007-06-05 00:28:52 +00:00
uint8_t index1 = codeBody(t, t->code)[ip++];
uint8_t index2 = codeBody(t, t->code)[ip++];
2007-05-30 00:08:10 +00:00
uint16_t index = (index1 << 8) | index2;
2007-06-06 00:41:04 +00:00
object method = resolveMethod(t, codePool(t, t->code), index);
2007-05-30 00:08:10 +00:00
if (t->exception) goto throw_;
parameterCount = methodParameterCount(method);
if (t->stack[t->sp - parameterCount]) {
if (isSpecialMethod(method, t->stack[t->sp - parameterCount])) {
2007-06-06 02:24:09 +00:00
t->code = findSpecialMethod
(t, method, t->stack[t->sp - parameterCount]);
2007-05-30 00:08:10 +00:00
if (t->exception) goto throw_;
} else {
2007-06-06 02:24:09 +00:00
t->code = method;
2007-05-30 00:08:10 +00:00
}
goto invoke;
} else {
t->exception = makeNullPointerException(t, 0);
goto throw_;
}
} goto loop;
case invokestatic: {
2007-06-05 00:28:52 +00:00
uint8_t index1 = codeBody(t, t->code)[ip++];
uint8_t index2 = codeBody(t, t->code)[ip++];
2007-05-30 00:08:10 +00:00
uint16_t index = (index1 << 8) | index2;
2007-06-06 00:41:04 +00:00
object method = resolveMethod(t, codePool(t, t->code), index);
2007-05-30 00:08:10 +00:00
if (t->exception) goto throw_;
2007-06-06 00:41:04 +00:00
if (not classInitialized(methodClass(t, method))) {
t->code = classInitializer(methodClass(t, method));
2007-05-30 00:08:10 +00:00
ip -= 2;
parameterCount = 0;
goto invoke;
}
parameterCount = methodParameterCount(method);
2007-06-06 02:24:09 +00:00
t->code = method;
2007-05-30 00:08:10 +00:00
} goto invoke;
case invokevirtual: {
2007-06-05 00:28:52 +00:00
uint8_t index1 = codeBody(t, t->code)[ip++];
uint8_t index2 = codeBody(t, t->code)[ip++];
2007-05-30 00:08:10 +00:00
uint16_t index = (index1 << 8) | index2;
2007-06-06 00:41:04 +00:00
object method = resolveMethod(t, codePool(t, t->code), index);
2007-05-30 00:08:10 +00:00
if (t->exception) goto throw_;
parameterCount = methodParameterCount(method);
if (t->stack[t->sp - parameterCount]) {
2007-06-06 02:24:09 +00:00
t->code = findVirtualMethod(t, method, t->stack[t->sp - parameterCount]);
2007-05-30 00:08:10 +00:00
if (t->exception) goto throw_;
goto invoke;
} else {
t->exception = makeNullPointerException(t, 0);
goto throw_;
}
} goto loop;
case ior: {
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: {
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: {
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: {
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: {
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: {
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: {
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-05 00:28:52 +00:00
uint8_t offset1 = codeBody(t, t->code)[ip++];
uint8_t offset2 = codeBody(t, 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-05 00:28:52 +00:00
uint8_t offset1 = codeBody(t, t->code)[ip++];
uint8_t offset2 = codeBody(t, t->code)[ip++];
uint8_t offset3 = codeBody(t, t->code)[ip++];
uint8_t offset4 = codeBody(t, 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: {
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: {
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: {
object index = pop(t);
object array = pop(t);
2007-05-30 00:08:10 +00:00
if (array) {
2007-06-05 00:28:52 +00:00
int32_t i = intValue(t, index);
2007-06-06 00:41:04 +00:00
if (i >= 0 and static_cast<uint32_t>(i) < longArrayLength(t, array)) {
push(t, makeLong(t, longArrayBody(t, array)[i]));
2007-05-30 00:08:10 +00:00
} else {
2007-06-06 00:41:04 +00:00
object message = makeJString(t, "%d not in [0,%d]", i,
longArrayLength(t, array));
2007-05-30 00:08:10 +00:00
t->exception = makeArrayIndexOutOfBoundsException(t, message);
goto throw_;
}
} else {
t->exception = makeNullPointerException(t, 0);
goto throw_;
}
} goto loop;
case land: {
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: {
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
if (array) {
2007-06-06 00:41:04 +00:00
if (i >= 0 and static_cast<uint32_t>(i) < longArrayLength(t, array)) {
longArrayBody(t, array)[i] = longValue(t, value);
2007-05-30 00:08:10 +00:00
} else {
2007-06-06 00:41:04 +00:00
object message = makeJString(t, "%d not in [0,%d]", i,
longArrayLength(t, array));
2007-05-30 00:08:10 +00:00
t->exception = makeArrayIndexOutOfBoundsException(t, message);
goto throw_;
}
} else {
t->exception = makeNullPointerException(t, 0);
goto throw_;
}
} goto loop;
case lcmp: {
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-06 00:41:04 +00:00
push(t, rawArrayBody(t, codePool(t, t->code))[codeBody(t, t->code)[ip++]]);
2007-05-30 00:08:10 +00:00
} goto loop;
case ldc_w:
case ldc2_w: {
2007-06-05 00:28:52 +00:00
uint8_t index1 = codeBody(t, t->code)[ip++];
uint8_t index2 = codeBody(t, t->code)[ip++];
2007-05-30 00:08:10 +00:00
2007-06-06 00:41:04 +00:00
push(t, rawArrayBody(t, codePool(t, t->code))[(index1 << 8) | index2]);
2007-05-30 00:08:10 +00:00
} goto loop;
case ldiv: {
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: {
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: {
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: {
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: {
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: {
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: {
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: {
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: {
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: {
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 new_: {
2007-06-05 00:28:52 +00:00
uint8_t index1 = codeBody(t, t->code)[ip++];
uint8_t index2 = codeBody(t, t->code)[ip++];
uint16_t index = (index1 << 8) | index2;
2007-06-06 00:41:04 +00:00
object class_ = resolveClass(t, codePool(t, t->code), index);
if (t->exception) goto throw_;
if (not classInitialized(class_)) {
t->code = classInitializer(class_);
ip -= 3;
parameterCount = 0;
goto invoke;
}
unsigned size = instanceSize(class_);
object instance = allocate(t, size);
*static_cast<object*>(instance) = class_;
t->vm->sys->zero(static_cast<object*>(instance) + sizeof(object),
size - sizeof(object));
push(t, instance);
} goto loop;
case newarray: {
object count = pop(t);
2007-06-05 00:28:52 +00:00
int32_t c = intValue(t, count);
if (c >= 0) {
2007-06-05 00:28:52 +00:00
uint8_t type = codeBody(t, t->code)[ip++];
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;
default: abort(t);
}
t->vm->sys->zero(static_cast<object*>(instance) + (sizeof(object) * 2),
c * factor);
push(t, array);
} else {
2007-06-06 00:41:04 +00:00
object message = makeJString(t, "%d", c);
t->exception = makeNegativeArrayStoreException(t, message);
goto throw_;
}
} goto loop;
case nop: goto loop;
2007-06-05 00:28:52 +00:00
case pop_: {
-- (t->sp);
} goto loop;
case pop2: {
object top = t->stack[t->sp - 1];
if (isLongOrDouble(top)) {
-- (t->sp);
} else {
t->sp -= 2;
}
} goto loop;
case putfield: {
object instance = pop(t);
if (instance) {
2007-06-05 00:28:52 +00:00
uint8_t index1 = codeBody(t, t->code)[ip++];
uint8_t index2 = codeBody(t, t->code)[ip++];
uint16_t index = (index1 << 8) | index2;
2007-06-06 00:41:04 +00:00
object field = resolveField(t, codePool(t, t->code), index);
if (t->exception) goto throw_;
object value = pop(t);
setField(t, instance, field, value);
} else {
t->exception = makeNullPointerException(t, 0);
goto throw_;
}
} goto loop;
case putstatic: {
2007-06-05 00:28:52 +00:00
uint8_t index1 = codeBody(t, t->code)[ip++];
uint8_t index2 = codeBody(t, t->code)[ip++];
uint16_t index = (index1 << 8) | index2;
2007-06-06 00:41:04 +00:00
object field = resolveField(t, codePool(t, t->code), index);
if (t->exception) goto throw_;
2007-06-06 00:41:04 +00:00
if (not classInitialized(fieldClass(t, field))) {
t->code = classInitializer(fieldClass(t, field));
ip -= 3;
parameterCount = 0;
goto invoke;
}
object value = pop(t);
setStatic(t, field, value);
} goto loop;
case ret: {
2007-06-06 00:41:04 +00:00
ip = intValue(t, frameLocals(t, t->frame)[codeBody(t, t->code)[ip]]);
} goto loop;
case return_: {
2007-06-06 00:41:04 +00:00
t->frame = frameNext(t, t->frame);
if (t->frame) {
2007-06-06 00:41:04 +00:00
t->code = methodCode(t, frameMethod(t, t->frame));
ip = frameIp(t, t->frame);
goto loop;
} else {
t->code = 0;
return 0;
}
} goto loop;
case saload: {
object index = pop(t);
object array = pop(t);
if (array) {
2007-06-05 00:28:52 +00:00
int32_t i = intValue(t, index);
2007-06-06 00:41:04 +00:00
if (i >= 0 and static_cast<uint32_t>(i) < shortArrayLength(t, array)) {
push(t, makeShort(t, shortArrayBody(t, array)[i]));
} else {
2007-06-06 00:41:04 +00:00
object message = makeJString(t, "%d not in [0,%d]", i,
shortArrayLength(t, array));
t->exception = makeArrayIndexOutOfBoundsException(t, message);
goto throw_;
}
} else {
t->exception = makeNullPointerException(t, 0);
goto throw_;
}
} goto loop;
case sastore: {
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);
if (array) {
2007-06-06 00:41:04 +00:00
if (i >= 0 and static_cast<uint32_t>(i) < shortArrayLength(t, array)) {
shortArrayBody(t, array)[i] = intValue(t, value);
} else {
2007-06-06 00:41:04 +00:00
object message = makeJString(t, "%d not in [0,%d]", i,
shortArrayLength(t, array));
t->exception = makeArrayIndexOutOfBoundsException(t, message);
goto throw_;
}
} else {
t->exception = makeNullPointerException(t, 0);
goto throw_;
}
} goto loop;
case sipush: {
2007-06-05 00:28:52 +00:00
uint8_t byte1 = codeBody(t, t->code)[ip++];
uint8_t byte2 = codeBody(t, t->code)[ip++];
push(t, makeInt(t, (byte1 << 8) | byte2));
} goto loop;
case swap: {
object tmp = t->stack[t->sp - 1];
t->stack[t->sp - 1] = t->stack[t->sp - 2];
t->stack[t->sp - 2] = tmp;
} goto loop;
case wide: goto wide;
default: abort(t);
}
wide:
2007-06-05 00:28:52 +00:00
switch (codeBody(t, t->code)[ip++]) {
case aload:
case iload:
case lload: {
2007-06-05 00:28:52 +00:00
uint8_t index1 = codeBody(t, t->code)[ip++];
uint8_t index2 = codeBody(t, t->code)[ip++];
2007-06-06 00:41:04 +00:00
push(t, frameLocals(t, t->frame)[(index1 << 8) | index2]);
} goto loop;
case astore:
case istore:
case lstore: {
2007-06-05 00:28:52 +00:00
uint8_t index1 = codeBody(t, t->code)[ip++];
uint8_t index2 = codeBody(t, t->code)[ip++];
object value = pop(t);
2007-06-06 00:41:04 +00:00
set(t, frameLocals(t, t->frame)[(index1 << 8) | index2], value);
} goto loop;
case iinc: {
2007-06-05 00:28:52 +00:00
uint8_t index1 = codeBody(t, t->code)[ip++];
uint8_t index2 = codeBody(t, t->code)[ip++];
uint16_t index = (index1 << 8) | index2;
2007-06-05 00:28:52 +00:00
uint8_t count1 = codeBody(t, t->code)[ip++];
uint8_t count2 = codeBody(t, t->code)[ip++];
uint16_t count = (count1 << 8) | count2;
2007-06-06 00:41:04 +00:00
int32_t v = intValue(t, frameLocals(t, t->frame)[index]);
frameLocals(t, t->frame)[index] = makeInt(t, v + count);
} goto loop;
case ret: {
2007-06-05 00:28:52 +00:00
uint8_t index1 = codeBody(t, t->code)[ip++];
uint8_t index2 = codeBody(t, t->code)[ip++];
2007-06-06 00:41:04 +00:00
ip = intValue(t, frameLocals(t, t->frame)[(index1 << 8) | index2]);
2007-05-30 00:08:10 +00:00
} goto loop;
default: abort(t);
2007-05-30 00:08:10 +00:00
}
invoke:
2007-06-06 02:24:09 +00:00
if (codeMaxStack(t, methodCode(t, t->code)) + t->sp - parameterCount
> Thread::StackSize)
{
2007-05-30 00:08:10 +00:00
t->exception = makeStackOverflowException(t, 0);
goto throw_;
2007-05-21 15:47:44 +00:00
}
2007-05-30 00:08:10 +00:00
2007-06-06 00:41:04 +00:00
frameIp(t, t->frame) = ip;
2007-05-30 00:08:10 +00:00
t->sp -= parameterCount;
2007-06-06 02:24:09 +00:00
t->frame = makeFrame(t, t->code, t->frame, 0, t->sp,
codeMaxLocals(t, methodCode(t, t->code)));
t->vm->sys->copy(t->stack + t->sp, frameLocals(t, t->frame), parameterCount);
2007-05-30 00:08:10 +00:00
ip = 0;
goto loop;
2007-05-21 15:47:44 +00:00
throw_:
2007-06-06 00:41:04 +00:00
for (; t->frame; t->frame = frameNext(t, t->frame)) {
t->code = methodCode(t, frameMethod(t, t->frame));
object eht = codeExceptionHandlerTable(t, 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-06 00:41:04 +00:00
instanceOf(rawArrayBody(t, codePool(t, t->code))[catchType],
2007-05-25 14:48:07 +00:00
t->exception))
{
2007-06-06 00:41:04 +00:00
t->sp = frameStackBase(t, t->frame);
2007-05-25 14:48:07 +00:00
ip = exceptionHandlerIp(eh);
push(t, t->exception);
2007-05-25 14:48:07 +00:00
t->exception = 0;
goto loop;
2007-05-21 15:47:44 +00:00
}
}
}
}
2007-06-06 02:24:09 +00:00
object method = defaultExceptionHandler(t);
t->code = methodCode(t, method);
t->frame = makeFrame(t, method, 0, 0, 0, codeMaxLocals(t, t->code));
2007-05-22 00:05:29 +00:00
t->sp = 0;
2007-05-21 15:47:44 +00:00
ip = 0;
push(t, t->exception);
2007-05-21 15:47:44 +00:00
t->exception = 0;
goto loop;
}
} // namespace