mirror of
https://github.com/corda/corda.git
synced 2025-01-01 10:46:46 +00:00
Merge branch 'master' of dice.ecovate.com:/home/dicej/git/vm
This commit is contained in:
commit
ea307cfdf8
@ -10,6 +10,7 @@ public class Method<T> extends AccessibleObject implements Member {
|
|||||||
private byte[] spec;
|
private byte[] spec;
|
||||||
private Class<T> class_;
|
private Class<T> class_;
|
||||||
private Object code;
|
private Object code;
|
||||||
|
private Object compiled;
|
||||||
|
|
||||||
private Method() { }
|
private Method() { }
|
||||||
|
|
||||||
|
6
makefile
6
makefile
@ -24,6 +24,8 @@ else
|
|||||||
ld-library-path = LD_LIBRARY_PATH
|
ld-library-path = LD_LIBRARY_PATH
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
process = interpret
|
||||||
|
|
||||||
mode = debug
|
mode = debug
|
||||||
|
|
||||||
bld = build/$(platform)/$(arch)/$(mode)
|
bld = build/$(platform)/$(arch)/$(mode)
|
||||||
@ -32,7 +34,7 @@ src = src
|
|||||||
classpath = classpath
|
classpath = classpath
|
||||||
test = test
|
test = test
|
||||||
|
|
||||||
input = $(cls)/Threads.class
|
input = $(cls)/Instructions.class
|
||||||
|
|
||||||
cxx = g++
|
cxx = g++
|
||||||
cc = gcc
|
cc = gcc
|
||||||
@ -104,7 +106,7 @@ interpreter-sources = \
|
|||||||
$(src)/finder.cpp \
|
$(src)/finder.cpp \
|
||||||
$(src)/machine.cpp \
|
$(src)/machine.cpp \
|
||||||
$(src)/heap.cpp \
|
$(src)/heap.cpp \
|
||||||
$(src)/interpret.cpp \
|
$(src)/$(process).cpp \
|
||||||
$(src)/builtin.cpp \
|
$(src)/builtin.cpp \
|
||||||
$(src)/jnienv.cpp \
|
$(src)/jnienv.cpp \
|
||||||
$(src)/main.cpp
|
$(src)/main.cpp
|
||||||
|
17
src/common.h
17
src/common.h
@ -4,6 +4,7 @@
|
|||||||
#include "stdint.h"
|
#include "stdint.h"
|
||||||
#include "stdlib.h"
|
#include "stdlib.h"
|
||||||
#include "stdarg.h"
|
#include "stdarg.h"
|
||||||
|
#include "stddef.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "stdio.h"
|
#include "stdio.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
@ -44,6 +45,22 @@
|
|||||||
|
|
||||||
inline void* operator new(size_t, void* p) throw() { return p; }
|
inline void* operator new(size_t, void* p) throw() { return p; }
|
||||||
|
|
||||||
|
#ifdef __i386__
|
||||||
|
|
||||||
|
extern "C" uint64_t
|
||||||
|
cdeclCall(void* function, void* stack, unsigned stackSize,
|
||||||
|
unsigned returnType);
|
||||||
|
|
||||||
|
#elif defined __x86_64__
|
||||||
|
|
||||||
|
extern "C" uint64_t
|
||||||
|
amd64Call(void* function, void* stack, unsigned stackSize,
|
||||||
|
void* gprTable, void* sseTable, unsigned returnType);
|
||||||
|
|
||||||
|
#else
|
||||||
|
# error unsupported platform
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
const unsigned BytesPerWord = sizeof(uintptr_t);
|
const unsigned BytesPerWord = sizeof(uintptr_t);
|
||||||
|
657
src/compile.cpp
657
src/compile.cpp
@ -7,6 +7,11 @@ using namespace vm;
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
const unsigned FrameThread = 8;
|
||||||
|
const unsigned FrameMethod = 12;
|
||||||
|
const unsigned FrameNext = 16;
|
||||||
|
const unsigned FrameFootprint = 12;
|
||||||
|
|
||||||
class Rope {
|
class Rope {
|
||||||
public:
|
public:
|
||||||
class Node {
|
class Node {
|
||||||
@ -21,6 +26,8 @@ class Rope {
|
|||||||
uint8_t data[Size];
|
uint8_t data[Size];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Rope() { }
|
||||||
|
|
||||||
Rope(System* s):
|
Rope(System* s):
|
||||||
s(s),
|
s(s),
|
||||||
front(0),
|
front(0),
|
||||||
@ -31,12 +38,16 @@ class Rope {
|
|||||||
|
|
||||||
void append(uint8_t v) {
|
void append(uint8_t v) {
|
||||||
if (position == Node::Size) {
|
if (position == Node::Size) {
|
||||||
Node* n = new (s->allocate(sizeof(Node))) Node;
|
if (front == 0 or rear->next == 0) {
|
||||||
if (front == 0) {
|
Node* n = new (s->allocate(sizeof(Node))) Node;
|
||||||
front = rear = n;
|
if (front == 0) {
|
||||||
|
front = rear = n;
|
||||||
|
} else {
|
||||||
|
rear->next = n;
|
||||||
|
rear = n;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
rear->next = n;
|
rear = rear->next;
|
||||||
rear = n;
|
|
||||||
}
|
}
|
||||||
position = 0;
|
position = 0;
|
||||||
++ count;
|
++ count;
|
||||||
@ -45,6 +56,13 @@ class Rope {
|
|||||||
rear->data[position++] = v;
|
rear->data[position++] = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void append4(uint32_t v) {
|
||||||
|
append((v >> 0) & 0xFF);
|
||||||
|
append((v >> 8) & 0xFF);
|
||||||
|
append((v >> 16) & 0xFF);
|
||||||
|
append((v >> 24) & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
unsigned length() {
|
unsigned length() {
|
||||||
return (count * Node::Size) + position;
|
return (count * Node::Size) + position;
|
||||||
}
|
}
|
||||||
@ -72,16 +90,233 @@ class Rope {
|
|||||||
unsigned position;
|
unsigned position;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Assembler {
|
class ArgumentList;
|
||||||
|
|
||||||
|
class MyThread: public Thread {
|
||||||
public:
|
public:
|
||||||
Assembler(System* s):
|
MyThread(Machine* m, object javaThread, vm::Thread* parent):
|
||||||
rope(s)
|
vm::Thread(m, javaThread, parent),
|
||||||
|
argumentList(0),
|
||||||
|
frame(0)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
Rope rope;
|
ArgumentList* argumentList;
|
||||||
|
void* frame;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Compiler: private Assembler {
|
class Assembler {
|
||||||
|
public:
|
||||||
|
class Label {
|
||||||
|
public:
|
||||||
|
class Snapshot {
|
||||||
|
public:
|
||||||
|
Rope rope;
|
||||||
|
unsigned ip;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const unsigned Capacity = 8;
|
||||||
|
|
||||||
|
Label():
|
||||||
|
unresolvedCount(0),
|
||||||
|
mark_(-1)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
void reference(Rope* r, unsigned ip) {
|
||||||
|
if (mark_ == -1) {
|
||||||
|
expect(r->s, unresolvedCount < Capacity);
|
||||||
|
unresolved[unresolvedCount].rope = *r;
|
||||||
|
unresolved[unresolvedCount].ip = ip;
|
||||||
|
++ unresolvedCount;
|
||||||
|
|
||||||
|
r->append4(0);
|
||||||
|
} else {
|
||||||
|
r->append4(mark_ - ip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mark(Rope* r) {
|
||||||
|
mark_ = r->length();
|
||||||
|
for (unsigned i = 0; i < unresolvedCount; ++i) {
|
||||||
|
unresolved[i].rope.append4(mark_ - unresolved[i].ip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Snapshot unresolved[Capacity];
|
||||||
|
unsigned unresolvedCount;
|
||||||
|
int mark_;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Register {
|
||||||
|
eax = 0,
|
||||||
|
ecx = 1,
|
||||||
|
edx = 2,
|
||||||
|
ebx = 3,
|
||||||
|
esp = 4,
|
||||||
|
ebp = 5
|
||||||
|
};
|
||||||
|
|
||||||
|
Assembler(System* s):
|
||||||
|
r(s)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
void mov(Register src, Register dst) {
|
||||||
|
r.append(0x89);
|
||||||
|
r.append(0xc0 | (src << 3) | dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mov(Register src, int srcOffset, Register dst) {
|
||||||
|
r.append(0x8b);
|
||||||
|
if (srcOffset) {
|
||||||
|
r.append(0x40 | (dst << 3) | src);
|
||||||
|
r.append(srcOffset);
|
||||||
|
} else {
|
||||||
|
r.append((dst << 3) | src);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mov(Register src, Register dst, int dstOffset) {
|
||||||
|
r.append(0x89);
|
||||||
|
if (dstOffset) {
|
||||||
|
r.append(0x40 | (src << 3) | dst);
|
||||||
|
r.append(dstOffset);
|
||||||
|
} else {
|
||||||
|
r.append((src << 3) | dst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mov(uintptr_t src, Register dst) {
|
||||||
|
r.append(0xb8 | dst);
|
||||||
|
r.append4(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
void push(Register reg) {
|
||||||
|
r.append(0x50 | reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void push(Register reg, int offset) {
|
||||||
|
r.append(0xff);
|
||||||
|
r.append(0x70 | reg);
|
||||||
|
r.append(offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void push(int v) {
|
||||||
|
r.append(0x6a);
|
||||||
|
r.append(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pop(Register dst) {
|
||||||
|
r.append(0x58 | dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pop(Register dst, int offset) {
|
||||||
|
r.append(0x8f);
|
||||||
|
r.append(0x40 | dst);
|
||||||
|
r.append(offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void add(Register src, Register dst) {
|
||||||
|
r.append(0x01);
|
||||||
|
r.append(0xc0 | (src << 3) | dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
void add(int src, Register dst) {
|
||||||
|
r.append(0x83);
|
||||||
|
r.append(0xc0 | dst);
|
||||||
|
r.append(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sub(Register src, Register dst) {
|
||||||
|
r.append(0x29);
|
||||||
|
r.append(0xc0 | (src << 3) | dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sub(int src, Register dst) {
|
||||||
|
r.append(0x83);
|
||||||
|
r.append(0xe8 | dst);
|
||||||
|
r.append(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
void or_(Register src, Register dst) {
|
||||||
|
r.append(0x09);
|
||||||
|
r.append(0xc0 | (src << 3) | dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
void or_(int src, Register dst) {
|
||||||
|
r.append(0x83);
|
||||||
|
r.append(0xc8 | dst);
|
||||||
|
r.append(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
void and_(Register src, Register dst) {
|
||||||
|
r.append(0x21);
|
||||||
|
r.append(0xc0 | (src << 3) | dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
void and_(int src, Register dst) {
|
||||||
|
r.append(0x83);
|
||||||
|
r.append(0xe0 | dst);
|
||||||
|
r.append(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ret() {
|
||||||
|
r.append(0xc3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void jmp(Label& label) {
|
||||||
|
r.append(0xE9);
|
||||||
|
label.reference(&r, r.length() + 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void jmp(Register reg) {
|
||||||
|
r.append(0xff);
|
||||||
|
r.append(0xe0 | reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void jmp(Register reg, int offset) {
|
||||||
|
r.append(0xff);
|
||||||
|
r.append(0x60 | reg);
|
||||||
|
r.append(offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void jnz(Label& label) {
|
||||||
|
r.append(0x0F);
|
||||||
|
r.append(0x85);
|
||||||
|
label.reference(&r, r.length() + 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void jne(Label& label) {
|
||||||
|
jnz(label);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmp(int v, Register reg) {
|
||||||
|
r.append(0x83);
|
||||||
|
r.append(0xf8 | reg);
|
||||||
|
r.append(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
void call(Register reg) {
|
||||||
|
r.append(0xff);
|
||||||
|
r.append(0xd0 | reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
Rope r;
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
compileMethod(Thread* t, object method);
|
||||||
|
|
||||||
|
int
|
||||||
|
localOffset(int v, int parameterFootprint)
|
||||||
|
{
|
||||||
|
v *= 4;
|
||||||
|
if (v < parameterFootprint) {
|
||||||
|
return v + 8 + FrameFootprint;
|
||||||
|
} else {
|
||||||
|
return -(v + 4 - parameterFootprint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Compiler: public Assembler {
|
||||||
public:
|
public:
|
||||||
Compiler(System* s):
|
Compiler(System* s):
|
||||||
Assembler(s)
|
Assembler(s)
|
||||||
@ -92,9 +327,10 @@ class Compiler: private Assembler {
|
|||||||
mov(esp, ebp);
|
mov(esp, ebp);
|
||||||
|
|
||||||
object code = methodCode(t, method);
|
object code = methodCode(t, method);
|
||||||
|
unsigned parameterFootprint = methodParameterFootprint(t, method) * 4;
|
||||||
|
|
||||||
// reserve space for local variables
|
// reserve space for local variables
|
||||||
sub(codeMaxLocals(t, code), esp);
|
sub((codeMaxLocals(t, code) * 4) - parameterFootprint, esp);
|
||||||
|
|
||||||
for (unsigned i = 0; i < codeLength(t, code);) {
|
for (unsigned i = 0; i < codeLength(t, code);) {
|
||||||
switch (codeBody(t, code, i++)) {
|
switch (codeBody(t, code, i++)) {
|
||||||
@ -135,50 +371,42 @@ class Compiler: private Assembler {
|
|||||||
|
|
||||||
case iload_0:
|
case iload_0:
|
||||||
case fload_0:
|
case fload_0:
|
||||||
mov(ebp, 0, eax);
|
push(ebp, localOffset(0, parameterFootprint));
|
||||||
push(eax);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case iload_1:
|
case iload_1:
|
||||||
case fload_1:
|
case fload_1:
|
||||||
mov(ebp, -1, eax);
|
push(ebp, localOffset(1, parameterFootprint));
|
||||||
push(eax);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case iload_2:
|
case iload_2:
|
||||||
case fload_2:
|
case fload_2:
|
||||||
mov(ebp, -2, eax);
|
push(ebp, localOffset(2, parameterFootprint));
|
||||||
push(eax);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case iload_3:
|
case iload_3:
|
||||||
case fload_3:
|
case fload_3:
|
||||||
mov(ebp, -3, eax);
|
push(ebp, localOffset(3, parameterFootprint));
|
||||||
push(eax);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case istore_0:
|
case istore_0:
|
||||||
case fstore_0:
|
case fstore_0:
|
||||||
pop(eax);
|
pop(ebp, localOffset(0, parameterFootprint));
|
||||||
mov(eax, ebp, 0);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case istore_1:
|
case istore_1:
|
||||||
case fstore_1:
|
case fstore_1:
|
||||||
pop(eax);
|
pop(ebp, localOffset(1, parameterFootprint));
|
||||||
mov(eax, ebp, -1);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case istore_2:
|
case istore_2:
|
||||||
case fstore_2:
|
case fstore_2:
|
||||||
pop(eax);
|
pop(ebp, localOffset(2, parameterFootprint));
|
||||||
mov(eax, ebp, -2);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case istore_3:
|
case istore_3:
|
||||||
case fstore_3:
|
case fstore_3:
|
||||||
pop(eax);
|
pop(ebp, localOffset(3, parameterFootprint));
|
||||||
mov(eax, ebp, -3);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case return_:
|
case return_:
|
||||||
@ -192,26 +420,345 @@ class Compiler: private Assembler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void compileStub(MyThread* t) {
|
||||||
|
unsigned frameOffset = reinterpret_cast<uintptr_t>(&(t->frame))
|
||||||
|
- reinterpret_cast<uintptr_t>(t);
|
||||||
|
|
||||||
|
push(ebp);
|
||||||
|
mov(esp, ebp);
|
||||||
|
|
||||||
|
mov(ebp, FrameThread, eax);
|
||||||
|
mov(ebp, eax, frameOffset); // set thread frame to current
|
||||||
|
|
||||||
|
push(ebp, FrameMethod);
|
||||||
|
push(ebp, FrameThread);
|
||||||
|
mov(reinterpret_cast<uintptr_t>(compileMethod), eax);
|
||||||
|
call(eax);
|
||||||
|
add(8, esp);
|
||||||
|
|
||||||
|
mov(ebp, FrameMethod, eax);
|
||||||
|
mov(eax, MethodCompiled, eax); // load compiled code
|
||||||
|
|
||||||
|
mov(ebp, esp);
|
||||||
|
pop(ebp);
|
||||||
|
|
||||||
|
add(CompiledBody, eax);
|
||||||
|
jmp(eax); // call compiled code
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
compileMethod(Thread* t, object method)
|
||||||
|
{
|
||||||
|
if (methodCompiled(t, method) == t->m->processor->methodStub(t)) {
|
||||||
|
PROTECT(t, method);
|
||||||
|
|
||||||
|
ACQUIRE(t, t->m->classLock);
|
||||||
|
|
||||||
|
if (methodCompiled(t, method) == t->m->processor->methodStub(t)) {
|
||||||
|
Compiler c(t->m->system);
|
||||||
|
c.compile(t, method);
|
||||||
|
|
||||||
|
object compiled = makeCompiled(t, 0, c.r.length(), false);
|
||||||
|
c.r.copyTo(&compiledBody(t, compiled, 0));
|
||||||
|
|
||||||
|
set(t, methodCompiled(t, method), compiled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
compileStub(Thread* t)
|
||||||
|
{
|
||||||
|
Compiler c(t->m->system);
|
||||||
|
c.compileStub(static_cast<MyThread*>(t));
|
||||||
|
|
||||||
|
object stub = makeCompiled(t, 0, c.r.length(), false);
|
||||||
|
c.r.copyTo(&compiledBody(t, stub, 0));
|
||||||
|
|
||||||
|
return stub;
|
||||||
|
}
|
||||||
|
|
||||||
|
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),
|
||||||
|
position(0)
|
||||||
|
{
|
||||||
|
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_);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* s = spec;
|
||||||
|
++ s; // skip '('
|
||||||
|
while (*s and *s != ')') {
|
||||||
|
switch (*s) {
|
||||||
|
case 'L':
|
||||||
|
while (*s and *s != ';') ++ s;
|
||||||
|
++ s;
|
||||||
|
|
||||||
|
if (indirectObjects) {
|
||||||
|
object* v = va_arg(arguments, object*);
|
||||||
|
addObject(v ? *v : 0);
|
||||||
|
} else {
|
||||||
|
addObject(va_arg(arguments, object));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '[':
|
||||||
|
while (*s == '[') ++ s;
|
||||||
|
switch (*s) {
|
||||||
|
case 'L':
|
||||||
|
while (*s and *s != ';') ++ s;
|
||||||
|
++ s;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
++ s;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (indirectObjects) {
|
||||||
|
object* v = va_arg(arguments, object*);
|
||||||
|
addObject(v ? *v : 0);
|
||||||
|
} else {
|
||||||
|
addObject(va_arg(arguments, object));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'J':
|
||||||
|
case 'D':
|
||||||
|
++ s;
|
||||||
|
addLong(va_arg(arguments, uint64_t));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
++ s;
|
||||||
|
addInt(va_arg(arguments, uint32_t));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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),
|
||||||
|
position(0)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
const char* s = spec;
|
||||||
|
++ s; // skip '('
|
||||||
|
while (*s and *s != ')') {
|
||||||
|
switch (*s) {
|
||||||
|
case 'L':
|
||||||
|
while (*s and *s != ';') ++ s;
|
||||||
|
++ s;
|
||||||
|
addObject(objectArrayBody(t, arguments, index++));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '[':
|
||||||
|
while (*s == '[') ++ s;
|
||||||
|
switch (*s) {
|
||||||
|
case 'L':
|
||||||
|
while (*s and *s != ';') ++ s;
|
||||||
|
++ s;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
++ s;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
addObject(objectArrayBody(t, arguments, index++));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'J':
|
||||||
|
case 'D':
|
||||||
|
++ s;
|
||||||
|
addLong(cast<int64_t>(objectArrayBody(t, arguments, index++),
|
||||||
|
BytesPerWord));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
++ s;
|
||||||
|
addInt(cast<int32_t>(objectArrayBody(t, arguments, index++),
|
||||||
|
BytesPerWord));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~ArgumentList() {
|
||||||
|
t->argumentList = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addObject(object v) {
|
||||||
|
array[position] = reinterpret_cast<uintptr_t>(v);
|
||||||
|
objectMask[position] = true;
|
||||||
|
++ position;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addInt(uint32_t v) {
|
||||||
|
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
object
|
object
|
||||||
compile(Thread* t, object method)
|
invoke(Thread* thread, object method, ArgumentList* arguments)
|
||||||
{
|
{
|
||||||
Compiler c(t->vm->system);
|
MyThread* t = static_cast<MyThread*>(thread);
|
||||||
c.compile(t, method);
|
|
||||||
|
arguments->array[1] = reinterpret_cast<uintptr_t>(method);
|
||||||
|
|
||||||
object r = makeByteArray(t, c.rope.length(), false);
|
const char* s = reinterpret_cast<const char*>
|
||||||
c.rope.copyTo(&byteArrayBody(t, r, 0));
|
(&byteArrayBody(t, methodSpec(t, method), 0));
|
||||||
|
while (*s and *s != ')') ++s;
|
||||||
|
unsigned returnCode = fieldCode(t, s[1]);
|
||||||
|
unsigned returnType = fieldType(t, returnCode);
|
||||||
|
|
||||||
|
uint64_t result = cdeclCall
|
||||||
|
(&compiledBody(t, methodCompiled(t, method), 0), arguments->array,
|
||||||
|
arguments->position * 4, returnType);
|
||||||
|
|
||||||
|
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);
|
||||||
|
};
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyInvoker: public Invoker {
|
class MyProcessor: public Processor {
|
||||||
public:
|
public:
|
||||||
MyInvoker(System* s):
|
MyProcessor(System* s):
|
||||||
s(s)
|
s(s),
|
||||||
|
stub(0)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
virtual Thread*
|
||||||
|
makeThread(Machine* m, object javaThread, Thread* parent)
|
||||||
|
{
|
||||||
|
return new (s->allocate(sizeof(MyThread))) MyThread(m, javaThread, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual object
|
||||||
|
methodStub(Thread* t)
|
||||||
|
{
|
||||||
|
if (stub == 0) {
|
||||||
|
stub = compileStub(t);
|
||||||
|
}
|
||||||
|
return stub;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void
|
||||||
|
visitObjects(Thread* t, Heap::Visitor*)
|
||||||
|
{
|
||||||
|
abort(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual uintptr_t
|
||||||
|
frameStart(Thread* t)
|
||||||
|
{
|
||||||
|
abort(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual uintptr_t
|
||||||
|
frameNext(Thread* t, uintptr_t)
|
||||||
|
{
|
||||||
|
abort(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool
|
||||||
|
frameValid(Thread* t, uintptr_t)
|
||||||
|
{
|
||||||
|
abort(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual object
|
||||||
|
frameMethod(Thread* t, uintptr_t)
|
||||||
|
{
|
||||||
|
abort(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual unsigned
|
||||||
|
frameIp(Thread* t, uintptr_t)
|
||||||
|
{
|
||||||
|
abort(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual object*
|
||||||
|
makeLocalReference(Thread* t, object)
|
||||||
|
{
|
||||||
|
abort(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void
|
||||||
|
disposeLocalReference(Thread* t, object*)
|
||||||
|
{
|
||||||
|
abort(t);
|
||||||
|
}
|
||||||
|
|
||||||
virtual object
|
virtual object
|
||||||
invokeArray(Thread* t, object method, object this_, object arguments)
|
invokeArray(Thread* t, object method, object this_, object arguments)
|
||||||
{
|
{
|
||||||
@ -220,10 +767,15 @@ class MyInvoker: public Invoker {
|
|||||||
|
|
||||||
assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0));
|
assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0));
|
||||||
|
|
||||||
uintptr_t a[methodParameterCount(t, method) * 2];
|
const char* spec = reinterpret_cast<char*>
|
||||||
ArgumentArray array(t, a, method, this_, spec, arguments);
|
(&byteArrayBody(t, methodSpec(t, method), 0));
|
||||||
|
|
||||||
|
unsigned size = methodParameterCount(t, method) * 2;
|
||||||
|
uintptr_t array[size];
|
||||||
|
bool objectMask[size];
|
||||||
|
ArgumentList list(t, array, objectMask, this_, spec, arguments);
|
||||||
|
|
||||||
return invoke(t, method, &array);
|
return ::invoke(t, method, &list);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual object
|
virtual object
|
||||||
@ -235,10 +787,16 @@ class MyInvoker: public Invoker {
|
|||||||
|
|
||||||
assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0));
|
assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0));
|
||||||
|
|
||||||
uintptr_t a[methodParameterCount(t, method) * 2];
|
const char* spec = reinterpret_cast<char*>
|
||||||
ArgumentArray array(t, a, method, this_, spec, indirectObjects, arguments);
|
(&byteArrayBody(t, methodSpec(t, method), 0));
|
||||||
|
|
||||||
return invoke(t, method, &array);
|
unsigned size = methodParameterCount(t, method) * 2;
|
||||||
|
uintptr_t array[size];
|
||||||
|
bool objectMask[size];
|
||||||
|
ArgumentList list
|
||||||
|
(t, array, objectMask, this_, spec, indirectObjects, arguments);
|
||||||
|
|
||||||
|
return ::invoke(t, method, &list);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual object
|
virtual object
|
||||||
@ -248,14 +806,17 @@ class MyInvoker: public Invoker {
|
|||||||
assert(t, t->state == Thread::ActiveState
|
assert(t, t->state == Thread::ActiveState
|
||||||
or t->state == Thread::ExclusiveState);
|
or t->state == Thread::ExclusiveState);
|
||||||
|
|
||||||
uintptr_t a[methodParameterCount(t, method) * 2];
|
unsigned size = parameterCount(methodSpec) * 2;
|
||||||
ArgumentArray array(t, a, method, this_, methodSpec, false, arguments);
|
uintptr_t array[size];
|
||||||
|
bool objectMask[size];
|
||||||
|
ArgumentList list
|
||||||
|
(t, array, objectMask, this_, methodSpec, false, arguments);
|
||||||
|
|
||||||
object method = resolveMethod(t, className, methodName, methodSpec);
|
object method = resolveMethod(t, className, methodName, methodSpec);
|
||||||
if (LIKELY(t->exception == 0)) {
|
if (LIKELY(t->exception == 0)) {
|
||||||
assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0));
|
assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0));
|
||||||
|
|
||||||
return invoke(t, method, &array);
|
return ::invoke(t, method, &list);
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -266,16 +827,18 @@ class MyInvoker: public Invoker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
System* s;
|
System* s;
|
||||||
|
object stub;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace vm {
|
namespace vm {
|
||||||
|
|
||||||
Invoker*
|
Processor*
|
||||||
makeInvoker(System* system)
|
makeProcessor(System* system)
|
||||||
{
|
{
|
||||||
return new (system->allocate(sizeof(MyInvoker))) MyInvoker(system);
|
return new (system->allocate(sizeof(MyProcessor))) MyProcessor(system);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
|
||||||
|
@ -8,6 +8,12 @@ using namespace vm;
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
const unsigned FrameBaseOffset = 0;
|
||||||
|
const unsigned FrameNextOffset = 1;
|
||||||
|
const unsigned FrameMethodOffset = 2;
|
||||||
|
const unsigned FrameIpOffset = 3;
|
||||||
|
const unsigned FrameFootprint = 4;
|
||||||
|
|
||||||
class Thread: public vm::Thread {
|
class Thread: public vm::Thread {
|
||||||
public:
|
public:
|
||||||
static const unsigned StackSizeInBytes = 64 * 1024;
|
static const unsigned StackSizeInBytes = 64 * 1024;
|
||||||
@ -3012,6 +3018,12 @@ class MyProcessor: public Processor {
|
|||||||
return new (s->allocate(sizeof(Thread))) Thread(m, javaThread, parent);
|
return new (s->allocate(sizeof(Thread))) Thread(m, javaThread, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual object
|
||||||
|
methodStub(vm::Thread*)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
visitObjects(vm::Thread* vmt, Heap::Visitor* v)
|
visitObjects(vm::Thread* vmt, Heap::Visitor* v)
|
||||||
{
|
{
|
||||||
@ -3112,8 +3124,7 @@ class MyProcessor: public Processor {
|
|||||||
|
|
||||||
virtual object
|
virtual object
|
||||||
invokeList(vm::Thread* vmt, object method, object this_,
|
invokeList(vm::Thread* vmt, object method, object this_,
|
||||||
bool indirectObjects,
|
bool indirectObjects, va_list arguments)
|
||||||
va_list arguments)
|
|
||||||
{
|
{
|
||||||
Thread* t = static_cast<Thread*>(vmt);
|
Thread* t = static_cast<Thread*>(vmt);
|
||||||
|
|
||||||
|
@ -917,6 +917,7 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
|
|||||||
methodName(t, method),
|
methodName(t, method),
|
||||||
methodSpec(t, method),
|
methodSpec(t, method),
|
||||||
methodClass(t, method),
|
methodClass(t, method),
|
||||||
|
0,
|
||||||
0);
|
0);
|
||||||
hashMapInsert(t, virtualMap, method, method, methodHash);
|
hashMapInsert(t, virtualMap, method, method, methodHash);
|
||||||
}
|
}
|
||||||
@ -986,7 +987,8 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
|
|||||||
arrayBody(t, pool, name - 1),
|
arrayBody(t, pool, name - 1),
|
||||||
arrayBody(t, pool, spec - 1),
|
arrayBody(t, pool, spec - 1),
|
||||||
class_,
|
class_,
|
||||||
code);
|
code,
|
||||||
|
(code ? t->m->processor->methodStub(t) : 0));
|
||||||
PROTECT(t, method);
|
PROTECT(t, method);
|
||||||
|
|
||||||
if (flags & ACC_STATIC) {
|
if (flags & ACC_STATIC) {
|
||||||
|
@ -29,12 +29,6 @@ const bool DebugReferences = false;
|
|||||||
const uintptr_t HashTakenMark = 1;
|
const uintptr_t HashTakenMark = 1;
|
||||||
const uintptr_t ExtendedMark = 2;
|
const uintptr_t ExtendedMark = 2;
|
||||||
|
|
||||||
const unsigned FrameBaseOffset = 0;
|
|
||||||
const unsigned FrameNextOffset = 1;
|
|
||||||
const unsigned FrameMethodOffset = 2;
|
|
||||||
const unsigned FrameIpOffset = 3;
|
|
||||||
const unsigned FrameFootprint = 4;
|
|
||||||
|
|
||||||
enum FieldCode {
|
enum FieldCode {
|
||||||
VoidField,
|
VoidField,
|
||||||
ByteField,
|
ByteField,
|
||||||
@ -65,6 +59,7 @@ const unsigned PrimitiveFlag = 1 << 4;
|
|||||||
|
|
||||||
// method flags:
|
// method flags:
|
||||||
const unsigned ClassInitFlag = 1 << 0;
|
const unsigned ClassInitFlag = 1 << 0;
|
||||||
|
const unsigned CompiledFlag = 1 << 1;
|
||||||
|
|
||||||
typedef Machine JavaVM;
|
typedef Machine JavaVM;
|
||||||
typedef Thread JNIEnv;
|
typedef Thread JNIEnv;
|
||||||
|
@ -14,6 +14,9 @@ class Processor {
|
|||||||
virtual Thread*
|
virtual Thread*
|
||||||
makeThread(Machine* m, object javaThread, Thread* parent) = 0;
|
makeThread(Machine* m, object javaThread, Thread* parent) = 0;
|
||||||
|
|
||||||
|
virtual object
|
||||||
|
methodStub(Thread* t) = 0;
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
visitObjects(Thread* t, Heap::Visitor* v) = 0;
|
visitObjects(Thread* t, Heap::Visitor* v) = 0;
|
||||||
|
|
||||||
|
@ -15,14 +15,10 @@
|
|||||||
|
|
||||||
#define ACQUIRE(x) MutexResource MAKE_NAME(mutexResource_) (x)
|
#define ACQUIRE(x) MutexResource MAKE_NAME(mutexResource_) (x)
|
||||||
|
|
||||||
#ifdef __i386__
|
|
||||||
|
|
||||||
extern "C" uint64_t
|
|
||||||
cdeclCall(void* function, void* stack, unsigned stackSize,
|
|
||||||
unsigned returnType);
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
#ifdef __i386__
|
||||||
|
|
||||||
inline uint64_t
|
inline uint64_t
|
||||||
dynamicCall(void* function, uintptr_t* arguments, uint8_t*,
|
dynamicCall(void* function, uintptr_t* arguments, uint8_t*,
|
||||||
unsigned, unsigned argumentsSize, unsigned returnType)
|
unsigned, unsigned argumentsSize, unsigned returnType)
|
||||||
@ -30,16 +26,8 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t*,
|
|||||||
return cdeclCall(function, arguments, argumentsSize, returnType);
|
return cdeclCall(function, arguments, argumentsSize, returnType);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
#elif defined __x86_64__
|
#elif defined __x86_64__
|
||||||
|
|
||||||
extern "C" uint64_t
|
|
||||||
amd64Call(void* function, void* stack, unsigned stackSize,
|
|
||||||
void* gprTable, void* sseTable, unsigned returnType);
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
dynamicCall(void* function, uint64_t* arguments, uint8_t* argumentTypes,
|
dynamicCall(void* function, uint64_t* arguments, uint8_t* argumentTypes,
|
||||||
unsigned argumentCount, unsigned, unsigned returnType)
|
unsigned argumentCount, unsigned, unsigned returnType)
|
||||||
@ -80,12 +68,12 @@ dynamicCall(void* function, uint64_t* arguments, uint8_t* argumentTypes,
|
|||||||
(sseIndex ? sseTable : 0), returnType);
|
(sseIndex ? sseTable : 0), returnType);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
# error unsupported platform
|
# error unsupported platform
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
using namespace vm;
|
using namespace vm;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -1035,6 +1035,15 @@ writeAccessor(Output* out, Object* member, Object* offset, bool unsafe = false)
|
|||||||
const char* typeName = memberTypeName(member);
|
const char* typeName = memberTypeName(member);
|
||||||
if (memberTypeObject(member)) typeName = capitalize(typeName);
|
if (memberTypeObject(member)) typeName = capitalize(typeName);
|
||||||
|
|
||||||
|
if (not unsafe) {
|
||||||
|
out->write("const unsigned ");
|
||||||
|
out->write(capitalize(::typeName(memberOwner(member))));
|
||||||
|
out->write(capitalize(memberName(member)));
|
||||||
|
out->write(" = ");
|
||||||
|
writeOffset(out, offset);
|
||||||
|
out->write(";\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
out->write("inline ");
|
out->write("inline ");
|
||||||
out->write(typeName);
|
out->write(typeName);
|
||||||
if (member->type != Object::Scalar and memberTypeObject(member)) {
|
if (member->type != Object::Scalar and memberTypeObject(member)) {
|
||||||
@ -1094,7 +1103,10 @@ writeAccessor(Output* out, Object* member, Object* offset, bool unsafe = false)
|
|||||||
} else {
|
} else {
|
||||||
out->write("[");
|
out->write("[");
|
||||||
}
|
}
|
||||||
writeOffset(out, offset);
|
|
||||||
|
out->write(capitalize(::typeName(memberOwner(member))));
|
||||||
|
out->write(capitalize(memberName(member)));
|
||||||
|
|
||||||
if (member->type != Object::Scalar) {
|
if (member->type != Object::Scalar) {
|
||||||
out->write(" + (i * ");
|
out->write(" + (i * ");
|
||||||
unsigned elementSize = (memberTypeObject(member) ?
|
unsigned elementSize = (memberTypeObject(member) ?
|
||||||
|
@ -48,7 +48,12 @@
|
|||||||
(object name)
|
(object name)
|
||||||
(object spec)
|
(object spec)
|
||||||
(object class)
|
(object class)
|
||||||
(object code))
|
(object code)
|
||||||
|
(object compiled))
|
||||||
|
|
||||||
|
(type compiled
|
||||||
|
(nogc object method)
|
||||||
|
(array uint8_t body))
|
||||||
|
|
||||||
(type nativeMethodData
|
(type nativeMethodData
|
||||||
(void* function)
|
(void* function)
|
||||||
|
Loading…
Reference in New Issue
Block a user