2009-03-15 18:02:36 +00:00
|
|
|
/* Copyright (c) 2008-2009, Avian Contributors
|
2008-02-19 18:06:52 +00:00
|
|
|
|
|
|
|
Permission to use, copy, modify, and/or distribute this software
|
|
|
|
for any purpose with or without fee is hereby granted, provided
|
|
|
|
that the above copyright notice and this permission notice appear
|
|
|
|
in all copies.
|
|
|
|
|
|
|
|
There is NO WARRANTY for this software. See license.txt for
|
|
|
|
details. */
|
|
|
|
|
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"
|
2008-02-11 17:21:41 +00:00
|
|
|
#include "assembler.h"
|
2007-12-09 22:45:43 +00:00
|
|
|
#include "compiler.h"
|
2008-06-04 22:21:27 +00:00
|
|
|
#include "arch.h"
|
2007-09-24 01:39:03 +00:00
|
|
|
|
|
|
|
using namespace vm;
|
|
|
|
|
2007-09-26 23:23:03 +00:00
|
|
|
extern "C" uint64_t
|
2009-02-17 02:49:28 +00:00
|
|
|
vmInvoke(void* thread, void* function, void* arguments,
|
|
|
|
unsigned argumentFootprint, unsigned frameSize, unsigned returnType);
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2009-05-05 01:04:17 +00:00
|
|
|
extern "C" uint64_t
|
|
|
|
vmCallWithContinuation(void* thread, void* function, void* targetObject,
|
|
|
|
object continuation, void* base, void* stack);
|
|
|
|
|
2007-10-04 03:19:39 +00:00
|
|
|
extern "C" void
|
|
|
|
vmCall();
|
|
|
|
|
2007-09-24 01:39:03 +00:00
|
|
|
namespace {
|
|
|
|
|
2009-05-18 15:16:17 +00:00
|
|
|
const bool DebugCompile = false;
|
2007-12-26 23:59:55 +00:00
|
|
|
const bool DebugNatives = false;
|
2008-04-07 23:47:41 +00:00
|
|
|
const bool DebugCallTable = false;
|
2008-04-11 19:03:40 +00:00
|
|
|
const bool DebugMethodTree = false;
|
2008-11-08 22:36:38 +00:00
|
|
|
const bool DebugFrameMaps = false;
|
2007-12-11 23:52:28 +00:00
|
|
|
|
2008-01-08 17:10:24 +00:00
|
|
|
const bool CheckArrayBounds = true;
|
|
|
|
|
2008-09-28 19:00:52 +00:00
|
|
|
const unsigned MaxNativeCallFootprint = 4;
|
|
|
|
|
2008-11-25 23:01:30 +00:00
|
|
|
const unsigned InitialZoneCapacityInBytes = 64 * 1024;
|
|
|
|
|
2009-04-05 21:42:10 +00:00
|
|
|
const unsigned ExecutableAreaSizeInBytes = 16 * 1024 * 1024;
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
class MyThread: public Thread {
|
|
|
|
public:
|
|
|
|
class CallTrace {
|
|
|
|
public:
|
|
|
|
CallTrace(MyThread* t):
|
|
|
|
t(t),
|
2008-08-16 18:46:14 +00:00
|
|
|
base(t->base),
|
|
|
|
stack(t->stack),
|
2009-05-03 20:57:11 +00:00
|
|
|
continuation(t->continuation),
|
2008-04-07 23:47:41 +00:00
|
|
|
nativeMethod(0),
|
2009-04-27 01:53:42 +00:00
|
|
|
targetMethod(0),
|
2007-12-09 22:45:43 +00:00
|
|
|
next(t->trace)
|
|
|
|
{
|
|
|
|
t->trace = this;
|
2008-08-16 18:46:14 +00:00
|
|
|
t->base = 0;
|
|
|
|
t->stack = 0;
|
2009-05-17 00:39:08 +00:00
|
|
|
t->continuation = 0;
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2007-09-30 15:52:21 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
~CallTrace() {
|
2008-08-16 18:46:14 +00:00
|
|
|
t->stack = stack;
|
|
|
|
t->base = base;
|
2009-05-03 20:57:11 +00:00
|
|
|
t->continuation = continuation;
|
2007-12-09 22:45:43 +00:00
|
|
|
t->trace = next;
|
|
|
|
}
|
2007-09-25 23:53:11 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
MyThread* t;
|
2008-08-16 18:46:14 +00:00
|
|
|
void* base;
|
|
|
|
void* stack;
|
2009-05-03 20:57:11 +00:00
|
|
|
object continuation;
|
2008-04-07 23:47:41 +00:00
|
|
|
object nativeMethod;
|
2009-04-27 01:53:42 +00:00
|
|
|
object targetMethod;
|
2007-12-09 22:45:43 +00:00
|
|
|
CallTrace* next;
|
|
|
|
};
|
2007-10-01 15:19:15 +00:00
|
|
|
|
2008-08-18 15:23:01 +00:00
|
|
|
MyThread(Machine* m, object javaThread, MyThread* parent):
|
2007-12-09 22:45:43 +00:00
|
|
|
Thread(m, javaThread, parent),
|
2007-12-30 22:24:48 +00:00
|
|
|
ip(0),
|
2008-08-16 18:46:14 +00:00
|
|
|
base(0),
|
|
|
|
stack(0),
|
2009-05-03 20:57:11 +00:00
|
|
|
continuation(0),
|
|
|
|
exceptionStack(0),
|
|
|
|
exceptionOffset(0),
|
|
|
|
exceptionHandler(0),
|
2009-04-07 00:34:12 +00:00
|
|
|
tailAddress(0),
|
2009-05-03 20:57:11 +00:00
|
|
|
virtualCallTarget(0),
|
2009-04-07 00:34:12 +00:00
|
|
|
virtualCallIndex(0),
|
2007-12-09 22:45:43 +00:00
|
|
|
trace(0),
|
2008-08-18 15:23:01 +00:00
|
|
|
reference(0),
|
|
|
|
arch(parent ? parent->arch : makeArchitecture(m->system))
|
|
|
|
{
|
|
|
|
arch->acquire();
|
|
|
|
}
|
2007-10-03 00:22:48 +00:00
|
|
|
|
2007-12-30 22:24:48 +00:00
|
|
|
void* ip;
|
2008-08-16 18:46:14 +00:00
|
|
|
void* base;
|
|
|
|
void* stack;
|
2009-05-03 20:57:11 +00:00
|
|
|
object continuation;
|
|
|
|
void* exceptionStack;
|
|
|
|
uintptr_t exceptionOffset;
|
|
|
|
void* exceptionHandler;
|
2009-04-07 00:34:12 +00:00
|
|
|
void* tailAddress;
|
2009-05-03 20:57:11 +00:00
|
|
|
void* virtualCallTarget;
|
2009-04-07 00:34:12 +00:00
|
|
|
uintptr_t virtualCallIndex;
|
2007-12-09 22:45:43 +00:00
|
|
|
CallTrace* trace;
|
|
|
|
Reference* reference;
|
2008-08-18 15:23:01 +00:00
|
|
|
Assembler::Architecture* arch;
|
2007-12-09 22:45:43 +00:00
|
|
|
};
|
|
|
|
|
2009-02-28 19:33:26 +00:00
|
|
|
unsigned
|
|
|
|
parameterOffset(MyThread* t, object method)
|
|
|
|
{
|
|
|
|
return methodParameterFootprint(t, method)
|
|
|
|
+ t->arch->frameFooterSize()
|
|
|
|
+ t->arch->frameReturnAddressSize() - 1;
|
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
object
|
2009-05-05 01:04:17 +00:00
|
|
|
resolveThisPointer(MyThread* t, void* stack)
|
2007-12-09 22:45:43 +00:00
|
|
|
{
|
2009-05-03 20:57:11 +00:00
|
|
|
return reinterpret_cast<object*>(stack)
|
|
|
|
[t->arch->frameFooterSize() + t->arch->frameReturnAddressSize()];
|
2008-04-07 23:47:41 +00:00
|
|
|
}
|
2007-12-23 19:26:35 +00:00
|
|
|
|
2008-04-07 23:47:41 +00:00
|
|
|
object
|
|
|
|
resolveTarget(MyThread* t, void* stack, object method)
|
|
|
|
{
|
2009-05-05 01:04:17 +00:00
|
|
|
object class_ = objectClass(t, resolveThisPointer(t, stack));
|
2007-10-03 00:22:48 +00:00
|
|
|
|
2008-04-07 23:47:41 +00:00
|
|
|
if (classVmFlags(t, class_) & BootstrapFlag) {
|
|
|
|
PROTECT(t, method);
|
|
|
|
PROTECT(t, class_);
|
2007-12-31 22:40:56 +00:00
|
|
|
|
2008-04-07 23:47:41 +00:00
|
|
|
resolveClass(t, className(t, class_));
|
|
|
|
if (UNLIKELY(t->exception)) return 0;
|
2007-10-03 00:22:48 +00:00
|
|
|
}
|
|
|
|
|
2008-04-07 23:47:41 +00:00
|
|
|
if (classFlags(t, methodClass(t, method)) & ACC_INTERFACE) {
|
|
|
|
return findInterfaceMethod(t, method, class_);
|
|
|
|
} else {
|
|
|
|
return findMethod(t, method, class_);
|
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2007-10-03 00:22:48 +00:00
|
|
|
|
2009-04-05 21:42:10 +00:00
|
|
|
object
|
|
|
|
resolveTarget(MyThread* t, object class_, unsigned index)
|
|
|
|
{
|
|
|
|
if (classVmFlags(t, class_) & BootstrapFlag) {
|
|
|
|
PROTECT(t, class_);
|
|
|
|
|
|
|
|
resolveClass(t, className(t, class_));
|
|
|
|
if (UNLIKELY(t->exception)) return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return arrayBody(t, classVirtualTable(t, class_), index);
|
|
|
|
}
|
|
|
|
|
2008-04-07 23:47:41 +00:00
|
|
|
object&
|
|
|
|
methodTree(MyThread* t);
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
object
|
2008-04-07 23:47:41 +00:00
|
|
|
methodTreeSentinal(MyThread* t);
|
2007-10-03 00:22:48 +00:00
|
|
|
|
2008-11-23 23:58:01 +00:00
|
|
|
unsigned
|
|
|
|
compiledSize(intptr_t address)
|
|
|
|
{
|
|
|
|
return reinterpret_cast<uintptr_t*>(address)[-1];
|
|
|
|
}
|
|
|
|
|
2008-04-07 23:47:41 +00:00
|
|
|
intptr_t
|
|
|
|
compareIpToMethodBounds(Thread* t, intptr_t ip, object method)
|
|
|
|
{
|
2008-11-23 23:58:01 +00:00
|
|
|
intptr_t start = methodCompiled(t, method);
|
2008-04-10 23:48:28 +00:00
|
|
|
|
|
|
|
if (DebugMethodTree) {
|
2008-04-16 05:26:58 +00:00
|
|
|
fprintf(stderr, "find 0x%"LX" in (0x%"LX",0x%"LX")\n", ip, start,
|
2008-11-23 23:58:01 +00:00
|
|
|
start + compiledSize(start));
|
2008-04-10 23:48:28 +00:00
|
|
|
}
|
|
|
|
|
2008-04-07 23:47:41 +00:00
|
|
|
if (ip < start) {
|
|
|
|
return -1;
|
2008-04-11 23:01:17 +00:00
|
|
|
} else if (ip < start + static_cast<intptr_t>
|
2008-11-29 01:23:01 +00:00
|
|
|
(compiledSize(start) + BytesPerWord))
|
2008-04-10 23:48:28 +00:00
|
|
|
{
|
2008-04-07 23:47:41 +00:00
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
object
|
|
|
|
methodForIp(MyThread* t, void* ip)
|
|
|
|
{
|
2008-04-10 23:48:28 +00:00
|
|
|
if (DebugMethodTree) {
|
|
|
|
fprintf(stderr, "query for method containing %p\n", ip);
|
|
|
|
}
|
|
|
|
|
2009-03-03 01:40:06 +00:00
|
|
|
// we must use a version of the method tree at least as recent as the
|
|
|
|
// compiled form of the method containing the specified address (see
|
|
|
|
// compile(MyThread*, Allocator*, BootContext*, object)):
|
|
|
|
memoryBarrier();
|
|
|
|
|
2008-04-07 23:47:41 +00:00
|
|
|
return treeQuery(t, methodTree(t), reinterpret_cast<intptr_t>(ip),
|
|
|
|
methodTreeSentinal(t), compareIpToMethodBounds);
|
|
|
|
}
|
2007-10-03 00:22:48 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
class MyStackWalker: public Processor::StackWalker {
|
|
|
|
public:
|
2008-04-23 16:33:31 +00:00
|
|
|
enum State {
|
|
|
|
Start,
|
|
|
|
Next,
|
2009-05-05 01:04:17 +00:00
|
|
|
Continuation,
|
2008-04-23 16:33:31 +00:00
|
|
|
Method,
|
|
|
|
NativeMethod,
|
|
|
|
Finish
|
|
|
|
};
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
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) {
|
2008-04-07 23:47:41 +00:00
|
|
|
v->visit(&(walker->method_));
|
2009-05-03 20:57:11 +00:00
|
|
|
v->visit(&(walker->continuation));
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2007-10-03 00:22:48 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
MyStackWalker* walker;
|
|
|
|
};
|
|
|
|
|
|
|
|
MyStackWalker(MyThread* t):
|
|
|
|
t(t),
|
2008-04-23 16:33:31 +00:00
|
|
|
state(Start),
|
|
|
|
ip_(t->ip),
|
2007-12-09 22:45:43 +00:00
|
|
|
base(t->base),
|
|
|
|
stack(t->stack),
|
|
|
|
trace(t->trace),
|
2008-04-23 16:33:31 +00:00
|
|
|
method_(0),
|
2009-05-03 20:57:11 +00:00
|
|
|
continuation(t->continuation),
|
2007-12-09 22:45:43 +00:00
|
|
|
protector(this)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
MyStackWalker(MyStackWalker* w):
|
|
|
|
t(w->t),
|
2008-04-23 16:33:31 +00:00
|
|
|
state(w->state),
|
2008-04-10 23:48:28 +00:00
|
|
|
ip_(w->ip_),
|
2007-12-09 22:45:43 +00:00
|
|
|
base(w->base),
|
|
|
|
stack(w->stack),
|
|
|
|
trace(w->trace),
|
2008-04-07 23:47:41 +00:00
|
|
|
method_(w->method_),
|
2009-05-12 18:16:55 +00:00
|
|
|
continuation(w->continuation),
|
2007-12-09 22:45:43 +00:00
|
|
|
protector(this)
|
|
|
|
{ }
|
2007-10-11 22:43:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
virtual void walk(Processor::StackVisitor* v) {
|
2008-04-23 16:33:31 +00:00
|
|
|
for (MyStackWalker it(this); it.valid();) {
|
|
|
|
MyStackWalker walker(it);
|
|
|
|
if (not v->visit(&walker)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
it.next();
|
2007-12-14 18:27:56 +00:00
|
|
|
}
|
2008-04-23 16:33:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool valid() {
|
|
|
|
while (true) {
|
|
|
|
// fprintf(stderr, "state: %d\n", state);
|
|
|
|
switch (state) {
|
|
|
|
case Start:
|
2008-08-17 19:32:40 +00:00
|
|
|
if (ip_ == 0) {
|
2008-08-18 15:23:01 +00:00
|
|
|
ip_ = t->arch->frameIp(stack);
|
2008-04-23 16:33:31 +00:00
|
|
|
}
|
2007-12-14 18:27:56 +00:00
|
|
|
|
2008-04-23 16:33:31 +00:00
|
|
|
if (trace and trace->nativeMethod) {
|
|
|
|
method_ = trace->nativeMethod;
|
|
|
|
state = NativeMethod;
|
|
|
|
} else {
|
2008-08-14 18:13:05 +00:00
|
|
|
state = Next;
|
2008-04-23 16:33:31 +00:00
|
|
|
}
|
|
|
|
break;
|
2007-12-09 22:45:43 +00:00
|
|
|
|
2008-04-23 16:33:31 +00:00
|
|
|
case Next:
|
|
|
|
if (stack) {
|
|
|
|
method_ = methodForIp(t, ip_);
|
|
|
|
if (method_) {
|
|
|
|
state = Method;
|
2009-05-03 20:57:11 +00:00
|
|
|
} else if (continuation) {
|
2009-05-17 00:39:08 +00:00
|
|
|
method_ = continuationMethod(t, continuation);
|
2009-05-03 20:57:11 +00:00
|
|
|
state = Continuation;
|
2008-04-23 16:33:31 +00:00
|
|
|
} else if (trace) {
|
2009-05-03 20:57:11 +00:00
|
|
|
continuation = trace->continuation;
|
2008-08-17 19:32:40 +00:00
|
|
|
stack = trace->stack;
|
2008-08-14 18:13:05 +00:00
|
|
|
base = trace->base;
|
2008-08-18 15:23:01 +00:00
|
|
|
ip_ = t->arch->frameIp(stack);
|
2008-08-14 18:13:05 +00:00
|
|
|
trace = trace->next;
|
2008-04-23 16:33:31 +00:00
|
|
|
|
2008-08-14 18:13:05 +00:00
|
|
|
if (trace and trace->nativeMethod) {
|
2008-04-23 16:33:31 +00:00
|
|
|
method_ = trace->nativeMethod;
|
|
|
|
state = NativeMethod;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
state = Finish;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
state = Finish;
|
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
break;
|
2008-04-23 16:33:31 +00:00
|
|
|
|
2009-05-03 20:57:11 +00:00
|
|
|
case Continuation:
|
2008-04-23 16:33:31 +00:00
|
|
|
case Method:
|
|
|
|
case NativeMethod:
|
|
|
|
return true;
|
|
|
|
|
|
|
|
case Finish:
|
|
|
|
return false;
|
|
|
|
|
|
|
|
default:
|
|
|
|
abort(t);
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-04-23 16:33:31 +00:00
|
|
|
void next() {
|
|
|
|
switch (state) {
|
2009-05-03 20:57:11 +00:00
|
|
|
case Continuation:
|
|
|
|
continuation = continuationNext(t, continuation);
|
|
|
|
break;
|
|
|
|
|
2008-04-23 16:33:31 +00:00
|
|
|
case Method:
|
2008-08-17 19:32:40 +00:00
|
|
|
t->arch->nextFrame(&stack, &base);
|
2008-08-18 15:23:01 +00:00
|
|
|
ip_ = t->arch->frameIp(stack);
|
2008-04-23 16:33:31 +00:00
|
|
|
break;
|
2008-04-22 16:21:54 +00:00
|
|
|
|
2008-04-23 16:33:31 +00:00
|
|
|
case NativeMethod:
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
abort(t);
|
2008-04-22 16:21:54 +00:00
|
|
|
}
|
2008-08-14 18:13:05 +00:00
|
|
|
|
|
|
|
state = Next;
|
2007-10-12 17:56:43 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
virtual object method() {
|
2008-08-14 18:13:05 +00:00
|
|
|
// fprintf(stderr, "method %s.%s\n", &byteArrayBody
|
|
|
|
// (t, className(t, methodClass(t, method_)), 0),
|
|
|
|
// &byteArrayBody(t, methodName(t, method_), 0));
|
|
|
|
return method_;
|
2007-10-03 00:22:48 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
virtual int ip() {
|
2008-04-23 16:33:31 +00:00
|
|
|
switch (state) {
|
2009-05-03 20:57:11 +00:00
|
|
|
case Continuation:
|
2009-05-05 01:04:17 +00:00
|
|
|
return reinterpret_cast<intptr_t>(continuationAddress(t, continuation))
|
2009-05-03 20:57:11 +00:00
|
|
|
- methodCompiled(t, continuationMethod(t, continuation));
|
|
|
|
|
2008-04-23 16:33:31 +00:00
|
|
|
case Method:
|
2008-11-23 23:58:01 +00:00
|
|
|
return reinterpret_cast<intptr_t>(ip_) - methodCompiled(t, method_);
|
2008-04-23 16:33:31 +00:00
|
|
|
|
|
|
|
case NativeMethod:
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
default:
|
|
|
|
abort(t);
|
2007-10-03 00:22:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
virtual unsigned count() {
|
2008-04-23 16:33:31 +00:00
|
|
|
unsigned count = 0;
|
2007-12-09 22:45:43 +00:00
|
|
|
|
2008-04-23 16:33:31 +00:00
|
|
|
for (MyStackWalker walker(this); walker.valid();) {
|
|
|
|
walker.next();
|
|
|
|
++ count;
|
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
|
2008-04-23 16:33:31 +00:00
|
|
|
return count;
|
2007-10-03 00:22:48 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
MyThread* t;
|
2008-04-23 16:33:31 +00:00
|
|
|
State state;
|
2008-04-07 23:47:41 +00:00
|
|
|
void* ip_;
|
2007-12-09 22:45:43 +00:00
|
|
|
void* base;
|
|
|
|
void* stack;
|
|
|
|
MyThread::CallTrace* trace;
|
2008-04-07 23:47:41 +00:00
|
|
|
object method_;
|
2009-05-03 20:57:11 +00:00
|
|
|
object continuation;
|
2007-12-09 22:45:43 +00:00
|
|
|
MyProtector protector;
|
|
|
|
};
|
|
|
|
|
2008-08-18 15:23:01 +00:00
|
|
|
unsigned
|
|
|
|
localSize(MyThread* t, object method)
|
|
|
|
{
|
|
|
|
unsigned size = codeMaxLocals(t, methodCode(t, method));
|
|
|
|
if ((methodFlags(t, method) & (ACC_SYNCHRONIZED | ACC_STATIC))
|
|
|
|
== ACC_SYNCHRONIZED)
|
|
|
|
{
|
|
|
|
++ size;
|
|
|
|
}
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned
|
|
|
|
alignedFrameSize(MyThread* t, object method)
|
|
|
|
{
|
|
|
|
return t->arch->alignFrameSize
|
|
|
|
(localSize(t, method)
|
|
|
|
- methodParameterFootprint(t, method)
|
2008-09-28 19:00:52 +00:00
|
|
|
+ codeMaxStack(t, methodCode(t, method))
|
2009-04-25 17:49:56 +00:00
|
|
|
+ t->arch->frameFootprint(MaxNativeCallFootprint));
|
2008-08-18 15:23:01 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
int
|
|
|
|
localOffset(MyThread* t, int v, object method)
|
|
|
|
{
|
2008-09-09 00:31:19 +00:00
|
|
|
int parameterFootprint = methodParameterFootprint(t, method);
|
|
|
|
int frameSize = alignedFrameSize(t, method);
|
|
|
|
|
|
|
|
int offset = ((v < parameterFootprint) ?
|
|
|
|
(frameSize
|
|
|
|
+ parameterFootprint
|
2009-02-27 01:54:25 +00:00
|
|
|
+ t->arch->frameFooterSize()
|
2008-09-09 00:31:19 +00:00
|
|
|
+ t->arch->frameHeaderSize()
|
2008-09-15 02:28:42 +00:00
|
|
|
- v - 1) :
|
2008-09-09 00:31:19 +00:00
|
|
|
(frameSize
|
|
|
|
+ parameterFootprint
|
2009-05-17 23:43:48 +00:00
|
|
|
- v - 1));
|
2008-09-09 00:31:19 +00:00
|
|
|
|
|
|
|
assert(t, offset >= 0);
|
|
|
|
return offset;
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2007-10-03 00:22:48 +00:00
|
|
|
|
2009-05-03 20:57:11 +00:00
|
|
|
int
|
|
|
|
localOffsetFromStack(MyThread* t, int index, object method)
|
|
|
|
{
|
|
|
|
return localOffset(t, index, method)
|
2009-05-17 23:43:48 +00:00
|
|
|
+ t->arch->frameReturnAddressSize();
|
2009-05-03 20:57:11 +00:00
|
|
|
}
|
|
|
|
|
2009-04-26 21:55:35 +00:00
|
|
|
object*
|
2008-08-18 15:23:01 +00:00
|
|
|
localObject(MyThread* t, void* stack, object method, unsigned index)
|
2007-12-28 00:02:05 +00:00
|
|
|
{
|
2009-05-17 23:43:48 +00:00
|
|
|
return static_cast<object*>(stack) + localOffsetFromStack(t, index, method);
|
2009-05-03 20:57:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
stackOffsetFromFrame(MyThread* t, object method)
|
|
|
|
{
|
|
|
|
return alignedFrameSize(t, method) + t->arch->frameHeaderSize();
|
2007-12-28 00:02:05 +00:00
|
|
|
}
|
|
|
|
|
2009-04-26 21:55:35 +00:00
|
|
|
void*
|
|
|
|
stackForFrame(MyThread* t, void* frame, object method)
|
|
|
|
{
|
2009-05-03 20:57:11 +00:00
|
|
|
return static_cast<void**>(frame) - stackOffsetFromFrame(t, method);
|
2009-04-26 21:55:35 +00:00
|
|
|
}
|
|
|
|
|
2008-11-23 23:58:01 +00:00
|
|
|
class PoolElement: public Promise {
|
2007-12-09 22:45:43 +00:00
|
|
|
public:
|
2008-11-23 23:58:01 +00:00
|
|
|
PoolElement(Thread* t, object target, PoolElement* next):
|
|
|
|
t(t), target(target), address(0), next(next)
|
2007-12-16 00:24:15 +00:00
|
|
|
{ }
|
2007-12-09 22:45:43 +00:00
|
|
|
|
2008-11-23 23:58:01 +00:00
|
|
|
virtual int64_t value() {
|
|
|
|
assert(t, resolved());
|
|
|
|
return address;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool resolved() {
|
|
|
|
return address != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
Thread* t;
|
|
|
|
object target;
|
|
|
|
intptr_t address;
|
2007-12-31 22:40:56 +00:00
|
|
|
PoolElement* next;
|
2007-12-09 22:45:43 +00:00
|
|
|
};
|
|
|
|
|
2007-12-31 22:40:56 +00:00
|
|
|
class Context;
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
class TraceElement: public TraceHandler {
|
2007-12-09 22:45:43 +00:00
|
|
|
public:
|
2009-04-07 00:34:12 +00:00
|
|
|
static const unsigned VirtualCall = 1 << 0;
|
|
|
|
static const unsigned TailCall = 1 << 1;
|
2009-03-31 20:15:08 +00:00
|
|
|
|
2007-12-31 22:40:56 +00:00
|
|
|
TraceElement(Context* context, object target,
|
2009-03-31 20:15:08 +00:00
|
|
|
unsigned flags, TraceElement* next):
|
2007-12-31 22:40:56 +00:00
|
|
|
context(context),
|
|
|
|
address(0),
|
2008-11-09 23:56:37 +00:00
|
|
|
next(next),
|
2007-12-31 22:40:56 +00:00
|
|
|
target(target),
|
2009-04-27 01:53:42 +00:00
|
|
|
argumentIndex(0),
|
2009-03-31 20:15:08 +00:00
|
|
|
flags(flags)
|
2007-12-31 22:40:56 +00:00
|
|
|
{ }
|
2007-12-09 22:45:43 +00:00
|
|
|
|
2009-04-27 01:53:42 +00:00
|
|
|
virtual void handleTrace(Promise* address, unsigned argumentIndex) {
|
2007-12-31 22:40:56 +00:00
|
|
|
if (this->address == 0) {
|
|
|
|
this->address = address;
|
2009-04-27 01:53:42 +00:00
|
|
|
this->argumentIndex = argumentIndex;
|
2007-12-31 22:40:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Context* context;
|
|
|
|
Promise* address;
|
2008-11-09 23:56:37 +00:00
|
|
|
TraceElement* next;
|
2007-12-09 22:45:43 +00:00
|
|
|
object target;
|
2009-04-27 01:53:42 +00:00
|
|
|
unsigned argumentIndex;
|
2009-03-31 20:15:08 +00:00
|
|
|
unsigned flags;
|
2007-12-31 22:40:56 +00:00
|
|
|
uintptr_t map[0];
|
2007-10-03 00:22:48 +00:00
|
|
|
};
|
|
|
|
|
2009-03-31 20:15:08 +00:00
|
|
|
class TraceElementPromise: public Promise {
|
|
|
|
public:
|
2009-04-07 00:34:12 +00:00
|
|
|
TraceElementPromise(System* s, TraceElement* trace): s(s), trace(trace) { }
|
2009-03-31 20:15:08 +00:00
|
|
|
|
|
|
|
virtual int64_t value() {
|
|
|
|
assert(s, resolved());
|
2009-04-22 01:39:25 +00:00
|
|
|
return trace->address->value();
|
2009-03-31 20:15:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool resolved() {
|
2009-04-22 01:39:25 +00:00
|
|
|
return trace->address != 0 and trace->address->resolved();
|
2009-03-31 20:15:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
System* s;
|
|
|
|
TraceElement* trace;
|
|
|
|
};
|
|
|
|
|
2008-01-07 14:51:07 +00:00
|
|
|
enum Event {
|
2008-07-05 20:21:13 +00:00
|
|
|
PushContextEvent,
|
|
|
|
PopContextEvent,
|
2008-01-07 14:51:07 +00:00
|
|
|
IpEvent,
|
|
|
|
MarkEvent,
|
|
|
|
ClearEvent,
|
|
|
|
TraceEvent
|
|
|
|
};
|
|
|
|
|
2009-04-27 14:46:43 +00:00
|
|
|
unsigned
|
|
|
|
frameMapSizeInBits(MyThread* t, object method)
|
|
|
|
{
|
|
|
|
return localSize(t, method) + codeMaxStack(t, methodCode(t, method));
|
|
|
|
}
|
|
|
|
|
2008-01-07 14:51:07 +00:00
|
|
|
unsigned
|
|
|
|
frameMapSizeInWords(MyThread* t, object method)
|
|
|
|
{
|
2009-04-27 14:46:43 +00:00
|
|
|
return ceiling(frameMapSizeInBits(t, method), BitsPerWord) * BytesPerWord;
|
2008-01-07 14:51:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uint16_t*
|
|
|
|
makeVisitTable(MyThread* t, Zone* zone, object method)
|
|
|
|
{
|
|
|
|
unsigned size = codeLength(t, methodCode(t, method)) * 2;
|
|
|
|
uint16_t* table = static_cast<uint16_t*>(zone->allocate(size));
|
|
|
|
memset(table, 0, size);
|
|
|
|
return table;
|
|
|
|
}
|
|
|
|
|
|
|
|
uintptr_t*
|
2008-01-08 15:24:57 +00:00
|
|
|
makeRootTable(MyThread* t, Zone* zone, object method)
|
2008-01-07 14:51:07 +00:00
|
|
|
{
|
|
|
|
unsigned size = frameMapSizeInWords(t, method)
|
|
|
|
* codeLength(t, methodCode(t, method))
|
|
|
|
* BytesPerWord;
|
|
|
|
uintptr_t* table = static_cast<uintptr_t*>(zone->allocate(size));
|
2008-01-08 15:24:57 +00:00
|
|
|
memset(table, 0xFF, size);
|
2008-01-07 14:51:07 +00:00
|
|
|
return table;
|
|
|
|
}
|
|
|
|
|
2008-05-31 22:14:27 +00:00
|
|
|
enum Thunk {
|
|
|
|
#define THUNK(s) s##Thunk,
|
|
|
|
|
|
|
|
#include "thunks.cpp"
|
|
|
|
|
|
|
|
#undef THUNK
|
|
|
|
};
|
|
|
|
|
|
|
|
const unsigned ThunkCount = gcIfNecessaryThunk + 1;
|
|
|
|
|
|
|
|
intptr_t
|
|
|
|
getThunk(MyThread* t, Thunk thunk);
|
|
|
|
|
2008-11-23 23:58:01 +00:00
|
|
|
class BootContext {
|
|
|
|
public:
|
|
|
|
class MyProtector: public Thread::Protector {
|
|
|
|
public:
|
|
|
|
MyProtector(Thread* t, BootContext* c): Protector(t), c(c) { }
|
|
|
|
|
|
|
|
virtual void visit(Heap::Visitor* v) {
|
2008-11-27 20:59:40 +00:00
|
|
|
v->visit(&(c->constants));
|
|
|
|
v->visit(&(c->calls));
|
2008-11-23 23:58:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
BootContext* c;
|
|
|
|
};
|
|
|
|
|
2008-12-02 16:45:20 +00:00
|
|
|
BootContext(Thread* t, object constants, object calls,
|
|
|
|
DelayedPromise* addresses, Zone* zone):
|
|
|
|
protector(t, this), constants(constants), calls(calls),
|
|
|
|
addresses(addresses), addressSentinal(addresses), zone(zone)
|
2008-11-23 23:58:01 +00:00
|
|
|
{ }
|
|
|
|
|
|
|
|
MyProtector protector;
|
2008-11-27 20:59:40 +00:00
|
|
|
object constants;
|
|
|
|
object calls;
|
2008-12-02 16:45:20 +00:00
|
|
|
DelayedPromise* addresses;
|
|
|
|
DelayedPromise* addressSentinal;
|
2008-11-23 23:58:01 +00:00
|
|
|
Zone* zone;
|
|
|
|
};
|
|
|
|
|
2007-12-31 22:40:56 +00:00
|
|
|
class Context {
|
2007-10-10 22:39:40 +00:00
|
|
|
public:
|
2007-12-09 22:45:43 +00:00
|
|
|
class MyProtector: public Thread::Protector {
|
|
|
|
public:
|
2008-02-11 17:21:41 +00:00
|
|
|
MyProtector(Context* c): Protector(c->thread), c(c) { }
|
2007-12-09 22:45:43 +00:00
|
|
|
|
|
|
|
virtual void visit(Heap::Visitor* v) {
|
2007-12-31 22:40:56 +00:00
|
|
|
v->visit(&(c->method));
|
2007-12-09 22:45:43 +00:00
|
|
|
|
2007-12-31 22:40:56 +00:00
|
|
|
for (PoolElement* p = c->objectPool; p; p = p->next) {
|
2008-11-23 23:58:01 +00:00
|
|
|
v->visit(&(p->target));
|
2007-12-31 22:40:56 +00:00
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
|
2007-12-31 22:40:56 +00:00
|
|
|
for (TraceElement* p = c->traceLog; p; p = p->next) {
|
|
|
|
v->visit(&(p->target));
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-12-31 22:40:56 +00:00
|
|
|
Context* c;
|
2007-10-10 22:39:40 +00:00
|
|
|
};
|
|
|
|
|
2008-05-31 22:14:27 +00:00
|
|
|
class MyClient: public Compiler::Client {
|
|
|
|
public:
|
|
|
|
MyClient(MyThread* t): t(t) { }
|
|
|
|
|
|
|
|
virtual intptr_t getThunk(UnaryOperation, unsigned) {
|
|
|
|
abort(t);
|
|
|
|
}
|
|
|
|
|
2008-08-28 22:43:35 +00:00
|
|
|
virtual intptr_t getThunk(TernaryOperation op, unsigned size) {
|
2008-05-31 22:14:27 +00:00
|
|
|
switch (op) {
|
|
|
|
case Divide:
|
|
|
|
if (size == 8) {
|
|
|
|
return ::getThunk(t, divideLongThunk);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Remainder:
|
|
|
|
if (size == 8) {
|
|
|
|
return ::getThunk(t, moduloLongThunk);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
|
|
|
|
abort(t);
|
|
|
|
}
|
|
|
|
|
|
|
|
MyThread* t;
|
|
|
|
};
|
|
|
|
|
2008-11-23 23:58:01 +00:00
|
|
|
Context(MyThread* t, BootContext* bootContext, object method):
|
2008-02-11 17:21:41 +00:00
|
|
|
thread(t),
|
2008-11-25 23:01:30 +00:00
|
|
|
zone(t->m->system, t->m->heap, InitialZoneCapacityInBytes),
|
2008-08-19 23:38:37 +00:00
|
|
|
assembler(makeAssembler(t->m->system, t->m->heap, &zone, t->arch)),
|
2008-05-31 22:14:27 +00:00
|
|
|
client(t),
|
|
|
|
compiler(makeCompiler(t->m->system, assembler, &zone, &client)),
|
2007-10-10 22:39:40 +00:00
|
|
|
method(method),
|
2008-11-23 23:58:01 +00:00
|
|
|
bootContext(bootContext),
|
2007-12-31 22:40:56 +00:00
|
|
|
objectPool(0),
|
2008-11-29 01:23:01 +00:00
|
|
|
objectPoolCount(0),
|
2007-12-31 22:40:56 +00:00
|
|
|
traceLog(0),
|
2008-04-07 23:47:41 +00:00
|
|
|
traceLogCount(0),
|
2008-01-07 14:51:07 +00:00
|
|
|
visitTable(makeVisitTable(t, &zone, method)),
|
2008-01-08 15:24:57 +00:00
|
|
|
rootTable(makeRootTable(t, &zone, method)),
|
2008-01-14 23:37:24 +00:00
|
|
|
eventLog(t->m->system, t->m->heap, 1024),
|
2007-12-31 22:40:56 +00:00
|
|
|
protector(this)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
Context(MyThread* t):
|
2008-02-11 17:21:41 +00:00
|
|
|
thread(t),
|
2008-11-25 23:01:30 +00:00
|
|
|
zone(t->m->system, t->m->heap, InitialZoneCapacityInBytes),
|
2008-08-19 23:38:37 +00:00
|
|
|
assembler(makeAssembler(t->m->system, t->m->heap, &zone, t->arch)),
|
2008-05-31 22:14:27 +00:00
|
|
|
client(t),
|
2008-02-11 17:21:41 +00:00
|
|
|
compiler(0),
|
2007-12-31 22:40:56 +00:00
|
|
|
method(0),
|
2008-11-23 23:58:01 +00:00
|
|
|
bootContext(0),
|
2007-12-31 22:40:56 +00:00
|
|
|
objectPool(0),
|
2008-11-29 01:23:01 +00:00
|
|
|
objectPoolCount(0),
|
2007-12-31 22:40:56 +00:00
|
|
|
traceLog(0),
|
2008-04-07 23:47:41 +00:00
|
|
|
traceLogCount(0),
|
2008-01-07 14:51:07 +00:00
|
|
|
visitTable(0),
|
|
|
|
rootTable(0),
|
2008-01-14 23:37:24 +00:00
|
|
|
eventLog(t->m->system, t->m->heap, 0),
|
2007-12-31 22:40:56 +00:00
|
|
|
protector(this)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
~Context() {
|
2008-02-12 00:20:32 +00:00
|
|
|
if (compiler) compiler->dispose();
|
2008-02-11 17:21:41 +00:00
|
|
|
assembler->dispose();
|
2007-12-31 22:40:56 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
MyThread* thread;
|
2007-12-31 22:40:56 +00:00
|
|
|
Zone zone;
|
2008-02-11 17:21:41 +00:00
|
|
|
Assembler* assembler;
|
2008-05-31 22:14:27 +00:00
|
|
|
MyClient client;
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler* compiler;
|
2007-12-31 22:40:56 +00:00
|
|
|
object method;
|
2008-11-23 23:58:01 +00:00
|
|
|
BootContext* bootContext;
|
2007-12-31 22:40:56 +00:00
|
|
|
PoolElement* objectPool;
|
2008-11-29 01:23:01 +00:00
|
|
|
unsigned objectPoolCount;
|
2007-12-31 22:40:56 +00:00
|
|
|
TraceElement* traceLog;
|
2008-04-07 23:47:41 +00:00
|
|
|
unsigned traceLogCount;
|
2008-01-07 14:51:07 +00:00
|
|
|
uint16_t* visitTable;
|
|
|
|
uintptr_t* rootTable;
|
2008-03-05 21:44:17 +00:00
|
|
|
bool dirtyRoots;
|
2008-01-07 14:51:07 +00:00
|
|
|
Vector eventLog;
|
2007-12-31 22:40:56 +00:00
|
|
|
MyProtector protector;
|
|
|
|
};
|
|
|
|
|
2009-05-03 20:57:11 +00:00
|
|
|
unsigned
|
|
|
|
translateLocalIndex(Context* context, unsigned footprint, unsigned index)
|
|
|
|
{
|
|
|
|
unsigned parameterFootprint = methodParameterFootprint
|
|
|
|
(context->thread, context->method);
|
|
|
|
|
|
|
|
if (index < parameterFootprint) {
|
|
|
|
return parameterFootprint - index - footprint;
|
|
|
|
} else {
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Compiler::Operand*
|
|
|
|
loadLocal(Context* context, unsigned footprint, unsigned index)
|
|
|
|
{
|
|
|
|
return context->compiler->loadLocal
|
|
|
|
(footprint, translateLocalIndex(context, footprint, index));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
storeLocal(Context* context, unsigned footprint, Compiler::Operand* value,
|
|
|
|
unsigned index)
|
|
|
|
{
|
|
|
|
context->compiler->storeLocal
|
|
|
|
(footprint, value, translateLocalIndex(context, footprint, index));
|
|
|
|
}
|
|
|
|
|
2007-12-31 22:40:56 +00:00
|
|
|
class Frame {
|
|
|
|
public:
|
2008-02-11 17:21:41 +00:00
|
|
|
enum StackType {
|
|
|
|
Integer,
|
|
|
|
Long,
|
|
|
|
Object
|
|
|
|
};
|
|
|
|
|
|
|
|
Frame(Context* context, uint8_t* stackMap):
|
2007-12-31 22:40:56 +00:00
|
|
|
context(context),
|
2008-02-11 17:21:41 +00:00
|
|
|
t(context->thread),
|
|
|
|
c(context->compiler),
|
2009-02-14 20:26:39 +00:00
|
|
|
subroutine(0),
|
2008-01-07 14:51:07 +00:00
|
|
|
stackMap(stackMap),
|
2007-12-09 22:45:43 +00:00
|
|
|
ip(0),
|
2008-01-07 16:01:35 +00:00
|
|
|
sp(localSize()),
|
2008-01-07 14:51:07 +00:00
|
|
|
level(0)
|
2007-12-09 22:45:43 +00:00
|
|
|
{
|
2008-02-11 17:21:41 +00:00
|
|
|
memset(stackMap, 0, codeMaxStack(t, methodCode(t, context->method)));
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
Frame(Frame* f, uint8_t* stackMap):
|
2007-12-31 22:40:56 +00:00
|
|
|
context(f->context),
|
2008-02-11 17:21:41 +00:00
|
|
|
t(context->thread),
|
|
|
|
c(context->compiler),
|
2009-02-14 20:26:39 +00:00
|
|
|
subroutine(f->subroutine),
|
2008-01-07 14:51:07 +00:00
|
|
|
stackMap(stackMap),
|
2007-12-09 22:45:43 +00:00
|
|
|
ip(f->ip),
|
2008-01-07 14:51:07 +00:00
|
|
|
sp(f->sp),
|
|
|
|
level(f->level + 1)
|
2007-12-09 22:45:43 +00:00
|
|
|
{
|
2008-02-11 17:21:41 +00:00
|
|
|
memcpy(stackMap, f->stackMap, codeMaxStack
|
|
|
|
(t, methodCode(t, context->method)));
|
2008-01-07 14:51:07 +00:00
|
|
|
|
|
|
|
if (level > 1) {
|
2008-07-05 20:21:13 +00:00
|
|
|
context->eventLog.append(PushContextEvent);
|
2008-01-07 14:51:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
~Frame() {
|
2008-04-28 15:53:48 +00:00
|
|
|
if (t->exception == 0) {
|
|
|
|
if (level > 1) {
|
2008-07-05 20:21:13 +00:00
|
|
|
context->eventLog.append(PopContextEvent);
|
2008-04-28 15:53:48 +00:00
|
|
|
}
|
2008-01-07 14:51:07 +00:00
|
|
|
}
|
2007-10-10 22:39:40 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* append(object o) {
|
2008-11-23 23:58:01 +00:00
|
|
|
if (context->bootContext) {
|
|
|
|
BootContext* bc = context->bootContext;
|
|
|
|
|
2008-11-27 20:59:40 +00:00
|
|
|
Promise* p = new (bc->zone->allocate(sizeof(ListenPromise)))
|
|
|
|
ListenPromise(t->m->system, bc->zone);
|
2008-11-23 23:58:01 +00:00
|
|
|
|
2008-11-27 20:59:40 +00:00
|
|
|
PROTECT(t, o);
|
2008-11-23 23:58:01 +00:00
|
|
|
object pointer = makePointer(t, p);
|
2008-11-27 20:59:40 +00:00
|
|
|
bc->constants = makeTriple(t, o, pointer, bc->constants);
|
2008-11-23 23:58:01 +00:00
|
|
|
|
|
|
|
return c->promiseConstant(p);
|
|
|
|
} else {
|
|
|
|
context->objectPool = new
|
|
|
|
(context->zone.allocate(sizeof(PoolElement)))
|
|
|
|
PoolElement(t, o, context->objectPool);
|
|
|
|
|
2008-11-29 01:23:01 +00:00
|
|
|
++ context->objectPoolCount;
|
|
|
|
|
2008-11-23 23:58:01 +00:00
|
|
|
return c->address(context->objectPool);
|
|
|
|
}
|
2007-10-10 22:39:40 +00:00
|
|
|
}
|
|
|
|
|
2008-01-07 14:51:07 +00:00
|
|
|
unsigned localSize() {
|
2008-01-20 18:55:08 +00:00
|
|
|
return ::localSize(t, context->method);
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
|
|
|
|
2008-01-07 14:51:07 +00:00
|
|
|
unsigned stackSize() {
|
|
|
|
return codeMaxStack(t, methodCode(t, context->method));
|
2007-10-11 22:43:03 +00:00
|
|
|
}
|
|
|
|
|
2008-01-07 14:51:07 +00:00
|
|
|
unsigned frameSize() {
|
|
|
|
return localSize() + stackSize();
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2007-10-11 22:43:03 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
void set(unsigned index, uint8_t type) {
|
2008-01-07 14:51:07 +00:00
|
|
|
assert(t, index < frameSize());
|
2007-10-10 22:39:40 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
if (type == Object) {
|
|
|
|
context->eventLog.append(MarkEvent);
|
|
|
|
context->eventLog.append2(index);
|
|
|
|
} else {
|
|
|
|
context->eventLog.append(ClearEvent);
|
|
|
|
context->eventLog.append2(index);
|
2008-01-07 14:51:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int si = index - localSize();
|
|
|
|
if (si >= 0) {
|
2008-02-11 17:21:41 +00:00
|
|
|
stackMap[si] = type;
|
2008-01-07 14:51:07 +00:00
|
|
|
}
|
2007-10-10 22:39:40 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
uint8_t get(unsigned index) {
|
2008-01-07 14:51:07 +00:00
|
|
|
assert(t, index < frameSize());
|
|
|
|
int si = index - localSize();
|
|
|
|
assert(t, si >= 0);
|
2008-02-11 17:21:41 +00:00
|
|
|
return stackMap[si];
|
2007-10-10 22:39:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void pushedInt() {
|
2008-01-07 14:51:07 +00:00
|
|
|
assert(t, sp + 1 <= frameSize());
|
2008-02-11 17:21:41 +00:00
|
|
|
set(sp++, Integer);
|
|
|
|
}
|
|
|
|
|
|
|
|
void pushedLong() {
|
|
|
|
assert(t, sp + 2 <= frameSize());
|
|
|
|
set(sp++, Long);
|
|
|
|
set(sp++, Long);
|
2007-10-10 22:39:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void pushedObject() {
|
2008-01-07 14:51:07 +00:00
|
|
|
assert(t, sp + 1 <= frameSize());
|
2008-02-11 17:21:41 +00:00
|
|
|
set(sp++, Object);
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2007-12-12 22:19:13 +00:00
|
|
|
|
|
|
|
void popped(unsigned count) {
|
|
|
|
assert(t, sp >= count);
|
2008-01-07 14:51:07 +00:00
|
|
|
assert(t, sp - count >= localSize());
|
2007-12-12 22:19:13 +00:00
|
|
|
while (count) {
|
2008-02-11 17:21:41 +00:00
|
|
|
set(--sp, Integer);
|
2007-12-12 22:19:13 +00:00
|
|
|
-- count;
|
|
|
|
}
|
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
|
|
|
|
void poppedInt() {
|
|
|
|
assert(t, sp >= 1);
|
2008-01-07 14:51:07 +00:00
|
|
|
assert(t, sp - 1 >= localSize());
|
2008-02-11 17:21:41 +00:00
|
|
|
assert(t, get(sp - 1) == Integer);
|
2007-12-09 22:45:43 +00:00
|
|
|
-- sp;
|
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
void poppedLong() {
|
|
|
|
assert(t, sp >= 1);
|
|
|
|
assert(t, sp - 2 >= localSize());
|
|
|
|
assert(t, get(sp - 1) == Long);
|
|
|
|
assert(t, get(sp - 2) == Long);
|
|
|
|
sp -= 2;
|
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void poppedObject() {
|
|
|
|
assert(t, sp >= 1);
|
2008-01-07 14:51:07 +00:00
|
|
|
assert(t, sp - 1 >= localSize());
|
2008-02-11 17:21:41 +00:00
|
|
|
assert(t, get(sp - 1) == Object);
|
|
|
|
set(--sp, Integer);
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void storedInt(unsigned index) {
|
2008-01-07 14:51:07 +00:00
|
|
|
assert(t, index < localSize());
|
2008-02-11 17:21:41 +00:00
|
|
|
set(index, Integer);
|
|
|
|
}
|
|
|
|
|
|
|
|
void storedLong(unsigned index) {
|
|
|
|
assert(t, index + 1 < localSize());
|
|
|
|
set(index, Long);
|
|
|
|
set(index + 1, Long);
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void storedObject(unsigned index) {
|
2008-01-07 14:51:07 +00:00
|
|
|
assert(t, index < localSize());
|
2008-02-11 17:21:41 +00:00
|
|
|
set(index, Object);
|
2007-10-10 22:39:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void dupped() {
|
2008-01-07 14:51:07 +00:00
|
|
|
assert(t, sp + 1 <= frameSize());
|
|
|
|
assert(t, sp - 1 >= localSize());
|
2009-02-28 21:41:05 +00:00
|
|
|
set(sp, get(sp - 1));
|
|
|
|
++ sp;
|
2007-10-10 22:39:40 +00:00
|
|
|
}
|
|
|
|
|
2007-10-16 17:21:26 +00:00
|
|
|
void duppedX1() {
|
2008-01-07 14:51:07 +00:00
|
|
|
assert(t, sp + 1 <= frameSize());
|
|
|
|
assert(t, sp - 2 >= localSize());
|
2007-12-09 22:45:43 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
uint8_t b2 = get(sp - 2);
|
|
|
|
uint8_t b1 = get(sp - 1);
|
2007-12-09 22:45:43 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
set(sp - 1, b2);
|
|
|
|
set(sp - 2, b1);
|
|
|
|
set(sp , b1);
|
2007-12-09 22:45:43 +00:00
|
|
|
|
|
|
|
++ sp;
|
2007-10-16 17:21:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void duppedX2() {
|
2008-01-07 14:51:07 +00:00
|
|
|
assert(t, sp + 1 <= frameSize());
|
|
|
|
assert(t, sp - 3 >= localSize());
|
2007-12-09 22:45:43 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
uint8_t b3 = get(sp - 3);
|
|
|
|
uint8_t b2 = get(sp - 2);
|
|
|
|
uint8_t b1 = get(sp - 1);
|
2007-12-09 22:45:43 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
set(sp - 2, b3);
|
|
|
|
set(sp - 1, b2);
|
|
|
|
set(sp - 3, b1);
|
|
|
|
set(sp , b1);
|
2007-12-09 22:45:43 +00:00
|
|
|
|
|
|
|
++ sp;
|
2007-10-16 17:21:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void dupped2() {
|
2008-01-07 14:51:07 +00:00
|
|
|
assert(t, sp + 2 <= frameSize());
|
|
|
|
assert(t, sp - 2 >= localSize());
|
2007-12-09 22:45:43 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
uint8_t b2 = get(sp - 2);
|
|
|
|
uint8_t b1 = get(sp - 1);
|
2007-12-09 22:45:43 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
set(sp, b2);
|
|
|
|
set(sp + 1, b1);
|
2007-12-09 22:45:43 +00:00
|
|
|
|
|
|
|
sp += 2;
|
2007-10-16 17:21:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void dupped2X1() {
|
2008-01-07 14:51:07 +00:00
|
|
|
assert(t, sp + 2 <= frameSize());
|
|
|
|
assert(t, sp - 3 >= localSize());
|
2007-12-09 22:45:43 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
uint8_t b3 = get(sp - 3);
|
|
|
|
uint8_t b2 = get(sp - 2);
|
|
|
|
uint8_t b1 = get(sp - 1);
|
2007-12-09 22:45:43 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
set(sp - 1, b3);
|
|
|
|
set(sp - 3, b2);
|
|
|
|
set(sp , b2);
|
|
|
|
set(sp - 2, b1);
|
|
|
|
set(sp + 1, b1);
|
2007-12-09 22:45:43 +00:00
|
|
|
|
|
|
|
sp += 2;
|
2007-10-16 17:21:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void dupped2X2() {
|
2008-01-07 14:51:07 +00:00
|
|
|
assert(t, sp + 2 <= frameSize());
|
|
|
|
assert(t, sp - 4 >= localSize());
|
2007-10-16 17:21:26 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
uint8_t b4 = get(sp - 4);
|
|
|
|
uint8_t b3 = get(sp - 3);
|
|
|
|
uint8_t b2 = get(sp - 2);
|
|
|
|
uint8_t b1 = get(sp - 1);
|
2007-10-10 22:39:40 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
set(sp - 2, b4);
|
|
|
|
set(sp - 1, b3);
|
|
|
|
set(sp - 4, b2);
|
|
|
|
set(sp , b2);
|
|
|
|
set(sp - 3, b1);
|
|
|
|
set(sp + 1, b1);
|
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() {
|
2008-01-07 16:01:35 +00:00
|
|
|
assert(t, sp - 2 >= localSize());
|
2007-12-09 22:45:43 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
uint8_t saved = get(sp - 1);
|
2007-10-10 22:39:40 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
set(sp - 1, get(sp - 2));
|
|
|
|
set(sp - 2, saved);
|
2007-10-10 22:39:40 +00:00
|
|
|
}
|
|
|
|
|
2008-12-02 16:45:20 +00:00
|
|
|
Promise* addressPromise(Promise* p) {
|
|
|
|
BootContext* bc = context->bootContext;
|
|
|
|
if (bc) {
|
|
|
|
bc->addresses = new (bc->zone->allocate(sizeof(DelayedPromise)))
|
|
|
|
DelayedPromise(t->m->system, bc->zone, p, bc->addresses);
|
|
|
|
return bc->addresses;
|
|
|
|
} else {
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Compiler::Operand* addressOperand(Promise* p) {
|
|
|
|
return c->promiseConstant(addressPromise(p));
|
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* machineIp(unsigned logicalIp) {
|
2007-12-16 00:24:15 +00:00
|
|
|
return c->promiseConstant(c->machineIp(logicalIp));
|
|
|
|
}
|
|
|
|
|
2008-01-07 14:51:07 +00:00
|
|
|
void visitLogicalIp(unsigned ip) {
|
2008-04-20 00:43:12 +00:00
|
|
|
c->visitLogicalIp(ip);
|
|
|
|
|
2008-01-07 14:51:07 +00:00
|
|
|
context->eventLog.append(IpEvent);
|
2008-01-07 16:01:35 +00:00
|
|
|
context->eventLog.append2(ip);
|
2008-01-07 14:51:07 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void startLogicalIp(unsigned ip) {
|
|
|
|
c->startLogicalIp(ip);
|
2007-12-26 16:56:14 +00:00
|
|
|
|
2008-04-20 05:23:08 +00:00
|
|
|
context->eventLog.append(IpEvent);
|
|
|
|
context->eventLog.append2(ip);
|
2007-12-26 16:56:14 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
this->ip = ip;
|
2007-12-26 16:56:14 +00:00
|
|
|
}
|
|
|
|
|
2008-11-02 22:25:51 +00:00
|
|
|
void pushQuiet(unsigned footprint, Compiler::Operand* o) {
|
|
|
|
c->push(footprint, o);
|
2008-09-23 21:18:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void pushLongQuiet(Compiler::Operand* o) {
|
2008-11-02 22:25:51 +00:00
|
|
|
pushQuiet(2, o);
|
2008-07-05 20:21:13 +00:00
|
|
|
}
|
|
|
|
|
2008-11-02 22:25:51 +00:00
|
|
|
Compiler::Operand* popQuiet(unsigned footprint) {
|
|
|
|
return c->pop(footprint);
|
2008-09-23 21:18:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Compiler::Operand* popLongQuiet() {
|
2008-11-02 22:25:51 +00:00
|
|
|
Compiler::Operand* r = popQuiet(2);
|
2008-07-05 20:21:13 +00:00
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
void pushInt(Compiler::Operand* o) {
|
2008-11-02 22:25:51 +00:00
|
|
|
pushQuiet(1, o);
|
2007-12-09 22:45:43 +00:00
|
|
|
pushedInt();
|
2007-10-11 22:43:03 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
void pushAddress(Compiler::Operand* o) {
|
2008-11-02 22:25:51 +00:00
|
|
|
pushQuiet(1, o);
|
2007-12-26 23:59:55 +00:00
|
|
|
pushedInt();
|
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
void pushObject(Compiler::Operand* o) {
|
2008-11-02 22:25:51 +00:00
|
|
|
pushQuiet(1, o);
|
2007-12-09 22:45:43 +00:00
|
|
|
pushedObject();
|
2007-10-11 22:43:03 +00:00
|
|
|
}
|
|
|
|
|
2007-12-12 22:19:13 +00:00
|
|
|
void pushObject() {
|
2008-07-05 20:21:13 +00:00
|
|
|
c->pushed();
|
2007-12-12 22:19:13 +00:00
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
pushedObject();
|
2008-02-12 02:06:12 +00:00
|
|
|
}
|
2007-12-16 21:30:19 +00:00
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
void pushLong(Compiler::Operand* o) {
|
2008-09-23 21:18:41 +00:00
|
|
|
pushLongQuiet(o);
|
2008-02-11 17:21:41 +00:00
|
|
|
pushedLong();
|
2007-10-11 22:43:03 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void pop(unsigned count) {
|
2007-12-12 22:19:13 +00:00
|
|
|
popped(count);
|
2009-05-15 02:08:01 +00:00
|
|
|
c->popped(count);
|
2007-10-11 22:43:03 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* popInt() {
|
2007-12-09 22:45:43 +00:00
|
|
|
poppedInt();
|
2008-11-02 22:25:51 +00:00
|
|
|
return popQuiet(1);
|
2008-01-03 18:37:00 +00:00
|
|
|
}
|
2007-12-16 21:30:19 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* popLong() {
|
|
|
|
poppedLong();
|
2008-09-23 21:18:41 +00:00
|
|
|
return popLongQuiet();
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2007-10-11 22:43:03 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* popObject() {
|
2007-12-09 22:45:43 +00:00
|
|
|
poppedObject();
|
2008-11-02 22:25:51 +00:00
|
|
|
return popQuiet(1);
|
2007-10-11 22:43:03 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void loadInt(unsigned index) {
|
2008-01-07 14:51:07 +00:00
|
|
|
assert(t, index < localSize());
|
2009-05-03 20:57:11 +00:00
|
|
|
pushInt(loadLocal(context, 1, index));
|
2007-10-10 22:39:40 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void loadLong(unsigned index) {
|
2008-02-11 17:21:41 +00:00
|
|
|
assert(t, index < static_cast<unsigned>(localSize() - 1));
|
2009-05-03 20:57:11 +00:00
|
|
|
pushLong(loadLocal(context, 2, index));
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2007-10-11 22:43:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void loadObject(unsigned index) {
|
2008-01-07 14:51:07 +00:00
|
|
|
assert(t, index < localSize());
|
2009-05-03 20:57:11 +00:00
|
|
|
pushObject(loadLocal(context, 1, index));
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2007-10-11 22:43:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void storeInt(unsigned index) {
|
2009-05-03 20:57:11 +00:00
|
|
|
storeLocal(context, 1, popInt(), index);
|
2009-05-18 15:16:17 +00:00
|
|
|
storedInt(translateLocalIndex(context, 1, index));
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2007-10-11 22:43:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void storeLong(unsigned index) {
|
2009-05-03 20:57:11 +00:00
|
|
|
storeLocal(context, 2, popLong(), index);
|
2009-05-18 15:16:17 +00:00
|
|
|
storedLong(translateLocalIndex(context, 2, index));
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2007-10-11 22:43:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void storeObject(unsigned index) {
|
2009-05-03 20:57:11 +00:00
|
|
|
storeLocal(context, 1, popObject(), index);
|
2009-05-18 15:16:17 +00:00
|
|
|
storedObject(translateLocalIndex(context, 1, index));
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2007-10-11 22:43:03 +00:00
|
|
|
|
2007-12-26 23:59:55 +00:00
|
|
|
void storeObjectOrAddress(unsigned index) {
|
2009-05-03 20:57:11 +00:00
|
|
|
storeLocal(context, 1, popQuiet(1), index);
|
2007-12-26 23:59:55 +00:00
|
|
|
|
|
|
|
assert(t, sp >= 1);
|
2008-01-07 14:51:07 +00:00
|
|
|
assert(t, sp - 1 >= localSize());
|
2008-02-11 17:21:41 +00:00
|
|
|
if (get(sp - 1) == Object) {
|
2009-05-18 15:16:17 +00:00
|
|
|
storedObject(translateLocalIndex(context, 1, index));
|
2007-12-26 23:59:55 +00:00
|
|
|
} else {
|
2009-05-18 15:16:17 +00:00
|
|
|
storedInt(translateLocalIndex(context, 1, index));
|
2007-12-26 23:59:55 +00:00
|
|
|
}
|
|
|
|
|
2008-01-07 14:51:07 +00:00
|
|
|
popped(1);
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2007-10-11 22:43:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void dup() {
|
2008-11-02 22:25:51 +00:00
|
|
|
pushQuiet(1, c->peek(1, 0));
|
2008-02-11 17:21:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
dupped();
|
|
|
|
}
|
2007-10-11 22:43:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void dupX1() {
|
2008-11-02 22:25:51 +00:00
|
|
|
Compiler::Operand* s0 = popQuiet(1);
|
|
|
|
Compiler::Operand* s1 = popQuiet(1);
|
2008-02-11 17:21:41 +00:00
|
|
|
|
2008-11-02 22:25:51 +00:00
|
|
|
pushQuiet(1, s0);
|
|
|
|
pushQuiet(1, s1);
|
|
|
|
pushQuiet(1, 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() {
|
2008-11-02 22:25:51 +00:00
|
|
|
Compiler::Operand* s0 = popQuiet(1);
|
2008-02-11 17:21:41 +00:00
|
|
|
|
|
|
|
if (get(sp - 2) == Long) {
|
2008-09-23 21:18:41 +00:00
|
|
|
Compiler::Operand* s1 = popLongQuiet();
|
2008-02-12 02:06:12 +00:00
|
|
|
|
2008-11-02 22:25:51 +00:00
|
|
|
pushQuiet(1, s0);
|
2008-09-23 21:18:41 +00:00
|
|
|
pushLongQuiet(s1);
|
2008-11-02 22:25:51 +00:00
|
|
|
pushQuiet(1, s0);
|
2008-02-11 17:21:41 +00:00
|
|
|
} else {
|
2008-11-02 22:25:51 +00:00
|
|
|
Compiler::Operand* s1 = popQuiet(1);
|
|
|
|
Compiler::Operand* s2 = popQuiet(1);
|
2008-02-11 17:21:41 +00:00
|
|
|
|
2008-11-02 22:25:51 +00:00
|
|
|
pushQuiet(1, s0);
|
|
|
|
pushQuiet(1, s2);
|
|
|
|
pushQuiet(1, s1);
|
|
|
|
pushQuiet(1, s0);
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
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() {
|
2008-02-11 17:21:41 +00:00
|
|
|
if (get(sp - 1) == Long) {
|
2008-11-07 00:39:38 +00:00
|
|
|
pushLongQuiet(c->peek(2, 0));
|
2008-02-11 17:21:41 +00:00
|
|
|
} else {
|
2008-11-02 22:25:51 +00:00
|
|
|
Compiler::Operand* s0 = popQuiet(1);
|
|
|
|
Compiler::Operand* s1 = popQuiet(1);
|
2008-02-11 17:21:41 +00:00
|
|
|
|
2008-11-02 22:25:51 +00:00
|
|
|
pushQuiet(1, s1);
|
|
|
|
pushQuiet(1, s0);
|
|
|
|
pushQuiet(1, s1);
|
|
|
|
pushQuiet(1, s0);
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
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() {
|
2008-02-11 17:21:41 +00:00
|
|
|
if (get(sp - 1) == Long) {
|
2008-09-23 21:18:41 +00:00
|
|
|
Compiler::Operand* s0 = popLongQuiet();
|
2008-11-02 22:25:51 +00:00
|
|
|
Compiler::Operand* s1 = popQuiet(1);
|
2008-02-11 17:21:41 +00:00
|
|
|
|
2008-09-23 21:18:41 +00:00
|
|
|
pushLongQuiet(s0);
|
2008-11-02 22:25:51 +00:00
|
|
|
pushQuiet(1, s1);
|
2008-09-23 21:18:41 +00:00
|
|
|
pushLongQuiet(s0);
|
2008-02-12 02:06:12 +00:00
|
|
|
} else {
|
2008-11-02 22:25:51 +00:00
|
|
|
Compiler::Operand* s0 = popQuiet(1);
|
|
|
|
Compiler::Operand* s1 = popQuiet(1);
|
|
|
|
Compiler::Operand* s2 = popQuiet(1);
|
|
|
|
|
|
|
|
pushQuiet(1, s1);
|
|
|
|
pushQuiet(1, s0);
|
|
|
|
pushQuiet(1, s2);
|
|
|
|
pushQuiet(1, s1);
|
|
|
|
pushQuiet(1, s0);
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
|
|
|
|
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() {
|
2008-02-11 17:21:41 +00:00
|
|
|
if (get(sp - 1) == Long) {
|
2008-09-23 21:18:41 +00:00
|
|
|
Compiler::Operand* s0 = popLongQuiet();
|
2008-02-12 02:06:12 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
if (get(sp - 3) == Long) {
|
2008-09-23 21:18:41 +00:00
|
|
|
Compiler::Operand* s1 = popLongQuiet();
|
2008-02-12 02:06:12 +00:00
|
|
|
|
2008-09-23 21:18:41 +00:00
|
|
|
pushLongQuiet(s0);
|
|
|
|
pushLongQuiet(s1);
|
|
|
|
pushLongQuiet(s0);
|
2008-02-11 17:21:41 +00:00
|
|
|
} else {
|
2008-11-02 22:25:51 +00:00
|
|
|
Compiler::Operand* s1 = popQuiet(1);
|
|
|
|
Compiler::Operand* s2 = popQuiet(1);
|
2008-02-11 17:21:41 +00:00
|
|
|
|
2008-09-23 21:18:41 +00:00
|
|
|
pushLongQuiet(s0);
|
2008-11-02 22:25:51 +00:00
|
|
|
pushQuiet(1, s2);
|
|
|
|
pushQuiet(1, s1);
|
2008-09-23 21:18:41 +00:00
|
|
|
pushLongQuiet(s0);
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
|
|
|
} else {
|
2008-11-02 22:25:51 +00:00
|
|
|
Compiler::Operand* s0 = popQuiet(1);
|
|
|
|
Compiler::Operand* s1 = popQuiet(1);
|
|
|
|
Compiler::Operand* s2 = popQuiet(1);
|
|
|
|
Compiler::Operand* s3 = popQuiet(1);
|
|
|
|
|
|
|
|
pushQuiet(1, s1);
|
|
|
|
pushQuiet(1, s0);
|
|
|
|
pushQuiet(1, s3);
|
|
|
|
pushQuiet(1, s2);
|
|
|
|
pushQuiet(1, s1);
|
|
|
|
pushQuiet(1, s0);
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
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() {
|
2008-11-02 22:25:51 +00:00
|
|
|
Compiler::Operand* s0 = popQuiet(1);
|
|
|
|
Compiler::Operand* s1 = popQuiet(1);
|
2007-10-02 00:08:17 +00:00
|
|
|
|
2008-11-02 22:25:51 +00:00
|
|
|
pushQuiet(1, s0);
|
|
|
|
pushQuiet(1, s1);
|
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-31 22:40:56 +00:00
|
|
|
|
2009-03-31 20:15:08 +00:00
|
|
|
TraceElement* trace(object target, unsigned flags) {
|
2008-01-07 14:51:07 +00:00
|
|
|
unsigned mapSize = frameMapSizeInWords(t, context->method);
|
2007-12-31 22:40:56 +00:00
|
|
|
|
|
|
|
TraceElement* e = context->traceLog = new
|
|
|
|
(context->zone.allocate(sizeof(TraceElement) + (mapSize * BytesPerWord)))
|
2009-03-31 20:15:08 +00:00
|
|
|
TraceElement(context, target, flags, context->traceLog);
|
2007-12-31 22:40:56 +00:00
|
|
|
|
2008-04-07 23:47:41 +00:00
|
|
|
++ context->traceLogCount;
|
|
|
|
|
2008-01-07 14:51:07 +00:00
|
|
|
context->eventLog.append(TraceEvent);
|
|
|
|
context->eventLog.appendAddress(e);
|
2007-12-31 22:40:56 +00:00
|
|
|
|
|
|
|
return e;
|
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
|
2007-12-31 22:40:56 +00:00
|
|
|
Context* context;
|
2007-12-09 22:45:43 +00:00
|
|
|
MyThread* t;
|
|
|
|
Compiler* c;
|
2009-02-14 20:26:39 +00:00
|
|
|
Compiler::Subroutine* subroutine;
|
2008-02-11 17:21:41 +00:00
|
|
|
uint8_t* stackMap;
|
2007-12-09 22:45:43 +00:00
|
|
|
unsigned ip;
|
|
|
|
unsigned sp;
|
2008-01-07 14:51:07 +00:00
|
|
|
unsigned level;
|
2007-12-30 22:24:48 +00:00
|
|
|
};
|
|
|
|
|
2008-01-20 18:55:08 +00:00
|
|
|
unsigned
|
|
|
|
savedTargetIndex(MyThread* t, object method)
|
|
|
|
{
|
|
|
|
return codeMaxLocals(t, methodCode(t, method));
|
|
|
|
}
|
|
|
|
|
2008-04-07 23:47:41 +00:00
|
|
|
object
|
|
|
|
findCallNode(MyThread* t, void* address);
|
|
|
|
|
|
|
|
void
|
|
|
|
insertCallNode(MyThread* t, object node);
|
|
|
|
|
2008-04-11 19:03:40 +00:00
|
|
|
void*
|
|
|
|
findExceptionHandler(Thread* t, object method, void* ip)
|
|
|
|
{
|
2009-05-03 20:57:11 +00:00
|
|
|
if (t->exception) {
|
|
|
|
object table = codeExceptionHandlerTable(t, methodCode(t, method));
|
|
|
|
if (table) {
|
|
|
|
object index = arrayBody(t, table, 0);
|
2008-04-11 19:03:40 +00:00
|
|
|
|
2009-05-03 20:57:11 +00:00
|
|
|
uint8_t* compiled = reinterpret_cast<uint8_t*>
|
|
|
|
(methodCompiled(t, method));
|
2008-04-11 19:03:40 +00:00
|
|
|
|
2009-05-03 20:57:11 +00:00
|
|
|
for (unsigned i = 0; i < arrayLength(t, table) - 1; ++i) {
|
|
|
|
unsigned start = intArrayBody(t, index, i * 3);
|
|
|
|
unsigned end = intArrayBody(t, index, (i * 3) + 1);
|
|
|
|
unsigned key = difference(ip, compiled) - 1;
|
2008-04-11 19:03:40 +00:00
|
|
|
|
2009-05-03 20:57:11 +00:00
|
|
|
if (key >= start and key < end) {
|
|
|
|
object catchType = arrayBody(t, table, i + 1);
|
2008-04-11 19:03:40 +00:00
|
|
|
|
2009-05-03 20:57:11 +00:00
|
|
|
if (catchType == 0 or instanceOf(t, catchType, t->exception)) {
|
|
|
|
return compiled + intArrayBody(t, index, (i * 3) + 2);
|
|
|
|
}
|
2008-04-11 19:03:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-05-03 20:57:11 +00:00
|
|
|
void
|
2009-05-05 01:04:17 +00:00
|
|
|
releaseLock(MyThread* t, object method, void* stack)
|
2009-05-03 20:57:11 +00:00
|
|
|
{
|
|
|
|
if (methodFlags(t, method) & ACC_SYNCHRONIZED) {
|
|
|
|
object lock;
|
|
|
|
if (methodFlags(t, method) & ACC_STATIC) {
|
|
|
|
lock = methodClass(t, method);
|
|
|
|
} else {
|
|
|
|
lock = *localObject
|
|
|
|
(t, stackForFrame(t, stack, method), method,
|
|
|
|
savedTargetIndex(t, method));
|
|
|
|
}
|
|
|
|
|
|
|
|
release(t, lock);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-01-01 17:08:47 +00:00
|
|
|
void
|
|
|
|
findUnwindTarget(MyThread* t, void** targetIp, void** targetBase,
|
|
|
|
void** targetStack)
|
2007-09-29 21:08:29 +00:00
|
|
|
{
|
2007-12-30 22:24:48 +00:00
|
|
|
void* ip = t->ip;
|
2007-12-09 22:45:43 +00:00
|
|
|
void* base = t->base;
|
2008-08-17 19:32:40 +00:00
|
|
|
void* stack = t->stack;
|
2008-04-23 16:33:31 +00:00
|
|
|
if (ip == 0) {
|
2008-08-18 15:23:01 +00:00
|
|
|
ip = t->arch->frameIp(stack);
|
2007-12-30 22:24:48 +00:00
|
|
|
}
|
|
|
|
|
2009-05-17 00:39:08 +00:00
|
|
|
object target = t->trace->targetMethod;
|
|
|
|
|
2008-01-01 17:08:47 +00:00
|
|
|
*targetIp = 0;
|
|
|
|
while (*targetIp == 0) {
|
2008-04-07 23:47:41 +00:00
|
|
|
object method = methodForIp(t, ip);
|
|
|
|
if (method) {
|
2008-04-11 19:03:40 +00:00
|
|
|
void* handler = findExceptionHandler(t, method, ip);
|
2007-12-09 22:45:43 +00:00
|
|
|
|
2009-04-26 22:06:15 +00:00
|
|
|
if (handler) {
|
|
|
|
*targetIp = handler;
|
|
|
|
*targetBase = base;
|
2009-04-26 21:55:35 +00:00
|
|
|
|
2009-04-26 22:06:15 +00:00
|
|
|
t->arch->nextFrame(&stack, &base);
|
2009-04-26 21:55:35 +00:00
|
|
|
|
2009-04-26 22:06:15 +00:00
|
|
|
void** sp = static_cast<void**>(stackForFrame(t, stack, method))
|
2009-02-27 01:54:25 +00:00
|
|
|
+ t->arch->frameReturnAddressSize();
|
2007-10-04 22:41:19 +00:00
|
|
|
|
2009-04-26 22:06:15 +00:00
|
|
|
*targetStack = sp;
|
|
|
|
|
2009-05-17 23:43:48 +00:00
|
|
|
sp[localOffset(t, localSize(t, method), method)] = t->exception;
|
2007-10-04 22:41:19 +00:00
|
|
|
|
2008-08-18 15:23:01 +00:00
|
|
|
t->exception = 0;
|
2007-12-09 22:45:43 +00:00
|
|
|
} else {
|
2009-04-26 22:06:15 +00:00
|
|
|
t->arch->nextFrame(&stack, &base);
|
|
|
|
ip = t->arch->frameIp(stack);
|
|
|
|
|
2009-05-05 01:04:17 +00:00
|
|
|
releaseLock(t, method, stack);
|
2009-05-17 00:39:08 +00:00
|
|
|
|
|
|
|
target = method;
|
2009-05-03 20:57:11 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
*targetIp = ip;
|
|
|
|
*targetBase = base;
|
|
|
|
*targetStack = static_cast<void**>(stack)
|
|
|
|
+ t->arch->frameReturnAddressSize();
|
|
|
|
|
|
|
|
while (t->continuation) {
|
2009-05-17 00:39:08 +00:00
|
|
|
object method = continuationMethod(t, t->continuation);
|
|
|
|
|
2009-05-03 20:57:11 +00:00
|
|
|
void* handler = findExceptionHandler
|
2009-05-17 00:39:08 +00:00
|
|
|
(t, method, continuationAddress(t, t->continuation));
|
2009-05-03 20:57:11 +00:00
|
|
|
|
|
|
|
if (handler) {
|
|
|
|
t->exceptionHandler = handler;
|
|
|
|
|
2009-05-17 00:39:08 +00:00
|
|
|
t->exceptionStack = static_cast<void**>(*targetStack)
|
|
|
|
+ t->arch->argumentFootprint(methodParameterFootprint(t, target))
|
|
|
|
- t->arch->argumentFootprint(methodParameterFootprint(t, method))
|
|
|
|
- stackOffsetFromFrame(t, method);
|
2009-05-03 20:57:11 +00:00
|
|
|
|
2009-05-17 23:43:48 +00:00
|
|
|
t->exceptionOffset
|
|
|
|
= localOffset(t, localSize(t, method), method) * BytesPerWord;
|
2009-05-03 20:57:11 +00:00
|
|
|
break;
|
|
|
|
} else {
|
2009-05-17 00:39:08 +00:00
|
|
|
releaseLock(t, method,
|
2009-05-05 01:04:17 +00:00
|
|
|
reinterpret_cast<uint8_t*>(t->continuation)
|
|
|
|
+ ContinuationBody
|
|
|
|
+ continuationReturnAddressOffset(t, t->continuation)
|
2009-05-16 08:03:03 +00:00
|
|
|
- t->arch->returnAddressOffset());
|
2007-12-28 00:02:05 +00:00
|
|
|
}
|
2009-05-03 20:57:11 +00:00
|
|
|
|
2009-05-05 01:04:17 +00:00
|
|
|
t->continuation = continuationNext(t, t->continuation);
|
2009-05-03 20:57:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
object
|
|
|
|
makeCurrentContinuation(MyThread* t, void** targetIp, void** targetBase,
|
2009-05-17 00:39:08 +00:00
|
|
|
void** targetStack, unsigned* oldArgumentFootprint)
|
2009-05-03 20:57:11 +00:00
|
|
|
{
|
|
|
|
void* ip = t->ip;
|
|
|
|
void* base = t->base;
|
|
|
|
void* stack = t->stack;
|
|
|
|
if (ip == 0) {
|
|
|
|
ip = t->arch->frameIp(stack);
|
|
|
|
}
|
|
|
|
|
|
|
|
object target = t->trace->targetMethod;
|
|
|
|
PROTECT(t, target);
|
|
|
|
|
|
|
|
object first = 0;
|
|
|
|
PROTECT(t, first);
|
|
|
|
|
|
|
|
object last = 0;
|
|
|
|
PROTECT(t, last);
|
|
|
|
|
|
|
|
*targetIp = 0;
|
|
|
|
while (*targetIp == 0) {
|
|
|
|
object method = methodForIp(t, ip);
|
|
|
|
if (method) {
|
|
|
|
PROTECT(t, method);
|
|
|
|
|
2009-05-16 08:03:03 +00:00
|
|
|
void** top = static_cast<void**>(stack)
|
2009-05-17 00:39:08 +00:00
|
|
|
+ t->arch->frameReturnAddressSize();
|
2009-05-03 20:57:11 +00:00
|
|
|
unsigned argumentFootprint
|
|
|
|
= t->arch->argumentFootprint(methodParameterFootprint(t, target));
|
|
|
|
unsigned alignment = t->arch->stackAlignmentInWords();
|
|
|
|
if (argumentFootprint > alignment) {
|
|
|
|
top += argumentFootprint - alignment;
|
|
|
|
}
|
|
|
|
|
|
|
|
t->arch->nextFrame(&stack, &base);
|
|
|
|
|
2009-05-16 08:03:03 +00:00
|
|
|
void** bottom = static_cast<void**>(stack)
|
|
|
|
+ t->arch->frameReturnAddressSize();
|
2009-05-03 20:57:11 +00:00
|
|
|
unsigned frameSize = bottom - top;
|
|
|
|
unsigned totalSize = frameSize
|
|
|
|
+ t->arch->frameFooterSize()
|
|
|
|
+ t->arch->argumentFootprint(methodParameterFootprint(t, method));
|
|
|
|
|
|
|
|
object c = makeContinuation
|
|
|
|
(t, 0, method, ip,
|
2009-05-16 08:03:03 +00:00
|
|
|
((frameSize
|
|
|
|
+ t->arch->returnAddressOffset()
|
|
|
|
- t->arch->frameReturnAddressSize()) * BytesPerWord),
|
|
|
|
((frameSize
|
|
|
|
+ t->arch->framePointerOffset()
|
|
|
|
- t->arch->frameReturnAddressSize()) * BytesPerWord),
|
2009-05-03 20:57:11 +00:00
|
|
|
totalSize);
|
|
|
|
|
|
|
|
memcpy(&continuationBody(t, c, 0), top, totalSize * BytesPerWord);
|
|
|
|
|
|
|
|
if (last) {
|
|
|
|
set(t, last, ContinuationNext, c);
|
|
|
|
} else {
|
|
|
|
first = c;
|
2007-10-12 17:56:43 +00:00
|
|
|
}
|
2009-05-03 20:57:11 +00:00
|
|
|
last = c;
|
|
|
|
|
|
|
|
ip = t->arch->frameIp(stack);
|
|
|
|
|
|
|
|
target = method;
|
2007-10-12 22:06:33 +00:00
|
|
|
} else {
|
2008-01-01 17:08:47 +00:00
|
|
|
*targetIp = ip;
|
|
|
|
*targetBase = base;
|
2008-11-09 23:56:37 +00:00
|
|
|
*targetStack = static_cast<void**>(stack)
|
|
|
|
+ t->arch->frameReturnAddressSize();
|
2009-05-17 00:39:08 +00:00
|
|
|
*oldArgumentFootprint
|
|
|
|
= t->arch->argumentFootprint(methodParameterFootprint(t, target));
|
2007-10-12 17:56:43 +00:00
|
|
|
}
|
|
|
|
}
|
2009-05-03 20:57:11 +00:00
|
|
|
|
|
|
|
expect(t, last);
|
|
|
|
set(t, last, ContinuationNext, t->continuation);
|
|
|
|
|
|
|
|
return first;
|
2007-10-12 17:56:43 +00:00
|
|
|
}
|
|
|
|
|
2008-01-01 17:08:47 +00:00
|
|
|
void NO_RETURN
|
|
|
|
unwind(MyThread* t)
|
|
|
|
{
|
|
|
|
void* ip;
|
|
|
|
void* base;
|
|
|
|
void* stack;
|
|
|
|
findUnwindTarget(t, &ip, &base, &stack);
|
2009-05-05 01:04:17 +00:00
|
|
|
vmJump(ip, base, stack, t, 0, 0);
|
2008-01-01 17:08:47 +00:00
|
|
|
}
|
|
|
|
|
2008-12-02 02:38:00 +00:00
|
|
|
object&
|
|
|
|
objectPools(MyThread* t);
|
|
|
|
|
|
|
|
uintptr_t
|
|
|
|
defaultThunk(MyThread* t);
|
|
|
|
|
|
|
|
uintptr_t
|
|
|
|
nativeThunk(MyThread* t);
|
|
|
|
|
|
|
|
uintptr_t
|
|
|
|
aioobThunk(MyThread* t);
|
|
|
|
|
2009-04-07 00:34:12 +00:00
|
|
|
uintptr_t
|
|
|
|
virtualThunk(MyThread* t, unsigned index);
|
|
|
|
|
2008-12-02 02:38:00 +00:00
|
|
|
uintptr_t
|
|
|
|
methodAddress(Thread* t, object method)
|
|
|
|
{
|
|
|
|
if (methodFlags(t, method) & ACC_NATIVE) {
|
|
|
|
return nativeThunk(static_cast<MyThread*>(t));
|
|
|
|
} else {
|
|
|
|
return methodCompiled(t, method);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-02-28 21:20:43 +00:00
|
|
|
void
|
|
|
|
tryInitClass(MyThread* t, object class_)
|
|
|
|
{
|
|
|
|
initClass(t, class_);
|
|
|
|
if (UNLIKELY(t->exception)) unwind(t);
|
|
|
|
}
|
|
|
|
|
2009-04-05 21:42:10 +00:00
|
|
|
FixedAllocator*
|
|
|
|
codeAllocator(MyThread* t);
|
|
|
|
|
2009-04-07 00:34:12 +00:00
|
|
|
void
|
|
|
|
compile(MyThread* t, Allocator* allocator, BootContext* bootContext,
|
|
|
|
object method);
|
|
|
|
|
2009-02-28 21:20:43 +00:00
|
|
|
int64_t
|
2007-12-30 22:24:48 +00:00
|
|
|
findInterfaceMethodFromInstance(MyThread* t, object method, object instance)
|
2007-10-16 17:21:26 +00:00
|
|
|
{
|
2007-12-30 22:24:48 +00:00
|
|
|
if (instance) {
|
2009-04-05 21:42:10 +00:00
|
|
|
object target = findInterfaceMethod(t, method, objectClass(t, instance));
|
|
|
|
|
|
|
|
if (methodAddress(t, target) == defaultThunk(t)) {
|
|
|
|
PROTECT(t, target);
|
|
|
|
|
|
|
|
compile(t, codeAllocator(t), 0, target);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (UNLIKELY(t->exception)) {
|
|
|
|
unwind(t);
|
|
|
|
} else {
|
2009-05-16 08:03:03 +00:00
|
|
|
if (methodFlags(t, target) & ACC_NATIVE) {
|
|
|
|
t->trace->nativeMethod = target;
|
|
|
|
}
|
2009-04-05 21:42:10 +00:00
|
|
|
return methodAddress(t, target);
|
|
|
|
}
|
2007-12-30 22:24:48 +00:00
|
|
|
} else {
|
|
|
|
t->exception = makeNullPointerException(t);
|
|
|
|
unwind(t);
|
|
|
|
}
|
2007-10-16 17:21:26 +00:00
|
|
|
}
|
|
|
|
|
2009-02-28 21:20:43 +00:00
|
|
|
int64_t
|
2007-10-15 19:12:38 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-02-28 21:20:43 +00:00
|
|
|
int64_t
|
2007-10-15 19:12:38 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-02-28 21:20:43 +00:00
|
|
|
int64_t
|
2007-10-15 19:12:38 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-02-28 21:20:43 +00:00
|
|
|
int64_t
|
2007-10-15 19:12:38 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
uint64_t
|
2007-10-15 19:12:38 +00:00
|
|
|
addDouble(uint64_t b, uint64_t a)
|
|
|
|
{
|
|
|
|
return doubleToBits(bitsToDouble(a) + bitsToDouble(b));
|
|
|
|
}
|
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
uint64_t
|
2007-10-15 19:12:38 +00:00
|
|
|
subtractDouble(uint64_t b, uint64_t a)
|
|
|
|
{
|
|
|
|
return doubleToBits(bitsToDouble(a) - bitsToDouble(b));
|
|
|
|
}
|
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
uint64_t
|
2007-10-15 19:12:38 +00:00
|
|
|
multiplyDouble(uint64_t b, uint64_t a)
|
|
|
|
{
|
|
|
|
return doubleToBits(bitsToDouble(a) * bitsToDouble(b));
|
|
|
|
}
|
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
uint64_t
|
2007-10-15 19:12:38 +00:00
|
|
|
divideDouble(uint64_t b, uint64_t a)
|
|
|
|
{
|
|
|
|
return doubleToBits(bitsToDouble(a) / bitsToDouble(b));
|
|
|
|
}
|
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
uint64_t
|
2007-10-15 19:12:38 +00:00
|
|
|
moduloDouble(uint64_t b, uint64_t a)
|
|
|
|
{
|
|
|
|
return doubleToBits(fmod(bitsToDouble(a), bitsToDouble(b)));
|
|
|
|
}
|
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
uint64_t
|
2007-12-09 22:45:43 +00:00
|
|
|
negateDouble(uint64_t a)
|
|
|
|
{
|
|
|
|
return doubleToBits(- bitsToDouble(a));
|
|
|
|
}
|
|
|
|
|
2009-02-28 21:20:43 +00:00
|
|
|
uint64_t
|
2007-12-09 22:45:43 +00:00
|
|
|
doubleToFloat(int64_t a)
|
|
|
|
{
|
|
|
|
return floatToBits(static_cast<float>(bitsToDouble(a)));
|
|
|
|
}
|
|
|
|
|
2009-02-28 21:20:43 +00:00
|
|
|
int64_t
|
2007-12-09 22:45:43 +00:00
|
|
|
doubleToInt(int64_t a)
|
|
|
|
{
|
|
|
|
return static_cast<int32_t>(bitsToDouble(a));
|
|
|
|
}
|
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
int64_t
|
2007-12-09 22:45:43 +00:00
|
|
|
doubleToLong(int64_t a)
|
|
|
|
{
|
|
|
|
return static_cast<int64_t>(bitsToDouble(a));
|
|
|
|
}
|
|
|
|
|
2009-02-28 21:20:43 +00:00
|
|
|
uint64_t
|
2007-10-15 19:12:38 +00:00
|
|
|
addFloat(uint32_t b, uint32_t a)
|
|
|
|
{
|
|
|
|
return floatToBits(bitsToFloat(a) + bitsToFloat(b));
|
|
|
|
}
|
|
|
|
|
2009-02-28 21:20:43 +00:00
|
|
|
uint64_t
|
2007-10-15 19:12:38 +00:00
|
|
|
subtractFloat(uint32_t b, uint32_t a)
|
|
|
|
{
|
|
|
|
return floatToBits(bitsToFloat(a) - bitsToFloat(b));
|
|
|
|
}
|
|
|
|
|
2009-02-28 21:20:43 +00:00
|
|
|
uint64_t
|
2007-10-15 19:12:38 +00:00
|
|
|
multiplyFloat(uint32_t b, uint32_t a)
|
|
|
|
{
|
|
|
|
return floatToBits(bitsToFloat(a) * bitsToFloat(b));
|
|
|
|
}
|
|
|
|
|
2009-02-28 21:20:43 +00:00
|
|
|
uint64_t
|
2007-10-15 19:12:38 +00:00
|
|
|
divideFloat(uint32_t b, uint32_t a)
|
|
|
|
{
|
|
|
|
return floatToBits(bitsToFloat(a) / bitsToFloat(b));
|
|
|
|
}
|
|
|
|
|
2009-02-28 21:20:43 +00:00
|
|
|
uint64_t
|
2007-10-15 19:12:38 +00:00
|
|
|
moduloFloat(uint32_t b, uint32_t a)
|
|
|
|
{
|
|
|
|
return floatToBits(fmod(bitsToFloat(a), bitsToFloat(b)));
|
|
|
|
}
|
|
|
|
|
2009-02-28 21:20:43 +00:00
|
|
|
uint64_t
|
2007-12-09 22:45:43 +00:00
|
|
|
negateFloat(uint32_t a)
|
|
|
|
{
|
|
|
|
return floatToBits(- bitsToFloat(a));
|
|
|
|
}
|
|
|
|
|
2008-07-05 20:21:13 +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;
|
|
|
|
}
|
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
uint64_t
|
2007-12-09 22:45:43 +00:00
|
|
|
floatToDouble(int32_t a)
|
|
|
|
{
|
|
|
|
return doubleToBits(static_cast<double>(bitsToFloat(a)));
|
|
|
|
}
|
|
|
|
|
2009-02-28 21:20:43 +00:00
|
|
|
int64_t
|
2007-12-09 22:45:43 +00:00
|
|
|
floatToInt(int32_t a)
|
|
|
|
{
|
|
|
|
return static_cast<int32_t>(bitsToFloat(a));
|
|
|
|
}
|
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
int64_t
|
2007-12-09 22:45:43 +00:00
|
|
|
floatToLong(int32_t a)
|
|
|
|
{
|
|
|
|
return static_cast<int64_t>(bitsToFloat(a));
|
|
|
|
}
|
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
uint64_t
|
2007-12-09 22:45:43 +00:00
|
|
|
intToDouble(int32_t a)
|
|
|
|
{
|
|
|
|
return doubleToBits(static_cast<double>(a));
|
|
|
|
}
|
|
|
|
|
2009-02-28 21:20:43 +00:00
|
|
|
uint64_t
|
2007-12-09 22:45:43 +00:00
|
|
|
intToFloat(int32_t a)
|
|
|
|
{
|
|
|
|
return floatToBits(static_cast<float>(a));
|
|
|
|
}
|
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
uint64_t
|
2008-03-21 00:37:58 +00:00
|
|
|
longToDouble(int64_t a)
|
|
|
|
{
|
|
|
|
return doubleToBits(static_cast<double>(a));
|
|
|
|
}
|
|
|
|
|
2009-02-28 21:20:43 +00:00
|
|
|
uint64_t
|
2008-03-21 00:37:58 +00:00
|
|
|
longToFloat(int64_t a)
|
|
|
|
{
|
|
|
|
return floatToBits(static_cast<float>(a));
|
|
|
|
}
|
|
|
|
|
2009-02-28 21:20:43 +00:00
|
|
|
uint64_t
|
2008-04-26 20:56:03 +00:00
|
|
|
makeBlankObjectArray(MyThread* t, object class_, int32_t length)
|
2007-09-30 02:48:27 +00:00
|
|
|
{
|
2008-04-26 20:56:03 +00:00
|
|
|
if (length >= 0) {
|
2009-03-04 03:05:48 +00:00
|
|
|
return reinterpret_cast<uint64_t>(makeObjectArray(t, class_, length));
|
2008-04-26 20:56:03 +00:00
|
|
|
} else {
|
|
|
|
object message = makeString(t, "%d", length);
|
|
|
|
t->exception = makeNegativeArraySizeException(t, message);
|
|
|
|
unwind(t);
|
|
|
|
}
|
2007-09-30 02:48:27 +00:00
|
|
|
}
|
|
|
|
|
2009-02-28 21:20:43 +00:00
|
|
|
uint64_t
|
2008-11-30 01:39:42 +00:00
|
|
|
makeBlankArray(MyThread* t, unsigned type, int32_t length)
|
2007-09-30 02:48:27 +00:00
|
|
|
{
|
2008-04-26 20:56:03 +00:00
|
|
|
if (length >= 0) {
|
2009-03-04 03:05:48 +00:00
|
|
|
object (*constructor)(Thread*, uintptr_t);
|
2008-11-30 01:39:42 +00:00
|
|
|
switch (type) {
|
|
|
|
case T_BOOLEAN:
|
|
|
|
constructor = makeBooleanArray;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case T_CHAR:
|
|
|
|
constructor = makeCharArray;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case T_FLOAT:
|
|
|
|
constructor = makeFloatArray;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case T_DOUBLE:
|
|
|
|
constructor = makeDoubleArray;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case T_BYTE:
|
|
|
|
constructor = makeByteArray;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case T_SHORT:
|
|
|
|
constructor = makeShortArray;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case T_INT:
|
|
|
|
constructor = makeIntArray;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case T_LONG:
|
|
|
|
constructor = makeLongArray;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default: abort(t);
|
|
|
|
}
|
|
|
|
|
2009-03-04 03:05:48 +00:00
|
|
|
return reinterpret_cast<uintptr_t>(constructor(t, length));
|
2008-04-26 20:56:03 +00:00
|
|
|
} else {
|
|
|
|
object message = makeString(t, "%d", length);
|
|
|
|
t->exception = makeNegativeArraySizeException(t, message);
|
|
|
|
unwind(t);
|
|
|
|
}
|
2007-09-30 02:48:27 +00:00
|
|
|
}
|
|
|
|
|
2009-02-28 21:20:43 +00:00
|
|
|
uint64_t
|
2007-12-09 22:45:43 +00:00
|
|
|
lookUpAddress(int32_t key, uintptr_t* start, int32_t count,
|
2007-12-17 20:55:31 +00:00
|
|
|
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-17 20:55:31 +00:00
|
|
|
return default_;
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2007-10-01 15:19:15 +00:00
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
void
|
2007-12-30 22:24:48 +00:00
|
|
|
setMaybeNull(MyThread* t, object o, unsigned offset, object value)
|
2007-12-09 22:45:43 +00:00
|
|
|
{
|
2007-12-31 22:40:56 +00:00
|
|
|
if (LIKELY(o)) {
|
2007-12-30 22:24:48 +00:00
|
|
|
set(t, o, offset, value);
|
|
|
|
} else {
|
|
|
|
t->exception = makeNullPointerException(t);
|
|
|
|
unwind(t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
void
|
2007-12-30 22:24:48 +00:00
|
|
|
acquireMonitorForObject(MyThread* t, object o)
|
|
|
|
{
|
2007-12-31 22:40:56 +00:00
|
|
|
if (LIKELY(o)) {
|
2007-12-30 22:24:48 +00:00
|
|
|
acquire(t, o);
|
|
|
|
} else {
|
|
|
|
t->exception = makeNullPointerException(t);
|
|
|
|
unwind(t);
|
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2007-10-01 15:19:15 +00:00
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
void
|
2007-12-30 22:24:48 +00:00
|
|
|
releaseMonitorForObject(MyThread* t, object o)
|
2007-12-09 22:45:43 +00:00
|
|
|
{
|
2007-12-31 22:40:56 +00:00
|
|
|
if (LIKELY(o)) {
|
2007-12-30 22:24:48 +00:00
|
|
|
release(t, o);
|
|
|
|
} else {
|
|
|
|
t->exception = makeNullPointerException(t);
|
|
|
|
unwind(t);
|
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2007-10-01 15:19:15 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
object
|
2008-11-11 00:07:44 +00:00
|
|
|
makeMultidimensionalArray2(MyThread* t, object class_, uintptr_t* countStack,
|
2007-12-09 22:45:43 +00:00
|
|
|
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) {
|
2008-11-11 00:07:44 +00:00
|
|
|
counts[i] = countStack[dimensions - i - 1];
|
2007-12-09 22:45:43 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-03-04 03:05:48 +00:00
|
|
|
object array = makeArray(t, counts[0]);
|
2007-12-09 22:45:43 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2009-02-28 21:20:43 +00:00
|
|
|
uint64_t
|
2008-05-18 15:45:11 +00:00
|
|
|
makeMultidimensionalArray(MyThread* t, object class_, int32_t dimensions,
|
2008-11-11 00:07:44 +00:00
|
|
|
int32_t offset)
|
2007-10-01 15:19:15 +00:00
|
|
|
{
|
2008-11-11 00:07:44 +00:00
|
|
|
object r = makeMultidimensionalArray2
|
|
|
|
(t, class_, static_cast<uintptr_t*>(t->stack) + offset, dimensions);
|
|
|
|
|
2007-10-01 15:19:15 +00:00
|
|
|
if (UNLIKELY(t->exception)) {
|
|
|
|
unwind(t);
|
|
|
|
} else {
|
2009-02-28 21:20:43 +00:00
|
|
|
return reinterpret_cast<uintptr_t>(r);
|
2007-10-01 15:19:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-05-31 22:14:27 +00:00
|
|
|
unsigned
|
|
|
|
traceSize(Thread* t)
|
2007-09-27 00:01:38 +00:00
|
|
|
{
|
2008-05-31 22:14:27 +00:00
|
|
|
class Counter: public Processor::StackVisitor {
|
|
|
|
public:
|
|
|
|
Counter(): count(0) { }
|
|
|
|
|
|
|
|
virtual bool visit(Processor::StackWalker*) {
|
|
|
|
++ count;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned count;
|
|
|
|
} counter;
|
|
|
|
|
|
|
|
t->m->processor->walkStack(t, &counter);
|
|
|
|
|
|
|
|
return FixedSizeOfArray + (counter.count * ArrayElementSizeOfArray)
|
|
|
|
+ (counter.count * FixedSizeOfTraceElement);
|
2008-01-03 18:37:00 +00:00
|
|
|
}
|
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
void NO_RETURN
|
2008-05-31 22:14:27 +00:00
|
|
|
throwArrayIndexOutOfBounds(MyThread* t)
|
2008-01-03 18:37:00 +00:00
|
|
|
{
|
2008-05-31 22:14:27 +00:00
|
|
|
ensure(t, FixedSizeOfArrayIndexOutOfBoundsException + traceSize(t));
|
|
|
|
|
|
|
|
t->tracing = true;
|
|
|
|
t->exception = makeArrayIndexOutOfBoundsException(t, 0);
|
|
|
|
t->tracing = false;
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
unwind(t);
|
2007-09-27 00:01:38 +00:00
|
|
|
}
|
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
void NO_RETURN
|
2007-12-09 22:45:43 +00:00
|
|
|
throw_(MyThread* t, object o)
|
2007-10-09 17:15:40 +00:00
|
|
|
{
|
2007-12-31 22:40:56 +00:00
|
|
|
if (LIKELY(o)) {
|
2007-12-09 22:45:43 +00:00
|
|
|
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
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
void
|
2007-12-23 00:00:35 +00:00
|
|
|
checkCast(MyThread* t, object class_, object o)
|
|
|
|
{
|
|
|
|
if (UNLIKELY(o and not isAssignableFrom(t, class_, objectClass(t, o)))) {
|
2008-01-15 23:33:20 +00:00
|
|
|
object message = makeString
|
|
|
|
(t, "%s as %s",
|
|
|
|
&byteArrayBody(t, className(t, objectClass(t, o)), 0),
|
|
|
|
&byteArrayBody(t, className(t, class_), 0));
|
2008-01-03 18:37:00 +00:00
|
|
|
t->exception = makeClassCastException(t, message);
|
|
|
|
unwind(t);
|
2007-12-23 00:00:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-02-28 21:20:43 +00:00
|
|
|
uint64_t
|
|
|
|
instanceOf64(Thread* t, object class_, object o)
|
|
|
|
{
|
|
|
|
return instanceOf(t, class_, o);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
makeNewWeakReference64(Thread* t, object class_)
|
|
|
|
{
|
|
|
|
return reinterpret_cast<uintptr_t>(makeNewWeakReference(t, class_));
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
makeNew64(Thread* t, object class_)
|
|
|
|
{
|
|
|
|
return reinterpret_cast<uintptr_t>(makeNew(t, class_));
|
|
|
|
}
|
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
void
|
2008-04-09 19:08:13 +00:00
|
|
|
gcIfNecessary(MyThread* t)
|
|
|
|
{
|
|
|
|
if (UNLIKELY(t->backupHeap)) {
|
|
|
|
collect(t, Heap::MinorCollection);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
unsigned
|
|
|
|
resultSize(MyThread* t, unsigned code)
|
2007-12-09 22:45:43 +00:00
|
|
|
{
|
|
|
|
switch (code) {
|
|
|
|
case ByteField:
|
|
|
|
case BooleanField:
|
|
|
|
case CharField:
|
|
|
|
case ShortField:
|
|
|
|
case FloatField:
|
2008-02-11 17:21:41 +00:00
|
|
|
case IntField:
|
|
|
|
return 4;
|
|
|
|
|
|
|
|
case ObjectField:
|
|
|
|
return BytesPerWord;
|
2007-09-25 23:53:11 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case LongField:
|
2008-02-11 17:21:41 +00:00
|
|
|
case DoubleField:
|
|
|
|
return 8;
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case VoidField:
|
2008-02-11 17:21:41 +00:00
|
|
|
return 0;
|
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
|
|
|
|
2008-03-11 16:57:35 +00:00
|
|
|
void
|
|
|
|
pushReturnValue(MyThread* t, Frame* frame, unsigned code,
|
|
|
|
Compiler::Operand* result)
|
|
|
|
{
|
|
|
|
switch (code) {
|
|
|
|
case ByteField:
|
|
|
|
case BooleanField:
|
|
|
|
case CharField:
|
|
|
|
case ShortField:
|
|
|
|
case FloatField:
|
|
|
|
case IntField:
|
|
|
|
return frame->pushInt(result);
|
|
|
|
|
|
|
|
case ObjectField:
|
|
|
|
return frame->pushObject(result);
|
|
|
|
|
|
|
|
case LongField:
|
|
|
|
case DoubleField:
|
|
|
|
return frame->pushLong(result);
|
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
|
|
|
|
2008-03-10 13:28:21 +00:00
|
|
|
bool
|
|
|
|
emptyMethod(MyThread* t, object method)
|
|
|
|
{
|
2008-03-10 22:37:21 +00:00
|
|
|
return ((methodFlags(t, method) & ACC_NATIVE) == 0)
|
|
|
|
and (codeLength(t, methodCode(t, method)) == 1)
|
|
|
|
and (codeBody(t, methodCode(t, method), 0) == return_);
|
2008-03-10 13:28:21 +00:00
|
|
|
}
|
|
|
|
|
2009-03-31 20:15:08 +00:00
|
|
|
Compiler::Operand*
|
|
|
|
compileDirectInvoke(MyThread* t, Frame* frame, object target, bool tailCall,
|
|
|
|
bool useThunk, unsigned rSize, Promise* addressPromise)
|
|
|
|
{
|
2009-04-07 00:34:12 +00:00
|
|
|
Compiler* c = frame->c;
|
|
|
|
|
2009-04-19 22:36:11 +00:00
|
|
|
unsigned flags = (tailCall ? Compiler::TailJump : 0);
|
2009-03-31 20:15:08 +00:00
|
|
|
|
2009-04-19 22:36:11 +00:00
|
|
|
if (useThunk or (tailCall and (methodFlags(t, target) & ACC_NATIVE))) {
|
|
|
|
if (tailCall) {
|
|
|
|
TraceElement* trace = frame->trace(target, TraceElement::TailCall);
|
|
|
|
Compiler::Operand* returnAddress = c->promiseConstant
|
|
|
|
(new (frame->context->zone.allocate(sizeof(TraceElementPromise)))
|
|
|
|
TraceElementPromise(t->m->system, trace));;
|
2009-03-31 20:15:08 +00:00
|
|
|
|
2009-04-19 22:36:11 +00:00
|
|
|
Compiler::Operand* result = c->stackCall
|
|
|
|
(returnAddress,
|
|
|
|
flags | Compiler::Aligned,
|
2009-04-22 01:39:25 +00:00
|
|
|
trace,
|
2009-04-19 22:36:11 +00:00
|
|
|
rSize,
|
|
|
|
methodParameterFootprint(t, target));
|
|
|
|
|
|
|
|
c->store(BytesPerWord, returnAddress, BytesPerWord,
|
|
|
|
c->memory(c->register_(t->arch->thread()),
|
|
|
|
difference(&(t->tailAddress), t)));
|
|
|
|
|
|
|
|
if (methodFlags(t, target) & ACC_NATIVE) {
|
2009-04-26 02:54:36 +00:00
|
|
|
c->exit(c->constant(nativeThunk(t)));
|
2009-03-31 20:15:08 +00:00
|
|
|
} else {
|
2009-04-26 02:54:36 +00:00
|
|
|
c->exit(c->constant(defaultThunk(t)));
|
2009-03-31 20:15:08 +00:00
|
|
|
}
|
|
|
|
|
2009-04-19 22:36:11 +00:00
|
|
|
return result;
|
|
|
|
} else {
|
2009-03-31 20:15:08 +00:00
|
|
|
return c->stackCall
|
2009-04-19 22:36:11 +00:00
|
|
|
(c->constant(defaultThunk(t)),
|
|
|
|
flags | Compiler::Aligned,
|
|
|
|
frame->trace(target, 0),
|
2009-03-31 20:15:08 +00:00
|
|
|
rSize,
|
|
|
|
methodParameterFootprint(t, target));
|
|
|
|
}
|
2009-04-19 22:36:11 +00:00
|
|
|
} else {
|
|
|
|
Compiler::Operand* address =
|
|
|
|
(addressPromise
|
|
|
|
? c->promiseConstant(addressPromise)
|
|
|
|
: c->constant(methodAddress(t, target)));
|
|
|
|
|
|
|
|
return c->stackCall
|
|
|
|
(address,
|
|
|
|
flags,
|
|
|
|
tailCall ? 0 : frame->trace
|
|
|
|
((methodFlags(t, target) & ACC_NATIVE) ? target : 0, 0),
|
|
|
|
rSize,
|
|
|
|
methodParameterFootprint(t, target));
|
2009-03-31 20:15:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-04-22 01:39:25 +00:00
|
|
|
bool
|
2009-03-31 20:15:08 +00:00
|
|
|
compileDirectInvoke(MyThread* t, Frame* frame, object target, bool tailCall)
|
2007-12-09 22:45:43 +00:00
|
|
|
{
|
2008-02-12 02:06:12 +00:00
|
|
|
unsigned rSize = resultSize(t, methodReturnCode(t, target));
|
|
|
|
|
2008-03-10 13:28:21 +00:00
|
|
|
Compiler::Operand* result = 0;
|
|
|
|
|
2009-04-22 01:39:25 +00:00
|
|
|
if (emptyMethod(t, target)) {
|
|
|
|
tailCall = false;
|
|
|
|
} else {
|
2008-11-30 04:58:09 +00:00
|
|
|
BootContext* bc = frame->context->bootContext;
|
|
|
|
if (bc) {
|
|
|
|
if (methodClass(t, target) == methodClass(t, frame->context->method)
|
|
|
|
or (not classNeedsInit(t, methodClass(t, target))))
|
|
|
|
{
|
|
|
|
Promise* p = new (bc->zone->allocate(sizeof(ListenPromise)))
|
|
|
|
ListenPromise(t->m->system, bc->zone);
|
|
|
|
|
|
|
|
PROTECT(t, target);
|
|
|
|
object pointer = makePointer(t, p);
|
|
|
|
bc->calls = makeTriple(t, target, pointer, bc->calls);
|
|
|
|
|
2009-03-31 20:15:08 +00:00
|
|
|
result = compileDirectInvoke
|
|
|
|
(t, frame, target, tailCall, false, rSize, p);
|
2008-11-27 20:59:40 +00:00
|
|
|
} else {
|
2009-03-31 20:15:08 +00:00
|
|
|
result = compileDirectInvoke
|
|
|
|
(t, frame, target, tailCall, true, rSize, 0);
|
2008-11-27 20:59:40 +00:00
|
|
|
}
|
2008-12-02 02:38:00 +00:00
|
|
|
} else if (methodAddress(t, target) == defaultThunk(t)
|
2008-11-30 04:58:09 +00:00
|
|
|
or classNeedsInit(t, methodClass(t, target)))
|
|
|
|
{
|
2009-03-31 20:15:08 +00:00
|
|
|
result = compileDirectInvoke
|
|
|
|
(t, frame, target, tailCall, true, rSize, 0);
|
2008-04-13 19:48:20 +00:00
|
|
|
} else {
|
2009-03-31 20:15:08 +00:00
|
|
|
result = compileDirectInvoke
|
|
|
|
(t, frame, target, tailCall, false, rSize, 0);
|
2008-04-13 19:48:20 +00:00
|
|
|
}
|
2008-04-09 19:08:13 +00:00
|
|
|
}
|
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
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
if (rSize) {
|
2008-03-11 16:57:35 +00:00
|
|
|
pushReturnValue(t, frame, methodReturnCode(t, target), result);
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
2009-04-22 01:39:25 +00:00
|
|
|
|
|
|
|
return tailCall;
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2007-10-17 01:21:35 +00:00
|
|
|
|
2007-12-28 00:02:05 +00:00
|
|
|
void
|
|
|
|
handleMonitorEvent(MyThread* t, Frame* frame, intptr_t function)
|
|
|
|
{
|
|
|
|
Compiler* c = frame->c;
|
2007-12-31 22:40:56 +00:00
|
|
|
object method = frame->context->method;
|
2007-12-28 00:02:05 +00:00
|
|
|
|
|
|
|
if (methodFlags(t, method) & ACC_SYNCHRONIZED) {
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* lock;
|
2007-12-28 00:02:05 +00:00
|
|
|
if (methodFlags(t, method) & ACC_STATIC) {
|
|
|
|
lock = frame->append(methodClass(t, method));
|
|
|
|
} else {
|
2009-05-03 20:57:11 +00:00
|
|
|
lock = loadLocal(frame->context, 1, savedTargetIndex(t, method));
|
2007-12-28 00:02:05 +00:00
|
|
|
}
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
c->call(c->constant(function),
|
2008-05-31 22:14:27 +00:00
|
|
|
0,
|
2009-03-31 20:15:08 +00:00
|
|
|
frame->trace(0, 0),
|
2008-02-11 17:21:41 +00:00
|
|
|
0,
|
2009-04-07 00:34:12 +00:00
|
|
|
2, c->register_(t->arch->thread()), lock);
|
2008-01-11 22:16:24 +00:00
|
|
|
}
|
2007-12-28 00:02:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
handleEntrance(MyThread* t, Frame* frame)
|
|
|
|
{
|
2008-01-20 18:55:08 +00:00
|
|
|
object method = frame->context->method;
|
|
|
|
|
2008-01-20 22:05:59 +00:00
|
|
|
if ((methodFlags(t, method) & (ACC_SYNCHRONIZED | ACC_STATIC))
|
|
|
|
== ACC_SYNCHRONIZED)
|
2008-01-20 18:55:08 +00:00
|
|
|
{
|
|
|
|
// save 'this' pointer in case it is overwritten.
|
|
|
|
unsigned index = savedTargetIndex(t, method);
|
2009-05-03 20:57:11 +00:00
|
|
|
storeLocal(frame->context, 1, loadLocal(frame->context, 1, 0), index);
|
2008-02-11 17:21:41 +00:00
|
|
|
frame->set(index, Frame::Object);
|
2008-01-20 18:55:08 +00:00
|
|
|
}
|
|
|
|
|
2007-12-28 00:02:05 +00:00
|
|
|
handleMonitorEvent
|
2008-05-31 22:14:27 +00:00
|
|
|
(t, frame, getThunk(t, acquireMonitorForObjectThunk));
|
2007-12-28 00:02:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
handleExit(MyThread* t, Frame* frame)
|
|
|
|
{
|
|
|
|
handleMonitorEvent
|
2008-05-31 22:14:27 +00:00
|
|
|
(t, frame, getThunk(t, releaseMonitorForObjectThunk));
|
2007-12-28 00:02:05 +00:00
|
|
|
}
|
|
|
|
|
2008-11-16 00:28:45 +00:00
|
|
|
int
|
|
|
|
exceptionIndex(MyThread* t, object code, unsigned jsrIp, unsigned dstIp)
|
|
|
|
{
|
|
|
|
object table = codeExceptionHandlerTable(t, code);
|
|
|
|
unsigned length = exceptionHandlerTableLength(t, table);
|
|
|
|
for (unsigned i = 0; i < length; ++i) {
|
|
|
|
ExceptionHandler* eh = exceptionHandlerTableBody(t, table, i);
|
|
|
|
if (exceptionHandlerCatchType(eh) == 0) {
|
|
|
|
unsigned ip = exceptionHandlerIp(eh);
|
|
|
|
unsigned index;
|
|
|
|
switch (codeBody(t, code, ip++)) {
|
|
|
|
case astore:
|
|
|
|
index = codeBody(t, code, ip++);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case astore_0:
|
|
|
|
index = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case astore_1:
|
|
|
|
index = 1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case astore_2:
|
|
|
|
index = 2;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case astore_3:
|
|
|
|
index = 3;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default: abort(t);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ip == jsrIp) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (codeBody(t, code, ip++)) {
|
|
|
|
case jsr: {
|
|
|
|
uint32_t offset = codeReadInt16(t, code, ip);
|
|
|
|
if ((ip - 3) + offset == dstIp) {
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case jsr_w: {
|
|
|
|
uint32_t offset = codeReadInt32(t, code, ip);
|
|
|
|
if ((ip - 5) + offset == dstIp) {
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
abort(t);
|
|
|
|
}
|
|
|
|
|
2008-11-25 17:34:48 +00:00
|
|
|
bool
|
|
|
|
inTryBlock(MyThread* t, object code, unsigned ip)
|
|
|
|
{
|
|
|
|
object table = codeExceptionHandlerTable(t, code);
|
|
|
|
if (table) {
|
|
|
|
unsigned length = exceptionHandlerTableLength(t, table);
|
|
|
|
for (unsigned i = 0; i < length; ++i) {
|
|
|
|
ExceptionHandler* eh = exceptionHandlerTableBody(t, table, i);
|
|
|
|
if (ip >= exceptionHandlerStart(eh)
|
|
|
|
and ip < exceptionHandlerEnd(eh))
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-03-31 20:15:08 +00:00
|
|
|
bool
|
|
|
|
needsReturnBarrier(MyThread* t, object method)
|
|
|
|
{
|
|
|
|
return (methodFlags(t, method) & ConstructorFlag)
|
|
|
|
and (classFlags(t, methodClass(t, method)) & HasFinalMemberFlag);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2009-04-26 01:51:33 +00:00
|
|
|
returnsNext(MyThread* t, object code, unsigned ip)
|
2009-03-31 20:15:08 +00:00
|
|
|
{
|
2009-04-26 01:51:33 +00:00
|
|
|
switch (codeBody(t, code, ip)) {
|
|
|
|
case return_:
|
|
|
|
case areturn:
|
|
|
|
case ireturn:
|
|
|
|
case freturn:
|
|
|
|
case lreturn:
|
|
|
|
case dreturn:
|
|
|
|
return true;
|
|
|
|
|
|
|
|
case goto_: {
|
|
|
|
uint32_t offset = codeReadInt16(t, code, ++ip);
|
|
|
|
uint32_t newIp = (ip - 3) + offset;
|
|
|
|
assert(t, newIp < codeLength(t, code));
|
|
|
|
|
|
|
|
return returnsNext(t, code, newIp);
|
2009-03-31 20:15:08 +00:00
|
|
|
}
|
2009-04-26 01:51:33 +00:00
|
|
|
|
|
|
|
case goto_w: {
|
|
|
|
uint32_t offset = codeReadInt32(t, code, ++ip);
|
|
|
|
uint32_t newIp = (ip - 5) + offset;
|
|
|
|
assert(t, newIp < codeLength(t, code));
|
|
|
|
|
|
|
|
return returnsNext(t, code, newIp);
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
isTailCall(MyThread* t, object code, unsigned ip, object caller, object callee)
|
|
|
|
{
|
|
|
|
return (((methodFlags(t, caller) & ACC_SYNCHRONIZED) == 0)
|
|
|
|
and (not inTryBlock(t, code, ip - 1))
|
|
|
|
and (not needsReturnBarrier(t, caller))
|
|
|
|
and (methodReturnCode(t, caller) == VoidField
|
|
|
|
or methodReturnCode(t, caller) == methodReturnCode(t, callee))
|
|
|
|
and returnsNext(t, code, ip));
|
2009-03-31 20:15:08 +00:00
|
|
|
}
|
|
|
|
|
2008-09-20 23:42:46 +00:00
|
|
|
void
|
|
|
|
compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
2008-09-25 00:48:32 +00:00
|
|
|
int exceptionHandlerStart = -1);
|
2008-09-20 23:42:46 +00:00
|
|
|
|
|
|
|
void
|
2008-09-25 00:48:32 +00:00
|
|
|
saveStateAndCompile(MyThread* t, Frame* initialFrame, unsigned ip)
|
2008-09-20 23:42:46 +00:00
|
|
|
{
|
2008-09-22 14:28:18 +00:00
|
|
|
Compiler::State* state = initialFrame->c->saveState();
|
2008-11-07 00:39:38 +00:00
|
|
|
compile(t, initialFrame, ip);
|
2008-09-22 14:28:18 +00:00
|
|
|
initialFrame->c->restoreState(state);
|
2008-09-20 23:42:46 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void
|
2008-09-25 00:48:32 +00:00
|
|
|
compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
|
|
|
int exceptionHandlerStart)
|
2007-12-09 22:45:43 +00:00
|
|
|
{
|
2008-02-11 17:21:41 +00:00
|
|
|
uint8_t stackMap
|
|
|
|
[codeMaxStack(t, methodCode(t, initialFrame->context->method))];
|
2008-01-07 16:01:35 +00:00
|
|
|
Frame myFrame(initialFrame, stackMap);
|
2007-12-09 22:45:43 +00:00
|
|
|
Frame* frame = &myFrame;
|
|
|
|
Compiler* c = frame->c;
|
2007-12-31 22:40:56 +00:00
|
|
|
Context* context = frame->context;
|
2007-09-25 23:53:11 +00:00
|
|
|
|
2007-12-31 22:40:56 +00:00
|
|
|
object code = methodCode(t, context->method);
|
2007-12-09 22:45:43 +00:00
|
|
|
PROTECT(t, code);
|
|
|
|
|
|
|
|
while (ip < codeLength(t, code)) {
|
2008-01-07 14:51:07 +00:00
|
|
|
if (context->visitTable[ip] ++) {
|
2007-12-09 22:45:43 +00:00
|
|
|
// we've already visited this part of the code
|
2008-04-20 05:23:08 +00:00
|
|
|
frame->visitLogicalIp(ip);
|
2007-12-09 22:45:43 +00:00
|
|
|
return;
|
2007-09-30 04:07:22 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
frame->startLogicalIp(ip);
|
2007-10-17 01:21:35 +00:00
|
|
|
|
2008-11-08 23:21:30 +00:00
|
|
|
if (exceptionHandlerStart >= 0) {
|
2008-09-25 00:48:32 +00:00
|
|
|
c->initLocalsFromLogicalIp(exceptionHandlerStart);
|
|
|
|
|
|
|
|
exceptionHandlerStart = -1;
|
2008-04-19 07:03:59 +00:00
|
|
|
|
|
|
|
frame->pushObject();
|
2008-04-09 19:08:13 +00:00
|
|
|
|
2008-04-17 22:07:32 +00:00
|
|
|
c->call
|
2008-05-31 22:14:27 +00:00
|
|
|
(c->constant(getThunk(t, gcIfNecessaryThunk)),
|
|
|
|
0,
|
2009-03-31 20:15:08 +00:00
|
|
|
frame->trace(0, 0),
|
2008-04-17 22:07:32 +00:00
|
|
|
0,
|
2009-04-07 00:34:12 +00:00
|
|
|
1, c->register_(t->arch->thread()));
|
2008-04-09 19:08:13 +00:00
|
|
|
}
|
|
|
|
|
2008-01-07 14:51:07 +00:00
|
|
|
// fprintf(stderr, "ip: %d map: %ld\n", ip, *(frame->map));
|
|
|
|
|
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: {
|
2008-04-19 20:41:31 +00:00
|
|
|
Compiler::Operand* index = frame->popInt();
|
|
|
|
Compiler::Operand* array = frame->popObject();
|
2007-09-28 23:41:03 +00:00
|
|
|
|
2008-11-25 17:34:48 +00:00
|
|
|
if (inTryBlock(t, code, ip - 1)) {
|
|
|
|
c->saveLocals();
|
|
|
|
}
|
|
|
|
|
2008-01-08 17:10:24 +00:00
|
|
|
if (CheckArrayBounds) {
|
2008-11-23 23:58:01 +00:00
|
|
|
c->checkBounds(array, ArrayLength, index, aioobThunk(t));
|
2008-01-08 17:10:24 +00:00
|
|
|
}
|
2007-09-25 23:53:11 +00:00
|
|
|
|
2008-06-10 14:49:13 +00:00
|
|
|
switch (instruction) {
|
|
|
|
case aaload:
|
|
|
|
frame->pushObject
|
|
|
|
(c->load
|
2009-03-06 17:56:11 +00:00
|
|
|
(BytesPerWord, BytesPerWord,
|
|
|
|
c->memory(array, ArrayBody, index, BytesPerWord), BytesPerWord));
|
2008-06-10 14:49:13 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case faload:
|
|
|
|
case iaload:
|
2008-12-21 21:41:56 +00:00
|
|
|
frame->pushInt
|
2009-03-06 17:56:11 +00:00
|
|
|
(c->load(4, 4, c->memory(array, ArrayBody, index, 4), BytesPerWord));
|
2008-06-10 14:49:13 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case baload:
|
2008-12-21 21:41:56 +00:00
|
|
|
frame->pushInt
|
2009-03-06 17:56:11 +00:00
|
|
|
(c->load(1, 1, c->memory(array, ArrayBody, index, 1), BytesPerWord));
|
2008-06-10 14:49:13 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case caload:
|
2008-12-21 21:41:56 +00:00
|
|
|
frame->pushInt
|
2009-03-06 17:56:11 +00:00
|
|
|
(c->loadz(2, 2, c->memory(array, ArrayBody, index, 2),
|
|
|
|
BytesPerWord));
|
2008-06-10 14:49:13 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case daload:
|
|
|
|
case laload:
|
2008-12-21 21:41:56 +00:00
|
|
|
frame->pushLong
|
2009-03-06 17:56:11 +00:00
|
|
|
(c->load(8, 8, c->memory(array, ArrayBody, index, 8), 8));
|
2008-06-10 14:49:13 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case saload:
|
2008-12-21 21:41:56 +00:00
|
|
|
frame->pushInt
|
2009-03-06 17:56:11 +00:00
|
|
|
(c->load(2, 2, c->memory(array, ArrayBody, index, 2), BytesPerWord));
|
2008-06-10 14:49:13 +00:00
|
|
|
break;
|
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 aastore:
|
|
|
|
case bastore:
|
|
|
|
case castore:
|
|
|
|
case dastore:
|
|
|
|
case fastore:
|
|
|
|
case iastore:
|
|
|
|
case lastore:
|
|
|
|
case sastore: {
|
2008-04-19 22:13:57 +00:00
|
|
|
Compiler::Operand* value;
|
2007-12-09 22:45:43 +00:00
|
|
|
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
|
|
|
|
2008-04-19 22:13:57 +00:00
|
|
|
Compiler::Operand* index = frame->popInt();
|
|
|
|
Compiler::Operand* array = frame->popObject();
|
2007-09-28 23:41:03 +00:00
|
|
|
|
2008-11-25 17:34:48 +00:00
|
|
|
if (inTryBlock(t, code, ip - 1)) {
|
|
|
|
c->saveLocals();
|
|
|
|
}
|
|
|
|
|
2008-01-08 17:10:24 +00:00
|
|
|
if (CheckArrayBounds) {
|
2008-11-23 23:58:01 +00:00
|
|
|
c->checkBounds(array, ArrayLength, index, aioobThunk(t));
|
2008-01-08 17:10:24 +00:00
|
|
|
}
|
2007-09-29 20:24:14 +00:00
|
|
|
|
2008-06-10 14:49:13 +00:00
|
|
|
switch (instruction) {
|
|
|
|
case aastore: {
|
|
|
|
c->call
|
|
|
|
(c->constant(getThunk(t, setMaybeNullThunk)),
|
|
|
|
0,
|
2009-03-31 20:15:08 +00:00
|
|
|
frame->trace(0, 0),
|
2008-06-10 14:49:13 +00:00
|
|
|
0,
|
2009-04-07 00:34:12 +00:00
|
|
|
4, c->register_(t->arch->thread()), array,
|
2008-06-10 14:49:13 +00:00
|
|
|
c->add(4, c->constant(ArrayBody),
|
|
|
|
c->shl(4, c->constant(log(BytesPerWord)), index)),
|
|
|
|
value);
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case fastore:
|
|
|
|
case iastore:
|
2009-02-28 23:17:24 +00:00
|
|
|
c->store
|
|
|
|
(BytesPerWord, value, 4, c->memory(array, ArrayBody, index, 4));
|
2008-06-10 14:49:13 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case bastore:
|
2009-02-28 23:17:24 +00:00
|
|
|
c->store
|
|
|
|
(BytesPerWord, value, 1, c->memory(array, ArrayBody, index, 1));
|
2008-06-10 14:49:13 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case castore:
|
|
|
|
case sastore:
|
2009-02-28 23:17:24 +00:00
|
|
|
c->store
|
|
|
|
(BytesPerWord, value, 2, c->memory(array, ArrayBody, index, 2));
|
2008-06-10 14:49:13 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case dastore:
|
|
|
|
case lastore:
|
2009-02-28 23:17:24 +00:00
|
|
|
c->store(8, value, 8, c->memory(array, ArrayBody, index, 8));
|
2008-06-10 14:49:13 +00:00
|
|
|
break;
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
|
|
|
} 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
|
|
|
|
2008-04-26 20:56:03 +00:00
|
|
|
Compiler::Operand* length = frame->popInt();
|
2007-10-08 23:13:55 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
frame->pushObject
|
|
|
|
(c->call
|
2008-05-31 22:14:27 +00:00
|
|
|
(c->constant(getThunk(t, makeBlankObjectArrayThunk)),
|
|
|
|
0,
|
2009-03-31 20:15:08 +00:00
|
|
|
frame->trace(0, 0),
|
2008-02-11 17:21:41 +00:00
|
|
|
BytesPerWord,
|
2009-04-07 00:34:12 +00:00
|
|
|
3, c->register_(t->arch->thread()), frame->append(class_), length));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-09-28 23:41:03 +00:00
|
|
|
|
2007-12-12 22:19:13 +00:00
|
|
|
case areturn: {
|
2009-04-19 22:36:11 +00:00
|
|
|
Compiler::Operand* value = frame->popObject();
|
2009-04-26 01:51:33 +00:00
|
|
|
handleExit(t, frame);
|
|
|
|
c->return_(BytesPerWord, value);
|
2007-12-12 22:19:13 +00:00
|
|
|
} return;
|
2007-09-28 23:41:03 +00:00
|
|
|
|
2007-12-12 22:19:13 +00:00
|
|
|
case arraylength: {
|
2008-02-11 17:21:41 +00:00
|
|
|
frame->pushInt
|
|
|
|
(c->load
|
2009-03-06 17:56:11 +00:00
|
|
|
(BytesPerWord, BytesPerWord,
|
|
|
|
c->memory(frame->popObject(), ArrayLength, 0, 1), BytesPerWord));
|
2007-12-12 22:19:13 +00:00
|
|
|
} break;
|
2007-10-04 03:19:39 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case astore:
|
2007-12-26 23:59:55 +00:00
|
|
|
frame->storeObjectOrAddress(codeBody(t, code, ip++));
|
2007-12-09 22:45:43 +00:00
|
|
|
break;
|
2007-10-10 21:34:04 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case astore_0:
|
2007-12-27 16:02:03 +00:00
|
|
|
frame->storeObjectOrAddress(0);
|
2007-12-09 22:45:43 +00:00
|
|
|
break;
|
2007-10-17 17:22:09 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case astore_1:
|
2007-12-27 16:02:03 +00:00
|
|
|
frame->storeObjectOrAddress(1);
|
2007-12-09 22:45:43 +00:00
|
|
|
break;
|
2007-10-10 21:34:04 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case astore_2:
|
2007-12-27 16:02:03 +00:00
|
|
|
frame->storeObjectOrAddress(2);
|
2007-12-09 22:45:43 +00:00
|
|
|
break;
|
2007-10-10 21:34:04 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case astore_3:
|
2007-12-27 16:02:03 +00:00
|
|
|
frame->storeObjectOrAddress(3);
|
2007-12-09 22:45:43 +00:00
|
|
|
break;
|
2007-10-10 21:34:04 +00:00
|
|
|
|
2007-12-12 22:19:13 +00:00
|
|
|
case athrow: {
|
2009-03-18 22:24:13 +00:00
|
|
|
Compiler::Operand* target = frame->popObject();
|
2008-02-11 17:21:41 +00:00
|
|
|
c->call
|
2008-05-31 22:14:27 +00:00
|
|
|
(c->constant(getThunk(t, throw_Thunk)),
|
|
|
|
Compiler::NoReturn,
|
2009-03-31 20:15:08 +00:00
|
|
|
frame->trace(0, 0),
|
2008-02-11 17:21:41 +00:00
|
|
|
0,
|
2009-04-07 00:34:12 +00:00
|
|
|
2, c->register_(t->arch->thread()), target);
|
2007-12-12 22:19:13 +00:00
|
|
|
} return;
|
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
|
|
|
|
2008-11-02 22:25:51 +00:00
|
|
|
Compiler::Operand* instance = c->peek(1, 0);
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
c->call
|
2008-05-31 22:14:27 +00:00
|
|
|
(c->constant(getThunk(t, checkCastThunk)),
|
|
|
|
0,
|
2009-03-31 20:15:08 +00:00
|
|
|
frame->trace(0, 0),
|
2008-02-11 17:21:41 +00:00
|
|
|
0,
|
2009-04-07 00:34:12 +00:00
|
|
|
3, c->register_(t->arch->thread()), frame->append(class_), instance);
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-10-10 21:34:04 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case d2f: {
|
2008-02-11 17:21:41 +00:00
|
|
|
frame->pushInt
|
|
|
|
(c->call
|
2008-05-31 22:14:27 +00:00
|
|
|
(c->constant(getThunk(t, doubleToFloatThunk)),
|
|
|
|
0, 0, 4, 2,
|
2008-05-23 00:08:41 +00:00
|
|
|
static_cast<Compiler::Operand*>(0), frame->popLong()));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case d2i: {
|
2008-02-11 17:21:41 +00:00
|
|
|
frame->pushInt
|
|
|
|
(c->call
|
2008-05-31 22:14:27 +00:00
|
|
|
(c->constant(getThunk(t, doubleToIntThunk)),
|
|
|
|
0, 0, 4, 2,
|
2008-05-23 00:08:41 +00:00
|
|
|
static_cast<Compiler::Operand*>(0), frame->popLong()));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-09-24 01:39:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case d2l: {
|
2008-02-11 17:21:41 +00:00
|
|
|
frame->pushLong
|
|
|
|
(c->call
|
2008-05-31 22:14:27 +00:00
|
|
|
(c->constant(getThunk(t, doubleToLongThunk)),
|
|
|
|
0, 0, 8, 2,
|
2008-05-23 00:08:41 +00:00
|
|
|
static_cast<Compiler::Operand*>(0), frame->popLong()));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-10-10 21:34:04 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case dadd: {
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* a = frame->popLong();
|
|
|
|
Compiler::Operand* b = frame->popLong();
|
2007-12-23 00:00:35 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
frame->pushLong
|
|
|
|
(c->call
|
2008-05-31 22:14:27 +00:00
|
|
|
(c->constant(getThunk(t, addDoubleThunk)),
|
|
|
|
0, 0, 8, 4,
|
2008-05-14 23:22:44 +00:00
|
|
|
static_cast<Compiler::Operand*>(0), a,
|
|
|
|
static_cast<Compiler::Operand*>(0), b));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-10-10 21:34:04 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case dcmpg: {
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* a = frame->popLong();
|
|
|
|
Compiler::Operand* b = frame->popLong();
|
2007-12-23 00:00:35 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
frame->pushInt
|
|
|
|
(c->call
|
2008-05-31 22:14:27 +00:00
|
|
|
(c->constant(getThunk(t, compareDoublesGThunk)),
|
|
|
|
0, 0, 4, 4,
|
2008-05-14 23:22:44 +00:00
|
|
|
static_cast<Compiler::Operand*>(0), a,
|
|
|
|
static_cast<Compiler::Operand*>(0), b));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-10-10 21:34:04 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case dcmpl: {
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* a = frame->popLong();
|
|
|
|
Compiler::Operand* b = frame->popLong();
|
2007-12-23 00:00:35 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
frame->pushInt
|
|
|
|
(c->call
|
2008-05-31 22:14:27 +00:00
|
|
|
(c->constant(getThunk(t, compareDoublesLThunk)),
|
|
|
|
0, 0, 4, 4,
|
2008-05-14 23:22:44 +00:00
|
|
|
static_cast<Compiler::Operand*>(0), a,
|
|
|
|
static_cast<Compiler::Operand*>(0), b));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case dconst_0:
|
2007-12-26 16:56:14 +00:00
|
|
|
frame->pushLong(c->constant(doubleToBits(0.0)));
|
2007-12-09 22:45:43 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case dconst_1:
|
2007-12-26 16:56:14 +00:00
|
|
|
frame->pushLong(c->constant(doubleToBits(1.0)));
|
2007-12-09 22:45:43 +00:00
|
|
|
break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case ddiv: {
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* a = frame->popLong();
|
|
|
|
Compiler::Operand* b = frame->popLong();
|
2007-12-23 00:00:35 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
frame->pushLong
|
|
|
|
(c->call
|
2008-05-31 22:14:27 +00:00
|
|
|
(c->constant(getThunk(t, divideDoubleThunk)),
|
|
|
|
0, 0, 8, 4,
|
2008-05-14 23:22:44 +00:00
|
|
|
static_cast<Compiler::Operand*>(0), a,
|
|
|
|
static_cast<Compiler::Operand*>(0), b));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case dmul: {
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* a = frame->popLong();
|
|
|
|
Compiler::Operand* b = frame->popLong();
|
|
|
|
|
|
|
|
frame->pushLong
|
|
|
|
(c->call
|
2008-05-31 22:14:27 +00:00
|
|
|
(c->constant(getThunk(t, multiplyDoubleThunk)),
|
|
|
|
0, 0, 8, 4,
|
2008-05-14 23:22:44 +00:00
|
|
|
static_cast<Compiler::Operand*>(0), a,
|
|
|
|
static_cast<Compiler::Operand*>(0), b));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-10-16 17:21:26 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case dneg: {
|
2008-02-11 17:21:41 +00:00
|
|
|
frame->pushLong
|
|
|
|
(c->call
|
2008-05-31 22:14:27 +00:00
|
|
|
(c->constant(getThunk(t, negateDoubleThunk)),
|
|
|
|
0, 0, 8, 2,
|
2008-05-14 23:22:44 +00:00
|
|
|
static_cast<Compiler::Operand*>(0), frame->popLong()));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case vm::drem: {
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* a = frame->popLong();
|
|
|
|
Compiler::Operand* b = frame->popLong();
|
2007-12-23 00:00:35 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
frame->pushLong
|
|
|
|
(c->call
|
2008-05-31 22:14:27 +00:00
|
|
|
(c->constant(getThunk(t, moduloDoubleThunk)),
|
|
|
|
0, 0, 8, 4,
|
2008-05-14 23:22:44 +00:00
|
|
|
static_cast<Compiler::Operand*>(0), a,
|
|
|
|
static_cast<Compiler::Operand*>(0), b));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case dsub: {
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* a = frame->popLong();
|
|
|
|
Compiler::Operand* b = frame->popLong();
|
2007-12-23 00:00:35 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
frame->pushLong
|
|
|
|
(c->call
|
2008-05-31 22:14:27 +00:00
|
|
|
(c->constant(getThunk(t, subtractDoubleThunk)),
|
|
|
|
0, 0, 8, 4,
|
2008-05-14 23:22:44 +00:00
|
|
|
static_cast<Compiler::Operand*>(0), a,
|
|
|
|
static_cast<Compiler::Operand*>(0), b));
|
2007-12-09 22:45:43 +00:00
|
|
|
} 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: {
|
2008-02-11 17:21:41 +00:00
|
|
|
frame->pushLong
|
|
|
|
(c->call
|
2008-05-31 22:14:27 +00:00
|
|
|
(c->constant(getThunk(t, floatToDoubleThunk)),
|
|
|
|
0, 0, 8, 1, frame->popInt()));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case f2i: {
|
2008-02-11 17:21:41 +00:00
|
|
|
frame->pushInt
|
|
|
|
(c->call
|
2008-05-31 22:14:27 +00:00
|
|
|
(c->constant(getThunk(t, floatToIntThunk)),
|
|
|
|
0, 0, 4, 1, frame->popInt()));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-10-13 21:48:40 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case f2l: {
|
2008-02-11 17:21:41 +00:00
|
|
|
frame->pushLong
|
|
|
|
(c->call
|
2008-05-31 22:14:27 +00:00
|
|
|
(c->constant(getThunk(t, floatToLongThunk)),
|
|
|
|
0, 0, 8, 1, frame->popInt()));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case fadd: {
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* a = frame->popInt();
|
|
|
|
Compiler::Operand* b = frame->popInt();
|
2007-12-23 00:00:35 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
frame->pushInt
|
|
|
|
(c->call
|
2008-05-31 22:14:27 +00:00
|
|
|
(c->constant(getThunk(t, addFloatThunk)),
|
|
|
|
0, 0, 4, 2, a, b));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case fcmpg: {
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* a = frame->popInt();
|
|
|
|
Compiler::Operand* b = frame->popInt();
|
2007-12-23 00:00:35 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
frame->pushInt
|
|
|
|
(c->call
|
2008-05-31 22:14:27 +00:00
|
|
|
(c->constant(getThunk(t, compareFloatsGThunk)),
|
|
|
|
0, 0, 4, 2, a, b));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case fcmpl: {
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* a = frame->popInt();
|
|
|
|
Compiler::Operand* b = frame->popInt();
|
2007-12-23 00:00:35 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
frame->pushInt
|
|
|
|
(c->call
|
2008-05-31 22:14:27 +00:00
|
|
|
(c->constant(getThunk(t, compareFloatsLThunk)),
|
|
|
|
0, 0, 4, 2, a, b));
|
2007-12-09 22:45:43 +00:00
|
|
|
} 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: {
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* a = frame->popInt();
|
|
|
|
Compiler::Operand* b = frame->popInt();
|
2007-12-23 00:00:35 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
frame->pushInt
|
|
|
|
(c->call
|
2008-05-31 22:14:27 +00:00
|
|
|
(c->constant(getThunk(t, divideFloatThunk)),
|
|
|
|
0, 0, 4, 2, a, b));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case fmul: {
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* a = frame->popInt();
|
|
|
|
Compiler::Operand* b = frame->popInt();
|
2007-12-23 00:00:35 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
frame->pushInt
|
|
|
|
(c->call
|
2008-05-31 22:14:27 +00:00
|
|
|
(c->constant(getThunk(t, multiplyFloatThunk)),
|
|
|
|
0, 0, 4, 2, a, b));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case fneg: {
|
2008-02-11 17:21:41 +00:00
|
|
|
frame->pushInt
|
|
|
|
(c->call
|
2008-05-31 22:14:27 +00:00
|
|
|
(c->constant(getThunk(t, negateFloatThunk)),
|
|
|
|
0, 0, 4, 1, frame->popInt()));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case vm::frem: {
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* a = frame->popInt();
|
|
|
|
Compiler::Operand* b = frame->popInt();
|
2007-12-23 00:00:35 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
frame->pushInt
|
|
|
|
(c->call
|
2008-05-31 22:14:27 +00:00
|
|
|
(c->constant(getThunk(t, moduloFloatThunk)),
|
|
|
|
0, 0, 4, 2, a, b));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case fsub: {
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* a = frame->popInt();
|
|
|
|
Compiler::Operand* b = frame->popInt();
|
2007-12-23 00:00:35 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
frame->pushInt
|
|
|
|
(c->call
|
2008-05-31 22:14:27 +00:00
|
|
|
(c->constant(getThunk(t, subtractFloatThunk)),
|
|
|
|
0, 0, 4, 2, a, b));
|
2007-12-09 22:45:43 +00:00
|
|
|
} 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
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* table;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
if (instruction == getstatic) {
|
2009-01-10 19:25:52 +00:00
|
|
|
assert(t, fieldFlags(t, field) & ACC_STATIC);
|
|
|
|
|
2008-11-30 04:58:09 +00:00
|
|
|
if (fieldClass(t, field) != methodClass(t, context->method)
|
2008-12-02 02:38:00 +00:00
|
|
|
and classNeedsInit(t, fieldClass(t, field)))
|
2008-04-23 22:56:02 +00:00
|
|
|
{
|
2008-03-16 19:38:43 +00:00
|
|
|
c->call
|
2008-05-31 22:14:27 +00:00
|
|
|
(c->constant(getThunk(t, tryInitClassThunk)),
|
|
|
|
0,
|
2009-03-31 20:15:08 +00:00
|
|
|
frame->trace(0, 0),
|
2008-03-16 19:38:43 +00:00
|
|
|
0,
|
2009-04-07 00:34:12 +00:00
|
|
|
2, c->register_(t->arch->thread()),
|
|
|
|
frame->append(fieldClass(t, field)));
|
2008-04-23 22:56:02 +00:00
|
|
|
}
|
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 {
|
2009-01-10 19:25:52 +00:00
|
|
|
assert(t, (fieldFlags(t, field) & ACC_STATIC) == 0);
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
table = frame->popObject();
|
2008-11-25 17:34:48 +00:00
|
|
|
|
|
|
|
if (inTryBlock(t, code, ip - 3)) {
|
|
|
|
c->saveLocals();
|
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2009-03-04 01:02:11 +00:00
|
|
|
Compiler::Operand* fieldOperand = 0;
|
|
|
|
|
|
|
|
if ((fieldFlags(t, field) & ACC_VOLATILE)
|
|
|
|
and BytesPerWord == 4
|
|
|
|
and (fieldCode(t, field) == DoubleField
|
|
|
|
or fieldCode(t, field) == LongField))
|
|
|
|
{
|
|
|
|
fieldOperand = frame->append(field);
|
|
|
|
|
|
|
|
c->call
|
|
|
|
(c->constant(getThunk(t, acquireMonitorForObjectThunk)),
|
2009-04-07 00:34:12 +00:00
|
|
|
0, frame->trace(0, 0), 0, 2, c->register_(t->arch->thread()),
|
|
|
|
fieldOperand);
|
2009-03-04 01:02:11 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
switch (fieldCode(t, field)) {
|
|
|
|
case ByteField:
|
|
|
|
case BooleanField:
|
2008-02-11 17:21:41 +00:00
|
|
|
frame->pushInt
|
2009-03-06 17:56:11 +00:00
|
|
|
(c->load(1, 1, c->memory(table, fieldOffset(t, field), 0, 1),
|
|
|
|
BytesPerWord));
|
2007-12-09 22:45:43 +00:00
|
|
|
break;
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case CharField:
|
2008-02-11 17:21:41 +00:00
|
|
|
frame->pushInt
|
2009-03-06 17:56:11 +00:00
|
|
|
(c->loadz(2, 2, c->memory(table, fieldOffset(t, field), 0, 1),
|
|
|
|
BytesPerWord));
|
2007-12-09 22:45:43 +00:00
|
|
|
break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case ShortField:
|
2008-02-11 17:21:41 +00:00
|
|
|
frame->pushInt
|
2009-03-06 17:56:11 +00:00
|
|
|
(c->load(2, 2, c->memory(table, fieldOffset(t, field), 0, 1),
|
|
|
|
BytesPerWord));
|
2007-12-09 22:45:43 +00:00
|
|
|
break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case FloatField:
|
|
|
|
case IntField:
|
2008-02-11 17:21:41 +00:00
|
|
|
frame->pushInt
|
2009-03-06 17:56:11 +00:00
|
|
|
(c->load(4, 4, c->memory(table, fieldOffset(t, field), 0, 1),
|
|
|
|
BytesPerWord));
|
2007-12-09 22:45:43 +00:00
|
|
|
break;
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case DoubleField:
|
|
|
|
case LongField:
|
2007-12-30 22:24:48 +00:00
|
|
|
frame->pushLong
|
2009-03-06 17:56:11 +00:00
|
|
|
(c->load(8, 8, c->memory(table, fieldOffset(t, field), 0, 1), 8));
|
2007-12-09 22:45:43 +00:00
|
|
|
break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case ObjectField:
|
2007-12-30 22:24:48 +00:00
|
|
|
frame->pushObject
|
2008-02-12 02:06:12 +00:00
|
|
|
(c->load
|
2009-03-06 17:56:11 +00:00
|
|
|
(BytesPerWord, BytesPerWord,
|
|
|
|
c->memory(table, fieldOffset(t, field), 0, 1), BytesPerWord));
|
2007-12-09 22:45:43 +00:00
|
|
|
break;
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
default:
|
|
|
|
abort(t);
|
|
|
|
}
|
2009-03-03 03:18:15 +00:00
|
|
|
|
|
|
|
if (fieldFlags(t, field) & ACC_VOLATILE) {
|
2009-03-04 01:02:11 +00:00
|
|
|
if (BytesPerWord == 4
|
|
|
|
and (fieldCode(t, field) == DoubleField
|
|
|
|
or fieldCode(t, field) == LongField))
|
|
|
|
{
|
|
|
|
c->call
|
|
|
|
(c->constant(getThunk(t, releaseMonitorForObjectThunk)),
|
2009-04-07 00:34:12 +00:00
|
|
|
0, frame->trace(0, 0), 0, 2, c->register_(t->arch->thread()),
|
|
|
|
fieldOperand);
|
2009-03-04 01:02:11 +00:00
|
|
|
} else {
|
|
|
|
c->loadBarrier();
|
|
|
|
}
|
2009-03-03 03:18:15 +00:00
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case goto_: {
|
2008-11-11 15:20:49 +00:00
|
|
|
uint32_t offset = codeReadInt16(t, code, ip);
|
|
|
|
uint32_t newIp = (ip - 3) + offset;
|
2007-12-09 22:45:43 +00:00
|
|
|
assert(t, newIp < codeLength(t, code));
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-16 00:24:15 +00:00
|
|
|
c->jmp(frame->machineIp(newIp));
|
2007-12-09 22:45:43 +00:00
|
|
|
ip = newIp;
|
|
|
|
} break;
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case goto_w: {
|
2008-11-11 15:20:49 +00:00
|
|
|
uint32_t offset = codeReadInt32(t, code, ip);
|
|
|
|
uint32_t newIp = (ip - 5) + offset;
|
2007-12-09 22:45:43 +00:00
|
|
|
assert(t, newIp < codeLength(t, code));
|
2007-09-28 14:45:26 +00:00
|
|
|
|
2007-12-16 00:24:15 +00:00
|
|
|
c->jmp(frame->machineIp(newIp));
|
2007-12-09 22:45:43 +00:00
|
|
|
ip = newIp;
|
|
|
|
} break;
|
2007-09-28 14:45:26 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case i2b: {
|
2009-03-06 17:56:11 +00:00
|
|
|
frame->pushInt(c->load(BytesPerWord, 1, frame->popInt(), BytesPerWord));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-09-28 14:45:26 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case i2c: {
|
2009-03-06 17:56:11 +00:00
|
|
|
frame->pushInt(c->loadz(BytesPerWord, 2, frame->popInt(), BytesPerWord));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-10-13 21:48:40 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case i2d: {
|
2008-02-11 17:21:41 +00:00
|
|
|
frame->pushLong
|
|
|
|
(c->call
|
2008-05-31 22:14:27 +00:00
|
|
|
(c->constant(getThunk(t, intToDoubleThunk)),
|
|
|
|
0, 0, 8, 1, frame->popInt()));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-09-28 14:45:26 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case i2f: {
|
2008-02-11 17:21:41 +00:00
|
|
|
frame->pushInt
|
|
|
|
(c->call
|
2008-05-31 22:14:27 +00:00
|
|
|
(c->constant(getThunk(t, intToFloatThunk)),
|
|
|
|
0, 0, 4, 1, frame->popInt()));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-09-28 14:45:26 +00:00
|
|
|
|
2007-12-26 23:59:55 +00:00
|
|
|
case i2l:
|
2009-03-06 17:56:11 +00:00
|
|
|
frame->pushLong(c->load(BytesPerWord, 4, frame->popInt(), 8));
|
2007-12-26 23:59:55 +00:00
|
|
|
break;
|
2007-10-04 03:19:39 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case i2s: {
|
2009-03-06 17:56:11 +00:00
|
|
|
frame->pushInt(c->load(BytesPerWord, 2, frame->popInt(), BytesPerWord));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case iadd: {
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* a = frame->popInt();
|
|
|
|
Compiler::Operand* b = frame->popInt();
|
2008-02-12 02:06:12 +00:00
|
|
|
frame->pushInt(c->add(4, a, b));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case iand: {
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* a = frame->popInt();
|
|
|
|
Compiler::Operand* b = frame->popInt();
|
2008-02-12 02:06:12 +00:00
|
|
|
frame->pushInt(c->and_(4, a, b));
|
2007-12-09 22:45:43 +00:00
|
|
|
} 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: {
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* a = frame->popInt();
|
|
|
|
Compiler::Operand* b = frame->popInt();
|
2008-02-12 02:06:12 +00:00
|
|
|
frame->pushInt(c->div(4, a, b));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-10-13 21:48:40 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case if_acmpeq:
|
|
|
|
case if_acmpne: {
|
2008-11-11 15:20:49 +00:00
|
|
|
uint32_t offset = codeReadInt16(t, code, ip);
|
|
|
|
uint32_t newIp = (ip - 3) + offset;
|
2007-12-09 22:45:43 +00:00
|
|
|
assert(t, newIp < codeLength(t, code));
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* a = frame->popObject();
|
|
|
|
Compiler::Operand* b = frame->popObject();
|
|
|
|
Compiler::Operand* target = frame->machineIp(newIp);
|
2007-09-28 14:45:26 +00:00
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
c->cmp(BytesPerWord, a, b);
|
2007-12-09 22:45:43 +00:00
|
|
|
if (instruction == if_acmpeq) {
|
|
|
|
c->je(target);
|
|
|
|
} else {
|
|
|
|
c->jne(target);
|
|
|
|
}
|
2008-09-13 21:09:26 +00:00
|
|
|
|
2008-09-20 23:42:46 +00:00
|
|
|
saveStateAndCompile(t, frame, newIp);
|
2007-12-09 22:45:43 +00:00
|
|
|
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: {
|
2008-11-11 15:20:49 +00:00
|
|
|
uint32_t offset = codeReadInt16(t, code, ip);
|
|
|
|
uint32_t newIp = (ip - 3) + offset;
|
2007-12-09 22:45:43 +00:00
|
|
|
assert(t, newIp < codeLength(t, code));
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* a = frame->popInt();
|
|
|
|
Compiler::Operand* b = frame->popInt();
|
|
|
|
Compiler::Operand* target = frame->machineIp(newIp);
|
2007-10-13 21:48:40 +00:00
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
c->cmp(4, a, b);
|
2007-12-09 22:45:43 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2008-09-20 23:42:46 +00:00
|
|
|
saveStateAndCompile(t, frame, newIp);
|
2007-12-09 22:45:43 +00:00
|
|
|
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: {
|
2008-11-11 15:20:49 +00:00
|
|
|
uint32_t offset = codeReadInt16(t, code, ip);
|
|
|
|
uint32_t newIp = (ip - 3) + offset;
|
2007-12-09 22:45:43 +00:00
|
|
|
assert(t, newIp < codeLength(t, code));
|
2007-10-03 00:22:48 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* a = frame->popInt();
|
|
|
|
Compiler::Operand* target = frame->machineIp(newIp);
|
2007-10-16 17:21:26 +00:00
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
c->cmp(4, c->constant(0), a);
|
2007-12-09 22:45:43 +00:00
|
|
|
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;
|
|
|
|
}
|
2008-06-10 14:49:13 +00:00
|
|
|
|
2008-09-20 23:42:46 +00:00
|
|
|
saveStateAndCompile(t, frame, newIp);
|
2007-12-09 22:45:43 +00:00
|
|
|
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: {
|
2008-11-11 15:20:49 +00:00
|
|
|
uint32_t offset = codeReadInt16(t, code, ip);
|
|
|
|
uint32_t newIp = (ip - 3) + offset;
|
2007-12-09 22:45:43 +00:00
|
|
|
assert(t, newIp < codeLength(t, code));
|
2007-10-16 17:21:26 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* a = frame->popObject();
|
|
|
|
Compiler::Operand* target = frame->machineIp(newIp);
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
c->cmp(BytesPerWord, c->constant(0), a);
|
2007-12-09 22:45:43 +00:00
|
|
|
if (instruction == ifnull) {
|
|
|
|
c->je(target);
|
|
|
|
} else {
|
|
|
|
c->jne(target);
|
|
|
|
}
|
2008-09-13 21:09:26 +00:00
|
|
|
|
2008-09-20 23:42:46 +00:00
|
|
|
saveStateAndCompile(t, frame, newIp);
|
2007-12-09 22:45:43 +00:00
|
|
|
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
|
|
|
|
2009-05-15 02:08:01 +00:00
|
|
|
storeLocal
|
|
|
|
(context, 1,
|
|
|
|
c->add(4, c->constant(count), loadLocal(context, 1, index)),
|
2009-05-03 20:57:11 +00:00
|
|
|
index);
|
2007-12-09 22:45:43 +00:00
|
|
|
} 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: {
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* a = frame->popInt();
|
|
|
|
Compiler::Operand* b = frame->popInt();
|
2008-02-12 02:06:12 +00:00
|
|
|
frame->pushInt(c->mul(4, a, b));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-26 19:19:45 +00:00
|
|
|
case ineg: {
|
2008-02-12 02:06:12 +00:00
|
|
|
frame->pushInt(c->neg(4, frame->popInt()));
|
2007-12-26 19:19:45 +00:00
|
|
|
} break;
|
|
|
|
|
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
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
frame->pushInt
|
|
|
|
(c->call
|
2009-02-28 21:20:43 +00:00
|
|
|
(c->constant(getThunk(t, instanceOf64Thunk)),
|
2008-05-31 22:14:27 +00:00
|
|
|
0, 0, 4,
|
2009-04-07 00:34:12 +00:00
|
|
|
3, c->register_(t->arch->thread()), frame->append(class_),
|
|
|
|
frame->popObject()));
|
2007-12-09 22:45:43 +00:00
|
|
|
} 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
|
|
|
|
2008-07-12 20:52:14 +00:00
|
|
|
assert(t, (methodFlags(t, target) & ACC_STATIC) == 0);
|
|
|
|
|
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
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
unsigned rSize = resultSize(t, methodReturnCode(t, target));
|
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
Compiler::Operand* result = c->stackCall
|
2008-02-11 17:21:41 +00:00
|
|
|
(c->call
|
2007-12-16 23:52:38 +00:00
|
|
|
(c->constant
|
2008-05-31 22:14:27 +00:00
|
|
|
(getThunk(t, findInterfaceMethodFromInstanceThunk)),
|
|
|
|
0,
|
2009-03-31 20:15:08 +00:00
|
|
|
frame->trace(0, 0),
|
2008-02-11 17:21:41 +00:00
|
|
|
BytesPerWord,
|
2009-04-07 00:34:12 +00:00
|
|
|
3, c->register_(t->arch->thread()), frame->append(target),
|
2008-11-02 22:25:51 +00:00
|
|
|
c->peek(1, instance)),
|
2008-02-11 17:21:41 +00:00
|
|
|
0,
|
2009-04-05 21:42:10 +00:00
|
|
|
frame->trace(0, 0),
|
2008-02-12 02:06:12 +00:00
|
|
|
rSize,
|
2008-07-05 20:21:13 +00:00
|
|
|
parameterFootprint);
|
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
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
if (rSize) {
|
2008-03-11 16:57:35 +00:00
|
|
|
pushReturnValue(t, frame, methodReturnCode(t, target), result);
|
2008-02-11 17:21:41 +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 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
|
|
|
|
2008-01-11 22:16:24 +00:00
|
|
|
object class_ = methodClass(t, context->method);
|
2007-12-09 22:45:43 +00:00
|
|
|
if (isSpecialMethod(t, target, class_)) {
|
|
|
|
target = findMethod(t, target, classSuper(t, class_));
|
|
|
|
}
|
2007-09-28 23:41:03 +00:00
|
|
|
|
2008-07-12 20:52:14 +00:00
|
|
|
assert(t, (methodFlags(t, target) & ACC_STATIC) == 0);
|
|
|
|
|
2009-04-26 01:51:33 +00:00
|
|
|
bool tailCall = isTailCall(t, code, ip, context->method, target);
|
2009-04-19 22:36:11 +00:00
|
|
|
|
2009-04-26 01:51:33 +00:00
|
|
|
compileDirectInvoke(t, frame, target, tailCall);
|
2007-12-09 22:45:43 +00:00
|
|
|
} 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;
|
2007-09-29 21:08:29 +00:00
|
|
|
|
2008-07-12 20:52:14 +00:00
|
|
|
assert(t, methodFlags(t, target) & ACC_STATIC);
|
|
|
|
|
2009-04-26 01:51:33 +00:00
|
|
|
bool tailCall = isTailCall(t, code, ip, context->method, target);
|
2009-04-19 22:36:11 +00:00
|
|
|
|
2009-04-26 01:51:33 +00:00
|
|
|
compileDirectInvoke(t, frame, target, tailCall);
|
2007-12-09 22:45:43 +00:00
|
|
|
} 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
|
|
|
|
2008-07-12 20:52:14 +00:00
|
|
|
assert(t, (methodFlags(t, target) & ACC_STATIC) == 0);
|
|
|
|
|
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
|
|
|
|
2008-11-02 22:25:51 +00:00
|
|
|
Compiler::Operand* instance = c->peek(1, parameterFootprint - 1);
|
2007-09-29 21:08:29 +00:00
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
unsigned rSize = resultSize(t, methodReturnCode(t, target));
|
2007-10-15 19:12:38 +00:00
|
|
|
|
2009-04-26 01:51:33 +00:00
|
|
|
bool tailCall = isTailCall(t, code, ip, context->method, target);
|
2009-04-05 21:42:10 +00:00
|
|
|
|
2009-04-19 22:36:11 +00:00
|
|
|
Compiler::Operand* result = c->stackCall
|
2009-05-03 20:57:11 +00:00
|
|
|
(c->memory
|
|
|
|
(c->and_
|
|
|
|
(BytesPerWord, c->constant(PointerMask),
|
|
|
|
c->memory(instance, 0, 0, 1)), offset, 0, 1),
|
2009-04-22 01:39:25 +00:00
|
|
|
tailCall ? Compiler::TailJump : 0,
|
2009-04-19 22:36:11 +00:00
|
|
|
frame->trace(0, 0),
|
|
|
|
rSize,
|
|
|
|
parameterFootprint);
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
frame->pop(parameterFootprint);
|
2007-10-15 19:12:38 +00:00
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
if (rSize) {
|
2008-03-11 16:57:35 +00:00
|
|
|
pushReturnValue(t, frame, methodReturnCode(t, target), result);
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-10-15 19:12:38 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case ior: {
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* a = frame->popInt();
|
|
|
|
Compiler::Operand* b = frame->popInt();
|
2008-02-12 02:06:12 +00:00
|
|
|
frame->pushInt(c->or_(4, a, b));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-10-15 19:12:38 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case irem: {
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* a = frame->popInt();
|
|
|
|
Compiler::Operand* b = frame->popInt();
|
2008-02-12 02:06:12 +00:00
|
|
|
frame->pushInt(c->rem(4, a, b));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-10-15 19:12:38 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case ireturn:
|
2007-12-14 18:27:56 +00:00
|
|
|
case freturn: {
|
2009-04-19 22:36:11 +00:00
|
|
|
Compiler::Operand* value = frame->popInt();
|
2009-04-26 01:51:33 +00:00
|
|
|
handleExit(t, frame);
|
|
|
|
c->return_(4, value);
|
2007-12-14 18:27:56 +00:00
|
|
|
} return;
|
2007-10-15 19:12:38 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case ishl: {
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* a = frame->popInt();
|
|
|
|
Compiler::Operand* b = frame->popInt();
|
2008-02-12 02:06:12 +00:00
|
|
|
frame->pushInt(c->shl(4, a, b));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-10-15 19:12:38 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case ishr: {
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* a = frame->popInt();
|
|
|
|
Compiler::Operand* b = frame->popInt();
|
2008-02-12 02:06:12 +00:00
|
|
|
frame->pushInt(c->shr(4, a, b));
|
2007-12-09 22:45:43 +00:00
|
|
|
} 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: {
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* a = frame->popInt();
|
|
|
|
Compiler::Operand* b = frame->popInt();
|
2008-02-12 02:06:12 +00:00
|
|
|
frame->pushInt(c->sub(4, a, b));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-10-15 19:12:38 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case iushr: {
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* a = frame->popInt();
|
|
|
|
Compiler::Operand* b = frame->popInt();
|
2008-02-12 02:06:12 +00:00
|
|
|
frame->pushInt(c->ushr(4, a, b));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-10-15 19:12:38 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case ixor: {
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* a = frame->popInt();
|
|
|
|
Compiler::Operand* b = frame->popInt();
|
2008-02-12 02:06:12 +00:00
|
|
|
frame->pushInt(c->xor_(4, a, b));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-10-15 19:12:38 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case jsr:
|
2007-12-26 23:59:55 +00:00
|
|
|
case jsr_w: {
|
2008-11-16 00:28:45 +00:00
|
|
|
uint32_t thisIp;
|
2007-12-26 23:59:55 +00:00
|
|
|
uint32_t newIp;
|
2007-10-15 19:12:38 +00:00
|
|
|
|
2007-12-26 23:59:55 +00:00
|
|
|
if (instruction == jsr) {
|
2008-11-11 15:20:49 +00:00
|
|
|
uint32_t offset = codeReadInt16(t, code, ip);
|
2008-11-16 00:28:45 +00:00
|
|
|
thisIp = ip - 3;
|
|
|
|
newIp = thisIp + offset;
|
2007-12-26 23:59:55 +00:00
|
|
|
} else {
|
2008-11-11 15:20:49 +00:00
|
|
|
uint32_t offset = codeReadInt32(t, code, ip);
|
2008-11-16 00:28:45 +00:00
|
|
|
thisIp = ip - 5;
|
|
|
|
newIp = thisIp + offset;
|
2007-12-26 23:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
assert(t, newIp < codeLength(t, code));
|
|
|
|
|
2008-11-16 00:28:45 +00:00
|
|
|
int index = exceptionIndex(t, code, thisIp, newIp);
|
|
|
|
if (index >= 0) {
|
|
|
|
// store a null pointer at the same index the exception would
|
|
|
|
// be stored in the finally block so we can safely treat that
|
|
|
|
// location as a GC root. Of course, this assumes there
|
|
|
|
// wasn't already a live value there, which is something we
|
|
|
|
// should verify once we have complete data flow information
|
|
|
|
// (todo).
|
2009-05-03 20:57:11 +00:00
|
|
|
storeLocal(context, 1, c->constant(0), index);
|
2009-05-18 15:16:17 +00:00
|
|
|
frame->storedObject(translateLocalIndex(context, 1, index));
|
2008-11-16 00:28:45 +00:00
|
|
|
}
|
|
|
|
|
2009-02-14 21:23:23 +00:00
|
|
|
frame->pushAddress(frame->addressOperand(c->machineIp(ip)));
|
2008-06-11 00:16:02 +00:00
|
|
|
|
2007-12-26 23:59:55 +00:00
|
|
|
c->jmp(frame->machineIp(newIp));
|
|
|
|
|
2009-02-14 20:26:39 +00:00
|
|
|
frame->subroutine = c->startSubroutine();
|
2008-11-14 00:59:21 +00:00
|
|
|
|
2007-12-26 23:59:55 +00:00
|
|
|
compile(t, frame, newIp);
|
|
|
|
if (UNLIKELY(t->exception)) return;
|
2007-12-27 20:32:34 +00:00
|
|
|
|
2008-11-14 00:59:21 +00:00
|
|
|
frame->poppedInt();
|
2008-09-13 21:09:26 +00:00
|
|
|
|
2009-02-14 20:26:39 +00:00
|
|
|
c->restoreFromSubroutine(frame->subroutine);
|
2007-12-16 21:30:19 +00:00
|
|
|
} break;
|
2007-10-15 19:12:38 +00:00
|
|
|
|
2008-03-21 00:37:58 +00:00
|
|
|
case l2d: {
|
2008-04-17 22:07:32 +00:00
|
|
|
frame->pushLong
|
|
|
|
(c->call
|
2008-05-31 22:14:27 +00:00
|
|
|
(c->constant(getThunk(t, longToDoubleThunk)),
|
|
|
|
0, 0, 8, 2,
|
2008-05-23 00:08:41 +00:00
|
|
|
static_cast<Compiler::Operand*>(0), frame->popLong()));
|
2008-03-21 00:37:58 +00:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case l2f: {
|
2008-04-17 22:07:32 +00:00
|
|
|
frame->pushInt
|
|
|
|
(c->call
|
2008-05-31 22:14:27 +00:00
|
|
|
(c->constant(getThunk(t, longToFloatThunk)),
|
|
|
|
0, 0, 4, 2,
|
2008-05-23 00:08:41 +00:00
|
|
|
static_cast<Compiler::Operand*>(0), frame->popLong()));
|
2008-03-21 00:37:58 +00:00
|
|
|
} break;
|
|
|
|
|
2007-12-26 23:59:55 +00:00
|
|
|
case l2i:
|
2009-03-06 17:56:11 +00:00
|
|
|
frame->pushInt(c->load(8, 8, frame->popLong(), BytesPerWord));
|
2007-12-26 23:59:55 +00:00
|
|
|
break;
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case ladd: {
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* a = frame->popLong();
|
|
|
|
Compiler::Operand* b = frame->popLong();
|
2008-02-12 02:06:12 +00:00
|
|
|
frame->pushLong(c->add(8, a, b));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-10-15 19:12:38 +00:00
|
|
|
|
2007-12-26 19:19:45 +00:00
|
|
|
case land: {
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* a = frame->popLong();
|
|
|
|
Compiler::Operand* b = frame->popLong();
|
2008-02-12 02:06:12 +00:00
|
|
|
frame->pushLong(c->and_(8, a, b));
|
2007-12-26 19:19:45 +00:00
|
|
|
} break;
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case lcmp: {
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* a = frame->popLong();
|
|
|
|
Compiler::Operand* b = frame->popLong();
|
2007-12-12 22:19:13 +00:00
|
|
|
|
2008-12-21 21:41:56 +00:00
|
|
|
frame->pushInt(c->lcmp(a, b));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case lconst_0:
|
2007-12-26 16:56:14 +00:00
|
|
|
frame->pushLong(c->constant(0));
|
2007-12-09 22:45:43 +00:00
|
|
|
break;
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case lconst_1:
|
2007-12-26 16:56:14 +00:00
|
|
|
frame->pushLong(c->constant(1));
|
2007-12-09 22:45:43 +00:00
|
|
|
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);
|
2007-12-26 16:56:14 +00:00
|
|
|
frame->pushLong(c->constant(v));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-09-24 01:39:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case ldiv_: {
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* a = frame->popLong();
|
|
|
|
Compiler::Operand* b = frame->popLong();
|
2008-02-12 02:06:12 +00:00
|
|
|
frame->pushLong(c->div(8, a, b));
|
2007-12-09 22:45:43 +00:00
|
|
|
} 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: {
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* a = frame->popLong();
|
|
|
|
Compiler::Operand* b = frame->popLong();
|
2008-02-12 02:06:12 +00:00
|
|
|
frame->pushLong(c->mul(8, a, b));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-10-17 01:21:35 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case lneg:
|
2008-02-12 02:06:12 +00:00
|
|
|
frame->pushLong(c->neg(8, frame->popLong()));
|
2007-12-09 22:45:43 +00:00
|
|
|
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
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* key = frame->popInt();
|
2007-12-09 22:45:43 +00:00
|
|
|
|
|
|
|
uint32_t defaultIp = base + codeReadInt32(t, code, ip);
|
|
|
|
assert(t, defaultIp < codeLength(t, code));
|
2007-09-29 20:24:14 +00:00
|
|
|
|
2008-12-02 16:45:20 +00:00
|
|
|
Compiler::Operand* default_ = frame->addressOperand
|
|
|
|
(c->machineIp(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
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* start = 0;
|
2007-12-16 00:24:15 +00:00
|
|
|
uint32_t ipTable[pairCount];
|
2007-12-09 22:45:43 +00:00
|
|
|
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-16 00:24:15 +00:00
|
|
|
ipTable[i] = newIp;
|
2007-09-24 01:39:03 +00:00
|
|
|
|
2007-12-16 00:24:15 +00:00
|
|
|
Promise* p = c->poolAppend(key);
|
2007-12-09 22:45:43 +00:00
|
|
|
if (i == 0) {
|
2008-12-02 16:45:20 +00:00
|
|
|
start = frame->addressOperand(p);
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2008-12-02 16:45:20 +00:00
|
|
|
c->poolAppendPromise(frame->addressPromise(c->machineIp(newIp)));
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2007-12-16 00:24:15 +00:00
|
|
|
assert(t, start);
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
c->jmp
|
|
|
|
(c->call
|
2008-05-31 22:14:27 +00:00
|
|
|
(c->constant(getThunk(t, lookUpAddressThunk)),
|
|
|
|
0, 0, BytesPerWord,
|
2008-02-11 17:21:41 +00:00
|
|
|
4, key, start, c->constant(pairCount), default_));
|
2007-12-16 00:24:15 +00:00
|
|
|
|
2008-09-13 21:09:26 +00:00
|
|
|
Compiler::State* state = c->saveState();
|
|
|
|
|
2007-12-16 00:24:15 +00:00
|
|
|
for (int32_t i = 0; i < pairCount; ++i) {
|
|
|
|
compile(t, frame, ipTable[i]);
|
|
|
|
if (UNLIKELY(t->exception)) return;
|
2008-09-13 21:09:26 +00:00
|
|
|
|
|
|
|
c->restoreState(state);
|
2007-12-16 00:24:15 +00:00
|
|
|
}
|
|
|
|
|
2008-01-07 14:51:07 +00:00
|
|
|
ip = defaultIp;
|
|
|
|
} break;
|
2007-09-29 20:24:14 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case lor: {
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* a = frame->popLong();
|
|
|
|
Compiler::Operand* b = frame->popLong();
|
2008-02-12 02:06:12 +00:00
|
|
|
frame->pushLong(c->or_(8, a, b));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-09-29 20:24:14 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case lrem: {
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* a = frame->popLong();
|
|
|
|
Compiler::Operand* b = frame->popLong();
|
2008-02-12 02:06:12 +00:00
|
|
|
frame->pushLong(c->rem(8, a, b));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-09-29 20:24:14 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case lreturn:
|
2007-12-12 22:19:13 +00:00
|
|
|
case dreturn: {
|
2009-04-19 22:36:11 +00:00
|
|
|
Compiler::Operand* value = frame->popLong();
|
2009-04-26 01:51:33 +00:00
|
|
|
handleExit(t, frame);
|
|
|
|
c->return_(8, value);
|
2007-12-12 22:19:13 +00:00
|
|
|
} return;
|
2007-09-29 20:24:14 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case lshl: {
|
2008-04-28 15:53:48 +00:00
|
|
|
Compiler::Operand* a = frame->popInt();
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* b = frame->popLong();
|
2008-02-12 02:06:12 +00:00
|
|
|
frame->pushLong(c->shl(8, a, b));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-09-29 20:24:14 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case lshr: {
|
2008-04-28 15:53:48 +00:00
|
|
|
Compiler::Operand* a = frame->popInt();
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* b = frame->popLong();
|
2008-02-12 02:06:12 +00:00
|
|
|
frame->pushLong(c->shr(8, a, b));
|
2007-12-09 22:45:43 +00:00
|
|
|
} 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: {
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* a = frame->popLong();
|
|
|
|
Compiler::Operand* b = frame->popLong();
|
2008-02-12 02:06:12 +00:00
|
|
|
frame->pushLong(c->sub(8, a, b));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case lushr: {
|
2008-04-28 15:53:48 +00:00
|
|
|
Compiler::Operand* a = frame->popInt();
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* b = frame->popLong();
|
2008-02-12 02:06:12 +00:00
|
|
|
frame->pushLong(c->ushr(8, a, b));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case lxor: {
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* a = frame->popLong();
|
|
|
|
Compiler::Operand* b = frame->popLong();
|
2008-02-12 02:06:12 +00:00
|
|
|
frame->pushLong(c->xor_(8, a, b));
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case monitorenter: {
|
2009-03-18 22:24:13 +00:00
|
|
|
Compiler::Operand* target = frame->popObject();
|
2008-02-11 17:21:41 +00:00
|
|
|
c->call
|
2008-05-31 22:14:27 +00:00
|
|
|
(c->constant(getThunk(t, acquireMonitorForObjectThunk)),
|
2009-04-07 00:34:12 +00:00
|
|
|
0, frame->trace(0, 0), 0, 2, c->register_(t->arch->thread()), target);
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-09-29 21:08:29 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case monitorexit: {
|
2009-03-18 22:24:13 +00:00
|
|
|
Compiler::Operand* target = frame->popObject();
|
2008-02-11 17:21:41 +00:00
|
|
|
c->call
|
2008-05-31 22:14:27 +00:00
|
|
|
(c->constant(getThunk(t, releaseMonitorForObjectThunk)),
|
2009-04-07 00:34:12 +00:00
|
|
|
0, frame->trace(0, 0), 0, 2, c->register_(t->arch->thread()), target);
|
2007-12-09 22:45:43 +00:00
|
|
|
} 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
|
|
|
|
2009-03-01 22:39:52 +00:00
|
|
|
unsigned offset
|
2009-05-17 23:43:48 +00:00
|
|
|
= localOffset
|
|
|
|
(t, localSize(t, context->method) + c->topOfStack(), context->method)
|
2009-03-01 22:39:52 +00:00
|
|
|
+ t->arch->frameReturnAddressSize();
|
2008-11-11 00:07:44 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* result = c->call
|
2008-05-31 22:14:27 +00:00
|
|
|
(c->constant(getThunk(t, makeMultidimensionalArrayThunk)),
|
|
|
|
0,
|
2009-03-31 20:15:08 +00:00
|
|
|
frame->trace(0, 0),
|
2008-02-11 17:21:41 +00:00
|
|
|
BytesPerWord,
|
2009-04-07 00:34:12 +00:00
|
|
|
4, c->register_(t->arch->thread()), frame->append(class_),
|
|
|
|
c->constant(dimensions), c->constant(offset));
|
2007-12-23 00:00:35 +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;
|
|
|
|
|
|
|
|
if (classVmFlags(t, class_) & WeakReferenceFlag) {
|
2008-02-11 17:21:41 +00:00
|
|
|
frame->pushObject
|
|
|
|
(c->call
|
2009-02-28 21:20:43 +00:00
|
|
|
(c->constant(getThunk(t, makeNewWeakReference64Thunk)),
|
2008-05-31 22:14:27 +00:00
|
|
|
0,
|
2009-03-31 20:15:08 +00:00
|
|
|
frame->trace(0, 0),
|
2008-02-11 17:21:41 +00:00
|
|
|
BytesPerWord,
|
2009-04-07 00:34:12 +00:00
|
|
|
2, c->register_(t->arch->thread()), frame->append(class_)));
|
2007-12-09 22:45:43 +00:00
|
|
|
} else {
|
2008-02-11 17:21:41 +00:00
|
|
|
frame->pushObject
|
|
|
|
(c->call
|
2009-02-28 21:20:43 +00:00
|
|
|
(c->constant(getThunk(t, makeNew64Thunk)),
|
2008-05-31 22:14:27 +00:00
|
|
|
0,
|
2009-03-31 20:15:08 +00:00
|
|
|
frame->trace(0, 0),
|
2008-02-11 17:21:41 +00:00
|
|
|
BytesPerWord,
|
2009-04-07 00:34:12 +00:00
|
|
|
2, c->register_(t->arch->thread()), frame->append(class_)));
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
|
|
|
} 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
|
|
|
|
2008-04-26 20:56:03 +00:00
|
|
|
Compiler::Operand* length = frame->popInt();
|
2007-10-16 17:21:26 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
frame->pushObject
|
|
|
|
(c->call
|
2008-05-31 22:14:27 +00:00
|
|
|
(c->constant(getThunk(t, makeBlankArrayThunk)),
|
|
|
|
0,
|
2009-03-31 20:15:08 +00:00
|
|
|
frame->trace(0, 0),
|
2008-02-11 17:21:41 +00:00
|
|
|
BytesPerWord,
|
2009-04-07 00:34:12 +00:00
|
|
|
3, c->register_(t->arch->thread()), c->constant(type), length));
|
2007-12-09 22:45:43 +00:00
|
|
|
} 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-17 22:38:59 +00:00
|
|
|
object staticTable = 0;
|
2007-09-27 22:20:54 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
if (instruction == putstatic) {
|
2009-01-10 19:25:52 +00:00
|
|
|
assert(t, fieldFlags(t, field) & ACC_STATIC);
|
|
|
|
|
2008-11-30 04:58:09 +00:00
|
|
|
if (fieldClass(t, field) != methodClass(t, context->method)
|
|
|
|
and classNeedsInit(t, fieldClass(t, field)))
|
2008-04-23 22:56:02 +00:00
|
|
|
{
|
2008-03-16 19:38:43 +00:00
|
|
|
c->call
|
2008-05-31 22:14:27 +00:00
|
|
|
(c->constant(getThunk(t, tryInitClassThunk)),
|
|
|
|
0,
|
2009-03-31 20:15:08 +00:00
|
|
|
frame->trace(0, 0),
|
2008-03-16 19:38:43 +00:00
|
|
|
0,
|
2009-04-07 00:34:12 +00:00
|
|
|
2, c->register_(t->arch->thread()),
|
|
|
|
frame->append(fieldClass(t, field)));
|
2008-04-23 22:56:02 +00:00
|
|
|
}
|
2007-09-27 22:20:54 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
staticTable = classStaticTable(t, fieldClass(t, field));
|
2009-01-10 19:25:52 +00:00
|
|
|
} else {
|
|
|
|
assert(t, (fieldFlags(t, field) & ACC_STATIC) == 0);
|
2009-02-09 23:22:01 +00:00
|
|
|
|
|
|
|
if (inTryBlock(t, code, ip - 3)) {
|
|
|
|
c->saveLocals();
|
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2007-10-12 22:06:33 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* value;
|
2007-12-09 22:45:43 +00:00
|
|
|
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: {
|
2007-12-12 22:19:13 +00:00
|
|
|
value = frame->popObject();
|
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
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::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
|
|
|
|
2009-03-04 01:02:11 +00:00
|
|
|
Compiler::Operand* fieldOperand = 0;
|
|
|
|
|
2009-03-03 03:18:15 +00:00
|
|
|
if (fieldFlags(t, field) & ACC_VOLATILE) {
|
2009-03-04 01:02:11 +00:00
|
|
|
if (BytesPerWord == 4
|
|
|
|
and (fieldCode(t, field) == DoubleField
|
|
|
|
or fieldCode(t, field) == LongField))
|
|
|
|
{
|
|
|
|
fieldOperand = frame->append(field);
|
|
|
|
|
|
|
|
c->call
|
|
|
|
(c->constant(getThunk(t, acquireMonitorForObjectThunk)),
|
2009-04-07 00:34:12 +00:00
|
|
|
0, frame->trace(0, 0), 0, 2, c->register_(t->arch->thread()),
|
|
|
|
fieldOperand);
|
2009-03-04 01:02:11 +00:00
|
|
|
} else {
|
|
|
|
c->storeStoreBarrier();
|
|
|
|
}
|
2009-03-03 03:18:15 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
switch (fieldCode(t, field)) {
|
|
|
|
case ByteField:
|
|
|
|
case BooleanField:
|
2009-02-28 23:17:24 +00:00
|
|
|
c->store(BytesPerWord, value, 1,
|
|
|
|
c->memory(table, fieldOffset(t, field), 0, 1));
|
2007-10-17 01:21:35 +00:00
|
|
|
break;
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case CharField:
|
|
|
|
case ShortField:
|
2009-02-28 23:17:24 +00:00
|
|
|
c->store(BytesPerWord, value, 2,
|
|
|
|
c->memory(table, fieldOffset(t, field), 0, 1));
|
2007-10-17 01:21:35 +00:00
|
|
|
break;
|
2007-12-09 22:45:43 +00:00
|
|
|
|
|
|
|
case FloatField:
|
|
|
|
case IntField:
|
2009-02-28 23:17:24 +00:00
|
|
|
c->store(BytesPerWord, value, 4,
|
|
|
|
c->memory(table, fieldOffset(t, field), 0, 1));
|
2007-10-10 17:26:28 +00:00
|
|
|
break;
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case DoubleField:
|
|
|
|
case LongField:
|
2009-02-28 23:17:24 +00:00
|
|
|
c->store(8, value, 8, c->memory(table, fieldOffset(t, field), 0, 1));
|
2007-10-10 17:26:28 +00:00
|
|
|
break;
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case ObjectField:
|
2007-12-31 22:40:56 +00:00
|
|
|
if (instruction == putfield) {
|
2008-02-11 17:21:41 +00:00
|
|
|
c->call
|
2008-05-31 22:14:27 +00:00
|
|
|
(c->constant(getThunk(t, setMaybeNullThunk)),
|
|
|
|
0,
|
2009-03-31 20:15:08 +00:00
|
|
|
frame->trace(0, 0),
|
2008-02-11 17:21:41 +00:00
|
|
|
0,
|
2009-04-07 00:34:12 +00:00
|
|
|
4, c->register_(t->arch->thread()), table,
|
|
|
|
c->constant(fieldOffset(t, field)), value);
|
2007-12-30 22:24:48 +00:00
|
|
|
} else {
|
2008-02-11 17:21:41 +00:00
|
|
|
c->call
|
2008-05-31 22:14:27 +00:00
|
|
|
(c->constant(getThunk(t, setThunk)),
|
|
|
|
0, 0, 0,
|
2009-04-07 00:34:12 +00:00
|
|
|
4, c->register_(t->arch->thread()), table,
|
|
|
|
c->constant(fieldOffset(t, field)), value);
|
2007-12-30 22:24:48 +00:00
|
|
|
}
|
2007-10-10 17:26:28 +00:00
|
|
|
break;
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
default: abort(t);
|
|
|
|
}
|
2009-03-03 03:18:15 +00:00
|
|
|
|
|
|
|
if (fieldFlags(t, field) & ACC_VOLATILE) {
|
2009-03-04 01:02:11 +00:00
|
|
|
if (BytesPerWord == 4
|
|
|
|
and (fieldCode(t, field) == DoubleField
|
|
|
|
or fieldCode(t, field) == LongField))
|
|
|
|
{
|
|
|
|
c->call
|
|
|
|
(c->constant(getThunk(t, releaseMonitorForObjectThunk)),
|
2009-04-07 00:34:12 +00:00
|
|
|
0, frame->trace(0, 0), 0, 2, c->register_(t->arch->thread()),
|
|
|
|
fieldOperand);
|
2009-03-04 01:02:11 +00:00
|
|
|
} else {
|
|
|
|
c->storeLoadBarrier();
|
|
|
|
}
|
2009-03-03 03:18:15 +00:00
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
} break;
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-12-26 23:59:55 +00:00
|
|
|
case ret:
|
2009-05-03 20:57:11 +00:00
|
|
|
c->jmp(loadLocal(context, 1, codeBody(t, code, ip)));
|
2009-02-14 20:26:39 +00:00
|
|
|
c->endSubroutine(frame->subroutine);
|
2007-12-26 23:59:55 +00:00
|
|
|
return;
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case return_:
|
2009-04-26 01:51:33 +00:00
|
|
|
if (needsReturnBarrier(t, context->method)) {
|
|
|
|
c->storeStoreBarrier();
|
2009-04-19 22:36:11 +00:00
|
|
|
}
|
2009-04-26 01:51:33 +00:00
|
|
|
|
|
|
|
handleExit(t, frame);
|
|
|
|
c->return_(0, 0);
|
2007-12-09 22:45:43 +00:00
|
|
|
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
|
|
|
uint32_t defaultIp = base + codeReadInt32(t, code, ip);
|
|
|
|
assert(t, defaultIp < codeLength(t, code));
|
|
|
|
|
|
|
|
int32_t bottom = codeReadInt32(t, code, ip);
|
|
|
|
int32_t top = codeReadInt32(t, code, ip);
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler::Operand* start = 0;
|
2007-12-16 00:24:15 +00:00
|
|
|
uint32_t ipTable[top - bottom + 1];
|
|
|
|
for (int32_t i = 0; i < top - bottom + 1; ++i) {
|
2007-12-09 22:45:43 +00:00
|
|
|
unsigned index = ip + (i * 4);
|
|
|
|
uint32_t newIp = base + codeReadInt32(t, code, index);
|
|
|
|
assert(t, newIp < codeLength(t, code));
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-16 00:24:15 +00:00
|
|
|
ipTable[i] = newIp;
|
|
|
|
|
2008-12-02 16:45:20 +00:00
|
|
|
Promise* p = c->poolAppendPromise
|
|
|
|
(frame->addressPromise(c->machineIp(newIp)));
|
2007-12-09 22:45:43 +00:00
|
|
|
if (i == 0) {
|
2008-12-02 16:45:20 +00:00
|
|
|
start = frame->addressOperand(p);
|
2007-09-26 23:23:03 +00:00
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2007-12-16 00:24:15 +00:00
|
|
|
assert(t, start);
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2008-04-19 22:13:57 +00:00
|
|
|
Compiler::Operand* key = frame->popInt();
|
2007-12-09 22:45:43 +00:00
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
c->cmp(4, c->constant(bottom), key);
|
2008-09-20 23:42:46 +00:00
|
|
|
c->jl(frame->machineIp(defaultIp));
|
|
|
|
|
2008-11-07 00:39:38 +00:00
|
|
|
c->save(1, key);
|
|
|
|
|
2008-09-20 23:42:46 +00:00
|
|
|
saveStateAndCompile(t, frame, defaultIp);
|
2007-10-04 22:41:19 +00:00
|
|
|
|
2008-02-12 02:06:12 +00:00
|
|
|
c->cmp(4, c->constant(top), key);
|
2008-09-20 23:42:46 +00:00
|
|
|
c->jg(frame->machineIp(defaultIp));
|
|
|
|
|
2008-11-07 00:39:38 +00:00
|
|
|
c->save(1, key);
|
|
|
|
|
2008-09-20 23:42:46 +00:00
|
|
|
saveStateAndCompile(t, frame, defaultIp);
|
2007-10-04 22:41:19 +00:00
|
|
|
|
2009-03-07 00:11:14 +00:00
|
|
|
Compiler::Operand* normalizedKey
|
|
|
|
= (bottom ? c->sub(4, c->constant(bottom), key) : key);
|
|
|
|
|
2009-03-06 17:56:11 +00:00
|
|
|
c->jmp(c->load(BytesPerWord, BytesPerWord,
|
2009-03-07 00:11:14 +00:00
|
|
|
c->memory(start, 0, normalizedKey, BytesPerWord),
|
|
|
|
BytesPerWord));
|
2007-12-09 22:45:43 +00:00
|
|
|
|
2008-09-13 21:09:26 +00:00
|
|
|
Compiler::State* state = c->saveState();
|
|
|
|
|
2007-12-16 00:24:15 +00:00
|
|
|
for (int32_t i = 0; i < top - bottom + 1; ++i) {
|
|
|
|
compile(t, frame, ipTable[i]);
|
|
|
|
if (UNLIKELY(t->exception)) return;
|
2008-09-13 21:09:26 +00:00
|
|
|
|
|
|
|
c->restoreState(state);
|
2007-12-16 00:24:15 +00:00
|
|
|
}
|
|
|
|
|
2008-01-07 14:51:07 +00:00
|
|
|
ip = defaultIp;
|
|
|
|
} break;
|
2007-12-09 22:45:43 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
2009-05-15 02:08:01 +00:00
|
|
|
storeLocal
|
|
|
|
(context, 1,
|
|
|
|
c->add(4, c->constant(count), loadLocal(context, 1, index)),
|
2009-05-03 20:57:11 +00:00
|
|
|
index);
|
2007-12-09 22:45:43 +00:00
|
|
|
} 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:
|
2009-05-03 20:57:11 +00:00
|
|
|
c->jmp(loadLocal(context, 1, codeReadInt16(t, code, ip)));
|
2009-02-14 20:26:39 +00:00
|
|
|
c->endSubroutine(frame->subroutine);
|
2007-12-26 23:59:55 +00:00
|
|
|
return;
|
2007-10-04 22:41:19 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
default: abort(t);
|
|
|
|
}
|
|
|
|
} break;
|
2007-12-26 19:19:45 +00:00
|
|
|
|
|
|
|
default: abort(t);
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-10-04 22:41:19 +00:00
|
|
|
|
2007-12-26 16:56:14 +00:00
|
|
|
void
|
2008-11-11 15:20:49 +00:00
|
|
|
logCompile(MyThread* t, const void* code, unsigned size, const char* class_,
|
2008-01-07 22:04:53 +00:00
|
|
|
const char* name, const char* spec)
|
2007-12-26 16:56:14 +00:00
|
|
|
{
|
2008-11-11 15:20:49 +00:00
|
|
|
static FILE* log = 0;
|
|
|
|
static bool open = false;
|
|
|
|
if (not open) {
|
|
|
|
open = true;
|
|
|
|
const char* path = findProperty(t, "avian.jit.log");
|
2008-11-11 16:17:11 +00:00
|
|
|
if (path) {
|
2008-11-11 15:20:49 +00:00
|
|
|
log = fopen(path, "wb");
|
|
|
|
} else if (DebugCompile) {
|
|
|
|
log = stderr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (log) {
|
|
|
|
fprintf(log, "%p %p %s.%s%s\n",
|
|
|
|
code, static_cast<const uint8_t*>(code) + size,
|
|
|
|
class_, name, spec);
|
|
|
|
}
|
2007-12-26 16:56:14 +00:00
|
|
|
}
|
|
|
|
|
2008-01-07 14:51:07 +00:00
|
|
|
void
|
2008-04-11 19:03:40 +00:00
|
|
|
translateExceptionHandlerTable(MyThread* t, Compiler* c, object code,
|
|
|
|
intptr_t start)
|
2008-01-07 14:51:07 +00:00
|
|
|
{
|
|
|
|
object oldTable = codeExceptionHandlerTable(t, code);
|
|
|
|
if (oldTable) {
|
|
|
|
PROTECT(t, code);
|
|
|
|
PROTECT(t, oldTable);
|
|
|
|
|
|
|
|
unsigned length = exceptionHandlerTableLength(t, oldTable);
|
2008-04-11 19:03:40 +00:00
|
|
|
|
2009-03-04 03:05:48 +00:00
|
|
|
object newIndex = makeIntArray(t, length * 3);
|
2008-04-11 19:03:40 +00:00
|
|
|
PROTECT(t, newIndex);
|
|
|
|
|
2009-03-04 03:05:48 +00:00
|
|
|
object newTable = makeArray(t, length + 1);
|
2008-04-24 22:06:36 +00:00
|
|
|
PROTECT(t, newTable);
|
|
|
|
|
2008-04-11 19:03:40 +00:00
|
|
|
set(t, newTable, ArrayBody, newIndex);
|
|
|
|
|
2008-01-07 14:51:07 +00:00
|
|
|
for (unsigned i = 0; i < length; ++i) {
|
|
|
|
ExceptionHandler* oldHandler = exceptionHandlerTableBody
|
|
|
|
(t, oldTable, i);
|
|
|
|
|
2008-04-11 19:03:40 +00:00
|
|
|
intArrayBody(t, newIndex, i * 3)
|
2008-02-11 17:21:41 +00:00
|
|
|
= c->machineIp(exceptionHandlerStart(oldHandler))->value() - start;
|
2008-01-07 14:51:07 +00:00
|
|
|
|
2008-04-11 19:03:40 +00:00
|
|
|
intArrayBody(t, newIndex, (i * 3) + 1)
|
2008-02-11 17:21:41 +00:00
|
|
|
= c->machineIp(exceptionHandlerEnd(oldHandler))->value() - start;
|
2008-01-07 14:51:07 +00:00
|
|
|
|
2008-04-11 19:03:40 +00:00
|
|
|
intArrayBody(t, newIndex, (i * 3) + 2)
|
2008-02-11 17:21:41 +00:00
|
|
|
= c->machineIp(exceptionHandlerIp(oldHandler))->value() - start;
|
2008-01-07 14:51:07 +00:00
|
|
|
|
2008-04-24 22:06:36 +00:00
|
|
|
object type;
|
|
|
|
if (exceptionHandlerCatchType(oldHandler)) {
|
|
|
|
type = resolveClassInPool
|
|
|
|
(t, codePool(t, code), exceptionHandlerCatchType(oldHandler) - 1);
|
|
|
|
if (UNLIKELY(t->exception)) return;
|
|
|
|
} else {
|
|
|
|
type = 0;
|
|
|
|
}
|
2008-04-11 19:03:40 +00:00
|
|
|
|
|
|
|
set(t, newTable, ArrayBody + ((i + 1) * BytesPerWord), type);
|
2008-01-07 14:51:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
set(t, code, CodeExceptionHandlerTable, newTable);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-04-11 19:03:40 +00:00
|
|
|
translateLineNumberTable(MyThread* t, Compiler* c, object code, intptr_t start)
|
2008-01-07 14:51:07 +00:00
|
|
|
{
|
|
|
|
object oldTable = codeLineNumberTable(t, code);
|
|
|
|
if (oldTable) {
|
|
|
|
PROTECT(t, code);
|
|
|
|
PROTECT(t, oldTable);
|
|
|
|
|
|
|
|
unsigned length = lineNumberTableLength(t, oldTable);
|
2009-03-04 03:05:48 +00:00
|
|
|
object newTable = makeLineNumberTable(t, length);
|
2008-01-07 14:51:07 +00:00
|
|
|
for (unsigned i = 0; i < length; ++i) {
|
|
|
|
LineNumber* oldLine = lineNumberTableBody(t, oldTable, i);
|
|
|
|
LineNumber* newLine = lineNumberTableBody(t, newTable, i);
|
|
|
|
|
|
|
|
lineNumberIp(newLine)
|
2008-02-11 17:21:41 +00:00
|
|
|
= c->machineIp(lineNumberIp(oldLine))->value() - start;
|
2008-01-07 14:51:07 +00:00
|
|
|
|
|
|
|
lineNumberLine(newLine) = lineNumberLine(oldLine);
|
|
|
|
}
|
|
|
|
|
|
|
|
set(t, code, CodeLineNumberTable, newTable);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-11-25 23:01:30 +00:00
|
|
|
printSet(uintptr_t m, unsigned limit)
|
2008-01-07 16:01:35 +00:00
|
|
|
{
|
2008-11-25 23:01:30 +00:00
|
|
|
if (limit) {
|
|
|
|
for (unsigned i = 0; i < 16; ++i) {
|
|
|
|
if ((m >> i) & 1) {
|
|
|
|
fprintf(stderr, "1");
|
|
|
|
} else {
|
|
|
|
fprintf(stderr, "_");
|
|
|
|
}
|
2008-01-07 16:01:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned
|
2008-01-20 23:03:28 +00:00
|
|
|
calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots,
|
2009-04-27 01:53:42 +00:00
|
|
|
unsigned eventIndex)
|
2008-01-07 14:51:07 +00:00
|
|
|
{
|
2008-01-20 23:03:28 +00:00
|
|
|
// for each instruction with more than one predecessor, and for each
|
|
|
|
// stack position, determine if there exists a path to that
|
|
|
|
// instruction such that there is not an object pointer left at that
|
|
|
|
// stack position (i.e. it is uninitialized or contains primitive
|
|
|
|
// data).
|
|
|
|
|
2008-01-07 14:51:07 +00:00
|
|
|
unsigned mapSize = frameMapSizeInWords(t, context->method);
|
|
|
|
|
|
|
|
uintptr_t roots[mapSize];
|
2008-01-20 23:03:28 +00:00
|
|
|
if (originalRoots) {
|
|
|
|
memcpy(roots, originalRoots, mapSize * BytesPerWord);
|
|
|
|
} else {
|
|
|
|
memset(roots, 0, mapSize * BytesPerWord);
|
|
|
|
}
|
2008-01-07 14:51:07 +00:00
|
|
|
|
|
|
|
int32_t ip = -1;
|
|
|
|
|
2008-01-08 17:10:24 +00:00
|
|
|
// invariant: for each stack position, roots contains a zero at that
|
|
|
|
// position if there exists some path to the current instruction
|
|
|
|
// such that there is definitely not an object pointer at that
|
|
|
|
// position. Otherwise, roots contains a one at that position,
|
|
|
|
// meaning either all known paths result in an object pointer at
|
|
|
|
// that position, or the contents of that position are as yet
|
|
|
|
// unknown.
|
|
|
|
|
2008-03-05 21:44:17 +00:00
|
|
|
unsigned length = context->eventLog.length();
|
|
|
|
while (eventIndex < length) {
|
2008-01-20 23:03:28 +00:00
|
|
|
Event e = static_cast<Event>(context->eventLog.get(eventIndex++));
|
2008-01-07 14:51:07 +00:00
|
|
|
switch (e) {
|
2008-07-05 20:21:13 +00:00
|
|
|
case PushContextEvent: {
|
2009-04-27 01:53:42 +00:00
|
|
|
eventIndex = calculateFrameMaps(t, context, roots, eventIndex);
|
2008-01-07 14:51:07 +00:00
|
|
|
} break;
|
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
case PopContextEvent:
|
2008-01-20 23:03:28 +00:00
|
|
|
return eventIndex;
|
2008-01-07 14:51:07 +00:00
|
|
|
|
|
|
|
case IpEvent: {
|
2008-01-20 23:03:28 +00:00
|
|
|
ip = context->eventLog.get2(eventIndex);
|
2008-03-05 21:44:17 +00:00
|
|
|
eventIndex += 2;
|
2008-01-07 14:51:07 +00:00
|
|
|
|
2008-01-07 21:32:41 +00:00
|
|
|
if (DebugFrameMaps) {
|
|
|
|
fprintf(stderr, " roots at ip %3d: ", ip);
|
2008-11-25 23:01:30 +00:00
|
|
|
printSet(*roots, mapSize);
|
2008-01-07 21:32:41 +00:00
|
|
|
fprintf(stderr, "\n");
|
|
|
|
}
|
|
|
|
|
2008-01-20 23:03:28 +00:00
|
|
|
uintptr_t* tableRoots = context->rootTable + (ip * mapSize);
|
|
|
|
|
2008-01-07 14:51:07 +00:00
|
|
|
if (context->visitTable[ip] > 1) {
|
|
|
|
for (unsigned wi = 0; wi < mapSize; ++wi) {
|
2008-03-05 21:44:17 +00:00
|
|
|
uintptr_t newRoots = tableRoots[wi] & roots[wi];
|
|
|
|
|
|
|
|
if ((eventIndex == length
|
2008-07-05 20:21:13 +00:00
|
|
|
or context->eventLog.get(eventIndex) == PopContextEvent)
|
2008-03-05 21:44:17 +00:00
|
|
|
and newRoots != tableRoots[wi])
|
|
|
|
{
|
|
|
|
if (DebugFrameMaps) {
|
|
|
|
fprintf(stderr, "dirty roots!\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
context->dirtyRoots = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
tableRoots[wi] = newRoots;
|
2008-01-08 15:24:57 +00:00
|
|
|
roots[wi] &= tableRoots[wi];
|
2008-01-07 14:51:07 +00:00
|
|
|
}
|
|
|
|
|
2008-01-07 16:01:35 +00:00
|
|
|
if (DebugFrameMaps) {
|
|
|
|
fprintf(stderr, "table roots at ip %3d: ", ip);
|
2008-11-25 23:01:30 +00:00
|
|
|
printSet(*tableRoots, mapSize);
|
2008-01-07 16:01:35 +00:00
|
|
|
fprintf(stderr, "\n");
|
|
|
|
}
|
2008-01-20 23:03:28 +00:00
|
|
|
} else {
|
|
|
|
memcpy(tableRoots, roots, mapSize * BytesPerWord);
|
2008-01-07 14:51:07 +00:00
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case MarkEvent: {
|
2008-01-20 23:03:28 +00:00
|
|
|
unsigned i = context->eventLog.get2(eventIndex);
|
|
|
|
eventIndex += 2;
|
2008-01-07 14:51:07 +00:00
|
|
|
|
|
|
|
markBit(roots, i);
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case ClearEvent: {
|
2008-01-20 23:03:28 +00:00
|
|
|
unsigned i = context->eventLog.get2(eventIndex);
|
|
|
|
eventIndex += 2;
|
2008-03-05 21:44:17 +00:00
|
|
|
|
|
|
|
clearBit(roots, i);
|
2008-01-07 14:51:07 +00:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case TraceEvent: {
|
2008-01-20 23:03:28 +00:00
|
|
|
TraceElement* te; context->eventLog.get(eventIndex, &te, BytesPerWord);
|
2008-11-09 23:56:37 +00:00
|
|
|
if (DebugFrameMaps) {
|
|
|
|
fprintf(stderr, "trace roots at ip %3d: ", ip);
|
2008-11-25 23:01:30 +00:00
|
|
|
printSet(*roots, mapSize);
|
2008-11-09 23:56:37 +00:00
|
|
|
fprintf(stderr, "\n");
|
|
|
|
}
|
2009-03-31 20:15:08 +00:00
|
|
|
|
2008-01-07 16:01:35 +00:00
|
|
|
memcpy(te->map, roots, mapSize * BytesPerWord);
|
|
|
|
|
2008-01-20 23:03:28 +00:00
|
|
|
eventIndex += BytesPerWord;
|
2008-01-07 14:51:07 +00:00
|
|
|
} break;
|
|
|
|
|
|
|
|
default: abort(t);
|
|
|
|
}
|
|
|
|
}
|
2008-01-07 16:01:35 +00:00
|
|
|
|
2008-01-20 23:03:28 +00:00
|
|
|
return eventIndex;
|
2008-01-07 14:51:07 +00:00
|
|
|
}
|
|
|
|
|
2008-04-07 23:47:41 +00:00
|
|
|
int
|
|
|
|
compareTraceElementPointers(const void* va, const void* vb)
|
|
|
|
{
|
|
|
|
TraceElement* a = *static_cast<TraceElement* const*>(va);
|
|
|
|
TraceElement* b = *static_cast<TraceElement* const*>(vb);
|
2008-04-13 19:48:20 +00:00
|
|
|
if (a->address->value() > b->address->value()) {
|
2008-04-07 23:47:41 +00:00
|
|
|
return 1;
|
2008-04-13 19:48:20 +00:00
|
|
|
} else if (a->address->value() < b->address->value()) {
|
2008-04-07 23:47:41 +00:00
|
|
|
return -1;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-04-11 21:00:18 +00:00
|
|
|
unsigned
|
|
|
|
frameObjectMapSize(MyThread* t, object method, object map)
|
|
|
|
{
|
2009-04-27 14:46:43 +00:00
|
|
|
int size = frameMapSizeInBits(t, method);
|
2008-04-11 21:00:18 +00:00
|
|
|
return ceiling(intArrayLength(t, map) * size, 32 + size);
|
|
|
|
}
|
|
|
|
|
2008-05-31 22:14:27 +00:00
|
|
|
unsigned
|
|
|
|
codeSingletonSizeInBytes(MyThread*, unsigned codeSizeInBytes)
|
2007-12-09 22:45:43 +00:00
|
|
|
{
|
2008-05-31 22:14:27 +00:00
|
|
|
unsigned count = ceiling(codeSizeInBytes, BytesPerWord);
|
|
|
|
unsigned size = count + singletonMaskSize(count);
|
|
|
|
return pad(SingletonBody + (size * BytesPerWord));
|
|
|
|
}
|
2007-12-18 02:09:32 +00:00
|
|
|
|
2008-11-23 23:58:01 +00:00
|
|
|
uint8_t*
|
|
|
|
finish(MyThread* t, Allocator* allocator, Assembler* a, const char* name)
|
2008-02-11 17:21:41 +00:00
|
|
|
{
|
2008-11-23 23:58:01 +00:00
|
|
|
uint8_t* start = static_cast<uint8_t*>
|
|
|
|
(allocator->allocate(pad(a->length())));
|
2007-10-04 22:41:19 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
a->writeTo(start);
|
2007-10-04 22:41:19 +00:00
|
|
|
|
2008-11-11 15:20:49 +00:00
|
|
|
logCompile(t, start, a->length(), 0, name, 0);
|
2007-10-04 22:41:19 +00:00
|
|
|
|
2008-11-23 23:58:01 +00:00
|
|
|
return start;
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
2007-10-12 14:26:36 +00:00
|
|
|
|
2008-11-09 23:56:37 +00:00
|
|
|
void
|
|
|
|
setBit(MyThread* t, object map, unsigned count, unsigned size, unsigned i,
|
|
|
|
unsigned j)
|
|
|
|
{
|
|
|
|
unsigned index = ((i * size) + j);
|
|
|
|
intArrayBody(t, map, count + (index / 32))
|
|
|
|
|= static_cast<int32_t>(1) << (index % 32);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
clearBit(MyThread* t, object map, unsigned count, unsigned size, unsigned i,
|
|
|
|
unsigned j)
|
|
|
|
{
|
|
|
|
unsigned index = ((i * size) + j);
|
|
|
|
intArrayBody(t, map, count + (index / 32))
|
|
|
|
&= ~(static_cast<int32_t>(1) << (index % 32));
|
|
|
|
}
|
|
|
|
|
2008-11-23 23:58:01 +00:00
|
|
|
uint8_t*
|
|
|
|
finish(MyThread* t, Allocator* allocator, Context* context)
|
2008-02-11 17:21:41 +00:00
|
|
|
{
|
|
|
|
Compiler* c = context->compiler;
|
2008-04-11 19:03:40 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
unsigned codeSize = c->compile();
|
2008-11-23 23:58:01 +00:00
|
|
|
uintptr_t* code = static_cast<uintptr_t*>
|
2008-11-29 01:23:01 +00:00
|
|
|
(allocator->allocate(pad(codeSize) + pad(c->poolSize()) + BytesPerWord));
|
2008-11-23 23:58:01 +00:00
|
|
|
code[0] = codeSize;
|
|
|
|
uint8_t* start = reinterpret_cast<uint8_t*>(code + 1);
|
|
|
|
|
|
|
|
if (context->objectPool) {
|
|
|
|
object pool = allocate3
|
|
|
|
(t, allocator, Machine::ImmortalAllocation,
|
2008-11-29 01:23:01 +00:00
|
|
|
FixedSizeOfArray + ((context->objectPoolCount + 1) * BytesPerWord),
|
|
|
|
true);
|
2008-11-23 23:58:01 +00:00
|
|
|
|
2009-03-04 03:05:48 +00:00
|
|
|
initArray(t, pool, context->objectPoolCount + 1);
|
2008-11-29 01:23:01 +00:00
|
|
|
mark(t, pool, 0);
|
2008-11-23 23:58:01 +00:00
|
|
|
|
|
|
|
set(t, pool, ArrayBody, objectPools(t));
|
|
|
|
objectPools(t) = pool;
|
|
|
|
|
|
|
|
unsigned i = 1;
|
|
|
|
for (PoolElement* p = context->objectPool; p; p = p->next) {
|
|
|
|
unsigned offset = ArrayBody + ((i++) * BytesPerWord);
|
2008-04-07 23:47:41 +00:00
|
|
|
|
2008-11-23 23:58:01 +00:00
|
|
|
p->address = reinterpret_cast<uintptr_t>(pool) + offset;
|
|
|
|
|
|
|
|
set(t, pool, offset, p->target);
|
|
|
|
}
|
|
|
|
}
|
2008-04-11 19:03:40 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
c->writeTo(start);
|
2008-04-07 23:47:41 +00:00
|
|
|
|
2008-12-02 16:45:20 +00:00
|
|
|
BootContext* bc = context->bootContext;
|
|
|
|
if (bc) {
|
|
|
|
for (DelayedPromise* p = bc->addresses;
|
|
|
|
p != bc->addressSentinal;
|
|
|
|
p = p->next)
|
|
|
|
{
|
|
|
|
p->basis = new (bc->zone->allocate(sizeof(ResolvedPromise)))
|
|
|
|
ResolvedPromise(p->basis->value());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-04-13 19:48:20 +00:00
|
|
|
translateExceptionHandlerTable(t, c, methodCode(t, context->method),
|
|
|
|
reinterpret_cast<intptr_t>(start));
|
2008-04-27 22:40:53 +00:00
|
|
|
if (UNLIKELY(t->exception)) return 0;
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2008-04-13 19:48:20 +00:00
|
|
|
translateLineNumberTable(t, c, methodCode(t, context->method),
|
|
|
|
reinterpret_cast<intptr_t>(start));
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2008-04-13 19:48:20 +00:00
|
|
|
{ object code = methodCode(t, context->method);
|
2008-04-11 21:00:18 +00:00
|
|
|
|
2008-04-13 19:48:20 +00:00
|
|
|
code = makeCode(t, 0,
|
|
|
|
codeExceptionHandlerTable(t, code),
|
|
|
|
codeLineNumberTable(t, code),
|
|
|
|
codeMaxStack(t, code),
|
|
|
|
codeMaxLocals(t, code),
|
2009-03-04 03:05:48 +00:00
|
|
|
0);
|
2008-04-07 23:47:41 +00:00
|
|
|
|
2008-04-13 19:48:20 +00:00
|
|
|
set(t, context->method, MethodCode, code);
|
2008-02-11 17:21:41 +00:00
|
|
|
}
|
2008-04-07 23:47:41 +00:00
|
|
|
|
2008-04-13 19:48:20 +00:00
|
|
|
if (context->traceLogCount) {
|
|
|
|
TraceElement* elements[context->traceLogCount];
|
|
|
|
unsigned index = 0;
|
|
|
|
for (TraceElement* p = context->traceLog; p; p = p->next) {
|
|
|
|
assert(t, index < context->traceLogCount);
|
2008-04-11 21:00:18 +00:00
|
|
|
|
2008-04-13 19:48:20 +00:00
|
|
|
elements[index++] = p;
|
2008-04-07 23:47:41 +00:00
|
|
|
|
2008-04-13 19:48:20 +00:00
|
|
|
if (p->target) {
|
|
|
|
insertCallNode
|
|
|
|
(t, makeCallNode
|
2009-03-31 20:15:08 +00:00
|
|
|
(t, p->address->value(), p->target, p->flags, 0));
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2008-04-13 19:48:20 +00:00
|
|
|
}
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2008-04-13 19:48:20 +00:00
|
|
|
qsort(elements, context->traceLogCount, sizeof(TraceElement*),
|
|
|
|
compareTraceElementPointers);
|
2008-04-07 23:47:41 +00:00
|
|
|
|
2009-04-27 14:46:43 +00:00
|
|
|
unsigned size = frameMapSizeInBits(t, context->method);
|
2008-04-13 19:48:20 +00:00
|
|
|
object map = makeIntArray
|
|
|
|
(t, context->traceLogCount
|
2009-03-04 03:05:48 +00:00
|
|
|
+ ceiling(context->traceLogCount * size, 32));
|
2008-04-07 23:47:41 +00:00
|
|
|
|
2008-04-13 19:48:20 +00:00
|
|
|
assert(t, intArrayLength(t, map) == context->traceLogCount
|
|
|
|
+ frameObjectMapSize(t, context->method, map));
|
2008-04-11 21:00:18 +00:00
|
|
|
|
2008-04-13 19:48:20 +00:00
|
|
|
for (unsigned i = 0; i < context->traceLogCount; ++i) {
|
|
|
|
TraceElement* p = elements[i];
|
2008-04-07 23:47:41 +00:00
|
|
|
|
2008-04-13 19:48:20 +00:00
|
|
|
intArrayBody(t, map, i) = static_cast<intptr_t>(p->address->value())
|
|
|
|
- reinterpret_cast<intptr_t>(start);
|
2008-04-07 23:47:41 +00:00
|
|
|
|
2008-11-09 23:56:37 +00:00
|
|
|
if (DebugFrameMaps) {
|
|
|
|
fprintf(stderr, " orig roots at ip %p: ", reinterpret_cast<void*>
|
|
|
|
(p->address->value()));
|
2008-11-25 23:01:30 +00:00
|
|
|
printSet(p->map[0], frameMapSizeInWords(t, context->method));
|
2008-11-09 23:56:37 +00:00
|
|
|
fprintf(stderr, "\n");
|
|
|
|
|
|
|
|
fprintf(stderr, "final roots at ip %p: ", reinterpret_cast<void*>
|
|
|
|
(p->address->value()));
|
|
|
|
}
|
|
|
|
|
2009-04-27 01:53:42 +00:00
|
|
|
for (unsigned j = 0; j < p->argumentIndex; ++j) {
|
|
|
|
if (getBit(p->map, j)) {
|
2008-11-09 23:56:37 +00:00
|
|
|
if (DebugFrameMaps) {
|
|
|
|
fprintf(stderr, "1");
|
|
|
|
}
|
|
|
|
setBit(t, map, context->traceLogCount, size, i, j);
|
2008-04-13 19:48:20 +00:00
|
|
|
} else {
|
2008-11-09 23:56:37 +00:00
|
|
|
if (DebugFrameMaps) {
|
|
|
|
fprintf(stderr, "_");
|
|
|
|
}
|
|
|
|
clearBit(t, map, context->traceLogCount, size, i, j);
|
2008-04-07 23:47:41 +00:00
|
|
|
}
|
|
|
|
}
|
2008-11-09 23:56:37 +00:00
|
|
|
|
|
|
|
if (DebugFrameMaps) {
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2008-04-13 19:48:20 +00:00
|
|
|
set(t, methodCode(t, context->method), CodePool, map);
|
|
|
|
}
|
2007-12-31 22:40:56 +00:00
|
|
|
|
2008-11-11 15:20:49 +00:00
|
|
|
logCompile
|
|
|
|
(t, start, codeSize,
|
|
|
|
reinterpret_cast<const char*>
|
|
|
|
(&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)),
|
|
|
|
reinterpret_cast<const char*>
|
|
|
|
(&byteArrayBody(t, methodName(t, context->method), 0)),
|
|
|
|
reinterpret_cast<const char*>
|
|
|
|
(&byteArrayBody(t, methodSpec(t, context->method), 0)));
|
2008-02-11 17:21:41 +00:00
|
|
|
|
|
|
|
// for debugging:
|
2009-04-26 22:06:15 +00:00
|
|
|
if (false and
|
2008-02-11 17:21:41 +00:00
|
|
|
strcmp
|
|
|
|
(reinterpret_cast<const char*>
|
|
|
|
(&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)),
|
2009-04-26 22:06:15 +00:00
|
|
|
"java/lang/Throwable") == 0 and
|
2008-02-11 17:21:41 +00:00
|
|
|
strcmp
|
|
|
|
(reinterpret_cast<const char*>
|
|
|
|
(&byteArrayBody(t, methodName(t, context->method), 0)),
|
2009-04-26 22:06:15 +00:00
|
|
|
"printStackTrace") == 0)
|
2008-02-11 17:21:41 +00:00
|
|
|
{
|
2009-03-03 01:40:06 +00:00
|
|
|
trap();
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2007-09-27 22:20:54 +00:00
|
|
|
|
2009-03-09 14:26:23 +00:00
|
|
|
syncInstructionCache(start, codeSize);
|
|
|
|
|
2008-11-23 23:58:01 +00:00
|
|
|
return start;
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2008-11-23 23:58:01 +00:00
|
|
|
uint8_t*
|
|
|
|
compile(MyThread* t, Allocator* allocator, Context* context)
|
2007-12-09 22:45:43 +00:00
|
|
|
{
|
2008-02-11 17:21:41 +00:00
|
|
|
Compiler* c = context->compiler;
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2008-01-08 21:23:49 +00:00
|
|
|
// fprintf(stderr, "compiling %s.%s%s\n",
|
|
|
|
// &byteArrayBody(t, className(t, methodClass(t, context->method)), 0),
|
|
|
|
// &byteArrayBody(t, methodName(t, context->method), 0),
|
|
|
|
// &byteArrayBody(t, methodSpec(t, context->method), 0));
|
|
|
|
|
2007-12-31 22:40:56 +00:00
|
|
|
unsigned footprint = methodParameterFootprint(t, context->method);
|
2008-01-20 18:55:08 +00:00
|
|
|
unsigned locals = localSize(t, context->method);
|
2008-08-23 18:04:36 +00:00
|
|
|
c->init(codeLength(t, methodCode(t, context->method)), footprint, locals,
|
2008-09-28 19:00:52 +00:00
|
|
|
alignedFrameSize(t, context->method));
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
uint8_t stackMap[codeMaxStack(t, methodCode(t, context->method))];
|
2008-01-07 14:51:07 +00:00
|
|
|
Frame frame(context, stackMap);
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2009-05-15 02:08:01 +00:00
|
|
|
unsigned index = methodParameterFootprint(t, context->method);
|
2008-01-07 16:01:35 +00:00
|
|
|
if ((methodFlags(t, context->method) & ACC_STATIC) == 0) {
|
2009-05-15 02:08:01 +00:00
|
|
|
frame.set(--index, Frame::Object);
|
|
|
|
c->initLocal(1, index);
|
2008-01-07 14:51:07 +00:00
|
|
|
}
|
|
|
|
|
2008-01-07 16:01:35 +00:00
|
|
|
for (MethodSpecIterator it
|
|
|
|
(t, reinterpret_cast<const char*>
|
|
|
|
(&byteArrayBody(t, methodSpec(t, context->method), 0)));
|
|
|
|
it.hasNext();)
|
|
|
|
{
|
2008-01-07 14:51:07 +00:00
|
|
|
switch (*it.next()) {
|
|
|
|
case 'L':
|
|
|
|
case '[':
|
2009-05-15 02:08:01 +00:00
|
|
|
frame.set(--index, Frame::Object);
|
|
|
|
c->initLocal(1, index);
|
2008-01-07 14:51:07 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'J':
|
|
|
|
case 'D':
|
2009-05-15 02:08:01 +00:00
|
|
|
frame.set(--index, Frame::Long);
|
|
|
|
frame.set(--index, Frame::Long);
|
|
|
|
c->initLocal(2, index);
|
2008-01-07 14:51:07 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2009-05-15 02:08:01 +00:00
|
|
|
frame.set(--index, Frame::Integer);
|
|
|
|
c->initLocal(1, index);
|
2008-01-07 14:51:07 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-09 23:56:37 +00:00
|
|
|
handleEntrance(t, &frame);
|
|
|
|
|
2008-09-13 21:09:26 +00:00
|
|
|
Compiler::State* state = c->saveState();
|
|
|
|
|
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
|
|
|
|
2008-03-05 21:44:17 +00:00
|
|
|
context->dirtyRoots = false;
|
2009-04-27 01:53:42 +00:00
|
|
|
unsigned eventIndex = calculateFrameMaps(t, context, 0, 0);
|
2008-01-07 14:51:07 +00:00
|
|
|
|
2007-12-31 22:40:56 +00:00
|
|
|
object eht = codeExceptionHandlerTable(t, methodCode(t, context->method));
|
2007-12-09 22:45:43 +00:00
|
|
|
if (eht) {
|
|
|
|
PROTECT(t, eht);
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2008-01-26 00:17:27 +00:00
|
|
|
unsigned visitCount = exceptionHandlerTableLength(t, eht);
|
2009-03-08 01:23:28 +00:00
|
|
|
|
2008-01-26 00:17:27 +00:00
|
|
|
bool visited[visitCount];
|
2009-03-08 01:23:28 +00:00
|
|
|
memset(visited, 0, visitCount * sizeof(bool));
|
2008-01-26 00:17:27 +00:00
|
|
|
|
|
|
|
while (visitCount) {
|
|
|
|
bool progress = false;
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < exceptionHandlerTableLength(t, eht); ++i) {
|
2008-09-13 21:09:26 +00:00
|
|
|
c->restoreState(state);
|
|
|
|
|
2008-01-26 00:17:27 +00:00
|
|
|
ExceptionHandler* eh = exceptionHandlerTableBody(t, eht, i);
|
|
|
|
unsigned start = exceptionHandlerStart(eh);
|
|
|
|
|
2009-03-08 01:23:28 +00:00
|
|
|
if ((not visited[i]) and context->visitTable[start]) {
|
2008-01-26 00:17:27 +00:00
|
|
|
-- visitCount;
|
|
|
|
visited[i] = true;
|
|
|
|
progress = true;
|
|
|
|
|
2008-02-11 17:21:41 +00:00
|
|
|
uint8_t stackMap[codeMaxStack(t, methodCode(t, context->method))];
|
2008-01-26 00:17:27 +00:00
|
|
|
Frame frame2(&frame, stackMap);
|
|
|
|
|
|
|
|
uintptr_t* roots = context->rootTable
|
|
|
|
+ (start * frameMapSizeInWords(t, context->method));
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < localSize(t, context->method); ++ i) {
|
|
|
|
if (getBit(roots, i)) {
|
2008-02-11 17:21:41 +00:00
|
|
|
frame2.set(i, Frame::Object);
|
2008-01-26 00:17:27 +00:00
|
|
|
} else {
|
2008-02-11 17:21:41 +00:00
|
|
|
frame2.set(i, Frame::Integer);
|
2008-01-26 00:17:27 +00:00
|
|
|
}
|
|
|
|
}
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2008-01-26 00:17:27 +00:00
|
|
|
for (unsigned i = 1;
|
|
|
|
i < codeMaxStack(t, methodCode(t, context->method));
|
|
|
|
++i)
|
|
|
|
{
|
2008-02-11 17:21:41 +00:00
|
|
|
frame2.set(localSize(t, context->method) + i, Frame::Integer);
|
2008-01-26 00:17:27 +00:00
|
|
|
}
|
2008-01-07 14:51:07 +00:00
|
|
|
|
2008-09-25 00:48:32 +00:00
|
|
|
compile(t, &frame2, exceptionHandlerIp(eh), start);
|
2008-01-26 00:17:27 +00:00
|
|
|
if (UNLIKELY(t->exception)) return 0;
|
2008-01-20 23:03:28 +00:00
|
|
|
|
2009-04-27 01:53:42 +00:00
|
|
|
eventIndex = calculateFrameMaps(t, context, 0, eventIndex);
|
2008-01-26 00:17:27 +00:00
|
|
|
}
|
2008-01-20 23:03:28 +00:00
|
|
|
}
|
|
|
|
|
2008-01-26 00:17:27 +00:00
|
|
|
assert(t, progress);
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
|
|
|
}
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2008-03-05 21:44:17 +00:00
|
|
|
while (context->dirtyRoots) {
|
|
|
|
context->dirtyRoots = false;
|
2009-04-27 01:53:42 +00:00
|
|
|
calculateFrameMaps(t, context, 0, 0);
|
2008-03-05 21:44:17 +00:00
|
|
|
}
|
2008-01-20 23:03:28 +00:00
|
|
|
|
2008-11-23 23:58:01 +00:00
|
|
|
return finish(t, allocator, context);
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2008-11-29 23:08:14 +00:00
|
|
|
void
|
|
|
|
updateCall(MyThread* t, UnaryOperation op, bool assertAlignment,
|
|
|
|
void* returnAddress, void* target)
|
|
|
|
{
|
2009-02-09 23:22:01 +00:00
|
|
|
t->arch->updateCall(op, assertAlignment, returnAddress, target);
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void*
|
2009-04-07 00:34:12 +00:00
|
|
|
compileMethod2(MyThread* t, void* ip)
|
2007-12-09 22:45:43 +00:00
|
|
|
{
|
2009-03-31 20:15:08 +00:00
|
|
|
object node = findCallNode(t, ip);
|
2008-04-07 23:47:41 +00:00
|
|
|
object target = callNodeTarget(t, node);
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
if (LIKELY(t->exception == 0)) {
|
2009-04-27 01:53:42 +00:00
|
|
|
PROTECT(t, node);
|
|
|
|
PROTECT(t, target);
|
|
|
|
|
|
|
|
t->trace->targetMethod = target;
|
|
|
|
|
2009-04-05 21:42:10 +00:00
|
|
|
compile(t, codeAllocator(t), 0, target);
|
2009-04-27 01:53:42 +00:00
|
|
|
|
|
|
|
t->trace->targetMethod = 0;
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2007-10-13 21:48:40 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
if (UNLIKELY(t->exception)) {
|
2007-12-16 22:41:07 +00:00
|
|
|
return 0;
|
2007-12-09 22:45:43 +00:00
|
|
|
} else {
|
2008-12-02 02:38:00 +00:00
|
|
|
void* address = reinterpret_cast<void*>(methodAddress(t, target));
|
2009-04-07 00:34:12 +00:00
|
|
|
uint8_t* updateIp = static_cast<uint8_t*>(ip);
|
2009-04-05 21:42:10 +00:00
|
|
|
|
2009-04-22 01:39:25 +00:00
|
|
|
updateCall(t, (callNodeFlags(t, node) & TraceElement::TailCall)
|
|
|
|
? Jump : Call, true, updateIp, address);
|
2009-04-05 21:42:10 +00:00
|
|
|
|
2008-11-23 23:58:01 +00:00
|
|
|
return address;
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
|
|
|
}
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2009-02-28 21:20:43 +00:00
|
|
|
uint64_t
|
2007-12-16 22:41:07 +00:00
|
|
|
compileMethod(MyThread* t)
|
|
|
|
{
|
2009-04-07 00:34:12 +00:00
|
|
|
void* ip;
|
2009-03-31 20:15:08 +00:00
|
|
|
if (t->tailAddress) {
|
|
|
|
ip = t->tailAddress;
|
|
|
|
t->tailAddress = 0;
|
|
|
|
} else {
|
|
|
|
ip = t->arch->frameIp(t->stack);
|
|
|
|
}
|
|
|
|
|
|
|
|
void* r = compileMethod2(t, ip);
|
|
|
|
|
|
|
|
if (UNLIKELY(t->exception)) {
|
|
|
|
unwind(t);
|
|
|
|
} else {
|
|
|
|
return reinterpret_cast<uintptr_t>(r);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-04-05 21:42:10 +00:00
|
|
|
void*
|
|
|
|
compileVirtualMethod2(MyThread* t, object class_, unsigned index)
|
|
|
|
{
|
2009-04-27 01:53:42 +00:00
|
|
|
// If class_ has BootstrapFlag set, that means its vtable is not yet
|
|
|
|
// available. However, we must set t->trace->targetMethod to an
|
|
|
|
// appropriate method to ensure we can accurately scan the stack for
|
|
|
|
// GC roots. We find such a method by looking for a superclass with
|
|
|
|
// a vtable and using it instead:
|
|
|
|
|
|
|
|
object c = class_;
|
|
|
|
while (classVmFlags(t, c) & BootstrapFlag) {
|
|
|
|
c = classSuper(t, c);
|
|
|
|
}
|
|
|
|
t->trace->targetMethod = arrayBody(t, classVirtualTable(t, c), index);
|
|
|
|
|
2009-04-05 21:42:10 +00:00
|
|
|
PROTECT(t, class_);
|
|
|
|
|
|
|
|
object target = resolveTarget(t, class_, index);
|
2009-04-27 14:46:43 +00:00
|
|
|
PROTECT(t, target);
|
2009-04-05 21:42:10 +00:00
|
|
|
|
|
|
|
if (LIKELY(t->exception == 0)) {
|
|
|
|
compile(t, codeAllocator(t), 0, target);
|
|
|
|
}
|
|
|
|
|
2009-04-27 01:53:42 +00:00
|
|
|
t->trace->targetMethod = 0;
|
|
|
|
|
2009-04-05 21:42:10 +00:00
|
|
|
if (UNLIKELY(t->exception)) {
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
void* address = reinterpret_cast<void*>(methodAddress(t, target));
|
2009-04-25 23:52:08 +00:00
|
|
|
if (methodFlags(t, target) & ACC_NATIVE) {
|
|
|
|
t->trace->nativeMethod = target;
|
|
|
|
} else {
|
2009-04-05 21:42:10 +00:00
|
|
|
classVtable(t, class_, methodOffset(t, target)) = address;
|
|
|
|
}
|
|
|
|
return address;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
compileVirtualMethod(MyThread* t)
|
|
|
|
{
|
2009-05-03 20:57:11 +00:00
|
|
|
object class_ = objectClass(t, static_cast<object>(t->virtualCallTarget));
|
|
|
|
t->virtualCallTarget = 0;
|
2009-04-05 21:42:10 +00:00
|
|
|
|
|
|
|
unsigned index = t->virtualCallIndex;
|
|
|
|
t->virtualCallIndex = 0;
|
|
|
|
|
|
|
|
void* r = compileVirtualMethod2(t, class_, index);
|
|
|
|
|
|
|
|
if (UNLIKELY(t->exception)) {
|
|
|
|
unwind(t);
|
|
|
|
} else {
|
|
|
|
return reinterpret_cast<uintptr_t>(r);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-05 01:04:17 +00:00
|
|
|
void
|
|
|
|
resolveNative(MyThread* t, object method)
|
|
|
|
{
|
|
|
|
PROTECT(t, method);
|
|
|
|
|
|
|
|
assert(t, methodFlags(t, method) & ACC_NATIVE);
|
|
|
|
|
|
|
|
initClass(t, methodClass(t, method));
|
|
|
|
|
|
|
|
if (LIKELY(t->exception == 0)
|
|
|
|
and methodCompiled(t, method) == defaultThunk(t))
|
|
|
|
{
|
|
|
|
void* function = resolveNativeMethod(t, method);
|
|
|
|
if (UNLIKELY(function == 0)) {
|
|
|
|
object message = makeString
|
|
|
|
(t, "%s.%s%s",
|
|
|
|
&byteArrayBody(t, className(t, methodClass(t, method)), 0),
|
|
|
|
&byteArrayBody(t, methodName(t, method), 0),
|
|
|
|
&byteArrayBody(t, methodSpec(t, method), 0));
|
|
|
|
t->exception = makeUnsatisfiedLinkError(t, message);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ensure other threads see updated methodVmFlags before
|
|
|
|
// methodCompiled, since we don't want them using the slow calling
|
|
|
|
// convention on a function that expects the fast calling
|
|
|
|
// convention:
|
|
|
|
memoryBarrier();
|
|
|
|
|
|
|
|
methodCompiled(t, method) = reinterpret_cast<uintptr_t>(function);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
2009-05-03 20:57:11 +00:00
|
|
|
invokeNativeFast(MyThread* t, object method)
|
|
|
|
{
|
|
|
|
return reinterpret_cast<FastNativeFunction>(methodCompiled(t, method))
|
|
|
|
(t, method,
|
|
|
|
static_cast<uintptr_t*>(t->stack)
|
|
|
|
+ t->arch->frameFooterSize()
|
|
|
|
+ t->arch->frameReturnAddressSize());
|
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
uint64_t
|
2009-05-03 20:57:11 +00:00
|
|
|
invokeNativeSlow(MyThread* t, object method)
|
2007-12-09 22:45:43 +00:00
|
|
|
{
|
|
|
|
PROTECT(t, method);
|
2007-09-26 23:23:03 +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;
|
|
|
|
if (methodFlags(t, method) & ACC_STATIC) {
|
|
|
|
++ footprint;
|
|
|
|
}
|
2008-01-03 19:49:07 +00:00
|
|
|
unsigned count = methodParameterCount(t, method) + 2;
|
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)
|
2009-05-03 20:57:11 +00:00
|
|
|
+ t->arch->frameFooterSize()
|
|
|
|
+ t->arch->frameReturnAddressSize();
|
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 {
|
2009-05-03 20:57:11 +00:00
|
|
|
args[argOffset++] = reinterpret_cast<uintptr_t>(sp++);
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
|
|
|
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:
|
2009-05-03 20:57:11 +00:00
|
|
|
args[argOffset++] = *(sp++);
|
2007-12-09 22:45:43 +00:00
|
|
|
break;
|
2007-10-22 14:14:05 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
case INT64_TYPE:
|
|
|
|
case DOUBLE_TYPE: {
|
2009-05-03 20:57:11 +00:00
|
|
|
memcpy(args + argOffset, sp, 8);
|
2007-12-18 02:09:32 +00:00
|
|
|
argOffset += (8 / BytesPerWord);
|
2009-05-03 20:57:11 +00:00
|
|
|
sp += 2;
|
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: {
|
2007-12-20 00:02:32 +00:00
|
|
|
if (*sp) {
|
|
|
|
args[argOffset++] = reinterpret_cast<uintptr_t>(sp);
|
|
|
|
} else {
|
|
|
|
args[argOffset++] = 0;
|
|
|
|
}
|
2009-05-03 20:57:11 +00:00
|
|
|
++ sp;
|
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
|
|
|
default: abort(t);
|
2007-10-03 00:22:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-12-02 02:38:00 +00:00
|
|
|
void* function = reinterpret_cast<void*>(methodCompiled(t, method));
|
2007-12-23 18:09:41 +00:00
|
|
|
unsigned returnCode = methodReturnCode(t, method);
|
|
|
|
unsigned returnType = fieldType(t, returnCode);
|
2007-12-09 22:45:43 +00:00
|
|
|
uint64_t result;
|
2008-01-20 22:05:59 +00:00
|
|
|
|
2007-12-26 23:59:55 +00:00
|
|
|
if (DebugNatives) {
|
2007-12-09 22:45:43 +00:00
|
|
|
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
|
|
|
|
2008-01-11 17:49:11 +00:00
|
|
|
if (methodFlags(t, method) & ACC_SYNCHRONIZED) {
|
|
|
|
if (methodFlags(t, method) & ACC_STATIC) {
|
|
|
|
acquire(t, methodClass(t, method));
|
|
|
|
} else {
|
|
|
|
acquire(t, *reinterpret_cast<object*>(args[0]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-02-01 21:17:54 +00:00
|
|
|
Reference* reference = t->reference;
|
|
|
|
|
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,
|
2008-01-03 19:49:07 +00:00
|
|
|
count,
|
2007-12-09 22:45:43 +00:00
|
|
|
footprint * BytesPerWord,
|
|
|
|
returnType);
|
2007-09-24 01:39:03 +00:00
|
|
|
}
|
2007-09-25 23:53:11 +00:00
|
|
|
|
2008-01-11 17:49:11 +00:00
|
|
|
if (methodFlags(t, method) & ACC_SYNCHRONIZED) {
|
|
|
|
if (methodFlags(t, method) & ACC_STATIC) {
|
|
|
|
release(t, methodClass(t, method));
|
|
|
|
} else {
|
|
|
|
release(t, *reinterpret_cast<object*>(args[0]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-12-26 23:59:55 +00:00
|
|
|
if (DebugNatives) {
|
2007-12-09 22:45:43 +00:00
|
|
|
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-23 18:09:41 +00:00
|
|
|
if (LIKELY(t->exception == 0)) {
|
|
|
|
switch (returnCode) {
|
|
|
|
case ByteField:
|
|
|
|
case BooleanField:
|
2008-02-01 21:17:54 +00:00
|
|
|
result = static_cast<int8_t>(result);
|
|
|
|
break;
|
2007-12-23 18:09:41 +00:00
|
|
|
|
|
|
|
case CharField:
|
2008-02-01 21:17:54 +00:00
|
|
|
result = static_cast<uint16_t>(result);
|
|
|
|
break;
|
2007-12-23 18:09:41 +00:00
|
|
|
|
|
|
|
case ShortField:
|
2008-02-01 21:17:54 +00:00
|
|
|
result = static_cast<int16_t>(result);
|
|
|
|
break;
|
2007-12-23 18:09:41 +00:00
|
|
|
|
|
|
|
case FloatField:
|
|
|
|
case IntField:
|
2008-02-01 21:17:54 +00:00
|
|
|
result = static_cast<int32_t>(result);
|
|
|
|
break;
|
2007-12-18 02:09:32 +00:00
|
|
|
|
2007-12-23 18:09:41 +00:00
|
|
|
case LongField:
|
|
|
|
case DoubleField:
|
2008-02-01 21:17:54 +00:00
|
|
|
break;
|
2007-12-23 18:09:41 +00:00
|
|
|
|
|
|
|
case ObjectField:
|
2008-02-01 21:17:54 +00:00
|
|
|
result = static_cast<uintptr_t>(result) ? *reinterpret_cast<uintptr_t*>
|
2007-12-23 18:09:41 +00:00
|
|
|
(static_cast<uintptr_t>(result)) : 0;
|
2008-02-01 21:17:54 +00:00
|
|
|
break;
|
2007-12-23 18:09:41 +00:00
|
|
|
|
|
|
|
case VoidField:
|
2008-02-01 21:17:54 +00:00
|
|
|
result = 0;
|
|
|
|
break;
|
2007-12-23 18:09:41 +00:00
|
|
|
|
|
|
|
default: abort(t);
|
2007-12-18 02:09:32 +00:00
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
} else {
|
2008-02-01 21:17:54 +00:00
|
|
|
result = 0;
|
2007-10-03 00:22:48 +00:00
|
|
|
}
|
2008-02-01 21:17:54 +00:00
|
|
|
|
|
|
|
while (t->reference != reference) {
|
|
|
|
dispose(t, t->reference);
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2009-05-03 20:57:11 +00:00
|
|
|
|
|
|
|
uint64_t
|
|
|
|
invokeNative2(MyThread* t, object method)
|
|
|
|
{
|
|
|
|
if (methodVmFlags(t, method) & FastNative) {
|
|
|
|
return invokeNativeFast(t, method);
|
|
|
|
} else {
|
|
|
|
return invokeNativeSlow(t, method);
|
|
|
|
}
|
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
|
2008-07-05 20:21:13 +00:00
|
|
|
uint64_t
|
2007-12-09 22:45:43 +00:00
|
|
|
invokeNative(MyThread* t)
|
|
|
|
{
|
2008-04-07 23:47:41 +00:00
|
|
|
if (t->trace->nativeMethod == 0) {
|
2009-04-07 00:34:12 +00:00
|
|
|
void* ip;
|
2009-03-31 20:15:08 +00:00
|
|
|
if (t->tailAddress) {
|
|
|
|
ip = t->tailAddress;
|
|
|
|
t->tailAddress = 0;
|
|
|
|
} else {
|
|
|
|
ip = t->arch->frameIp(t->stack);
|
|
|
|
}
|
|
|
|
|
|
|
|
object node = findCallNode(t, ip);
|
2008-04-23 16:33:31 +00:00
|
|
|
object target = callNodeTarget(t, node);
|
2009-03-31 20:15:08 +00:00
|
|
|
if (callNodeFlags(t, node) & TraceElement::VirtualCall) {
|
2008-04-23 16:33:31 +00:00
|
|
|
target = resolveTarget(t, t->stack, target);
|
2008-04-01 17:37:59 +00:00
|
|
|
}
|
2008-04-23 16:33:31 +00:00
|
|
|
t->trace->nativeMethod = target;
|
2008-01-11 22:16:24 +00:00
|
|
|
}
|
2008-04-01 17:37:59 +00:00
|
|
|
|
2009-03-31 20:15:08 +00:00
|
|
|
assert(t, t->tailAddress == 0);
|
|
|
|
|
2007-12-17 22:38:59 +00:00
|
|
|
uint64_t result = 0;
|
2007-10-03 00:22:48 +00:00
|
|
|
|
2009-04-27 01:53:42 +00:00
|
|
|
t->trace->targetMethod = t->trace->nativeMethod;
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
if (LIKELY(t->exception == 0)) {
|
2009-05-03 20:57:11 +00:00
|
|
|
resolveNative(t, t->trace->nativeMethod);
|
|
|
|
|
|
|
|
if (LIKELY(t->exception == 0)) {
|
|
|
|
result = invokeNative2(t, t->trace->nativeMethod);
|
|
|
|
}
|
2007-10-03 00:22:48 +00:00
|
|
|
}
|
|
|
|
|
2009-05-17 00:39:08 +00:00
|
|
|
unsigned parameterFootprint = methodParameterFootprint
|
|
|
|
(t, t->trace->targetMethod);
|
|
|
|
|
2009-04-27 01:53:42 +00:00
|
|
|
t->trace->targetMethod = 0;
|
2008-04-10 23:48:28 +00:00
|
|
|
t->trace->nativeMethod = 0;
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
if (UNLIKELY(t->exception)) {
|
|
|
|
unwind(t);
|
|
|
|
} else {
|
2009-05-17 00:39:08 +00:00
|
|
|
if (t->arch->argumentFootprint(parameterFootprint)
|
|
|
|
> t->arch->stackAlignmentInWords())
|
|
|
|
{
|
|
|
|
t->stack = static_cast<uintptr_t*>(t->stack)
|
|
|
|
+ (t->arch->argumentFootprint(parameterFootprint)
|
|
|
|
- t->arch->stackAlignmentInWords());
|
|
|
|
}
|
|
|
|
|
|
|
|
t->stack = static_cast<uintptr_t*>(t->stack)
|
|
|
|
+ t->arch->frameReturnAddressSize();
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
return result;
|
2007-10-03 00:22:48 +00:00
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2008-04-10 23:48:28 +00:00
|
|
|
|
2008-04-07 23:47:41 +00:00
|
|
|
unsigned
|
|
|
|
frameMapIndex(MyThread* t, object method, int32_t offset)
|
|
|
|
{
|
|
|
|
object map = codePool(t, methodCode(t, method));
|
2008-04-11 21:00:18 +00:00
|
|
|
unsigned mapSize = frameObjectMapSize(t, method, map);
|
2008-04-07 23:47:41 +00:00
|
|
|
unsigned indexSize = intArrayLength(t, map) - mapSize;
|
|
|
|
|
|
|
|
unsigned bottom = 0;
|
|
|
|
unsigned top = indexSize;
|
|
|
|
for (unsigned span = top - bottom; span; span = top - bottom) {
|
|
|
|
unsigned middle = bottom + (span / 2);
|
|
|
|
int32_t v = intArrayBody(t, map, middle);
|
|
|
|
|
|
|
|
if (offset == v) {
|
2009-04-27 14:46:43 +00:00
|
|
|
return (indexSize * 32) + (frameMapSizeInBits(t, method) * middle);
|
2008-04-07 23:47:41 +00:00
|
|
|
} else if (offset < v) {
|
|
|
|
top = middle;
|
|
|
|
} else {
|
|
|
|
bottom = middle + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
abort(t);
|
|
|
|
}
|
2007-10-03 00:22:48 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
void
|
2009-04-26 21:55:35 +00:00
|
|
|
visitStackAndLocals(MyThread* t, Heap::Visitor* v, void* frame, object method,
|
2009-04-27 01:53:42 +00:00
|
|
|
void* ip)
|
2007-12-09 22:45:43 +00:00
|
|
|
{
|
2009-04-27 14:46:43 +00:00
|
|
|
unsigned count = frameMapSizeInBits(t, method);
|
2009-04-26 21:55:35 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
if (count) {
|
2008-04-07 23:47:41 +00:00
|
|
|
object map = codePool(t, methodCode(t, method));
|
|
|
|
int index = frameMapIndex
|
|
|
|
(t, method, difference
|
2008-12-02 02:38:00 +00:00
|
|
|
(ip, reinterpret_cast<void*>(methodAddress(t, method))));
|
2007-09-29 20:24:14 +00:00
|
|
|
|
2009-04-26 21:55:35 +00:00
|
|
|
void* stack = stackForFrame(t, frame, method);
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
for (unsigned i = 0; i < count; ++i) {
|
2008-04-07 23:47:41 +00:00
|
|
|
int j = index + i;
|
|
|
|
if ((intArrayBody(t, map, j / 32)
|
|
|
|
& (static_cast<int32_t>(1) << (j % 32))))
|
|
|
|
{
|
2008-08-18 15:23:01 +00:00
|
|
|
v->visit(localObject(t, stack, method, i));
|
2007-10-17 01:21:35 +00:00
|
|
|
}
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-04-27 01:53:42 +00:00
|
|
|
void
|
2009-05-15 02:08:01 +00:00
|
|
|
visitArgument(MyThread* t, Heap::Visitor* v, void* stack, unsigned index)
|
2009-04-27 01:53:42 +00:00
|
|
|
{
|
|
|
|
v->visit(static_cast<object*>(stack)
|
2009-05-15 02:08:01 +00:00
|
|
|
+ index
|
2009-04-27 01:53:42 +00:00
|
|
|
+ t->arch->frameReturnAddressSize()
|
|
|
|
+ t->arch->frameFooterSize());
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
visitArguments(MyThread* t, Heap::Visitor* v, void* stack, object method)
|
|
|
|
{
|
|
|
|
unsigned index = 0;
|
|
|
|
|
|
|
|
if ((methodFlags(t, method) & ACC_STATIC) == 0) {
|
2009-05-15 02:08:01 +00:00
|
|
|
visitArgument(t, v, stack, index++);
|
2009-04-27 01:53:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (MethodSpecIterator it
|
|
|
|
(t, reinterpret_cast<const char*>
|
|
|
|
(&byteArrayBody(t, methodSpec(t, method), 0)));
|
|
|
|
it.hasNext();)
|
|
|
|
{
|
|
|
|
switch (*it.next()) {
|
|
|
|
case 'L':
|
|
|
|
case '[':
|
2009-05-15 02:08:01 +00:00
|
|
|
visitArgument(t, v, stack, index++);
|
2009-04-27 01:53:42 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'J':
|
|
|
|
case 'D':
|
|
|
|
index += 2;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
++ index;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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-30 22:24:48 +00:00
|
|
|
void* ip = t->ip;
|
2007-12-09 22:45:43 +00:00
|
|
|
void* base = t->base;
|
2008-08-17 19:32:40 +00:00
|
|
|
void* stack = t->stack;
|
|
|
|
if (ip == 0) {
|
2008-08-18 15:23:01 +00:00
|
|
|
ip = t->arch->frameIp(stack);
|
2007-12-30 22:24:48 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
MyThread::CallTrace* trace = t->trace;
|
2009-04-27 01:53:42 +00:00
|
|
|
object targetMethod = (trace ? trace->targetMethod : 0);
|
2007-12-09 22:45:43 +00:00
|
|
|
|
2007-12-16 22:41:07 +00:00
|
|
|
while (stack) {
|
2009-05-17 23:43:48 +00:00
|
|
|
if (targetMethod) {
|
|
|
|
visitArguments(t, v, stack, targetMethod);
|
|
|
|
targetMethod = 0;
|
|
|
|
}
|
|
|
|
|
2008-04-07 23:47:41 +00:00
|
|
|
object method = methodForIp(t, ip);
|
|
|
|
if (method) {
|
|
|
|
PROTECT(t, method);
|
2008-01-07 16:01:35 +00:00
|
|
|
|
2009-04-27 01:53:42 +00:00
|
|
|
t->arch->nextFrame(&stack, &base);
|
2008-01-07 14:51:07 +00:00
|
|
|
|
2009-04-27 01:53:42 +00:00
|
|
|
visitStackAndLocals(t, v, stack, method, ip);
|
2007-12-09 22:45:43 +00:00
|
|
|
|
2008-08-18 15:23:01 +00:00
|
|
|
ip = t->arch->frameIp(stack);
|
2007-12-09 22:45:43 +00:00
|
|
|
} else if (trace) {
|
2008-08-17 19:32:40 +00:00
|
|
|
stack = trace->stack;
|
2007-12-09 22:45:43 +00:00
|
|
|
base = trace->base;
|
2008-08-18 15:23:01 +00:00
|
|
|
ip = t->arch->frameIp(stack);
|
2007-12-09 22:45:43 +00:00
|
|
|
trace = trace->next;
|
2009-04-27 01:53:42 +00:00
|
|
|
|
|
|
|
if (trace) {
|
|
|
|
targetMethod = trace->targetMethod;
|
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
2008-07-12 00:11:13 +00:00
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2009-05-03 20:57:11 +00:00
|
|
|
void
|
|
|
|
walkContinuationBody(MyThread* t, Heap::Walker* w, object c, int start)
|
|
|
|
{
|
2009-05-17 23:43:48 +00:00
|
|
|
const int BodyOffset = ContinuationBody / BytesPerWord;
|
2009-05-03 20:57:11 +00:00
|
|
|
|
2009-05-05 01:04:17 +00:00
|
|
|
object method = static_cast<object>
|
|
|
|
(t->m->heap->follow(continuationMethod(t, c)));
|
2009-05-17 23:43:48 +00:00
|
|
|
int count = frameMapSizeInBits(t, method);
|
2009-05-03 20:57:11 +00:00
|
|
|
|
|
|
|
if (count) {
|
2009-05-17 23:43:48 +00:00
|
|
|
int stack = BodyOffset
|
|
|
|
+ (continuationFramePointerOffset(t, c) / BytesPerWord)
|
|
|
|
- t->arch->framePointerOffset()
|
|
|
|
- stackOffsetFromFrame(t, method);
|
|
|
|
|
|
|
|
int first = stack + localOffsetFromStack(t, count - 1, method);
|
|
|
|
if (start > first) {
|
|
|
|
count -= start - first;
|
|
|
|
}
|
|
|
|
|
2009-05-03 20:57:11 +00:00
|
|
|
object map = codePool(t, methodCode(t, method));
|
|
|
|
int index = frameMapIndex
|
|
|
|
(t, method, difference
|
|
|
|
(continuationAddress(t, c),
|
|
|
|
reinterpret_cast<void*>(methodAddress(t, method))));
|
|
|
|
|
2009-05-17 23:43:48 +00:00
|
|
|
for (int i = count - 1; i >= 0; --i) {
|
2009-05-03 20:57:11 +00:00
|
|
|
int j = index + i;
|
|
|
|
if ((intArrayBody(t, map, j / 32)
|
|
|
|
& (static_cast<int32_t>(1) << (j % 32))))
|
|
|
|
{
|
2009-05-17 23:43:48 +00:00
|
|
|
if (not w->visit(stack + localOffsetFromStack(t, i, method))) {
|
2009-05-03 20:57:11 +00:00
|
|
|
return;
|
2009-05-17 23:43:48 +00:00
|
|
|
}
|
2009-05-03 20:57:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
callWithContinuation(MyThread* t, object method, object this_,
|
2009-05-17 00:39:08 +00:00
|
|
|
object continuation, void* base, void* stack,
|
|
|
|
unsigned oldArgumentFootprint)
|
2009-05-03 20:57:11 +00:00
|
|
|
{
|
|
|
|
t->trace->targetMethod = 0;
|
|
|
|
|
|
|
|
if (methodFlags(t, method) & ACC_NATIVE) {
|
|
|
|
t->trace->nativeMethod = method;
|
|
|
|
} else {
|
|
|
|
t->trace->nativeMethod = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
vmCallWithContinuation
|
2009-05-05 01:04:17 +00:00
|
|
|
(t, reinterpret_cast<void*>(methodAddress(t, method)),
|
|
|
|
this_,
|
|
|
|
continuation,
|
|
|
|
base,
|
2009-05-03 20:57:11 +00:00
|
|
|
static_cast<void**>(stack)
|
2009-05-17 00:39:08 +00:00
|
|
|
+ oldArgumentFootprint
|
2009-05-03 20:57:11 +00:00
|
|
|
- t->arch->argumentFootprint(methodParameterFootprint(t, method))
|
|
|
|
- t->arch->frameFooterSize()
|
2009-05-05 01:04:17 +00:00
|
|
|
- t->arch->frameReturnAddressSize());
|
2009-05-03 20:57:11 +00:00
|
|
|
}
|
|
|
|
|
2007-09-25 23:53:11 +00:00
|
|
|
class ArgumentList {
|
|
|
|
public:
|
2009-02-17 02:49:28 +00:00
|
|
|
ArgumentList(Thread* t, uintptr_t* array, unsigned size, bool* objectMask,
|
|
|
|
object this_, const char* spec, bool indirectObjects,
|
|
|
|
va_list arguments):
|
2007-09-25 23:53:11 +00:00
|
|
|
t(static_cast<MyThread*>(t)),
|
|
|
|
array(array),
|
|
|
|
objectMask(objectMask),
|
2009-02-17 02:49:28 +00:00
|
|
|
size(size),
|
2009-05-03 20:57:11 +00:00
|
|
|
position(0),
|
2007-10-12 17:56:43 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2009-02-17 02:49:28 +00:00
|
|
|
ArgumentList(Thread* t, uintptr_t* array, unsigned size, bool* objectMask,
|
|
|
|
object this_, const char* spec, object arguments):
|
2007-09-25 23:53:11 +00:00
|
|
|
t(static_cast<MyThread*>(t)),
|
|
|
|
array(array),
|
|
|
|
objectMask(objectMask),
|
2009-02-17 02:49:28 +00:00
|
|
|
size(size),
|
2009-05-03 20:57:11 +00:00
|
|
|
position(0),
|
2007-10-12 17:56:43 +00:00
|
|
|
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) {
|
2009-05-03 20:57:11 +00:00
|
|
|
assert(t, position < size);
|
2009-02-17 02:49:28 +00:00
|
|
|
|
2007-09-25 23:53:11 +00:00
|
|
|
array[position] = reinterpret_cast<uintptr_t>(v);
|
|
|
|
objectMask[position] = true;
|
2009-05-03 20:57:11 +00:00
|
|
|
++ position;
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
2007-10-12 22:06:33 +00:00
|
|
|
void addInt(uintptr_t v) {
|
2009-05-03 20:57:11 +00:00
|
|
|
assert(t, position < size);
|
2009-02-17 02:49:28 +00:00
|
|
|
|
2007-09-25 23:53:11 +00:00
|
|
|
array[position] = v;
|
|
|
|
objectMask[position] = false;
|
2009-05-03 20:57:11 +00:00
|
|
|
++ position;
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void addLong(uint64_t v) {
|
2009-05-03 20:57:11 +00:00
|
|
|
assert(t, position < size - 1);
|
2009-02-17 02:49:28 +00:00
|
|
|
|
2009-05-03 20:57:11 +00:00
|
|
|
memcpy(array + position, &v, 8);
|
2009-02-17 02:49:28 +00:00
|
|
|
|
2007-09-25 23:53:11 +00:00
|
|
|
objectMask[position] = false;
|
2007-12-23 20:06:24 +00:00
|
|
|
objectMask[position + 1] = false;
|
2009-05-03 20:57:11 +00:00
|
|
|
|
|
|
|
position += 2;
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
MyThread* t;
|
|
|
|
uintptr_t* array;
|
|
|
|
bool* objectMask;
|
2009-02-17 02:49:28 +00:00
|
|
|
unsigned size;
|
2007-09-25 23:53:11 +00:00
|
|
|
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) {
|
2009-05-17 23:43:48 +00:00
|
|
|
for (unsigned i = 0; i < list->position; ++i) {
|
2007-10-12 17:56:43 +00:00
|
|
|
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-12-30 22:24:48 +00:00
|
|
|
uint64_t result;
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2007-12-30 22:24:48 +00:00
|
|
|
{ MyThread::CallTrace trace(t);
|
|
|
|
|
2008-04-07 23:47:41 +00:00
|
|
|
if (methodFlags(t, method) & ACC_NATIVE) {
|
|
|
|
trace.nativeMethod = method;
|
|
|
|
}
|
|
|
|
|
2009-05-15 02:08:01 +00:00
|
|
|
assert(t, arguments->position == arguments->size);
|
2009-02-17 02:49:28 +00:00
|
|
|
|
2007-12-30 22:24:48 +00:00
|
|
|
result = vmInvoke
|
2008-12-02 02:38:00 +00:00
|
|
|
(t, reinterpret_cast<void*>(methodAddress(t, method)),
|
2009-05-15 02:08:01 +00:00
|
|
|
arguments->array,
|
|
|
|
arguments->position * BytesPerWord,
|
|
|
|
t->arch->alignFrameSize
|
2009-05-17 00:39:08 +00:00
|
|
|
(t->arch->argumentFootprint(arguments->position))
|
2009-04-25 23:33:42 +00:00
|
|
|
* BytesPerWord,
|
2009-02-17 02:49:28 +00:00
|
|
|
returnType);
|
2007-12-30 22:24:48 +00:00
|
|
|
}
|
2007-09-25 23:53:11 +00:00
|
|
|
|
2008-04-20 16:21:32 +00:00
|
|
|
if (t->exception) {
|
|
|
|
if (t->backupHeap) {
|
|
|
|
collect(t, Heap::MinorCollection);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
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:
|
2007-12-16 00:24:15 +00:00
|
|
|
r = reinterpret_cast<object>(result);
|
2007-09-25 23:53:11 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case VoidField:
|
|
|
|
r = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
abort(t);
|
|
|
|
};
|
2007-09-24 01:39:03 +00:00
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2007-12-30 22:24:48 +00:00
|
|
|
class SegFaultHandler: public System::SignalHandler {
|
|
|
|
public:
|
|
|
|
SegFaultHandler(): m(0) { }
|
|
|
|
|
2008-01-01 17:08:47 +00:00
|
|
|
virtual bool handleSignal(void** ip, void** base, void** stack,
|
|
|
|
void** thread)
|
|
|
|
{
|
2007-12-30 22:24:48 +00:00
|
|
|
MyThread* t = static_cast<MyThread*>(m->localThread->get());
|
2008-01-02 01:07:12 +00:00
|
|
|
if (t->state == Thread::ActiveState) {
|
2008-04-07 23:51:32 +00:00
|
|
|
object node = methodForIp(t, *ip);
|
2008-01-02 01:07:12 +00:00
|
|
|
if (node) {
|
2008-04-23 16:33:31 +00:00
|
|
|
void* oldIp = t->ip;
|
|
|
|
void* oldBase = t->base;
|
|
|
|
void* oldStack = t->stack;
|
|
|
|
|
2008-01-02 01:07:12 +00:00
|
|
|
t->ip = *ip;
|
|
|
|
t->base = *base;
|
2008-11-09 23:56:37 +00:00
|
|
|
t->stack = static_cast<void**>(*stack)
|
|
|
|
- t->arch->frameReturnAddressSize();
|
2008-04-09 19:08:13 +00:00
|
|
|
|
|
|
|
ensure(t, FixedSizeOfNullPointerException + traceSize(t));
|
|
|
|
|
2008-04-21 22:36:13 +00:00
|
|
|
t->tracing = true;
|
2008-01-02 01:07:12 +00:00
|
|
|
t->exception = makeNullPointerException(t);
|
2008-04-21 22:36:13 +00:00
|
|
|
t->tracing = false;
|
2008-01-02 01:07:12 +00:00
|
|
|
|
|
|
|
findUnwindTarget(t, ip, base, stack);
|
2008-04-23 16:33:31 +00:00
|
|
|
|
|
|
|
t->ip = oldIp;
|
|
|
|
t->base = oldBase;
|
|
|
|
t->stack = oldStack;
|
|
|
|
|
2008-01-02 01:07:12 +00:00
|
|
|
*thread = t;
|
|
|
|
return true;
|
|
|
|
}
|
2007-12-30 22:24:48 +00:00
|
|
|
}
|
2008-01-02 01:07:12 +00:00
|
|
|
return false;
|
2007-12-30 22:24:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Machine* m;
|
|
|
|
};
|
|
|
|
|
2008-12-02 02:38:00 +00:00
|
|
|
void
|
|
|
|
boot(MyThread* t, BootImage* image);
|
2008-11-23 23:58:01 +00:00
|
|
|
|
2008-04-22 15:31:40 +00:00
|
|
|
class MyProcessor;
|
|
|
|
|
2008-11-23 23:58:01 +00:00
|
|
|
void
|
|
|
|
compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p,
|
|
|
|
BootImage* image, uint8_t* imageBase);
|
|
|
|
|
2008-04-22 15:31:40 +00:00
|
|
|
MyProcessor*
|
|
|
|
processor(MyThread* t);
|
|
|
|
|
2007-09-25 23:53:11 +00:00
|
|
|
class MyProcessor: public Processor {
|
2007-09-24 01:39:03 +00:00
|
|
|
public:
|
2008-01-13 22:05:08 +00:00
|
|
|
MyProcessor(System* s, Allocator* allocator):
|
2007-09-25 23:53:11 +00:00
|
|
|
s(s),
|
2008-01-13 22:05:08 +00:00
|
|
|
allocator(allocator),
|
2008-05-31 22:14:27 +00:00
|
|
|
defaultThunk(0),
|
2009-04-07 00:34:12 +00:00
|
|
|
defaultVirtualThunk(0),
|
2008-05-31 22:14:27 +00:00
|
|
|
nativeThunk(0),
|
|
|
|
aioobThunk(0),
|
2008-04-07 23:47:41 +00:00
|
|
|
callTable(0),
|
|
|
|
callTableSize(0),
|
|
|
|
methodTree(0),
|
|
|
|
methodTreeSentinal(0),
|
2008-11-28 04:44:04 +00:00
|
|
|
objectPools(0),
|
2008-12-02 02:38:00 +00:00
|
|
|
staticTableArray(0),
|
2009-04-05 21:42:10 +00:00
|
|
|
virtualThunks(0),
|
2009-05-06 00:29:05 +00:00
|
|
|
receiveMethod(0),
|
2009-04-05 21:42:10 +00:00
|
|
|
codeAllocator(s, 0, 0)
|
2009-04-19 22:36:11 +00:00
|
|
|
{ }
|
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)
|
|
|
|
{
|
2008-04-13 18:15:04 +00:00
|
|
|
MyThread* t = new (m->heap->allocate(sizeof(MyThread)))
|
2008-08-18 15:23:01 +00:00
|
|
|
MyThread(m, javaThread, static_cast<MyThread*>(parent));
|
2007-10-25 22:06:05 +00:00
|
|
|
t->init();
|
2009-05-05 01:04:17 +00:00
|
|
|
|
2007-10-25 22:06:05 +00:00
|
|
|
return t;
|
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
|
|
|
return vm::makeMethod
|
|
|
|
(t, vmFlags, returnCode, parameterCount, parameterFootprint, flags,
|
2008-08-15 18:32:33 +00:00
|
|
|
offset, 0, name, spec, class_, code,
|
2008-05-31 22:14:27 +00:00
|
|
|
::defaultThunk(static_cast<MyThread*>(t)));
|
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-11 21:26:59 +00:00
|
|
|
return vm::makeClass
|
2007-12-09 22:45:43 +00:00
|
|
|
(t, flags, vmFlags, arrayDimensions, fixedSize, arrayElementSize,
|
|
|
|
objectMask, name, super, interfaceTable, virtualTable, fieldTable,
|
2009-03-04 03:05:48 +00:00
|
|
|
methodTable, staticTable, loader, vtableLength);
|
2007-12-11 21:26:59 +00:00
|
|
|
}
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-12-11 21:26:59 +00:00
|
|
|
virtual void
|
|
|
|
initVtable(Thread* t, object c)
|
|
|
|
{
|
2009-04-19 22:36:11 +00:00
|
|
|
for (int i = classLength(t, c) - 1; i >= 0; --i) {
|
2009-04-07 00:34:12 +00:00
|
|
|
classVtable(t, c, i) = reinterpret_cast<void*>
|
|
|
|
(virtualThunk(static_cast<MyThread*>(t), i));
|
2007-09-26 23:23:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void
|
|
|
|
initClass(Thread* t, object c)
|
|
|
|
{
|
|
|
|
PROTECT(t, c);
|
|
|
|
|
|
|
|
ACQUIRE(t, t->m->classLock);
|
2008-11-30 04:58:09 +00:00
|
|
|
if (classNeedsInit(t, c)) {
|
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) {
|
2008-04-07 23:47:41 +00:00
|
|
|
v->visit(&callTable);
|
|
|
|
v->visit(&methodTree);
|
|
|
|
v->visit(&methodTreeSentinal);
|
2008-11-23 23:58:01 +00:00
|
|
|
v->visit(&objectPools);
|
2008-12-02 02:38:00 +00:00
|
|
|
v->visit(&staticTableArray);
|
2009-04-26 02:24:04 +00:00
|
|
|
v->visit(&virtualThunks);
|
2009-05-17 23:43:48 +00:00
|
|
|
v->visit(&receiveMethod);
|
2007-10-14 01:18:25 +00:00
|
|
|
}
|
2007-09-25 23:53:11 +00:00
|
|
|
|
2008-04-07 23:47:41 +00:00
|
|
|
for (MyThread::CallTrace* trace = t->trace; trace; trace = trace->next) {
|
2009-05-03 20:57:11 +00:00
|
|
|
v->visit(&(trace->continuation));
|
2008-04-07 23:47:41 +00:00
|
|
|
v->visit(&(trace->nativeMethod));
|
2009-04-27 01:53:42 +00:00
|
|
|
v->visit(&(trace->targetMethod));
|
2008-04-07 23:47:41 +00:00
|
|
|
}
|
2008-04-01 17:37:59 +00:00
|
|
|
|
2009-05-03 20:57:11 +00:00
|
|
|
v->visit(&(t->continuation));
|
|
|
|
|
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);
|
2008-01-13 22:05:08 +00:00
|
|
|
PROTECT(t, o);
|
2007-09-30 03:33:38 +00:00
|
|
|
|
2008-04-13 18:15:04 +00:00
|
|
|
Reference* r = new (t->m->heap->allocate(sizeof(Reference)))
|
2007-09-30 03:33:38 +00:00
|
|
|
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)
|
|
|
|
{
|
2008-04-01 17:37:59 +00:00
|
|
|
if (UNLIKELY(t->exception)) return 0;
|
|
|
|
|
2007-09-24 01:39:03 +00:00
|
|
|
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];
|
2009-02-17 02:49:28 +00:00
|
|
|
ArgumentList list(t, array, size, objectMask, this_, spec, arguments);
|
2007-09-24 01:39:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
PROTECT(t, method);
|
|
|
|
|
2009-04-05 21:42:10 +00:00
|
|
|
compile(static_cast<MyThread*>(t),
|
|
|
|
::codeAllocator(static_cast<MyThread*>(t)), 0, method);
|
2007-12-09 22:45:43 +00:00
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2008-04-01 17:37:59 +00:00
|
|
|
if (UNLIKELY(t->exception)) return 0;
|
|
|
|
|
2007-09-24 01:39:03 +00:00
|
|
|
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
|
2009-02-17 02:49:28 +00:00
|
|
|
(t, array, size, objectMask, this_, spec, indirectObjects, arguments);
|
2007-09-24 01:39:03 +00:00
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
PROTECT(t, method);
|
|
|
|
|
2009-04-05 21:42:10 +00:00
|
|
|
compile(static_cast<MyThread*>(t),
|
|
|
|
::codeAllocator(static_cast<MyThread*>(t)), 0, method);
|
2007-12-09 22:45:43 +00:00
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2008-04-01 17:37:59 +00:00
|
|
|
if (UNLIKELY(t->exception)) return 0;
|
|
|
|
|
2007-09-24 01:39:03 +00:00
|
|
|
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
|
2009-02-17 02:49:28 +00:00
|
|
|
(t, array, size, 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);
|
|
|
|
|
2009-04-05 21:42:10 +00:00
|
|
|
compile(static_cast<MyThread*>(t),
|
|
|
|
::codeAllocator(static_cast<MyThread*>(t)), 0, 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-30 22:24:48 +00:00
|
|
|
virtual void dispose(Thread* vmt) {
|
|
|
|
MyThread* t = static_cast<MyThread*>(vmt);
|
|
|
|
|
2007-12-11 21:26:59 +00:00
|
|
|
while (t->reference) {
|
|
|
|
vm::dispose(t, t->reference);
|
|
|
|
}
|
2008-01-10 01:20:36 +00:00
|
|
|
|
2008-08-18 15:23:01 +00:00
|
|
|
t->arch->release();
|
|
|
|
|
2008-04-13 18:15:04 +00:00
|
|
|
t->m->heap->free(t, sizeof(*t));
|
2007-12-11 21:26:59 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
virtual void dispose() {
|
2009-04-05 21:42:10 +00:00
|
|
|
if (codeAllocator.base) {
|
|
|
|
s->freeExecutable(codeAllocator.base, codeAllocator.capacity);
|
|
|
|
}
|
|
|
|
|
2008-01-10 01:20:36 +00:00
|
|
|
s->handleSegFault(0);
|
|
|
|
|
2008-04-13 18:15:04 +00:00
|
|
|
allocator->free(this, sizeof(*this));
|
2007-09-24 01:39:03 +00:00
|
|
|
}
|
2008-04-09 19:08:13 +00:00
|
|
|
|
|
|
|
virtual object getStackTrace(Thread* vmt, Thread* vmTarget) {
|
|
|
|
MyThread* t = static_cast<MyThread*>(vmt);
|
|
|
|
MyThread* target = static_cast<MyThread*>(vmTarget);
|
2008-12-02 02:38:00 +00:00
|
|
|
MyProcessor* p = this;
|
2008-04-22 15:31:40 +00:00
|
|
|
|
2008-04-09 19:08:13 +00:00
|
|
|
class Visitor: public System::ThreadVisitor {
|
|
|
|
public:
|
2008-05-31 22:14:27 +00:00
|
|
|
Visitor(MyThread* t, MyProcessor* p, MyThread* target):
|
|
|
|
t(t), p(p), target(target)
|
|
|
|
{ }
|
2008-04-09 19:08:13 +00:00
|
|
|
|
|
|
|
virtual void visit(void* ip, void* base, void* stack) {
|
|
|
|
void* oldIp = target->ip;
|
2008-04-21 22:36:13 +00:00
|
|
|
void* oldBase = target->base;
|
2008-04-09 19:08:13 +00:00
|
|
|
void* oldStack = target->stack;
|
|
|
|
|
2008-04-21 17:29:36 +00:00
|
|
|
if (methodForIp(t, ip)) {
|
|
|
|
target->ip = ip;
|
|
|
|
target->base = base;
|
|
|
|
target->stack = stack;
|
2008-04-22 15:31:40 +00:00
|
|
|
} else {
|
2008-11-23 23:58:01 +00:00
|
|
|
uint8_t* thunkStart = p->thunkTable;
|
2008-05-31 22:14:27 +00:00
|
|
|
uint8_t* thunkEnd = thunkStart + (p->thunkSize * ThunkCount);
|
2008-04-22 15:31:40 +00:00
|
|
|
|
2008-05-31 22:14:27 +00:00
|
|
|
if (static_cast<uint8_t*>(ip) >= thunkStart
|
|
|
|
and static_cast<uint8_t*>(ip) < thunkEnd)
|
2008-04-22 15:31:40 +00:00
|
|
|
{
|
2008-08-18 15:23:01 +00:00
|
|
|
target->ip = t->arch->frameIp(stack);
|
2008-04-22 15:31:40 +00:00
|
|
|
target->base = base;
|
|
|
|
target->stack = stack;
|
|
|
|
}
|
2008-04-21 17:29:36 +00:00
|
|
|
}
|
2008-04-09 19:08:13 +00:00
|
|
|
|
2008-04-25 22:18:19 +00:00
|
|
|
ensure(t, traceSize(target));
|
|
|
|
|
2008-04-21 22:36:13 +00:00
|
|
|
t->tracing = true;
|
2008-04-09 19:08:13 +00:00
|
|
|
trace = makeTrace(t, target);
|
2008-04-21 22:36:13 +00:00
|
|
|
t->tracing = false;
|
2008-04-09 19:08:13 +00:00
|
|
|
|
|
|
|
target->ip = oldIp;
|
|
|
|
target->base = oldBase;
|
|
|
|
target->stack = oldStack;
|
|
|
|
}
|
|
|
|
|
|
|
|
MyThread* t;
|
2008-05-31 22:14:27 +00:00
|
|
|
MyProcessor* p;
|
2008-04-09 19:08:13 +00:00
|
|
|
MyThread* target;
|
|
|
|
object trace;
|
2008-05-31 22:14:27 +00:00
|
|
|
} visitor(t, p, target);
|
2008-04-09 19:08:13 +00:00
|
|
|
|
2008-04-21 22:36:13 +00:00
|
|
|
t->m->system->visit(t->systemThread, target->systemThread, &visitor);
|
|
|
|
|
2008-04-09 19:08:13 +00:00
|
|
|
if (t->backupHeap) {
|
|
|
|
PROTECT(t, visitor.trace);
|
|
|
|
|
|
|
|
collect(t, Heap::MinorCollection);
|
|
|
|
}
|
|
|
|
|
|
|
|
return visitor.trace;
|
|
|
|
}
|
2008-11-23 23:58:01 +00:00
|
|
|
|
2009-04-05 21:42:10 +00:00
|
|
|
virtual void initialize(Thread* vmt, BootImage* image, uint8_t* code,
|
|
|
|
unsigned capacity)
|
2008-11-23 23:58:01 +00:00
|
|
|
{
|
2009-04-05 21:42:10 +00:00
|
|
|
codeAllocator.base = code;
|
|
|
|
codeAllocator.capacity = capacity;
|
2008-11-23 23:58:01 +00:00
|
|
|
|
2009-04-05 21:42:10 +00:00
|
|
|
::compileThunks
|
|
|
|
(static_cast<MyThread*>(vmt), &codeAllocator, this, image, code);
|
2008-11-23 23:58:01 +00:00
|
|
|
}
|
|
|
|
|
2009-04-05 21:42:10 +00:00
|
|
|
virtual void compileMethod(Thread* vmt, Zone* zone, object* constants,
|
|
|
|
object* calls, DelayedPromise** addresses,
|
|
|
|
object method)
|
2008-11-23 23:58:01 +00:00
|
|
|
{
|
|
|
|
MyThread* t = static_cast<MyThread*>(vmt);
|
2008-12-02 16:45:20 +00:00
|
|
|
BootContext bootContext(t, *constants, *calls, *addresses, zone);
|
2008-11-23 23:58:01 +00:00
|
|
|
|
2009-04-05 21:42:10 +00:00
|
|
|
compile(t, &codeAllocator, &bootContext, method);
|
2008-11-23 23:58:01 +00:00
|
|
|
|
2008-11-27 20:59:40 +00:00
|
|
|
*constants = bootContext.constants;
|
|
|
|
*calls = bootContext.calls;
|
2008-12-02 16:45:20 +00:00
|
|
|
*addresses = bootContext.addresses;
|
2008-11-23 23:58:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void visitRoots(BootImage* image, HeapWalker* w) {
|
|
|
|
image->methodTree = w->visitRoot(methodTree);
|
|
|
|
image->methodTreeSentinal = w->visitRoot(methodTreeSentinal);
|
2009-04-05 21:42:10 +00:00
|
|
|
image->virtualThunks = w->visitRoot(virtualThunks);
|
2008-11-28 22:02:45 +00:00
|
|
|
}
|
|
|
|
|
2008-12-02 02:38:00 +00:00
|
|
|
virtual unsigned* makeCallTable(Thread* t, BootImage* image, HeapWalker* w,
|
|
|
|
uint8_t* code)
|
2008-11-28 22:02:45 +00:00
|
|
|
{
|
2008-12-02 02:38:00 +00:00
|
|
|
image->callCount = callTableSize;
|
2008-11-28 22:02:45 +00:00
|
|
|
|
2008-12-02 02:38:00 +00:00
|
|
|
unsigned* table = static_cast<unsigned*>
|
|
|
|
(t->m->heap->allocate(callTableSize * sizeof(unsigned) * 2));
|
2008-11-29 23:08:14 +00:00
|
|
|
|
2008-12-02 02:38:00 +00:00
|
|
|
unsigned index = 0;
|
|
|
|
for (unsigned i = 0; i < arrayLength(t, callTable); ++i) {
|
|
|
|
for (object p = arrayBody(t, callTable, i); p; p = callNodeNext(t, p)) {
|
|
|
|
table[index++] = callNodeAddress(t, p)
|
|
|
|
- reinterpret_cast<uintptr_t>(code);
|
|
|
|
table[index++] = w->map()->find(callNodeTarget(t, p))
|
2009-04-07 00:34:12 +00:00
|
|
|
| (static_cast<unsigned>(callNodeFlags(t, p)) << BootShift);
|
2008-12-02 02:38:00 +00:00
|
|
|
}
|
|
|
|
}
|
2008-11-29 23:08:14 +00:00
|
|
|
|
2008-12-02 02:38:00 +00:00
|
|
|
return table;
|
|
|
|
}
|
2008-11-28 22:02:45 +00:00
|
|
|
|
2008-12-02 02:38:00 +00:00
|
|
|
virtual void boot(Thread* t, BootImage* image) {
|
2009-04-07 00:34:12 +00:00
|
|
|
codeAllocator.base = static_cast<uint8_t*>
|
|
|
|
(s->tryAllocateExecutable(ExecutableAreaSizeInBytes));
|
2009-04-05 21:42:10 +00:00
|
|
|
codeAllocator.capacity = ExecutableAreaSizeInBytes;
|
|
|
|
|
2008-12-02 02:38:00 +00:00
|
|
|
if (image) {
|
|
|
|
::boot(static_cast<MyThread*>(t), image);
|
|
|
|
} else {
|
2009-03-04 03:05:48 +00:00
|
|
|
callTable = makeArray(t, 128);
|
2008-11-28 22:02:45 +00:00
|
|
|
|
2008-12-02 02:38:00 +00:00
|
|
|
methodTree = methodTreeSentinal = makeTreeNode(t, 0, 0, 0);
|
|
|
|
set(t, methodTree, TreeNodeLeft, methodTreeSentinal);
|
|
|
|
set(t, methodTree, TreeNodeRight, methodTreeSentinal);
|
2008-11-28 22:02:45 +00:00
|
|
|
|
2009-04-05 21:42:10 +00:00
|
|
|
::compileThunks(static_cast<MyThread*>(t), &codeAllocator, this, 0, 0);
|
2008-12-02 02:38:00 +00:00
|
|
|
}
|
2008-11-28 22:02:45 +00:00
|
|
|
|
2008-12-02 02:38:00 +00:00
|
|
|
segFaultHandler.m = t->m;
|
|
|
|
expect(t, t->m->system->success
|
|
|
|
(t->m->system->handleSegFault(&segFaultHandler)));
|
2008-11-23 23:58:01 +00:00
|
|
|
}
|
2009-05-03 20:57:11 +00:00
|
|
|
|
2009-05-06 00:29:05 +00:00
|
|
|
virtual void callWithCurrentContinuation(Thread* vmt, object receiver) {
|
2009-05-05 01:04:17 +00:00
|
|
|
MyThread* t = static_cast<MyThread*>(vmt);
|
|
|
|
|
2009-05-06 00:29:05 +00:00
|
|
|
{ PROTECT(t, receiver);
|
|
|
|
|
|
|
|
if (receiveMethod == 0) {
|
|
|
|
const char* const className = "avian/CallbackReceiver";
|
|
|
|
const char* const methodName = "receive";
|
|
|
|
const char* const methodSpec = "(Lavian/Callback;)Ljava/lang/Object;";
|
2009-05-03 20:57:11 +00:00
|
|
|
|
2009-05-06 00:29:05 +00:00
|
|
|
receiveMethod = resolveMethod(t, className, methodName, methodSpec);
|
|
|
|
|
|
|
|
if (receiveMethod == 0) {
|
|
|
|
object message = makeString
|
|
|
|
(t, "%s %s not found in %s", methodName, methodSpec, className);
|
|
|
|
t->exception = makeNoSuchMethodError(t, message);
|
|
|
|
}
|
2009-05-16 08:03:03 +00:00
|
|
|
|
|
|
|
if (LIKELY(t->exception == 0)) {
|
|
|
|
object continuationClass = arrayBody
|
|
|
|
(t, t->m->types, Machine::ContinuationType);
|
|
|
|
|
|
|
|
if (classVmFlags(t, continuationClass) & BootstrapFlag) {
|
|
|
|
resolveClass(t, vm::className(t, continuationClass));
|
|
|
|
}
|
|
|
|
}
|
2009-05-06 00:29:05 +00:00
|
|
|
}
|
2009-05-03 20:57:11 +00:00
|
|
|
|
|
|
|
if (LIKELY(t->exception == 0)) {
|
2009-05-20 00:28:43 +00:00
|
|
|
object method = findInterfaceMethod
|
2009-05-06 00:29:05 +00:00
|
|
|
(t, receiveMethod, objectClass(t, receiver));
|
|
|
|
PROTECT(t, method);
|
|
|
|
|
|
|
|
compile(t, ::codeAllocator(t), 0, method);
|
|
|
|
if (LIKELY(t->exception == 0)) {
|
|
|
|
void* ip;
|
2009-05-20 00:28:43 +00:00
|
|
|
void* base;
|
|
|
|
void* stack;
|
|
|
|
unsigned oldArgumentFootprint;
|
|
|
|
t->continuation = makeCurrentContinuation
|
2009-05-17 00:39:08 +00:00
|
|
|
(t, &ip, &base, &stack, &oldArgumentFootprint);
|
2009-05-20 00:28:43 +00:00
|
|
|
|
|
|
|
callWithContinuation
|
|
|
|
(t, method, receiver, t->continuation, base, stack,
|
|
|
|
oldArgumentFootprint);
|
2009-05-06 00:29:05 +00:00
|
|
|
}
|
2009-05-03 20:57:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-20 00:28:43 +00:00
|
|
|
unwind(t);
|
2009-05-03 20:57:11 +00:00
|
|
|
}
|
|
|
|
|
2009-05-06 00:29:05 +00:00
|
|
|
virtual void feedResultToContinuation(Thread* vmt, object continuation,
|
|
|
|
object result)
|
2009-05-03 20:57:11 +00:00
|
|
|
{
|
2009-05-05 01:04:17 +00:00
|
|
|
MyThread* t = static_cast<MyThread*>(vmt);
|
|
|
|
|
2009-05-03 20:57:11 +00:00
|
|
|
assert(t, t->exception == 0);
|
|
|
|
|
|
|
|
void* ip;
|
|
|
|
void* base;
|
|
|
|
void* stack;
|
|
|
|
findUnwindTarget(t, &ip, &base, &stack);
|
|
|
|
|
|
|
|
t->trace->nativeMethod = 0;
|
|
|
|
t->trace->targetMethod = 0;
|
|
|
|
|
|
|
|
t->continuation = continuation;
|
2009-05-05 01:04:17 +00:00
|
|
|
|
|
|
|
vmJump(ip, base, stack, t, reinterpret_cast<uintptr_t>(result), 0);
|
2009-05-03 20:57:11 +00:00
|
|
|
}
|
|
|
|
|
2009-05-06 00:29:05 +00:00
|
|
|
virtual void feedExceptionToContinuation(Thread* vmt, object continuation,
|
|
|
|
object exception)
|
|
|
|
{
|
|
|
|
MyThread* t = static_cast<MyThread*>(vmt);
|
|
|
|
|
|
|
|
assert(t, t->exception == 0);
|
|
|
|
|
|
|
|
void* ip;
|
|
|
|
void* base;
|
|
|
|
void* stack;
|
|
|
|
findUnwindTarget(t, &ip, &base, &stack);
|
|
|
|
|
|
|
|
t->trace->nativeMethod = 0;
|
|
|
|
t->trace->targetMethod = 0;
|
|
|
|
|
|
|
|
t->continuation = continuation;
|
|
|
|
|
|
|
|
t->exception = exception;
|
|
|
|
|
|
|
|
findUnwindTarget(t, &ip, &base, &stack);
|
|
|
|
|
|
|
|
vmJump(ip, base, stack, t, 0, 0);
|
|
|
|
}
|
|
|
|
|
2009-05-03 20:57:11 +00:00
|
|
|
virtual void walkContinuationBody(Thread* t, Heap::Walker* w, object o,
|
|
|
|
unsigned start)
|
|
|
|
{
|
|
|
|
::walkContinuationBody(static_cast<MyThread*>(t), w, o, start);
|
|
|
|
}
|
2007-09-24 01:39:03 +00:00
|
|
|
|
|
|
|
System* s;
|
2008-01-13 22:05:08 +00:00
|
|
|
Allocator* allocator;
|
2008-11-23 23:58:01 +00:00
|
|
|
uint8_t* defaultThunk;
|
2009-04-07 00:34:12 +00:00
|
|
|
uint8_t* defaultVirtualThunk;
|
2008-11-23 23:58:01 +00:00
|
|
|
uint8_t* nativeThunk;
|
|
|
|
uint8_t* aioobThunk;
|
|
|
|
uint8_t* thunkTable;
|
2008-05-31 22:14:27 +00:00
|
|
|
unsigned thunkSize;
|
2008-04-07 23:47:41 +00:00
|
|
|
object callTable;
|
|
|
|
unsigned callTableSize;
|
|
|
|
object methodTree;
|
|
|
|
object methodTreeSentinal;
|
2008-11-23 23:58:01 +00:00
|
|
|
object objectPools;
|
2008-12-02 02:38:00 +00:00
|
|
|
object staticTableArray;
|
2009-04-05 21:42:10 +00:00
|
|
|
object virtualThunks;
|
2009-05-06 00:29:05 +00:00
|
|
|
object receiveMethod;
|
2007-12-30 22:24:48 +00:00
|
|
|
SegFaultHandler segFaultHandler;
|
2009-04-05 21:42:10 +00:00
|
|
|
FixedAllocator codeAllocator;
|
2007-09-24 01:39:03 +00:00
|
|
|
};
|
|
|
|
|
2008-12-02 02:38:00 +00:00
|
|
|
object
|
|
|
|
findCallNode(MyThread* t, void* address)
|
2008-05-31 22:14:27 +00:00
|
|
|
{
|
2008-12-02 02:38:00 +00:00
|
|
|
if (DebugCallTable) {
|
|
|
|
fprintf(stderr, "find call node %p\n", address);
|
|
|
|
}
|
|
|
|
|
2009-03-03 01:40:06 +00:00
|
|
|
// we must use a version of the call table at least as recent as the
|
|
|
|
// compiled form of the method containing the specified address (see
|
|
|
|
// compile(MyThread*, Allocator*, BootContext*, object)):
|
|
|
|
memoryBarrier();
|
|
|
|
|
2008-05-31 22:14:27 +00:00
|
|
|
MyProcessor* p = processor(t);
|
2008-12-02 02:38:00 +00:00
|
|
|
object table = p->callTable;
|
2008-05-31 22:14:27 +00:00
|
|
|
|
2008-12-02 02:38:00 +00:00
|
|
|
intptr_t key = reinterpret_cast<intptr_t>(address);
|
|
|
|
unsigned index = static_cast<uintptr_t>(key)
|
|
|
|
& (arrayLength(t, table) - 1);
|
2008-05-31 22:14:27 +00:00
|
|
|
|
2008-12-02 02:38:00 +00:00
|
|
|
for (object n = arrayBody(t, table, index);
|
|
|
|
n; n = callNodeNext(t, n))
|
|
|
|
{
|
|
|
|
intptr_t k = callNodeAddress(t, n);
|
2008-05-31 22:14:27 +00:00
|
|
|
|
2008-12-02 02:38:00 +00:00
|
|
|
if (k == key) {
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
}
|
2008-05-31 22:14:27 +00:00
|
|
|
|
2008-12-02 02:38:00 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2008-05-31 22:14:27 +00:00
|
|
|
|
2008-12-02 02:38:00 +00:00
|
|
|
object
|
|
|
|
resizeTable(MyThread* t, object oldTable, unsigned newLength)
|
|
|
|
{
|
|
|
|
PROTECT(t, oldTable);
|
2008-05-31 22:14:27 +00:00
|
|
|
|
2008-12-02 02:38:00 +00:00
|
|
|
object oldNode = 0;
|
|
|
|
PROTECT(t, oldNode);
|
2008-08-16 18:46:14 +00:00
|
|
|
|
2009-03-04 03:05:48 +00:00
|
|
|
object newTable = makeArray(t, newLength);
|
2008-12-02 02:38:00 +00:00
|
|
|
PROTECT(t, newTable);
|
2008-05-31 22:14:27 +00:00
|
|
|
|
2008-12-02 02:38:00 +00:00
|
|
|
for (unsigned i = 0; i < arrayLength(t, oldTable); ++i) {
|
|
|
|
for (oldNode = arrayBody(t, oldTable, i);
|
|
|
|
oldNode;
|
|
|
|
oldNode = callNodeNext(t, oldNode))
|
|
|
|
{
|
|
|
|
intptr_t k = callNodeAddress(t, oldNode);
|
2008-05-31 22:14:27 +00:00
|
|
|
|
2008-12-02 02:38:00 +00:00
|
|
|
unsigned index = k & (newLength - 1);
|
|
|
|
|
|
|
|
object newNode = makeCallNode
|
|
|
|
(t, callNodeAddress(t, oldNode),
|
|
|
|
callNodeTarget(t, oldNode),
|
2009-03-31 20:15:08 +00:00
|
|
|
callNodeFlags(t, oldNode),
|
2008-12-02 02:38:00 +00:00
|
|
|
arrayBody(t, newTable, index));
|
|
|
|
|
|
|
|
set(t, newTable, ArrayBody + (index * BytesPerWord), newNode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return newTable;
|
|
|
|
}
|
|
|
|
|
|
|
|
object
|
|
|
|
insertCallNode(MyThread* t, object table, unsigned* size, object node)
|
|
|
|
{
|
|
|
|
if (DebugCallTable) {
|
|
|
|
fprintf(stderr, "insert call node %p\n",
|
|
|
|
reinterpret_cast<void*>(callNodeAddress(t, node)));
|
|
|
|
}
|
|
|
|
|
|
|
|
PROTECT(t, table);
|
|
|
|
PROTECT(t, node);
|
|
|
|
|
|
|
|
++ (*size);
|
|
|
|
|
|
|
|
if (*size >= arrayLength(t, table) * 2) {
|
|
|
|
table = resizeTable(t, table, arrayLength(t, table) * 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
intptr_t key = callNodeAddress(t, node);
|
|
|
|
unsigned index = static_cast<uintptr_t>(key) & (arrayLength(t, table) - 1);
|
|
|
|
|
|
|
|
set(t, node, CallNodeNext, arrayBody(t, table, index));
|
|
|
|
set(t, table, ArrayBody + (index * BytesPerWord), node);
|
|
|
|
|
|
|
|
return table;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
insertCallNode(MyThread* t, object node)
|
|
|
|
{
|
|
|
|
MyProcessor* p = processor(t);
|
|
|
|
p->callTable = insertCallNode(t, p->callTable, &(p->callTableSize), node);
|
|
|
|
}
|
|
|
|
|
|
|
|
object
|
|
|
|
makeClassMap(Thread* t, unsigned* table, unsigned count, uintptr_t* heap)
|
|
|
|
{
|
2009-03-04 03:05:48 +00:00
|
|
|
object array = makeArray(t, nextPowerOfTwo(count));
|
2008-12-02 02:38:00 +00:00
|
|
|
object map = makeHashMap(t, 0, array);
|
|
|
|
PROTECT(t, map);
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < count; ++i) {
|
|
|
|
object c = bootObject(heap, table[i]);
|
|
|
|
hashMapInsert(t, map, className(t, c), c, byteArrayHash);
|
|
|
|
}
|
|
|
|
|
|
|
|
return map;
|
|
|
|
}
|
|
|
|
|
|
|
|
object
|
|
|
|
makeStaticTableArray(Thread* t, unsigned* table, unsigned count,
|
|
|
|
uintptr_t* heap)
|
|
|
|
{
|
2009-03-04 03:05:48 +00:00
|
|
|
object array = makeArray(t, count);
|
2008-12-02 02:38:00 +00:00
|
|
|
|
|
|
|
for (unsigned i = 0; i < count; ++i) {
|
|
|
|
set(t, array, ArrayBody + (i * BytesPerWord),
|
|
|
|
classStaticTable(t, bootObject(heap, table[i])));
|
|
|
|
}
|
|
|
|
|
|
|
|
return array;
|
|
|
|
}
|
|
|
|
|
|
|
|
object
|
|
|
|
makeStringMap(Thread* t, unsigned* table, unsigned count, uintptr_t* heap)
|
|
|
|
{
|
2009-03-04 03:05:48 +00:00
|
|
|
object array = makeArray(t, nextPowerOfTwo(count));
|
2008-12-02 02:38:00 +00:00
|
|
|
object map = makeWeakHashMap(t, 0, array);
|
|
|
|
PROTECT(t, map);
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < count; ++i) {
|
|
|
|
object s = bootObject(heap, table[i]);
|
|
|
|
hashMapInsert(t, map, s, 0, stringHash);
|
|
|
|
}
|
|
|
|
|
|
|
|
return map;
|
|
|
|
}
|
|
|
|
|
|
|
|
object
|
|
|
|
makeCallTable(MyThread* t, uintptr_t* heap, unsigned* calls, unsigned count,
|
|
|
|
uintptr_t base)
|
|
|
|
{
|
2009-03-04 03:05:48 +00:00
|
|
|
object table = makeArray(t, nextPowerOfTwo(count));
|
2008-12-02 02:38:00 +00:00
|
|
|
PROTECT(t, table);
|
|
|
|
|
|
|
|
unsigned size = 0;
|
|
|
|
for (unsigned i = 0; i < count; ++i) {
|
|
|
|
unsigned address = calls[i * 2];
|
|
|
|
unsigned target = calls[(i * 2) + 1];
|
|
|
|
|
|
|
|
object node = makeCallNode
|
|
|
|
(t, base + address, bootObject(heap, target & BootMask),
|
|
|
|
target >> BootShift, 0);
|
|
|
|
|
|
|
|
table = insertCallNode(t, table, &size, node);
|
|
|
|
}
|
|
|
|
|
|
|
|
return table;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-12-03 02:39:56 +00:00
|
|
|
fixupHeap(MyThread* t UNUSED, uintptr_t* map, unsigned size, uintptr_t* heap)
|
2008-12-02 02:38:00 +00:00
|
|
|
{
|
|
|
|
for (unsigned word = 0; word < size; ++word) {
|
|
|
|
uintptr_t w = map[word];
|
|
|
|
if (w) {
|
|
|
|
for (unsigned bit = 0; bit < BitsPerWord; ++bit) {
|
|
|
|
if (w & (static_cast<uintptr_t>(1) << bit)) {
|
|
|
|
unsigned index = indexOf(word, bit);
|
|
|
|
uintptr_t* p = heap + index;
|
|
|
|
assert(t, *p);
|
|
|
|
|
|
|
|
uintptr_t number = *p & BootMask;
|
|
|
|
uintptr_t mark = *p >> BootShift;
|
|
|
|
|
|
|
|
if (number) {
|
|
|
|
*p = reinterpret_cast<uintptr_t>(heap + (number - 1)) | mark;
|
|
|
|
} else {
|
|
|
|
*p = mark;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-03-10 00:52:09 +00:00
|
|
|
fixupCode(Thread* t, uintptr_t* map, unsigned size, uint8_t* code,
|
2008-12-02 02:38:00 +00:00
|
|
|
uintptr_t* heap)
|
|
|
|
{
|
2009-03-10 00:52:09 +00:00
|
|
|
Assembler::Architecture* arch = makeArchitecture(t->m->system);
|
|
|
|
arch->acquire();
|
|
|
|
|
2008-12-02 02:38:00 +00:00
|
|
|
for (unsigned word = 0; word < size; ++word) {
|
|
|
|
uintptr_t w = map[word];
|
|
|
|
if (w) {
|
|
|
|
for (unsigned bit = 0; bit < BitsPerWord; ++bit) {
|
|
|
|
if (w & (static_cast<uintptr_t>(1) << bit)) {
|
|
|
|
unsigned index = indexOf(word, bit);
|
2009-03-11 01:08:16 +00:00
|
|
|
uintptr_t oldValue; memcpy(&oldValue, code + index, BytesPerWord);
|
|
|
|
uintptr_t newValue;
|
|
|
|
if (oldValue & BootHeapOffset) {
|
|
|
|
newValue = reinterpret_cast<uintptr_t>
|
|
|
|
(heap + (oldValue & BootMask) - 1);
|
2008-12-02 16:45:20 +00:00
|
|
|
} else {
|
2009-03-11 01:08:16 +00:00
|
|
|
newValue = reinterpret_cast<uintptr_t>
|
|
|
|
(code + (oldValue & BootMask));
|
|
|
|
}
|
|
|
|
if (oldValue & BootFlatConstant) {
|
|
|
|
memcpy(code + index, &newValue, BytesPerWord);
|
|
|
|
} else {
|
|
|
|
arch->setConstant(code + index, newValue);
|
2008-12-02 16:45:20 +00:00
|
|
|
}
|
2008-12-02 02:38:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-03-10 00:52:09 +00:00
|
|
|
|
|
|
|
arch->release();
|
2008-12-02 02:38:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
fixupMethods(Thread* t, BootImage* image, uint8_t* code)
|
|
|
|
{
|
|
|
|
for (HashMapIterator it(t, t->m->classMap); it.hasMore();) {
|
|
|
|
object c = tripleSecond(t, it.next());
|
|
|
|
|
|
|
|
if (classMethodTable(t, c)) {
|
|
|
|
for (unsigned i = 0; i < arrayLength(t, classMethodTable(t, c)); ++i) {
|
|
|
|
object method = arrayBody(t, classMethodTable(t, c), i);
|
|
|
|
if (methodCode(t, method) or (methodFlags(t, method) & ACC_NATIVE)) {
|
|
|
|
assert(t, (methodCompiled(t, method) - image->codeBase)
|
|
|
|
<= image->codeSize);
|
|
|
|
|
|
|
|
methodCompiled(t, method)
|
|
|
|
= (methodCompiled(t, method) - image->codeBase)
|
|
|
|
+ reinterpret_cast<uintptr_t>(code);
|
|
|
|
|
|
|
|
if (DebugCompile and (methodFlags(t, method) & ACC_NATIVE) == 0) {
|
|
|
|
logCompile
|
|
|
|
(static_cast<MyThread*>(t),
|
|
|
|
reinterpret_cast<uint8_t*>(methodCompiled(t, method)),
|
|
|
|
reinterpret_cast<uintptr_t*>
|
|
|
|
(methodCompiled(t, method))[-1],
|
|
|
|
reinterpret_cast<char*>
|
|
|
|
(&byteArrayBody(t, className(t, methodClass(t, method)), 0)),
|
|
|
|
reinterpret_cast<char*>
|
|
|
|
(&byteArrayBody(t, methodName(t, method), 0)),
|
|
|
|
reinterpret_cast<char*>
|
|
|
|
(&byteArrayBody(t, methodSpec(t, method), 0)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
t->m->processor->initVtable(t, c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
fixupThunks(MyThread* t, BootImage* image, uint8_t* code)
|
|
|
|
{
|
|
|
|
MyProcessor* p = processor(t);
|
|
|
|
|
|
|
|
p->defaultThunk = code + image->defaultThunk;
|
|
|
|
|
|
|
|
updateCall(t, LongCall, false, code + image->compileMethodCall,
|
|
|
|
voidPointer(::compileMethod));
|
|
|
|
|
2009-04-07 00:34:12 +00:00
|
|
|
p->defaultVirtualThunk = code + image->defaultVirtualThunk;
|
|
|
|
|
|
|
|
updateCall(t, LongCall, false, code + image->compileVirtualMethodCall,
|
|
|
|
voidPointer(::compileVirtualMethod));
|
|
|
|
|
2008-12-02 02:38:00 +00:00
|
|
|
p->nativeThunk = code + image->nativeThunk;
|
|
|
|
|
|
|
|
updateCall(t, LongCall, false, code + image->invokeNativeCall,
|
|
|
|
voidPointer(invokeNative));
|
|
|
|
|
|
|
|
p->aioobThunk = code + image->aioobThunk;
|
|
|
|
|
|
|
|
updateCall(t, LongCall, false,
|
|
|
|
code + image->throwArrayIndexOutOfBoundsCall,
|
|
|
|
voidPointer(throwArrayIndexOutOfBounds));
|
|
|
|
|
|
|
|
p->thunkTable = code + image->thunkTable;
|
|
|
|
p->thunkSize = image->thunkSize;
|
|
|
|
|
|
|
|
#define THUNK(s) \
|
|
|
|
updateCall(t, LongJump, false, code + image->s##Call, voidPointer(s));
|
|
|
|
|
|
|
|
#include "thunks.cpp"
|
|
|
|
|
|
|
|
#undef THUNK
|
|
|
|
}
|
|
|
|
|
2009-04-05 21:42:10 +00:00
|
|
|
void
|
|
|
|
fixupVirtualThunks(MyThread* t, BootImage* image, uint8_t* code)
|
|
|
|
{
|
|
|
|
MyProcessor* p = processor(t);
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < wordArrayLength(t, p->virtualThunks); ++i) {
|
|
|
|
if (wordArrayBody(t, p->virtualThunks, 0)) {
|
|
|
|
wordArrayBody(t, p->virtualThunks, 0)
|
|
|
|
= (wordArrayBody(t, p->virtualThunks, 0) - image->codeBase)
|
|
|
|
+ reinterpret_cast<uintptr_t>(code);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-12-02 02:38:00 +00:00
|
|
|
void
|
|
|
|
boot(MyThread* t, BootImage* image)
|
|
|
|
{
|
|
|
|
assert(t, image->magic == BootImage::Magic);
|
|
|
|
|
|
|
|
unsigned* classTable = reinterpret_cast<unsigned*>(image + 1);
|
|
|
|
unsigned* stringTable = classTable + image->classCount;
|
|
|
|
unsigned* callTable = stringTable + image->stringCount;
|
|
|
|
|
|
|
|
uintptr_t* heapMap = reinterpret_cast<uintptr_t*>
|
|
|
|
(pad(reinterpret_cast<uintptr_t>(callTable + (image->callCount * 2))));
|
|
|
|
unsigned heapMapSizeInWords = ceiling
|
|
|
|
(heapMapSize(image->heapSize), BytesPerWord);
|
|
|
|
uintptr_t* heap = heapMap + heapMapSizeInWords;
|
|
|
|
|
|
|
|
// fprintf(stderr, "heap from %p to %p\n",
|
|
|
|
// heap, heap + ceiling(image->heapSize, BytesPerWord));
|
|
|
|
|
|
|
|
uintptr_t* codeMap = heap + ceiling(image->heapSize, BytesPerWord);
|
|
|
|
unsigned codeMapSizeInWords = ceiling
|
|
|
|
(codeMapSize(image->codeSize), BytesPerWord);
|
|
|
|
uint8_t* code = reinterpret_cast<uint8_t*>(codeMap + codeMapSizeInWords);
|
|
|
|
|
2008-12-02 16:45:20 +00:00
|
|
|
// fprintf(stderr, "code from %p to %p\n",
|
|
|
|
// code, code + image->codeSize);
|
2008-12-02 02:38:00 +00:00
|
|
|
|
|
|
|
fixupHeap(t, heapMap, heapMapSizeInWords, heap);
|
|
|
|
|
|
|
|
t->m->heap->setImmortalHeap(heap, image->heapSize / BytesPerWord);
|
|
|
|
|
|
|
|
t->m->loader = bootObject(heap, image->loader);
|
|
|
|
t->m->types = bootObject(heap, image->types);
|
|
|
|
|
|
|
|
MyProcessor* p = static_cast<MyProcessor*>(t->m->processor);
|
|
|
|
|
|
|
|
p->methodTree = bootObject(heap, image->methodTree);
|
|
|
|
p->methodTreeSentinal = bootObject(heap, image->methodTreeSentinal);
|
|
|
|
|
2009-04-05 21:42:10 +00:00
|
|
|
p->virtualThunks = bootObject(heap, image->virtualThunks);
|
|
|
|
|
2008-12-02 02:38:00 +00:00
|
|
|
fixupCode(t, codeMap, codeMapSizeInWords, code, heap);
|
|
|
|
|
2009-03-11 01:08:16 +00:00
|
|
|
syncInstructionCache(code, image->codeSize);
|
|
|
|
|
2008-12-02 02:38:00 +00:00
|
|
|
t->m->classMap = makeClassMap(t, classTable, image->classCount, heap);
|
|
|
|
t->m->stringMap = makeStringMap(t, stringTable, image->stringCount, heap);
|
|
|
|
|
|
|
|
p->callTableSize = image->callCount;
|
|
|
|
p->callTable = makeCallTable
|
|
|
|
(t, heap, callTable, image->callCount,
|
|
|
|
reinterpret_cast<uintptr_t>(code));
|
|
|
|
|
|
|
|
p->staticTableArray = makeStaticTableArray
|
|
|
|
(t, classTable, image->classCount, heap);
|
|
|
|
|
|
|
|
fixupThunks(t, image, code);
|
|
|
|
|
2009-04-05 21:42:10 +00:00
|
|
|
fixupVirtualThunks(t, image, code);
|
|
|
|
|
2008-12-02 02:38:00 +00:00
|
|
|
fixupMethods(t, image, code);
|
|
|
|
|
|
|
|
t->m->bootstrapClassMap = makeHashMap(t, 0, 0);
|
|
|
|
}
|
|
|
|
|
2008-05-31 22:14:27 +00:00
|
|
|
intptr_t
|
|
|
|
getThunk(MyThread* t, Thunk thunk)
|
|
|
|
{
|
|
|
|
MyProcessor* p = processor(t);
|
|
|
|
|
|
|
|
return reinterpret_cast<intptr_t>
|
2008-11-29 01:23:01 +00:00
|
|
|
(p->thunkTable + (thunk * p->thunkSize));
|
2008-05-31 22:14:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-11-23 23:58:01 +00:00
|
|
|
compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p,
|
|
|
|
BootImage* image, uint8_t* imageBase)
|
2008-05-31 22:14:27 +00:00
|
|
|
{
|
|
|
|
class ThunkContext {
|
|
|
|
public:
|
2008-11-27 20:59:40 +00:00
|
|
|
ThunkContext(MyThread* t, Zone* zone):
|
|
|
|
context(t), promise(t->m->system, zone)
|
|
|
|
{ }
|
2008-05-31 22:14:27 +00:00
|
|
|
|
|
|
|
Context context;
|
2008-11-27 20:59:40 +00:00
|
|
|
ListenPromise promise;
|
2008-05-31 22:14:27 +00:00
|
|
|
};
|
|
|
|
|
2008-11-27 20:59:40 +00:00
|
|
|
Zone zone(t->m->system, t->m->heap, 1024);
|
2009-03-31 20:15:08 +00:00
|
|
|
|
2008-11-27 20:59:40 +00:00
|
|
|
ThunkContext defaultContext(t, &zone);
|
2008-05-31 22:14:27 +00:00
|
|
|
|
|
|
|
{ Assembler* a = defaultContext.context.assembler;
|
2009-02-09 23:22:01 +00:00
|
|
|
|
|
|
|
a->saveFrame(difference(&(t->stack), t), difference(&(t->base), t));
|
|
|
|
|
|
|
|
Assembler::Register thread(t->arch->thread());
|
|
|
|
a->pushFrame(1, BytesPerWord, RegisterOperand, &thread);
|
2008-05-31 22:14:27 +00:00
|
|
|
|
|
|
|
Assembler::Constant proc(&(defaultContext.promise));
|
2008-06-02 13:49:09 +00:00
|
|
|
a->apply(LongCall, BytesPerWord, ConstantOperand, &proc);
|
2008-05-31 22:14:27 +00:00
|
|
|
|
2009-02-09 23:22:01 +00:00
|
|
|
a->popFrame();
|
2008-05-31 22:14:27 +00:00
|
|
|
|
2009-02-28 21:20:43 +00:00
|
|
|
Assembler::Register result(t->arch->returnLow());
|
2008-05-31 22:14:27 +00:00
|
|
|
a->apply(Jump, BytesPerWord, RegisterOperand, &result);
|
2008-09-07 20:12:11 +00:00
|
|
|
|
2008-09-09 00:31:19 +00:00
|
|
|
a->endBlock(false)->resolve(0, 0);
|
2008-05-31 22:14:27 +00:00
|
|
|
}
|
|
|
|
|
2009-04-05 21:42:10 +00:00
|
|
|
ThunkContext defaultVirtualContext(t, &zone);
|
|
|
|
|
|
|
|
{ Assembler* a = defaultVirtualContext.context.assembler;
|
|
|
|
|
2009-05-03 20:57:11 +00:00
|
|
|
Assembler::Register class_(t->arch->virtualCallTarget());
|
|
|
|
Assembler::Memory virtualCallTargetSrc
|
|
|
|
(t->arch->stack(),
|
2009-05-12 18:16:55 +00:00
|
|
|
(t->arch->frameFooterSize() + t->arch->frameReturnAddressSize())
|
|
|
|
* BytesPerWord);
|
2009-05-03 20:57:11 +00:00
|
|
|
|
|
|
|
a->apply(Move, BytesPerWord, MemoryOperand, &virtualCallTargetSrc,
|
|
|
|
BytesPerWord, RegisterOperand, &class_);
|
|
|
|
|
|
|
|
Assembler::Memory virtualCallTargetDst
|
|
|
|
(t->arch->thread(), difference(&(t->virtualCallTarget), t));
|
|
|
|
|
2009-04-05 21:42:10 +00:00
|
|
|
a->apply(Move, BytesPerWord, RegisterOperand, &class_,
|
2009-05-03 20:57:11 +00:00
|
|
|
BytesPerWord, MemoryOperand, &virtualCallTargetDst);
|
2009-04-05 21:42:10 +00:00
|
|
|
|
2009-04-19 22:36:11 +00:00
|
|
|
Assembler::Register index(t->arch->virtualCallIndex());
|
2009-04-05 21:42:10 +00:00
|
|
|
Assembler::Memory virtualCallIndex
|
|
|
|
(t->arch->thread(), difference(&(t->virtualCallIndex), t));
|
2009-05-03 20:57:11 +00:00
|
|
|
|
2009-04-05 21:42:10 +00:00
|
|
|
a->apply(Move, BytesPerWord, RegisterOperand, &index,
|
|
|
|
BytesPerWord, MemoryOperand, &virtualCallIndex);
|
|
|
|
|
|
|
|
a->saveFrame(difference(&(t->stack), t), difference(&(t->base), t));
|
|
|
|
|
|
|
|
Assembler::Register thread(t->arch->thread());
|
|
|
|
a->pushFrame(1, BytesPerWord, RegisterOperand, &thread);
|
|
|
|
|
|
|
|
Assembler::Constant proc(&(defaultVirtualContext.promise));
|
|
|
|
a->apply(LongCall, BytesPerWord, ConstantOperand, &proc);
|
|
|
|
|
|
|
|
a->popFrame();
|
|
|
|
|
|
|
|
Assembler::Register result(t->arch->returnLow());
|
|
|
|
a->apply(Jump, BytesPerWord, RegisterOperand, &result);
|
|
|
|
|
|
|
|
a->endBlock(false)->resolve(0, 0);
|
|
|
|
}
|
|
|
|
|
2008-11-27 20:59:40 +00:00
|
|
|
ThunkContext nativeContext(t, &zone);
|
2008-05-31 22:14:27 +00:00
|
|
|
|
|
|
|
{ Assembler* a = nativeContext.context.assembler;
|
2009-03-31 20:15:08 +00:00
|
|
|
|
2008-08-16 18:46:14 +00:00
|
|
|
a->saveFrame(difference(&(t->stack), t), difference(&(t->base), t));
|
|
|
|
|
2008-08-18 15:23:01 +00:00
|
|
|
Assembler::Register thread(t->arch->thread());
|
2008-08-16 18:46:14 +00:00
|
|
|
a->pushFrame(1, BytesPerWord, RegisterOperand, &thread);
|
2008-05-31 22:14:27 +00:00
|
|
|
|
|
|
|
Assembler::Constant proc(&(nativeContext.promise));
|
2008-06-02 13:49:09 +00:00
|
|
|
a->apply(LongCall, BytesPerWord, ConstantOperand, &proc);
|
2008-05-31 22:14:27 +00:00
|
|
|
|
2009-04-25 17:49:56 +00:00
|
|
|
a->popFrameAndUpdateStackAndReturn(difference(&(t->stack), t));
|
2008-09-07 20:12:11 +00:00
|
|
|
|
2008-09-09 00:31:19 +00:00
|
|
|
a->endBlock(false)->resolve(0, 0);
|
2008-05-31 22:14:27 +00:00
|
|
|
}
|
|
|
|
|
2008-11-27 20:59:40 +00:00
|
|
|
ThunkContext aioobContext(t, &zone);
|
2008-05-31 22:14:27 +00:00
|
|
|
|
|
|
|
{ Assembler* a = aioobContext.context.assembler;
|
|
|
|
|
2008-08-16 18:46:14 +00:00
|
|
|
a->saveFrame(difference(&(t->stack), t), difference(&(t->base), t));
|
|
|
|
|
2008-08-18 15:23:01 +00:00
|
|
|
Assembler::Register thread(t->arch->thread());
|
2008-08-16 18:46:14 +00:00
|
|
|
a->pushFrame(1, BytesPerWord, RegisterOperand, &thread);
|
2008-05-31 22:14:27 +00:00
|
|
|
|
|
|
|
Assembler::Constant proc(&(aioobContext.promise));
|
2008-06-02 13:49:09 +00:00
|
|
|
a->apply(LongCall, BytesPerWord, ConstantOperand, &proc);
|
2008-09-07 20:12:11 +00:00
|
|
|
|
2008-09-09 00:31:19 +00:00
|
|
|
a->endBlock(false)->resolve(0, 0);
|
2008-05-31 22:14:27 +00:00
|
|
|
}
|
|
|
|
|
2008-11-27 20:59:40 +00:00
|
|
|
ThunkContext tableContext(t, &zone);
|
2008-05-31 22:14:27 +00:00
|
|
|
|
|
|
|
{ Assembler* a = tableContext.context.assembler;
|
|
|
|
|
2008-08-16 18:46:14 +00:00
|
|
|
a->saveFrame(difference(&(t->stack), t), difference(&(t->base), t));
|
2008-05-31 22:14:27 +00:00
|
|
|
|
|
|
|
Assembler::Constant proc(&(tableContext.promise));
|
2008-06-02 13:49:09 +00:00
|
|
|
a->apply(LongJump, BytesPerWord, ConstantOperand, &proc);
|
2008-09-07 20:12:11 +00:00
|
|
|
|
2008-09-09 00:31:19 +00:00
|
|
|
a->endBlock(false)->resolve(0, 0);
|
2008-05-31 22:14:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
p->thunkSize = pad(tableContext.context.assembler->length());
|
|
|
|
|
2009-04-19 22:36:11 +00:00
|
|
|
p->defaultThunk = finish
|
2008-11-23 23:58:01 +00:00
|
|
|
(t, allocator, defaultContext.context.assembler, "default");
|
2008-05-31 22:14:27 +00:00
|
|
|
|
2009-03-11 01:08:16 +00:00
|
|
|
{ void* call;
|
|
|
|
defaultContext.promise.listener->resolve
|
|
|
|
(reinterpret_cast<intptr_t>(voidPointer(compileMethod)), &call);
|
2008-05-31 22:14:27 +00:00
|
|
|
|
2008-11-28 04:44:04 +00:00
|
|
|
if (image) {
|
2008-11-28 22:02:45 +00:00
|
|
|
image->defaultThunk = p->defaultThunk - imageBase;
|
2009-03-11 01:08:16 +00:00
|
|
|
image->compileMethodCall = static_cast<uint8_t*>(call) - imageBase;
|
2008-11-28 04:44:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-04-05 21:42:10 +00:00
|
|
|
p->defaultVirtualThunk = finish
|
|
|
|
(t, allocator, defaultVirtualContext.context.assembler, "defaultVirtual");
|
|
|
|
|
|
|
|
{ void* call;
|
|
|
|
defaultVirtualContext.promise.listener->resolve
|
|
|
|
(reinterpret_cast<intptr_t>(voidPointer(compileVirtualMethod)), &call);
|
|
|
|
|
|
|
|
if (image) {
|
|
|
|
image->defaultVirtualThunk = p->defaultVirtualThunk - imageBase;
|
|
|
|
image->compileVirtualMethodCall
|
|
|
|
= static_cast<uint8_t*>(call) - imageBase;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-04-19 22:36:11 +00:00
|
|
|
p->nativeThunk = finish
|
2008-11-23 23:58:01 +00:00
|
|
|
(t, allocator, nativeContext.context.assembler, "native");
|
|
|
|
|
2009-03-11 01:08:16 +00:00
|
|
|
{ void* call;
|
|
|
|
nativeContext.promise.listener->resolve
|
|
|
|
(reinterpret_cast<intptr_t>(voidPointer(invokeNative)), &call);
|
2008-11-28 04:44:04 +00:00
|
|
|
|
|
|
|
if (image) {
|
2008-11-28 22:02:45 +00:00
|
|
|
image->nativeThunk = p->nativeThunk - imageBase;
|
2009-03-11 01:08:16 +00:00
|
|
|
image->invokeNativeCall = static_cast<uint8_t*>(call) - imageBase;
|
2008-11-28 04:44:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-23 23:58:01 +00:00
|
|
|
p->aioobThunk = finish
|
|
|
|
(t, allocator, aioobContext.context.assembler, "aioob");
|
2008-05-31 22:14:27 +00:00
|
|
|
|
2009-03-11 01:08:16 +00:00
|
|
|
{ void* call;
|
|
|
|
aioobContext.promise.listener->resolve
|
|
|
|
(reinterpret_cast<intptr_t>(voidPointer(throwArrayIndexOutOfBounds)),
|
|
|
|
&call);
|
2008-05-31 22:14:27 +00:00
|
|
|
|
2008-11-28 04:44:04 +00:00
|
|
|
if (image) {
|
2008-11-28 22:02:45 +00:00
|
|
|
image->aioobThunk = p->aioobThunk - imageBase;
|
2009-03-11 01:08:16 +00:00
|
|
|
image->throwArrayIndexOutOfBoundsCall
|
|
|
|
= static_cast<uint8_t*>(call) - imageBase;
|
2008-11-28 04:44:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-23 23:58:01 +00:00
|
|
|
p->thunkTable = static_cast<uint8_t*>
|
|
|
|
(allocator->allocate(p->thunkSize * ThunkCount));
|
2008-05-31 22:14:27 +00:00
|
|
|
|
2008-11-28 22:02:45 +00:00
|
|
|
if (image) {
|
|
|
|
image->thunkTable = p->thunkTable - imageBase;
|
|
|
|
image->thunkSize = p->thunkSize;
|
|
|
|
}
|
2008-05-31 22:14:27 +00:00
|
|
|
|
2008-11-23 23:58:01 +00:00
|
|
|
logCompile(t, p->thunkTable, p->thunkSize * ThunkCount, 0, "thunkTable", 0);
|
2008-05-31 22:14:27 +00:00
|
|
|
|
2008-11-23 23:58:01 +00:00
|
|
|
uint8_t* start = p->thunkTable;
|
2008-05-31 22:14:27 +00:00
|
|
|
|
2008-11-23 23:58:01 +00:00
|
|
|
#define THUNK(s) \
|
|
|
|
tableContext.context.assembler->writeTo(start); \
|
|
|
|
start += p->thunkSize; \
|
2009-03-11 01:08:16 +00:00
|
|
|
{ void* call; \
|
|
|
|
tableContext.promise.listener->resolve \
|
|
|
|
(reinterpret_cast<intptr_t>(voidPointer(s)), &call); \
|
2008-11-27 20:59:40 +00:00
|
|
|
if (image) { \
|
2009-03-11 01:08:16 +00:00
|
|
|
image->s##Call = static_cast<uint8_t*>(call) - imageBase; \
|
2008-11-27 20:59:40 +00:00
|
|
|
} \
|
2008-11-23 23:58:01 +00:00
|
|
|
}
|
2008-05-31 22:14:27 +00:00
|
|
|
|
|
|
|
#include "thunks.cpp"
|
|
|
|
|
|
|
|
#undef THUNK
|
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
MyProcessor*
|
|
|
|
processor(MyThread* t)
|
2007-10-04 03:19:39 +00:00
|
|
|
{
|
2008-12-02 02:38:00 +00:00
|
|
|
return static_cast<MyProcessor*>(t->m->processor);
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2007-12-30 22:24:48 +00:00
|
|
|
|
2008-11-23 23:58:01 +00:00
|
|
|
object&
|
|
|
|
objectPools(MyThread* t)
|
|
|
|
{
|
|
|
|
return processor(t)->objectPools;
|
2007-12-09 22:45:43 +00:00
|
|
|
}
|
2007-09-24 01:39:03 +00:00
|
|
|
|
2008-11-23 23:58:01 +00:00
|
|
|
uintptr_t
|
2008-05-31 22:14:27 +00:00
|
|
|
defaultThunk(MyThread* t)
|
|
|
|
{
|
2008-11-23 23:58:01 +00:00
|
|
|
return reinterpret_cast<uintptr_t>(processor(t)->defaultThunk);
|
2008-05-31 22:14:27 +00:00
|
|
|
}
|
|
|
|
|
2009-04-07 00:34:12 +00:00
|
|
|
uintptr_t
|
|
|
|
defaultVirtualThunk(MyThread* t)
|
|
|
|
{
|
|
|
|
return reinterpret_cast<uintptr_t>(processor(t)->defaultVirtualThunk);
|
|
|
|
}
|
|
|
|
|
2008-11-23 23:58:01 +00:00
|
|
|
uintptr_t
|
2008-05-31 22:14:27 +00:00
|
|
|
nativeThunk(MyThread* t)
|
2008-04-09 19:08:13 +00:00
|
|
|
{
|
2008-11-23 23:58:01 +00:00
|
|
|
return reinterpret_cast<uintptr_t>(processor(t)->nativeThunk);
|
2008-04-09 19:08:13 +00:00
|
|
|
}
|
|
|
|
|
2008-11-23 23:58:01 +00:00
|
|
|
uintptr_t
|
2008-05-31 22:14:27 +00:00
|
|
|
aioobThunk(MyThread* t)
|
2008-04-09 19:08:13 +00:00
|
|
|
{
|
2008-11-23 23:58:01 +00:00
|
|
|
return reinterpret_cast<uintptr_t>(processor(t)->aioobThunk);
|
2008-04-09 19:08:13 +00:00
|
|
|
}
|
|
|
|
|
2009-04-05 21:42:10 +00:00
|
|
|
uintptr_t
|
|
|
|
compileVirtualThunk(MyThread* t, unsigned index)
|
|
|
|
{
|
2009-04-07 00:34:12 +00:00
|
|
|
Context context(t);
|
2009-04-05 21:42:10 +00:00
|
|
|
Assembler* a = context.assembler;
|
|
|
|
|
2009-04-07 00:34:12 +00:00
|
|
|
ResolvedPromise indexPromise(index);
|
|
|
|
Assembler::Constant indexConstant(&indexPromise);
|
2009-04-19 22:36:11 +00:00
|
|
|
Assembler::Register indexRegister(t->arch->virtualCallIndex());
|
2009-04-05 21:42:10 +00:00
|
|
|
a->apply(Move, BytesPerWord, ConstantOperand, &indexConstant,
|
2009-04-19 22:36:11 +00:00
|
|
|
BytesPerWord, RegisterOperand, &indexRegister);
|
2009-04-05 21:42:10 +00:00
|
|
|
|
2009-04-07 00:34:12 +00:00
|
|
|
ResolvedPromise defaultVirtualThunkPromise(defaultVirtualThunk(t));
|
|
|
|
Assembler::Constant thunk(&defaultVirtualThunkPromise);
|
2009-04-05 21:42:10 +00:00
|
|
|
a->apply(Jump, BytesPerWord, ConstantOperand, &thunk);
|
|
|
|
|
2009-04-19 22:36:11 +00:00
|
|
|
a->endBlock(false)->resolve(0, 0);
|
|
|
|
|
2009-04-07 00:34:12 +00:00
|
|
|
uint8_t* start = static_cast<uint8_t*>
|
|
|
|
(codeAllocator(t)->allocate(a->length()));
|
|
|
|
|
2009-04-05 21:42:10 +00:00
|
|
|
a->writeTo(start);
|
2009-04-08 00:55:43 +00:00
|
|
|
|
2009-04-19 22:36:11 +00:00
|
|
|
logCompile(t, start, a->length(), 0, "virtualThunk", 0);
|
|
|
|
|
2009-04-08 00:55:43 +00:00
|
|
|
return reinterpret_cast<uintptr_t>(start);
|
2009-04-05 21:42:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uintptr_t
|
|
|
|
virtualThunk(MyThread* t, unsigned index)
|
|
|
|
{
|
|
|
|
MyProcessor* p = processor(t);
|
|
|
|
|
|
|
|
if (p->virtualThunks == 0 or wordArrayLength(t, p->virtualThunks) <= index) {
|
2009-04-19 22:36:11 +00:00
|
|
|
object newArray = makeWordArray(t, nextPowerOfTwo(index + 1));
|
2009-04-05 21:42:10 +00:00
|
|
|
if (p->virtualThunks) {
|
|
|
|
memcpy(&wordArrayBody(t, newArray, 0),
|
|
|
|
&wordArrayBody(t, p->virtualThunks, 0),
|
|
|
|
wordArrayLength(t, p->virtualThunks) * BytesPerWord);
|
|
|
|
}
|
|
|
|
p->virtualThunks = newArray;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (wordArrayBody(t, p->virtualThunks, index) == 0) {
|
|
|
|
ACQUIRE(t, t->m->classLock);
|
|
|
|
|
|
|
|
if (wordArrayBody(t, p->virtualThunks, index) == 0) {
|
|
|
|
uintptr_t thunk = compileVirtualThunk(t, index);
|
|
|
|
wordArrayBody(t, p->virtualThunks, index) = thunk;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return wordArrayBody(t, p->virtualThunks, index);
|
|
|
|
}
|
|
|
|
|
2007-10-16 17:21:26 +00:00
|
|
|
void
|
2008-11-23 23:58:01 +00:00
|
|
|
compile(MyThread* t, Allocator* allocator, BootContext* bootContext,
|
|
|
|
object method)
|
2007-12-09 22:45:43 +00:00
|
|
|
{
|
2008-11-30 04:58:09 +00:00
|
|
|
PROTECT(t, method);
|
2007-12-09 22:45:43 +00:00
|
|
|
|
2008-11-30 04:58:09 +00:00
|
|
|
if (bootContext == 0) {
|
|
|
|
initClass(t, methodClass(t, method));
|
|
|
|
if (UNLIKELY(t->exception)) return;
|
|
|
|
}
|
2007-12-09 22:45:43 +00:00
|
|
|
|
2008-12-02 02:38:00 +00:00
|
|
|
if (methodAddress(t, method) == defaultThunk(t)) {
|
2007-12-09 22:45:43 +00:00
|
|
|
ACQUIRE(t, t->m->classLock);
|
|
|
|
|
2008-12-02 02:38:00 +00:00
|
|
|
if (methodAddress(t, method) == defaultThunk(t)) {
|
|
|
|
assert(t, (methodFlags(t, method) & ACC_NATIVE) == 0);
|
2007-12-09 22:45:43 +00:00
|
|
|
|
2008-12-02 02:38:00 +00:00
|
|
|
Context context(t, bootContext, method);
|
|
|
|
uint8_t* compiled = compile(t, allocator, &context);
|
|
|
|
if (UNLIKELY(t->exception)) return;
|
2008-04-10 23:48:28 +00:00
|
|
|
|
2008-12-02 02:38:00 +00:00
|
|
|
if (DebugMethodTree) {
|
|
|
|
fprintf(stderr, "insert method at %p\n", compiled);
|
2007-12-11 23:52:28 +00:00
|
|
|
}
|
2007-12-11 00:48:09 +00:00
|
|
|
|
2008-12-02 02:38:00 +00:00
|
|
|
// We can't set the MethodCompiled field on the original method
|
|
|
|
// before it is placed into the method tree, since another
|
|
|
|
// thread might call the method, from which stack unwinding
|
|
|
|
// would fail (since there is not yet an entry in the method
|
|
|
|
// tree). However, we can't insert the original method into the
|
|
|
|
// tree before setting the MethodCompiled field on it since we
|
|
|
|
// rely on that field to determine its position in the tree.
|
|
|
|
// Therefore, we insert a clone in its place. Later, we'll
|
|
|
|
// replace the clone with the original to save memory.
|
|
|
|
|
|
|
|
object clone = makeMethod
|
|
|
|
(t, methodVmFlags(t, method),
|
|
|
|
methodReturnCode(t, method),
|
|
|
|
methodParameterCount(t, method),
|
|
|
|
methodParameterFootprint(t, method),
|
|
|
|
methodFlags(t, method),
|
|
|
|
methodOffset(t, method),
|
|
|
|
methodNativeID(t, method),
|
|
|
|
methodName(t, method),
|
|
|
|
methodSpec(t, method),
|
|
|
|
methodClass(t, method),
|
|
|
|
methodCode(t, method),
|
|
|
|
reinterpret_cast<intptr_t>(compiled));
|
|
|
|
|
|
|
|
methodTree(t) = treeInsert
|
|
|
|
(t, &(context.zone), methodTree(t),
|
|
|
|
reinterpret_cast<intptr_t>(compiled), clone, methodTreeSentinal(t),
|
|
|
|
compareIpToMethodBounds);
|
|
|
|
|
2009-03-03 01:40:06 +00:00
|
|
|
memoryBarrier();
|
|
|
|
|
2008-12-02 02:38:00 +00:00
|
|
|
methodCompiled(t, method) = reinterpret_cast<intptr_t>(compiled);
|
|
|
|
|
|
|
|
if (methodVirtual(t, method)) {
|
|
|
|
classVtable(t, methodClass(t, method), methodOffset(t, method))
|
|
|
|
= compiled;
|
|
|
|
}
|
2007-12-28 16:50:26 +00:00
|
|
|
|
2008-12-02 02:38:00 +00:00
|
|
|
treeUpdate(t, methodTree(t), reinterpret_cast<intptr_t>(compiled),
|
|
|
|
method, methodTreeSentinal(t), compareIpToMethodBounds);
|
2007-12-11 00:48:09 +00:00
|
|
|
}
|
|
|
|
}
|
2008-04-07 23:47:41 +00:00
|
|
|
}
|
2007-12-11 00:48:09 +00:00
|
|
|
|
2008-04-07 23:47:41 +00:00
|
|
|
object&
|
|
|
|
methodTree(MyThread* t)
|
|
|
|
{
|
|
|
|
return processor(t)->methodTree;
|
|
|
|
}
|
|
|
|
|
|
|
|
object
|
|
|
|
methodTreeSentinal(MyThread* t)
|
|
|
|
{
|
|
|
|
return processor(t)->methodTreeSentinal;
|
2007-10-16 17:21:26 +00:00
|
|
|
}
|
|
|
|
|
2009-04-05 21:42:10 +00:00
|
|
|
FixedAllocator*
|
|
|
|
codeAllocator(MyThread* t)
|
|
|
|
{
|
|
|
|
return &(processor(t)->codeAllocator);
|
2008-01-10 01:20:36 +00:00
|
|
|
}
|
|
|
|
|
2007-12-09 22:45:43 +00:00
|
|
|
} // namespace
|
|
|
|
|
|
|
|
namespace vm {
|
|
|
|
|
2007-09-25 23:53:11 +00:00
|
|
|
Processor*
|
2008-01-13 22:05:08 +00:00
|
|
|
makeProcessor(System* system, Allocator* allocator)
|
2007-09-24 01:39:03 +00:00
|
|
|
{
|
2008-04-13 18:15:04 +00:00
|
|
|
return new (allocator->allocate(sizeof(MyProcessor)))
|
2008-01-13 22:05:08 +00:00
|
|
|
MyProcessor(system, allocator);
|
2007-09-24 01:39:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace vm
|