2007-09-24 01:39:03 +00:00
|
|
|
#include "machine.h"
|
2007-12-09 22:45:43 +00:00
|
|
|
#include "util.h"
|
|
|
|
#include "vector.h"
|
2007-09-26 23:23:03 +00:00
|
|
|
#include "process.h"
|
2007-12-09 22:45:43 +00:00
|
|
|
#include "compiler.h"
|
2007-09-24 01:39:03 +00:00
|
|
|
|
|
|
|
using namespace vm;
|
|
|
|
|
2007-09-26 23:23:03 +00:00
|
|
|
extern "C" uint64_t
|
2007-12-09 22:45:43 +00:00
|
|
|
vmInvoke(void* thread, void* function, void* stack, unsigned stackSize,
|
2007-09-26 23:23:03 +00:00
|
|
|
unsigned returnType);
|
|
|
|
|
2007-10-04 03:19:39 +00:00
|
|
|
extern "C" void
|
|
|
|
vmCall();
|
|
|
|
|
2007-10-02 00:08:17 +00:00
|
|
|
extern "C" void NO_RETURN
|
2007-10-04 22:41:19 +00:00
|
|
|
vmJump(void* address, void* base, void* stack);
|
2007-10-02 00:08:17 +00:00
|
|
|
|
2007-09-24 01:39:03 +00:00
|
|
|
namespace {
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
class MyThread: public Thread {
|
|
|
|
public:
|
|
|
|
class CallTrace {
|
|
|
|
public:
|
|
|
|
CallTrace(MyThread* t):
|
|
|
|
t(t),
|
|
|
|
base(t->base),
|
|
|
|
stack(t->stack),
|
|
|
|
next(t->trace)
|
|
|
|
{
|
|
|
|
t->trace = this;
|
|
|
|
t->base = 0;
|
|
|
|
t->stack = 0;
|
|
|
|
}
|
2007-09-30 15:52:21 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
~CallTrace() {
|
|
|
|
t->stack = stack;
|
|
|
|
t->base = base;
|
|
|
|
t->trace = next;
|
|
|
|
}
|
2007-09-25 23:53:11 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
MyThread* t;
|
|
|
|
void* base;
|
|
|
|
void* stack;
|
|
|
|
CallTrace* next;
|
|
|
|
};
|
2007-10-01 15:19:15 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
MyThread(Machine* m, object javaThread, Thread* parent):
|
|
|
|
Thread(m, javaThread, parent),
|
|
|
|
base(0),
|
|
|
|
stack(0),
|
|
|
|
trace(0),
|
|
|
|
reference(0)
|
2007-10-03 00:22:48 +00:00
|
|
|
{ }
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void* base;
|
|
|
|
void* stack;
|
|
|
|
CallTrace* trace;
|
|
|
|
Reference* reference;
|
|
|
|
};
|
|
|
|
|
|
|
|
object
|
|
|
|
resolveTarget(MyThread* t, void* stack, object method)
|
|
|
|
{
|
|
|
|
if (methodVirtual(t, method)) {
|
|
|
|
unsigned parameterFootprint = methodParameterFootprint(t, method);
|
|
|
|
object class_ = objectClass
|
|
|
|
(t, reinterpret_cast<object*>(stack)[parameterFootprint + 1]);
|
|
|
|
|
|
|
|
if (classVmFlags(t, class_) & BootstrapFlag) {
|
|
|
|
resolveClass(t, className(t, class_));
|
|
|
|
if (UNLIKELY(t->exception)) return 0;
|
2007-10-03 00:22:48 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
if (classFlags(t, methodClass(t, method)) & ACC_INTERFACE) {
|
|
|
|
return findInterfaceMethod(t, method, class_);
|
|
|
|
} else {
|
|
|
|
return findMethod(t, method, class_);
|
2007-10-03 00:22:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
return method;
|
|
|
|
}
|
2007-10-03 00:22:48 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
object
|
|
|
|
findTraceNode(MyThread* t, void* address);
|
2007-10-03 00:22:48 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void
|
|
|
|
insertTraceNode(MyThread* t, object node);
|
2007-10-03 00:22:48 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
class MyStackWalker: public Processor::StackWalker {
|
|
|
|
public:
|
|
|
|
class MyProtector: public Thread::Protector {
|
|
|
|
public:
|
|
|
|
MyProtector(MyStackWalker* walker):
|
|
|
|
Protector(walker->t), walker(walker)
|
|
|
|
{ }
|
2007-10-03 00:22:48 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
virtual void visit(Heap::Visitor* v) {
|
|
|
|
v->visit(&(walker->node));
|
|
|
|
v->visit(&(walker->nativeMethod));
|
|
|
|
}
|
2007-10-03 00:22:48 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
MyStackWalker* walker;
|
|
|
|
};
|
|
|
|
|
|
|
|
MyStackWalker(MyThread* t):
|
|
|
|
t(t),
|
|
|
|
base(t->base),
|
|
|
|
stack(t->stack),
|
|
|
|
trace(t->trace),
|
|
|
|
node(findTraceNode(t, *static_cast<void**>(stack))),
|
|
|
|
nativeMethod(resolveNativeMethod(t, stack, node)),
|
|
|
|
protector(this)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
MyStackWalker(MyStackWalker* w):
|
|
|
|
t(w->t),
|
|
|
|
base(w->base),
|
|
|
|
stack(w->stack),
|
|
|
|
trace(w->trace),
|
|
|
|
node(w->node),
|
|
|
|
nativeMethod(w->nativeMethod),
|
|
|
|
protector(this)
|
|
|
|
{ }
|
2007-10-11 22:43:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
static object resolveNativeMethod(MyThread* t, void* stack, object node) {
|
|
|
|
if (node) {
|
|
|
|
object target = resolveTarget(t, stack, traceNodeTarget(t, node));
|
|
|
|
if (target and methodFlags(t, target) & ACC_NATIVE) {
|
|
|
|
return target;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
2007-10-03 00:22:48 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
virtual void walk(Processor::StackVisitor* v) {
|
|
|
|
if (not v->visit(this)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (MyStackWalker it(this); it.next();) {
|
|
|
|
MyStackWalker walker(it);
|
|
|
|
if (not v->visit(&walker)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool next() {
|
|
|
|
if (nativeMethod) {
|
|
|
|
nativeMethod = 0;
|
|
|
|
} else {
|
|
|
|
stack = static_cast<void**>(base) + 1;
|
|
|
|
base = *static_cast<void**>(base);
|
|
|
|
node = findTraceNode(t, *static_cast<void**>(stack));
|
|
|
|
if (node == 0) {
|
|
|
|
if (trace) {
|
|
|
|
base = trace->base;
|
|
|
|
stack = static_cast<void**>(trace->stack);
|
|
|
|
trace = trace->next;
|
|
|
|
node = findTraceNode(t, *static_cast<void**>(stack));
|
|
|
|
nativeMethod = resolveNativeMethod(t, stack, node);
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
2007-10-12 17:56:43 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
virtual object method() {
|
|
|
|
if (nativeMethod) {
|
|
|
|
return nativeMethod;
|
|
|
|
} else {
|
|
|
|
return traceNodeMethod(t, node);
|
|
|
|
}
|
2007-10-03 00:22:48 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
virtual int ip() {
|
|
|
|
if (nativeMethod) {
|
|
|
|
return 0;
|
|
|
|
} else {
|
2007-12-11 00:48:09 +00:00
|
|
|
return traceNodeAddress(t, node);
|
2007-10-03 00:22:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
virtual unsigned count() {
|
|
|
|
class Visitor: public Processor::StackVisitor {
|
|
|
|
public:
|
|
|
|
Visitor(): count(0) { }
|
|
|
|
|
|
|
|
virtual bool visit(Processor::StackWalker*) {
|
|
|
|
++ count;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned count;
|
|
|
|
} v;
|
|
|
|
|
|
|
|
MyStackWalker walker(this);
|
|
|
|
walker.walk(&v);
|
|
|
|
|
|
|
|
return v.count;
|
2007-10-03 00:22:48 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
MyThread* t;
|
|
|
|
void* base;
|
|
|
|
void* stack;
|
|
|
|
MyThread::CallTrace* trace;
|
|
|
|
object node;
|
|
|
|
object nativeMethod;
|
|
|
|
MyProtector protector;
|
|
|
|
};
|
|
|
|
|
|
|
|
uintptr_t*
|
|
|
|
makeCodeMask(MyThread* t, unsigned length)
|
|
|
|
{
|
|
|
|
unsigned size = ceiling(length, BytesPerWord) * BytesPerWord;
|
|
|
|
uintptr_t* mask = static_cast<uintptr_t*>(t->m->system->allocate(size));
|
|
|
|
memset(mask, 0, size);
|
|
|
|
return mask;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
localOffset(MyThread* t, int v, object method)
|
|
|
|
{
|
|
|
|
int parameterFootprint = methodParameterFootprint(t, method) * BytesPerWord;
|
|
|
|
|
|
|
|
v *= BytesPerWord;
|
|
|
|
if (v < parameterFootprint) {
|
|
|
|
return (parameterFootprint - v - BytesPerWord) + (BytesPerWord * 2);
|
|
|
|
} else {
|
|
|
|
return -(v + BytesPerWord - parameterFootprint);
|
2007-10-03 00:22:48 +00:00
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2007-10-03 00:22:48 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
class PoolElement {
|
|
|
|
public:
|
|
|
|
PoolElement(object value, Promise* offset): value(value), offset(offset) { }
|
|
|
|
|
|
|
|
object value;
|
|
|
|
Promise* offset;
|
|
|
|
};
|
|
|
|
|
|
|
|
class TraceElement {
|
|
|
|
public:
|
|
|
|
TraceElement(object target, Promise* offset, bool virtualCall):
|
|
|
|
target(target), offset(offset), virtualCall(virtualCall) { }
|
|
|
|
|
|
|
|
object target;
|
|
|
|
Promise* offset;
|
|
|
|
bool virtualCall;
|
|
|
|
uint8_t map[0];
|
2007-10-03 00:22:48 +00:00
|
|
|
};
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
class Frame {
|
2007-10-10 22:39:40 +00:00
|
|
|
public:
|
2007-12-09 22:45:43 +00:00
|
|
|
class MyProtector: public Thread::Protector {
|
|
|
|
public:
|
|
|
|
MyProtector(Frame* frame): Protector(frame->t), frame(frame) { }
|
|
|
|
|
|
|
|
virtual void visit(Heap::Visitor* v) {
|
|
|
|
v->visit(&(frame->method));
|
|
|
|
|
|
|
|
if (next == 0) {
|
|
|
|
Vector* pool = frame->objectPool;
|
|
|
|
for (unsigned i = 0; i < pool->length(); i += sizeof(PoolElement)) {
|
|
|
|
v->visit(&(pool->peek<PoolElement>(i)->value));
|
|
|
|
}
|
|
|
|
|
|
|
|
Vector* log = frame->traceLog;
|
|
|
|
unsigned traceSize = traceSizeInBytes(t, frame->method);
|
|
|
|
for (unsigned i = 0; i < log->length(); i += traceSize) {
|
|
|
|
v->visit(&(pool->peek<TraceElement>(i)->target));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Frame* frame;
|
2007-10-10 22:39:40 +00:00
|
|
|
};
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Frame(MyThread* t, Compiler* c, object method, uintptr_t* map,
|
|
|
|
Vector* objectPool, Vector* traceLog):
|
|
|
|
next(0),
|
2007-10-10 22:39:40 +00:00
|
|
|
t(t),
|
2007-12-09 22:45:43 +00:00
|
|
|
c(c),
|
2007-10-10 22:39:40 +00:00
|
|
|
method(method),
|
2007-12-09 22:45:43 +00:00
|
|
|
map(map),
|
|
|
|
objectPool(objectPool),
|
|
|
|
traceLog(traceLog),
|
|
|
|
codeMask(makeCodeMask(t, codeLength(t, methodCode(t, method)))),
|
|
|
|
ip(0),
|
|
|
|
sp(localSize(t, method)),
|
2007-10-13 21:48:40 +00:00
|
|
|
protector(this)
|
2007-12-09 22:45:43 +00:00
|
|
|
{
|
|
|
|
memset(map, 0, mapSizeInBytes(t, method));
|
|
|
|
}
|
|
|
|
|
|
|
|
Frame(Frame* f, uintptr_t* map):
|
|
|
|
next(f),
|
|
|
|
t(f->t),
|
|
|
|
c(f->c),
|
|
|
|
method(f->method),
|
|
|
|
map(map),
|
|
|
|
objectPool(f->objectPool),
|
|
|
|
traceLog(f->traceLog),
|
|
|
|
codeMask(f->codeMask),
|
|
|
|
ip(f->ip),
|
|
|
|
sp(f->sp),
|
|
|
|
protector(this)
|
|
|
|
{
|
|
|
|
memcpy(map, f->map, mapSizeInBytes(t, method));
|
|
|
|
}
|
2007-10-10 22:39:40 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
~Frame() {
|
|
|
|
t->m->system->free(codeMask);
|
2007-10-10 22:39:40 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* append(object o) {
|
|
|
|
new (objectPool->allocate(sizeof(PoolElement)))
|
|
|
|
PoolElement(o, c->poolOffset());
|
|
|
|
return c->poolAppend(c->constant(0));
|
2007-10-10 22:39:40 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
static unsigned parameterFootprint(Thread* t, object method) {
|
|
|
|
return methodParameterFootprint(t, method);
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned localSize(Thread* t, object method) {
|
|
|
|
return codeMaxLocals(t, methodCode(t, method))
|
|
|
|
- parameterFootprint(t, method);
|
2007-10-11 22:43:03 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
static unsigned stackSize(Thread* t, object method) {
|
|
|
|
return codeMaxStack(t, methodCode(t, method));
|
|
|
|
}
|
2007-10-11 22:43:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
static unsigned mapSize(Thread* t, object method) {
|
|
|
|
return stackSize(t, method) + localSize(t, method);
|
2007-10-10 22:39:40 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
static unsigned mapSizeInWords(Thread* t, object method) {
|
|
|
|
return ceiling(mapSize(t, method), BytesPerWord);
|
2007-10-11 22:43:03 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
static unsigned mapSizeInBytes(Thread* t, object method) {
|
|
|
|
return mapSizeInWords(t, method) * BytesPerWord;
|
2007-10-10 22:39:40 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
static unsigned traceSizeInBytes(Thread* t, object method) {
|
|
|
|
return BytesPerWord + BytesPerWord + 1 + mapSizeInWords(t, method);
|
2007-10-10 22:39:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void pushedInt() {
|
2007-12-09 22:45:43 +00:00
|
|
|
assert(t, sp + 1 <= mapSize(t, method));
|
|
|
|
assert(t, getBit(map, sp) == 0);
|
|
|
|
++ sp;
|
2007-10-10 22:39:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void pushedObject() {
|
2007-12-09 22:45:43 +00:00
|
|
|
assert(t, sp + 1 <= mapSize(t, method));
|
|
|
|
markBit(map, sp++);
|
|
|
|
}
|
|
|
|
|
|
|
|
void poppedInt() {
|
|
|
|
assert(t, sp >= 1);
|
|
|
|
assert(t, sp - 1 >= localSize(t, method));
|
|
|
|
assert(t, getBit(map, sp - 1) == 0);
|
|
|
|
-- sp;
|
|
|
|
}
|
|
|
|
|
|
|
|
void poppedObject() {
|
|
|
|
assert(t, sp >= 1);
|
|
|
|
assert(t, sp - 1 >= localSize(t, method));
|
|
|
|
assert(t, getBit(map, sp - 1) != 0);
|
|
|
|
clearBit(map, -- sp);
|
|
|
|
}
|
|
|
|
|
|
|
|
void storedInt(unsigned index) {
|
|
|
|
assert(t, index < localSize(t, method));
|
|
|
|
clearBit(map, index);
|
|
|
|
}
|
|
|
|
|
|
|
|
void storedObject(unsigned index) {
|
|
|
|
assert(t, index < localSize(t, method));
|
|
|
|
markBit(map, index);
|
2007-10-10 22:39:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void dupped() {
|
2007-12-09 22:45:43 +00:00
|
|
|
assert(t, sp + 1 <= mapSize(t, method));
|
|
|
|
assert(t, sp - 1 >= localSize(t, method));
|
|
|
|
if (getBit(map, sp - 1)) {
|
|
|
|
markBit(map, sp);
|
|
|
|
}
|
|
|
|
++ sp;
|
2007-10-10 22:39:40 +00:00
|
|
|
}
|
|
|
|
|
2007-10-16 17:21:26 +00:00
|
|
|
void duppedX1() {
|
2007-12-09 22:45:43 +00:00
|
|
|
assert(t, sp + 1 <= mapSize(t, method));
|
|
|
|
assert(t, sp - 2 >= localSize(t, method));
|
|
|
|
|
|
|
|
unsigned b2 = getBit(map, sp - 2);
|
|
|
|
unsigned b1 = getBit(map, sp - 1);
|
|
|
|
|
|
|
|
if (b2) {
|
|
|
|
markBit(map, sp - 1);
|
|
|
|
} else {
|
|
|
|
clearBit(map, sp - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (b1) {
|
|
|
|
markBit(map, sp - 2);
|
|
|
|
markBit(map, sp);
|
|
|
|
} else {
|
|
|
|
clearBit(map, sp - 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
++ sp;
|
2007-10-16 17:21:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void duppedX2() {
|
2007-12-09 22:45:43 +00:00
|
|
|
assert(t, sp + 1 <= mapSize(t, method));
|
|
|
|
assert(t, sp - 3 >= localSize(t, method));
|
|
|
|
|
|
|
|
unsigned b3 = getBit(map, sp - 3);
|
|
|
|
unsigned b2 = getBit(map, sp - 2);
|
|
|
|
unsigned b1 = getBit(map, sp - 1);
|
|
|
|
|
|
|
|
if (b3) {
|
|
|
|
markBit(map, sp - 2);
|
|
|
|
} else {
|
|
|
|
clearBit(map, sp - 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (b2) {
|
|
|
|
markBit(map, sp - 1);
|
|
|
|
} else {
|
|
|
|
clearBit(map, sp - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (b1) {
|
|
|
|
markBit(map, sp - 3);
|
|
|
|
markBit(map, sp);
|
|
|
|
} else {
|
|
|
|
clearBit(map, sp - 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
++ sp;
|
2007-10-16 17:21:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void dupped2() {
|
2007-12-09 22:45:43 +00:00
|
|
|
assert(t, sp + 2 <= mapSize(t, method));
|
|
|
|
assert(t, sp - 2 >= localSize(t, method));
|
|
|
|
|
|
|
|
unsigned b2 = getBit(map, sp - 2);
|
|
|
|
unsigned b1 = getBit(map, sp - 1);
|
|
|
|
|
|
|
|
if (b2) {
|
|
|
|
markBit(map, sp);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (b1) {
|
|
|
|
markBit(map, sp + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
sp += 2;
|
2007-10-16 17:21:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void dupped2X1() {
|
2007-12-09 22:45:43 +00:00
|
|
|
assert(t, sp + 2 <= mapSize(t, method));
|
|
|
|
assert(t, sp - 3 >= localSize(t, method));
|
|
|
|
|
|
|
|
unsigned b3 = getBit(map, sp - 3);
|
|
|
|
unsigned b2 = getBit(map, sp - 2);
|
|
|
|
unsigned b1 = getBit(map, sp - 1);
|
|
|
|
|
|
|
|
if (b3) {
|
|
|
|
markBit(map, sp - 1);
|
|
|
|
} else {
|
|
|
|
clearBit(map, sp - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (b2) {
|
|
|
|
markBit(map, sp - 3);
|
|
|
|
markBit(map, sp);
|
|
|
|
} else {
|
|
|
|
clearBit(map, sp - 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (b1) {
|
|
|
|
markBit(map, sp - 2);
|
|
|
|
markBit(map, sp + 1);
|
|
|
|
} else {
|
|
|
|
clearBit(map, sp - 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
sp += 2;
|
2007-10-16 17:21:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void dupped2X2() {
|
2007-12-09 22:45:43 +00:00
|
|
|
assert(t, sp + 2 <= mapSize(t, method));
|
|
|
|
assert(t, sp - 4 >= localSize(t, method));
|
2007-10-16 17:21:26 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
unsigned b4 = getBit(map, sp - 4);
|
|
|
|
unsigned b3 = getBit(map, sp - 3);
|
|
|
|
unsigned b2 = getBit(map, sp - 2);
|
|
|
|
unsigned b1 = getBit(map, sp - 1);
|
2007-10-12 00:30:46 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
if (b4) {
|
|
|
|
markBit(map, sp - 2);
|
|
|
|
} else {
|
|
|
|
clearBit(map, sp - 2);
|
|
|
|
}
|
2007-10-10 22:39:40 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
if (b3) {
|
|
|
|
markBit(map, sp - 1);
|
|
|
|
} else {
|
|
|
|
clearBit(map, sp - 1);
|
|
|
|
}
|
2007-10-10 22:39:40 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
if (b2) {
|
|
|
|
markBit(map, sp - 4);
|
|
|
|
markBit(map, sp);
|
|
|
|
} else {
|
|
|
|
clearBit(map, sp - 4);
|
|
|
|
}
|
2007-10-10 22:39:40 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
if (b1) {
|
|
|
|
markBit(map, sp - 3);
|
|
|
|
markBit(map, sp + 1);
|
|
|
|
} else {
|
|
|
|
clearBit(map, sp - 3);
|
2007-10-13 21:48:40 +00:00
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
|
|
|
|
sp += 2;
|
2007-10-13 21:48:40 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void swapped() {
|
|
|
|
assert(t, sp - 1 >= localSize(t, method));
|
|
|
|
assert(t, sp - 2 >= localSize(t, method));
|
|
|
|
|
|
|
|
bool savedBit = getBit(map, sp - 1);
|
|
|
|
if (getBit(map, sp - 2)) {
|
|
|
|
markBit(map, sp - 1);
|
|
|
|
} else {
|
|
|
|
clearBit(map, sp - 1);
|
2007-10-13 21:48:40 +00:00
|
|
|
}
|
2007-10-10 22:39:40 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
if (savedBit) {
|
|
|
|
markBit(map, sp - 2);
|
|
|
|
} else {
|
|
|
|
clearBit(map, sp - 2);
|
2007-10-13 21:48:40 +00:00
|
|
|
}
|
2007-10-10 22:39:40 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void trace(object target, bool virtualCall) {
|
|
|
|
TraceElement* e = new (traceLog->allocate(traceSizeInBytes(t, method)))
|
|
|
|
TraceElement(target, c->codeOffset(), virtualCall);
|
|
|
|
memcpy(e->map, map, mapSizeInWords(t, method) * BytesPerWord);
|
2007-10-10 22:39:40 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void trace() {
|
|
|
|
trace(0, false);
|
2007-10-10 22:39:40 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void startLogicalIp(unsigned ip) {
|
|
|
|
c->startLogicalIp(ip);
|
|
|
|
this->ip = ip;
|
2007-10-11 22:43:03 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void pushInt(Operand* o) {
|
|
|
|
c->push(o);
|
|
|
|
pushedInt();
|
2007-10-11 22:43:03 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void pushObject(Operand* o) {
|
|
|
|
c->push(o);
|
|
|
|
pushedObject();
|
2007-10-11 22:43:03 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void pushLong(Operand* o) {
|
|
|
|
c->push2(o);
|
|
|
|
pushedInt();
|
|
|
|
pushedInt();
|
2007-10-11 22:43:03 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void pop(unsigned count) {
|
|
|
|
assert(t, sp >= count);
|
|
|
|
assert(t, sp - count >= localSize(t, method));
|
|
|
|
while (count) {
|
|
|
|
clearBit(map, -- sp);
|
|
|
|
-- count;
|
|
|
|
}
|
2007-10-11 22:43:03 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* topInt() {
|
|
|
|
assert(t, sp >= 1);
|
|
|
|
assert(t, sp - 1 >= localSize(t, method));
|
|
|
|
assert(t, getBit(map, sp - 1) == 0);
|
|
|
|
return c->stack(0);
|
2007-10-11 22:43:03 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* topLong() {
|
|
|
|
assert(t, sp >= 2);
|
|
|
|
assert(t, sp - 2 >= localSize(t, method));
|
|
|
|
assert(t, getBit(map, sp - 1) == 0);
|
|
|
|
assert(t, getBit(map, sp - 2) == 0);
|
2007-12-11 00:48:09 +00:00
|
|
|
return c->stack(1);
|
2007-10-11 22:43:03 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* topObject() {
|
|
|
|
assert(t, sp >= 1);
|
|
|
|
assert(t, sp - 1 >= localSize(t, method));
|
|
|
|
assert(t, getBit(map, sp - 1) != 0);
|
|
|
|
return c->stack(0);
|
2007-10-11 22:43:03 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* popInt() {
|
|
|
|
poppedInt();
|
|
|
|
return c->pop();
|
|
|
|
}
|
2007-10-11 22:43:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* popLong() {
|
|
|
|
poppedInt();
|
|
|
|
poppedInt();
|
|
|
|
return c->pop2();
|
|
|
|
}
|
2007-10-11 22:43:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* popObject() {
|
|
|
|
poppedObject();
|
|
|
|
return c->pop();
|
|
|
|
}
|
2007-10-11 22:43:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void popInt(Operand* o) {
|
|
|
|
c->pop(o);
|
|
|
|
poppedInt();
|
|
|
|
}
|
2007-10-11 22:43:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void popLong(Operand* o) {
|
|
|
|
c->pop2(o);
|
|
|
|
poppedInt();
|
|
|
|
poppedInt();
|
|
|
|
}
|
2007-10-11 22:43:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void popObject(Operand* o) {
|
|
|
|
c->pop(o);
|
|
|
|
poppedObject();
|
2007-10-11 22:43:03 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void loadInt(unsigned index) {
|
|
|
|
assert(t, index < localSize(t, method));
|
|
|
|
assert(t, getBit(map, index) == 0);
|
|
|
|
pushInt(c->memory(c->base(), localOffset(t, index, method)));
|
2007-10-10 22:39:40 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void loadLong(unsigned index) {
|
|
|
|
assert(t, index < localSize(t, method) - 1);
|
|
|
|
assert(t, getBit(map, index) == 0);
|
|
|
|
assert(t, getBit(map, index + 1) == 0);
|
|
|
|
pushLong(c->memory(c->base(), localOffset(t, index, method)));
|
|
|
|
}
|
2007-10-11 22:43:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void loadObject(unsigned index) {
|
|
|
|
assert(t, index < localSize(t, method));
|
|
|
|
assert(t, getBit(map, index) != 0);
|
|
|
|
pushObject(c->memory(c->base(), localOffset(t, index, method)));
|
|
|
|
}
|
2007-10-11 22:43:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void storeInt(unsigned index) {
|
|
|
|
popInt(c->memory(c->base(), localOffset(t, index, method)));
|
|
|
|
storedInt(index);
|
|
|
|
}
|
2007-10-11 22:43:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void storeLong(unsigned index) {
|
|
|
|
popLong(c->memory(c->base(), localOffset(t, index, method)));
|
|
|
|
storedInt(index);
|
|
|
|
storedInt(index + 1);
|
|
|
|
}
|
2007-10-11 22:43:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void storeObject(unsigned index) {
|
|
|
|
popObject(c->memory(c->base(), localOffset(t, index, method)));
|
|
|
|
storedObject(index);
|
|
|
|
}
|
2007-10-11 22:43:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void increment(unsigned index, unsigned count) {
|
|
|
|
assert(t, index < localSize(t, method));
|
|
|
|
assert(t, getBit(map, index) == 0);
|
|
|
|
c->add(c->constant(count),
|
|
|
|
c->memory(c->base(), localOffset(t, index, method)));
|
|
|
|
}
|
2007-10-11 22:43:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void dup() {
|
|
|
|
c->push(c->stack(0));
|
|
|
|
dupped();
|
|
|
|
}
|
2007-10-11 22:43:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void dupX1() {
|
|
|
|
Operand* s0 = c->stack(0);
|
|
|
|
Operand* s1 = c->stack(1);
|
2007-10-11 22:43:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->mov(s0, s1);
|
|
|
|
c->mov(s1, s0);
|
|
|
|
c->push(s0);
|
2007-10-11 22:43:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
duppedX1();
|
|
|
|
}
|
2007-10-11 22:43:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void dupX2() {
|
|
|
|
Operand* s0 = c->stack(0);
|
|
|
|
Operand* s1 = c->stack(1);
|
|
|
|
Operand* s2 = c->stack(2);
|
2007-10-11 22:43:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->mov(s0, s2);
|
|
|
|
c->mov(s2, s1);
|
|
|
|
c->mov(s1, s0);
|
|
|
|
c->push(s0);
|
2007-10-11 22:43:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
duppedX2();
|
2007-10-10 22:39:40 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void dup2() {
|
|
|
|
Operand* s0 = c->stack(0);
|
2007-10-13 21:48:40 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->push(s0);
|
|
|
|
c->push(s0);
|
2007-10-13 21:48:40 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
dupped2();
|
|
|
|
}
|
2007-10-13 21:48:40 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void dup2X1() {
|
|
|
|
Operand* s0 = c->stack(0);
|
|
|
|
Operand* s1 = c->stack(1);
|
|
|
|
Operand* s2 = c->stack(2);
|
2007-10-10 22:39:40 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->mov(s1, s2);
|
|
|
|
c->mov(s0, s1);
|
|
|
|
c->mov(s2, s0);
|
|
|
|
c->push(s1);
|
|
|
|
c->push(s0);
|
|
|
|
|
|
|
|
dupped2X1();
|
2007-10-18 00:41:49 +00:00
|
|
|
}
|
2007-10-01 15:19:15 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void dup2X2() {
|
|
|
|
Operand* s0 = c->stack(0);
|
|
|
|
Operand* s1 = c->stack(1);
|
|
|
|
Operand* s2 = c->stack(2);
|
|
|
|
Operand* s3 = c->stack(3);
|
2007-10-01 15:19:15 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->mov(s1, s3);
|
|
|
|
c->mov(s0, s2);
|
|
|
|
c->mov(s3, s1);
|
|
|
|
c->mov(s2, s0);
|
|
|
|
c->push(s1);
|
|
|
|
c->push(s0);
|
2007-10-02 00:08:17 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
dupped2X2();
|
|
|
|
}
|
2007-10-02 00:08:17 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void swap() {
|
|
|
|
Operand* s0 = c->stack(0);
|
|
|
|
Operand* s1 = c->stack(1);
|
|
|
|
Operand* tmp = c->temporary();
|
2007-10-02 00:08:17 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->mov(s0, tmp);
|
|
|
|
c->mov(s1, s0);
|
|
|
|
c->mov(tmp, s1);
|
2007-10-02 00:08:17 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->release(tmp);
|
2007-10-02 00:08:17 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
swapped();
|
2007-10-02 00:08:17 +00:00
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
|
|
|
|
Frame* next;
|
|
|
|
MyThread* t;
|
|
|
|
Compiler* c;
|
|
|
|
object method;
|
|
|
|
uintptr_t* map;
|
|
|
|
Vector* objectPool;
|
|
|
|
Vector* traceLog;
|
|
|
|
uintptr_t* codeMask;
|
|
|
|
unsigned ip;
|
|
|
|
unsigned sp;
|
|
|
|
MyProtector protector;
|
|
|
|
};
|
2007-10-18 00:41:49 +00:00
|
|
|
|
2007-10-01 15:19:15 +00:00
|
|
|
void NO_RETURN
|
2007-10-03 00:22:48 +00:00
|
|
|
unwind(MyThread* t)
|
2007-09-29 21:08:29 +00:00
|
|
|
{
|
2007-12-09 22:45:43 +00:00
|
|
|
void* base = t->base;
|
|
|
|
void** stack = static_cast<void**>(t->stack);
|
|
|
|
while (true) {
|
|
|
|
void* returnAddress = *stack;
|
|
|
|
object node = findTraceNode(t, returnAddress);
|
|
|
|
if (node) {
|
|
|
|
object method = traceNodeMethod(t, node);
|
|
|
|
uint8_t* compiled = reinterpret_cast<uint8_t*>
|
|
|
|
(&singletonValue(t, methodCompiled(t, method), 0));
|
|
|
|
|
|
|
|
ExceptionHandler* handler = findExceptionHandler
|
|
|
|
(t, method, difference(returnAddress, compiled));
|
|
|
|
|
|
|
|
if (handler) {
|
2007-10-04 22:41:19 +00:00
|
|
|
unsigned parameterFootprint = methodParameterFootprint(t, method);
|
2007-12-09 22:45:43 +00:00
|
|
|
unsigned localFootprint = codeMaxLocals(t, methodCode(t, method));
|
2007-10-04 22:41:19 +00:00
|
|
|
|
|
|
|
if (localFootprint > parameterFootprint) {
|
|
|
|
stack -= (localFootprint - parameterFootprint);
|
|
|
|
}
|
|
|
|
|
|
|
|
*(--stack) = t->exception;
|
|
|
|
t->exception = 0;
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
vmJump(compiled + exceptionHandlerIp(handler), base, stack);
|
|
|
|
} else {
|
|
|
|
stack = static_cast<void**>(base) + 1;
|
|
|
|
base = *static_cast<void**>(base);
|
2007-10-12 17:56:43 +00:00
|
|
|
}
|
2007-10-12 22:06:33 +00:00
|
|
|
} else {
|
2007-12-09 22:45:43 +00:00
|
|
|
vmJump(returnAddress, base, stack + 1);
|
2007-10-12 17:56:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-10-16 17:21:26 +00:00
|
|
|
object
|
|
|
|
findInterfaceMethodFromInstance(Thread* t, object method, object instance)
|
|
|
|
{
|
|
|
|
return findInterfaceMethod(t, method, objectClass(t, instance));
|
|
|
|
}
|
|
|
|
|
2007-10-15 19:12:38 +00:00
|
|
|
intptr_t
|
|
|
|
compareDoublesG(uint64_t bi, uint64_t ai)
|
|
|
|
{
|
|
|
|
double a = bitsToDouble(ai);
|
|
|
|
double b = bitsToDouble(bi);
|
|
|
|
|
|
|
|
if (a < b) {
|
|
|
|
return -1;
|
|
|
|
} else if (a > b) {
|
|
|
|
return 1;
|
|
|
|
} else if (a == b) {
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
intptr_t
|
|
|
|
compareDoublesL(uint64_t bi, uint64_t ai)
|
|
|
|
{
|
|
|
|
double a = bitsToDouble(ai);
|
|
|
|
double b = bitsToDouble(bi);
|
|
|
|
|
|
|
|
if (a < b) {
|
|
|
|
return -1;
|
|
|
|
} else if (a > b) {
|
|
|
|
return 1;
|
|
|
|
} else if (a == b) {
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
intptr_t
|
|
|
|
compareFloatsG(uint32_t bi, uint32_t ai)
|
|
|
|
{
|
|
|
|
float a = bitsToFloat(ai);
|
|
|
|
float b = bitsToFloat(bi);
|
|
|
|
|
|
|
|
if (a < b) {
|
|
|
|
return -1;
|
|
|
|
} else if (a > b) {
|
|
|
|
return 1;
|
|
|
|
} else if (a == b) {
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
intptr_t
|
|
|
|
compareFloatsL(uint32_t bi, uint32_t ai)
|
|
|
|
{
|
|
|
|
float a = bitsToFloat(ai);
|
|
|
|
float b = bitsToFloat(bi);
|
|
|
|
|
|
|
|
if (a < b) {
|
|
|
|
return -1;
|
|
|
|
} else if (a > b) {
|
|
|
|
return 1;
|
|
|
|
} else if (a == b) {
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
addDouble(uint64_t b, uint64_t a)
|
|
|
|
{
|
|
|
|
return doubleToBits(bitsToDouble(a) + bitsToDouble(b));
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
subtractDouble(uint64_t b, uint64_t a)
|
|
|
|
{
|
|
|
|
return doubleToBits(bitsToDouble(a) - bitsToDouble(b));
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
multiplyDouble(uint64_t b, uint64_t a)
|
|
|
|
{
|
|
|
|
return doubleToBits(bitsToDouble(a) * bitsToDouble(b));
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
divideDouble(uint64_t b, uint64_t a)
|
|
|
|
{
|
|
|
|
return doubleToBits(bitsToDouble(a) / bitsToDouble(b));
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
moduloDouble(uint64_t b, uint64_t a)
|
|
|
|
{
|
|
|
|
return doubleToBits(fmod(bitsToDouble(a), bitsToDouble(b)));
|
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
uint64_t
|
|
|
|
negateDouble(uint64_t a)
|
|
|
|
{
|
|
|
|
return doubleToBits(- bitsToDouble(a));
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t
|
|
|
|
doubleToFloat(int64_t a)
|
|
|
|
{
|
|
|
|
return floatToBits(static_cast<float>(bitsToDouble(a)));
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t
|
|
|
|
doubleToInt(int64_t a)
|
|
|
|
{
|
|
|
|
return static_cast<int32_t>(bitsToDouble(a));
|
|
|
|
}
|
|
|
|
|
|
|
|
int64_t
|
|
|
|
doubleToLong(int64_t a)
|
|
|
|
{
|
|
|
|
return static_cast<int64_t>(bitsToDouble(a));
|
|
|
|
}
|
|
|
|
|
2007-10-15 19:12:38 +00:00
|
|
|
uint32_t
|
|
|
|
addFloat(uint32_t b, uint32_t a)
|
|
|
|
{
|
|
|
|
return floatToBits(bitsToFloat(a) + bitsToFloat(b));
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t
|
|
|
|
subtractFloat(uint32_t b, uint32_t a)
|
|
|
|
{
|
|
|
|
return floatToBits(bitsToFloat(a) - bitsToFloat(b));
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t
|
|
|
|
multiplyFloat(uint32_t b, uint32_t a)
|
|
|
|
{
|
|
|
|
return floatToBits(bitsToFloat(a) * bitsToFloat(b));
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t
|
|
|
|
divideFloat(uint32_t b, uint32_t a)
|
|
|
|
{
|
|
|
|
return floatToBits(bitsToFloat(a) / bitsToFloat(b));
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t
|
|
|
|
moduloFloat(uint32_t b, uint32_t a)
|
|
|
|
{
|
|
|
|
return floatToBits(fmod(bitsToFloat(a), bitsToFloat(b)));
|
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
uint32_t
|
|
|
|
negateFloat(uint32_t a)
|
|
|
|
{
|
|
|
|
return floatToBits(- bitsToFloat(a));
|
|
|
|
}
|
|
|
|
|
2007-10-08 21:41:41 +00:00
|
|
|
int64_t
|
2007-10-15 19:12:38 +00:00
|
|
|
divideLong(int64_t b, int64_t a)
|
2007-10-08 21:41:41 +00:00
|
|
|
{
|
|
|
|
return a / b;
|
|
|
|
}
|
|
|
|
|
|
|
|
int64_t
|
2007-10-15 19:12:38 +00:00
|
|
|
moduloLong(int64_t b, int64_t a)
|
2007-10-08 21:41:41 +00:00
|
|
|
{
|
|
|
|
return a % b;
|
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
uint64_t
|
|
|
|
floatToDouble(int32_t a)
|
|
|
|
{
|
|
|
|
return doubleToBits(static_cast<double>(bitsToFloat(a)));
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t
|
|
|
|
floatToInt(int32_t a)
|
|
|
|
{
|
|
|
|
return static_cast<int32_t>(bitsToFloat(a));
|
|
|
|
}
|
|
|
|
|
|
|
|
int64_t
|
|
|
|
floatToLong(int32_t a)
|
|
|
|
{
|
|
|
|
return static_cast<int64_t>(bitsToFloat(a));
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
intToDouble(int32_t a)
|
|
|
|
{
|
|
|
|
return doubleToBits(static_cast<double>(a));
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t
|
|
|
|
intToFloat(int32_t a)
|
|
|
|
{
|
|
|
|
return floatToBits(static_cast<float>(a));
|
|
|
|
}
|
|
|
|
|
2007-09-30 02:48:27 +00:00
|
|
|
object
|
|
|
|
makeBlankObjectArray(Thread* t, object class_, int32_t length)
|
|
|
|
{
|
|
|
|
return makeObjectArray(t, class_, length, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
object
|
|
|
|
makeBlankArray(Thread* t, object (*constructor)(Thread*, uintptr_t, bool),
|
|
|
|
int32_t length)
|
|
|
|
{
|
|
|
|
return constructor(t, length, true);
|
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
uintptr_t
|
|
|
|
lookUpAddress(int32_t key, uintptr_t* start, int32_t count,
|
|
|
|
uintptr_t* default_)
|
2007-10-01 15:19:15 +00:00
|
|
|
{
|
2007-12-09 22:45:43 +00:00
|
|
|
int32_t bottom = 0;
|
|
|
|
int32_t top = count;
|
|
|
|
for (int32_t span = top - bottom; span; span = top - bottom) {
|
|
|
|
int32_t middle = bottom + (span / 2);
|
|
|
|
uintptr_t* p = start + (middle * 2);
|
|
|
|
int32_t k = *p;
|
|
|
|
|
|
|
|
if (key < k) {
|
|
|
|
top = middle;
|
|
|
|
} else if (key > k) {
|
|
|
|
bottom = middle + 1;
|
|
|
|
} else {
|
|
|
|
return p[1];
|
2007-10-01 15:19:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
return *default_;
|
|
|
|
}
|
2007-10-01 15:19:15 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void
|
|
|
|
acquireMonitorForObject(Thread* t, object o)
|
|
|
|
{
|
|
|
|
acquire(t, o);
|
|
|
|
}
|
2007-10-01 15:19:15 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void
|
|
|
|
releaseMonitorForObject(Thread* t, object o)
|
|
|
|
{
|
|
|
|
release(t, o);
|
|
|
|
}
|
2007-10-01 15:19:15 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
object
|
|
|
|
makeMultidimensionalArray2(MyThread* t, object class_, uintptr_t* stack,
|
|
|
|
int32_t dimensions)
|
|
|
|
{
|
|
|
|
PROTECT(t, class_);
|
2007-10-01 15:19:15 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
int32_t counts[dimensions];
|
|
|
|
for (int i = dimensions - 1; i >= 0; --i) {
|
|
|
|
counts[i] = stack[dimensions - i - 1];
|
|
|
|
if (UNLIKELY(counts[i] < 0)) {
|
|
|
|
object message = makeString(t, "%d", counts[i]);
|
|
|
|
t->exception = makeNegativeArraySizeException(t, message);
|
|
|
|
return 0;
|
2007-10-01 15:19:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
object array = makeArray(t, counts[0], true);
|
|
|
|
setObjectClass(t, array, class_);
|
|
|
|
PROTECT(t, array);
|
2007-10-01 15:19:15 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
populateMultiArray(t, array, counts, 0, dimensions);
|
2007-10-01 15:19:15 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
return array;
|
2007-10-01 15:19:15 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
object
|
|
|
|
makeMultidimensionalArray(MyThread* t, object class_, uintptr_t* stack,
|
|
|
|
int32_t dimensions)
|
2007-10-01 15:19:15 +00:00
|
|
|
{
|
2007-12-09 22:45:43 +00:00
|
|
|
object r = makeMultidimensionalArray2(t, class_, stack, dimensions);
|
2007-10-01 15:19:15 +00:00
|
|
|
if (UNLIKELY(t->exception)) {
|
|
|
|
unwind(t);
|
|
|
|
} else {
|
2007-12-09 22:45:43 +00:00
|
|
|
return r;
|
2007-10-01 15:19:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void NO_RETURN
|
|
|
|
throwNew(MyThread* t, object class_)
|
2007-09-27 00:01:38 +00:00
|
|
|
{
|
2007-12-09 22:45:43 +00:00
|
|
|
t->exception = makeNew(t, class_);
|
|
|
|
object trace = makeTrace(t);
|
|
|
|
set(t, t->exception, ThrowableTrace, trace);
|
|
|
|
unwind(t);
|
2007-09-27 00:01:38 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void NO_RETURN
|
|
|
|
throw_(MyThread* t, object o)
|
2007-10-09 17:15:40 +00:00
|
|
|
{
|
2007-12-09 22:45:43 +00:00
|
|
|
if (o) {
|
|
|
|
t->exception = o;
|
|
|
|
} else {
|
|
|
|
t->exception = makeNullPointerException(t);
|
2007-10-08 21:41:41 +00:00
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
unwind(t);
|
|
|
|
}
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void
|
|
|
|
compileThrowNew(MyThread* t, Frame* frame, Machine::Type type)
|
|
|
|
{
|
|
|
|
Operand* class_ = frame->append(arrayBody(t, t->m->types, type));
|
|
|
|
Compiler* c = frame->c;
|
|
|
|
c->indirectCallNoReturn
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(throwNew)),
|
|
|
|
2, c->thread(), class_);
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
frame->trace();
|
|
|
|
}
|
2007-09-25 23:53:11 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void
|
|
|
|
pushReturnValue(MyThread* t, Frame* frame, unsigned code, Operand* result)
|
|
|
|
{
|
|
|
|
switch (code) {
|
|
|
|
case ByteField:
|
|
|
|
case BooleanField:
|
|
|
|
case CharField:
|
|
|
|
case ShortField:
|
|
|
|
case FloatField:
|
|
|
|
case IntField:
|
|
|
|
frame->pushInt(result);
|
|
|
|
break;
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case ObjectField:
|
|
|
|
frame->pushObject(result);
|
|
|
|
break;
|
2007-09-25 23:53:11 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case LongField:
|
|
|
|
case DoubleField:
|
|
|
|
frame->pushLong(result);
|
|
|
|
break;
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case VoidField:
|
|
|
|
break;
|
2007-09-25 23:53:11 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
default:
|
|
|
|
abort(t);
|
2007-10-17 01:21:35 +00:00
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2007-10-17 01:21:35 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void
|
|
|
|
compileDirectInvoke(MyThread* t, Frame* frame, object target)
|
|
|
|
{
|
|
|
|
Operand* result = frame->c->alignedCall
|
|
|
|
(frame->c->constant
|
|
|
|
(reinterpret_cast<intptr_t>
|
|
|
|
(&singletonBody(t, methodCompiled(t, target), 0))));
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
frame->trace(target, false);
|
2007-09-25 23:53:11 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
frame->pop(methodParameterFootprint(t, target));
|
2007-09-25 23:53:11 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
pushReturnValue(t, frame, methodReturnCode(t, target), result);
|
|
|
|
}
|
2007-10-17 01:21:35 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void
|
|
|
|
compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
|
|
|
{
|
|
|
|
uintptr_t map[Frame::mapSizeInWords(t, initialFrame->method)];
|
|
|
|
Frame myFrame(initialFrame, map);
|
|
|
|
Frame* frame = &myFrame;
|
|
|
|
Compiler* c = frame->c;
|
2007-09-25 23:53:11 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
object code = methodCode(t, frame->method);
|
|
|
|
PROTECT(t, code);
|
|
|
|
|
|
|
|
while (ip < codeLength(t, code)) {
|
|
|
|
if (getBit(frame->codeMask, ip)) {
|
|
|
|
// we've already visited this part of the code
|
|
|
|
return;
|
2007-09-30 04:07:22 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
markBit(frame->codeMask, ip);
|
2007-10-17 01:21:35 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
frame->startLogicalIp(ip);
|
2007-10-17 01:21:35 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
unsigned instruction = codeBody(t, code, ip++);
|
2007-09-25 23:53:11 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
switch (instruction) {
|
|
|
|
case aaload:
|
|
|
|
case baload:
|
|
|
|
case caload:
|
|
|
|
case daload:
|
|
|
|
case faload:
|
|
|
|
case iaload:
|
|
|
|
case laload:
|
|
|
|
case saload: {
|
|
|
|
Operand* next = c->label();
|
|
|
|
Operand* outOfBounds = c->label();
|
2007-09-28 23:41:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* index = frame->popInt();
|
|
|
|
Operand* array = frame->popObject();
|
2007-09-28 23:41:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->cmp(c->constant(0), index);
|
|
|
|
c->jl(outOfBounds);
|
2007-09-28 23:41:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->cmp(c->memory(array, ArrayLength), index);
|
|
|
|
c->jge(outOfBounds);
|
2007-09-25 23:53:11 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
switch (instruction) {
|
|
|
|
case aaload:
|
|
|
|
frame->pushObject(c->memory(array, ArrayBody, index, BytesPerWord));
|
|
|
|
break;
|
2007-09-25 23:53:11 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case faload:
|
|
|
|
case iaload:
|
|
|
|
frame->pushInt(c->select4(c->memory(array, ArrayBody, index, 4)));
|
|
|
|
break;
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case baload:
|
|
|
|
frame->pushInt(c->select1(c->memory(array, ArrayBody, index, 1)));
|
|
|
|
break;
|
2007-09-28 23:41:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case caload:
|
|
|
|
frame->pushInt(c->select2z(c->memory(array, ArrayBody, index, 2)));
|
|
|
|
break;
|
2007-09-28 23:41:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case daload:
|
|
|
|
case laload:
|
|
|
|
frame->pushInt(c->select8(c->memory(array, ArrayBody, index, 8)));
|
|
|
|
break;
|
2007-09-25 23:53:11 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case saload:
|
|
|
|
frame->pushInt(c->select2(c->memory(array, ArrayBody, index, 2)));
|
|
|
|
break;
|
|
|
|
}
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->jmp(next);
|
2007-09-29 20:24:14 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->mark(outOfBounds);
|
|
|
|
compileThrowNew(t, frame, Machine::ArrayIndexOutOfBoundsExceptionType);
|
2007-09-25 23:53:11 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->mark(next);
|
|
|
|
} break;
|
2007-09-28 23:41:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case aastore:
|
|
|
|
case bastore:
|
|
|
|
case castore:
|
|
|
|
case dastore:
|
|
|
|
case fastore:
|
|
|
|
case iastore:
|
|
|
|
case lastore:
|
|
|
|
case sastore: {
|
|
|
|
Operand* next = c->label();
|
|
|
|
Operand* outOfBounds = c->label();
|
|
|
|
|
|
|
|
Operand* value;
|
|
|
|
if (instruction == dastore or instruction == lastore) {
|
|
|
|
value = frame->popLong();
|
|
|
|
} else if (instruction == aastore) {
|
|
|
|
value = frame->popObject();
|
|
|
|
} else {
|
|
|
|
value = frame->popInt();
|
|
|
|
}
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* index = frame->popInt();
|
|
|
|
Operand* array = frame->popObject();
|
2007-09-28 23:41:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->cmp(c->constant(0), index);
|
|
|
|
c->jl(outOfBounds);
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->cmp(c->memory(array, BytesPerWord), index);
|
|
|
|
c->jge(outOfBounds);
|
2007-09-29 20:24:14 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
switch (instruction) {
|
|
|
|
case aastore:
|
|
|
|
c->shl(c->constant(log(BytesPerWord)), index);
|
|
|
|
c->add(c->constant(ArrayBody), index);
|
|
|
|
|
|
|
|
c->directCall
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(set)),
|
|
|
|
4, c->thread(), array, index, value);
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
frame->trace();
|
|
|
|
break;
|
2007-09-29 20:24:14 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case fastore:
|
|
|
|
case iastore:
|
|
|
|
c->mov(value, c->select4(c->memory(array, ArrayBody, index, 4)));
|
|
|
|
break;
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case bastore:
|
|
|
|
c->mov(value, c->select1(c->memory(array, ArrayBody, index, 1)));
|
|
|
|
break;
|
2007-09-25 23:53:11 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case castore:
|
|
|
|
case sastore:
|
|
|
|
c->mov(value, c->select2(c->memory(array, ArrayBody, index, 2)));
|
|
|
|
break;
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case dastore:
|
|
|
|
case lastore:
|
|
|
|
c->mov(value, c->select8(c->memory(array, ArrayBody, index, 8)));
|
|
|
|
break;
|
|
|
|
}
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->jmp(next);
|
2007-09-30 15:52:21 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->mark(outOfBounds);
|
|
|
|
compileThrowNew(t, frame, Machine::ArrayIndexOutOfBoundsExceptionType);
|
2007-09-25 23:53:11 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->mark(next);
|
|
|
|
} break;
|
2007-09-30 15:52:21 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case aconst_null:
|
|
|
|
frame->pushObject(c->constant(0));
|
|
|
|
break;
|
2007-09-25 23:53:11 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case aload:
|
|
|
|
frame->loadObject(codeBody(t, code, ip++));
|
|
|
|
break;
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case aload_0:
|
|
|
|
frame->loadObject(0);
|
|
|
|
break;
|
2007-10-08 23:13:55 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case aload_1:
|
|
|
|
frame->loadObject(1);
|
|
|
|
break;
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case aload_2:
|
|
|
|
frame->loadObject(2);
|
|
|
|
break;
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case aload_3:
|
|
|
|
frame->loadObject(3);
|
|
|
|
break;
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case anewarray: {
|
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
|
|
|
|
|
|
|
object class_ = resolveClassInPool(t, codePool(t, code), index - 1);
|
|
|
|
if (UNLIKELY(t->exception)) return;
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* nonnegative = c->label();
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* length = frame->popInt();
|
|
|
|
c->cmp(c->constant(0), length);
|
|
|
|
c->jge(nonnegative);
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
compileThrowNew(t, frame, Machine::NegativeArraySizeExceptionType);
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->mark(nonnegative);
|
2007-10-08 23:13:55 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* r = c->indirectCall
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(makeBlankObjectArray)),
|
|
|
|
3, c->thread(), frame->append(class_), length);
|
2007-09-24 01:39:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
frame->trace();
|
2007-09-28 23:41:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
frame->pushObject(r);
|
|
|
|
} break;
|
2007-09-28 23:41:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case areturn:
|
|
|
|
c->epilogue();
|
|
|
|
c->return_(frame->popObject());
|
|
|
|
return;
|
2007-09-28 23:41:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case arraylength:
|
|
|
|
frame->pushInt(c->memory(frame->popObject(), ArrayLength));
|
|
|
|
break;
|
2007-10-04 03:19:39 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case astore:
|
|
|
|
frame->storeObject(codeBody(t, code, ip++));
|
|
|
|
break;
|
2007-10-10 21:34:04 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case astore_0:
|
|
|
|
frame->storeObject(0);
|
|
|
|
break;
|
2007-10-17 17:22:09 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case astore_1:
|
|
|
|
frame->storeObject(1);
|
|
|
|
break;
|
2007-10-10 21:34:04 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case astore_2:
|
|
|
|
frame->storeObject(2);
|
|
|
|
break;
|
2007-10-10 21:34:04 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case astore_3:
|
|
|
|
frame->storeObject(3);
|
|
|
|
break;
|
2007-10-10 21:34:04 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case athrow:
|
|
|
|
c->indirectCallNoReturn
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(throw_)),
|
|
|
|
2, c->thread(), frame->popObject());
|
2007-10-10 21:34:04 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
frame->trace();
|
|
|
|
break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case bipush:
|
|
|
|
frame->pushInt
|
|
|
|
(c->constant(static_cast<int8_t>(codeBody(t, code, ip++))));
|
|
|
|
break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case checkcast: {
|
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
object class_ = resolveClassInPool(t, codePool(t, code), index - 1);
|
|
|
|
if (UNLIKELY(t->exception)) return;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* next = c->label();
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* instance = frame->topObject();
|
|
|
|
Operand* tmp = c->temporary();
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->mov(instance, tmp);
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->cmp(c->constant(0), tmp);
|
|
|
|
c->je(next);
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* classOperand = frame->append(class_);
|
2007-10-10 21:34:04 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->mov(c->memory(tmp), tmp);
|
|
|
|
c->and_(c->constant(PointerMask), tmp);
|
2007-10-10 22:39:40 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->cmp(classOperand, tmp);
|
|
|
|
c->je(next);
|
2007-10-10 22:39:40 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* result = c->directCall
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(isAssignableFrom)),
|
|
|
|
2, classOperand, tmp);
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->release(tmp);
|
2007-10-10 21:34:04 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->cmp(0, result);
|
|
|
|
c->jne(next);
|
|
|
|
|
|
|
|
compileThrowNew(t, frame, Machine::ClassCastExceptionType);
|
2007-10-10 21:34:04 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->mark(next);
|
|
|
|
} break;
|
2007-10-10 21:34:04 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case d2f: {
|
|
|
|
Operand* a = frame->popLong();
|
|
|
|
frame->pushInt
|
|
|
|
(c->directCall
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(doubleToFloat)), 1, a));
|
|
|
|
} break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case d2i: {
|
|
|
|
Operand* a = frame->popLong();
|
|
|
|
frame->pushInt
|
|
|
|
(c->directCall
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(doubleToInt)), 1, a));
|
|
|
|
} break;
|
2007-09-24 01:39:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case d2l: {
|
|
|
|
Operand* a = frame->popLong();
|
|
|
|
frame->pushLong
|
|
|
|
(c->directCall
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(doubleToLong)), 1, a));
|
|
|
|
} break;
|
2007-10-10 21:34:04 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case dadd: {
|
|
|
|
Operand* a = frame->popLong();
|
|
|
|
Operand* b = frame->popLong();
|
|
|
|
frame->pushLong
|
|
|
|
(c->directCall
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(addDouble)), 2, a, b));
|
|
|
|
} break;
|
2007-10-10 21:34:04 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case dcmpg: {
|
|
|
|
Operand* a = frame->popLong();
|
|
|
|
Operand* b = frame->popLong();
|
|
|
|
frame->pushInt
|
|
|
|
(c->directCall
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(compareDoublesG)), 2, a, b));
|
|
|
|
} break;
|
2007-10-10 21:34:04 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case dcmpl: {
|
|
|
|
Operand* a = frame->popLong();
|
|
|
|
Operand* b = frame->popLong();
|
|
|
|
frame->pushInt
|
|
|
|
(c->directCall
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(compareDoublesL)), 2, a, b));
|
|
|
|
} break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case dconst_0:
|
|
|
|
frame->pushLong(c->constant(doubleToBits(0.0)));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case dconst_1:
|
|
|
|
frame->pushLong(c->constant(doubleToBits(1.0)));
|
|
|
|
break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case ddiv: {
|
|
|
|
Operand* a = frame->popLong();
|
|
|
|
Operand* b = frame->popLong();
|
|
|
|
frame->pushLong
|
|
|
|
(c->directCall
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(divideDouble)), 2, a, b));
|
|
|
|
} break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case dmul: {
|
|
|
|
Operand* a = frame->popLong();
|
|
|
|
Operand* b = frame->popLong();
|
|
|
|
frame->pushLong
|
|
|
|
(c->directCall
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(multiplyDouble)), 2, a, b));
|
|
|
|
} break;
|
2007-10-16 17:21:26 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case dneg: {
|
|
|
|
Operand* a = frame->popLong();
|
|
|
|
frame->pushLong
|
|
|
|
(c->directCall
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(negateDouble)), 1, a));
|
|
|
|
} break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case vm::drem: {
|
|
|
|
Operand* a = frame->popLong();
|
|
|
|
Operand* b = frame->popLong();
|
|
|
|
frame->pushLong
|
|
|
|
(c->directCall
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(moduloDouble)), 2, a, b));
|
|
|
|
} break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case dsub: {
|
|
|
|
Operand* a = frame->popLong();
|
|
|
|
Operand* b = frame->popLong();
|
|
|
|
frame->pushLong
|
|
|
|
(c->directCall
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(subtractDouble)), 2, a, b));
|
|
|
|
} break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case dup:
|
|
|
|
frame->dup();
|
|
|
|
break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case dup_x1:
|
|
|
|
frame->dupX1();
|
|
|
|
break;
|
2007-10-13 21:48:40 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case dup_x2:
|
|
|
|
frame->dupX2();
|
|
|
|
break;
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case dup2:
|
|
|
|
frame->dup2();
|
|
|
|
break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case dup2_x1:
|
|
|
|
frame->dup2X1();
|
|
|
|
break;
|
2007-10-13 21:48:40 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case dup2_x2:
|
|
|
|
frame->dup2X2();
|
|
|
|
break;
|
2007-10-09 17:15:40 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case f2d: {
|
|
|
|
Operand* a = frame->popInt();
|
|
|
|
frame->pushLong
|
|
|
|
(c->directCall
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(floatToDouble)), 1, a));
|
|
|
|
} break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case f2i: {
|
|
|
|
Operand* a = frame->popInt();
|
|
|
|
frame->pushInt
|
|
|
|
(c->directCall
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(floatToInt)), 1, a));
|
|
|
|
} break;
|
2007-10-13 21:48:40 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case f2l: {
|
|
|
|
Operand* a = frame->popInt();
|
|
|
|
frame->pushLong
|
|
|
|
(c->directCall
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(floatToLong)), 1, a));
|
|
|
|
} break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case fadd: {
|
|
|
|
Operand* a = frame->popInt();
|
|
|
|
Operand* b = frame->popInt();
|
|
|
|
frame->pushInt
|
|
|
|
(c->directCall
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(addFloat)), 2, a, b));
|
|
|
|
} break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case fcmpg: {
|
|
|
|
Operand* a = frame->popInt();
|
|
|
|
Operand* b = frame->popInt();
|
|
|
|
frame->pushInt
|
|
|
|
(c->directCall
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(compareFloatsG)), 2, a, b));
|
|
|
|
} break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case fcmpl: {
|
|
|
|
Operand* a = frame->popInt();
|
|
|
|
Operand* b = frame->popInt();
|
|
|
|
frame->pushInt
|
|
|
|
(c->directCall
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(compareFloatsL)), 2, a, b));
|
|
|
|
} break;
|
2007-10-16 17:21:26 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case fconst_0:
|
|
|
|
frame->pushInt(c->constant(floatToBits(0.0)));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case fconst_1:
|
|
|
|
frame->pushInt(c->constant(floatToBits(1.0)));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case fconst_2:
|
|
|
|
frame->pushInt(c->constant(floatToBits(2.0)));
|
|
|
|
break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case fdiv: {
|
|
|
|
Operand* a = frame->popInt();
|
|
|
|
Operand* b = frame->popInt();
|
|
|
|
frame->pushInt
|
|
|
|
(c->directCall
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(divideFloat)), 2, a, b));
|
|
|
|
} break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case fmul: {
|
|
|
|
Operand* a = frame->popInt();
|
|
|
|
Operand* b = frame->popInt();
|
|
|
|
frame->pushInt
|
|
|
|
(c->directCall
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(multiplyFloat)), 2, a, b));
|
|
|
|
} break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case fneg: {
|
|
|
|
Operand* a = frame->popLong();
|
|
|
|
frame->pushLong
|
|
|
|
(c->directCall
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(negateFloat)), 1, a));
|
|
|
|
} break;
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case vm::frem: {
|
|
|
|
Operand* a = frame->popInt();
|
|
|
|
Operand* b = frame->popInt();
|
|
|
|
frame->pushInt
|
|
|
|
(c->directCall
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(moduloFloat)), 2, a, b));
|
|
|
|
} break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case fsub: {
|
|
|
|
Operand* a = frame->popInt();
|
|
|
|
Operand* b = frame->popInt();
|
|
|
|
frame->pushInt
|
|
|
|
(c->directCall
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(subtractFloat)), 2, a, b));
|
|
|
|
} break;
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case getfield:
|
|
|
|
case getstatic: {
|
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
|
|
|
|
|
|
|
object field = resolveField(t, codePool(t, code), index - 1);
|
|
|
|
if (UNLIKELY(t->exception)) return;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* table;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
if (instruction == getstatic) {
|
|
|
|
initClass(t, fieldClass(t, field));
|
|
|
|
if (UNLIKELY(t->exception)) return;
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
table = frame->append(classStaticTable(t, fieldClass(t, field)));
|
|
|
|
} else {
|
|
|
|
table = frame->popObject();
|
|
|
|
}
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
switch (fieldCode(t, field)) {
|
|
|
|
case ByteField:
|
|
|
|
case BooleanField:
|
|
|
|
frame->pushInt(c->select1(c->memory(table, fieldOffset(t, field))));
|
|
|
|
break;
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case CharField:
|
|
|
|
frame->pushInt(c->select2z(c->memory(table, fieldOffset(t, field))));
|
|
|
|
break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case ShortField:
|
|
|
|
frame->pushInt(c->select2(c->memory(table, fieldOffset(t, field))));
|
|
|
|
break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case FloatField:
|
|
|
|
case IntField:
|
|
|
|
frame->pushInt(c->select4(c->memory(table, fieldOffset(t, field))));
|
|
|
|
break;
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case DoubleField:
|
|
|
|
case LongField:
|
|
|
|
frame->pushLong(c->select8(c->memory(table, fieldOffset(t, field))));
|
|
|
|
break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case ObjectField:
|
|
|
|
frame->pushObject(c->memory(c->memory(table, fieldOffset(t, field))));
|
|
|
|
break;
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
default:
|
|
|
|
abort(t);
|
|
|
|
}
|
|
|
|
} break;
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case goto_: {
|
|
|
|
uint32_t newIp = (ip - 3) + codeReadInt16(t, code, ip);
|
|
|
|
assert(t, newIp < codeLength(t, code));
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->jmp(c->logicalIp(newIp));
|
|
|
|
ip = newIp;
|
|
|
|
} break;
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case goto_w: {
|
|
|
|
uint32_t newIp = (ip - 5) + codeReadInt32(t, code, ip);
|
|
|
|
assert(t, newIp < codeLength(t, code));
|
2007-09-28 14:45:26 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->jmp(c->logicalIp(newIp));
|
|
|
|
ip = newIp;
|
|
|
|
} break;
|
2007-09-28 14:45:26 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case i2b: {
|
|
|
|
Operand* top = frame->topInt();
|
|
|
|
c->mov(c->select1(top), top);
|
|
|
|
} break;
|
2007-09-28 14:45:26 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case i2c: {
|
|
|
|
Operand* top = frame->topInt();
|
|
|
|
c->mov(c->select2z(top), top);
|
|
|
|
} break;
|
2007-10-13 21:48:40 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case i2d: {
|
|
|
|
Operand* a = frame->popInt();
|
|
|
|
frame->pushLong
|
|
|
|
(c->directCall
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(intToDouble)), 1, a));
|
|
|
|
} break;
|
2007-09-28 14:45:26 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case i2f: {
|
|
|
|
Operand* a = frame->popInt();
|
|
|
|
frame->pushInt
|
|
|
|
(c->directCall
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(intToFloat)), 1, a));
|
|
|
|
} break;
|
2007-09-28 14:45:26 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case i2l:
|
|
|
|
frame->pushLong(frame->popInt());
|
|
|
|
break;
|
2007-10-04 03:19:39 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case i2s: {
|
|
|
|
Operand* top = frame->topInt();
|
|
|
|
c->mov(c->select2(top), top);
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case iadd: {
|
|
|
|
Operand* a = frame->popInt();
|
|
|
|
c->add(a, frame->topInt());
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case iand: {
|
|
|
|
Operand* a = frame->popInt();
|
|
|
|
c->and_(a, frame->topInt());
|
|
|
|
} break;
|
2007-10-04 00:41:54 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case iconst_m1:
|
|
|
|
frame->pushInt(c->constant(-1));
|
|
|
|
break;
|
2007-10-04 00:41:54 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case iconst_0:
|
|
|
|
frame->pushInt(c->constant(0));
|
|
|
|
break;
|
2007-10-04 00:41:54 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case iconst_1:
|
|
|
|
frame->pushInt(c->constant(1));
|
|
|
|
break;
|
2007-10-13 21:48:40 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case iconst_2:
|
|
|
|
frame->pushInt(c->constant(2));
|
|
|
|
break;
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case iconst_3:
|
|
|
|
frame->pushInt(c->constant(3));
|
|
|
|
break;
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case iconst_4:
|
|
|
|
frame->pushInt(c->constant(4));
|
|
|
|
break;
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case iconst_5:
|
|
|
|
frame->pushInt(c->constant(5));
|
|
|
|
break;
|
2007-10-13 21:48:40 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case idiv: {
|
|
|
|
Operand* a = frame->popInt();
|
|
|
|
c->div(a, frame->topInt());
|
|
|
|
} break;
|
2007-10-13 21:48:40 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case if_acmpeq:
|
|
|
|
case if_acmpne: {
|
|
|
|
uint32_t newIp = (ip - 3) + codeReadInt16(t, code, ip);
|
|
|
|
assert(t, newIp < codeLength(t, code));
|
|
|
|
|
|
|
|
Operand* a = frame->popObject();
|
|
|
|
Operand* b = frame->popObject();
|
|
|
|
c->cmp(a, b);
|
2007-09-28 14:45:26 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* target = c->logicalIp(newIp);
|
|
|
|
if (instruction == if_acmpeq) {
|
|
|
|
c->je(target);
|
|
|
|
} else {
|
|
|
|
c->jne(target);
|
|
|
|
}
|
|
|
|
|
|
|
|
compile(t, frame, newIp);
|
|
|
|
if (UNLIKELY(t->exception)) return;
|
|
|
|
} break;
|
2007-09-28 14:45:26 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case if_icmpeq:
|
|
|
|
case if_icmpne:
|
|
|
|
case if_icmpgt:
|
|
|
|
case if_icmpge:
|
|
|
|
case if_icmplt:
|
|
|
|
case if_icmple: {
|
|
|
|
uint32_t newIp = (ip - 3) + codeReadInt16(t, code, ip);
|
|
|
|
assert(t, newIp < codeLength(t, code));
|
|
|
|
|
|
|
|
Operand* a = frame->popInt();
|
|
|
|
Operand* b = frame->popInt();
|
|
|
|
c->cmp(a, b);
|
2007-10-13 21:48:40 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* target = c->logicalIp(newIp);
|
|
|
|
switch (instruction) {
|
|
|
|
case if_icmpeq:
|
|
|
|
c->je(target);
|
|
|
|
break;
|
|
|
|
case if_icmpne:
|
|
|
|
c->jne(target);
|
|
|
|
break;
|
|
|
|
case if_icmpgt:
|
|
|
|
c->jg(target);
|
|
|
|
break;
|
|
|
|
case if_icmpge:
|
|
|
|
c->jge(target);
|
|
|
|
break;
|
|
|
|
case if_icmplt:
|
|
|
|
c->jl(target);
|
|
|
|
break;
|
|
|
|
case if_icmple:
|
|
|
|
c->jle(target);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
compile(t, frame, newIp);
|
|
|
|
if (UNLIKELY(t->exception)) return;
|
|
|
|
} break;
|
2007-10-03 00:22:48 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case ifeq:
|
|
|
|
case ifne:
|
|
|
|
case ifgt:
|
|
|
|
case ifge:
|
|
|
|
case iflt:
|
|
|
|
case ifle: {
|
|
|
|
uint32_t newIp = (ip - 3) + codeReadInt16(t, code, ip);
|
|
|
|
assert(t, newIp < codeLength(t, code));
|
2007-10-03 00:22:48 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->cmp(0, frame->popInt());
|
2007-10-16 17:21:26 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* target = c->logicalIp(newIp);
|
|
|
|
switch (instruction) {
|
|
|
|
case ifeq:
|
|
|
|
c->je(target);
|
|
|
|
break;
|
|
|
|
case ifne:
|
|
|
|
c->jne(target);
|
|
|
|
break;
|
|
|
|
case ifgt:
|
|
|
|
c->jg(target);
|
|
|
|
break;
|
|
|
|
case ifge:
|
|
|
|
c->jge(target);
|
|
|
|
break;
|
|
|
|
case iflt:
|
|
|
|
c->jl(target);
|
|
|
|
break;
|
|
|
|
case ifle:
|
|
|
|
c->jle(target);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
compile(t, frame, newIp);
|
|
|
|
if (UNLIKELY(t->exception)) return;
|
|
|
|
} break;
|
2007-10-16 17:21:26 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case ifnull:
|
|
|
|
case ifnonnull: {
|
|
|
|
uint32_t newIp = (ip - 3) + codeReadInt16(t, code, ip);
|
|
|
|
assert(t, newIp < codeLength(t, code));
|
2007-10-16 17:21:26 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->cmp(0, frame->popObject());
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* target = c->logicalIp(newIp);
|
|
|
|
if (instruction == ifnull) {
|
|
|
|
c->je(target);
|
|
|
|
} else {
|
|
|
|
c->jne(target);
|
|
|
|
}
|
|
|
|
|
|
|
|
compile(t, frame, newIp);
|
|
|
|
if (UNLIKELY(t->exception)) return;
|
|
|
|
} break;
|
2007-09-29 21:08:29 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case iinc: {
|
|
|
|
uint8_t index = codeBody(t, code, ip++);
|
|
|
|
int8_t count = codeBody(t, code, ip++);
|
2007-09-29 21:08:29 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
frame->increment(index, count);
|
|
|
|
} break;
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case iload:
|
|
|
|
case fload:
|
|
|
|
frame->loadInt(codeBody(t, code, ip++));
|
|
|
|
break;
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case iload_0:
|
|
|
|
case fload_0:
|
|
|
|
frame->loadInt(0);
|
|
|
|
break;
|
2007-09-24 01:39:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case iload_1:
|
|
|
|
case fload_1:
|
|
|
|
frame->loadInt(1);
|
|
|
|
break;
|
2007-09-28 23:41:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case iload_2:
|
|
|
|
case fload_2:
|
|
|
|
frame->loadInt(2);
|
|
|
|
break;
|
2007-10-03 00:22:48 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case iload_3:
|
|
|
|
case fload_3:
|
|
|
|
frame->loadInt(3);
|
|
|
|
break;
|
2007-10-03 00:22:48 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case imul: {
|
|
|
|
Operand* a = frame->popInt();
|
|
|
|
c->mul(a, frame->topInt());
|
|
|
|
} break;
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case instanceof: {
|
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
2007-09-30 04:07:22 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
object class_ = resolveClassInPool(t, codePool(t, code), index - 1);
|
|
|
|
if (UNLIKELY(t->exception)) return;
|
2007-09-30 04:07:22 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* call = c->label();
|
|
|
|
Operand* next = c->label();
|
|
|
|
Operand* zero = c->label();
|
2007-09-30 04:07:22 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* instance = frame->topObject();
|
|
|
|
Operand* tmp = c->temporary();
|
|
|
|
Operand* result = c->temporary();
|
2007-09-30 04:07:22 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->mov(instance, tmp);
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->cmp(c->constant(0), tmp);
|
|
|
|
c->je(zero);
|
2007-09-30 15:52:21 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* classOperand = frame->append(class_);
|
2007-09-30 15:52:21 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->mov(c->memory(tmp), tmp);
|
|
|
|
c->and_(c->constant(PointerMask), tmp);
|
2007-09-30 15:52:21 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->cmp(classOperand, tmp);
|
|
|
|
c->jne(call);
|
2007-09-30 15:52:21 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->mov(c->constant(1), result);
|
|
|
|
c->jmp(next);
|
2007-09-29 20:24:14 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->mov
|
|
|
|
(c->directCall
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(isAssignableFrom)),
|
|
|
|
2, classOperand, tmp), result);
|
2007-09-28 23:41:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->release(tmp);
|
2007-09-28 23:41:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->jmp(next);
|
|
|
|
|
|
|
|
c->mark(zero);
|
2007-09-28 23:41:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->mov(c->constant(0), result);
|
2007-09-28 23:41:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->mark(next);
|
|
|
|
frame->pushInt(result);
|
2007-09-28 23:41:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->release(result);
|
|
|
|
} break;
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case invokeinterface: {
|
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
|
|
|
ip += 2;
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
object target = resolveMethod(t, codePool(t, code), index - 1);
|
|
|
|
if (UNLIKELY(t->exception)) return;
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
unsigned parameterFootprint = methodParameterFootprint(t, target);
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
unsigned instance = parameterFootprint - 1;
|
2007-10-13 21:48:40 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* found = c->directCall
|
|
|
|
(c->constant
|
|
|
|
(reinterpret_cast<intptr_t>(findInterfaceMethodFromInstance)),
|
|
|
|
3, c->thread(), frame->append(target), c->stack(instance));
|
2007-10-13 21:48:40 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->mov(c->memory(found, MethodCompiled), found);
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* result = c->call(c->memory(found, SingletonBody));
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
frame->trace(target, true);
|
2007-09-30 15:52:21 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
frame->pop(parameterFootprint);
|
2007-09-28 23:41:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
pushReturnValue(t, frame, methodReturnCode(t, target), result);
|
|
|
|
} break;
|
2007-09-28 23:41:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case invokespecial: {
|
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
2007-09-28 23:41:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
object target = resolveMethod(t, codePool(t, code), index - 1);
|
|
|
|
if (UNLIKELY(t->exception)) return;
|
2007-09-28 23:41:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
object class_ = methodClass(t, target);
|
|
|
|
if (isSpecialMethod(t, target, class_)) {
|
|
|
|
target = findMethod(t, target, classSuper(t, class_));
|
|
|
|
}
|
2007-09-28 23:41:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
compileDirectInvoke(t, frame, target);
|
|
|
|
} break;
|
2007-10-13 21:48:40 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case invokestatic: {
|
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
object target = resolveMethod(t, codePool(t, code), index - 1);
|
|
|
|
if (UNLIKELY(t->exception)) return;
|
|
|
|
PROTECT(t, target);
|
2007-09-28 14:45:26 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
initClass(t, methodClass(t, target));
|
|
|
|
if (UNLIKELY(t->exception)) return;
|
2007-09-29 21:08:29 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
compileDirectInvoke(t, frame, target);
|
|
|
|
} break;
|
2007-09-29 21:08:29 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case invokevirtual: {
|
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
2007-09-29 21:08:29 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
object target = resolveMethod(t, codePool(t, code), index - 1);
|
|
|
|
if (UNLIKELY(t->exception)) return;
|
2007-09-29 21:08:29 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
unsigned parameterFootprint = methodParameterFootprint(t, target);
|
2007-10-13 21:48:40 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
unsigned offset = ClassVtable + (methodOffset(t, target) * BytesPerWord);
|
2007-09-29 21:08:29 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* instance = c->stack(parameterFootprint - 1);
|
|
|
|
Operand* class_ = c->temporary();
|
|
|
|
|
|
|
|
c->mov(c->memory(instance), class_);
|
|
|
|
c->and_(c->constant(PointerMask), class_);
|
2007-09-29 21:08:29 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* result = c->call(c->memory(class_, offset));
|
2007-10-15 19:12:38 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
frame->trace(target, true);
|
2007-10-15 19:12:38 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->release(class_);
|
2007-10-15 19:12:38 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
frame->pop(parameterFootprint);
|
2007-10-15 19:12:38 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
pushReturnValue(t, frame, methodReturnCode(t, target), result);
|
|
|
|
} break;
|
2007-10-15 19:12:38 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case ior: {
|
|
|
|
Operand* a = frame->popInt();
|
|
|
|
c->or_(a, frame->topInt());
|
|
|
|
} break;
|
2007-10-15 19:12:38 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case irem: {
|
|
|
|
Operand* a = frame->popInt();
|
|
|
|
c->rem(a, frame->topInt());
|
|
|
|
} break;
|
2007-10-15 19:12:38 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case ireturn:
|
|
|
|
case freturn:
|
|
|
|
c->epilogue();
|
|
|
|
c->return_(frame->popInt());
|
|
|
|
return;
|
2007-10-15 19:12:38 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case ishl: {
|
|
|
|
Operand* a = frame->popInt();
|
|
|
|
c->shl(a, frame->topInt());
|
|
|
|
} break;
|
2007-10-15 19:12:38 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case ishr: {
|
|
|
|
Operand* a = frame->popInt();
|
|
|
|
c->shr(a, frame->topInt());
|
|
|
|
} break;
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case istore:
|
|
|
|
case fstore:
|
|
|
|
frame->storeInt(codeBody(t, code, ip++));
|
|
|
|
break;
|
2007-10-16 17:21:26 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case istore_0:
|
|
|
|
case fstore_0:
|
|
|
|
frame->storeInt(0);
|
|
|
|
break;
|
2007-10-16 17:21:26 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case istore_1:
|
|
|
|
case fstore_1:
|
|
|
|
frame->storeInt(1);
|
|
|
|
break;
|
2007-10-16 17:21:26 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case istore_2:
|
|
|
|
case fstore_2:
|
|
|
|
frame->storeInt(2);
|
|
|
|
break;
|
2007-10-16 17:21:26 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case istore_3:
|
|
|
|
case fstore_3:
|
|
|
|
frame->storeInt(3);
|
|
|
|
break;
|
2007-10-16 17:21:26 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case isub: {
|
|
|
|
Operand* a = frame->popInt();
|
|
|
|
c->sub(a, frame->topInt());
|
|
|
|
} break;
|
2007-10-15 19:12:38 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case iushr: {
|
|
|
|
Operand* a = frame->popInt();
|
|
|
|
c->ushr(a, frame->topInt());
|
|
|
|
} break;
|
2007-10-15 19:12:38 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case ixor: {
|
|
|
|
Operand* a = frame->popInt();
|
|
|
|
c->xor_(a, frame->topInt());
|
|
|
|
} break;
|
2007-10-15 19:12:38 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case jsr:
|
|
|
|
case jsr_w:
|
|
|
|
case ret:
|
|
|
|
// see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4381996
|
|
|
|
abort(t);
|
2007-10-15 19:12:38 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case l2i:
|
|
|
|
frame->pushInt(frame->popLong());
|
|
|
|
break;
|
2007-10-15 19:12:38 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case ladd: {
|
|
|
|
Operand* a = frame->popLong();
|
|
|
|
c->sub(a, frame->topLong());
|
|
|
|
} break;
|
2007-10-15 19:12:38 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case lcmp: {
|
|
|
|
Operand* next = c->label();
|
|
|
|
Operand* less = c->label();
|
|
|
|
Operand* greater = c->label();
|
2007-10-15 19:12:38 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* a = frame->popLong();
|
|
|
|
Operand* b = frame->popLong();
|
|
|
|
Operand* result = c->temporary();
|
|
|
|
|
|
|
|
c->cmp(a, b);
|
|
|
|
c->jl(less);
|
|
|
|
c->jg(greater);
|
2007-10-15 19:12:38 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->mov(c->constant(0), result);
|
|
|
|
c->jmp(next);
|
|
|
|
|
|
|
|
c->mark(less);
|
|
|
|
c->mov(c->constant(-1), result);
|
|
|
|
c->jmp(next);
|
2007-10-15 19:12:38 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->mark(greater);
|
|
|
|
c->mov(c->constant(1), result);
|
2007-10-15 19:12:38 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->mark(next);
|
|
|
|
frame->pushInt(result);
|
2007-09-29 20:24:14 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->release(result);
|
|
|
|
} break;
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case lconst_0:
|
|
|
|
frame->pushLong(c->constant(0));
|
|
|
|
break;
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case lconst_1:
|
|
|
|
frame->pushLong(c->constant(1));
|
|
|
|
break;
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case ldc:
|
|
|
|
case ldc_w: {
|
|
|
|
uint16_t index;
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
if (instruction == ldc) {
|
|
|
|
index = codeBody(t, code, ip++);
|
|
|
|
} else {
|
|
|
|
index = codeReadInt16(t, code, ip);
|
|
|
|
}
|
2007-09-30 15:52:21 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
object pool = codePool(t, code);
|
2007-09-30 15:52:21 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
if (singletonIsObject(t, pool, index - 1)) {
|
|
|
|
object v = singletonObject(t, pool, index - 1);
|
|
|
|
if (objectClass(t, v)
|
|
|
|
== arrayBody(t, t->m->types, Machine::ByteArrayType))
|
|
|
|
{
|
|
|
|
object class_ = resolveClassInPool(t, pool, index - 1);
|
|
|
|
if (UNLIKELY(t->exception)) return;
|
2007-09-30 15:52:21 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
frame->pushObject(frame->append(class_));
|
2007-10-08 21:41:41 +00:00
|
|
|
} else {
|
2007-12-09 22:45:43 +00:00
|
|
|
frame->pushObject(frame->append(v));
|
2007-10-08 21:41:41 +00:00
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
} else {
|
|
|
|
frame->pushInt(c->constant(singletonValue(t, pool, index - 1)));
|
|
|
|
}
|
|
|
|
} break;
|
2007-10-04 22:41:19 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case ldc2_w: {
|
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
2007-09-24 01:39:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
object pool = codePool(t, code);
|
2007-10-17 01:21:35 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
uint64_t v;
|
|
|
|
memcpy(&v, &singletonValue(t, pool, index - 1), 8);
|
|
|
|
frame->pushLong(c->constant(v));
|
|
|
|
} break;
|
2007-09-24 01:39:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case ldiv_: {
|
|
|
|
Operand* a = frame->popLong();
|
|
|
|
c->div(a, frame->topLong());
|
|
|
|
} break;
|
2007-09-24 01:39:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case lload:
|
|
|
|
case dload:
|
|
|
|
frame->loadLong(codeBody(t, code, ip++));
|
|
|
|
break;
|
2007-09-24 01:39:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case lload_0:
|
|
|
|
case dload_0:
|
|
|
|
frame->loadLong(0);
|
|
|
|
break;
|
2007-09-24 01:39:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case lload_1:
|
|
|
|
case dload_1:
|
|
|
|
frame->loadLong(1);
|
|
|
|
break;
|
2007-09-24 01:39:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case lload_2:
|
|
|
|
case dload_2:
|
|
|
|
frame->loadLong(2);
|
|
|
|
break;
|
2007-09-24 01:39:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case lload_3:
|
|
|
|
case dload_3:
|
|
|
|
frame->loadLong(3);
|
|
|
|
break;
|
2007-09-24 01:39:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case lmul: {
|
|
|
|
Operand* a = frame->popLong();
|
|
|
|
c->mul(a, frame->topLong());
|
|
|
|
} break;
|
2007-10-17 01:21:35 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case lneg:
|
|
|
|
c->neg(frame->topLong());
|
|
|
|
break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case lookupswitch: {
|
|
|
|
int32_t base = ip - 1;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
ip = (ip + 3) & ~3; // pad to four byte boundary
|
2007-09-29 20:24:14 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* key = frame->popInt();
|
|
|
|
|
|
|
|
uint32_t defaultIp = base + codeReadInt32(t, code, ip);
|
|
|
|
assert(t, defaultIp < codeLength(t, code));
|
2007-09-29 20:24:14 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
compile(t, frame, defaultIp);
|
|
|
|
if (UNLIKELY(t->exception)) return;
|
2007-09-29 20:24:14 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* default_ = c->poolAppend(c->logicalIp(defaultIp));
|
2007-09-29 20:24:14 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
int32_t pairCount = codeReadInt32(t, code, ip);
|
2007-09-29 20:24:14 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* start;
|
|
|
|
for (int32_t i = 0; i < pairCount; ++i) {
|
|
|
|
unsigned index = ip + (i * 8);
|
|
|
|
int32_t key = codeReadInt32(t, code, index);
|
|
|
|
uint32_t newIp = base + codeReadInt32(t, code, index);
|
|
|
|
assert(t, newIp < codeLength(t, code));
|
2007-09-29 20:24:14 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
compile(t, frame, newIp);
|
|
|
|
if (UNLIKELY(t->exception)) return;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* result = c->poolAppend(c->constant(key));
|
|
|
|
c->poolAppend(c->logicalIp(newIp));
|
2007-09-24 01:39:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
if (i == 0) {
|
|
|
|
start = result;
|
|
|
|
}
|
|
|
|
}
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->jmp
|
|
|
|
(c->directCall
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(lookUpAddress)),
|
|
|
|
4, key, start, c->constant(pairCount), default_));
|
|
|
|
} return;
|
2007-09-29 20:24:14 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case lor: {
|
|
|
|
Operand* a = frame->popLong();
|
|
|
|
c->or_(a, frame->topLong());
|
|
|
|
} break;
|
2007-09-29 20:24:14 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case lrem: {
|
|
|
|
Operand* a = frame->popLong();
|
|
|
|
c->rem(a, frame->topLong());
|
|
|
|
} break;
|
2007-09-29 20:24:14 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case lreturn:
|
|
|
|
case dreturn:
|
|
|
|
c->epilogue();
|
|
|
|
c->return_(frame->popLong());
|
|
|
|
return;
|
2007-09-29 20:24:14 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case lshl: {
|
|
|
|
Operand* a = frame->popLong();
|
|
|
|
c->shl(a, frame->topLong());
|
|
|
|
} break;
|
2007-09-29 20:24:14 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case lshr: {
|
|
|
|
Operand* a = frame->popLong();
|
|
|
|
c->shr(a, frame->topLong());
|
|
|
|
} break;
|
2007-09-29 20:24:14 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case lstore:
|
|
|
|
case dstore:
|
|
|
|
frame->storeLong(codeBody(t, code, ip++));
|
|
|
|
break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case lstore_0:
|
|
|
|
case dstore_0:
|
|
|
|
frame->storeLong(0);
|
|
|
|
break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case lstore_1:
|
|
|
|
case dstore_1:
|
|
|
|
frame->storeLong(1);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case lstore_2:
|
|
|
|
case dstore_2:
|
|
|
|
frame->storeLong(2);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case lstore_3:
|
|
|
|
case dstore_3:
|
|
|
|
frame->storeLong(3);
|
|
|
|
break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case lsub: {
|
|
|
|
Operand* a = frame->popLong();
|
|
|
|
c->sub(a, frame->topLong());
|
|
|
|
} break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case lushr: {
|
|
|
|
Operand* a = frame->popLong();
|
|
|
|
c->ushr(a, frame->topLong());
|
|
|
|
} break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case lxor: {
|
|
|
|
Operand* a = frame->popLong();
|
|
|
|
c->xor_(a, frame->topLong());
|
|
|
|
} break;
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case monitorenter: {
|
|
|
|
c->indirectCall
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(acquireMonitorForObject)),
|
|
|
|
2, c->thread(), frame->popObject());
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
frame->trace();
|
|
|
|
} break;
|
2007-09-29 21:08:29 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case monitorexit: {
|
|
|
|
c->indirectCall
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(releaseMonitorForObject)),
|
|
|
|
2, c->thread(), frame->popObject());
|
2007-09-29 21:08:29 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
frame->trace();
|
|
|
|
} break;
|
2007-09-29 21:08:29 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case multianewarray: {
|
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
|
|
|
uint8_t dimensions = codeBody(t, code, ip++);
|
2007-10-13 21:48:40 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
object class_ = resolveClassInPool(t, codePool(t, code), index - 1);
|
|
|
|
if (UNLIKELY(t->exception)) return;
|
|
|
|
PROTECT(t, class_);
|
2007-10-13 21:48:40 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* result = c->indirectCall
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(makeMultidimensionalArray)),
|
|
|
|
4, c->thread(), frame->append(class_), c->stack(),
|
|
|
|
c->constant(dimensions));
|
2007-09-29 21:08:29 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
frame->trace();
|
2007-09-29 21:08:29 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
frame->pop(dimensions);
|
|
|
|
frame->pushObject(result);
|
|
|
|
} break;
|
2007-10-12 00:30:46 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case new_: {
|
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
|
|
|
|
|
|
|
object class_ = resolveClassInPool(t, codePool(t, code), index - 1);
|
|
|
|
if (UNLIKELY(t->exception)) return;
|
|
|
|
PROTECT(t, class_);
|
|
|
|
|
|
|
|
initClass(t, class_);
|
|
|
|
if (UNLIKELY(t->exception)) return;
|
|
|
|
|
|
|
|
Operand* result;
|
|
|
|
if (classVmFlags(t, class_) & WeakReferenceFlag) {
|
|
|
|
result = c->indirectCall
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(makeNewWeakReference)),
|
|
|
|
2, c->thread(), frame->append(class_));
|
|
|
|
} else {
|
|
|
|
result = c->indirectCall
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(makeNew)),
|
|
|
|
2, c->thread(), frame->append(class_));
|
|
|
|
}
|
2007-09-29 21:08:29 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
frame->trace();
|
2007-10-16 17:21:26 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
frame->pushObject(result);
|
|
|
|
} break;
|
2007-10-16 17:21:26 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case newarray: {
|
|
|
|
uint8_t type = codeBody(t, code, ip++);
|
2007-10-16 17:21:26 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* nonnegative = c->label();
|
2007-10-16 17:21:26 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* size = frame->popInt();
|
|
|
|
c->cmp(0, size);
|
|
|
|
c->jge(nonnegative);
|
2007-10-16 17:21:26 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
compileThrowNew(t, frame, Machine::NegativeArraySizeExceptionType);
|
2007-10-16 17:21:26 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->mark(nonnegative);
|
2007-10-16 17:21:26 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
object (*constructor)(Thread*, uintptr_t, bool);
|
|
|
|
switch (type) {
|
|
|
|
case T_BOOLEAN:
|
|
|
|
constructor = makeBooleanArray;
|
|
|
|
break;
|
2007-10-16 17:21:26 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case T_CHAR:
|
|
|
|
constructor = makeCharArray;
|
|
|
|
break;
|
2007-10-16 17:21:26 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case T_FLOAT:
|
|
|
|
constructor = makeFloatArray;
|
|
|
|
break;
|
2007-10-16 17:21:26 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case T_DOUBLE:
|
|
|
|
constructor = makeDoubleArray;
|
|
|
|
break;
|
2007-10-16 17:21:26 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case T_BYTE:
|
|
|
|
constructor = makeByteArray;
|
|
|
|
break;
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case T_SHORT:
|
|
|
|
constructor = makeShortArray;
|
|
|
|
break;
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case T_INT:
|
|
|
|
constructor = makeIntArray;
|
|
|
|
break;
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case T_LONG:
|
|
|
|
constructor = makeLongArray;
|
|
|
|
break;
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
default: abort(t);
|
|
|
|
}
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* result = c->indirectCall
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(makeBlankArray)),
|
|
|
|
2, c->constant(reinterpret_cast<intptr_t>(constructor)), size);
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
frame->trace();
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
frame->pushObject(result);
|
|
|
|
} break;
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case nop: break;
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case pop_:
|
|
|
|
frame->pop(1);
|
|
|
|
break;
|
2007-09-27 22:20:54 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case pop2:
|
|
|
|
frame->pop(2);
|
|
|
|
break;
|
2007-09-27 22:20:54 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case putfield:
|
|
|
|
case putstatic: {
|
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
|
|
|
|
|
|
|
object field = resolveField(t, codePool(t, code), index - 1);
|
|
|
|
if (UNLIKELY(t->exception)) return;
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
object staticTable;
|
2007-09-27 22:20:54 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
if (instruction == putstatic) {
|
|
|
|
PROTECT(t, field);
|
|
|
|
initClass(t, fieldClass(t, field));
|
|
|
|
if (UNLIKELY(t->exception)) return;
|
2007-09-27 22:20:54 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
staticTable = classStaticTable(t, fieldClass(t, field));
|
|
|
|
}
|
2007-10-12 22:06:33 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* value;
|
|
|
|
switch (fieldCode(t, field)) {
|
|
|
|
case ByteField:
|
|
|
|
case BooleanField:
|
|
|
|
case CharField:
|
|
|
|
case ShortField:
|
|
|
|
case FloatField:
|
|
|
|
case IntField: {
|
|
|
|
value = frame->popInt();
|
|
|
|
} break;
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case DoubleField:
|
|
|
|
case LongField: {
|
|
|
|
value = frame->popLong();
|
|
|
|
} break;
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case ObjectField: {
|
|
|
|
value = frame->popLong();
|
2007-09-26 23:23:03 +00:00
|
|
|
} break;
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
default: abort(t);
|
|
|
|
}
|
2007-10-17 01:21:35 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* table;
|
2007-10-17 01:21:35 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
if (instruction == putstatic) {
|
|
|
|
table = frame->append(staticTable);
|
|
|
|
} else {
|
|
|
|
table = frame->popObject();
|
|
|
|
}
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
switch (fieldCode(t, field)) {
|
|
|
|
case ByteField:
|
|
|
|
case BooleanField:
|
|
|
|
c->mov(value, c->select1(c->memory(table, fieldOffset(t, field))));
|
2007-10-17 01:21:35 +00:00
|
|
|
break;
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case CharField:
|
|
|
|
case ShortField:
|
|
|
|
c->mov(value, c->select2(c->memory(table, fieldOffset(t, field))));
|
2007-10-17 01:21:35 +00:00
|
|
|
break;
|
2007-12-09 22:45:43 +00:00
|
|
|
|
|
|
|
case FloatField:
|
|
|
|
case IntField:
|
|
|
|
c->mov(value, c->select4(c->memory(table, fieldOffset(t, field))));
|
2007-10-10 17:26:28 +00:00
|
|
|
break;
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case DoubleField:
|
|
|
|
case LongField:
|
|
|
|
c->mov(value, c->select8(c->memory(table, fieldOffset(t, field))));
|
2007-10-10 17:26:28 +00:00
|
|
|
break;
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case ObjectField:
|
|
|
|
c->directCall
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(set)),
|
|
|
|
4, c->thread(), table, fieldOffset(t, field), value);
|
2007-10-10 17:26:28 +00:00
|
|
|
break;
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
default: abort(t);
|
|
|
|
}
|
|
|
|
} break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case return_:
|
|
|
|
c->epilogue();
|
|
|
|
c->ret();
|
|
|
|
return;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case sipush:
|
|
|
|
frame->pushInt
|
|
|
|
(c->constant(static_cast<int16_t>(codeReadInt16(t, code, ip))));
|
|
|
|
break;
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case swap:
|
|
|
|
frame->swap();
|
|
|
|
break;
|
2007-10-17 01:21:35 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case tableswitch: {
|
|
|
|
int32_t base = ip - 1;
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
ip = (ip + 3) & ~3; // pad to four byte boundary
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* key = frame->popInt();
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
uint32_t defaultIp = base + codeReadInt32(t, code, ip);
|
|
|
|
assert(t, defaultIp < codeLength(t, code));
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
compile(t, frame, defaultIp);
|
|
|
|
if (UNLIKELY(t->exception)) return;
|
|
|
|
|
|
|
|
Operand* default_ = c->poolAppend(c->logicalIp(defaultIp));
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
int32_t bottom = codeReadInt32(t, code, ip);
|
|
|
|
int32_t top = codeReadInt32(t, code, ip);
|
|
|
|
|
|
|
|
Operand* start;
|
|
|
|
for (int32_t i = 0; i < bottom - top + 1; ++i) {
|
|
|
|
unsigned index = ip + (i * 4);
|
|
|
|
uint32_t newIp = base + codeReadInt32(t, code, index);
|
|
|
|
assert(t, newIp < codeLength(t, code));
|
|
|
|
|
|
|
|
compile(t, frame, newIp);
|
|
|
|
if (UNLIKELY(t->exception)) return;
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* result = c->poolAppend(c->logicalIp(newIp));
|
|
|
|
if (i == 0) {
|
|
|
|
start = result;
|
2007-09-26 23:23:03 +00:00
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Operand* defaultCase = c->label();
|
|
|
|
|
|
|
|
c->cmp(c->constant(bottom), key);
|
|
|
|
c->jl(defaultCase);
|
2007-10-04 22:41:19 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->cmp(c->constant(top), key);
|
|
|
|
c->jg(defaultCase);
|
2007-10-04 22:41:19 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->shl(c->constant(1), key);
|
|
|
|
c->jmp(c->memory(start, 0, key, BytesPerWord));
|
|
|
|
|
|
|
|
c->mark(defaultCase);
|
|
|
|
c->jmp(default_);
|
|
|
|
} return;
|
|
|
|
|
|
|
|
case wide: {
|
|
|
|
switch (codeBody(t, code, ip++)) {
|
|
|
|
case aload: {
|
|
|
|
frame->loadObject(codeReadInt16(t, code, ip));
|
2007-10-04 22:41:19 +00:00
|
|
|
} break;
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case astore: {
|
|
|
|
frame->storeObject(codeReadInt16(t, code, ip));
|
|
|
|
} break;
|
2007-10-04 22:41:19 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case iinc: {
|
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
|
|
|
uint16_t count = codeReadInt16(t, code, ip);
|
2007-10-04 22:41:19 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
frame->increment(index, count);
|
|
|
|
} break;
|
2007-10-04 22:41:19 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case iload: {
|
|
|
|
frame->loadInt(codeReadInt16(t, code, ip));
|
|
|
|
} break;
|
2007-10-04 22:41:19 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case istore: {
|
|
|
|
frame->storeInt(codeReadInt16(t, code, ip));
|
|
|
|
} break;
|
2007-10-04 22:41:19 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case lload: {
|
|
|
|
frame->loadLong(codeReadInt16(t, code, ip));
|
|
|
|
} break;
|
2007-10-04 22:41:19 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case lstore: {
|
|
|
|
frame->storeLong(codeReadInt16(t, code, ip));
|
|
|
|
} break;
|
2007-10-12 14:26:36 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case ret:
|
|
|
|
// see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4381996
|
|
|
|
abort(t);
|
2007-10-04 22:41:19 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
default: abort(t);
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-10-04 22:41:19 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
object
|
|
|
|
finish(MyThread* t, Compiler* c, object method, Vector* objectPool,
|
|
|
|
Vector* traceLog)
|
|
|
|
{
|
|
|
|
unsigned count = ceiling(c->size(), BytesPerWord);
|
|
|
|
unsigned size = count + singletonMaskSize(count);
|
|
|
|
object result = allocate2(t, size * BytesPerWord, true, true);
|
|
|
|
initSingleton(t, result, size, true);
|
|
|
|
singletonMask(t, result)[0] = 1;
|
2007-10-04 22:41:19 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
uint8_t* start = reinterpret_cast<uint8_t*>(&singletonValue(t, result, 0));
|
2007-10-04 22:41:19 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->writeTo(start);
|
2007-10-04 22:41:19 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
if (method) {
|
|
|
|
PROTECT(t, method);
|
2007-10-12 14:26:36 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
for (unsigned i = 0; i < objectPool->length(); i += sizeof(PoolElement)) {
|
|
|
|
PoolElement* e = objectPool->peek<PoolElement>(i);
|
2007-10-04 22:41:19 +00:00
|
|
|
|
2007-12-11 00:48:09 +00:00
|
|
|
singletonMarkObject(t, result, e->offset->value(c) / BytesPerWord);
|
2007-10-04 22:41:19 +00:00
|
|
|
|
2007-12-11 00:48:09 +00:00
|
|
|
set(t, result, SingletonBody + e->offset->value(c), e->value);
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
unsigned traceSize = Frame::traceSizeInBytes(t, method);
|
|
|
|
unsigned mapSize = Frame::mapSizeInBytes(t, method);
|
|
|
|
for (unsigned i = 0; i < traceLog->length(); i += traceSize) {
|
|
|
|
TraceElement* e = traceLog->peek<TraceElement>(i);
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
object node = makeTraceNode
|
2007-12-11 00:48:09 +00:00
|
|
|
(t, reinterpret_cast<intptr_t>(start + e->offset->value(c)),
|
|
|
|
0, method, e->target, e->virtualCall, mapSize / BytesPerWord,
|
2007-12-09 22:45:43 +00:00
|
|
|
false);
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
if (mapSize) {
|
|
|
|
memcpy(&traceNodeMap(t, node, 0), e->map, mapSize);
|
|
|
|
}
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
insertTraceNode(t, node);
|
|
|
|
}
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
object code = methodCode(t, method);
|
|
|
|
PROTECT(t, code);
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
{
|
|
|
|
object oldTable = codeExceptionHandlerTable(t, code);
|
|
|
|
if (oldTable) {
|
|
|
|
PROTECT(t, oldTable);
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
unsigned length = exceptionHandlerTableLength(t, oldTable);
|
|
|
|
object newTable = makeExceptionHandlerTable(t, length, false);
|
|
|
|
for (unsigned i = 0; i < length; ++i) {
|
|
|
|
ExceptionHandler* oldHandler = exceptionHandlerTableBody
|
|
|
|
(t, oldTable, i);
|
|
|
|
ExceptionHandler* newHandler = exceptionHandlerTableBody
|
|
|
|
(t, newTable, i);
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
exceptionHandlerStart(newHandler)
|
2007-12-11 00:48:09 +00:00
|
|
|
= c->logicalIpToOffset(exceptionHandlerStart(oldHandler))
|
|
|
|
->value(c);
|
2007-10-15 19:12:38 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
exceptionHandlerEnd(newHandler)
|
2007-12-11 00:48:09 +00:00
|
|
|
= c->logicalIpToOffset(exceptionHandlerEnd(oldHandler))
|
|
|
|
->value(c);
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
exceptionHandlerIp(newHandler)
|
2007-12-11 00:48:09 +00:00
|
|
|
= c->logicalIpToOffset(exceptionHandlerIp(oldHandler))
|
|
|
|
->value(c);
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
exceptionHandlerCatchType(newHandler)
|
|
|
|
= exceptionHandlerCatchType(oldHandler);
|
|
|
|
}
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
set(t, code, CodeExceptionHandlerTable, newTable);
|
|
|
|
}
|
|
|
|
}
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
{
|
|
|
|
object oldTable = codeLineNumberTable(t, code);
|
|
|
|
if (oldTable) {
|
|
|
|
PROTECT(t, oldTable);
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
unsigned length = lineNumberTableLength(t, oldTable);
|
|
|
|
object newTable = makeLineNumberTable(t, length, false);
|
|
|
|
for (unsigned i = 0; i < length; ++i) {
|
|
|
|
LineNumber* oldLine = lineNumberTableBody(t, oldTable, i);
|
|
|
|
LineNumber* newLine = lineNumberTableBody(t, newTable, i);
|
2007-10-04 22:41:19 +00:00
|
|
|
|
2007-12-11 00:48:09 +00:00
|
|
|
lineNumberIp(newLine) = c->logicalIpToOffset(lineNumberIp(oldLine))
|
|
|
|
->value(c);
|
2007-09-28 14:45:26 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
lineNumberLine(newLine) = lineNumberLine(oldLine);
|
2007-09-27 22:20:54 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
set(t, code, CodeLineNumberTable, newTable);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-09-27 22:20:54 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
return result;
|
|
|
|
}
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
object
|
|
|
|
finish(MyThread* t, Compiler* c)
|
|
|
|
{
|
|
|
|
return finish(t, c, 0, 0, 0);
|
|
|
|
}
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
object
|
|
|
|
compile(MyThread* t, Compiler* c, object method)
|
|
|
|
{
|
|
|
|
PROTECT(t, method);
|
|
|
|
|
|
|
|
c->prologue();
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
object code = methodCode(t, method);
|
|
|
|
PROTECT(t, code);
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
unsigned footprint = methodParameterFootprint(t, method);
|
|
|
|
unsigned locals = codeMaxLocals(t, code);
|
|
|
|
c->sub(c->constant((locals - footprint) * BytesPerWord), c->stack());
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Vector objectPool(t->m->system, 256);
|
|
|
|
Vector traceLog(t->m->system, 1024);
|
|
|
|
uintptr_t map[Frame::mapSizeInWords(t, method)];
|
|
|
|
Frame frame(t, c, method, map, &objectPool, &traceLog);
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
compile(t, &frame, 0);
|
|
|
|
if (UNLIKELY(t->exception)) return 0;
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
object eht = codeExceptionHandlerTable(t, methodCode(t, method));
|
|
|
|
if (eht) {
|
|
|
|
PROTECT(t, eht);
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
for (unsigned i = 0; i < exceptionHandlerTableLength(t, eht); ++i) {
|
|
|
|
ExceptionHandler* eh = exceptionHandlerTableBody(t, eht, i);
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
assert(t, getBit(frame.codeMask, exceptionHandlerStart(eh)));
|
|
|
|
|
|
|
|
uintptr_t map[Frame::mapSizeInWords(t, method)];
|
|
|
|
Frame frame2(&frame, map);
|
|
|
|
frame2.pushedObject();
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
compile(t, &frame2, exceptionHandlerIp(eh));
|
|
|
|
if (UNLIKELY(t->exception)) return 0;
|
|
|
|
}
|
|
|
|
}
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
return finish(t, c, method, &objectPool, &traceLog);
|
|
|
|
}
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void
|
|
|
|
compile(MyThread* t, object method);
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void*
|
|
|
|
compileMethod(MyThread* t)
|
|
|
|
{
|
|
|
|
object node = findTraceNode(t, *static_cast<void**>(t->stack));
|
|
|
|
object target = resolveTarget(t, t->stack, traceNodeTarget(t, node));
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
if (LIKELY(t->exception == 0)) {
|
|
|
|
compile(t, target);
|
|
|
|
}
|
2007-10-13 21:48:40 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
if (UNLIKELY(t->exception)) {
|
|
|
|
unwind(t);
|
|
|
|
} else {
|
|
|
|
if (not traceNodeVirtualCall(t, node)) {
|
|
|
|
Compiler* c = makeCompiler(t->m->system, 0);
|
2007-12-11 00:48:09 +00:00
|
|
|
c->updateCall(reinterpret_cast<void*>(traceNodeAddress(t, node)),
|
2007-12-09 22:45:43 +00:00
|
|
|
&singletonValue(t, methodCompiled(t, target), 0));
|
|
|
|
c->dispose();
|
|
|
|
}
|
|
|
|
return &singletonValue(t, methodCompiled(t, target), 0);
|
|
|
|
}
|
|
|
|
}
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
uint64_t
|
|
|
|
invokeNative2(MyThread* t, object method)
|
|
|
|
{
|
|
|
|
PROTECT(t, method);
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
if (objectClass(t, methodCode(t, method))
|
|
|
|
== arrayBody(t, t->m->types, Machine::ByteArrayType))
|
|
|
|
{
|
|
|
|
void* function = resolveNativeMethod(t, method);
|
|
|
|
if (UNLIKELY(function == 0)) {
|
|
|
|
object message = makeString
|
|
|
|
(t, "%s", &byteArrayBody(t, methodCode(t, method), 0));
|
|
|
|
t->exception = makeUnsatisfiedLinkError(t, message);
|
|
|
|
return 0;
|
|
|
|
}
|
2007-09-29 20:24:14 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
object p = makePointer(t, function);
|
|
|
|
set(t, method, MethodCode, p);
|
|
|
|
}
|
2007-09-28 14:45:26 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
object class_ = methodClass(t, method);
|
|
|
|
PROTECT(t, class_);
|
2007-09-28 14:45:26 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
unsigned footprint = methodParameterFootprint(t, method) + 1;
|
|
|
|
unsigned count = methodParameterCount(t, method) + 1;
|
|
|
|
if (methodFlags(t, method) & ACC_STATIC) {
|
|
|
|
++ footprint;
|
|
|
|
++ count;
|
|
|
|
}
|
2007-09-24 01:39:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
uintptr_t args[footprint];
|
|
|
|
unsigned argOffset = 0;
|
|
|
|
uint8_t types[count];
|
|
|
|
unsigned typeOffset = 0;
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
args[argOffset++] = reinterpret_cast<uintptr_t>(t);
|
|
|
|
types[typeOffset++] = POINTER_TYPE;
|
2007-10-22 14:14:05 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
uintptr_t* sp = static_cast<uintptr_t*>(t->stack)
|
|
|
|
+ (methodParameterFootprint(t, method) + 1);
|
2007-10-22 14:14:05 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
if (methodFlags(t, method) & ACC_STATIC) {
|
|
|
|
args[argOffset++] = reinterpret_cast<uintptr_t>(&class_);
|
|
|
|
} else {
|
|
|
|
args[argOffset++] = reinterpret_cast<uintptr_t>(sp--);
|
|
|
|
}
|
|
|
|
types[typeOffset++] = POINTER_TYPE;
|
2007-10-22 14:14:05 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
MethodSpecIterator it
|
|
|
|
(t, reinterpret_cast<const char*>
|
|
|
|
(&byteArrayBody(t, methodSpec(t, method), 0)));
|
|
|
|
|
|
|
|
while (it.hasNext()) {
|
|
|
|
unsigned type = types[typeOffset++]
|
|
|
|
= fieldType(t, fieldCode(t, *it.next()));
|
2007-10-22 14:14:05 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
switch (type) {
|
|
|
|
case INT8_TYPE:
|
|
|
|
case INT16_TYPE:
|
|
|
|
case INT32_TYPE:
|
|
|
|
case FLOAT_TYPE:
|
|
|
|
args[argOffset++] = *(sp--);
|
|
|
|
break;
|
2007-10-22 14:14:05 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case INT64_TYPE:
|
|
|
|
case DOUBLE_TYPE: {
|
|
|
|
if (BytesPerWord == 8) {
|
|
|
|
uint64_t a = *(sp--);
|
|
|
|
uint64_t b = *(sp--);
|
|
|
|
args[argOffset++] = (a << 32) | b;
|
|
|
|
} else {
|
|
|
|
memcpy(args + argOffset, sp, 8);
|
|
|
|
argOffset += 2;
|
|
|
|
sp -= 2;
|
2007-09-24 01:39:03 +00:00
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-09-28 23:41:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case POINTER_TYPE: {
|
|
|
|
args[argOffset++] = reinterpret_cast<uintptr_t>(sp--);
|
|
|
|
} break;
|
2007-09-28 23:41:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
default: abort(t);
|
2007-10-03 00:22:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void* function = pointerValue(t, methodCode(t, method));
|
|
|
|
unsigned returnType = fieldType(t, methodReturnCode(t, method));
|
|
|
|
uint64_t result;
|
|
|
|
|
|
|
|
if (Verbose) {
|
|
|
|
fprintf(stderr, "invoke native method %s.%s\n",
|
|
|
|
&byteArrayBody(t, className(t, methodClass(t, method)), 0),
|
|
|
|
&byteArrayBody(t, methodName(t, method), 0));
|
|
|
|
}
|
2007-10-04 00:41:54 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
{ ENTER(t, Thread::IdleState);
|
2007-10-03 00:22:48 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
result = t->m->system->call
|
|
|
|
(function,
|
|
|
|
args,
|
|
|
|
types,
|
|
|
|
count + 1,
|
|
|
|
footprint * BytesPerWord,
|
|
|
|
returnType);
|
2007-09-24 01:39:03 +00:00
|
|
|
}
|
2007-09-25 23:53:11 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
if (Verbose) {
|
|
|
|
fprintf(stderr, "return from native method %s.%s\n",
|
|
|
|
&byteArrayBody(t, className(t, methodClass(t, method)), 0),
|
|
|
|
&byteArrayBody(t, methodName(t, method), 0));
|
2007-10-03 00:22:48 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
if (LIKELY(t->exception == 0) and returnType == POINTER_TYPE) {
|
|
|
|
return result ? *reinterpret_cast<uintptr_t*>(result) : 0;
|
|
|
|
} else {
|
|
|
|
return result;
|
2007-10-03 00:22:48 +00:00
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
invokeNative(MyThread* t)
|
|
|
|
{
|
|
|
|
object node = findTraceNode(t, *static_cast<void**>(t->stack));
|
|
|
|
object target = resolveTarget(t, t->stack, traceNodeTarget(t, node));
|
|
|
|
uint64_t result;
|
2007-10-03 00:22:48 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
if (LIKELY(t->exception == 0)) {
|
|
|
|
result = invokeNative2(t, target);
|
2007-10-03 00:22:48 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
if (UNLIKELY(t->exception)) {
|
|
|
|
unwind(t);
|
|
|
|
} else {
|
|
|
|
return result;
|
2007-10-03 00:22:48 +00:00
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2007-10-03 00:22:48 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
inline object*
|
|
|
|
localObject(MyThread* t, void* base, object method, unsigned index)
|
|
|
|
{
|
|
|
|
return reinterpret_cast<object*>
|
|
|
|
(static_cast<uint8_t*>(base) + localOffset(t, index, method));
|
|
|
|
}
|
2007-10-12 17:56:43 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void
|
|
|
|
visitParameters(MyThread* t, Heap::Visitor* v, void* base, object method)
|
|
|
|
{
|
|
|
|
const char* spec = reinterpret_cast<const char*>
|
|
|
|
(&byteArrayBody(t, methodSpec(t, method), 0));
|
2007-10-12 17:56:43 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
unsigned index = 0;
|
|
|
|
if ((methodFlags(t, method) & ACC_STATIC) == 0) {
|
|
|
|
v->visit(localObject(t, base, method, index++));
|
|
|
|
}
|
2007-10-12 17:56:43 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
for (MethodSpecIterator it(t, spec); it.hasNext();) {
|
|
|
|
switch (*it.next()) {
|
|
|
|
case 'L':
|
|
|
|
case '[':
|
|
|
|
v->visit(localObject(t, base, method, index++));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'J':
|
|
|
|
case 'D':
|
|
|
|
index += 2;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
++ index;
|
|
|
|
break;
|
2007-10-12 17:56:43 +00:00
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2007-10-12 17:56:43 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
assert(t, index == methodParameterFootprint(t, method));
|
|
|
|
}
|
2007-09-24 01:39:03 +00:00
|
|
|
|
2007-09-25 23:53:11 +00:00
|
|
|
void
|
2007-12-09 22:45:43 +00:00
|
|
|
visitStackAndLocals(MyThread* t, Heap::Visitor* v, void* base, object node)
|
2007-09-25 23:53:11 +00:00
|
|
|
{
|
2007-12-09 22:45:43 +00:00
|
|
|
object method = traceNodeMethod(t, node);
|
2007-09-25 23:53:11 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
unsigned parameterFootprint = methodParameterFootprint(t, method);
|
|
|
|
unsigned count = codeMaxStack(t, methodCode(t, method))
|
|
|
|
+ codeMaxLocals(t, methodCode(t, method))
|
|
|
|
- parameterFootprint;
|
|
|
|
|
|
|
|
if (count) {
|
|
|
|
uintptr_t* map = &traceNodeMap(t, node, 0);
|
2007-09-29 20:24:14 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
for (unsigned i = 0; i < count; ++i) {
|
|
|
|
if (getBit(map, i)) {
|
|
|
|
v->visit(localObject(t, base, method, i + parameterFootprint));
|
2007-10-17 01:21:35 +00:00
|
|
|
}
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-09-26 23:23:03 +00:00
|
|
|
void
|
2007-12-09 22:45:43 +00:00
|
|
|
visitStack(MyThread* t, Heap::Visitor* v)
|
2007-09-26 23:23:03 +00:00
|
|
|
{
|
2007-12-09 22:45:43 +00:00
|
|
|
void* base = t->base;
|
|
|
|
void** stack = static_cast<void**>(t->stack);
|
|
|
|
MyThread::CallTrace* trace = t->trace;
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
object node = findTraceNode(t, *stack);
|
|
|
|
if (node) {
|
|
|
|
object method = traceNodeMethod(t, node);
|
|
|
|
|
|
|
|
// we only need to visit the parameters of this method if the
|
|
|
|
// caller is native. Otherwise, the caller owns them.
|
|
|
|
object next = findTraceNode(t, static_cast<void**>(base)[1]);
|
|
|
|
if (next == 0) {
|
|
|
|
visitParameters(t, v, base, method);
|
|
|
|
}
|
|
|
|
|
|
|
|
visitStackAndLocals(t, v, base, method);
|
|
|
|
|
|
|
|
stack = static_cast<void**>(base) + 1;
|
|
|
|
base = *static_cast<void**>(base);
|
|
|
|
} else if (trace) {
|
|
|
|
base = trace->base;
|
|
|
|
stack = static_cast<void**>(trace->stack);
|
|
|
|
trace = trace->next;
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
object
|
|
|
|
compileDefault(MyThread* t, Compiler* c)
|
|
|
|
{
|
|
|
|
c->prologue();
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->mov(c->base(), c->memory(c->thread(), difference(&(t->base), t)));
|
|
|
|
c->mov(c->stack(), c->memory(c->thread(), difference(&(t->stack), t)));
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->epilogue();
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->jmp
|
|
|
|
(c->directCall
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(compileMethod)),
|
|
|
|
1, c->thread()));
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
return finish(t, c);
|
2007-09-26 23:23:03 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
object
|
|
|
|
compileNative(MyThread* t, Compiler* c)
|
2007-09-26 23:23:03 +00:00
|
|
|
{
|
2007-12-09 22:45:43 +00:00
|
|
|
c->prologue();
|
2007-10-13 21:48:40 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
c->mov(c->base(), c->memory(c->thread(), difference(&(t->base), t)));
|
|
|
|
c->mov(c->stack(), c->memory(c->thread(), difference(&(t->stack), t)));
|
|
|
|
|
|
|
|
c->call
|
|
|
|
(c->directCall
|
|
|
|
(c->constant(reinterpret_cast<intptr_t>(invokeNative)),
|
|
|
|
1, c->thread()));
|
|
|
|
|
|
|
|
c->epilogue();
|
|
|
|
c->ret();
|
|
|
|
|
|
|
|
return finish(t, c);
|
2007-09-26 23:23:03 +00:00
|
|
|
}
|
|
|
|
|
2007-09-25 23:53:11 +00:00
|
|
|
class ArgumentList {
|
|
|
|
public:
|
|
|
|
ArgumentList(Thread* t, uintptr_t* array, bool* objectMask, object this_,
|
|
|
|
const char* spec, bool indirectObjects, va_list arguments):
|
|
|
|
t(static_cast<MyThread*>(t)),
|
|
|
|
array(array),
|
|
|
|
objectMask(objectMask),
|
2007-10-12 17:56:43 +00:00
|
|
|
position(0),
|
|
|
|
protector(this)
|
2007-09-25 23:53:11 +00:00
|
|
|
{
|
|
|
|
if (this_) {
|
|
|
|
addObject(this_);
|
|
|
|
}
|
|
|
|
|
2007-10-12 17:56:43 +00:00
|
|
|
for (MethodSpecIterator it(t, spec); it.hasNext();) {
|
|
|
|
switch (*it.next()) {
|
2007-09-25 23:53:11 +00:00
|
|
|
case 'L':
|
|
|
|
case '[':
|
|
|
|
if (indirectObjects) {
|
|
|
|
object* v = va_arg(arguments, object*);
|
|
|
|
addObject(v ? *v : 0);
|
|
|
|
} else {
|
|
|
|
addObject(va_arg(arguments, object));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'J':
|
|
|
|
case 'D':
|
|
|
|
addLong(va_arg(arguments, uint64_t));
|
|
|
|
break;
|
2007-10-12 17:56:43 +00:00
|
|
|
|
2007-09-25 23:53:11 +00:00
|
|
|
default:
|
|
|
|
addInt(va_arg(arguments, uint32_t));
|
2007-10-12 17:56:43 +00:00
|
|
|
break;
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
2007-10-12 17:56:43 +00:00
|
|
|
}
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ArgumentList(Thread* t, uintptr_t* array, bool* objectMask, object this_,
|
|
|
|
const char* spec, object arguments):
|
|
|
|
t(static_cast<MyThread*>(t)),
|
|
|
|
array(array),
|
|
|
|
objectMask(objectMask),
|
2007-10-12 17:56:43 +00:00
|
|
|
position(0),
|
|
|
|
protector(this)
|
2007-09-25 23:53:11 +00:00
|
|
|
{
|
|
|
|
if (this_) {
|
|
|
|
addObject(this_);
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned index = 0;
|
2007-10-12 17:56:43 +00:00
|
|
|
for (MethodSpecIterator it(t, spec); it.hasNext();) {
|
|
|
|
switch (*it.next()) {
|
2007-09-25 23:53:11 +00:00
|
|
|
case 'L':
|
|
|
|
case '[':
|
|
|
|
addObject(objectArrayBody(t, arguments, index++));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'J':
|
|
|
|
case 'D':
|
|
|
|
addLong(cast<int64_t>(objectArrayBody(t, arguments, index++),
|
|
|
|
BytesPerWord));
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
addInt(cast<int32_t>(objectArrayBody(t, arguments, index++),
|
|
|
|
BytesPerWord));
|
2007-10-12 17:56:43 +00:00
|
|
|
break;
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void addObject(object v) {
|
|
|
|
array[position] = reinterpret_cast<uintptr_t>(v);
|
|
|
|
objectMask[position] = true;
|
|
|
|
++ position;
|
|
|
|
}
|
|
|
|
|
2007-10-12 22:06:33 +00:00
|
|
|
void addInt(uintptr_t v) {
|
2007-09-25 23:53:11 +00:00
|
|
|
array[position] = v;
|
|
|
|
objectMask[position] = false;
|
|
|
|
++ position;
|
|
|
|
}
|
|
|
|
|
|
|
|
void addLong(uint64_t v) {
|
|
|
|
memcpy(array + position, &v, 8);
|
|
|
|
objectMask[position] = false;
|
|
|
|
objectMask[position] = false;
|
|
|
|
position += 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
MyThread* t;
|
|
|
|
uintptr_t* array;
|
|
|
|
bool* objectMask;
|
|
|
|
unsigned position;
|
2007-10-12 17:56:43 +00:00
|
|
|
|
|
|
|
class MyProtector: public Thread::Protector {
|
|
|
|
public:
|
|
|
|
MyProtector(ArgumentList* list): Protector(list->t), list(list) { }
|
|
|
|
|
|
|
|
virtual void visit(Heap::Visitor* v) {
|
|
|
|
for (unsigned i = 0; i < list->position; ++i) {
|
|
|
|
if (list->objectMask[i]) {
|
2007-10-28 19:14:53 +00:00
|
|
|
v->visit(reinterpret_cast<object*>(list->array + i));
|
2007-10-12 17:56:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ArgumentList* list;
|
|
|
|
} protector;
|
2007-09-25 23:53:11 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
object
|
|
|
|
invoke(Thread* thread, object method, ArgumentList* arguments)
|
|
|
|
{
|
|
|
|
MyThread* t = static_cast<MyThread*>(thread);
|
|
|
|
|
2007-09-26 23:23:03 +00:00
|
|
|
unsigned returnCode = methodReturnCode(t, method);
|
2007-09-25 23:53:11 +00:00
|
|
|
unsigned returnType = fieldType(t, returnCode);
|
|
|
|
|
2007-09-30 03:33:38 +00:00
|
|
|
Reference* reference = t->reference;
|
2007-12-09 22:45:43 +00:00
|
|
|
MyThread::CallTrace trace(t);
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2007-09-26 23:23:03 +00:00
|
|
|
uint64_t result = vmInvoke
|
2007-12-09 22:45:43 +00:00
|
|
|
(t, &singletonValue(t, methodCompiled(t, method), 0), arguments->array,
|
|
|
|
arguments->position * BytesPerWord, returnType);
|
2007-09-25 23:53:11 +00:00
|
|
|
|
2007-09-30 03:33:38 +00:00
|
|
|
while (t->reference != reference) {
|
|
|
|
dispose(t, t->reference);
|
|
|
|
}
|
2007-10-18 00:41:49 +00:00
|
|
|
|
2007-09-25 23:53:11 +00:00
|
|
|
object r;
|
|
|
|
switch (returnCode) {
|
|
|
|
case ByteField:
|
|
|
|
case BooleanField:
|
|
|
|
case CharField:
|
|
|
|
case ShortField:
|
|
|
|
case FloatField:
|
|
|
|
case IntField:
|
|
|
|
r = makeInt(t, result);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LongField:
|
|
|
|
case DoubleField:
|
|
|
|
r = makeLong(t, result);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ObjectField:
|
|
|
|
r = (result == 0 ? 0 :
|
|
|
|
*reinterpret_cast<object*>(static_cast<uintptr_t>(result)));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VoidField:
|
|
|
|
r = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
abort(t);
|
|
|
|
};
|
2007-09-24 01:39:03 +00:00
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2007-09-25 23:53:11 +00:00
|
|
|
class MyProcessor: public Processor {
|
2007-09-24 01:39:03 +00:00
|
|
|
public:
|
2007-09-25 23:53:11 +00:00
|
|
|
MyProcessor(System* s):
|
|
|
|
s(s),
|
2007-12-09 22:45:43 +00:00
|
|
|
defaultCompiled(0),
|
|
|
|
nativeCompiled(0),
|
2007-12-11 00:48:09 +00:00
|
|
|
addressTable(0),
|
|
|
|
addressCount(0),
|
2007-12-09 22:45:43 +00:00
|
|
|
indirectCaller(0)
|
2007-09-24 01:39:03 +00:00
|
|
|
{ }
|
|
|
|
|
2007-09-25 23:53:11 +00:00
|
|
|
virtual Thread*
|
|
|
|
makeThread(Machine* m, object javaThread, Thread* parent)
|
|
|
|
{
|
2007-10-25 22:06:05 +00:00
|
|
|
MyThread* t = new (s->allocate(sizeof(Thread)))
|
|
|
|
MyThread(m, javaThread, parent);
|
|
|
|
t->init();
|
|
|
|
return t;
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
object getDefaultCompiled(MyThread* t) {
|
|
|
|
if (defaultCompiled == 0) {
|
|
|
|
Compiler* c = makeCompiler(t->m->system, 0);
|
|
|
|
defaultCompiled = compileDefault(t, c);
|
|
|
|
c->dispose();
|
2007-10-01 15:19:15 +00:00
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
return defaultCompiled;
|
2007-10-01 15:19:15 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
object getNativeCompiled(MyThread* t) {
|
|
|
|
if (nativeCompiled == 0) {
|
|
|
|
Compiler* c = makeCompiler(t->m->system, 0);
|
|
|
|
nativeCompiled = compileNative(t, c);
|
|
|
|
c->dispose();
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
return nativeCompiled;
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
virtual object
|
|
|
|
makeMethod(vm::Thread* t,
|
|
|
|
uint8_t vmFlags,
|
|
|
|
uint8_t returnCode,
|
|
|
|
uint8_t parameterCount,
|
|
|
|
uint8_t parameterFootprint,
|
|
|
|
uint16_t flags,
|
|
|
|
uint16_t offset,
|
|
|
|
object name,
|
|
|
|
object spec,
|
|
|
|
object class_,
|
|
|
|
object code)
|
2007-10-04 03:19:39 +00:00
|
|
|
{
|
2007-12-09 22:45:43 +00:00
|
|
|
object compiled
|
|
|
|
= ((flags & ACC_NATIVE)
|
|
|
|
? getNativeCompiled(static_cast<MyThread*>(t))
|
|
|
|
: getDefaultCompiled(static_cast<MyThread*>(t)));
|
|
|
|
|
|
|
|
return vm::makeMethod
|
|
|
|
(t, vmFlags, returnCode, parameterCount, parameterFootprint, flags,
|
|
|
|
offset, name, spec, class_, code, compiled);
|
2007-10-04 03:19:39 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
virtual object
|
|
|
|
makeClass(vm::Thread* t,
|
|
|
|
uint16_t flags,
|
|
|
|
uint8_t vmFlags,
|
|
|
|
uint8_t arrayDimensions,
|
|
|
|
uint16_t fixedSize,
|
|
|
|
uint16_t arrayElementSize,
|
|
|
|
object objectMask,
|
|
|
|
object name,
|
|
|
|
object super,
|
|
|
|
object interfaceTable,
|
|
|
|
object virtualTable,
|
|
|
|
object fieldTable,
|
|
|
|
object methodTable,
|
|
|
|
object staticTable,
|
|
|
|
object loader,
|
|
|
|
unsigned vtableLength)
|
2007-09-26 23:23:03 +00:00
|
|
|
{
|
2007-12-09 22:45:43 +00:00
|
|
|
object c = vm::makeClass
|
|
|
|
(t, flags, vmFlags, arrayDimensions, fixedSize, arrayElementSize,
|
|
|
|
objectMask, name, super, interfaceTable, virtualTable, fieldTable,
|
|
|
|
methodTable, staticTable, loader, vtableLength, false);
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
for (unsigned i = 0; i < vtableLength; ++i) {
|
|
|
|
object compiled
|
|
|
|
= ((flags & ACC_NATIVE)
|
|
|
|
? getNativeCompiled(static_cast<MyThread*>(t))
|
|
|
|
: getDefaultCompiled(static_cast<MyThread*>(t)));
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
classVtable(t, c, i) = &singletonBody(t, compiled, 0);
|
2007-09-26 23:23:03 +00:00
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
|
|
|
|
return c;
|
2007-09-26 23:23:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void
|
|
|
|
initClass(Thread* t, object c)
|
|
|
|
{
|
|
|
|
PROTECT(t, c);
|
|
|
|
|
|
|
|
ACQUIRE(t, t->m->classLock);
|
|
|
|
if (classVmFlags(t, c) & NeedInitFlag
|
|
|
|
and (classVmFlags(t, c) & InitFlag) == 0)
|
|
|
|
{
|
2007-09-28 23:41:03 +00:00
|
|
|
classVmFlags(t, c) |= InitFlag;
|
2007-09-26 23:23:03 +00:00
|
|
|
invoke(t, classInitializer(t, c), 0);
|
|
|
|
if (t->exception) {
|
|
|
|
t->exception = makeExceptionInInitializerError(t, t->exception);
|
|
|
|
}
|
|
|
|
classVmFlags(t, c) &= ~(NeedInitFlag | InitFlag);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-09-25 23:53:11 +00:00
|
|
|
virtual void
|
2007-10-12 17:56:43 +00:00
|
|
|
visitObjects(Thread* vmt, Heap::Visitor* v)
|
2007-09-25 23:53:11 +00:00
|
|
|
{
|
2007-10-12 17:56:43 +00:00
|
|
|
MyThread* t = static_cast<MyThread*>(vmt);
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
if (t == t->m->rootThread) {
|
|
|
|
v->visit(&defaultCompiled);
|
|
|
|
v->visit(&nativeCompiled);
|
2007-12-11 00:48:09 +00:00
|
|
|
v->visit(&addressTable);
|
2007-10-14 01:18:25 +00:00
|
|
|
}
|
2007-09-25 23:53:11 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
for (Reference* r = t->reference; r; r = r->next) {
|
|
|
|
v->visit(&(r->target));
|
|
|
|
}
|
2007-09-25 23:53:11 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
visitStack(t, v);
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
virtual void
|
|
|
|
walkStack(Thread* vmt, StackVisitor* v)
|
2007-09-25 23:53:11 +00:00
|
|
|
{
|
2007-12-09 22:45:43 +00:00
|
|
|
MyThread* t = static_cast<MyThread*>(vmt);
|
2007-09-25 23:53:11 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
MyStackWalker walker(t);
|
|
|
|
walker.walk(v);
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
2007-10-04 22:41:19 +00:00
|
|
|
virtual int
|
2007-12-09 22:45:43 +00:00
|
|
|
lineNumber(Thread* vmt, object method, int ip)
|
2007-10-04 22:41:19 +00:00
|
|
|
{
|
2007-12-09 22:45:43 +00:00
|
|
|
return findLineNumber(static_cast<MyThread*>(vmt), method, ip);
|
2007-10-04 22:41:19 +00:00
|
|
|
}
|
|
|
|
|
2007-09-25 23:53:11 +00:00
|
|
|
virtual object*
|
2007-09-30 03:33:38 +00:00
|
|
|
makeLocalReference(Thread* vmt, object o)
|
2007-09-25 23:53:11 +00:00
|
|
|
{
|
2007-09-30 03:33:38 +00:00
|
|
|
if (o) {
|
|
|
|
MyThread* t = static_cast<MyThread*>(vmt);
|
|
|
|
|
|
|
|
Reference* r = new (t->m->system->allocate(sizeof(Reference)))
|
|
|
|
Reference(o, &(t->reference));
|
|
|
|
|
|
|
|
return &(r->target);
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void
|
2007-09-30 03:33:38 +00:00
|
|
|
disposeLocalReference(Thread* t, object* r)
|
2007-09-25 23:53:11 +00:00
|
|
|
{
|
2007-09-30 03:33:38 +00:00
|
|
|
if (r) {
|
|
|
|
vm::dispose(t, reinterpret_cast<Reference*>(r));
|
|
|
|
}
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
2007-09-24 01:39:03 +00:00
|
|
|
virtual object
|
|
|
|
invokeArray(Thread* t, object method, object this_, object arguments)
|
|
|
|
{
|
|
|
|
assert(t, t->state == Thread::ActiveState
|
|
|
|
or t->state == Thread::ExclusiveState);
|
|
|
|
|
|
|
|
assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0));
|
|
|
|
|
2007-09-25 23:53:11 +00:00
|
|
|
const char* spec = reinterpret_cast<char*>
|
|
|
|
(&byteArrayBody(t, methodSpec(t, method), 0));
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
unsigned size = methodParameterFootprint(t, method);
|
2007-09-25 23:53:11 +00:00
|
|
|
uintptr_t array[size];
|
|
|
|
bool objectMask[size];
|
|
|
|
ArgumentList list(t, array, objectMask, this_, spec, arguments);
|
2007-09-24 01:39:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
PROTECT(t, method);
|
|
|
|
|
|
|
|
compile(static_cast<MyThread*>(t), method);
|
|
|
|
|
|
|
|
if (LIKELY(t->exception == 0)) {
|
|
|
|
return ::invoke(t, method, &list);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2007-09-24 01:39:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual object
|
|
|
|
invokeList(Thread* t, object method, object this_, bool indirectObjects,
|
|
|
|
va_list arguments)
|
|
|
|
{
|
|
|
|
assert(t, t->state == Thread::ActiveState
|
|
|
|
or t->state == Thread::ExclusiveState);
|
|
|
|
|
|
|
|
assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0));
|
|
|
|
|
2007-09-25 23:53:11 +00:00
|
|
|
const char* spec = reinterpret_cast<char*>
|
|
|
|
(&byteArrayBody(t, methodSpec(t, method), 0));
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
unsigned size = methodParameterFootprint(t, method);
|
2007-09-25 23:53:11 +00:00
|
|
|
uintptr_t array[size];
|
|
|
|
bool objectMask[size];
|
|
|
|
ArgumentList list
|
|
|
|
(t, array, objectMask, this_, spec, indirectObjects, arguments);
|
2007-09-24 01:39:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
PROTECT(t, method);
|
|
|
|
|
|
|
|
compile(static_cast<MyThread*>(t), method);
|
|
|
|
|
|
|
|
if (LIKELY(t->exception == 0)) {
|
|
|
|
return ::invoke(t, method, &list);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2007-09-24 01:39:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual object
|
|
|
|
invokeList(Thread* t, const char* className, const char* methodName,
|
|
|
|
const char* methodSpec, object this_, va_list arguments)
|
|
|
|
{
|
|
|
|
assert(t, t->state == Thread::ActiveState
|
|
|
|
or t->state == Thread::ExclusiveState);
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
unsigned size = parameterFootprint(t, methodSpec, false);
|
2007-09-25 23:53:11 +00:00
|
|
|
uintptr_t array[size];
|
|
|
|
bool objectMask[size];
|
|
|
|
ArgumentList list
|
|
|
|
(t, array, objectMask, this_, methodSpec, false, arguments);
|
2007-09-24 01:39:03 +00:00
|
|
|
|
|
|
|
object method = resolveMethod(t, className, methodName, methodSpec);
|
|
|
|
if (LIKELY(t->exception == 0)) {
|
|
|
|
assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0));
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
PROTECT(t, method);
|
|
|
|
|
|
|
|
compile(static_cast<MyThread*>(t), method);
|
2007-09-24 01:39:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
if (LIKELY(t->exception == 0)) {
|
|
|
|
return ::invoke(t, method, &list);
|
|
|
|
}
|
2007-10-03 00:22:48 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2007-10-03 00:22:48 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
virtual void dispose() {
|
|
|
|
if (indirectCaller) {
|
|
|
|
s->free(indirectCaller);
|
2007-10-04 03:19:39 +00:00
|
|
|
}
|
|
|
|
|
2007-09-24 01:39:03 +00:00
|
|
|
s->free(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
System* s;
|
2007-12-09 22:45:43 +00:00
|
|
|
object defaultCompiled;
|
|
|
|
object nativeCompiled;
|
2007-12-11 00:48:09 +00:00
|
|
|
object addressTable;
|
|
|
|
unsigned addressCount;
|
2007-12-09 22:45:43 +00:00
|
|
|
void* indirectCaller;
|
2007-09-24 01:39:03 +00:00
|
|
|
};
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
MyProcessor*
|
|
|
|
processor(MyThread* t)
|
2007-10-04 03:19:39 +00:00
|
|
|
{
|
2007-12-09 22:45:43 +00:00
|
|
|
MyProcessor* p = static_cast<MyProcessor*>(t->m->processor);
|
2007-12-11 00:48:09 +00:00
|
|
|
if (p->addressTable == 0) {
|
2007-12-09 22:45:43 +00:00
|
|
|
ACQUIRE(t, t->m->classLock);
|
2007-10-04 03:19:39 +00:00
|
|
|
|
2007-12-11 00:48:09 +00:00
|
|
|
if (p->addressTable == 0) {
|
|
|
|
p->addressTable = makeArray(t, 128, true);
|
2007-09-24 01:39:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
Compiler* c = makeCompiler(t->m->system, 0);
|
|
|
|
|
|
|
|
c->mov(c->base(), c->memory(c->thread(), difference(&(t->base), t)));
|
|
|
|
c->mov(c->stack(), c->memory(c->thread(), difference(&(t->stack), t)));
|
|
|
|
|
|
|
|
c->jmp(c->indirectTarget());
|
|
|
|
|
|
|
|
p->indirectCaller = t->m->system->allocate(c->size());
|
|
|
|
c->writeTo(p->indirectCaller);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return p;
|
|
|
|
}
|
2007-09-24 01:39:03 +00:00
|
|
|
|
2007-10-16 17:21:26 +00:00
|
|
|
void
|
2007-12-09 22:45:43 +00:00
|
|
|
compile(MyThread* t, object method)
|
|
|
|
{
|
|
|
|
MyProcessor* p = processor(t);
|
|
|
|
|
|
|
|
object stub = p->getDefaultCompiled(t);
|
|
|
|
|
|
|
|
if (methodCompiled(t, method) == stub) {
|
|
|
|
PROTECT(t, method);
|
|
|
|
|
|
|
|
ACQUIRE(t, t->m->classLock);
|
|
|
|
|
|
|
|
if (methodCompiled(t, method) == stub) {
|
|
|
|
PROTECT(t, method);
|
|
|
|
|
|
|
|
Compiler* c = makeCompiler(t->m->system, p->indirectCaller);
|
|
|
|
|
|
|
|
object compiled = compile(t, c, method);
|
|
|
|
set(t, method, MethodCompiled, compiled);
|
|
|
|
|
|
|
|
c->dispose();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
object
|
|
|
|
findTraceNode(MyThread* t, void* address)
|
2007-10-16 17:21:26 +00:00
|
|
|
{
|
2007-12-09 22:45:43 +00:00
|
|
|
MyProcessor* p = processor(t);
|
2007-12-11 00:48:09 +00:00
|
|
|
|
|
|
|
intptr_t key = reinterpret_cast<intptr_t>(address);
|
|
|
|
unsigned index = static_cast<uintptr_t>(key)
|
|
|
|
& (arrayLength(t, p->addressTable) - 1);
|
|
|
|
|
|
|
|
for (object n = arrayBody(t, p->addressTable, index);
|
|
|
|
n; n = tripleThird(t, n))
|
|
|
|
{
|
|
|
|
intptr_t k = traceNodeAddress(t, n);
|
|
|
|
|
|
|
|
if (k == key) {
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
abort(t);
|
|
|
|
}
|
|
|
|
|
|
|
|
object
|
|
|
|
resizeTable(MyThread* t, object oldTable, unsigned newLength)
|
|
|
|
{
|
|
|
|
PROTECT(t, oldTable);
|
|
|
|
|
|
|
|
object newTable = makeArray(t, newLength, true);
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < arrayLength(t, oldTable); ++i) {
|
|
|
|
object next;
|
|
|
|
for (object p = arrayBody(t, oldTable, i); p; p = next) {
|
|
|
|
next = traceNodeNext(t, p);
|
|
|
|
|
|
|
|
intptr_t k = traceNodeAddress(t, p);
|
|
|
|
|
|
|
|
unsigned index = k & (newLength - 1);
|
|
|
|
|
|
|
|
set(t, p, TraceNodeNext, arrayBody(t, newTable, index));
|
|
|
|
set(t, newTable, ArrayBody + (index * BytesPerWord), p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return newTable;
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2007-10-16 17:21:26 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void
|
|
|
|
insertTraceNode(MyThread* t, object node)
|
|
|
|
{
|
|
|
|
MyProcessor* p = processor(t);
|
2007-12-11 00:48:09 +00:00
|
|
|
ENTER(t, Thread::ExclusiveState);
|
|
|
|
|
|
|
|
++ p->addressCount;
|
|
|
|
|
|
|
|
if (p->addressCount >= arrayLength(t, p->addressTable) * 2) {
|
|
|
|
PROTECT(t, node);
|
|
|
|
|
|
|
|
p->addressTable = resizeTable
|
|
|
|
(t, p->addressTable, arrayLength(t, p->addressTable) * 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
intptr_t key = traceNodeAddress(t, node);
|
|
|
|
unsigned index = static_cast<uintptr_t>(key)
|
|
|
|
& (arrayLength(t, p->addressTable) - 1);
|
|
|
|
|
|
|
|
set(t, node, TraceNodeNext, arrayBody(t, p->addressTable, index));
|
|
|
|
set(t, p->addressTable, ArrayBody + (index * BytesPerWord), node);
|
2007-10-16 17:21:26 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
} // namespace
|
|
|
|
|
|
|
|
namespace vm {
|
|
|
|
|
2007-09-25 23:53:11 +00:00
|
|
|
Processor*
|
|
|
|
makeProcessor(System* system)
|
2007-09-24 01:39:03 +00:00
|
|
|
{
|
2007-09-25 23:53:11 +00:00
|
|
|
return new (system->allocate(sizeof(MyProcessor))) MyProcessor(system);
|
2007-09-24 01:39:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace vm
|