2007-09-24 01:39:03 +00:00
|
|
|
#include "common.h"
|
|
|
|
#include "system.h"
|
|
|
|
#include "constants.h"
|
|
|
|
#include "machine.h"
|
2007-09-26 23:23:03 +00:00
|
|
|
#include "processor.h"
|
|
|
|
#include "process.h"
|
2007-09-24 01:39:03 +00:00
|
|
|
|
|
|
|
using namespace vm;
|
|
|
|
|
2007-09-26 23:23:03 +00:00
|
|
|
extern "C" uint64_t
|
|
|
|
vmInvoke(void* function, void* stack, unsigned stackSize,
|
|
|
|
unsigned returnType);
|
|
|
|
|
2007-10-04 03:19:39 +00:00
|
|
|
extern "C" void
|
|
|
|
vmCall();
|
|
|
|
|
2007-10-02 00:08:17 +00:00
|
|
|
extern "C" void NO_RETURN
|
2007-10-04 22:41:19 +00:00
|
|
|
vmJump(void* address, void* base, void* stack);
|
2007-10-02 00:08:17 +00:00
|
|
|
|
2007-09-24 01:39:03 +00:00
|
|
|
namespace {
|
|
|
|
|
2007-10-04 00:41:54 +00:00
|
|
|
const bool Verbose = true;
|
2007-09-30 15:52:21 +00:00
|
|
|
|
2007-09-26 23:23:03 +00:00
|
|
|
const unsigned FrameThread = BytesPerWord * 2;
|
|
|
|
const unsigned FrameMethod = FrameThread + BytesPerWord;
|
2007-10-04 00:41:54 +00:00
|
|
|
const unsigned FrameNext = FrameMethod + BytesPerWord;
|
2007-09-26 23:23:03 +00:00
|
|
|
const unsigned FrameFootprint = BytesPerWord * 3;
|
2007-09-25 23:53:11 +00:00
|
|
|
|
2007-10-01 15:19:15 +00:00
|
|
|
class ArgumentList;
|
|
|
|
|
2007-10-03 00:22:48 +00:00
|
|
|
class Buffer {
|
|
|
|
public:
|
|
|
|
Buffer(System* s, unsigned minimumCapacity):
|
|
|
|
s(s),
|
|
|
|
data(0),
|
|
|
|
position(0),
|
|
|
|
capacity(0),
|
|
|
|
minimumCapacity(minimumCapacity)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
~Buffer() {
|
|
|
|
if (data) {
|
|
|
|
s->free(data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ensure(unsigned space) {
|
|
|
|
if (position + space > capacity) {
|
|
|
|
unsigned newCapacity = max
|
|
|
|
(position + space, max(minimumCapacity, capacity * 2));
|
|
|
|
uint8_t* newData = static_cast<uint8_t*>(s->allocate(newCapacity));
|
|
|
|
if (data) {
|
|
|
|
memcpy(newData, data, position);
|
|
|
|
s->free(data);
|
|
|
|
}
|
|
|
|
data = newData;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void append(uint8_t v) {
|
|
|
|
ensure(1);
|
|
|
|
data[position++] = v;
|
|
|
|
}
|
|
|
|
|
|
|
|
void append2(uint16_t v) {
|
|
|
|
ensure(2);
|
|
|
|
memcpy(data + position, &v, 2);
|
|
|
|
position += 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
void append4(uint32_t v) {
|
|
|
|
ensure(4);
|
|
|
|
memcpy(data + position, &v, 4);
|
|
|
|
position += 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
void set2(unsigned offset, uint32_t v) {
|
|
|
|
assert(s, offset + 2 <= position);
|
|
|
|
memcpy(data + offset, &v, 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
void set4(unsigned offset, uint32_t v) {
|
|
|
|
assert(s, offset + 4 <= position);
|
|
|
|
memcpy(data + offset, &v, 4);
|
|
|
|
}
|
|
|
|
|
2007-10-12 17:56:43 +00:00
|
|
|
uint8_t& get(unsigned offset) {
|
2007-10-11 22:43:03 +00:00
|
|
|
assert(s, offset + 1 <= position);
|
|
|
|
return data[offset];
|
|
|
|
}
|
|
|
|
|
2007-10-12 17:56:43 +00:00
|
|
|
uint16_t& get2(unsigned offset) {
|
2007-10-03 00:22:48 +00:00
|
|
|
assert(s, offset + 2 <= position);
|
2007-10-12 17:56:43 +00:00
|
|
|
return *reinterpret_cast<uint16_t*>(data + offset);
|
2007-10-03 00:22:48 +00:00
|
|
|
}
|
|
|
|
|
2007-10-12 17:56:43 +00:00
|
|
|
uint32_t& get4(unsigned offset) {
|
2007-10-03 00:22:48 +00:00
|
|
|
assert(s, offset + 4 <= position);
|
2007-10-12 17:56:43 +00:00
|
|
|
return *reinterpret_cast<uint32_t*>(data + offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
uintptr_t& getAddress(unsigned offset) {
|
|
|
|
assert(s, offset + 4 <= position);
|
|
|
|
return *reinterpret_cast<uintptr_t*>(data + offset);
|
2007-10-03 00:22:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void appendAddress(uintptr_t v) {
|
|
|
|
append4(v);
|
|
|
|
if (BytesPerWord == 8) {
|
|
|
|
// we have to use the preprocessor here to avoid a warning on
|
|
|
|
// 32-bit systems
|
|
|
|
#ifdef __x86_64__
|
|
|
|
append4(v >> 32);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned length() {
|
|
|
|
return position;
|
|
|
|
}
|
|
|
|
|
|
|
|
void copyTo(void* b) {
|
|
|
|
if (data) {
|
|
|
|
memcpy(b, data, position);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
System* s;
|
|
|
|
uint8_t* data;
|
|
|
|
unsigned position;
|
|
|
|
unsigned capacity;
|
|
|
|
unsigned minimumCapacity;
|
|
|
|
};
|
|
|
|
|
2007-10-10 22:39:40 +00:00
|
|
|
class StackMapper {
|
|
|
|
public:
|
|
|
|
static const uint32_t Infinity = ~static_cast<uint32_t>(0);
|
|
|
|
|
|
|
|
enum {
|
2007-10-11 22:43:03 +00:00
|
|
|
Call,
|
2007-10-10 22:39:40 +00:00
|
|
|
PushLong,
|
|
|
|
PushInt,
|
|
|
|
PushObject,
|
|
|
|
Duplicate,
|
2007-10-12 00:30:46 +00:00
|
|
|
Pop,
|
2007-10-10 22:39:40 +00:00
|
|
|
PopLong,
|
|
|
|
PopInt,
|
|
|
|
PopObject,
|
2007-10-13 21:48:40 +00:00
|
|
|
StoreLong,
|
|
|
|
StoreInt,
|
2007-10-10 22:39:40 +00:00
|
|
|
StoreObject,
|
2007-10-11 22:43:03 +00:00
|
|
|
Return,
|
2007-10-10 22:39:40 +00:00
|
|
|
Jump,
|
2007-10-11 22:43:03 +00:00
|
|
|
Branch,
|
|
|
|
End
|
2007-10-10 22:39:40 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
StackMapper(Thread* t, object method):
|
|
|
|
t(t),
|
|
|
|
method(method),
|
2007-10-11 22:43:03 +00:00
|
|
|
ip(-1),
|
2007-10-10 22:39:40 +00:00
|
|
|
index(codeSize() ? static_cast<uint32_t*>
|
|
|
|
(t->m->system->allocate(codeSize() * 4)) : 0),
|
|
|
|
log(t->m->system, 1024),
|
2007-10-13 21:48:40 +00:00
|
|
|
callCount(0),
|
|
|
|
protector(this)
|
2007-10-10 22:39:40 +00:00
|
|
|
{ }
|
|
|
|
|
|
|
|
~StackMapper() {
|
|
|
|
if (index) {
|
|
|
|
t->m->system->free(index);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned codeSize() {
|
|
|
|
return codeLength(t, methodCode(t, method));
|
|
|
|
}
|
|
|
|
|
2007-10-11 22:43:03 +00:00
|
|
|
void end(unsigned nextIp) {
|
|
|
|
if (ip >= 0) {
|
|
|
|
log.append(End);
|
|
|
|
log.append2(nextIp);
|
|
|
|
}
|
|
|
|
ip = nextIp;
|
|
|
|
}
|
|
|
|
|
2007-10-10 22:39:40 +00:00
|
|
|
void newIp(unsigned javaIp) {
|
|
|
|
assert(t, javaIp < codeSize());
|
2007-10-11 22:43:03 +00:00
|
|
|
|
|
|
|
end(javaIp);
|
2007-10-10 22:39:40 +00:00
|
|
|
index[javaIp] = log.length();
|
|
|
|
}
|
|
|
|
|
2007-10-11 22:43:03 +00:00
|
|
|
void finish() {
|
|
|
|
end(codeSize());
|
|
|
|
}
|
|
|
|
|
|
|
|
void called(unsigned nextMachineIp) {
|
|
|
|
log.append(Call);
|
|
|
|
log.append4(nextMachineIp);
|
|
|
|
++ callCount;
|
2007-10-10 22:39:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void pushedLong() {
|
|
|
|
log.append(PushLong);
|
|
|
|
}
|
|
|
|
|
|
|
|
void pushedInt() {
|
|
|
|
log.append(PushInt);
|
|
|
|
}
|
|
|
|
|
|
|
|
void pushedObject() {
|
|
|
|
log.append(PushObject);
|
|
|
|
}
|
|
|
|
|
|
|
|
void dupped() {
|
|
|
|
log.append(Duplicate);
|
|
|
|
}
|
|
|
|
|
2007-10-12 00:30:46 +00:00
|
|
|
void popped(unsigned count) {
|
|
|
|
log.append(Pop);
|
|
|
|
log.append(count);
|
|
|
|
}
|
|
|
|
|
2007-10-10 22:39:40 +00:00
|
|
|
void poppedLong() {
|
|
|
|
log.append(PopLong);
|
|
|
|
}
|
|
|
|
|
|
|
|
void poppedInt() {
|
|
|
|
log.append(PopInt);
|
|
|
|
}
|
|
|
|
|
|
|
|
void poppedObject() {
|
|
|
|
log.append(PopObject);
|
|
|
|
}
|
|
|
|
|
2007-10-13 21:48:40 +00:00
|
|
|
void storedLong(unsigned index) {
|
|
|
|
if (index >= parameterFootprint()) {
|
|
|
|
log.append(StoreLong);
|
|
|
|
log.append2(index - parameterFootprint());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void storedInt(unsigned index) {
|
|
|
|
if (index >= parameterFootprint()) {
|
|
|
|
log.append(StoreInt);
|
|
|
|
log.append2(index - parameterFootprint());
|
|
|
|
}
|
2007-10-10 22:39:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void storedObject(unsigned index) {
|
2007-10-13 21:48:40 +00:00
|
|
|
if (index >= parameterFootprint()) {
|
|
|
|
log.append(StoreObject);
|
|
|
|
log.append2(index - parameterFootprint());
|
|
|
|
}
|
2007-10-10 22:39:40 +00:00
|
|
|
}
|
|
|
|
|
2007-10-12 00:30:46 +00:00
|
|
|
void exited() {
|
2007-10-11 22:43:03 +00:00
|
|
|
log.append(Return);
|
2007-10-10 22:39:40 +00:00
|
|
|
}
|
|
|
|
|
2007-10-11 22:43:03 +00:00
|
|
|
void jumped(unsigned targetJavaIp) {
|
2007-10-10 22:39:40 +00:00
|
|
|
log.append(Jump);
|
2007-10-11 22:43:03 +00:00
|
|
|
log.append2(targetJavaIp);
|
2007-10-10 22:39:40 +00:00
|
|
|
}
|
|
|
|
|
2007-10-11 22:43:03 +00:00
|
|
|
void branched(unsigned targetJavaIp) {
|
2007-10-10 22:39:40 +00:00
|
|
|
log.append(Branch);
|
2007-10-11 22:43:03 +00:00
|
|
|
log.append2(targetJavaIp);
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned parameterFootprint() {
|
|
|
|
return methodParameterFootprint(t, method);
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned localSize() {
|
|
|
|
return codeMaxLocals(t, methodCode(t, method))
|
|
|
|
- parameterFootprint();
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned stackSize() {
|
|
|
|
return codeMaxStack(t, methodCode(t, method));
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned mapSize() {
|
|
|
|
return stackSize() + localSize();
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned mapSizeInWords() {
|
|
|
|
return ceiling(mapSize(), BytesPerWord);
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned mapSizeInBytes() {
|
|
|
|
return mapSizeInWords() * BytesPerWord;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned callTableSize() {
|
|
|
|
return callCount * (mapSizeInBytes() + BytesPerWord);
|
|
|
|
}
|
|
|
|
|
|
|
|
void populateCalls(uintptr_t* calls, unsigned& callIndex, uintptr_t* table,
|
|
|
|
uintptr_t* mask, uintptr_t* initialMap,
|
|
|
|
unsigned initialSp, unsigned ip)
|
|
|
|
{
|
|
|
|
uintptr_t map[mapSizeInWords()];
|
|
|
|
memcpy(map, initialMap, mapSizeInBytes());
|
|
|
|
|
|
|
|
unsigned sp = initialSp;
|
|
|
|
|
|
|
|
while (ip < codeSize()) {
|
|
|
|
if (getBit(mask, ip)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
markBit(mask, ip);
|
|
|
|
memcpy(table + (ip * mapSizeInWords()), map, mapSizeInBytes());
|
|
|
|
|
|
|
|
unsigned i = index[ip];
|
|
|
|
while (true) {
|
|
|
|
switch (log.get(i++)) {
|
|
|
|
case Call: {
|
|
|
|
assert(t, callIndex < callCount);
|
|
|
|
unsigned machineIp = log.get4(i); i += 4;
|
|
|
|
calls[callIndex * (mapSizeInWords() + 1)] = machineIp;
|
|
|
|
memcpy(calls + (callIndex * (mapSizeInWords() + 1)) + 1,
|
|
|
|
map, mapSizeInBytes());
|
|
|
|
++ callIndex;
|
2007-10-13 21:48:40 +00:00
|
|
|
|
|
|
|
// fprintf(stderr,
|
|
|
|
// "call stack and locals 0x%x of size %d at %d of %s.%s\n",
|
|
|
|
// *map,
|
|
|
|
// mapSize(),
|
|
|
|
// machineIp,
|
|
|
|
// &byteArrayBody
|
|
|
|
// (t, className(t, methodClass(t, method)), 0),
|
|
|
|
// &byteArrayBody(t, methodName(t, method), 0));
|
|
|
|
|
2007-10-11 22:43:03 +00:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case PushLong:
|
|
|
|
assert(t, sp + 2 <= mapSize());
|
2007-10-12 00:30:46 +00:00
|
|
|
assert(t, getBit(map, sp) == 0);
|
|
|
|
assert(t, getBit(map, sp + 1) == 0);
|
2007-10-11 22:43:03 +00:00
|
|
|
sp += 2;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PushInt:
|
|
|
|
assert(t, sp + 1 <= mapSize());
|
2007-10-12 00:30:46 +00:00
|
|
|
assert(t, getBit(map, sp) == 0);
|
2007-10-11 22:43:03 +00:00
|
|
|
++ sp;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PushObject:
|
|
|
|
assert(t, sp + 1 <= mapSize());
|
|
|
|
markBit(map, sp++);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Duplicate:
|
|
|
|
assert(t, sp + 1 <= mapSize());
|
|
|
|
assert(t, sp - 1 >= localSize());
|
|
|
|
if (getBit(map, sp - 1)) {
|
|
|
|
markBit(map, sp);
|
|
|
|
}
|
|
|
|
++ sp;
|
|
|
|
break;
|
|
|
|
|
2007-10-12 00:30:46 +00:00
|
|
|
case Pop: {
|
|
|
|
unsigned count = log.get(i++);
|
|
|
|
assert(t, sp >= count);
|
|
|
|
assert(t, sp - count >= localSize());
|
|
|
|
while (count) {
|
|
|
|
clearBit(map, -- sp);
|
|
|
|
-- count;
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
2007-10-11 22:43:03 +00:00
|
|
|
case PopLong:
|
2007-10-12 00:30:46 +00:00
|
|
|
assert(t, sp >= 2);
|
2007-10-11 22:43:03 +00:00
|
|
|
assert(t, sp - 2 >= localSize());
|
|
|
|
assert(t, getBit(map, sp - 1) == 0);
|
|
|
|
assert(t, getBit(map, sp - 2) == 0);
|
|
|
|
sp -= 2;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PopInt:
|
2007-10-12 00:30:46 +00:00
|
|
|
assert(t, sp >= 1);
|
2007-10-11 22:43:03 +00:00
|
|
|
assert(t, sp - 1 >= localSize());
|
|
|
|
assert(t, getBit(map, sp - 1) == 0);
|
|
|
|
-- sp;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PopObject:
|
2007-10-12 00:30:46 +00:00
|
|
|
assert(t, sp >= 1);
|
2007-10-11 22:43:03 +00:00
|
|
|
assert(t, sp - 1 >= localSize());
|
|
|
|
assert(t, getBit(map, sp - 1) != 0);
|
|
|
|
clearBit(map, -- sp);
|
|
|
|
break;
|
|
|
|
|
2007-10-13 21:48:40 +00:00
|
|
|
case StoreLong: {
|
|
|
|
unsigned index = log.get2(i); i += 2;
|
|
|
|
assert(t, index + 1 < localSize());
|
|
|
|
clearBit(map, index);
|
|
|
|
clearBit(map, index + 1);
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case StoreInt: {
|
|
|
|
unsigned index = log.get2(i); i += 2;
|
|
|
|
assert(t, index < localSize());
|
|
|
|
clearBit(map, index);
|
|
|
|
} break;
|
2007-10-11 22:43:03 +00:00
|
|
|
|
|
|
|
case StoreObject: {
|
|
|
|
unsigned index = log.get2(i); i += 2;
|
|
|
|
assert(t, index < localSize());
|
|
|
|
markBit(map, index);
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case Return:
|
|
|
|
ip = codeSize();
|
|
|
|
goto loop;
|
|
|
|
|
|
|
|
case Jump:
|
|
|
|
ip = log.get2(i); i += 2;
|
|
|
|
assert(t, ip < codeSize());
|
|
|
|
goto loop;
|
|
|
|
|
|
|
|
case Branch: {
|
|
|
|
unsigned target = log.get2(i); i += 2;
|
|
|
|
assert(t, target < codeSize());
|
|
|
|
populateCalls(calls, callIndex, table, mask, map, sp, target);
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case End:
|
|
|
|
goto next;
|
|
|
|
|
|
|
|
default:
|
|
|
|
abort(t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
next:
|
|
|
|
ip = log.get2(i);
|
|
|
|
|
|
|
|
loop:;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int compareCalls(const void* a, const void* b) {
|
|
|
|
return (*static_cast<const uintptr_t*>(a) >
|
|
|
|
*static_cast<const uintptr_t*>(b) ? 1 : -1);
|
2007-10-10 22:39:40 +00:00
|
|
|
}
|
|
|
|
|
2007-10-11 22:43:03 +00:00
|
|
|
void writeCallTableTo(uintptr_t* calls) {
|
|
|
|
uintptr_t* table = static_cast<uintptr_t*>
|
|
|
|
(t->m->system->allocate(codeSize() * mapSizeInBytes()));
|
|
|
|
|
|
|
|
uintptr_t* mask = static_cast<uintptr_t*>
|
|
|
|
(t->m->system->allocate
|
|
|
|
(ceiling(codeSize(), BytesPerWord) * BytesPerWord));
|
|
|
|
memset(mask, 0, ceiling(codeSize(), BytesPerWord) * BytesPerWord);
|
|
|
|
|
|
|
|
uintptr_t map[mapSizeInWords()];
|
2007-10-13 21:48:40 +00:00
|
|
|
memset(map, 0, mapSizeInBytes());
|
2007-10-11 22:43:03 +00:00
|
|
|
|
|
|
|
unsigned callIndex = 0;
|
|
|
|
|
|
|
|
populateCalls(calls, callIndex, table, mask, map, localSize(), 0);
|
|
|
|
|
|
|
|
object eht = codeExceptionHandlerTable(t, methodCode(t, method));
|
|
|
|
if (eht) {
|
|
|
|
PROTECT(t, eht);
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < exceptionHandlerTableLength(t, eht); ++i) {
|
|
|
|
ExceptionHandler* eh = exceptionHandlerTableBody(t, eht, i);
|
|
|
|
|
|
|
|
assert(t, getBit(mask, exceptionHandlerStart(eh)));
|
|
|
|
|
|
|
|
memcpy(map,
|
2007-10-12 14:26:36 +00:00
|
|
|
table + (exceptionHandlerStart(eh) * mapSizeInWords()),
|
2007-10-11 22:43:03 +00:00
|
|
|
mapSizeInBytes());
|
|
|
|
|
|
|
|
for (unsigned j = localSize() + 1; j < mapSize(); ++j) {
|
|
|
|
clearBit(map, j);
|
|
|
|
}
|
|
|
|
|
|
|
|
markBit(map, localSize());
|
|
|
|
|
|
|
|
populateCalls(calls, callIndex, table, mask, map, localSize() + 1,
|
|
|
|
exceptionHandlerIp(eh));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
t->m->system->free(mask);
|
2007-10-12 14:26:36 +00:00
|
|
|
t->m->system->free(table);
|
2007-10-11 22:43:03 +00:00
|
|
|
|
|
|
|
assert(t, callIndex == callCount);
|
|
|
|
qsort(calls, callCount, mapSizeInBytes() + BytesPerWord, compareCalls);
|
2007-10-10 22:39:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Thread* t;
|
|
|
|
object method;
|
2007-10-11 22:43:03 +00:00
|
|
|
int ip;
|
2007-10-10 22:39:40 +00:00
|
|
|
uint32_t* index;
|
|
|
|
Buffer log;
|
2007-10-11 22:43:03 +00:00
|
|
|
unsigned callCount;
|
2007-10-13 21:48:40 +00:00
|
|
|
|
|
|
|
class MyProtector: public Thread::Protector {
|
|
|
|
public:
|
|
|
|
MyProtector(StackMapper* mapper): Protector(mapper->t), mapper(mapper) { }
|
|
|
|
|
|
|
|
virtual void visit(Heap::Visitor* v) {
|
|
|
|
v->visit(&(mapper->method));
|
|
|
|
}
|
|
|
|
|
|
|
|
StackMapper* mapper;
|
|
|
|
} protector;
|
2007-10-10 22:39:40 +00:00
|
|
|
};
|
|
|
|
|
2007-10-01 15:19:15 +00:00
|
|
|
class MyThread: public Thread {
|
|
|
|
public:
|
|
|
|
MyThread(Machine* m, object javaThread, vm::Thread* parent):
|
|
|
|
vm::Thread(m, javaThread, parent),
|
|
|
|
argumentList(0),
|
|
|
|
frame(0),
|
|
|
|
reference(0)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
ArgumentList* argumentList;
|
|
|
|
void* frame;
|
|
|
|
Reference* reference;
|
|
|
|
};
|
|
|
|
|
2007-10-04 00:41:54 +00:00
|
|
|
inline void*
|
|
|
|
frameBase(void* frame)
|
2007-10-02 00:08:17 +00:00
|
|
|
{
|
2007-10-04 22:41:19 +00:00
|
|
|
return static_cast<void**>(frame)
|
|
|
|
[static_cast<int>(- (FrameFootprint / BytesPerWord) - 2)];
|
2007-10-02 00:08:17 +00:00
|
|
|
}
|
|
|
|
|
2007-10-04 00:41:54 +00:00
|
|
|
inline bool
|
|
|
|
frameValid(void* frame)
|
2007-10-02 00:08:17 +00:00
|
|
|
{
|
2007-10-04 03:19:39 +00:00
|
|
|
return frame != 0;
|
2007-10-02 00:08:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
inline void*
|
|
|
|
frameNext(void* frame)
|
|
|
|
{
|
2007-10-04 03:19:39 +00:00
|
|
|
return static_cast<void**>(frameBase(frame))[FrameNext / BytesPerWord];
|
2007-10-02 00:08:17 +00:00
|
|
|
}
|
|
|
|
|
2007-10-12 17:56:43 +00:00
|
|
|
inline object&
|
2007-10-02 00:08:17 +00:00
|
|
|
frameMethod(void* frame)
|
|
|
|
{
|
|
|
|
return static_cast<object*>(frameBase(frame))[FrameMethod / BytesPerWord];
|
|
|
|
}
|
|
|
|
|
2007-10-03 00:22:48 +00:00
|
|
|
inline void*
|
2007-10-02 00:08:17 +00:00
|
|
|
frameAddress(void* frame)
|
|
|
|
{
|
2007-10-04 22:41:19 +00:00
|
|
|
return static_cast<void**>(frame)
|
|
|
|
[static_cast<int>(- (FrameFootprint / BytesPerWord) - 1)];
|
2007-10-02 00:08:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
inline void*
|
|
|
|
frameReturnAddress(void* frame)
|
|
|
|
{
|
|
|
|
return static_cast<void**>(frameBase(frame))[1];
|
|
|
|
}
|
|
|
|
|
2007-10-04 00:41:54 +00:00
|
|
|
inline uint8_t*
|
|
|
|
compiledCode(Compiled* code)
|
|
|
|
{
|
|
|
|
return compiledBody(code);
|
|
|
|
}
|
|
|
|
|
2007-10-04 22:41:19 +00:00
|
|
|
inline unsigned
|
|
|
|
compiledLineNumberCount(Thread*, Compiled* code)
|
|
|
|
{
|
|
|
|
return compiledLineNumberTableLength(code) / sizeof(NativeLineNumber);
|
|
|
|
}
|
|
|
|
|
2007-10-04 00:41:54 +00:00
|
|
|
inline NativeLineNumber*
|
|
|
|
compiledLineNumber(Thread* t, Compiled* code, unsigned index)
|
|
|
|
{
|
2007-10-04 22:41:19 +00:00
|
|
|
assert(t, index < compiledLineNumberCount(t, code));
|
2007-10-04 00:41:54 +00:00
|
|
|
return reinterpret_cast<NativeLineNumber*>
|
2007-10-04 22:41:19 +00:00
|
|
|
(compiledBody(code) + pad(compiledCodeLength(code))) + index;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline unsigned
|
|
|
|
compiledExceptionHandlerCount(Thread*, Compiled* code)
|
|
|
|
{
|
|
|
|
return compiledExceptionHandlerTableLength(code)
|
|
|
|
/ sizeof(NativeExceptionHandler);
|
2007-10-04 00:41:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
inline NativeExceptionHandler*
|
|
|
|
compiledExceptionHandler(Thread* t, Compiled* code, unsigned index)
|
|
|
|
{
|
2007-10-04 22:41:19 +00:00
|
|
|
assert(t, index < compiledExceptionHandlerCount(t, code));
|
2007-10-04 00:41:54 +00:00
|
|
|
return reinterpret_cast<NativeExceptionHandler*>
|
2007-10-10 22:39:40 +00:00
|
|
|
(compiledBody(code)
|
|
|
|
+ pad(compiledCodeLength(code))
|
2007-10-04 22:41:19 +00:00
|
|
|
+ pad(compiledLineNumberTableLength(code))) + index;
|
2007-10-04 00:41:54 +00:00
|
|
|
}
|
|
|
|
|
2007-10-10 22:39:40 +00:00
|
|
|
inline unsigned
|
|
|
|
compiledStackMapSize(Thread*, Compiled* code)
|
|
|
|
{
|
|
|
|
return ceiling(compiledMaxStack(code)
|
|
|
|
+ compiledMaxLocals(code)
|
|
|
|
- compiledParameterFootprint(code),
|
2007-10-11 22:43:03 +00:00
|
|
|
BytesPerWord) + 1;
|
2007-10-10 22:39:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
inline unsigned
|
|
|
|
compiledStackMapCount(Thread* t, Compiled* code)
|
|
|
|
{
|
|
|
|
return compiledStackMapTableLength(code)
|
|
|
|
/ (compiledStackMapSize(t, code) * BytesPerWord);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline uintptr_t*
|
|
|
|
compiledStackMap(Thread* t, Compiled* code, unsigned index)
|
|
|
|
{
|
|
|
|
assert(t, index < compiledStackMapCount(t, code));
|
|
|
|
return reinterpret_cast<uintptr_t*>
|
|
|
|
(compiledBody(code)
|
|
|
|
+ pad(compiledCodeLength(code))
|
|
|
|
+ pad(compiledLineNumberTableLength(code))
|
|
|
|
+ pad(compiledExceptionHandlerTableLength(code)))
|
|
|
|
+ (index * compiledStackMapSize(t, code));
|
|
|
|
}
|
|
|
|
|
|
|
|
inline Compiled*
|
|
|
|
makeCompiled(Thread* t, Buffer* code)
|
|
|
|
{
|
|
|
|
Compiled* c = static_cast<Compiled*>
|
|
|
|
(t->m->system->allocate(sizeof(Compiled) + pad(code->length())));
|
|
|
|
|
|
|
|
compiledMaxLocals(c) = 0;
|
|
|
|
compiledMaxStack(c) = 0;
|
|
|
|
compiledParameterFootprint(c) = 0;
|
|
|
|
compiledCodeLength(c) = code->length();
|
|
|
|
compiledLineNumberTableLength(c) = 0;
|
|
|
|
compiledExceptionHandlerTableLength(c) = 0;
|
|
|
|
compiledStackMapTableLength(c) = 0;
|
|
|
|
|
|
|
|
if (code->length()) {
|
|
|
|
code->copyTo(compiledCode(c));
|
|
|
|
}
|
|
|
|
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
2007-10-04 00:41:54 +00:00
|
|
|
inline Compiled*
|
2007-10-10 17:26:28 +00:00
|
|
|
makeCompiled(Thread* t, object method, Buffer* code,
|
|
|
|
NativeLineNumber* lineNumbers,
|
2007-10-10 22:39:40 +00:00
|
|
|
NativeExceptionHandler* exceptionHandlers,
|
|
|
|
StackMapper* stackMapper)
|
2007-10-04 00:41:54 +00:00
|
|
|
{
|
2007-10-10 17:26:28 +00:00
|
|
|
unsigned lineNumberCount
|
2007-10-10 22:39:40 +00:00
|
|
|
= codeLineNumberTable(t, methodCode(t, method)) ?
|
2007-10-10 17:26:28 +00:00
|
|
|
lineNumberTableLength
|
|
|
|
(t, codeLineNumberTable(t, methodCode(t, method))) : 0;
|
2007-10-10 22:39:40 +00:00
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
unsigned exceptionHandlerCount
|
2007-10-10 22:39:40 +00:00
|
|
|
= codeExceptionHandlerTable(t, methodCode(t, method)) ?
|
2007-10-10 17:26:28 +00:00
|
|
|
exceptionHandlerTableLength
|
|
|
|
(t, codeExceptionHandlerTable(t, methodCode(t, method))) : 0;
|
|
|
|
|
2007-10-10 22:39:40 +00:00
|
|
|
unsigned maxStack = codeMaxStack(t, methodCode(t, method));
|
|
|
|
unsigned maxLocals = codeMaxLocals(t, methodCode(t, method));
|
|
|
|
unsigned parameterFootprint = methodParameterFootprint(t, method);
|
|
|
|
|
2007-10-04 00:41:54 +00:00
|
|
|
Compiled* c = static_cast<Compiled*>
|
|
|
|
(t->m->system->allocate(sizeof(Compiled)
|
|
|
|
+ pad(code->length())
|
2007-10-10 22:39:40 +00:00
|
|
|
+ pad(lineNumberCount
|
|
|
|
* sizeof(NativeLineNumber))
|
2007-10-10 17:26:28 +00:00
|
|
|
+ pad(exceptionHandlerCount
|
2007-10-10 22:39:40 +00:00
|
|
|
* sizeof(NativeExceptionHandler))
|
2007-10-11 22:43:03 +00:00
|
|
|
+ pad(stackMapper->callTableSize())));
|
2007-10-10 22:39:40 +00:00
|
|
|
|
2007-10-13 21:48:40 +00:00
|
|
|
compiledMaxLocals(c) = maxLocals;
|
|
|
|
compiledMaxStack(c) = maxStack;
|
2007-10-10 22:39:40 +00:00
|
|
|
compiledParameterFootprint(c) = parameterFootprint;
|
2007-10-04 00:41:54 +00:00
|
|
|
compiledCodeLength(c) = code->length();
|
2007-10-10 22:39:40 +00:00
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
compiledLineNumberTableLength(c)
|
|
|
|
= lineNumberCount * sizeof(NativeLineNumber);
|
2007-10-10 22:39:40 +00:00
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
compiledExceptionHandlerTableLength(c)
|
|
|
|
= exceptionHandlerCount * sizeof(NativeExceptionHandler);
|
2007-10-04 00:41:54 +00:00
|
|
|
|
2007-10-11 22:43:03 +00:00
|
|
|
compiledStackMapTableLength(c) = stackMapper->callTableSize();
|
2007-10-10 22:39:40 +00:00
|
|
|
|
2007-10-04 00:41:54 +00:00
|
|
|
if (code->length()) {
|
|
|
|
code->copyTo(compiledCode(c));
|
|
|
|
}
|
2007-10-10 22:39:40 +00:00
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
if (lineNumberCount) {
|
|
|
|
memcpy(compiledLineNumber(t, c, 0),
|
|
|
|
lineNumbers,
|
|
|
|
lineNumberCount * sizeof(NativeLineNumber));
|
2007-10-04 00:41:54 +00:00
|
|
|
}
|
2007-10-10 22:39:40 +00:00
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
if (exceptionHandlerCount) {
|
|
|
|
memcpy(compiledExceptionHandler(t, c, 0),
|
|
|
|
exceptionHandlers,
|
|
|
|
exceptionHandlerCount * sizeof(NativeExceptionHandler));
|
2007-10-04 00:41:54 +00:00
|
|
|
}
|
|
|
|
|
2007-10-12 00:30:46 +00:00
|
|
|
if (stackMapper->callTableSize()) {
|
2007-10-11 22:43:03 +00:00
|
|
|
stackMapper->writeCallTableTo(compiledStackMap(t, c, 0));
|
2007-10-10 22:39:40 +00:00
|
|
|
}
|
|
|
|
|
2007-10-04 00:41:54 +00:00
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
2007-10-03 00:22:48 +00:00
|
|
|
inline unsigned
|
|
|
|
addressOffset(Thread* t, object method, void* address)
|
2007-10-02 00:08:17 +00:00
|
|
|
{
|
2007-10-04 00:41:54 +00:00
|
|
|
Compiled* code = reinterpret_cast<Compiled*>(methodCompiled(t, method));
|
|
|
|
return static_cast<uint8_t*>(address) - compiledCode(code);
|
2007-10-02 00:08:17 +00:00
|
|
|
}
|
|
|
|
|
2007-10-03 01:54:21 +00:00
|
|
|
NativeExceptionHandler*
|
2007-10-03 00:22:48 +00:00
|
|
|
findExceptionHandler(Thread* t, void* frame)
|
2007-10-02 00:08:17 +00:00
|
|
|
{
|
2007-10-03 00:22:48 +00:00
|
|
|
object method = frameMethod(frame);
|
2007-10-04 00:41:54 +00:00
|
|
|
Compiled* code = reinterpret_cast<Compiled*>(methodCompiled(t, method));
|
2007-10-03 00:22:48 +00:00
|
|
|
|
2007-10-04 22:41:19 +00:00
|
|
|
for (unsigned i = 0; i < compiledExceptionHandlerCount(t, code); ++i) {
|
2007-10-04 00:41:54 +00:00
|
|
|
NativeExceptionHandler* handler = compiledExceptionHandler(t, code, i);
|
2007-10-03 00:22:48 +00:00
|
|
|
unsigned offset = addressOffset(t, method, frameAddress(frame));
|
|
|
|
|
2007-10-03 01:54:21 +00:00
|
|
|
if (offset - 1 >= nativeExceptionHandlerStart(handler)
|
|
|
|
and offset - 1 < nativeExceptionHandlerEnd(handler))
|
2007-10-03 00:22:48 +00:00
|
|
|
{
|
|
|
|
object catchType;
|
2007-10-03 01:54:21 +00:00
|
|
|
if (nativeExceptionHandlerCatchType(handler)) {
|
2007-10-03 00:22:48 +00:00
|
|
|
catchType = arrayBody
|
2007-10-03 01:54:21 +00:00
|
|
|
(t, methodCode(t, method),
|
|
|
|
nativeExceptionHandlerCatchType(handler) - 1);
|
2007-10-03 00:22:48 +00:00
|
|
|
} else {
|
|
|
|
catchType = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (catchType == 0 or instanceOf(t, catchType, t->exception)) {
|
2007-10-04 22:41:19 +00:00
|
|
|
fprintf(stderr, "exception handler match for %d in %s: "
|
|
|
|
"start: %d; end: %d; ip: %d\n",
|
|
|
|
offset,
|
|
|
|
&byteArrayBody(t, methodName(t, frameMethod(frame)), 0),
|
|
|
|
nativeExceptionHandlerStart(handler),
|
|
|
|
nativeExceptionHandlerEnd(handler),
|
|
|
|
nativeExceptionHandlerIp(handler));
|
|
|
|
|
2007-10-03 00:22:48 +00:00
|
|
|
return handler;
|
|
|
|
}
|
2007-10-02 00:08:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-10-03 00:22:48 +00:00
|
|
|
return 0;
|
2007-10-02 00:08:17 +00:00
|
|
|
}
|
|
|
|
|
2007-10-01 15:19:15 +00:00
|
|
|
void NO_RETURN
|
2007-10-03 00:22:48 +00:00
|
|
|
unwind(MyThread* t)
|
2007-09-29 21:08:29 +00:00
|
|
|
{
|
2007-10-02 00:08:17 +00:00
|
|
|
for (void* frame = t->frame; frameValid(frame); frame = frameNext(frame)) {
|
2007-10-04 22:41:19 +00:00
|
|
|
if ((methodFlags(t, frameMethod(frame)) & ACC_NATIVE) == 0) {
|
2007-10-03 01:54:21 +00:00
|
|
|
NativeExceptionHandler* eh = findExceptionHandler(t, frame);
|
2007-10-02 00:08:17 +00:00
|
|
|
if (eh) {
|
2007-10-04 22:41:19 +00:00
|
|
|
object method = frameMethod(frame);
|
2007-10-04 00:41:54 +00:00
|
|
|
Compiled* code = reinterpret_cast<Compiled*>
|
2007-10-04 22:41:19 +00:00
|
|
|
(methodCompiled(t, method));
|
2007-10-02 00:08:17 +00:00
|
|
|
t->frame = frame;
|
2007-10-04 22:41:19 +00:00
|
|
|
|
|
|
|
void** stack = static_cast<void**>(frameBase(frame));
|
|
|
|
|
|
|
|
unsigned parameterFootprint = methodParameterFootprint(t, method);
|
|
|
|
unsigned localFootprint = compiledMaxLocals(code);
|
|
|
|
|
|
|
|
if (localFootprint > parameterFootprint) {
|
|
|
|
stack -= (localFootprint - parameterFootprint);
|
|
|
|
}
|
|
|
|
|
|
|
|
*(--stack) = t->exception;
|
|
|
|
t->exception = 0;
|
|
|
|
|
2007-10-04 00:41:54 +00:00
|
|
|
vmJump(compiledCode(code) + nativeExceptionHandlerIp(eh),
|
2007-10-04 22:41:19 +00:00
|
|
|
frameBase(frame),
|
|
|
|
stack);
|
2007-10-02 00:08:17 +00:00
|
|
|
}
|
|
|
|
}
|
2007-10-04 22:41:19 +00:00
|
|
|
|
|
|
|
void* next = frameNext(frame);
|
|
|
|
if (not frameValid(next)
|
|
|
|
or methodFlags(t, frameMethod(next)) & ACC_NATIVE)
|
|
|
|
{
|
|
|
|
t->frame = next;
|
|
|
|
vmJump(frameReturnAddress(frame),
|
|
|
|
*static_cast<void**>(frameBase(frame)),
|
|
|
|
static_cast<void**>(frameBase(frame)) + 2);
|
|
|
|
}
|
2007-10-02 00:08:17 +00:00
|
|
|
}
|
2007-09-29 21:08:29 +00:00
|
|
|
abort(t);
|
|
|
|
}
|
|
|
|
|
2007-10-01 15:19:15 +00:00
|
|
|
void NO_RETURN
|
2007-10-03 00:22:48 +00:00
|
|
|
throwNew(MyThread* t, object class_)
|
2007-09-29 21:08:29 +00:00
|
|
|
{
|
|
|
|
t->exception = makeNew(t, class_);
|
2007-10-09 19:30:01 +00:00
|
|
|
object trace = makeTrace(t);
|
|
|
|
set(t, cast<object>(t->exception, ThrowableTrace), trace);
|
2007-09-29 21:08:29 +00:00
|
|
|
unwind(t);
|
|
|
|
}
|
|
|
|
|
2007-10-01 15:19:15 +00:00
|
|
|
void NO_RETURN
|
2007-10-03 00:22:48 +00:00
|
|
|
throw_(MyThread* t, object o)
|
2007-09-30 02:48:27 +00:00
|
|
|
{
|
|
|
|
if (o) {
|
|
|
|
t->exception = o;
|
2007-10-04 00:41:54 +00:00
|
|
|
} else {
|
|
|
|
t->exception = makeNullPointerException(t);
|
2007-09-30 02:48:27 +00:00
|
|
|
}
|
|
|
|
unwind(t);
|
|
|
|
}
|
|
|
|
|
2007-10-12 17:56:43 +00:00
|
|
|
uintptr_t*
|
|
|
|
frameStackMap(MyThread* t, void* frame)
|
|
|
|
{
|
|
|
|
Compiled* code = reinterpret_cast<Compiled*>
|
|
|
|
(methodCompiled(t, frameMethod(frame)));
|
|
|
|
unsigned ip = static_cast<uint8_t*>(frameAddress(frame))
|
|
|
|
- compiledCode(code);
|
|
|
|
|
|
|
|
unsigned bottom = 0;
|
|
|
|
unsigned top = compiledStackMapCount(t, code);
|
|
|
|
for (unsigned span = top - bottom; span; span = top - bottom) {
|
|
|
|
unsigned middle = bottom + (span / 2);
|
|
|
|
uintptr_t* map = compiledStackMap(t, code, middle);
|
|
|
|
|
|
|
|
if (ip < *map) {
|
|
|
|
top = middle;
|
|
|
|
} else if (ip > *map) {
|
|
|
|
bottom = middle + 1;
|
|
|
|
} else {
|
|
|
|
return map + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(stderr, "%d not found in ", ip);
|
|
|
|
for (unsigned i = 0; i < compiledStackMapCount(t, code); ++i) {
|
|
|
|
fprintf(stderr, "%"LD" ", *compiledStackMap(t, code, i));
|
|
|
|
}
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
|
|
|
|
abort(t);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
localOffset(MyThread* t, int v, object method)
|
|
|
|
{
|
|
|
|
int parameterFootprint
|
|
|
|
= methodParameterFootprint(t, method) * BytesPerWord;
|
|
|
|
|
|
|
|
v *= BytesPerWord;
|
|
|
|
if (v < parameterFootprint) {
|
|
|
|
return (parameterFootprint - v - BytesPerWord) + (BytesPerWord * 2)
|
|
|
|
+ FrameFootprint;
|
|
|
|
} else {
|
|
|
|
return -(v + BytesPerWord - parameterFootprint);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
inline object*
|
|
|
|
frameLocalObject(MyThread* t, void* frame, unsigned index)
|
|
|
|
{
|
|
|
|
return reinterpret_cast<object*>
|
|
|
|
(static_cast<uint8_t*>(frameBase(frame))
|
|
|
|
+ localOffset(t, index, frameMethod(frame)));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
visitParameters(MyThread* t, Heap::Visitor* v, void* frame)
|
|
|
|
{
|
|
|
|
object method = frameMethod(frame);
|
|
|
|
|
|
|
|
const char* spec = reinterpret_cast<const char*>
|
|
|
|
(&byteArrayBody(t, methodSpec(t, method), 0));
|
|
|
|
|
|
|
|
unsigned index = 0;
|
|
|
|
if ((methodFlags(t, method) & ACC_STATIC) == 0) {
|
|
|
|
v->visit(frameLocalObject(t, frame, index++));
|
|
|
|
}
|
|
|
|
|
|
|
|
for (MethodSpecIterator it(t, spec); it.hasNext();) {
|
|
|
|
switch (*it.next()) {
|
|
|
|
case 'L':
|
|
|
|
case '[':
|
|
|
|
v->visit(frameLocalObject(t, frame, index++));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'J':
|
|
|
|
case 'D':
|
|
|
|
index += 2;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
++ index;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(t, index == methodParameterFootprint(t, method));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
visitStackAndLocals(MyThread* t, Heap::Visitor* v, void* frame)
|
|
|
|
{
|
|
|
|
Compiled* code = reinterpret_cast<Compiled*>
|
|
|
|
(methodCompiled(t, frameMethod(frame)));
|
|
|
|
|
2007-10-13 21:48:40 +00:00
|
|
|
unsigned parameterFootprint = compiledParameterFootprint(code);
|
|
|
|
unsigned count = compiledMaxStack(code)
|
|
|
|
+ compiledMaxLocals(code)
|
|
|
|
- parameterFootprint;
|
2007-10-12 17:56:43 +00:00
|
|
|
|
2007-10-13 21:48:40 +00:00
|
|
|
if (count) {
|
|
|
|
uintptr_t* stackMap = frameStackMap(t, frame);
|
|
|
|
|
|
|
|
// fprintf(stderr, "visit stack and locals 0x%x of size %d, at %d of %s.%s\n",
|
|
|
|
// *stackMap,
|
|
|
|
// count,
|
|
|
|
// static_cast<uint8_t*>(frameAddress(frame))
|
|
|
|
// - compiledCode(code),
|
|
|
|
// &byteArrayBody
|
|
|
|
// (t, className(t, methodClass(t, frameMethod(frame))), 0),
|
|
|
|
// &byteArrayBody(t, methodName(t, frameMethod(frame)), 0));
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < count; ++i) {
|
|
|
|
if (getBit(stackMap, i)) {
|
|
|
|
v->visit(frameLocalObject(t, frame, i + parameterFootprint));
|
|
|
|
}
|
2007-10-12 17:56:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
visitStack(MyThread* t, Heap::Visitor* v)
|
|
|
|
{
|
2007-10-13 21:48:40 +00:00
|
|
|
if (frameValid(t->frame)) {
|
|
|
|
v->visit(&frameMethod(t->frame));
|
|
|
|
}
|
|
|
|
|
2007-10-12 17:56:43 +00:00
|
|
|
for (void* f = t->frame; frameValid(f); f = frameNext(f)) {
|
|
|
|
// we only need to visit the parameters of this method if the
|
|
|
|
// caller is native. Otherwise, the caller owns them.
|
|
|
|
void* next = frameNext(f);
|
2007-10-12 22:06:33 +00:00
|
|
|
if (frameValid(next)) {
|
2007-10-12 17:56:43 +00:00
|
|
|
v->visit(&frameMethod(next));
|
|
|
|
|
|
|
|
if (methodFlags(t, frameMethod(next)) & ACC_NATIVE) {
|
|
|
|
visitParameters(t, v, f);
|
|
|
|
}
|
2007-10-12 22:06:33 +00:00
|
|
|
} else {
|
|
|
|
visitParameters(t, v, f);
|
2007-10-12 17:56:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
object method = frameMethod(f);
|
|
|
|
Compiled* code = reinterpret_cast<Compiled*>(methodCompiled(t, method));
|
|
|
|
|
|
|
|
if ((methodFlags(t, method) & ACC_NATIVE) == 0
|
|
|
|
and code != t->m->processor->methodStub(t))
|
|
|
|
{
|
|
|
|
visitStackAndLocals(t, v, f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-10-08 21:41:41 +00:00
|
|
|
int64_t
|
|
|
|
divideLong(MyThread*, int64_t a, int64_t b)
|
|
|
|
{
|
|
|
|
return a / b;
|
|
|
|
}
|
|
|
|
|
|
|
|
int64_t
|
|
|
|
moduloLong(MyThread*, int64_t a, int64_t b)
|
|
|
|
{
|
|
|
|
return a % b;
|
|
|
|
}
|
|
|
|
|
2007-09-30 02:48:27 +00:00
|
|
|
object
|
|
|
|
makeBlankObjectArray(Thread* t, object class_, int32_t length)
|
|
|
|
{
|
|
|
|
return makeObjectArray(t, class_, length, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
object
|
|
|
|
makeBlankArray(Thread* t, object (*constructor)(Thread*, uintptr_t, bool),
|
|
|
|
int32_t length)
|
|
|
|
{
|
|
|
|
return constructor(t, length, true);
|
|
|
|
}
|
|
|
|
|
2007-10-01 15:19:15 +00:00
|
|
|
uint64_t
|
|
|
|
invokeNative2(MyThread* t, object method)
|
|
|
|
{
|
|
|
|
PROTECT(t, method);
|
|
|
|
|
|
|
|
if (objectClass(t, methodCode(t, method))
|
|
|
|
== arrayBody(t, t->m->types, Machine::ByteArrayType))
|
|
|
|
{
|
|
|
|
void* function = resolveNativeMethod(t, method);
|
|
|
|
if (UNLIKELY(function == 0)) {
|
|
|
|
object message = makeString
|
|
|
|
(t, "%s", &byteArrayBody(t, methodCode(t, method), 0));
|
|
|
|
t->exception = makeUnsatisfiedLinkError(t, message);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
object p = makePointer(t, function);
|
|
|
|
set(t, methodCode(t, method), p);
|
|
|
|
}
|
|
|
|
|
|
|
|
object class_ = methodClass(t, method);
|
|
|
|
PROTECT(t, class_);
|
|
|
|
|
|
|
|
unsigned footprint = methodParameterFootprint(t, method) + 1;
|
|
|
|
unsigned count = methodParameterCount(t, method) + 1;
|
|
|
|
if (methodFlags(t, method) & ACC_STATIC) {
|
|
|
|
++ footprint;
|
|
|
|
++ count;
|
|
|
|
}
|
|
|
|
|
|
|
|
uintptr_t args[footprint];
|
|
|
|
unsigned argOffset = 0;
|
|
|
|
uint8_t types[count];
|
|
|
|
unsigned typeOffset = 0;
|
|
|
|
|
|
|
|
args[argOffset++] = reinterpret_cast<uintptr_t>(t);
|
|
|
|
types[typeOffset++] = POINTER_TYPE;
|
|
|
|
|
2007-10-04 03:19:39 +00:00
|
|
|
uintptr_t* sp = static_cast<uintptr_t*>(frameBase(t->frame))
|
2007-10-01 15:19:15 +00:00
|
|
|
+ (methodParameterFootprint(t, method) + 1)
|
|
|
|
+ (FrameFootprint / BytesPerWord);
|
|
|
|
|
|
|
|
if (methodFlags(t, method) & ACC_STATIC) {
|
|
|
|
args[argOffset++] = reinterpret_cast<uintptr_t>(&class_);
|
|
|
|
} else {
|
|
|
|
args[argOffset++] = reinterpret_cast<uintptr_t>(sp--);
|
|
|
|
}
|
|
|
|
types[typeOffset++] = POINTER_TYPE;
|
|
|
|
|
|
|
|
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()));
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case INT8_TYPE:
|
|
|
|
case INT16_TYPE:
|
|
|
|
case INT32_TYPE:
|
|
|
|
case FLOAT_TYPE:
|
|
|
|
args[argOffset++] = *(sp--);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case INT64_TYPE:
|
|
|
|
case DOUBLE_TYPE: {
|
|
|
|
if (BytesPerWord == 8) {
|
|
|
|
uint64_t a = *(sp--);
|
|
|
|
uint64_t b = *(sp--);
|
|
|
|
args[argOffset++] = (a << 32) | b;
|
|
|
|
} else {
|
|
|
|
memcpy(args + argOffset, sp, 8);
|
|
|
|
argOffset += 2;
|
|
|
|
sp -= 2;
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case POINTER_TYPE: {
|
|
|
|
args[argOffset++] = reinterpret_cast<uintptr_t>(sp--);
|
|
|
|
} break;
|
|
|
|
|
|
|
|
default: abort(t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void* function = pointerValue(t, methodCode(t, method));
|
|
|
|
unsigned returnType = fieldType(t, methodReturnCode(t, method));
|
|
|
|
uint64_t result;
|
|
|
|
|
|
|
|
if (Verbose) {
|
|
|
|
fprintf(stderr, "invoke native method %s.%s\n",
|
|
|
|
&byteArrayBody(t, className(t, methodClass(t, method)), 0),
|
|
|
|
&byteArrayBody(t, methodName(t, method), 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
{ ENTER(t, Thread::IdleState);
|
|
|
|
|
|
|
|
result = t->m->system->call
|
|
|
|
(function,
|
|
|
|
args,
|
|
|
|
types,
|
|
|
|
count + 1,
|
2007-10-04 03:19:39 +00:00
|
|
|
footprint * BytesPerWord,
|
2007-10-01 15:19:15 +00:00
|
|
|
returnType);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Verbose) {
|
|
|
|
fprintf(stderr, "return from native method %s.%s\n",
|
|
|
|
&byteArrayBody(t, className(t, methodClass(t, method)), 0),
|
|
|
|
&byteArrayBody(t, methodName(t, method), 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (LIKELY(t->exception == 0) and returnType == POINTER_TYPE) {
|
2007-10-09 19:30:01 +00:00
|
|
|
return result ? *reinterpret_cast<uintptr_t*>(result) : 0;
|
2007-10-01 15:19:15 +00:00
|
|
|
} else {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
invokeNative(MyThread* t, object method)
|
|
|
|
{
|
|
|
|
uint64_t result = invokeNative2(t, method);
|
|
|
|
if (UNLIKELY(t->exception)) {
|
|
|
|
unwind(t);
|
|
|
|
} else {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
compileMethod(MyThread* t, object method);
|
|
|
|
|
2007-09-27 00:01:38 +00:00
|
|
|
inline bool
|
|
|
|
isByte(int32_t v)
|
|
|
|
{
|
|
|
|
return v == static_cast<int8_t>(v);
|
|
|
|
}
|
|
|
|
|
2007-10-09 17:15:40 +00:00
|
|
|
inline bool
|
|
|
|
isInt32(uintptr_t v)
|
|
|
|
{
|
|
|
|
return v == static_cast<uintptr_t>(static_cast<int32_t>(v));
|
|
|
|
}
|
|
|
|
|
2007-09-28 23:41:03 +00:00
|
|
|
enum Register {
|
|
|
|
rax = 0,
|
|
|
|
rcx = 1,
|
|
|
|
rdx = 2,
|
|
|
|
rbx = 3,
|
|
|
|
rsp = 4,
|
|
|
|
rbp = 5,
|
|
|
|
rsi = 6,
|
|
|
|
rdi = 7,
|
|
|
|
r8 = 8,
|
|
|
|
r9 = 9,
|
|
|
|
r10 = 10,
|
|
|
|
r11 = 11,
|
|
|
|
r12 = 12,
|
|
|
|
r13 = 13,
|
|
|
|
r14 = 14,
|
|
|
|
r15 = 15,
|
|
|
|
};
|
|
|
|
|
|
|
|
enum SSERegister {
|
|
|
|
xmm0 = 0,
|
|
|
|
xmm1 = 1,
|
|
|
|
xmm2 = 2,
|
|
|
|
xmm3 = 3,
|
|
|
|
xmm4 = 4,
|
|
|
|
xmm5 = 5,
|
|
|
|
xmm6 = 6,
|
|
|
|
xmm7 = 7
|
|
|
|
};
|
|
|
|
|
2007-09-24 01:39:03 +00:00
|
|
|
class Assembler {
|
|
|
|
public:
|
2007-09-25 23:53:11 +00:00
|
|
|
class Label {
|
|
|
|
public:
|
|
|
|
static const unsigned Capacity = 8;
|
|
|
|
|
2007-09-26 23:23:03 +00:00
|
|
|
Label(Assembler* a):
|
|
|
|
code(&(a->code)),
|
2007-09-25 23:53:11 +00:00
|
|
|
unresolvedCount(0),
|
|
|
|
mark_(-1)
|
|
|
|
{ }
|
|
|
|
|
2007-09-28 23:41:03 +00:00
|
|
|
void reference() {
|
2007-09-25 23:53:11 +00:00
|
|
|
if (mark_ == -1) {
|
2007-09-26 23:23:03 +00:00
|
|
|
expect(code->s, unresolvedCount < Capacity);
|
2007-09-28 23:41:03 +00:00
|
|
|
unresolved[unresolvedCount] = code->length();
|
2007-09-25 23:53:11 +00:00
|
|
|
++ unresolvedCount;
|
|
|
|
|
2007-09-28 23:41:03 +00:00
|
|
|
code->append4(0);
|
2007-09-25 23:53:11 +00:00
|
|
|
} else {
|
2007-09-28 23:41:03 +00:00
|
|
|
code->append4(mark_ - (code->length() + 4));
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-09-26 23:23:03 +00:00
|
|
|
void mark() {
|
|
|
|
mark_ = code->length();
|
2007-09-25 23:53:11 +00:00
|
|
|
for (unsigned i = 0; i < unresolvedCount; ++i) {
|
2007-09-28 23:41:03 +00:00
|
|
|
code->set4(unresolved[i], mark_ - (unresolved[i] + 4));
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-09-28 23:41:03 +00:00
|
|
|
Buffer* code;
|
|
|
|
unsigned unresolved[Capacity];
|
2007-09-25 23:53:11 +00:00
|
|
|
unsigned unresolvedCount;
|
|
|
|
int mark_;
|
|
|
|
};
|
|
|
|
|
2007-09-24 01:39:03 +00:00
|
|
|
Assembler(System* s):
|
2007-09-28 23:41:03 +00:00
|
|
|
code(s, 1024),
|
2007-10-10 21:34:04 +00:00
|
|
|
jumps(s, 256)
|
2007-09-24 01:39:03 +00:00
|
|
|
{ }
|
|
|
|
|
2007-09-26 23:23:03 +00:00
|
|
|
void rex() {
|
|
|
|
if (BytesPerWord == 8) {
|
|
|
|
code.append(0x48);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-09-25 23:53:11 +00:00
|
|
|
void mov(Register src, Register dst) {
|
2007-09-26 23:23:03 +00:00
|
|
|
rex();
|
|
|
|
code.append(0x89);
|
|
|
|
code.append(0xc0 | (src << 3) | dst);
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
2007-09-28 14:45:26 +00:00
|
|
|
void offsetInstruction(uint8_t instruction, uint8_t zeroPrefix,
|
|
|
|
uint8_t bytePrefix, uint8_t wordPrefix,
|
2007-09-28 23:41:03 +00:00
|
|
|
unsigned a, unsigned b, int32_t offset)
|
2007-09-28 14:45:26 +00:00
|
|
|
{
|
|
|
|
code.append(instruction);
|
|
|
|
|
|
|
|
uint8_t prefix;
|
|
|
|
if (offset == 0 and b != rbp) {
|
|
|
|
prefix = zeroPrefix;
|
|
|
|
} else if (isByte(offset)) {
|
|
|
|
prefix = bytePrefix;
|
2007-09-25 23:53:11 +00:00
|
|
|
} else {
|
2007-09-28 14:45:26 +00:00
|
|
|
prefix = wordPrefix;
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
2007-09-28 14:45:26 +00:00
|
|
|
|
|
|
|
code.append(prefix | (a << 3) | b);
|
|
|
|
|
|
|
|
if (b == rsp) {
|
|
|
|
code.append(0x24);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (offset == 0 and b != rbp) {
|
|
|
|
// do nothing
|
|
|
|
} else if (isByte(offset)) {
|
|
|
|
code.append(offset);
|
|
|
|
} else {
|
|
|
|
code.append4(offset);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-09-30 15:52:21 +00:00
|
|
|
void movz1(Register src, Register dst) {
|
|
|
|
code.append(0x0f);
|
|
|
|
code.append(0xb6);
|
|
|
|
code.append(0xc0 | (dst << 3) | src);
|
|
|
|
}
|
|
|
|
|
2007-09-29 20:24:14 +00:00
|
|
|
void movz1(Register src, int32_t srcOffset, Register dst) {
|
|
|
|
code.append(0x0f);
|
2007-09-30 15:52:21 +00:00
|
|
|
offsetInstruction(0xb6, 0, 0x40, 0x80, dst, src, srcOffset);
|
|
|
|
}
|
|
|
|
|
|
|
|
void movs1(Register src, Register dst) {
|
|
|
|
code.append(0x0f);
|
|
|
|
code.append(0xbe);
|
|
|
|
code.append(0xc0 | (dst << 3) | src);
|
2007-09-29 20:24:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void movs1(Register src, int32_t srcOffset, Register dst) {
|
|
|
|
code.append(0x0f);
|
2007-09-30 15:52:21 +00:00
|
|
|
offsetInstruction(0xbe, 0, 0x40, 0x80, dst, src, srcOffset);
|
|
|
|
}
|
|
|
|
|
|
|
|
void movz2(Register src, Register dst) {
|
|
|
|
code.append(0x0f);
|
|
|
|
code.append(0xb7);
|
|
|
|
code.append(0xc0 | (dst << 3) | src);
|
2007-09-29 20:24:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void movz2(Register src, int32_t srcOffset, Register dst) {
|
|
|
|
code.append(0x0f);
|
2007-09-30 15:52:21 +00:00
|
|
|
offsetInstruction(0xb7, 0, 0x40, 0x80, dst, src, srcOffset);
|
|
|
|
}
|
|
|
|
|
|
|
|
void movs2(Register src, Register dst) {
|
|
|
|
code.append(0x0f);
|
|
|
|
code.append(0xbf);
|
|
|
|
code.append(0xc0 | (dst << 3) | src);
|
2007-09-29 20:24:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void movs2(Register src, int32_t srcOffset, Register dst) {
|
|
|
|
code.append(0x0f);
|
2007-09-30 15:52:21 +00:00
|
|
|
offsetInstruction(0xbf, 0, 0x40, 0x80, dst, src, srcOffset);
|
2007-09-29 20:24:14 +00:00
|
|
|
}
|
|
|
|
|
2007-09-28 14:45:26 +00:00
|
|
|
void mov4(Register src, int32_t srcOffset, Register dst) {
|
|
|
|
offsetInstruction(0x8b, 0, 0x40, 0x80, dst, src, srcOffset);
|
|
|
|
}
|
|
|
|
|
2007-09-29 20:24:14 +00:00
|
|
|
void mov1(Register src, Register dst, int32_t dstOffset) {
|
|
|
|
offsetInstruction(0x88, 0, 0x40, 0x80, src, dst, dstOffset);
|
|
|
|
}
|
|
|
|
|
|
|
|
void mov2(Register src, Register dst, int32_t dstOffset) {
|
|
|
|
code.append(0x66);
|
|
|
|
offsetInstruction(0x89, 0, 0x40, 0x80, src, dst, dstOffset);
|
|
|
|
}
|
|
|
|
|
2007-09-28 14:45:26 +00:00
|
|
|
void mov4(Register src, Register dst, int32_t dstOffset) {
|
|
|
|
offsetInstruction(0x89, 0, 0x40, 0x80, src, dst, dstOffset);
|
|
|
|
}
|
|
|
|
|
2007-09-28 23:41:03 +00:00
|
|
|
void mov(Register src, int32_t srcOffset, SSERegister dst) {
|
|
|
|
code.append(0xf3);
|
|
|
|
code.append(0x0f);
|
|
|
|
offsetInstruction(0x7e, 0, 0x40, 0x80, dst, src, srcOffset);
|
|
|
|
}
|
|
|
|
|
2007-09-28 14:45:26 +00:00
|
|
|
void mov(Register src, int32_t srcOffset, Register dst) {
|
|
|
|
rex();
|
|
|
|
mov4(src, srcOffset, dst);
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
2007-09-27 00:01:38 +00:00
|
|
|
void mov(Register src, Register dst, int32_t dstOffset) {
|
2007-09-26 23:23:03 +00:00
|
|
|
rex();
|
2007-09-28 14:45:26 +00:00
|
|
|
mov4(src, dst, dstOffset);
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
2007-09-26 23:23:03 +00:00
|
|
|
void mov(uintptr_t v, Register dst) {
|
|
|
|
rex();
|
|
|
|
code.append(0xb8 | dst);
|
|
|
|
code.appendAddress(v);
|
|
|
|
}
|
|
|
|
|
|
|
|
void alignedMov(uintptr_t v, Register dst) {
|
|
|
|
while ((code.length() + (BytesPerWord == 8 ? 2 : 1)) % BytesPerWord) {
|
|
|
|
nop();
|
|
|
|
}
|
|
|
|
rex();
|
|
|
|
code.append(0xb8 | dst);
|
|
|
|
code.appendAddress(v);
|
|
|
|
}
|
|
|
|
|
2007-10-04 00:41:54 +00:00
|
|
|
void lea(Register src, int32_t srcOffset, Register dst) {
|
|
|
|
rex();
|
|
|
|
offsetInstruction(0x8d, 0, 0x40, 0x80, dst, src, srcOffset);
|
|
|
|
}
|
|
|
|
|
2007-09-26 23:23:03 +00:00
|
|
|
void nop() {
|
|
|
|
code.append(0x90);
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void push(Register reg) {
|
2007-09-26 23:23:03 +00:00
|
|
|
code.append(0x50 | reg);
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
2007-09-27 00:01:38 +00:00
|
|
|
void push(Register reg, int32_t offset) {
|
2007-09-28 14:45:26 +00:00
|
|
|
offsetInstruction(0xff, 0x30, 0x70, 0xb0, rax, reg, offset);
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
2007-09-27 00:01:38 +00:00
|
|
|
void push(int32_t v) {
|
2007-09-29 18:34:56 +00:00
|
|
|
if (isByte(v)) {
|
|
|
|
code.append(0x6a);
|
|
|
|
code.append(v);
|
|
|
|
} else {
|
|
|
|
code.append(0x68);
|
|
|
|
code.append4(v);
|
|
|
|
}
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
2007-10-03 00:22:48 +00:00
|
|
|
void push4(Register reg, int32_t offset) {
|
2007-09-27 22:20:54 +00:00
|
|
|
if (BytesPerWord == 8) {
|
2007-10-03 00:22:48 +00:00
|
|
|
mov4(reg, offset, rsi);
|
2007-09-27 22:20:54 +00:00
|
|
|
push(rsi);
|
|
|
|
} else {
|
2007-10-03 00:22:48 +00:00
|
|
|
push(reg, offset);
|
2007-09-27 22:20:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-10-03 00:22:48 +00:00
|
|
|
void pushAddress(uintptr_t v) {
|
2007-10-09 17:15:40 +00:00
|
|
|
if (BytesPerWord == 8 and not isInt32(v)) {
|
2007-10-03 00:22:48 +00:00
|
|
|
mov(v, rsi);
|
2007-09-28 14:45:26 +00:00
|
|
|
push(rsi);
|
|
|
|
} else {
|
2007-10-03 00:22:48 +00:00
|
|
|
push(v);
|
2007-09-28 14:45:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-09-25 23:53:11 +00:00
|
|
|
void pop(Register dst) {
|
2007-09-26 23:23:03 +00:00
|
|
|
code.append(0x58 | dst);
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
2007-09-27 00:01:38 +00:00
|
|
|
void pop(Register dst, int32_t offset) {
|
2007-09-28 14:45:26 +00:00
|
|
|
offsetInstruction(0x8f, 0, 0x40, 0x80, rax, dst, offset);
|
|
|
|
}
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-09-28 14:45:26 +00:00
|
|
|
void pop4(Register reg, int32_t offset) {
|
|
|
|
if (BytesPerWord == 8) {
|
|
|
|
pop(rsi);
|
|
|
|
mov4(rsi, reg, offset);
|
|
|
|
} else {
|
|
|
|
pop(reg, offset);
|
|
|
|
}
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void add(Register src, Register dst) {
|
2007-09-26 23:23:03 +00:00
|
|
|
rex();
|
|
|
|
code.append(0x01);
|
|
|
|
code.append(0xc0 | (src << 3) | dst);
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
2007-09-27 00:01:38 +00:00
|
|
|
void add(int32_t v, Register dst) {
|
|
|
|
assert(code.s, isByte(v)); // todo
|
2007-09-26 23:23:03 +00:00
|
|
|
|
|
|
|
rex();
|
|
|
|
code.append(0x83);
|
|
|
|
code.append(0xc0 | dst);
|
|
|
|
code.append(v);
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
2007-09-30 02:48:27 +00:00
|
|
|
void add(int32_t v, Register dst, unsigned offset) {
|
|
|
|
rex();
|
|
|
|
unsigned i = (isByte(v) ? 0x83 : 0x81);
|
|
|
|
offsetInstruction(i, 0, 0x40, 0x80, rax, dst, offset);
|
|
|
|
if (isByte(v)) {
|
|
|
|
code.append(v);
|
|
|
|
} else {
|
|
|
|
code.append4(v);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-10-09 17:15:40 +00:00
|
|
|
void add(Register src, Register dst, unsigned dstOffset) {
|
|
|
|
rex();
|
|
|
|
offsetInstruction(0x01, 0, 0x40, 0x80, src, dst, dstOffset);
|
|
|
|
}
|
|
|
|
|
2007-10-08 21:41:41 +00:00
|
|
|
void adc(int32_t v, Register dst) {
|
|
|
|
assert(code.s, isByte(v)); // todo
|
|
|
|
|
|
|
|
rex();
|
|
|
|
code.append(0x83);
|
|
|
|
code.append(0xd0 | dst);
|
|
|
|
code.append(v);
|
|
|
|
}
|
|
|
|
|
|
|
|
void adc(Register src, Register dst, unsigned dstOffset) {
|
|
|
|
rex();
|
|
|
|
offsetInstruction(0x11, 0, 0x40, 0x80, src, dst, dstOffset);
|
|
|
|
}
|
|
|
|
|
|
|
|
void sub(Register src, Register dst, unsigned dstOffset) {
|
|
|
|
rex();
|
|
|
|
offsetInstruction(0x29, 0, 0x40, 0x80, src, dst, dstOffset);
|
|
|
|
}
|
|
|
|
|
2007-09-25 23:53:11 +00:00
|
|
|
void sub(Register src, Register dst) {
|
2007-09-26 23:23:03 +00:00
|
|
|
rex();
|
|
|
|
code.append(0x29);
|
|
|
|
code.append(0xc0 | (src << 3) | dst);
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
2007-09-27 00:01:38 +00:00
|
|
|
void sub(int32_t v, Register dst) {
|
|
|
|
assert(code.s, isByte(v)); // todo
|
2007-09-26 23:23:03 +00:00
|
|
|
|
|
|
|
rex();
|
|
|
|
code.append(0x83);
|
|
|
|
code.append(0xe8 | dst);
|
|
|
|
code.append(v);
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
2007-10-08 21:41:41 +00:00
|
|
|
void sbb(Register src, Register dst, unsigned dstOffset) {
|
|
|
|
rex();
|
|
|
|
offsetInstruction(0x19, 0, 0x40, 0x80, src, dst, dstOffset);
|
|
|
|
}
|
|
|
|
|
2007-09-25 23:53:11 +00:00
|
|
|
void or_(Register src, Register dst) {
|
2007-09-26 23:23:03 +00:00
|
|
|
rex();
|
|
|
|
code.append(0x09);
|
|
|
|
code.append(0xc0 | (src << 3) | dst);
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
2007-09-27 00:01:38 +00:00
|
|
|
void or_(int32_t v, Register dst) {
|
|
|
|
assert(code.s, isByte(v)); // todo
|
2007-09-26 23:23:03 +00:00
|
|
|
|
|
|
|
rex();
|
|
|
|
code.append(0x83);
|
|
|
|
code.append(0xc8 | dst);
|
|
|
|
code.append(v);
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void and_(Register src, Register dst) {
|
2007-09-26 23:23:03 +00:00
|
|
|
rex();
|
|
|
|
code.append(0x21);
|
|
|
|
code.append(0xc0 | (src << 3) | dst);
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
2007-09-27 00:01:38 +00:00
|
|
|
void and_(int32_t v, Register dst) {
|
|
|
|
assert(code.s, isByte(v)); // todo
|
2007-09-26 23:23:03 +00:00
|
|
|
|
|
|
|
rex();
|
|
|
|
code.append(0x83);
|
|
|
|
code.append(0xe0 | dst);
|
|
|
|
code.append(v);
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
2007-09-30 04:07:22 +00:00
|
|
|
void shl(int8_t v, Register dst) {
|
|
|
|
rex();
|
|
|
|
if (v == 1) {
|
|
|
|
code.append(0xd1);
|
|
|
|
code.append(0xe0 | dst);
|
|
|
|
} else {
|
|
|
|
code.append(0xc1);
|
|
|
|
code.append(0xe0 | dst);
|
|
|
|
code.append(v);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-09-25 23:53:11 +00:00
|
|
|
void ret() {
|
2007-09-26 23:23:03 +00:00
|
|
|
code.append(0xc3);
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void jmp(Label& label) {
|
2007-09-26 23:23:03 +00:00
|
|
|
code.append(0xE9);
|
2007-09-28 23:41:03 +00:00
|
|
|
label.reference();
|
|
|
|
}
|
|
|
|
|
|
|
|
void jmp(unsigned javaIP) {
|
|
|
|
code.append(0xE9);
|
|
|
|
|
|
|
|
jumps.append4(javaIP);
|
|
|
|
jumps.append4(code.length());
|
|
|
|
|
|
|
|
code.append4(0);
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void jmp(Register reg) {
|
2007-09-26 23:23:03 +00:00
|
|
|
code.append(0xff);
|
|
|
|
code.append(0xe0 | reg);
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
2007-09-30 02:48:27 +00:00
|
|
|
void conditional(Label& label, unsigned condition) {
|
2007-09-29 20:24:14 +00:00
|
|
|
code.append(0x0f);
|
2007-09-30 02:48:27 +00:00
|
|
|
code.append(condition);
|
2007-09-28 23:41:03 +00:00
|
|
|
label.reference();
|
2007-09-26 23:23:03 +00:00
|
|
|
}
|
|
|
|
|
2007-09-29 20:24:14 +00:00
|
|
|
void conditional(unsigned javaIP, unsigned condition) {
|
|
|
|
code.append(0x0f);
|
|
|
|
code.append(condition);
|
2007-09-28 23:41:03 +00:00
|
|
|
|
|
|
|
jumps.append4(javaIP);
|
|
|
|
jumps.append4(code.length());
|
|
|
|
|
|
|
|
code.append4(0);
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
2007-09-30 02:48:27 +00:00
|
|
|
void je(Label& label) {
|
|
|
|
conditional(label, 0x84);
|
|
|
|
}
|
|
|
|
|
2007-09-29 21:08:29 +00:00
|
|
|
void je(unsigned javaIP) {
|
2007-09-29 20:24:14 +00:00
|
|
|
conditional(javaIP, 0x84);
|
|
|
|
}
|
|
|
|
|
2007-09-29 21:08:29 +00:00
|
|
|
void jne(Label& label) {
|
2007-09-30 02:48:27 +00:00
|
|
|
conditional(label, 0x85);
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
2007-09-29 21:08:29 +00:00
|
|
|
void jne(unsigned javaIP) {
|
2007-09-29 20:24:14 +00:00
|
|
|
conditional(javaIP, 0x85);
|
|
|
|
}
|
2007-09-28 23:41:03 +00:00
|
|
|
|
2007-09-30 02:48:27 +00:00
|
|
|
void jg(Label& label) {
|
|
|
|
conditional(label, 0x8f);
|
|
|
|
}
|
|
|
|
|
2007-09-29 20:24:14 +00:00
|
|
|
void jg(unsigned javaIP) {
|
|
|
|
conditional(javaIP, 0x8f);
|
|
|
|
}
|
2007-09-28 23:41:03 +00:00
|
|
|
|
2007-09-30 02:48:27 +00:00
|
|
|
void jge(Label& label) {
|
|
|
|
conditional(label, 0x8d);
|
|
|
|
}
|
|
|
|
|
2007-09-29 20:24:14 +00:00
|
|
|
void jge(unsigned javaIP) {
|
|
|
|
conditional(javaIP, 0x8d);
|
|
|
|
}
|
|
|
|
|
2007-09-30 02:48:27 +00:00
|
|
|
void jl(Label& label) {
|
|
|
|
conditional(label, 0x8c);
|
|
|
|
}
|
|
|
|
|
2007-09-29 20:24:14 +00:00
|
|
|
void jl(unsigned javaIP) {
|
|
|
|
conditional(javaIP, 0x8c);
|
|
|
|
}
|
|
|
|
|
2007-09-30 02:48:27 +00:00
|
|
|
void jle(Label& label) {
|
|
|
|
conditional(label, 0x8e);
|
|
|
|
}
|
|
|
|
|
2007-09-29 20:24:14 +00:00
|
|
|
void jle(unsigned javaIP) {
|
|
|
|
conditional(javaIP, 0x8e);
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
2007-10-08 21:41:41 +00:00
|
|
|
void jb(Label& label) {
|
|
|
|
conditional(label, 0x82);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ja(Label& label) {
|
|
|
|
conditional(label, 0x87);
|
|
|
|
}
|
|
|
|
|
2007-09-25 23:53:11 +00:00
|
|
|
void cmp(int v, Register reg) {
|
2007-09-30 15:52:21 +00:00
|
|
|
assert(code.s, isByte(v)); // todo
|
|
|
|
|
2007-10-09 19:30:01 +00:00
|
|
|
rex();
|
2007-09-26 23:23:03 +00:00
|
|
|
code.append(0x83);
|
|
|
|
code.append(0xf8 | reg);
|
|
|
|
code.append(v);
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
2007-09-30 15:52:21 +00:00
|
|
|
void cmp(Register a, Register b) {
|
2007-10-09 17:15:40 +00:00
|
|
|
rex();
|
2007-09-30 15:52:21 +00:00
|
|
|
code.append(0x39);
|
|
|
|
code.append(0xc0 | (a << 3) | b);
|
|
|
|
}
|
|
|
|
|
2007-09-25 23:53:11 +00:00
|
|
|
void call(Register reg) {
|
2007-09-26 23:23:03 +00:00
|
|
|
code.append(0xff);
|
|
|
|
code.append(0xd0 | reg);
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
2007-10-08 21:41:41 +00:00
|
|
|
void cdq() {
|
|
|
|
code.append(0x99);
|
|
|
|
}
|
|
|
|
|
2007-10-08 23:13:55 +00:00
|
|
|
void cqo() {
|
|
|
|
rex();
|
|
|
|
cdq();
|
|
|
|
}
|
|
|
|
|
2007-10-08 21:41:41 +00:00
|
|
|
void imul4(Register src, unsigned srcOffset, Register dst) {
|
|
|
|
code.append(0x0f);
|
|
|
|
offsetInstruction(0xaf, 0, 0x40, 0x80, dst, src, srcOffset);
|
|
|
|
}
|
|
|
|
|
|
|
|
void imul(Register src, unsigned srcOffset, Register dst) {
|
|
|
|
rex();
|
|
|
|
imul4(src, srcOffset, dst);
|
|
|
|
}
|
|
|
|
|
|
|
|
void imul(Register src) {
|
|
|
|
rex();
|
|
|
|
code.append(0xf7);
|
|
|
|
code.append(0xe8 | src);
|
|
|
|
}
|
|
|
|
|
|
|
|
void idiv(Register src) {
|
|
|
|
rex();
|
|
|
|
code.append(0xf7);
|
|
|
|
code.append(0xf8 | src);
|
|
|
|
}
|
|
|
|
|
|
|
|
void mul(Register src, unsigned offset) {
|
|
|
|
rex();
|
|
|
|
offsetInstruction(0xf7, 0x20, 0x60, 0xa0, rax, src, offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
void neg(Register reg, unsigned offset) {
|
|
|
|
rex();
|
|
|
|
offsetInstruction(0xf7, 0x10, 0x50, 0x90, rax, reg, offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
void neg(Register reg) {
|
|
|
|
rex();
|
|
|
|
code.append(0xf7);
|
|
|
|
code.append(0xd8 | reg);
|
|
|
|
}
|
|
|
|
|
2007-10-08 23:13:55 +00:00
|
|
|
void int3() {
|
|
|
|
code.append(0xcc);
|
|
|
|
}
|
|
|
|
|
2007-09-28 23:41:03 +00:00
|
|
|
Buffer code;
|
|
|
|
Buffer jumps;
|
2007-09-24 01:39:03 +00:00
|
|
|
};
|
|
|
|
|
2007-09-28 23:41:03 +00:00
|
|
|
Register
|
|
|
|
gpRegister(Thread* t, unsigned index)
|
|
|
|
{
|
|
|
|
switch (index) {
|
|
|
|
case 0:
|
|
|
|
return rdi;
|
|
|
|
case 1:
|
|
|
|
return rsi;
|
|
|
|
case 2:
|
|
|
|
return rdx;
|
|
|
|
case 3:
|
|
|
|
return rcx;
|
|
|
|
case 4:
|
|
|
|
return r8;
|
|
|
|
case 5:
|
|
|
|
return r9;
|
|
|
|
default:
|
|
|
|
abort(t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SSERegister
|
2007-09-30 16:32:17 +00:00
|
|
|
sseRegister(Thread* t UNUSED, unsigned index)
|
2007-09-28 23:41:03 +00:00
|
|
|
{
|
|
|
|
assert(t, index < 8);
|
2007-09-30 16:32:17 +00:00
|
|
|
return static_cast<SSERegister>(index);
|
2007-09-28 23:41:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
unsigned
|
2007-09-30 02:48:27 +00:00
|
|
|
parameterOffset(unsigned index)
|
2007-09-28 23:41:03 +00:00
|
|
|
{
|
2007-09-30 02:48:27 +00:00
|
|
|
return FrameFootprint + ((index + 2) * BytesPerWord);
|
2007-09-28 23:41:03 +00:00
|
|
|
}
|
|
|
|
|
2007-10-04 03:19:39 +00:00
|
|
|
Compiled*
|
|
|
|
caller(MyThread* t);
|
|
|
|
|
2007-10-10 22:39:40 +00:00
|
|
|
class Compiler: public Assembler {
|
2007-10-10 17:26:28 +00:00
|
|
|
public:
|
2007-10-10 22:39:40 +00:00
|
|
|
Compiler(MyThread* t):
|
|
|
|
Assembler(t->m->system),
|
|
|
|
t(t)
|
|
|
|
{ }
|
2007-10-10 21:34:04 +00:00
|
|
|
|
2007-10-10 22:39:40 +00:00
|
|
|
unsigned threadFrameOffset() {
|
|
|
|
return reinterpret_cast<uintptr_t>(&(t->frame))
|
|
|
|
- reinterpret_cast<uintptr_t>(t);
|
|
|
|
}
|
2007-10-10 21:34:04 +00:00
|
|
|
|
2007-10-10 22:39:40 +00:00
|
|
|
Compiled* compileStub() {
|
|
|
|
push(rbp);
|
|
|
|
mov(rsp, rbp);
|
2007-10-10 21:34:04 +00:00
|
|
|
|
2007-10-10 22:39:40 +00:00
|
|
|
if (BytesPerWord == 4) {
|
|
|
|
push(rbp, FrameMethod);
|
|
|
|
push(rbp, FrameThread);
|
|
|
|
} else {
|
|
|
|
mov(rbp, FrameMethod, rsi);
|
|
|
|
mov(rbp, FrameThread, rdi);
|
2007-10-10 21:34:04 +00:00
|
|
|
}
|
|
|
|
|
2007-10-10 22:39:40 +00:00
|
|
|
mov(reinterpret_cast<uintptr_t>(compileMethod), rbx);
|
|
|
|
callAddress(compiledCode(caller(t)));
|
2007-10-10 21:34:04 +00:00
|
|
|
|
2007-10-10 22:39:40 +00:00
|
|
|
if (BytesPerWord == 4) {
|
|
|
|
add(BytesPerWord * 2, rsp);
|
|
|
|
}
|
2007-10-10 21:34:04 +00:00
|
|
|
|
2007-10-10 22:39:40 +00:00
|
|
|
mov(rbp, FrameMethod, rax);
|
|
|
|
mov(rax, MethodCompiled, rax); // load compiled code
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-10-10 22:39:40 +00:00
|
|
|
mov(rbp, rsp);
|
|
|
|
pop(rbp);
|
|
|
|
|
|
|
|
add(CompiledBody, rax);
|
|
|
|
jmp(rax); // call compiled code
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-10-10 22:39:40 +00:00
|
|
|
return finish();
|
2007-10-10 17:26:28 +00:00
|
|
|
}
|
|
|
|
|
2007-10-10 22:39:40 +00:00
|
|
|
Compiled* compileNativeInvoker() {
|
|
|
|
push(rbp);
|
|
|
|
mov(rsp, rbp);
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-10-10 22:39:40 +00:00
|
|
|
if (BytesPerWord == 4) {
|
|
|
|
push(rbp, FrameMethod);
|
|
|
|
push(rbp, FrameThread);
|
|
|
|
} else {
|
|
|
|
mov(rbp, FrameMethod, rsi);
|
|
|
|
mov(rbp, FrameThread, rdi);
|
|
|
|
}
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-10-10 22:39:40 +00:00
|
|
|
mov(reinterpret_cast<uintptr_t>(invokeNative), rbx);
|
|
|
|
callAddress(compiledCode(caller(t)));
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-10-10 22:39:40 +00:00
|
|
|
if (BytesPerWord == 4) {
|
|
|
|
add(BytesPerWord * 2, rsp);
|
|
|
|
}
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-10-10 22:39:40 +00:00
|
|
|
mov(rbp, rsp);
|
|
|
|
pop(rbp);
|
|
|
|
ret();
|
2007-10-10 17:26:28 +00:00
|
|
|
|
2007-10-10 22:39:40 +00:00
|
|
|
return finish();
|
2007-10-10 21:34:04 +00:00
|
|
|
}
|
|
|
|
|
2007-10-10 22:39:40 +00:00
|
|
|
Compiled* compileCaller() {
|
|
|
|
mov(rbp, FrameThread, rdi);
|
|
|
|
lea(rsp, FrameFootprint + BytesPerWord, rcx);
|
|
|
|
mov(rcx, rdi, threadFrameOffset()); // set thread frame to current
|
|
|
|
|
|
|
|
jmp(rbx);
|
|
|
|
|
|
|
|
return finish();
|
2007-10-10 17:26:28 +00:00
|
|
|
}
|
|
|
|
|
2007-10-10 22:39:40 +00:00
|
|
|
Compiled* finish() {
|
|
|
|
return makeCompiled(t, &code);
|
2007-10-10 17:26:28 +00:00
|
|
|
}
|
2007-10-10 21:34:04 +00:00
|
|
|
|
2007-10-10 22:39:40 +00:00
|
|
|
void callAddress(void* function) {
|
|
|
|
mov(reinterpret_cast<uintptr_t>(function), rax);
|
|
|
|
call(rax);
|
2007-10-10 21:34:04 +00:00
|
|
|
}
|
|
|
|
|
2007-10-10 22:39:40 +00:00
|
|
|
void callAlignedAddress(void* function) {
|
|
|
|
alignedMov(reinterpret_cast<uintptr_t>(function), rax);
|
|
|
|
call(rax);
|
2007-10-10 21:34:04 +00:00
|
|
|
}
|
|
|
|
|
2007-10-10 22:39:40 +00:00
|
|
|
MyThread* t;
|
2007-10-10 17:26:28 +00:00
|
|
|
};
|
|
|
|
|
2007-10-10 22:39:40 +00:00
|
|
|
class JavaCompiler: public Compiler {
|
2007-09-24 01:39:03 +00:00
|
|
|
public:
|
2007-10-10 22:39:40 +00:00
|
|
|
JavaCompiler(MyThread* t, object method):
|
|
|
|
Compiler(t),
|
2007-10-10 17:26:28 +00:00
|
|
|
method(method),
|
2007-10-10 21:34:04 +00:00
|
|
|
stackMapper(t, method),
|
2007-10-03 01:54:21 +00:00
|
|
|
poolRegisterClobbered(true),
|
2007-10-10 22:39:40 +00:00
|
|
|
machineIPs(static_cast<uint32_t*>
|
2007-10-10 17:26:28 +00:00
|
|
|
(t->m->system->allocate
|
2007-10-10 22:39:40 +00:00
|
|
|
(codeLength(t, methodCode(t, method)) * 4))),
|
|
|
|
lineNumbers(codeLineNumberTable(t, methodCode(t, method)) ?
|
2007-10-10 17:26:28 +00:00
|
|
|
static_cast<NativeLineNumber*>
|
|
|
|
(t->m->system->allocate
|
|
|
|
(lineNumberTableLength
|
|
|
|
(t, codeLineNumberTable(t, methodCode(t, method)))
|
|
|
|
* sizeof(NativeLineNumber))) : 0),
|
2007-10-10 22:39:40 +00:00
|
|
|
exceptionHandlers(codeExceptionHandlerTable(t, methodCode(t, method)) ?
|
2007-10-10 17:26:28 +00:00
|
|
|
static_cast<NativeExceptionHandler*>
|
|
|
|
(t->m->system->allocate
|
|
|
|
(exceptionHandlerTableLength
|
|
|
|
(t, codeExceptionHandlerTable
|
|
|
|
(t, methodCode(t, method)))
|
|
|
|
* sizeof(NativeExceptionHandler))) : 0),
|
2007-10-12 17:56:43 +00:00
|
|
|
pool(t->m->system, 256),
|
|
|
|
protector(this)
|
2007-09-24 01:39:03 +00:00
|
|
|
{ }
|
|
|
|
|
2007-10-10 22:39:40 +00:00
|
|
|
~JavaCompiler() {
|
2007-10-10 21:34:04 +00:00
|
|
|
if (machineIPs) {
|
|
|
|
t->m->system->free(machineIPs);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lineNumbers) {
|
|
|
|
t->m->system->free(lineNumbers);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (exceptionHandlers) {
|
|
|
|
t->m->system->free(exceptionHandlers);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
void pushInt() {
|
|
|
|
sub(BytesPerWord, rsp);
|
2007-10-10 21:34:04 +00:00
|
|
|
stackMapper.pushedInt();
|
2007-10-10 17:26:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void pushInt(int32_t v) {
|
|
|
|
push(v);
|
2007-10-10 21:34:04 +00:00
|
|
|
stackMapper.pushedInt();
|
2007-10-10 17:26:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void pushInt(Register r) {
|
|
|
|
push(r);
|
2007-10-10 21:34:04 +00:00
|
|
|
stackMapper.pushedInt();
|
2007-10-10 17:26:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void pushInt(Register r, int32_t offset) {
|
|
|
|
push4(r, offset);
|
2007-10-10 21:34:04 +00:00
|
|
|
stackMapper.pushedInt();
|
2007-10-10 17:26:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void pushObject(int32_t v) {
|
|
|
|
push(v);
|
2007-10-10 21:34:04 +00:00
|
|
|
stackMapper.pushedObject();
|
2007-10-10 17:26:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void pushObject(Register r) {
|
|
|
|
push(r);
|
2007-10-10 21:34:04 +00:00
|
|
|
stackMapper.pushedObject();
|
2007-10-10 17:26:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void pushObject(Register r, int32_t offset) {
|
|
|
|
push(r, offset);
|
2007-10-10 21:34:04 +00:00
|
|
|
stackMapper.pushedObject();
|
2007-10-10 17:26:28 +00:00
|
|
|
}
|
|
|
|
|
2007-10-13 21:48:40 +00:00
|
|
|
void pushLongQuiet(uint64_t v) {
|
2007-10-08 21:41:41 +00:00
|
|
|
if (BytesPerWord == 8) {
|
|
|
|
pushAddress(v);
|
|
|
|
sub(8, rsp);
|
|
|
|
} else {
|
|
|
|
push((v >> 32) & 0xFFFFFFFF);
|
|
|
|
push((v ) & 0xFFFFFFFF);
|
|
|
|
}
|
2007-10-13 21:48:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void pushLong(uint64_t v) {
|
|
|
|
pushLongQuiet(v);
|
2007-10-10 21:34:04 +00:00
|
|
|
stackMapper.pushedLong();
|
2007-10-08 21:41:41 +00:00
|
|
|
}
|
|
|
|
|
2007-10-09 17:15:40 +00:00
|
|
|
void pushLong(Register r) {
|
|
|
|
assert(t, BytesPerWord == 8);
|
|
|
|
push(r);
|
|
|
|
sub(8, rsp);
|
2007-10-10 21:34:04 +00:00
|
|
|
stackMapper.pushedLong();
|
2007-10-10 17:26:28 +00:00
|
|
|
}
|
|
|
|
|
2007-10-13 21:48:40 +00:00
|
|
|
void pushLongQuiet(Register r, int32_t offset) {
|
2007-10-10 17:26:28 +00:00
|
|
|
assert(t, BytesPerWord == 8);
|
|
|
|
push(r, offset);
|
|
|
|
sub(8, rsp);
|
2007-10-13 21:48:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void pushLong(Register r, int32_t offset) {
|
|
|
|
pushLongQuiet(r, offset);
|
2007-10-10 21:34:04 +00:00
|
|
|
stackMapper.pushedLong();
|
2007-10-09 17:15:40 +00:00
|
|
|
}
|
|
|
|
|
2007-10-08 21:41:41 +00:00
|
|
|
void pushLong(Register low, Register high) {
|
|
|
|
assert(t, BytesPerWord == 4);
|
|
|
|
push(high);
|
|
|
|
push(low);
|
2007-10-10 21:34:04 +00:00
|
|
|
stackMapper.pushedLong();
|
2007-10-10 17:26:28 +00:00
|
|
|
}
|
|
|
|
|
2007-10-13 21:48:40 +00:00
|
|
|
void pushLongQuiet(Register low, int32_t lowOffset,
|
|
|
|
Register high, int32_t highOffset)
|
2007-10-10 17:26:28 +00:00
|
|
|
{
|
|
|
|
assert(t, BytesPerWord == 4);
|
|
|
|
push(high, highOffset);
|
|
|
|
push(low, lowOffset);
|
2007-10-13 21:48:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void pushLong(Register low, int32_t lowOffset,
|
|
|
|
Register high, int32_t highOffset)
|
|
|
|
{
|
|
|
|
pushLongQuiet(low, lowOffset, high, highOffset);
|
2007-10-10 21:34:04 +00:00
|
|
|
stackMapper.pushedLong();
|
2007-10-10 17:26:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void popInt() {
|
|
|
|
add(BytesPerWord, rsp);
|
2007-10-10 21:34:04 +00:00
|
|
|
stackMapper.poppedInt();
|
2007-10-10 17:26:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void popInt(Register r) {
|
|
|
|
pop(r);
|
2007-10-10 21:34:04 +00:00
|
|
|
stackMapper.poppedInt();
|
2007-10-10 17:26:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void popInt(Register r, int32_t offset) {
|
|
|
|
pop4(r, offset);
|
2007-10-10 21:34:04 +00:00
|
|
|
stackMapper.poppedInt();
|
2007-10-10 17:26:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void popObject(Register r) {
|
|
|
|
pop(r);
|
2007-10-10 21:34:04 +00:00
|
|
|
stackMapper.poppedObject();
|
2007-10-10 17:26:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void popObject(Register r, int32_t offset) {
|
|
|
|
pop(r, offset);
|
2007-10-10 21:34:04 +00:00
|
|
|
stackMapper.poppedObject();
|
2007-10-10 17:26:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void popLong() {
|
|
|
|
add(BytesPerWord * 2, rsp);
|
2007-10-10 21:34:04 +00:00
|
|
|
stackMapper.poppedLong();
|
2007-10-08 21:41:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void popLong(Register r) {
|
|
|
|
assert(t, BytesPerWord == 8);
|
2007-10-10 17:26:28 +00:00
|
|
|
add(BytesPerWord, rsp);
|
2007-10-08 21:41:41 +00:00
|
|
|
pop(r);
|
2007-10-10 21:34:04 +00:00
|
|
|
stackMapper.poppedLong();
|
2007-10-10 17:26:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void popLong(Register r, int32_t offset) {
|
|
|
|
assert(t, BytesPerWord == 8);
|
|
|
|
add(BytesPerWord, rsp);
|
|
|
|
pop(r, offset);
|
2007-10-10 21:34:04 +00:00
|
|
|
stackMapper.poppedLong();
|
2007-10-08 21:41:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void popLong(Register low, Register high) {
|
|
|
|
assert(t, BytesPerWord == 4);
|
|
|
|
pop(low);
|
|
|
|
pop(high);
|
2007-10-10 21:34:04 +00:00
|
|
|
stackMapper.poppedLong();
|
2007-10-10 17:26:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void popLong(Register low, int32_t lowOffset,
|
|
|
|
Register high, int32_t highOffset)
|
|
|
|
{
|
|
|
|
assert(t, BytesPerWord == 4);
|
|
|
|
pop(low, lowOffset);
|
|
|
|
pop(high, highOffset);
|
2007-10-10 21:34:04 +00:00
|
|
|
stackMapper.poppedLong();
|
2007-10-10 17:26:28 +00:00
|
|
|
}
|
|
|
|
|
2007-10-10 21:34:04 +00:00
|
|
|
void loadInt(unsigned index) {
|
2007-10-10 17:26:28 +00:00
|
|
|
pushInt(rbp, localOffset(t, index, method));
|
2007-10-08 21:41:41 +00:00
|
|
|
}
|
|
|
|
|
2007-10-10 21:34:04 +00:00
|
|
|
void loadObject(unsigned index) {
|
2007-10-10 17:26:28 +00:00
|
|
|
pushObject(rbp, localOffset(t, index, method));
|
|
|
|
}
|
|
|
|
|
2007-10-10 21:34:04 +00:00
|
|
|
void loadLong(unsigned index) {
|
2007-10-08 21:41:41 +00:00
|
|
|
if (BytesPerWord == 8) {
|
2007-10-10 17:26:28 +00:00
|
|
|
pushLong(rbp, localOffset(t, index, method));
|
2007-10-08 21:41:41 +00:00
|
|
|
} else {
|
2007-10-10 17:26:28 +00:00
|
|
|
pushLong(rbp, localOffset(t, index + 1, method),
|
|
|
|
rbp, localOffset(t, index, method));
|
2007-10-08 21:41:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-10-10 21:34:04 +00:00
|
|
|
void storeInt(unsigned index) {
|
2007-10-10 17:26:28 +00:00
|
|
|
popInt(rbp, localOffset(t, index, method));
|
2007-10-13 21:48:40 +00:00
|
|
|
stackMapper.storedInt(index);
|
2007-10-10 17:26:28 +00:00
|
|
|
}
|
|
|
|
|
2007-10-10 21:34:04 +00:00
|
|
|
void storeObject(unsigned index) {
|
2007-10-10 17:26:28 +00:00
|
|
|
popObject(rbp, localOffset(t, index, method));
|
2007-10-10 21:34:04 +00:00
|
|
|
stackMapper.storedObject(index);
|
2007-10-10 17:26:28 +00:00
|
|
|
}
|
|
|
|
|
2007-10-10 21:34:04 +00:00
|
|
|
void storeLong(unsigned index) {
|
2007-10-08 21:41:41 +00:00
|
|
|
if (BytesPerWord == 8) {
|
2007-10-10 17:26:28 +00:00
|
|
|
popLong(rbp, localOffset(t, index, method));
|
2007-10-08 21:41:41 +00:00
|
|
|
} else {
|
2007-10-10 17:26:28 +00:00
|
|
|
popLong(rbp, localOffset(t, index, method),
|
|
|
|
rbp, localOffset(t, index + 1, method));
|
2007-10-08 21:41:41 +00:00
|
|
|
}
|
2007-10-13 21:48:40 +00:00
|
|
|
stackMapper.storedLong(index);
|
2007-10-08 21:41:41 +00:00
|
|
|
}
|
|
|
|
|
2007-10-03 00:22:48 +00:00
|
|
|
void pushReturnValue(unsigned code) {
|
2007-09-26 23:23:03 +00:00
|
|
|
switch (code) {
|
|
|
|
case ByteField:
|
|
|
|
case BooleanField:
|
|
|
|
case CharField:
|
|
|
|
case ShortField:
|
|
|
|
case FloatField:
|
|
|
|
case IntField:
|
2007-10-10 17:26:28 +00:00
|
|
|
push(rax);
|
2007-10-10 21:34:04 +00:00
|
|
|
stackMapper.pushedInt();
|
2007-10-10 17:26:28 +00:00
|
|
|
break;
|
|
|
|
|
2007-09-26 23:23:03 +00:00
|
|
|
case ObjectField:
|
|
|
|
push(rax);
|
2007-10-10 21:34:04 +00:00
|
|
|
stackMapper.pushedObject();
|
2007-09-26 23:23:03 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case LongField:
|
|
|
|
case DoubleField:
|
|
|
|
push(rax);
|
|
|
|
push(rdx);
|
2007-10-10 21:34:04 +00:00
|
|
|
stackMapper.pushedLong();
|
2007-09-26 23:23:03 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case VoidField:
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
abort(t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-10-03 00:22:48 +00:00
|
|
|
void compileDirectInvoke(object target) {
|
2007-09-28 14:45:26 +00:00
|
|
|
unsigned footprint = FrameFootprint
|
|
|
|
+ (methodParameterFootprint(t, target) * BytesPerWord);
|
|
|
|
|
2007-10-04 00:41:54 +00:00
|
|
|
Compiled* code = reinterpret_cast<Compiled*>(methodCompiled(t, target));
|
2007-09-28 14:45:26 +00:00
|
|
|
|
2007-10-04 03:19:39 +00:00
|
|
|
push(rsp);
|
2007-10-03 00:22:48 +00:00
|
|
|
push(poolRegister(), poolReference(target));
|
2007-09-28 14:45:26 +00:00
|
|
|
push(rbp, FrameThread);
|
|
|
|
|
2007-10-04 00:41:54 +00:00
|
|
|
callAlignedAddress(compiledCode(code));
|
2007-09-28 14:45:26 +00:00
|
|
|
|
2007-10-13 21:48:40 +00:00
|
|
|
stackMapper.called(this->code.length());
|
|
|
|
poolRegisterClobbered = true;
|
|
|
|
|
2007-10-04 03:19:39 +00:00
|
|
|
add(footprint, rsp); // pop arguments
|
2007-10-12 00:30:46 +00:00
|
|
|
stackMapper.popped(methodParameterFootprint(t, target));
|
2007-09-28 14:45:26 +00:00
|
|
|
|
2007-10-03 00:22:48 +00:00
|
|
|
pushReturnValue(methodReturnCode(t, target));
|
2007-09-28 14:45:26 +00:00
|
|
|
}
|
|
|
|
|
2007-10-13 21:48:40 +00:00
|
|
|
void compileThrowNew(Machine::Type type) {
|
|
|
|
object class_ = arrayBody(t, t->m->types, type);
|
|
|
|
|
|
|
|
if (BytesPerWord == 8) {
|
|
|
|
mov(poolRegister(), poolReference(class_), rsi);
|
2007-10-04 03:19:39 +00:00
|
|
|
mov(rbp, FrameThread, rdi);
|
2007-10-13 21:48:40 +00:00
|
|
|
} else {
|
|
|
|
push(poolRegister(), poolReference(class_));
|
|
|
|
push(rbp, FrameThread);
|
2007-10-04 03:19:39 +00:00
|
|
|
}
|
|
|
|
|
2007-10-13 21:48:40 +00:00
|
|
|
indirectCall(reinterpret_cast<void*>(throwNew));
|
|
|
|
}
|
2007-10-04 00:41:54 +00:00
|
|
|
|
2007-10-13 21:48:40 +00:00
|
|
|
void directCall(void* function) {
|
|
|
|
callAddress(function);
|
2007-10-04 00:41:54 +00:00
|
|
|
|
2007-10-13 21:48:40 +00:00
|
|
|
poolRegisterClobbered = true;
|
2007-10-04 00:41:54 +00:00
|
|
|
}
|
|
|
|
|
2007-10-13 21:48:40 +00:00
|
|
|
void indirectCall(void* function) {
|
|
|
|
mov(reinterpret_cast<uintptr_t>(function), rbx);
|
|
|
|
callAddress(compiledCode(caller(t)));
|
|
|
|
|
|
|
|
stackMapper.called(code.length());
|
|
|
|
poolRegisterClobbered = true;
|
2007-10-08 21:41:41 +00:00
|
|
|
}
|
|
|
|
|
2007-10-13 21:48:40 +00:00
|
|
|
void compileCall(bool direct, void* function, Register arg1, Register arg2) {
|
|
|
|
if (BytesPerWord == 8) {
|
|
|
|
mov(arg2, rdx);
|
|
|
|
mov(arg1, rsi);
|
|
|
|
mov(rbp, FrameThread, rdi);
|
2007-09-30 02:48:27 +00:00
|
|
|
} else {
|
2007-10-13 21:48:40 +00:00
|
|
|
push(arg2);
|
|
|
|
push(arg1);
|
|
|
|
push(rbp, FrameThread);
|
2007-09-30 02:48:27 +00:00
|
|
|
}
|
|
|
|
|
2007-10-13 21:48:40 +00:00
|
|
|
if (direct) {
|
|
|
|
directCall(function);
|
|
|
|
} else {
|
|
|
|
indirectCall(function);
|
|
|
|
}
|
2007-09-30 02:48:27 +00:00
|
|
|
|
|
|
|
if (BytesPerWord == 4) {
|
2007-10-13 21:48:40 +00:00
|
|
|
add(BytesPerWord * 3, rsp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void compileCall(bool direct, void* function, uintptr_t arg1, Register arg2)
|
|
|
|
{
|
|
|
|
if (BytesPerWord == 8) {
|
|
|
|
mov(arg2, rdx);
|
|
|
|
mov(arg1, rsi);
|
|
|
|
mov(rbp, FrameThread, rdi);
|
|
|
|
} else {
|
|
|
|
push(arg2);
|
2007-09-30 02:48:27 +00:00
|
|
|
push(arg1);
|
2007-10-13 21:48:40 +00:00
|
|
|
push(rbp, FrameThread);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (direct) {
|
|
|
|
directCall(function);
|
2007-09-28 14:45:26 +00:00
|
|
|
} else {
|
2007-10-13 21:48:40 +00:00
|
|
|
indirectCall(function);
|
2007-09-28 14:45:26 +00:00
|
|
|
}
|
|
|
|
|
2007-10-13 21:48:40 +00:00
|
|
|
if (BytesPerWord == 4) {
|
|
|
|
add(BytesPerWord * 3, rsp);
|
|
|
|
}
|
2007-09-28 14:45:26 +00:00
|
|
|
}
|
|
|
|
|
2007-10-13 21:48:40 +00:00
|
|
|
void compileCall(bool direct, void* function, object arg1, Register arg2) {
|
|
|
|
if (BytesPerWord == 8) {
|
|
|
|
mov(arg2, rdx);
|
|
|
|
mov(poolRegister(), poolReference(arg1), rsi);
|
|
|
|
mov(rbp, FrameThread, rdi);
|
|
|
|
} else {
|
2007-09-30 02:48:27 +00:00
|
|
|
push(arg2);
|
2007-10-03 00:22:48 +00:00
|
|
|
push(poolRegister(), poolReference(arg1));
|
2007-10-13 21:48:40 +00:00
|
|
|
push(rbp, FrameThread);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (direct) {
|
|
|
|
directCall(function);
|
2007-10-03 00:22:48 +00:00
|
|
|
} else {
|
2007-10-13 21:48:40 +00:00
|
|
|
indirectCall(function);
|
2007-10-03 00:22:48 +00:00
|
|
|
}
|
|
|
|
|
2007-10-13 21:48:40 +00:00
|
|
|
if (BytesPerWord == 4) {
|
|
|
|
add(BytesPerWord * 3, rsp);
|
|
|
|
}
|
2007-10-03 00:22:48 +00:00
|
|
|
}
|
|
|
|
|
2007-10-13 21:48:40 +00:00
|
|
|
void compileCall(bool direct, void* function, object arg1) {
|
|
|
|
if (BytesPerWord == 8) {
|
|
|
|
mov(poolRegister(), poolReference(arg1), rsi);
|
|
|
|
mov(rbp, FrameThread, rdi);
|
2007-09-30 02:48:27 +00:00
|
|
|
} else {
|
2007-10-13 21:48:40 +00:00
|
|
|
push(poolRegister(), poolReference(arg1));
|
|
|
|
push(rbp, FrameThread);
|
2007-09-30 02:48:27 +00:00
|
|
|
}
|
|
|
|
|
2007-10-13 21:48:40 +00:00
|
|
|
if (direct) {
|
|
|
|
directCall(function);
|
2007-09-29 21:08:29 +00:00
|
|
|
} else {
|
2007-10-13 21:48:40 +00:00
|
|
|
indirectCall(function);
|
2007-09-29 21:08:29 +00:00
|
|
|
}
|
|
|
|
|
2007-10-13 21:48:40 +00:00
|
|
|
if (BytesPerWord == 4) {
|
|
|
|
add(BytesPerWord * 2, rsp);
|
|
|
|
}
|
2007-09-29 21:08:29 +00:00
|
|
|
}
|
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
Compiled* compile() {
|
2007-09-24 01:39:03 +00:00
|
|
|
object code = methodCode(t, method);
|
2007-09-26 23:23:03 +00:00
|
|
|
PROTECT(t, code);
|
|
|
|
|
|
|
|
unsigned parameterFootprint
|
|
|
|
= methodParameterFootprint(t, method) * BytesPerWord;
|
|
|
|
|
|
|
|
unsigned localFootprint = codeMaxLocals(t, code) * BytesPerWord;
|
2007-09-24 01:39:03 +00:00
|
|
|
|
2007-09-28 23:41:03 +00:00
|
|
|
push(rbp);
|
|
|
|
mov(rsp, rbp);
|
|
|
|
|
2007-09-27 22:20:54 +00:00
|
|
|
if (localFootprint > parameterFootprint) {
|
|
|
|
// reserve space for local variables
|
|
|
|
sub(localFootprint - parameterFootprint, rsp);
|
|
|
|
}
|
2007-10-03 00:22:48 +00:00
|
|
|
|
|
|
|
int lineNumberIndex;
|
|
|
|
object lnt = codeLineNumberTable(t, code);
|
|
|
|
if (lnt and lineNumberTableLength(t, lnt)) {
|
|
|
|
lineNumberIndex = 0;
|
|
|
|
} else {
|
2007-10-04 00:41:54 +00:00
|
|
|
lineNumberIndex = -1;
|
2007-10-03 00:22:48 +00:00
|
|
|
}
|
2007-09-24 01:39:03 +00:00
|
|
|
|
2007-10-11 22:43:03 +00:00
|
|
|
for (unsigned ip = 0; ip < codeLength(t, code);) {
|
2007-10-10 21:34:04 +00:00
|
|
|
stackMapper.newIp(ip);
|
2007-10-10 17:26:28 +00:00
|
|
|
machineIPs[ip] = this->code.length();
|
2007-09-28 23:41:03 +00:00
|
|
|
|
2007-10-03 00:22:48 +00:00
|
|
|
if (lineNumberIndex >= 0) {
|
|
|
|
object lnt = codeLineNumberTable(t, code);
|
|
|
|
LineNumber* ln = lineNumberTableBody(t, lnt, lineNumberIndex);
|
|
|
|
|
2007-10-04 00:41:54 +00:00
|
|
|
if (lineNumberIp(ln) == ip) {
|
2007-10-10 17:26:28 +00:00
|
|
|
nativeLineNumberIp(lineNumbers + lineNumberIndex)
|
|
|
|
= this->code.length();
|
|
|
|
nativeLineNumberLine(lineNumbers + lineNumberIndex)
|
|
|
|
= lineNumberLine(ln);
|
2007-10-04 00:41:54 +00:00
|
|
|
if (static_cast<unsigned>(lineNumberIndex) + 1
|
|
|
|
< lineNumberTableLength(t, lnt))
|
|
|
|
{
|
2007-10-03 00:22:48 +00:00
|
|
|
++ lineNumberIndex;
|
2007-10-04 00:41:54 +00:00
|
|
|
} else {
|
|
|
|
lineNumberIndex = -1;
|
2007-10-03 00:22:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-09-26 23:23:03 +00:00
|
|
|
unsigned instruction = codeBody(t, code, ip++);
|
|
|
|
|
|
|
|
switch (instruction) {
|
2007-09-30 04:07:22 +00:00
|
|
|
case aaload:
|
|
|
|
case baload:
|
|
|
|
case caload:
|
|
|
|
case daload:
|
|
|
|
case faload:
|
|
|
|
case iaload:
|
|
|
|
case laload:
|
|
|
|
case saload: {
|
|
|
|
Label next(this);
|
|
|
|
Label outOfBounds(this);
|
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
popInt(rcx);
|
|
|
|
popObject(rax);
|
2007-09-30 04:07:22 +00:00
|
|
|
|
|
|
|
cmp(0, rcx);
|
|
|
|
jl(outOfBounds);
|
|
|
|
|
|
|
|
mov(rax, BytesPerWord, rdx);
|
|
|
|
cmp(rdx, rcx);
|
|
|
|
jge(outOfBounds);
|
|
|
|
|
2007-09-30 15:52:21 +00:00
|
|
|
add(BytesPerWord * 2, rax);
|
2007-09-30 04:07:22 +00:00
|
|
|
|
|
|
|
switch (instruction) {
|
|
|
|
case aaload:
|
|
|
|
case faload:
|
|
|
|
case iaload:
|
|
|
|
shl(log(BytesPerWord), rcx);
|
2007-09-30 15:52:21 +00:00
|
|
|
add(rcx, rax);
|
2007-10-10 17:26:28 +00:00
|
|
|
|
|
|
|
if (instruction == aaload) {
|
|
|
|
pushObject(rax, 0);
|
|
|
|
} else {
|
|
|
|
pushInt(rax, 0);
|
|
|
|
}
|
2007-09-30 04:07:22 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case baload:
|
2007-09-30 15:52:21 +00:00
|
|
|
add(rcx, rax);
|
2007-09-30 04:07:22 +00:00
|
|
|
movs1(rax, 0, rax);
|
2007-10-10 17:26:28 +00:00
|
|
|
pushInt(rax);
|
2007-09-30 04:07:22 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case caload:
|
|
|
|
shl(1, rcx);
|
2007-09-30 15:52:21 +00:00
|
|
|
add(rcx, rax);
|
2007-09-30 04:07:22 +00:00
|
|
|
movz2(rax, 0, rax);
|
2007-10-10 17:26:28 +00:00
|
|
|
pushInt(rax);
|
2007-09-30 04:07:22 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case daload:
|
|
|
|
case laload:
|
|
|
|
shl(3, rcx);
|
2007-09-30 15:52:21 +00:00
|
|
|
add(rcx, rax);
|
2007-10-10 17:26:28 +00:00
|
|
|
pushLong(rax, 0);
|
2007-09-30 04:07:22 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case saload:
|
|
|
|
shl(1, rcx);
|
2007-09-30 15:52:21 +00:00
|
|
|
add(rcx, rax);
|
2007-09-30 04:07:22 +00:00
|
|
|
movs2(rax, 0, rax);
|
2007-10-10 17:26:28 +00:00
|
|
|
pushInt(rax);
|
2007-09-30 04:07:22 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
jmp(next);
|
|
|
|
|
|
|
|
outOfBounds.mark();
|
2007-10-13 21:48:40 +00:00
|
|
|
compileThrowNew(Machine::ArrayIndexOutOfBoundsExceptionType);
|
2007-09-30 04:07:22 +00:00
|
|
|
|
|
|
|
next.mark();
|
|
|
|
} break;
|
|
|
|
|
2007-09-30 15:52:21 +00:00
|
|
|
case aastore:
|
|
|
|
case bastore:
|
|
|
|
case castore:
|
|
|
|
case dastore:
|
|
|
|
case fastore:
|
|
|
|
case iastore:
|
|
|
|
case lastore:
|
|
|
|
case sastore: {
|
|
|
|
Label next(this);
|
|
|
|
Label outOfBounds(this);
|
|
|
|
|
|
|
|
if (instruction == dastore or instruction == lastore) {
|
2007-10-10 17:26:28 +00:00
|
|
|
popLong(rdx, rbx);
|
|
|
|
} else if (instruction == aastore) {
|
|
|
|
popObject(rbx);
|
|
|
|
} else {
|
|
|
|
popInt(rbx);
|
2007-09-30 15:52:21 +00:00
|
|
|
}
|
2007-10-10 17:26:28 +00:00
|
|
|
|
|
|
|
popInt(rcx);
|
|
|
|
popObject(rax);
|
2007-09-30 15:52:21 +00:00
|
|
|
|
|
|
|
cmp(0, rcx);
|
|
|
|
jl(outOfBounds);
|
|
|
|
|
2007-10-03 00:22:48 +00:00
|
|
|
mov(rax, BytesPerWord, rsi);
|
|
|
|
cmp(rsi, rcx);
|
2007-09-30 15:52:21 +00:00
|
|
|
jge(outOfBounds);
|
|
|
|
|
|
|
|
add(BytesPerWord * 2, rax);
|
|
|
|
|
|
|
|
switch (instruction) {
|
|
|
|
case aastore:
|
2007-10-13 21:48:40 +00:00
|
|
|
shl(log(BytesPerWord), rcx);
|
|
|
|
add(rcx, rax);
|
|
|
|
compileCall(true, reinterpret_cast<void*>(set), rax, rbx);
|
|
|
|
break;
|
|
|
|
|
2007-09-30 15:52:21 +00:00
|
|
|
case fastore:
|
|
|
|
case iastore:
|
|
|
|
shl(log(BytesPerWord), rcx);
|
|
|
|
add(rcx, rax);
|
|
|
|
mov(rbx, rax, 0);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case bastore:
|
|
|
|
add(rcx, rax);
|
|
|
|
mov1(rbx, rax, 0);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case castore:
|
|
|
|
case sastore:
|
|
|
|
shl(1, rcx);
|
|
|
|
add(rcx, rax);
|
|
|
|
mov2(rbx, rax, 0);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case dastore:
|
|
|
|
case lastore:
|
|
|
|
shl(3, rcx);
|
|
|
|
add(rcx, rax);
|
|
|
|
mov4(rbx, rax, 0);
|
|
|
|
mov4(rdx, rax, 4);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
jmp(next);
|
|
|
|
|
|
|
|
outOfBounds.mark();
|
2007-10-13 21:48:40 +00:00
|
|
|
compileThrowNew(Machine::ArrayIndexOutOfBoundsExceptionType);
|
2007-09-30 15:52:21 +00:00
|
|
|
|
|
|
|
next.mark();
|
|
|
|
} break;
|
|
|
|
|
2007-09-29 20:24:14 +00:00
|
|
|
case aconst_null:
|
2007-10-10 17:26:28 +00:00
|
|
|
pushObject(0);
|
2007-09-29 20:24:14 +00:00
|
|
|
break;
|
|
|
|
|
2007-09-28 23:41:03 +00:00
|
|
|
case aload:
|
2007-10-10 17:26:28 +00:00
|
|
|
loadObject(codeBody(t, code, ip++));
|
2007-09-28 23:41:03 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case aload_0:
|
2007-10-10 17:26:28 +00:00
|
|
|
loadObject(0);
|
2007-09-28 23:41:03 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case aload_1:
|
2007-10-10 17:26:28 +00:00
|
|
|
loadObject(1);
|
2007-09-28 23:41:03 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case aload_2:
|
2007-10-10 17:26:28 +00:00
|
|
|
loadObject(2);
|
2007-09-28 23:41:03 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case aload_3:
|
2007-10-10 17:26:28 +00:00
|
|
|
loadObject(3);
|
2007-09-28 23:41:03 +00:00
|
|
|
break;
|
|
|
|
|
2007-09-30 02:48:27 +00:00
|
|
|
case anewarray: {
|
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
|
|
|
|
|
|
|
object class_ = resolveClass(t, codePool(t, code), index - 1);
|
2007-10-04 00:41:54 +00:00
|
|
|
if (UNLIKELY(t->exception)) return 0;
|
2007-09-30 02:48:27 +00:00
|
|
|
|
|
|
|
Label nonnegative(this);
|
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
popInt(rax);
|
2007-09-30 02:48:27 +00:00
|
|
|
cmp(0, rax);
|
2007-10-09 19:30:01 +00:00
|
|
|
jge(nonnegative);
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2007-10-13 21:48:40 +00:00
|
|
|
compileThrowNew(Machine::NegativeArraySizeExceptionType);
|
2007-09-30 02:48:27 +00:00
|
|
|
|
|
|
|
nonnegative.mark();
|
2007-10-13 21:48:40 +00:00
|
|
|
|
|
|
|
compileCall(false, reinterpret_cast<void*>(makeBlankObjectArray),
|
2007-10-04 00:41:54 +00:00
|
|
|
class_, rax);
|
2007-10-13 21:48:40 +00:00
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
pushObject(rax);
|
2007-09-30 02:48:27 +00:00
|
|
|
} break;
|
|
|
|
|
2007-09-26 23:23:03 +00:00
|
|
|
case areturn:
|
2007-10-10 17:26:28 +00:00
|
|
|
popObject(rax);
|
2007-09-26 23:23:03 +00:00
|
|
|
mov(rbp, rsp);
|
|
|
|
pop(rbp);
|
|
|
|
ret();
|
2007-10-12 00:30:46 +00:00
|
|
|
stackMapper.exited();
|
2007-09-26 23:23:03 +00:00
|
|
|
break;
|
|
|
|
|
2007-09-30 15:52:21 +00:00
|
|
|
case arraylength:
|
2007-10-10 17:26:28 +00:00
|
|
|
popObject(rax);
|
2007-10-12 00:30:46 +00:00
|
|
|
pushInt(rax, BytesPerWord);
|
2007-09-30 15:52:21 +00:00
|
|
|
break;
|
|
|
|
|
2007-09-28 23:41:03 +00:00
|
|
|
case astore:
|
2007-10-10 17:26:28 +00:00
|
|
|
storeObject(codeBody(t, code, ip++));
|
2007-09-28 23:41:03 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case astore_0:
|
2007-10-10 17:26:28 +00:00
|
|
|
storeObject(0);
|
2007-09-28 23:41:03 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case astore_1:
|
2007-10-10 17:26:28 +00:00
|
|
|
storeObject(1);
|
2007-09-28 23:41:03 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case astore_2:
|
2007-10-10 17:26:28 +00:00
|
|
|
storeObject(2);
|
2007-09-28 23:41:03 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case astore_3:
|
2007-10-10 17:26:28 +00:00
|
|
|
storeObject(3);
|
2007-09-28 23:41:03 +00:00
|
|
|
break;
|
|
|
|
|
2007-09-30 02:48:27 +00:00
|
|
|
case athrow:
|
2007-10-13 21:48:40 +00:00
|
|
|
if (BytesPerWord == 8) {
|
|
|
|
popObject(rsi);
|
|
|
|
mov(rbp, FrameThread, rdi);
|
|
|
|
} else {
|
|
|
|
push(rbp, FrameThread);
|
|
|
|
}
|
|
|
|
|
|
|
|
indirectCall(reinterpret_cast<void*>(throw_));
|
2007-10-12 00:30:46 +00:00
|
|
|
stackMapper.exited();
|
2007-09-30 02:48:27 +00:00
|
|
|
break;
|
|
|
|
|
2007-09-28 14:45:26 +00:00
|
|
|
case bipush: {
|
2007-10-10 17:26:28 +00:00
|
|
|
pushInt(static_cast<int8_t>(codeBody(t, code, ip++)));
|
2007-09-28 14:45:26 +00:00
|
|
|
} break;
|
|
|
|
|
2007-09-29 21:08:29 +00:00
|
|
|
case checkcast: {
|
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
|
|
|
|
|
|
|
object class_ = resolveClass(t, codePool(t, code), index - 1);
|
2007-10-04 00:41:54 +00:00
|
|
|
if (UNLIKELY(t->exception)) return 0;
|
2007-09-29 21:08:29 +00:00
|
|
|
|
|
|
|
Label next(this);
|
|
|
|
|
2007-09-30 02:48:27 +00:00
|
|
|
mov(rsp, 0, rax);
|
2007-09-29 21:08:29 +00:00
|
|
|
cmp(0, rax);
|
|
|
|
je(next);
|
|
|
|
|
2007-10-03 00:22:48 +00:00
|
|
|
mov(poolRegister(), poolReference(class_), rcx);
|
2007-09-29 21:08:29 +00:00
|
|
|
mov(rax, 0, rax);
|
|
|
|
cmp(rcx, rax);
|
|
|
|
je(next);
|
|
|
|
|
2007-10-13 21:48:40 +00:00
|
|
|
compileCall(true, reinterpret_cast<void*>(isAssignableFrom), rcx, rax);
|
|
|
|
|
2007-09-29 21:08:29 +00:00
|
|
|
cmp(0, rax);
|
|
|
|
jne(next);
|
|
|
|
|
2007-10-13 21:48:40 +00:00
|
|
|
compileThrowNew(Machine::ClassCastExceptionType);
|
2007-09-29 21:08:29 +00:00
|
|
|
|
|
|
|
next.mark();
|
|
|
|
} break;
|
|
|
|
|
2007-09-26 23:23:03 +00:00
|
|
|
case dup:
|
2007-09-30 02:48:27 +00:00
|
|
|
push(rsp, 0);
|
2007-10-10 21:34:04 +00:00
|
|
|
stackMapper.dupped();
|
2007-09-26 23:23:03 +00:00
|
|
|
break;
|
|
|
|
|
2007-09-29 20:24:14 +00:00
|
|
|
case getfield: {
|
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
|
|
|
|
|
|
|
object field = resolveField(t, codePool(t, code), index - 1);
|
2007-10-04 00:41:54 +00:00
|
|
|
if (UNLIKELY(t->exception)) return 0;
|
2007-09-29 20:24:14 +00:00
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
popObject(rax);
|
2007-09-29 20:24:14 +00:00
|
|
|
|
|
|
|
switch (fieldCode(t, field)) {
|
|
|
|
case ByteField:
|
|
|
|
case BooleanField:
|
|
|
|
movs1(rax, fieldOffset(t, field), rax);
|
2007-10-10 17:26:28 +00:00
|
|
|
pushInt(rax);
|
2007-09-29 20:24:14 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CharField:
|
|
|
|
movz2(rax, fieldOffset(t, field), rax);
|
2007-10-10 17:26:28 +00:00
|
|
|
pushInt(rax);
|
2007-09-29 20:24:14 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ShortField:
|
|
|
|
movs2(rax, fieldOffset(t, field), rax);
|
2007-10-10 17:26:28 +00:00
|
|
|
pushInt(rax);
|
2007-09-29 20:24:14 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FloatField:
|
|
|
|
case IntField:
|
2007-10-10 17:26:28 +00:00
|
|
|
pushInt(rax, fieldOffset(t, field));
|
2007-09-29 20:24:14 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DoubleField:
|
|
|
|
case LongField:
|
2007-10-10 17:26:28 +00:00
|
|
|
pushLong(rax, fieldOffset(t, field));
|
2007-09-29 20:24:14 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ObjectField:
|
2007-10-10 17:26:28 +00:00
|
|
|
pushObject(rax, fieldOffset(t, field));
|
2007-09-29 20:24:14 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
abort(t);
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
2007-09-26 23:23:03 +00:00
|
|
|
case getstatic: {
|
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
|
|
|
|
|
|
|
object field = resolveField(t, codePool(t, code), index - 1);
|
2007-10-04 00:41:54 +00:00
|
|
|
if (UNLIKELY(t->exception)) return 0;
|
2007-09-26 23:23:03 +00:00
|
|
|
PROTECT(t, field);
|
|
|
|
|
|
|
|
initClass(t, fieldClass(t, field));
|
2007-10-04 00:41:54 +00:00
|
|
|
if (UNLIKELY(t->exception)) return 0;
|
2007-09-26 23:23:03 +00:00
|
|
|
|
|
|
|
object table = classStaticTable(t, fieldClass(t, field));
|
|
|
|
|
2007-10-03 00:22:48 +00:00
|
|
|
mov(poolRegister(), poolReference(table), rax);
|
2007-09-30 02:48:27 +00:00
|
|
|
add((fieldOffset(t, field) * BytesPerWord) + ArrayBody, rax);
|
2007-09-26 23:23:03 +00:00
|
|
|
|
|
|
|
switch (fieldCode(t, field)) {
|
|
|
|
case ByteField:
|
|
|
|
case BooleanField:
|
|
|
|
case CharField:
|
|
|
|
case ShortField:
|
|
|
|
case FloatField:
|
|
|
|
case IntField: {
|
|
|
|
Label zero(this);
|
|
|
|
Label next(this);
|
|
|
|
|
|
|
|
cmp(0, rax);
|
2007-09-29 21:08:29 +00:00
|
|
|
je(zero);
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-10-13 21:48:40 +00:00
|
|
|
push(rax, IntValue);
|
2007-09-26 23:23:03 +00:00
|
|
|
jmp(next);
|
|
|
|
|
|
|
|
zero.mark();
|
2007-10-13 21:48:40 +00:00
|
|
|
push(0);
|
2007-09-26 23:23:03 +00:00
|
|
|
|
|
|
|
next.mark();
|
2007-10-13 21:48:40 +00:00
|
|
|
stackMapper.pushedInt();
|
2007-09-26 23:23:03 +00:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case DoubleField:
|
|
|
|
case LongField: {
|
|
|
|
Label zero(this);
|
|
|
|
Label next(this);
|
|
|
|
|
|
|
|
cmp(0, rax);
|
2007-09-29 21:08:29 +00:00
|
|
|
je(zero);
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-10-13 21:48:40 +00:00
|
|
|
if (BytesPerWord == 8) {
|
|
|
|
pushLongQuiet(rax, LongValue);
|
|
|
|
} else {
|
|
|
|
pushLongQuiet(rax, LongValue);
|
|
|
|
pushLongQuiet(rax, LongValue + 4);
|
|
|
|
}
|
2007-09-26 23:23:03 +00:00
|
|
|
jmp(next);
|
|
|
|
|
|
|
|
zero.mark();
|
2007-10-13 21:48:40 +00:00
|
|
|
pushLongQuiet(0);
|
2007-09-26 23:23:03 +00:00
|
|
|
|
|
|
|
next.mark();
|
2007-10-13 21:48:40 +00:00
|
|
|
stackMapper.pushedLong();
|
2007-09-26 23:23:03 +00:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case ObjectField: {
|
2007-10-10 17:26:28 +00:00
|
|
|
pushObject(rax, 0);
|
2007-09-26 23:23:03 +00:00
|
|
|
} break;
|
|
|
|
|
|
|
|
default: abort(t);
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
2007-09-30 02:48:27 +00:00
|
|
|
case goto_: {
|
|
|
|
int16_t offset = codeReadInt16(t, code, ip);
|
|
|
|
jmp((ip - 3) + offset);
|
2007-10-11 22:43:03 +00:00
|
|
|
stackMapper.jumped((ip - 3) + offset);
|
2007-09-30 02:48:27 +00:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case goto_w: {
|
|
|
|
int32_t offset = codeReadInt32(t, code, ip);
|
|
|
|
jmp((ip - 5) + offset);
|
2007-10-11 22:43:03 +00:00
|
|
|
stackMapper.jumped((ip - 5) + offset);
|
2007-09-30 02:48:27 +00:00
|
|
|
} break;
|
|
|
|
|
2007-09-30 15:52:21 +00:00
|
|
|
case i2b:
|
|
|
|
mov(rsp, 0, rax);
|
|
|
|
movs1(rax, rax);
|
|
|
|
mov(rax, rsp, 0);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case i2c:
|
|
|
|
mov(rsp, 0, rax);
|
|
|
|
movz2(rax, rax);
|
|
|
|
mov(rax, rsp, 0);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case i2s:
|
|
|
|
mov(rsp, 0, rax);
|
|
|
|
movs2(rax, rax);
|
|
|
|
mov(rax, rsp, 0);
|
|
|
|
break;
|
|
|
|
|
2007-10-04 22:41:19 +00:00
|
|
|
case i2l:
|
2007-10-08 21:41:41 +00:00
|
|
|
if (BytesPerWord == 8) {
|
2007-10-10 17:26:28 +00:00
|
|
|
pushInt();
|
2007-10-08 21:41:41 +00:00
|
|
|
} else {
|
2007-10-10 17:26:28 +00:00
|
|
|
popInt(rax);
|
2007-10-08 21:41:41 +00:00
|
|
|
cdq();
|
|
|
|
pushLong(rax, rdx);
|
|
|
|
}
|
2007-10-04 22:41:19 +00:00
|
|
|
break;
|
|
|
|
|
2007-09-24 01:39:03 +00:00
|
|
|
case iadd:
|
2007-10-10 17:26:28 +00:00
|
|
|
popInt(rax);
|
|
|
|
popInt(rcx);
|
|
|
|
add(rcx, rax);
|
|
|
|
pushInt(rax);
|
2007-09-24 01:39:03 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case iconst_m1:
|
2007-10-10 17:26:28 +00:00
|
|
|
pushInt(-1);
|
2007-09-24 01:39:03 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case iconst_0:
|
2007-10-10 17:26:28 +00:00
|
|
|
pushInt(0);
|
2007-09-24 01:39:03 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case iconst_1:
|
2007-10-10 17:26:28 +00:00
|
|
|
pushInt(1);
|
2007-09-24 01:39:03 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case iconst_2:
|
2007-10-10 17:26:28 +00:00
|
|
|
pushInt(2);
|
2007-09-24 01:39:03 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case iconst_3:
|
2007-10-10 17:26:28 +00:00
|
|
|
pushInt(3);
|
2007-09-24 01:39:03 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case iconst_4:
|
2007-10-10 17:26:28 +00:00
|
|
|
pushInt(4);
|
2007-09-24 01:39:03 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case iconst_5:
|
2007-10-10 17:26:28 +00:00
|
|
|
pushInt(5);
|
2007-09-24 01:39:03 +00:00
|
|
|
break;
|
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
case if_acmpeq: {
|
|
|
|
int16_t offset = codeReadInt16(t, code, ip);
|
|
|
|
|
|
|
|
popObject(rax);
|
|
|
|
popObject(rcx);
|
|
|
|
cmp(rax, rcx);
|
|
|
|
je((ip - 3) + offset);
|
2007-10-11 22:43:03 +00:00
|
|
|
stackMapper.branched((ip - 3) + offset);
|
2007-10-10 17:26:28 +00:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case if_acmpne: {
|
|
|
|
int16_t offset = codeReadInt16(t, code, ip);
|
|
|
|
|
|
|
|
popObject(rax);
|
|
|
|
popObject(rcx);
|
|
|
|
cmp(rax, rcx);
|
|
|
|
jne((ip - 3) + offset);
|
2007-10-11 22:43:03 +00:00
|
|
|
stackMapper.branched((ip - 3) + offset);
|
2007-10-10 17:26:28 +00:00
|
|
|
} break;
|
|
|
|
|
2007-09-29 20:24:14 +00:00
|
|
|
case if_icmpeq: {
|
|
|
|
int16_t offset = codeReadInt16(t, code, ip);
|
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
popInt(rax);
|
|
|
|
popInt(rcx);
|
2007-09-29 20:24:14 +00:00
|
|
|
cmp(rax, rcx);
|
2007-09-29 21:08:29 +00:00
|
|
|
je((ip - 3) + offset);
|
2007-10-11 22:43:03 +00:00
|
|
|
stackMapper.branched((ip - 3) + offset);
|
2007-09-29 20:24:14 +00:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case if_icmpne: {
|
|
|
|
int16_t offset = codeReadInt16(t, code, ip);
|
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
popInt(rax);
|
|
|
|
popInt(rcx);
|
2007-09-29 20:24:14 +00:00
|
|
|
cmp(rax, rcx);
|
2007-09-29 21:08:29 +00:00
|
|
|
jne((ip - 3) + offset);
|
2007-10-11 22:43:03 +00:00
|
|
|
stackMapper.branched((ip - 3) + offset);
|
2007-09-29 20:24:14 +00:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case if_icmpgt: {
|
|
|
|
int16_t offset = codeReadInt16(t, code, ip);
|
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
popInt(rax);
|
|
|
|
popInt(rcx);
|
2007-09-29 20:24:14 +00:00
|
|
|
cmp(rax, rcx);
|
|
|
|
jg((ip - 3) + offset);
|
2007-10-11 22:43:03 +00:00
|
|
|
stackMapper.branched((ip - 3) + offset);
|
2007-09-29 20:24:14 +00:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case if_icmpge: {
|
|
|
|
int16_t offset = codeReadInt16(t, code, ip);
|
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
popInt(rax);
|
|
|
|
popInt(rcx);
|
2007-09-29 20:24:14 +00:00
|
|
|
cmp(rax, rcx);
|
|
|
|
jge((ip - 3) + offset);
|
2007-10-11 22:43:03 +00:00
|
|
|
stackMapper.branched((ip - 3) + offset);
|
2007-09-29 20:24:14 +00:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case if_icmplt: {
|
|
|
|
int16_t offset = codeReadInt16(t, code, ip);
|
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
popInt(rax);
|
|
|
|
popInt(rcx);
|
2007-09-29 20:24:14 +00:00
|
|
|
cmp(rax, rcx);
|
|
|
|
jl((ip - 3) + offset);
|
2007-10-11 22:43:03 +00:00
|
|
|
stackMapper.branched((ip - 3) + offset);
|
2007-09-29 20:24:14 +00:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case if_icmple: {
|
|
|
|
int16_t offset = codeReadInt16(t, code, ip);
|
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
popInt(rax);
|
|
|
|
popInt(rcx);
|
2007-09-29 20:24:14 +00:00
|
|
|
cmp(rax, rcx);
|
|
|
|
jle((ip - 3) + offset);
|
2007-10-11 22:43:03 +00:00
|
|
|
stackMapper.branched((ip - 3) + offset);
|
2007-09-29 20:24:14 +00:00
|
|
|
} break;
|
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
case ifeq: {
|
|
|
|
int16_t offset = codeReadInt16(t, code, ip);
|
|
|
|
|
|
|
|
popInt(rax);
|
|
|
|
cmp(0, rax);
|
|
|
|
je((ip - 3) + offset);
|
2007-10-12 00:30:46 +00:00
|
|
|
stackMapper.branched((ip - 3) + offset);
|
2007-10-10 17:26:28 +00:00
|
|
|
} break;
|
|
|
|
|
2007-09-28 23:41:03 +00:00
|
|
|
case ifnull: {
|
|
|
|
int16_t offset = codeReadInt16(t, code, ip);
|
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
popObject(rax);
|
2007-09-28 23:41:03 +00:00
|
|
|
cmp(0, rax);
|
2007-09-29 21:08:29 +00:00
|
|
|
je((ip - 3) + offset);
|
2007-10-11 22:43:03 +00:00
|
|
|
stackMapper.branched((ip - 3) + offset);
|
2007-09-28 23:41:03 +00:00
|
|
|
} break;
|
2007-09-24 01:39:03 +00:00
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
case ifne: {
|
|
|
|
int16_t offset = codeReadInt16(t, code, ip);
|
|
|
|
|
|
|
|
popInt(rax);
|
|
|
|
cmp(0, rax);
|
|
|
|
jne((ip - 3) + offset);
|
2007-10-11 22:43:03 +00:00
|
|
|
stackMapper.branched((ip - 3) + offset);
|
2007-10-10 17:26:28 +00:00
|
|
|
} break;
|
|
|
|
|
2007-09-29 20:24:14 +00:00
|
|
|
case ifnonnull: {
|
|
|
|
int16_t offset = codeReadInt16(t, code, ip);
|
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
popObject(rax);
|
2007-09-29 20:24:14 +00:00
|
|
|
cmp(0, rax);
|
2007-09-29 21:08:29 +00:00
|
|
|
jne((ip - 3) + offset);
|
2007-10-11 22:43:03 +00:00
|
|
|
stackMapper.branched((ip - 3) + offset);
|
2007-09-29 20:24:14 +00:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case ifgt: {
|
|
|
|
int16_t offset = codeReadInt16(t, code, ip);
|
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
popInt(rax);
|
2007-09-29 20:24:14 +00:00
|
|
|
cmp(0, rax);
|
|
|
|
jg((ip - 3) + offset);
|
2007-10-11 22:43:03 +00:00
|
|
|
stackMapper.branched((ip - 3) + offset);
|
2007-09-29 20:24:14 +00:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case ifge: {
|
|
|
|
int16_t offset = codeReadInt16(t, code, ip);
|
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
popInt(rax);
|
2007-09-29 20:24:14 +00:00
|
|
|
cmp(0, rax);
|
|
|
|
jge((ip - 3) + offset);
|
2007-10-11 22:43:03 +00:00
|
|
|
stackMapper.branched((ip - 3) + offset);
|
2007-09-29 20:24:14 +00:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case iflt: {
|
|
|
|
int16_t offset = codeReadInt16(t, code, ip);
|
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
popInt(rax);
|
2007-09-29 20:24:14 +00:00
|
|
|
cmp(0, rax);
|
|
|
|
jl((ip - 3) + offset);
|
2007-10-11 22:43:03 +00:00
|
|
|
stackMapper.branched((ip - 3) + offset);
|
2007-09-29 20:24:14 +00:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case ifle: {
|
|
|
|
int16_t offset = codeReadInt16(t, code, ip);
|
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
popInt(rax);
|
2007-09-29 20:24:14 +00:00
|
|
|
cmp(0, rax);
|
|
|
|
jle((ip - 3) + offset);
|
2007-10-11 22:43:03 +00:00
|
|
|
stackMapper.branched((ip - 3) + offset);
|
2007-09-29 20:24:14 +00:00
|
|
|
} break;
|
|
|
|
|
2007-09-30 02:48:27 +00:00
|
|
|
case iinc: {
|
|
|
|
uint8_t index = codeBody(t, code, ip++);
|
|
|
|
int8_t c = codeBody(t, code, ip++);
|
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
add(c, rbp, localOffset(t, index, method));
|
2007-09-29 20:24:14 +00:00
|
|
|
} break;
|
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
case iload:
|
|
|
|
case fload:
|
|
|
|
loadInt(codeBody(t, code, ip++));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case iload_0:
|
|
|
|
case fload_0:
|
|
|
|
loadInt(0);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case iload_1:
|
|
|
|
case fload_1:
|
|
|
|
loadInt(1);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case iload_2:
|
|
|
|
case fload_2:
|
|
|
|
loadInt(2);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case iload_3:
|
|
|
|
case fload_3:
|
|
|
|
loadInt(3);
|
|
|
|
break;
|
|
|
|
|
2007-10-08 21:41:41 +00:00
|
|
|
case vm::imul:
|
2007-10-10 17:26:28 +00:00
|
|
|
popInt(rax);
|
|
|
|
popInt(rcx);
|
2007-10-08 21:41:41 +00:00
|
|
|
Assembler::imul(rcx);
|
2007-10-10 17:26:28 +00:00
|
|
|
pushInt(rax);
|
2007-10-08 21:41:41 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ineg:
|
|
|
|
neg(rsp, 0);
|
|
|
|
break;
|
|
|
|
|
2007-09-29 21:08:29 +00:00
|
|
|
case instanceof: {
|
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
|
|
|
|
|
|
|
object class_ = resolveClass(t, codePool(t, code), index - 1);
|
2007-10-04 00:41:54 +00:00
|
|
|
if (UNLIKELY(t->exception)) return 0;
|
2007-09-29 21:08:29 +00:00
|
|
|
|
|
|
|
Label call(this);
|
|
|
|
Label zero(this);
|
|
|
|
Label next(this);
|
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
popObject(rax);
|
2007-09-29 21:08:29 +00:00
|
|
|
cmp(0, rax);
|
|
|
|
je(zero);
|
|
|
|
|
2007-10-03 00:22:48 +00:00
|
|
|
mov(poolRegister(), poolReference(class_), rcx);
|
2007-09-29 21:08:29 +00:00
|
|
|
mov(rax, 0, rax);
|
|
|
|
cmp(rcx, rax);
|
|
|
|
jne(call);
|
|
|
|
|
2007-10-12 00:30:46 +00:00
|
|
|
push(1);
|
2007-09-29 21:08:29 +00:00
|
|
|
jmp(next);
|
|
|
|
|
|
|
|
call.mark();
|
2007-10-13 21:48:40 +00:00
|
|
|
|
|
|
|
compileCall(true, reinterpret_cast<void*>(isAssignableFrom), rcx, rax);
|
|
|
|
|
2007-10-12 00:30:46 +00:00
|
|
|
push(rax);
|
2007-09-29 21:08:29 +00:00
|
|
|
jmp(next);
|
|
|
|
|
|
|
|
zero.mark();
|
2007-10-12 00:30:46 +00:00
|
|
|
push(0);
|
2007-09-29 21:08:29 +00:00
|
|
|
|
|
|
|
next.mark();
|
2007-10-12 00:30:46 +00:00
|
|
|
|
|
|
|
stackMapper.pushedInt();
|
2007-09-29 21:08:29 +00:00
|
|
|
} break;
|
|
|
|
|
2007-09-26 23:23:03 +00:00
|
|
|
case invokespecial: {
|
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
|
|
|
|
|
|
|
object target = resolveMethod(t, codePool(t, code), index - 1);
|
2007-10-04 00:41:54 +00:00
|
|
|
if (UNLIKELY(t->exception)) return 0;
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-09-29 20:24:14 +00:00
|
|
|
object class_ = methodClass(t, target);
|
2007-09-26 23:23:03 +00:00
|
|
|
if (isSpecialMethod(t, target, class_)) {
|
2007-09-28 14:45:26 +00:00
|
|
|
target = findMethod(t, target, classSuper(t, class_));
|
2007-09-26 23:23:03 +00:00
|
|
|
}
|
|
|
|
|
2007-10-04 00:41:54 +00:00
|
|
|
compileDirectInvoke(target);
|
2007-09-28 14:45:26 +00:00
|
|
|
} break;
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-09-28 14:45:26 +00:00
|
|
|
case invokestatic: {
|
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-09-28 14:45:26 +00:00
|
|
|
object target = resolveMethod(t, codePool(t, code), index - 1);
|
2007-10-04 00:41:54 +00:00
|
|
|
if (UNLIKELY(t->exception)) return 0;
|
2007-09-28 14:45:26 +00:00
|
|
|
PROTECT(t, target);
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-09-29 20:24:14 +00:00
|
|
|
initClass(t, methodClass(t, target));
|
2007-10-04 00:41:54 +00:00
|
|
|
if (UNLIKELY(t->exception)) return 0;
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-10-04 00:41:54 +00:00
|
|
|
compileDirectInvoke(target);
|
2007-09-26 23:23:03 +00:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case invokevirtual: {
|
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
|
|
|
|
|
|
|
object target = resolveMethod(t, codePool(t, code), index - 1);
|
2007-10-04 00:41:54 +00:00
|
|
|
if (UNLIKELY(t->exception)) return 0;
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-09-27 22:20:54 +00:00
|
|
|
unsigned parameterFootprint
|
|
|
|
= methodParameterFootprint(t, target) * BytesPerWord;
|
|
|
|
|
|
|
|
unsigned instance = parameterFootprint - BytesPerWord;
|
|
|
|
|
|
|
|
unsigned footprint = FrameFootprint + parameterFootprint;
|
2007-09-26 23:23:03 +00:00
|
|
|
|
|
|
|
unsigned offset = ArrayBody + (methodOffset(t, target) * BytesPerWord);
|
2007-09-27 22:20:54 +00:00
|
|
|
|
|
|
|
mov(rsp, instance, rax); // load instance
|
|
|
|
mov(rax, 0, rax); // load class
|
2007-09-26 23:23:03 +00:00
|
|
|
mov(rax, ClassVirtualTable, rax); // load vtable
|
|
|
|
mov(rax, offset, rax); // load method
|
2007-09-27 22:20:54 +00:00
|
|
|
|
2007-10-02 00:08:17 +00:00
|
|
|
push(rsp);
|
2007-09-27 22:20:54 +00:00
|
|
|
push(rax);
|
|
|
|
push(rbp, FrameThread);
|
|
|
|
|
2007-09-26 23:23:03 +00:00
|
|
|
mov(rax, MethodCompiled, rax); // load compiled code
|
|
|
|
add(CompiledBody, rax);
|
|
|
|
call(rax); // call compiled code
|
2007-10-12 22:06:33 +00:00
|
|
|
|
|
|
|
stackMapper.called(this->code.length());
|
2007-10-13 21:48:40 +00:00
|
|
|
poolRegisterClobbered = true;
|
2007-09-26 23:23:03 +00:00
|
|
|
|
|
|
|
add(footprint, rsp); // pop arguments
|
2007-10-12 00:30:46 +00:00
|
|
|
stackMapper.popped(methodParameterFootprint(t, target));
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-10-04 00:41:54 +00:00
|
|
|
pushReturnValue(methodReturnCode(t, target));
|
2007-09-26 23:23:03 +00:00
|
|
|
} break;
|
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
case ireturn:
|
|
|
|
case freturn:
|
|
|
|
popInt(rax);
|
|
|
|
mov(rbp, rsp);
|
|
|
|
pop(rbp);
|
|
|
|
ret();
|
2007-10-12 00:30:46 +00:00
|
|
|
stackMapper.exited();
|
2007-10-10 17:26:28 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case istore:
|
|
|
|
case fstore:
|
|
|
|
storeInt(codeBody(t, code, ip++));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case istore_0:
|
|
|
|
case fstore_0:
|
|
|
|
storeInt(0);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case istore_1:
|
|
|
|
case fstore_1:
|
|
|
|
storeInt(1);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case istore_2:
|
|
|
|
case fstore_2:
|
|
|
|
storeInt(2);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case istore_3:
|
|
|
|
case fstore_3:
|
|
|
|
storeInt(3);
|
|
|
|
break;
|
|
|
|
|
2007-09-30 02:48:27 +00:00
|
|
|
case isub:
|
2007-10-10 17:26:28 +00:00
|
|
|
popInt(rax);
|
2007-10-08 21:41:41 +00:00
|
|
|
sub(rax, rsp, 0);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case l2i:
|
|
|
|
if (BytesPerWord == 8) {
|
2007-10-10 17:26:28 +00:00
|
|
|
popInt();
|
2007-10-08 21:41:41 +00:00
|
|
|
} else {
|
2007-10-10 17:26:28 +00:00
|
|
|
popInt(rax);
|
2007-10-08 21:41:41 +00:00
|
|
|
mov(rax, rsp, 0);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ladd:
|
|
|
|
if (BytesPerWord == 8) {
|
2007-10-10 17:26:28 +00:00
|
|
|
popLong(rax);
|
2007-10-08 21:41:41 +00:00
|
|
|
add(rax, rsp, BytesPerWord);
|
|
|
|
} else {
|
|
|
|
popLong(rax, rdx);
|
|
|
|
add(rax, rsp, 0);
|
|
|
|
adc(rdx, rsp, BytesPerWord);
|
|
|
|
}
|
2007-09-30 02:48:27 +00:00
|
|
|
break;
|
|
|
|
|
2007-09-26 23:23:03 +00:00
|
|
|
case ldc:
|
|
|
|
case ldc_w: {
|
|
|
|
uint16_t index;
|
|
|
|
|
|
|
|
if (instruction == ldc) {
|
|
|
|
index = codeBody(t, code, ip++);
|
|
|
|
} else {
|
2007-10-04 22:41:19 +00:00
|
|
|
index = codeReadInt16(t, code, ip);
|
2007-09-26 23:23:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
object v = arrayBody(t, codePool(t, code), index - 1);
|
|
|
|
|
|
|
|
if (objectClass(t, v) == arrayBody(t, t->m->types, Machine::IntType)) {
|
2007-10-10 17:26:28 +00:00
|
|
|
pushInt(intValue(t, v));
|
2007-09-26 23:23:03 +00:00
|
|
|
} else if (objectClass(t, v)
|
|
|
|
== arrayBody(t, t->m->types, Machine::FloatType))
|
|
|
|
{
|
2007-10-10 17:26:28 +00:00
|
|
|
pushInt(floatValue(t, v));
|
2007-09-26 23:23:03 +00:00
|
|
|
} else if (objectClass(t, v)
|
|
|
|
== arrayBody(t, t->m->types, Machine::StringType))
|
|
|
|
{
|
2007-10-10 17:26:28 +00:00
|
|
|
pushObject(poolRegister(), poolReference(v));
|
2007-09-26 23:23:03 +00:00
|
|
|
} else {
|
|
|
|
object class_ = resolveClass(t, codePool(t, code), index - 1);
|
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
pushObject(poolRegister(), poolReference(class_));
|
2007-09-26 23:23:03 +00:00
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
2007-10-04 22:41:19 +00:00
|
|
|
case ldc2_w: {
|
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
|
|
|
|
|
|
|
object v = arrayBody(t, codePool(t, code), index - 1);
|
|
|
|
|
|
|
|
if (objectClass(t, v) == arrayBody(t, t->m->types, Machine::LongType))
|
|
|
|
{
|
2007-10-08 21:41:41 +00:00
|
|
|
pushLong(longValue(t, v));
|
2007-10-04 22:41:19 +00:00
|
|
|
} else if (objectClass(t, v)
|
|
|
|
== arrayBody(t, t->m->types, Machine::DoubleType))
|
|
|
|
{
|
2007-10-08 21:41:41 +00:00
|
|
|
pushLong(doubleValue(t, v));
|
2007-10-04 22:41:19 +00:00
|
|
|
} else {
|
|
|
|
abort(t);
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case lconst_0:
|
2007-10-08 21:41:41 +00:00
|
|
|
pushLong(0);
|
2007-10-04 22:41:19 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case lconst_1:
|
2007-10-08 21:41:41 +00:00
|
|
|
pushLong(1);
|
2007-10-04 22:41:19 +00:00
|
|
|
break;
|
|
|
|
|
2007-10-08 21:41:41 +00:00
|
|
|
case lcmp: {
|
|
|
|
Label next(this);
|
|
|
|
Label less(this);
|
|
|
|
Label greater(this);
|
2007-10-04 22:41:19 +00:00
|
|
|
|
2007-10-08 21:41:41 +00:00
|
|
|
if (BytesPerWord == 8) {
|
|
|
|
popLong(rax);
|
2007-10-08 23:13:55 +00:00
|
|
|
popLong(rcx);
|
2007-10-08 21:41:41 +00:00
|
|
|
|
2007-10-08 23:13:55 +00:00
|
|
|
cmp(rax, rcx);
|
2007-10-08 21:41:41 +00:00
|
|
|
jl(less);
|
|
|
|
jg(greater);
|
2007-10-04 22:41:19 +00:00
|
|
|
|
2007-10-12 14:26:36 +00:00
|
|
|
push(0);
|
2007-10-08 21:41:41 +00:00
|
|
|
jmp(next);
|
|
|
|
|
|
|
|
less.mark();
|
2007-10-12 14:26:36 +00:00
|
|
|
push(-1);
|
2007-10-08 21:41:41 +00:00
|
|
|
jmp(next);
|
2007-10-04 22:41:19 +00:00
|
|
|
|
2007-10-08 21:41:41 +00:00
|
|
|
greater.mark();
|
2007-10-12 14:26:36 +00:00
|
|
|
push(1);
|
2007-10-04 22:41:19 +00:00
|
|
|
|
2007-10-08 21:41:41 +00:00
|
|
|
next.mark();
|
2007-10-12 14:26:36 +00:00
|
|
|
|
|
|
|
stackMapper.pushedInt();
|
2007-10-08 21:41:41 +00:00
|
|
|
} else {
|
|
|
|
popLong(rax, rdx);
|
2007-10-08 23:13:55 +00:00
|
|
|
popLong(rcx, rbx);
|
2007-10-04 22:41:19 +00:00
|
|
|
|
2007-10-08 21:41:41 +00:00
|
|
|
cmp(rdx, rbx);
|
|
|
|
jl(less);
|
|
|
|
jg(greater);
|
|
|
|
|
|
|
|
cmp(rax, rcx);
|
|
|
|
jb(less);
|
|
|
|
ja(greater);
|
2007-10-04 22:41:19 +00:00
|
|
|
|
2007-10-12 14:26:36 +00:00
|
|
|
push(0);
|
2007-10-08 21:41:41 +00:00
|
|
|
jmp(next);
|
2007-10-04 22:41:19 +00:00
|
|
|
|
2007-10-08 21:41:41 +00:00
|
|
|
less.mark();
|
2007-10-12 14:26:36 +00:00
|
|
|
push(-1);
|
2007-10-08 21:41:41 +00:00
|
|
|
jmp(next);
|
2007-10-04 22:41:19 +00:00
|
|
|
|
2007-10-08 21:41:41 +00:00
|
|
|
greater.mark();
|
2007-10-12 14:26:36 +00:00
|
|
|
push(1);
|
2007-10-04 22:41:19 +00:00
|
|
|
|
2007-10-08 21:41:41 +00:00
|
|
|
next.mark();
|
2007-10-12 14:26:36 +00:00
|
|
|
|
|
|
|
stackMapper.pushedInt();
|
2007-10-08 21:41:41 +00:00
|
|
|
}
|
2007-10-04 22:41:19 +00:00
|
|
|
} break;
|
|
|
|
|
2007-10-08 21:41:41 +00:00
|
|
|
case ldiv_:
|
|
|
|
if (BytesPerWord == 8) {
|
|
|
|
popLong(rcx);
|
2007-10-08 23:13:55 +00:00
|
|
|
popLong(rax);
|
|
|
|
cqo();
|
2007-10-08 21:41:41 +00:00
|
|
|
Assembler::idiv(rcx);
|
|
|
|
pushLong(rax);
|
|
|
|
} else {
|
2007-10-13 21:48:40 +00:00
|
|
|
directCall(reinterpret_cast<void*>(divideLong));
|
2007-10-10 17:26:28 +00:00
|
|
|
popLong();
|
2007-10-08 21:41:41 +00:00
|
|
|
mov(rax, rsp, 0);
|
|
|
|
mov(rdx, rsp, 4);
|
|
|
|
}
|
|
|
|
break;
|
2007-10-04 22:41:19 +00:00
|
|
|
|
2007-10-08 21:41:41 +00:00
|
|
|
case lload:
|
2007-10-10 17:26:28 +00:00
|
|
|
loadLong(codeBody(t, code, ip++));
|
2007-10-08 21:41:41 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case lload_0:
|
2007-10-10 17:26:28 +00:00
|
|
|
loadLong(0);
|
2007-10-08 21:41:41 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case lload_1:
|
2007-10-10 17:26:28 +00:00
|
|
|
loadLong(1);
|
2007-10-08 21:41:41 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case lload_2:
|
2007-10-10 17:26:28 +00:00
|
|
|
loadLong(2);
|
2007-10-08 21:41:41 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case lload_3:
|
2007-10-10 17:26:28 +00:00
|
|
|
loadLong(3);
|
2007-10-08 21:41:41 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case lmul:
|
|
|
|
if (BytesPerWord == 8) {
|
|
|
|
popLong(rax);
|
|
|
|
popLong(rcx);
|
|
|
|
Assembler::imul(rcx);
|
|
|
|
pushLong(rax);
|
|
|
|
} else {
|
|
|
|
mov(rsp, 4, rcx);
|
|
|
|
Assembler::imul(rsp, 8, rcx);
|
|
|
|
mov(rsp, 12, rax);
|
|
|
|
Assembler::imul(rsp, 0, rax);
|
|
|
|
add(rax, rcx);
|
|
|
|
mov(rsp, 8, rax);
|
|
|
|
mul(rsp, 0);
|
|
|
|
add(rcx, rdx);
|
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
popLong();
|
2007-10-08 21:41:41 +00:00
|
|
|
mov(rax, rsp, 0);
|
|
|
|
mov(rdx, rsp, 4);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case lneg:
|
|
|
|
if (BytesPerWord == 8) {
|
|
|
|
neg(rsp, 8);
|
|
|
|
} else {
|
|
|
|
mov(rsp, 0, rax);
|
|
|
|
mov(rsp, 4, rdx);
|
|
|
|
neg(rax);
|
|
|
|
adc(0, rdx);
|
|
|
|
neg(rdx);
|
|
|
|
|
|
|
|
mov(rax, rsp, 0);
|
|
|
|
mov(rdx, rsp, 4);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case lrem:
|
|
|
|
if (BytesPerWord == 8) {
|
|
|
|
popLong(rcx);
|
2007-10-09 17:15:40 +00:00
|
|
|
popLong(rax);
|
2007-10-08 23:13:55 +00:00
|
|
|
cqo();
|
2007-10-08 21:41:41 +00:00
|
|
|
Assembler::idiv(rcx);
|
|
|
|
pushLong(rdx);
|
|
|
|
} else {
|
2007-10-13 21:48:40 +00:00
|
|
|
directCall(reinterpret_cast<void*>(moduloLong));
|
2007-10-10 17:26:28 +00:00
|
|
|
popLong();
|
2007-10-08 21:41:41 +00:00
|
|
|
mov(rax, rsp, 0);
|
|
|
|
mov(rdx, rsp, 4);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case lstore:
|
2007-10-10 17:26:28 +00:00
|
|
|
storeLong(codeBody(t, code, ip++));
|
2007-10-08 21:41:41 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case lstore_0:
|
2007-10-10 17:26:28 +00:00
|
|
|
storeLong(0);
|
2007-10-08 21:41:41 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case lstore_1:
|
2007-10-10 17:26:28 +00:00
|
|
|
storeLong(1);
|
2007-10-08 21:41:41 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case lstore_2:
|
2007-10-10 17:26:28 +00:00
|
|
|
storeLong(2);
|
2007-10-08 21:41:41 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case lstore_3:
|
2007-10-10 17:26:28 +00:00
|
|
|
storeLong(3);
|
2007-10-08 21:41:41 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case lsub:
|
|
|
|
if (BytesPerWord == 8) {
|
2007-10-10 17:26:28 +00:00
|
|
|
popLong(rax);
|
2007-10-08 21:41:41 +00:00
|
|
|
sub(rax, rsp, BytesPerWord);
|
|
|
|
} else {
|
|
|
|
popLong(rax, rdx);
|
|
|
|
sub(rax, rsp, 0);
|
|
|
|
sbb(rdx, rsp, BytesPerWord);
|
|
|
|
}
|
|
|
|
break;
|
2007-10-04 22:41:19 +00:00
|
|
|
|
2007-09-27 22:20:54 +00:00
|
|
|
case new_: {
|
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
|
|
|
|
|
|
|
object class_ = resolveClass(t, codePool(t, code), index - 1);
|
2007-10-04 00:41:54 +00:00
|
|
|
if (UNLIKELY(t->exception)) return 0;
|
2007-09-27 22:20:54 +00:00
|
|
|
PROTECT(t, class_);
|
|
|
|
|
|
|
|
initClass(t, class_);
|
2007-10-04 00:41:54 +00:00
|
|
|
if (UNLIKELY(t->exception)) return 0;
|
2007-09-28 14:45:26 +00:00
|
|
|
|
2007-09-27 22:20:54 +00:00
|
|
|
if (classVmFlags(t, class_) & WeakReferenceFlag) {
|
2007-10-13 21:48:40 +00:00
|
|
|
compileCall(false, reinterpret_cast<void*>(makeNewWeakReference),
|
|
|
|
class_);
|
2007-09-27 22:20:54 +00:00
|
|
|
} else {
|
2007-10-13 21:48:40 +00:00
|
|
|
compileCall(false, reinterpret_cast<void*>(makeNew), class_);
|
2007-09-27 22:20:54 +00:00
|
|
|
}
|
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
pushObject(rax);
|
2007-09-27 22:20:54 +00:00
|
|
|
} break;
|
|
|
|
|
2007-09-30 02:48:27 +00:00
|
|
|
case newarray: {
|
|
|
|
uint8_t type = codeBody(t, code, ip++);
|
|
|
|
|
|
|
|
Label nonnegative(this);
|
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
popInt(rax);
|
2007-09-30 02:48:27 +00:00
|
|
|
cmp(0, rax);
|
|
|
|
jge(nonnegative);
|
|
|
|
|
2007-10-13 21:48:40 +00:00
|
|
|
compileThrowNew(Machine::NegativeArraySizeExceptionType);
|
2007-09-30 02:48:27 +00:00
|
|
|
|
|
|
|
nonnegative.mark();
|
|
|
|
|
|
|
|
object (*constructor)(Thread*, uintptr_t, bool);
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2007-10-13 21:48:40 +00:00
|
|
|
compileCall(false, reinterpret_cast<void*>(makeBlankArray),
|
|
|
|
reinterpret_cast<uintptr_t>(constructor), rax);
|
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
pushObject(rax);
|
2007-09-30 02:48:27 +00:00
|
|
|
} break;
|
|
|
|
|
2007-09-26 23:23:03 +00:00
|
|
|
case pop_: {
|
|
|
|
add(BytesPerWord, rsp);
|
2007-10-13 21:48:40 +00:00
|
|
|
stackMapper.popped(1);
|
2007-09-26 23:23:03 +00:00
|
|
|
} break;
|
|
|
|
|
2007-09-29 20:24:14 +00:00
|
|
|
case putfield: {
|
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
|
|
|
|
|
|
|
object field = resolveField(t, codePool(t, code), index - 1);
|
2007-10-04 00:41:54 +00:00
|
|
|
if (UNLIKELY(t->exception)) return 0;
|
2007-09-29 20:24:14 +00:00
|
|
|
|
|
|
|
switch (fieldCode(t, field)) {
|
|
|
|
case ByteField:
|
|
|
|
case BooleanField:
|
|
|
|
case CharField:
|
|
|
|
case ShortField:
|
|
|
|
case FloatField:
|
|
|
|
case IntField: {
|
2007-10-10 17:26:28 +00:00
|
|
|
popInt(rcx);
|
|
|
|
popObject(rax);
|
|
|
|
|
2007-09-29 20:24:14 +00:00
|
|
|
switch (fieldCode(t, field)) {
|
|
|
|
case ByteField:
|
|
|
|
case BooleanField:
|
|
|
|
mov1(rcx, rax, fieldOffset(t, field));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CharField:
|
|
|
|
case ShortField:
|
|
|
|
mov2(rcx, rax, fieldOffset(t, field));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FloatField:
|
|
|
|
case IntField:
|
|
|
|
mov4(rcx, rax, fieldOffset(t, field));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case DoubleField:
|
|
|
|
case LongField: {
|
2007-10-10 17:26:28 +00:00
|
|
|
if (BytesPerWord == 8) {
|
|
|
|
popLong(rcx);
|
|
|
|
popObject(rax);
|
|
|
|
mov(rcx, rax, fieldOffset(t, field));
|
|
|
|
} else {
|
|
|
|
popLong(rcx, rbx);
|
|
|
|
popObject(rax);
|
|
|
|
mov(rcx, rax, fieldOffset(t, field));
|
|
|
|
mov(rbx, rax, fieldOffset(t, field) + 4);
|
|
|
|
}
|
2007-09-29 20:24:14 +00:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case ObjectField: {
|
2007-10-13 21:48:40 +00:00
|
|
|
if (BytesPerWord == 8) {
|
|
|
|
popObject(rdx);
|
|
|
|
popObject(rsi);
|
|
|
|
add(fieldOffset(t, field), rsi);
|
|
|
|
mov(rbp, FrameThread, rdi);
|
|
|
|
} else {
|
|
|
|
popObject(rdx);
|
|
|
|
popObject(rsi);
|
|
|
|
add(fieldOffset(t, field), rsi);
|
|
|
|
push(rdx);
|
|
|
|
push(rsi);
|
|
|
|
push(rbp, FrameThread);
|
|
|
|
}
|
|
|
|
|
|
|
|
directCall(reinterpret_cast<void*>(set));
|
|
|
|
|
|
|
|
if (BytesPerWord == 4) {
|
|
|
|
add(BytesPerWord * 3, rsp);
|
|
|
|
}
|
2007-09-29 20:24:14 +00:00
|
|
|
} break;
|
|
|
|
|
|
|
|
default: abort(t);
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
2007-09-28 14:45:26 +00:00
|
|
|
case putstatic: {
|
|
|
|
uint16_t index = codeReadInt16(t, code, ip);
|
|
|
|
|
|
|
|
object field = resolveField(t, codePool(t, code), index - 1);
|
2007-10-04 00:41:54 +00:00
|
|
|
if (UNLIKELY(t->exception)) return 0;
|
2007-09-28 14:45:26 +00:00
|
|
|
|
|
|
|
initClass(t, fieldClass(t, field));
|
2007-10-04 00:41:54 +00:00
|
|
|
if (UNLIKELY(t->exception)) return 0;
|
2007-09-28 14:45:26 +00:00
|
|
|
|
|
|
|
object table = classStaticTable(t, fieldClass(t, field));
|
2007-10-10 17:26:28 +00:00
|
|
|
unsigned offset = (fieldOffset(t, field) * BytesPerWord) + ArrayBody;
|
2007-09-28 14:45:26 +00:00
|
|
|
|
|
|
|
switch (fieldCode(t, field)) {
|
|
|
|
case ByteField:
|
|
|
|
case BooleanField:
|
|
|
|
case CharField:
|
|
|
|
case ShortField:
|
|
|
|
case FloatField:
|
|
|
|
case IntField: {
|
2007-10-13 21:48:40 +00:00
|
|
|
object intType = arrayBody(t, t->m->types, Machine::IntType);
|
|
|
|
|
|
|
|
if (BytesPerWord == 8) {
|
|
|
|
mov(poolRegister(), poolReference(intType), rsi);
|
|
|
|
mov(rbp, FrameThread, rdi);
|
|
|
|
} else {
|
|
|
|
push(poolRegister(), poolReference(intType));
|
|
|
|
push(rbp, FrameThread);
|
|
|
|
}
|
|
|
|
|
|
|
|
indirectCall(reinterpret_cast<void*>(makeNew));
|
|
|
|
|
|
|
|
if (BytesPerWord == 4) {
|
|
|
|
add(BytesPerWord * 2, rsp);
|
|
|
|
}
|
2007-09-28 14:45:26 +00:00
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
popInt(rax, IntValue);
|
|
|
|
|
2007-10-13 21:48:40 +00:00
|
|
|
if (BytesPerWord == 8) {
|
|
|
|
mov(rax, rdx);
|
|
|
|
mov(poolRegister(), poolReference(table), rsi);
|
|
|
|
add(offset, rsi);
|
|
|
|
mov(rbp, FrameThread, rdi);
|
|
|
|
} else {
|
|
|
|
push(rax);
|
|
|
|
mov(poolRegister(), poolReference(table), rsi);
|
|
|
|
add(offset, rsi);
|
|
|
|
push(rsi);
|
|
|
|
push(rbp, FrameThread);
|
|
|
|
}
|
|
|
|
|
|
|
|
directCall(reinterpret_cast<void*>(set));
|
|
|
|
|
|
|
|
if (BytesPerWord == 4) {
|
|
|
|
add(BytesPerWord * 3, rsp);
|
|
|
|
}
|
2007-09-28 14:45:26 +00:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case DoubleField:
|
|
|
|
case LongField: {
|
2007-10-13 21:48:40 +00:00
|
|
|
object longType = arrayBody(t, t->m->types, Machine::LongType);
|
|
|
|
|
|
|
|
if (BytesPerWord == 8) {
|
|
|
|
mov(poolRegister(), poolReference(longType), rsi);
|
|
|
|
mov(rbp, FrameThread, rdi);
|
|
|
|
} else {
|
|
|
|
push(poolRegister(), poolReference(longType));
|
|
|
|
push(rbp, FrameThread);
|
|
|
|
}
|
|
|
|
|
|
|
|
indirectCall(reinterpret_cast<void*>(makeNew));
|
2007-09-28 14:45:26 +00:00
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
if (BytesPerWord == 8) {
|
|
|
|
popLong(rax, LongValue);
|
|
|
|
} else {
|
2007-10-13 21:48:40 +00:00
|
|
|
add(BytesPerWord * 2, rsp);
|
2007-10-10 17:26:28 +00:00
|
|
|
popLong(rax, LongValue,
|
|
|
|
rax, LongValue + 4);
|
|
|
|
}
|
|
|
|
|
2007-10-13 21:48:40 +00:00
|
|
|
if (BytesPerWord == 8) {
|
|
|
|
mov(rax, rdx);
|
|
|
|
mov(poolRegister(), poolReference(table), rsi);
|
|
|
|
add(offset, rsi);
|
|
|
|
mov(rbp, FrameThread, rdi);
|
|
|
|
} else {
|
|
|
|
push(rax);
|
|
|
|
mov(poolRegister(), poolReference(table), rsi);
|
|
|
|
add(offset, rsi);
|
|
|
|
push(rsi);
|
|
|
|
push(rbp, FrameThread);
|
|
|
|
}
|
|
|
|
|
|
|
|
directCall(reinterpret_cast<void*>(set));
|
|
|
|
|
|
|
|
if (BytesPerWord == 4) {
|
|
|
|
add(BytesPerWord * 3, rsp);
|
|
|
|
}
|
2007-09-28 14:45:26 +00:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case ObjectField:
|
2007-10-13 21:48:40 +00:00
|
|
|
if (BytesPerWord == 8) {
|
|
|
|
popObject(rdx);
|
|
|
|
mov(poolRegister(), poolReference(table), rsi);
|
|
|
|
add(offset, rsi);
|
|
|
|
mov(rbp, FrameThread, rdi);
|
|
|
|
} else {
|
|
|
|
mov(poolRegister(), poolReference(table), rsi);
|
|
|
|
add(offset, rsi);
|
|
|
|
push(rsi);
|
|
|
|
push(rbp, FrameThread);
|
|
|
|
}
|
|
|
|
|
|
|
|
directCall(reinterpret_cast<void*>(set));
|
|
|
|
|
|
|
|
if (BytesPerWord == 4) {
|
|
|
|
add(BytesPerWord * 3, rsp);
|
|
|
|
stackMapper.poppedObject();
|
|
|
|
}
|
2007-09-28 14:45:26 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default: abort(t);
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
2007-09-24 01:39:03 +00:00
|
|
|
case return_:
|
2007-09-26 23:23:03 +00:00
|
|
|
mov(rbp, rsp);
|
|
|
|
pop(rbp);
|
2007-09-24 01:39:03 +00:00
|
|
|
ret();
|
2007-10-12 00:30:46 +00:00
|
|
|
stackMapper.exited();
|
2007-09-24 01:39:03 +00:00
|
|
|
break;
|
|
|
|
|
2007-09-30 02:48:27 +00:00
|
|
|
case sipush: {
|
2007-10-10 17:26:28 +00:00
|
|
|
pushInt(static_cast<int16_t>(codeReadInt16(t, code, ip)));
|
2007-09-30 02:48:27 +00:00
|
|
|
} break;
|
|
|
|
|
2007-09-24 01:39:03 +00:00
|
|
|
default:
|
|
|
|
abort(t);
|
|
|
|
}
|
|
|
|
}
|
2007-09-28 23:41:03 +00:00
|
|
|
|
|
|
|
resolveJumps();
|
2007-10-03 00:22:48 +00:00
|
|
|
buildExceptionHandlerTable(code);
|
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
return finish();
|
2007-09-28 23:41:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void resolveJumps() {
|
|
|
|
for (unsigned i = 0; i < jumps.length(); i += 8) {
|
|
|
|
uint32_t ip = jumps.get4(i);
|
|
|
|
uint32_t offset = jumps.get4(i + 4);
|
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
code.set4(offset, machineIPs[ip] - (offset + 4));
|
2007-10-03 00:22:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void buildExceptionHandlerTable(object code) {
|
|
|
|
PROTECT(t, code);
|
|
|
|
|
|
|
|
object eht = codeExceptionHandlerTable(t, code);
|
2007-10-04 00:41:54 +00:00
|
|
|
if (eht) {
|
|
|
|
PROTECT(t, eht);
|
2007-10-03 00:22:48 +00:00
|
|
|
|
2007-10-04 00:41:54 +00:00
|
|
|
for (unsigned i = 0; i < exceptionHandlerTableLength(t, eht); ++i) {
|
|
|
|
ExceptionHandler* eh = exceptionHandlerTableBody(t, eht, i);
|
2007-10-03 00:22:48 +00:00
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
nativeExceptionHandlerStart(exceptionHandlers + i)
|
|
|
|
= machineIPs[exceptionHandlerStart(eh)];
|
2007-10-03 00:22:48 +00:00
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
nativeExceptionHandlerEnd(exceptionHandlers + i)
|
|
|
|
= machineIPs[exceptionHandlerEnd(eh)];
|
2007-10-04 00:41:54 +00:00
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
nativeExceptionHandlerIp(exceptionHandlers + i)
|
|
|
|
= machineIPs[exceptionHandlerIp(eh)];
|
2007-10-04 00:41:54 +00:00
|
|
|
|
|
|
|
unsigned ct = exceptionHandlerCatchType(eh);
|
|
|
|
object catchType;
|
|
|
|
if (ct) {
|
|
|
|
catchType = resolveClass
|
|
|
|
(t, codePool(t, code), exceptionHandlerCatchType(eh) - 1);
|
|
|
|
} else {
|
|
|
|
catchType = 0;
|
|
|
|
}
|
2007-10-03 00:22:48 +00:00
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
nativeExceptionHandlerCatchType(exceptionHandlers + i)
|
|
|
|
= (catchType ? (poolReference(catchType) / BytesPerWord) - 1 : 0);
|
2007-10-04 00:41:54 +00:00
|
|
|
}
|
2007-09-28 23:41:03 +00:00
|
|
|
}
|
2007-09-24 01:39:03 +00:00
|
|
|
}
|
2007-09-25 23:53:11 +00:00
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
Compiled* finish() {
|
2007-10-11 22:43:03 +00:00
|
|
|
stackMapper.finish();
|
2007-10-10 22:39:40 +00:00
|
|
|
return makeCompiled(t, method, &code, lineNumbers, exceptionHandlers,
|
|
|
|
&stackMapper);
|
2007-10-03 00:22:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
object makePool() {
|
|
|
|
if (pool.length()) {
|
|
|
|
object array = makeArray(t, pool.length() / BytesPerWord, false);
|
2007-10-04 00:41:54 +00:00
|
|
|
pool.copyTo(&arrayBody(t, array, 0));
|
2007-10-03 00:22:48 +00:00
|
|
|
return array;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Register poolRegister() {
|
|
|
|
return rdi;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t poolReference(object o) {
|
|
|
|
if (poolRegisterClobbered) {
|
|
|
|
mov(rbp, FrameMethod, rdi);
|
|
|
|
mov(rdi, MethodCode, rdi);
|
2007-10-09 19:30:01 +00:00
|
|
|
//poolRegisterClobbered = false;
|
2007-10-03 00:22:48 +00:00
|
|
|
}
|
2007-10-04 00:41:54 +00:00
|
|
|
pool.appendAddress(reinterpret_cast<uintptr_t>(o));
|
2007-10-03 00:22:48 +00:00
|
|
|
return pool.length() + BytesPerWord;
|
|
|
|
}
|
|
|
|
|
2007-10-10 17:26:28 +00:00
|
|
|
object method;
|
2007-10-10 21:34:04 +00:00
|
|
|
StackMapper stackMapper;
|
2007-10-03 00:22:48 +00:00
|
|
|
bool poolRegisterClobbered;
|
2007-10-10 17:26:28 +00:00
|
|
|
uint32_t* machineIPs;
|
|
|
|
NativeLineNumber* lineNumbers;
|
|
|
|
NativeExceptionHandler* exceptionHandlers;
|
2007-10-03 00:22:48 +00:00
|
|
|
Buffer pool;
|
2007-10-12 17:56:43 +00:00
|
|
|
|
|
|
|
class MyProtector: public Thread::Protector {
|
|
|
|
public:
|
|
|
|
MyProtector(JavaCompiler* c): Protector(c->t), c(c) { }
|
|
|
|
|
|
|
|
virtual void visit(Heap::Visitor* v) {
|
|
|
|
v->visit(&(c->method));
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < c->pool.length(); i += BytesPerWord) {
|
|
|
|
v->visit(reinterpret_cast<object*>(&(c->pool.getAddress(i))));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
JavaCompiler* c;
|
|
|
|
} protector;
|
2007-09-24 01:39:03 +00:00
|
|
|
};
|
|
|
|
|
2007-09-25 23:53:11 +00:00
|
|
|
void
|
2007-09-26 23:23:03 +00:00
|
|
|
compileMethod2(MyThread* t, object method)
|
2007-09-25 23:53:11 +00:00
|
|
|
{
|
2007-10-04 00:41:54 +00:00
|
|
|
if (reinterpret_cast<Compiled*>(methodCompiled(t, method))
|
|
|
|
== t->m->processor->methodStub(t))
|
|
|
|
{
|
2007-09-25 23:53:11 +00:00
|
|
|
PROTECT(t, method);
|
|
|
|
|
|
|
|
ACQUIRE(t, t->m->classLock);
|
|
|
|
|
2007-10-04 00:41:54 +00:00
|
|
|
if (reinterpret_cast<Compiled*>(methodCompiled(t, method))
|
|
|
|
== t->m->processor->methodStub(t))
|
|
|
|
{
|
2007-09-30 15:52:21 +00:00
|
|
|
if (Verbose) {
|
|
|
|
fprintf(stderr, "compiling %s.%s\n",
|
|
|
|
&byteArrayBody(t, className(t, methodClass(t, method)), 0),
|
|
|
|
&byteArrayBody(t, methodName(t, method), 0));
|
|
|
|
}
|
2007-09-29 20:24:14 +00:00
|
|
|
|
2007-10-12 00:30:46 +00:00
|
|
|
if (strcmp(reinterpret_cast<const char*>
|
|
|
|
(&byteArrayBody(t, methodName(t, method), 0)),
|
|
|
|
"charAt") == 0)
|
|
|
|
{
|
|
|
|
noop();
|
|
|
|
}
|
|
|
|
|
2007-10-10 22:39:40 +00:00
|
|
|
JavaCompiler c(t, method);
|
2007-10-10 17:26:28 +00:00
|
|
|
Compiled* code = c.compile();
|
2007-09-25 23:53:11 +00:00
|
|
|
|
2007-09-30 15:52:21 +00:00
|
|
|
if (Verbose) {
|
|
|
|
fprintf(stderr, "compiled %s.%s from %p to %p\n",
|
|
|
|
&byteArrayBody(t, className(t, methodClass(t, method)), 0),
|
|
|
|
&byteArrayBody(t, methodName(t, method), 0),
|
2007-10-04 00:41:54 +00:00
|
|
|
compiledCode(code),
|
|
|
|
compiledCode(code) + compiledCodeLength(code));
|
2007-09-30 15:52:21 +00:00
|
|
|
}
|
2007-09-29 20:24:14 +00:00
|
|
|
|
2007-10-03 00:22:48 +00:00
|
|
|
object pool = c.makePool();
|
|
|
|
set(t, methodCode(t, method), pool);
|
2007-10-12 22:06:33 +00:00
|
|
|
|
|
|
|
methodCompiled(t, method) = reinterpret_cast<uint64_t>(code);
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-09-26 23:23:03 +00:00
|
|
|
void
|
|
|
|
updateCaller(MyThread* t, object method)
|
|
|
|
{
|
|
|
|
uintptr_t stub = reinterpret_cast<uintptr_t>
|
2007-10-04 00:41:54 +00:00
|
|
|
(compiledCode(static_cast<Compiled*>(t->m->processor->methodStub(t))));
|
2007-09-26 23:23:03 +00:00
|
|
|
|
|
|
|
Assembler a(t->m->system);
|
2007-09-28 23:41:03 +00:00
|
|
|
a.mov(stub, rax);
|
2007-09-26 23:23:03 +00:00
|
|
|
unsigned offset = a.code.length() - BytesPerWord;
|
|
|
|
|
2007-09-28 23:41:03 +00:00
|
|
|
a.call(rax);
|
2007-09-26 23:23:03 +00:00
|
|
|
|
2007-10-04 22:41:19 +00:00
|
|
|
uint8_t* caller = static_cast<uint8_t*>(frameAddress(t->frame))
|
|
|
|
- a.code.length();
|
2007-09-28 23:41:03 +00:00
|
|
|
if (memcmp(a.code.data, caller, a.code.length()) == 0) {
|
2007-09-26 23:23:03 +00:00
|
|
|
// it's a direct call - update caller to point to new code
|
|
|
|
|
|
|
|
// address must be aligned on a word boundary for this write to
|
|
|
|
// be atomic
|
|
|
|
assert(t, reinterpret_cast<uintptr_t>(caller + offset)
|
|
|
|
% BytesPerWord == 0);
|
|
|
|
|
|
|
|
*reinterpret_cast<void**>(caller + offset)
|
2007-10-04 00:41:54 +00:00
|
|
|
= compiledCode(reinterpret_cast<Compiled*>(methodCompiled(t, method)));
|
2007-09-26 23:23:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
compileMethod(MyThread* t, object method)
|
|
|
|
{
|
2007-10-13 21:48:40 +00:00
|
|
|
{ PROTECT(t, method);
|
|
|
|
compileMethod2(t, method);
|
|
|
|
|
|
|
|
if (LIKELY(t->exception == 0)) {
|
|
|
|
if (not methodVirtual(t, method)) {
|
|
|
|
updateCaller(t, method);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2007-09-26 23:23:03 +00:00
|
|
|
}
|
2007-10-13 21:48:40 +00:00
|
|
|
|
|
|
|
unwind(t);
|
2007-09-26 23:23:03 +00:00
|
|
|
}
|
|
|
|
|
2007-09-25 23:53:11 +00:00
|
|
|
class ArgumentList {
|
|
|
|
public:
|
|
|
|
ArgumentList(Thread* t, uintptr_t* array, bool* objectMask, object this_,
|
|
|
|
const char* spec, bool indirectObjects, va_list arguments):
|
|
|
|
t(static_cast<MyThread*>(t)),
|
|
|
|
next(this->t->argumentList),
|
|
|
|
array(array),
|
|
|
|
objectMask(objectMask),
|
2007-10-12 17:56:43 +00:00
|
|
|
position(0),
|
|
|
|
protector(this)
|
2007-09-25 23:53:11 +00:00
|
|
|
{
|
|
|
|
this->t->argumentList = this;
|
|
|
|
|
|
|
|
addInt(reinterpret_cast<uintptr_t>(t));
|
|
|
|
addObject(0); // reserve space for method
|
|
|
|
addInt(reinterpret_cast<uintptr_t>(this->t->frame));
|
|
|
|
|
|
|
|
if (this_) {
|
|
|
|
addObject(this_);
|
|
|
|
}
|
|
|
|
|
2007-10-12 17:56:43 +00:00
|
|
|
for (MethodSpecIterator it(t, spec); it.hasNext();) {
|
|
|
|
switch (*it.next()) {
|
2007-09-25 23:53:11 +00:00
|
|
|
case 'L':
|
|
|
|
case '[':
|
|
|
|
if (indirectObjects) {
|
|
|
|
object* v = va_arg(arguments, object*);
|
|
|
|
addObject(v ? *v : 0);
|
|
|
|
} else {
|
|
|
|
addObject(va_arg(arguments, object));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'J':
|
|
|
|
case 'D':
|
|
|
|
addLong(va_arg(arguments, uint64_t));
|
|
|
|
break;
|
2007-10-12 17:56:43 +00:00
|
|
|
|
2007-09-25 23:53:11 +00:00
|
|
|
default:
|
|
|
|
addInt(va_arg(arguments, uint32_t));
|
2007-10-12 17:56:43 +00:00
|
|
|
break;
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
2007-10-12 17:56:43 +00:00
|
|
|
}
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ArgumentList(Thread* t, uintptr_t* array, bool* objectMask, object this_,
|
|
|
|
const char* spec, object arguments):
|
|
|
|
t(static_cast<MyThread*>(t)),
|
|
|
|
next(this->t->argumentList),
|
|
|
|
array(array),
|
|
|
|
objectMask(objectMask),
|
2007-10-12 17:56:43 +00:00
|
|
|
position(0),
|
|
|
|
protector(this)
|
2007-09-25 23:53:11 +00:00
|
|
|
{
|
|
|
|
this->t->argumentList = this;
|
|
|
|
|
|
|
|
addInt(0); // reserve space for trace pointer
|
|
|
|
addObject(0); // reserve space for method pointer
|
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
~ArgumentList() {
|
|
|
|
t->argumentList = next;
|
|
|
|
}
|
|
|
|
|
|
|
|
void addObject(object v) {
|
|
|
|
array[position] = reinterpret_cast<uintptr_t>(v);
|
|
|
|
objectMask[position] = true;
|
|
|
|
++ position;
|
|
|
|
}
|
|
|
|
|
2007-10-12 22:06:33 +00:00
|
|
|
void addInt(uintptr_t v) {
|
2007-09-25 23:53:11 +00:00
|
|
|
array[position] = v;
|
|
|
|
objectMask[position] = false;
|
|
|
|
++ position;
|
|
|
|
}
|
|
|
|
|
|
|
|
void addLong(uint64_t v) {
|
|
|
|
memcpy(array + position, &v, 8);
|
|
|
|
objectMask[position] = false;
|
|
|
|
objectMask[position] = false;
|
|
|
|
position += 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
MyThread* t;
|
|
|
|
ArgumentList* next;
|
|
|
|
uintptr_t* array;
|
|
|
|
bool* objectMask;
|
|
|
|
unsigned position;
|
2007-10-12 17:56:43 +00:00
|
|
|
|
|
|
|
class MyProtector: public Thread::Protector {
|
|
|
|
public:
|
|
|
|
MyProtector(ArgumentList* list): Protector(list->t), list(list) { }
|
|
|
|
|
|
|
|
virtual void visit(Heap::Visitor* v) {
|
|
|
|
for (unsigned i = 0; i < list->position; ++i) {
|
|
|
|
if (list->objectMask[i]) {
|
|
|
|
v->visit(reinterpret_cast<object*>(list->array + i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
arguments->array[1] = reinterpret_cast<uintptr_t>(method);
|
|
|
|
|
2007-09-26 23:23:03 +00:00
|
|
|
unsigned returnCode = methodReturnCode(t, method);
|
2007-09-25 23:53:11 +00:00
|
|
|
unsigned returnType = fieldType(t, returnCode);
|
|
|
|
|
2007-09-30 02:48:27 +00:00
|
|
|
void* frame = t->frame;
|
2007-09-30 03:33:38 +00:00
|
|
|
Reference* reference = t->reference;
|
2007-09-30 02:48:27 +00:00
|
|
|
|
2007-10-04 00:41:54 +00:00
|
|
|
Compiled* code = reinterpret_cast<Compiled*>(methodCompiled(t, method));
|
2007-09-26 23:23:03 +00:00
|
|
|
uint64_t result = vmInvoke
|
2007-10-04 00:41:54 +00:00
|
|
|
(compiledCode(code), arguments->array, arguments->position * BytesPerWord,
|
|
|
|
returnType);
|
2007-09-25 23:53:11 +00:00
|
|
|
|
2007-09-30 03:33:38 +00:00
|
|
|
while (t->reference != reference) {
|
|
|
|
dispose(t, t->reference);
|
|
|
|
}
|
2007-09-30 02:48:27 +00:00
|
|
|
t->frame = frame;
|
|
|
|
|
2007-09-25 23:53:11 +00:00
|
|
|
object r;
|
|
|
|
switch (returnCode) {
|
|
|
|
case ByteField:
|
|
|
|
case BooleanField:
|
|
|
|
case CharField:
|
|
|
|
case ShortField:
|
|
|
|
case FloatField:
|
|
|
|
case IntField:
|
|
|
|
r = makeInt(t, result);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LongField:
|
|
|
|
case DoubleField:
|
|
|
|
r = makeLong(t, result);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ObjectField:
|
|
|
|
r = (result == 0 ? 0 :
|
|
|
|
*reinterpret_cast<object*>(static_cast<uintptr_t>(result)));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VoidField:
|
|
|
|
r = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
abort(t);
|
|
|
|
};
|
2007-09-24 01:39:03 +00:00
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2007-09-25 23:53:11 +00:00
|
|
|
class MyProcessor: public Processor {
|
2007-09-24 01:39:03 +00:00
|
|
|
public:
|
2007-09-25 23:53:11 +00:00
|
|
|
MyProcessor(System* s):
|
|
|
|
s(s),
|
2007-10-01 15:19:15 +00:00
|
|
|
methodStub_(0),
|
|
|
|
nativeInvoker_(0)
|
2007-09-24 01:39:03 +00:00
|
|
|
{ }
|
|
|
|
|
2007-09-25 23:53:11 +00:00
|
|
|
virtual Thread*
|
|
|
|
makeThread(Machine* m, object javaThread, Thread* parent)
|
|
|
|
{
|
|
|
|
return new (s->allocate(sizeof(MyThread))) MyThread(m, javaThread, parent);
|
|
|
|
}
|
|
|
|
|
2007-10-03 00:22:48 +00:00
|
|
|
virtual void*
|
2007-09-25 23:53:11 +00:00
|
|
|
methodStub(Thread* t)
|
|
|
|
{
|
2007-10-01 15:19:15 +00:00
|
|
|
if (methodStub_ == 0) {
|
2007-10-10 22:39:40 +00:00
|
|
|
Compiler c(static_cast<MyThread*>(t));
|
2007-10-03 00:22:48 +00:00
|
|
|
methodStub_ = c.compileStub();
|
2007-10-12 22:06:33 +00:00
|
|
|
fprintf(stderr, "compiled method stub from %p to %p\n",
|
|
|
|
compiledCode(methodStub_),
|
|
|
|
compiledCode(methodStub_) + compiledCodeLength(methodStub_));
|
2007-10-01 15:19:15 +00:00
|
|
|
}
|
|
|
|
return methodStub_;
|
|
|
|
}
|
|
|
|
|
2007-10-03 00:22:48 +00:00
|
|
|
virtual void*
|
2007-10-01 15:19:15 +00:00
|
|
|
nativeInvoker(Thread* t)
|
|
|
|
{
|
|
|
|
if (nativeInvoker_ == 0) {
|
2007-10-10 22:39:40 +00:00
|
|
|
Compiler c(static_cast<MyThread*>(t));
|
2007-10-03 00:22:48 +00:00
|
|
|
nativeInvoker_ = c.compileNativeInvoker();
|
2007-10-12 22:06:33 +00:00
|
|
|
fprintf(stderr, "compiled native invoker from %p to %p\n",
|
|
|
|
compiledCode(nativeInvoker_),
|
|
|
|
compiledCode(nativeInvoker_)
|
|
|
|
+ compiledCodeLength(nativeInvoker_));
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
2007-10-01 15:19:15 +00:00
|
|
|
return nativeInvoker_;
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
2007-10-04 03:19:39 +00:00
|
|
|
Compiled*
|
|
|
|
caller(Thread* t)
|
|
|
|
{
|
|
|
|
if (caller_ == 0) {
|
2007-10-10 22:39:40 +00:00
|
|
|
Compiler c(static_cast<MyThread*>(t));
|
2007-10-04 03:19:39 +00:00
|
|
|
caller_ = c.compileCaller();
|
2007-10-12 22:06:33 +00:00
|
|
|
fprintf(stderr, "compiled caller from %p to %p\n",
|
|
|
|
compiledCode(caller_),
|
|
|
|
compiledCode(caller_) + compiledCodeLength(caller_));
|
2007-10-04 03:19:39 +00:00
|
|
|
}
|
|
|
|
return caller_;
|
|
|
|
}
|
|
|
|
|
2007-09-26 23:23:03 +00:00
|
|
|
virtual unsigned
|
2007-10-12 17:56:43 +00:00
|
|
|
parameterFootprint(vm::Thread* t, const char* s, bool static_)
|
2007-09-26 23:23:03 +00:00
|
|
|
{
|
|
|
|
unsigned footprint = 0;
|
2007-10-12 17:56:43 +00:00
|
|
|
for (MethodSpecIterator it(t, s); it.hasNext();) {
|
|
|
|
switch (*it.next()) {
|
2007-09-26 23:23:03 +00:00
|
|
|
case 'J':
|
|
|
|
case 'D':
|
2007-10-12 17:56:43 +00:00
|
|
|
footprint += 2;
|
2007-09-26 23:23:03 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2007-10-12 17:56:43 +00:00
|
|
|
++ footprint;
|
|
|
|
break;
|
2007-09-26 23:23:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (not static_) {
|
|
|
|
++ footprint;
|
|
|
|
}
|
|
|
|
return footprint;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void
|
|
|
|
initClass(Thread* t, object c)
|
|
|
|
{
|
|
|
|
PROTECT(t, c);
|
|
|
|
|
|
|
|
ACQUIRE(t, t->m->classLock);
|
|
|
|
if (classVmFlags(t, c) & NeedInitFlag
|
|
|
|
and (classVmFlags(t, c) & InitFlag) == 0)
|
|
|
|
{
|
2007-09-28 23:41:03 +00:00
|
|
|
classVmFlags(t, c) |= InitFlag;
|
2007-09-26 23:23:03 +00:00
|
|
|
invoke(t, classInitializer(t, c), 0);
|
|
|
|
if (t->exception) {
|
|
|
|
t->exception = makeExceptionInInitializerError(t, t->exception);
|
|
|
|
}
|
|
|
|
classVmFlags(t, c) &= ~(NeedInitFlag | InitFlag);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-09-25 23:53:11 +00:00
|
|
|
virtual void
|
2007-10-12 17:56:43 +00:00
|
|
|
visitObjects(Thread* vmt, Heap::Visitor* v)
|
2007-09-25 23:53:11 +00:00
|
|
|
{
|
2007-10-12 17:56:43 +00:00
|
|
|
MyThread* t = static_cast<MyThread*>(vmt);
|
|
|
|
|
|
|
|
for (Reference* r = t->reference; r; r = r->next) {
|
|
|
|
v->visit(&(r->target));
|
|
|
|
}
|
|
|
|
|
|
|
|
visitStack(t, v);
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual uintptr_t
|
2007-10-02 00:08:17 +00:00
|
|
|
frameStart(Thread* vmt)
|
2007-09-25 23:53:11 +00:00
|
|
|
{
|
2007-10-04 00:41:54 +00:00
|
|
|
return reinterpret_cast<uintptr_t>(static_cast<MyThread*>(vmt)->frame);
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual uintptr_t
|
2007-10-02 00:08:17 +00:00
|
|
|
frameNext(Thread*, uintptr_t frame)
|
2007-09-25 23:53:11 +00:00
|
|
|
{
|
2007-10-04 00:41:54 +00:00
|
|
|
return reinterpret_cast<uintptr_t>
|
|
|
|
(::frameNext(reinterpret_cast<void*>(frame)));
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool
|
2007-10-02 00:08:17 +00:00
|
|
|
frameValid(Thread*, uintptr_t frame)
|
2007-09-25 23:53:11 +00:00
|
|
|
{
|
2007-10-04 00:41:54 +00:00
|
|
|
return ::frameValid(reinterpret_cast<void*>(frame));
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual object
|
2007-10-02 00:08:17 +00:00
|
|
|
frameMethod(Thread*, uintptr_t frame)
|
2007-09-25 23:53:11 +00:00
|
|
|
{
|
2007-10-04 00:41:54 +00:00
|
|
|
return ::frameMethod(reinterpret_cast<void*>(frame));
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual unsigned
|
2007-10-03 00:22:48 +00:00
|
|
|
frameIp(Thread* t, uintptr_t frame)
|
2007-09-25 23:53:11 +00:00
|
|
|
{
|
2007-10-04 00:41:54 +00:00
|
|
|
void* f = reinterpret_cast<void*>(frame);
|
|
|
|
return addressOffset(t, ::frameMethod(f), ::frameAddress(f));
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
2007-10-04 22:41:19 +00:00
|
|
|
virtual int
|
|
|
|
lineNumber(Thread* t, object method, unsigned ip)
|
|
|
|
{
|
|
|
|
if (methodFlags(t, method) & ACC_NATIVE) {
|
|
|
|
return NativeLine;
|
|
|
|
}
|
|
|
|
|
|
|
|
Compiled* code = reinterpret_cast<Compiled*>(methodCompiled(t, method));
|
|
|
|
if (compiledLineNumberCount(t, code)) {
|
|
|
|
unsigned bottom = 0;
|
|
|
|
unsigned top = compiledLineNumberCount(t, code);
|
|
|
|
for (unsigned span = top - bottom; span; span = top - bottom) {
|
|
|
|
unsigned middle = bottom + (span / 2);
|
|
|
|
NativeLineNumber* ln = compiledLineNumber(t, code, middle);
|
|
|
|
|
|
|
|
if (ip >= nativeLineNumberIp(ln)
|
|
|
|
and (middle + 1 == compiledLineNumberCount(t, code)
|
|
|
|
or ip < nativeLineNumberIp
|
|
|
|
(compiledLineNumber(t, code, middle + 1))))
|
|
|
|
{
|
|
|
|
return nativeLineNumberLine(ln);
|
|
|
|
} else if (ip < nativeLineNumberIp(ln)) {
|
|
|
|
top = middle;
|
|
|
|
} else if (ip > nativeLineNumberIp(ln)) {
|
|
|
|
bottom = middle + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
abort(t);
|
|
|
|
} else {
|
|
|
|
return UnknownLine;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-09-25 23:53:11 +00:00
|
|
|
virtual object*
|
2007-09-30 03:33:38 +00:00
|
|
|
makeLocalReference(Thread* vmt, object o)
|
2007-09-25 23:53:11 +00:00
|
|
|
{
|
2007-09-30 03:33:38 +00:00
|
|
|
if (o) {
|
|
|
|
MyThread* t = static_cast<MyThread*>(vmt);
|
|
|
|
|
|
|
|
Reference* r = new (t->m->system->allocate(sizeof(Reference)))
|
|
|
|
Reference(o, &(t->reference));
|
|
|
|
|
|
|
|
return &(r->target);
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void
|
2007-09-30 03:33:38 +00:00
|
|
|
disposeLocalReference(Thread* t, object* r)
|
2007-09-25 23:53:11 +00:00
|
|
|
{
|
2007-09-30 03:33:38 +00:00
|
|
|
if (r) {
|
|
|
|
vm::dispose(t, reinterpret_cast<Reference*>(r));
|
|
|
|
}
|
2007-09-25 23:53:11 +00:00
|
|
|
}
|
|
|
|
|
2007-09-24 01:39:03 +00:00
|
|
|
virtual object
|
|
|
|
invokeArray(Thread* t, object method, object this_, object arguments)
|
|
|
|
{
|
|
|
|
assert(t, t->state == Thread::ActiveState
|
|
|
|
or t->state == Thread::ExclusiveState);
|
|
|
|
|
|
|
|
assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0));
|
|
|
|
|
2007-09-25 23:53:11 +00:00
|
|
|
const char* spec = reinterpret_cast<char*>
|
|
|
|
(&byteArrayBody(t, methodSpec(t, method), 0));
|
|
|
|
|
2007-09-26 23:23:03 +00:00
|
|
|
unsigned size = methodParameterFootprint(t, method) + FrameFootprint;
|
2007-09-25 23:53:11 +00:00
|
|
|
uintptr_t array[size];
|
|
|
|
bool objectMask[size];
|
|
|
|
ArgumentList list(t, array, objectMask, this_, spec, arguments);
|
2007-09-24 01:39:03 +00:00
|
|
|
|
2007-09-25 23:53:11 +00:00
|
|
|
return ::invoke(t, method, &list);
|
2007-09-24 01:39:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual object
|
|
|
|
invokeList(Thread* t, object method, object this_, bool indirectObjects,
|
|
|
|
va_list arguments)
|
|
|
|
{
|
|
|
|
assert(t, t->state == Thread::ActiveState
|
|
|
|
or t->state == Thread::ExclusiveState);
|
|
|
|
|
|
|
|
assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0));
|
|
|
|
|
2007-09-25 23:53:11 +00:00
|
|
|
const char* spec = reinterpret_cast<char*>
|
|
|
|
(&byteArrayBody(t, methodSpec(t, method), 0));
|
|
|
|
|
2007-09-26 23:23:03 +00:00
|
|
|
unsigned size = methodParameterFootprint(t, method) + FrameFootprint;
|
2007-09-25 23:53:11 +00:00
|
|
|
uintptr_t array[size];
|
|
|
|
bool objectMask[size];
|
|
|
|
ArgumentList list
|
|
|
|
(t, array, objectMask, this_, spec, indirectObjects, arguments);
|
2007-09-24 01:39:03 +00:00
|
|
|
|
2007-09-25 23:53:11 +00:00
|
|
|
return ::invoke(t, method, &list);
|
2007-09-24 01:39:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual object
|
|
|
|
invokeList(Thread* t, const char* className, const char* methodName,
|
|
|
|
const char* methodSpec, object this_, va_list arguments)
|
|
|
|
{
|
|
|
|
assert(t, t->state == Thread::ActiveState
|
|
|
|
or t->state == Thread::ExclusiveState);
|
|
|
|
|
2007-09-26 23:23:03 +00:00
|
|
|
unsigned size = parameterFootprint(t, methodSpec, false) + FrameFootprint;
|
2007-09-25 23:53:11 +00:00
|
|
|
uintptr_t array[size];
|
|
|
|
bool objectMask[size];
|
|
|
|
ArgumentList list
|
|
|
|
(t, array, objectMask, this_, methodSpec, false, arguments);
|
2007-09-24 01:39:03 +00:00
|
|
|
|
|
|
|
object method = resolveMethod(t, className, methodName, methodSpec);
|
|
|
|
if (LIKELY(t->exception == 0)) {
|
|
|
|
assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0));
|
|
|
|
|
2007-09-25 23:53:11 +00:00
|
|
|
return ::invoke(t, method, &list);
|
2007-09-24 01:39:03 +00:00
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void dispose() {
|
2007-10-03 00:22:48 +00:00
|
|
|
if (methodStub_) {
|
|
|
|
s->free(methodStub_);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nativeInvoker_) {
|
|
|
|
s->free(nativeInvoker_);
|
|
|
|
}
|
|
|
|
|
2007-10-04 03:19:39 +00:00
|
|
|
if (caller_) {
|
|
|
|
s->free(caller_);
|
|
|
|
}
|
|
|
|
|
2007-09-24 01:39:03 +00:00
|
|
|
s->free(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
System* s;
|
2007-10-04 00:41:54 +00:00
|
|
|
Compiled* methodStub_;
|
|
|
|
Compiled* nativeInvoker_;
|
2007-10-04 03:19:39 +00:00
|
|
|
Compiled* caller_;
|
2007-09-24 01:39:03 +00:00
|
|
|
};
|
|
|
|
|
2007-10-04 03:19:39 +00:00
|
|
|
Compiled*
|
|
|
|
caller(MyThread* t)
|
|
|
|
{
|
|
|
|
return static_cast<MyProcessor*>(t->m->processor)->caller(t);
|
|
|
|
}
|
|
|
|
|
2007-09-24 01:39:03 +00:00
|
|
|
} // namespace
|
|
|
|
|
|
|
|
namespace vm {
|
|
|
|
|
2007-09-25 23:53:11 +00:00
|
|
|
Processor*
|
|
|
|
makeProcessor(System* system)
|
2007-09-24 01:39:03 +00:00
|
|
|
{
|
2007-09-25 23:53:11 +00:00
|
|
|
return new (system->allocate(sizeof(MyProcessor))) MyProcessor(system);
|
2007-09-24 01:39:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace vm
|
2007-09-25 23:53:11 +00:00
|
|
|
|