mirror of
https://github.com/corda/corda.git
synced 2024-12-29 09:18:58 +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 Class<T> class_;
|
||||
private Object code;
|
||||
private Object compiled;
|
||||
|
||||
private Method() { }
|
||||
|
||||
|
6
makefile
6
makefile
@ -24,6 +24,8 @@ else
|
||||
ld-library-path = LD_LIBRARY_PATH
|
||||
endif
|
||||
|
||||
process = interpret
|
||||
|
||||
mode = debug
|
||||
|
||||
bld = build/$(platform)/$(arch)/$(mode)
|
||||
@ -32,7 +34,7 @@ src = src
|
||||
classpath = classpath
|
||||
test = test
|
||||
|
||||
input = $(cls)/Threads.class
|
||||
input = $(cls)/Instructions.class
|
||||
|
||||
cxx = g++
|
||||
cc = gcc
|
||||
@ -104,7 +106,7 @@ interpreter-sources = \
|
||||
$(src)/finder.cpp \
|
||||
$(src)/machine.cpp \
|
||||
$(src)/heap.cpp \
|
||||
$(src)/interpret.cpp \
|
||||
$(src)/$(process).cpp \
|
||||
$(src)/builtin.cpp \
|
||||
$(src)/jnienv.cpp \
|
||||
$(src)/main.cpp
|
||||
|
17
src/common.h
17
src/common.h
@ -4,6 +4,7 @@
|
||||
#include "stdint.h"
|
||||
#include "stdlib.h"
|
||||
#include "stdarg.h"
|
||||
#include "stddef.h"
|
||||
#include "string.h"
|
||||
#include "stdio.h"
|
||||
#include "types.h"
|
||||
@ -44,6 +45,22 @@
|
||||
|
||||
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 {
|
||||
|
||||
const unsigned BytesPerWord = sizeof(uintptr_t);
|
||||
|
657
src/compile.cpp
657
src/compile.cpp
@ -7,6 +7,11 @@ using namespace vm;
|
||||
|
||||
namespace {
|
||||
|
||||
const unsigned FrameThread = 8;
|
||||
const unsigned FrameMethod = 12;
|
||||
const unsigned FrameNext = 16;
|
||||
const unsigned FrameFootprint = 12;
|
||||
|
||||
class Rope {
|
||||
public:
|
||||
class Node {
|
||||
@ -21,6 +26,8 @@ class Rope {
|
||||
uint8_t data[Size];
|
||||
};
|
||||
|
||||
Rope() { }
|
||||
|
||||
Rope(System* s):
|
||||
s(s),
|
||||
front(0),
|
||||
@ -31,12 +38,16 @@ class Rope {
|
||||
|
||||
void append(uint8_t v) {
|
||||
if (position == Node::Size) {
|
||||
Node* n = new (s->allocate(sizeof(Node))) Node;
|
||||
if (front == 0) {
|
||||
front = rear = n;
|
||||
if (front == 0 or rear->next == 0) {
|
||||
Node* n = new (s->allocate(sizeof(Node))) Node;
|
||||
if (front == 0) {
|
||||
front = rear = n;
|
||||
} else {
|
||||
rear->next = n;
|
||||
rear = n;
|
||||
}
|
||||
} else {
|
||||
rear->next = n;
|
||||
rear = n;
|
||||
rear = rear->next;
|
||||
}
|
||||
position = 0;
|
||||
++ count;
|
||||
@ -45,6 +56,13 @@ class Rope {
|
||||
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() {
|
||||
return (count * Node::Size) + position;
|
||||
}
|
||||
@ -72,16 +90,233 @@ class Rope {
|
||||
unsigned position;
|
||||
};
|
||||
|
||||
class Assembler {
|
||||
class ArgumentList;
|
||||
|
||||
class MyThread: public Thread {
|
||||
public:
|
||||
Assembler(System* s):
|
||||
rope(s)
|
||||
MyThread(Machine* m, object javaThread, vm::Thread* parent):
|
||||
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:
|
||||
Compiler(System* s):
|
||||
Assembler(s)
|
||||
@ -92,9 +327,10 @@ class Compiler: private Assembler {
|
||||
mov(esp, ebp);
|
||||
|
||||
object code = methodCode(t, method);
|
||||
unsigned parameterFootprint = methodParameterFootprint(t, method) * 4;
|
||||
|
||||
// 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);) {
|
||||
switch (codeBody(t, code, i++)) {
|
||||
@ -135,50 +371,42 @@ class Compiler: private Assembler {
|
||||
|
||||
case iload_0:
|
||||
case fload_0:
|
||||
mov(ebp, 0, eax);
|
||||
push(eax);
|
||||
push(ebp, localOffset(0, parameterFootprint));
|
||||
break;
|
||||
|
||||
case iload_1:
|
||||
case fload_1:
|
||||
mov(ebp, -1, eax);
|
||||
push(eax);
|
||||
push(ebp, localOffset(1, parameterFootprint));
|
||||
break;
|
||||
|
||||
case iload_2:
|
||||
case fload_2:
|
||||
mov(ebp, -2, eax);
|
||||
push(eax);
|
||||
push(ebp, localOffset(2, parameterFootprint));
|
||||
break;
|
||||
|
||||
case iload_3:
|
||||
case fload_3:
|
||||
mov(ebp, -3, eax);
|
||||
push(eax);
|
||||
push(ebp, localOffset(3, parameterFootprint));
|
||||
break;
|
||||
|
||||
case istore_0:
|
||||
case fstore_0:
|
||||
pop(eax);
|
||||
mov(eax, ebp, 0);
|
||||
pop(ebp, localOffset(0, parameterFootprint));
|
||||
break;
|
||||
|
||||
case istore_1:
|
||||
case fstore_1:
|
||||
pop(eax);
|
||||
mov(eax, ebp, -1);
|
||||
pop(ebp, localOffset(1, parameterFootprint));
|
||||
break;
|
||||
|
||||
case istore_2:
|
||||
case fstore_2:
|
||||
pop(eax);
|
||||
mov(eax, ebp, -2);
|
||||
pop(ebp, localOffset(2, parameterFootprint));
|
||||
break;
|
||||
|
||||
case istore_3:
|
||||
case fstore_3:
|
||||
pop(eax);
|
||||
mov(eax, ebp, -3);
|
||||
pop(ebp, localOffset(3, parameterFootprint));
|
||||
break;
|
||||
|
||||
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
|
||||
compile(Thread* t, object method)
|
||||
invoke(Thread* thread, object method, ArgumentList* arguments)
|
||||
{
|
||||
Compiler c(t->vm->system);
|
||||
c.compile(t, method);
|
||||
MyThread* t = static_cast<MyThread*>(thread);
|
||||
|
||||
arguments->array[1] = reinterpret_cast<uintptr_t>(method);
|
||||
|
||||
object r = makeByteArray(t, c.rope.length(), false);
|
||||
c.rope.copyTo(&byteArrayBody(t, r, 0));
|
||||
const char* s = reinterpret_cast<const char*>
|
||||
(&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;
|
||||
}
|
||||
|
||||
class MyInvoker: public Invoker {
|
||||
class MyProcessor: public Processor {
|
||||
public:
|
||||
MyInvoker(System* s):
|
||||
s(s)
|
||||
MyProcessor(System* 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
|
||||
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));
|
||||
|
||||
uintptr_t a[methodParameterCount(t, method) * 2];
|
||||
ArgumentArray array(t, a, method, this_, spec, arguments);
|
||||
const char* spec = reinterpret_cast<char*>
|
||||
(&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
|
||||
@ -235,10 +787,16 @@ class MyInvoker: public Invoker {
|
||||
|
||||
assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0));
|
||||
|
||||
uintptr_t a[methodParameterCount(t, method) * 2];
|
||||
ArgumentArray array(t, a, method, this_, spec, indirectObjects, arguments);
|
||||
const char* spec = reinterpret_cast<char*>
|
||||
(&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
|
||||
@ -248,14 +806,17 @@ class MyInvoker: public Invoker {
|
||||
assert(t, t->state == Thread::ActiveState
|
||||
or t->state == Thread::ExclusiveState);
|
||||
|
||||
uintptr_t a[methodParameterCount(t, method) * 2];
|
||||
ArgumentArray array(t, a, method, this_, methodSpec, false, arguments);
|
||||
unsigned size = parameterCount(methodSpec) * 2;
|
||||
uintptr_t array[size];
|
||||
bool objectMask[size];
|
||||
ArgumentList list
|
||||
(t, array, objectMask, this_, methodSpec, false, arguments);
|
||||
|
||||
object method = resolveMethod(t, className, methodName, methodSpec);
|
||||
if (LIKELY(t->exception == 0)) {
|
||||
assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0));
|
||||
|
||||
return invoke(t, method, &array);
|
||||
return ::invoke(t, method, &list);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
@ -266,16 +827,18 @@ class MyInvoker: public Invoker {
|
||||
}
|
||||
|
||||
System* s;
|
||||
object stub;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace vm {
|
||||
|
||||
Invoker*
|
||||
makeInvoker(System* system)
|
||||
Processor*
|
||||
makeProcessor(System* system)
|
||||
{
|
||||
return new (system->allocate(sizeof(MyInvoker))) MyInvoker(system);
|
||||
return new (system->allocate(sizeof(MyProcessor))) MyProcessor(system);
|
||||
}
|
||||
|
||||
} // namespace vm
|
||||
|
||||
|
@ -8,6 +8,12 @@ using namespace vm;
|
||||
|
||||
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 {
|
||||
public:
|
||||
static const unsigned StackSizeInBytes = 64 * 1024;
|
||||
@ -3012,6 +3018,12 @@ class MyProcessor: public Processor {
|
||||
return new (s->allocate(sizeof(Thread))) Thread(m, javaThread, parent);
|
||||
}
|
||||
|
||||
virtual object
|
||||
methodStub(vm::Thread*)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void
|
||||
visitObjects(vm::Thread* vmt, Heap::Visitor* v)
|
||||
{
|
||||
@ -3112,8 +3124,7 @@ class MyProcessor: public Processor {
|
||||
|
||||
virtual object
|
||||
invokeList(vm::Thread* vmt, object method, object this_,
|
||||
bool indirectObjects,
|
||||
va_list arguments)
|
||||
bool indirectObjects, va_list arguments)
|
||||
{
|
||||
Thread* t = static_cast<Thread*>(vmt);
|
||||
|
||||
|
@ -917,6 +917,7 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
|
||||
methodName(t, method),
|
||||
methodSpec(t, method),
|
||||
methodClass(t, method),
|
||||
0,
|
||||
0);
|
||||
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, spec - 1),
|
||||
class_,
|
||||
code);
|
||||
code,
|
||||
(code ? t->m->processor->methodStub(t) : 0));
|
||||
PROTECT(t, method);
|
||||
|
||||
if (flags & ACC_STATIC) {
|
||||
|
@ -29,12 +29,6 @@ const bool DebugReferences = false;
|
||||
const uintptr_t HashTakenMark = 1;
|
||||
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 {
|
||||
VoidField,
|
||||
ByteField,
|
||||
@ -65,6 +59,7 @@ const unsigned PrimitiveFlag = 1 << 4;
|
||||
|
||||
// method flags:
|
||||
const unsigned ClassInitFlag = 1 << 0;
|
||||
const unsigned CompiledFlag = 1 << 1;
|
||||
|
||||
typedef Machine JavaVM;
|
||||
typedef Thread JNIEnv;
|
||||
|
@ -14,6 +14,9 @@ class Processor {
|
||||
virtual Thread*
|
||||
makeThread(Machine* m, object javaThread, Thread* parent) = 0;
|
||||
|
||||
virtual object
|
||||
methodStub(Thread* t) = 0;
|
||||
|
||||
virtual void
|
||||
visitObjects(Thread* t, Heap::Visitor* v) = 0;
|
||||
|
||||
|
@ -15,14 +15,10 @@
|
||||
|
||||
#define ACQUIRE(x) MutexResource MAKE_NAME(mutexResource_) (x)
|
||||
|
||||
#ifdef __i386__
|
||||
|
||||
extern "C" uint64_t
|
||||
cdeclCall(void* function, void* stack, unsigned stackSize,
|
||||
unsigned returnType);
|
||||
|
||||
namespace {
|
||||
|
||||
#ifdef __i386__
|
||||
|
||||
inline uint64_t
|
||||
dynamicCall(void* function, uintptr_t* arguments, uint8_t*,
|
||||
unsigned, unsigned argumentsSize, unsigned returnType)
|
||||
@ -30,16 +26,8 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t*,
|
||||
return cdeclCall(function, arguments, argumentsSize, returnType);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#elif defined __x86_64__
|
||||
|
||||
extern "C" uint64_t
|
||||
amd64Call(void* function, void* stack, unsigned stackSize,
|
||||
void* gprTable, void* sseTable, unsigned returnType);
|
||||
|
||||
namespace {
|
||||
|
||||
uint64_t
|
||||
dynamicCall(void* function, uint64_t* arguments, uint8_t* argumentTypes,
|
||||
unsigned argumentCount, unsigned, unsigned returnType)
|
||||
@ -80,12 +68,12 @@ dynamicCall(void* function, uint64_t* arguments, uint8_t* argumentTypes,
|
||||
(sseIndex ? sseTable : 0), returnType);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#else
|
||||
# error unsupported platform
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
using namespace vm;
|
||||
|
||||
namespace {
|
||||
|
@ -1035,6 +1035,15 @@ writeAccessor(Output* out, Object* member, Object* offset, bool unsafe = false)
|
||||
const char* typeName = memberTypeName(member);
|
||||
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(typeName);
|
||||
if (member->type != Object::Scalar and memberTypeObject(member)) {
|
||||
@ -1094,7 +1103,10 @@ writeAccessor(Output* out, Object* member, Object* offset, bool unsafe = false)
|
||||
} else {
|
||||
out->write("[");
|
||||
}
|
||||
writeOffset(out, offset);
|
||||
|
||||
out->write(capitalize(::typeName(memberOwner(member))));
|
||||
out->write(capitalize(memberName(member)));
|
||||
|
||||
if (member->type != Object::Scalar) {
|
||||
out->write(" + (i * ");
|
||||
unsigned elementSize = (memberTypeObject(member) ?
|
||||
|
@ -48,7 +48,12 @@
|
||||
(object name)
|
||||
(object spec)
|
||||
(object class)
|
||||
(object code))
|
||||
(object code)
|
||||
(object compiled))
|
||||
|
||||
(type compiled
|
||||
(nogc object method)
|
||||
(array uint8_t body))
|
||||
|
||||
(type nativeMethodData
|
||||
(void* function)
|
||||
|
Loading…
Reference in New Issue
Block a user