mirror of
https://github.com/corda/corda.git
synced 2025-01-19 11:16:54 +00:00
snapshot
This commit is contained in:
parent
c147ef4e5c
commit
069a760918
212
src/compile.cpp
212
src/compile.cpp
@ -28,11 +28,13 @@ class MyThread: public Thread {
|
||||
public:
|
||||
CallTrace(MyThread* t):
|
||||
t(t),
|
||||
ip(t->ip),
|
||||
base(t->base),
|
||||
stack(t->stack),
|
||||
next(t->trace)
|
||||
{
|
||||
t->trace = this;
|
||||
t->ip = 0;
|
||||
t->base = 0;
|
||||
t->stack = 0;
|
||||
}
|
||||
@ -40,10 +42,12 @@ class MyThread: public Thread {
|
||||
~CallTrace() {
|
||||
t->stack = stack;
|
||||
t->base = base;
|
||||
t->ip = ip;
|
||||
t->trace = next;
|
||||
}
|
||||
|
||||
MyThread* t;
|
||||
void* ip;
|
||||
void* base;
|
||||
void* stack;
|
||||
CallTrace* next;
|
||||
@ -51,12 +55,14 @@ class MyThread: public Thread {
|
||||
|
||||
MyThread(Machine* m, object javaThread, Thread* parent):
|
||||
Thread(m, javaThread, parent),
|
||||
ip(0),
|
||||
base(0),
|
||||
stack(0),
|
||||
trace(0),
|
||||
reference(0)
|
||||
{ }
|
||||
|
||||
void* ip;
|
||||
void* base;
|
||||
void* stack;
|
||||
CallTrace* trace;
|
||||
@ -116,7 +122,9 @@ class MyStackWalker: public Processor::StackWalker {
|
||||
base(t->base),
|
||||
stack(t->stack),
|
||||
trace(t->trace),
|
||||
node(stack ? findTraceNode(t, *static_cast<void**>(stack)) : 0),
|
||||
node(t->ip ? findTraceNode(t, t->ip) :
|
||||
(stack ? findTraceNode(t, *static_cast<void**>(stack)) :
|
||||
0)),
|
||||
nativeMethod(resolveNativeMethod(t, stack, node)),
|
||||
protector(this)
|
||||
{ }
|
||||
@ -663,9 +671,9 @@ class Frame {
|
||||
}
|
||||
}
|
||||
|
||||
void trace(Promise* returnAddress, object target, bool virtualCall) {
|
||||
void trace(Promise* address, object target, bool virtualCall) {
|
||||
TraceElement* e = new (traceLog->allocate(traceSizeInBytes(t, method)))
|
||||
TraceElement(target, returnAddress, virtualCall);
|
||||
TraceElement(target, address, virtualCall);
|
||||
memcpy(e->map, map, mapSizeInWords(t, method) * BytesPerWord);
|
||||
}
|
||||
|
||||
@ -947,21 +955,38 @@ class Frame {
|
||||
MyProtector protector;
|
||||
};
|
||||
|
||||
class MyNullHandler: public Compiler::NullHandler {
|
||||
public:
|
||||
MyNullHandler(Frame* frame): frame(frame) {
|
||||
frame->c->setNullHandler(this);
|
||||
}
|
||||
|
||||
virtual void handleMaybeNull(Promise* address) {
|
||||
frame->trace(address, 0, false);
|
||||
}
|
||||
|
||||
Frame* frame;
|
||||
};
|
||||
|
||||
void NO_RETURN
|
||||
unwind(MyThread* t)
|
||||
{
|
||||
void* ip = t->ip;
|
||||
void* base = t->base;
|
||||
void** stack = static_cast<void**>(t->stack);
|
||||
if (ip == 0) {
|
||||
ip = *stack;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
void* returnAddress = *stack;
|
||||
object node = findTraceNode(t, returnAddress);
|
||||
object node = findTraceNode(t, ip);
|
||||
if (node) {
|
||||
object method = traceNodeMethod(t, node);
|
||||
uint8_t* compiled = reinterpret_cast<uint8_t*>
|
||||
(&singletonValue(t, methodCompiled(t, method), 0));
|
||||
|
||||
ExceptionHandler* handler = findExceptionHandler
|
||||
(t, method, difference(returnAddress, compiled));
|
||||
(t, method, difference(ip, compiled));
|
||||
|
||||
if (handler) {
|
||||
unsigned parameterFootprint = methodParameterFootprint(t, method);
|
||||
@ -987,20 +1012,26 @@ unwind(MyThread* t)
|
||||
}
|
||||
|
||||
stack = static_cast<void**>(base) + 1;
|
||||
ip = *stack;
|
||||
base = *static_cast<void**>(base);
|
||||
}
|
||||
} else {
|
||||
vmJump(returnAddress, base, stack + 1, 0);
|
||||
vmJump(ip, base, stack + 1, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void*
|
||||
findInterfaceMethodFromInstance(Thread* t, object method, object instance)
|
||||
findInterfaceMethodFromInstance(MyThread* t, object method, object instance)
|
||||
{
|
||||
return &singletonValue
|
||||
(t, methodCompiled
|
||||
(t, findInterfaceMethod(t, method, objectClass(t, instance))), 0);
|
||||
if (instance) {
|
||||
return &singletonValue
|
||||
(t, methodCompiled
|
||||
(t, findInterfaceMethod(t, method, objectClass(t, instance))), 0);
|
||||
} else {
|
||||
t->exception = makeNullPointerException(t);
|
||||
unwind(t);
|
||||
}
|
||||
}
|
||||
|
||||
intptr_t
|
||||
@ -1240,15 +1271,36 @@ lookUpAddress(int32_t key, uintptr_t* start, int32_t count,
|
||||
}
|
||||
|
||||
void
|
||||
acquireMonitorForObject(Thread* t, object o)
|
||||
setMaybeNull(MyThread* t, object o, unsigned offset, object value)
|
||||
{
|
||||
acquire(t, o);
|
||||
if (o) {
|
||||
set(t, o, offset, value);
|
||||
} else {
|
||||
t->exception = makeNullPointerException(t);
|
||||
unwind(t);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
releaseMonitorForObject(Thread* t, object o)
|
||||
acquireMonitorForObject(MyThread* t, object o)
|
||||
{
|
||||
release(t, o);
|
||||
if (o) {
|
||||
acquire(t, o);
|
||||
} else {
|
||||
t->exception = makeNullPointerException(t);
|
||||
unwind(t);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
releaseMonitorForObject(MyThread* t, object o)
|
||||
{
|
||||
if (o) {
|
||||
release(t, o);
|
||||
} else {
|
||||
t->exception = makeNullPointerException(t);
|
||||
unwind(t);
|
||||
}
|
||||
}
|
||||
|
||||
object
|
||||
@ -1465,29 +1517,30 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
|
||||
switch (instruction) {
|
||||
case aaload:
|
||||
frame->pushObject(c->memory(array, ArrayBody, index, BytesPerWord));
|
||||
frame->pushObject
|
||||
(c->memory(array, ArrayBody, index, BytesPerWord, true));
|
||||
break;
|
||||
|
||||
case faload:
|
||||
case iaload:
|
||||
frame->pushInt4(c->memory(array, ArrayBody, index, 4));
|
||||
frame->pushInt4(c->memory(array, ArrayBody, index, 4, true));
|
||||
break;
|
||||
|
||||
case baload:
|
||||
frame->pushInt1(c->memory(array, ArrayBody, index, 1));
|
||||
frame->pushInt1(c->memory(array, ArrayBody, index, 1, true));
|
||||
break;
|
||||
|
||||
case caload:
|
||||
frame->pushInt2z(c->memory(array, ArrayBody, index, 2));
|
||||
frame->pushInt2z(c->memory(array, ArrayBody, index, 2, true));
|
||||
break;
|
||||
|
||||
case daload:
|
||||
case laload:
|
||||
frame->pushLong(c->memory(array, ArrayBody, index, 8));
|
||||
frame->pushLong(c->memory(array, ArrayBody, index, 8, true));
|
||||
break;
|
||||
|
||||
case saload:
|
||||
frame->pushInt2(c->memory(array, ArrayBody, index, 2));
|
||||
frame->pushInt2(c->memory(array, ArrayBody, index, 2, true));
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1536,8 +1589,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
c->shl4(c->constant(log(BytesPerWord)), index);
|
||||
c->add4(c->constant(ArrayBody), index);
|
||||
|
||||
Promise* returnAddress = c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(set)),
|
||||
Promise* returnAddress = c->indirectCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(setMaybeNull)),
|
||||
4, c->thread(), array, index, value);
|
||||
|
||||
frame->trace(returnAddress, 0, false);
|
||||
@ -1545,21 +1598,21 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
|
||||
case fastore:
|
||||
case iastore:
|
||||
c->mov4(value, c->memory(array, ArrayBody, index, 4));
|
||||
c->mov4(value, c->memory(array, ArrayBody, index, 4, true));
|
||||
break;
|
||||
|
||||
case bastore:
|
||||
c->mov1(value, c->memory(array, ArrayBody, index, 1));
|
||||
c->mov1(value, c->memory(array, ArrayBody, index, 1, true));
|
||||
break;
|
||||
|
||||
case castore:
|
||||
case sastore:
|
||||
c->mov2(value, c->memory(array, ArrayBody, index, 2));
|
||||
c->mov2(value, c->memory(array, ArrayBody, index, 2, true));
|
||||
break;
|
||||
|
||||
case dastore:
|
||||
case lastore:
|
||||
c->mov8(value, c->memory(array, ArrayBody, index, 8));
|
||||
c->mov8(value, c->memory(array, ArrayBody, index, 8, true));
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1638,7 +1691,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
|
||||
case arraylength: {
|
||||
Operand* array = frame->popObject();
|
||||
frame->pushInt4(c->memory(array, ArrayLength));
|
||||
frame->pushInt4(c->memory(array, ArrayLength, 0, 1, true));
|
||||
c->release(array);
|
||||
} break;
|
||||
|
||||
@ -2055,32 +2108,40 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
table = frame->popObject();
|
||||
}
|
||||
|
||||
bool maybeNull = (instruction == getfield);
|
||||
|
||||
switch (fieldCode(t, field)) {
|
||||
case ByteField:
|
||||
case BooleanField:
|
||||
frame->pushInt1(c->memory(table, fieldOffset(t, field)));
|
||||
frame->pushInt1
|
||||
(c->memory(table, fieldOffset(t, field), 0, 1, maybeNull));
|
||||
break;
|
||||
|
||||
case CharField:
|
||||
frame->pushInt2z(c->memory(table, fieldOffset(t, field)));
|
||||
frame->pushInt2z
|
||||
(c->memory(table, fieldOffset(t, field), 0, 1, maybeNull));
|
||||
break;
|
||||
|
||||
case ShortField:
|
||||
frame->pushInt2(c->memory(table, fieldOffset(t, field)));
|
||||
frame->pushInt2
|
||||
(c->memory(table, fieldOffset(t, field), 0, 1, maybeNull));
|
||||
break;
|
||||
|
||||
case FloatField:
|
||||
case IntField:
|
||||
frame->pushInt4(c->memory(table, fieldOffset(t, field)));
|
||||
frame->pushInt4
|
||||
(c->memory(table, fieldOffset(t, field), 0, 1, maybeNull));
|
||||
break;
|
||||
|
||||
case DoubleField:
|
||||
case LongField:
|
||||
frame->pushLong(c->memory(table, fieldOffset(t, field)));
|
||||
frame->pushLong
|
||||
(c->memory(table, fieldOffset(t, field), 0, 1, maybeNull));
|
||||
break;
|
||||
|
||||
case ObjectField:
|
||||
frame->pushObject(c->memory(table, fieldOffset(t, field)));
|
||||
frame->pushObject
|
||||
(c->memory(table, fieldOffset(t, field), 0, 1, maybeNull));
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -2392,7 +2453,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
|
||||
unsigned instance = parameterFootprint - 1;
|
||||
|
||||
c->directCall
|
||||
c->indirectCall
|
||||
(c->constant
|
||||
(reinterpret_cast<intptr_t>(findInterfaceMethodFromInstance)),
|
||||
3, c->thread(), frame->append(target),
|
||||
@ -2455,7 +2516,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
mov(c, c->memory(instance), class_);
|
||||
and_(c, c->constant(PointerMask), class_);
|
||||
|
||||
c->call(c->memory(class_, offset));
|
||||
c->call(c->memory(class_, offset, 0, 1, true));
|
||||
|
||||
frame->trace(c->machineIp(), target, true);
|
||||
|
||||
@ -3022,31 +3083,43 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||
table = frame->popObject();
|
||||
}
|
||||
|
||||
bool maybeNull = (instruction == getstatic);
|
||||
|
||||
switch (fieldCode(t, field)) {
|
||||
case ByteField:
|
||||
case BooleanField:
|
||||
c->mov1(value, c->memory(table, fieldOffset(t, field)));
|
||||
c->mov1(value, c->memory
|
||||
(table, fieldOffset(t, field), 0, 1, maybeNull));
|
||||
break;
|
||||
|
||||
case CharField:
|
||||
case ShortField:
|
||||
c->mov2(value, c->memory(table, fieldOffset(t, field)));
|
||||
c->mov2(value, c->memory
|
||||
(table, fieldOffset(t, field), 0, 1, maybeNull));
|
||||
break;
|
||||
|
||||
case FloatField:
|
||||
case IntField:
|
||||
c->mov4(value, c->memory(table, fieldOffset(t, field)));
|
||||
c->mov4(value, c->memory
|
||||
(table, fieldOffset(t, field), 0, 1, maybeNull));
|
||||
break;
|
||||
|
||||
case DoubleField:
|
||||
case LongField:
|
||||
c->mov8(value, c->memory(table, fieldOffset(t, field)));
|
||||
c->mov8(value, c->memory
|
||||
(table, fieldOffset(t, field), 0, 1, maybeNull));
|
||||
break;
|
||||
|
||||
case ObjectField:
|
||||
c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(set)),
|
||||
4, c->thread(), table, c->constant(fieldOffset(t, field)), value);
|
||||
if (maybeNull) {
|
||||
c->indirectCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(setMaybeNull)),
|
||||
4, c->thread(), table, c->constant(fieldOffset(t, field)), value);
|
||||
} else {
|
||||
c->directCall
|
||||
(c->constant(reinterpret_cast<intptr_t>(set)),
|
||||
4, c->thread(), table, c->constant(fieldOffset(t, field)), value);
|
||||
}
|
||||
break;
|
||||
|
||||
default: abort(t);
|
||||
@ -3348,6 +3421,7 @@ compile(MyThread* t, Compiler* c, object method)
|
||||
Vector traceLog(t->m->system, 1024);
|
||||
uintptr_t map[Frame::mapSizeInWords(t, method)];
|
||||
Frame frame(t, c, method, map, &objectPool, &traceLog);
|
||||
MyNullHandler nullHandler(&frame);
|
||||
|
||||
handleEntrance(t, &frame);
|
||||
|
||||
@ -3640,12 +3714,17 @@ visitStackAndLocals(MyThread* t, Heap::Visitor* v, void* base, object node)
|
||||
void
|
||||
visitStack(MyThread* t, Heap::Visitor* v)
|
||||
{
|
||||
void* ip = t->ip;
|
||||
void* base = t->base;
|
||||
void** stack = static_cast<void**>(t->stack);
|
||||
if (ip == 0) {
|
||||
ip = *stack;
|
||||
}
|
||||
|
||||
MyThread::CallTrace* trace = t->trace;
|
||||
|
||||
while (stack) {
|
||||
object node = findTraceNode(t, *stack);
|
||||
object node = findTraceNode(t, ip);
|
||||
if (node) {
|
||||
PROTECT(t, node);
|
||||
|
||||
@ -3661,6 +3740,7 @@ visitStack(MyThread* t, Heap::Visitor* v)
|
||||
visitStackAndLocals(t, v, base, node);
|
||||
|
||||
stack = static_cast<void**>(base) + 1;
|
||||
ip = *stack;
|
||||
base = *static_cast<void**>(base);
|
||||
} else if (trace) {
|
||||
base = trace->base;
|
||||
@ -3828,11 +3908,14 @@ invoke(Thread* thread, object method, ArgumentList* arguments)
|
||||
unsigned returnType = fieldType(t, returnCode);
|
||||
|
||||
Reference* reference = t->reference;
|
||||
MyThread::CallTrace trace(t);
|
||||
uint64_t result;
|
||||
|
||||
uint64_t result = vmInvoke
|
||||
(t, &singletonValue(t, methodCompiled(t, method), 0), arguments->array,
|
||||
arguments->position, returnType);
|
||||
{ MyThread::CallTrace trace(t);
|
||||
|
||||
result = vmInvoke
|
||||
(t, &singletonValue(t, methodCompiled(t, method), 0), arguments->array,
|
||||
arguments->position, returnType);
|
||||
}
|
||||
|
||||
while (t->reference != reference) {
|
||||
dispose(t, t->reference);
|
||||
@ -3869,6 +3952,27 @@ invoke(Thread* thread, object method, ArgumentList* arguments)
|
||||
return r;
|
||||
}
|
||||
|
||||
class SegFaultHandler: public System::SignalHandler {
|
||||
public:
|
||||
SegFaultHandler(): m(0) { }
|
||||
|
||||
virtual bool handleSignal(void* ip, void* base, void* stack) {
|
||||
MyThread* t = static_cast<MyThread*>(m->localThread->get());
|
||||
object node = findTraceNode(t, ip);
|
||||
if (node) {
|
||||
t->ip = ip;
|
||||
t->base = base;
|
||||
t->stack = stack;
|
||||
t->exception = makeNullPointerException(t);
|
||||
unwind(t);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Machine* m;
|
||||
};
|
||||
|
||||
class MyProcessor: public Processor {
|
||||
public:
|
||||
MyProcessor(System* s):
|
||||
@ -4126,8 +4230,11 @@ class MyProcessor: public Processor {
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void dispose(Thread* thread) {
|
||||
MyThread* t = static_cast<MyThread*>(thread);
|
||||
virtual void dispose(Thread* vmt) {
|
||||
MyThread* t = static_cast<MyThread*>(vmt);
|
||||
|
||||
t->m->system->handleSegFault(0);
|
||||
|
||||
while (t->reference) {
|
||||
vm::dispose(t, t->reference);
|
||||
}
|
||||
@ -4147,6 +4254,7 @@ class MyProcessor: public Processor {
|
||||
object addressTable;
|
||||
unsigned addressCount;
|
||||
uint8_t* indirectCaller;
|
||||
SegFaultHandler segFaultHandler;
|
||||
};
|
||||
|
||||
MyProcessor*
|
||||
@ -4176,6 +4284,10 @@ processor(MyThread* t)
|
||||
|
||||
c->dispose();
|
||||
}
|
||||
|
||||
p->segFaultHandler.m = t->m;
|
||||
expect(t, t->m->system->success
|
||||
(t->m->system->handleSegFault(&(p->segFaultHandler))));
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
146
src/compiler.cpp
146
src/compiler.cpp
@ -146,7 +146,8 @@ class Context {
|
||||
indirectCaller(reinterpret_cast<intptr_t>(indirectCaller)),
|
||||
segmentTable(0),
|
||||
reserved(0),
|
||||
codeLength(-1)
|
||||
codeLength(-1),
|
||||
nullHandler(0)
|
||||
{
|
||||
plan.appendAddress(new (zone.allocate(sizeof(Segment))) Segment
|
||||
(-1, new (zone.allocate(sizeof(Event))) Event(0)));
|
||||
@ -173,6 +174,7 @@ class Context {
|
||||
Segment** segmentTable;
|
||||
unsigned reserved;
|
||||
int codeLength;
|
||||
Compiler::NullHandler* nullHandler;
|
||||
RegisterData registers[RegisterCount];
|
||||
};
|
||||
|
||||
@ -311,7 +313,7 @@ register_(Context* c, Register = NoRegister, Register = NoRegister);
|
||||
|
||||
MemoryOperand*
|
||||
memory(Context* c, MyOperand* base, int displacement,
|
||||
MyOperand* index, unsigned scale);
|
||||
MyOperand* index, unsigned scale, bool maybeNull);
|
||||
|
||||
class MyOperand: public Operand {
|
||||
public:
|
||||
@ -615,11 +617,12 @@ class AbsoluteOperand: public MyOperand {
|
||||
class MemoryOperand: public MyOperand {
|
||||
public:
|
||||
MemoryOperand(MyOperand* base, int displacement, MyOperand* index,
|
||||
unsigned scale):
|
||||
unsigned scale, bool maybeNull):
|
||||
base(base),
|
||||
displacement(displacement),
|
||||
index(index),
|
||||
scale(scale)
|
||||
scale(scale),
|
||||
maybeNull(maybeNull)
|
||||
{ }
|
||||
|
||||
virtual Register asRegister(Context*);
|
||||
@ -649,6 +652,20 @@ class MemoryOperand: public MyOperand {
|
||||
int displacement;
|
||||
MyOperand* index;
|
||||
unsigned scale;
|
||||
bool maybeNull;
|
||||
};
|
||||
|
||||
class CodePromiseTask: public Task {
|
||||
public:
|
||||
CodePromiseTask(CodePromise* promise, Task* next):
|
||||
Task(next), promise(promise)
|
||||
{ }
|
||||
|
||||
virtual void run(Context* c UNUSED, unsigned offset) {
|
||||
promise->offset = offset;
|
||||
}
|
||||
|
||||
CodePromise* promise;
|
||||
};
|
||||
|
||||
AddressOperand*
|
||||
@ -687,10 +704,10 @@ register_(Context* c, Register v, Register h)
|
||||
|
||||
MemoryOperand*
|
||||
memory(Context* c, MyOperand* base, int displacement,
|
||||
MyOperand* index, unsigned scale)
|
||||
MyOperand* index, unsigned scale, bool maybeNull)
|
||||
{
|
||||
return new (c->zone.allocate(sizeof(MemoryOperand)))
|
||||
MemoryOperand(base, displacement, index, scale);
|
||||
MemoryOperand(base, displacement, index, scale, maybeNull);
|
||||
}
|
||||
|
||||
RegisterOperand*
|
||||
@ -721,6 +738,29 @@ currentSegment(Context* c)
|
||||
return s;
|
||||
}
|
||||
|
||||
Promise*
|
||||
machineIp(Context* c)
|
||||
{
|
||||
CodePromise* p = new (c->zone.allocate(sizeof(CodePromise))) CodePromise();
|
||||
|
||||
Segment* s = currentSegment(c);
|
||||
s->event->task = new (c->zone.allocate(sizeof(CodePromiseTask)))
|
||||
CodePromiseTask(p, s->event->task);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
handleMaybeNull(Context* c)
|
||||
{
|
||||
if (c->codeLength >= 0) {
|
||||
c->nullHandler->handleMaybeNull
|
||||
(new (c->zone.allocate(sizeof(ResolvedPromise)))
|
||||
ResolvedPromise
|
||||
(reinterpret_cast<intptr_t>(c->code.data + c->code.length)));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
apply(Context* c, MyOperand::Operation op)
|
||||
{
|
||||
@ -990,7 +1030,8 @@ pushed(Context* c, MyStack* stack)
|
||||
int index = (stack ? stack->index + 1 : 0);
|
||||
|
||||
MyOperand* value = memory
|
||||
(c, register_(c, rbp), - (c->reserved + index + 1) * BytesPerWord, 0, 1);
|
||||
(c, register_(c, rbp), - (c->reserved + index + 1) * BytesPerWord, 0, 1,
|
||||
false);
|
||||
|
||||
stack = new (c->zone.allocate(sizeof(MyStack))) MyStack(value, index, stack);
|
||||
|
||||
@ -1426,6 +1467,8 @@ void
|
||||
RegisterOperand::accept(Context* c, Operation operation,
|
||||
MemoryOperand* operand)
|
||||
{
|
||||
assert(c, not operand->maybeNull);
|
||||
|
||||
switch (operation) {
|
||||
case cmp4:
|
||||
case cmp8:
|
||||
@ -1442,7 +1485,7 @@ RegisterOperand::accept(Context* c, Operation operation,
|
||||
register_(c, high(c))->accept
|
||||
(c, mov, memory
|
||||
(c, operand->base, operand->displacement + BytesPerWord,
|
||||
operand->index, operand->scale));
|
||||
operand->index, operand->scale, false));
|
||||
} else if (BytesPerWord == 8 and operation == mov4) {
|
||||
encode(c, 0x63, value(c), operand, true);
|
||||
} else {
|
||||
@ -1500,7 +1543,7 @@ RegisterOperand::accept(Context* c, Operation operation,
|
||||
|
||||
RegisterOperand* tmp = temporary(c);
|
||||
tmp->accept(c, mov, ::value(c, operand));
|
||||
accept(c, cmp, memory(c, tmp, 0, 0, 1));
|
||||
accept(c, cmp, memory(c, tmp, 0, 0, 1, false));
|
||||
tmp->release(c);
|
||||
} break;
|
||||
|
||||
@ -1509,7 +1552,7 @@ RegisterOperand::accept(Context* c, Operation operation,
|
||||
assert(c, BytesPerWord == 8 or operation == mov4); // todo
|
||||
|
||||
accept(c, mov, ::value(c, operand));
|
||||
accept(c, mov, memory(c, this, 0, 0, 1));
|
||||
accept(c, mov, memory(c, this, 0, 0, 1, false));
|
||||
} break;
|
||||
|
||||
default: abort(c);
|
||||
@ -1682,7 +1725,7 @@ absoluteApply(Context* c, MyOperand::Operation operation,
|
||||
{
|
||||
RegisterOperand* tmp = temporary(c);
|
||||
tmp->accept(c, MyOperand::mov, value(c, operand));
|
||||
memory(c, tmp, 0, 0, 1)->apply(c, operation);
|
||||
memory(c, tmp, 0, 0, 1, false)->apply(c, operation);
|
||||
tmp->release(c);
|
||||
}
|
||||
|
||||
@ -1713,22 +1756,28 @@ MemoryOperand::apply(Context* c, Operation operation)
|
||||
{
|
||||
switch (operation) {
|
||||
case call:
|
||||
if (maybeNull) handleMaybeNull(c);
|
||||
|
||||
encode(c, 0xff, 2, this, false);
|
||||
break;
|
||||
|
||||
case jmp:
|
||||
if (maybeNull) handleMaybeNull(c);
|
||||
|
||||
encode(c, 0xff, 4, this, false);
|
||||
break;
|
||||
|
||||
case neg4:
|
||||
case neg8:
|
||||
assert(c, not maybeNull);
|
||||
|
||||
if (BytesPerWord == 4 and operation == neg8) {
|
||||
RegisterOperand* ax = temporary(c, rax);
|
||||
RegisterOperand* dx = temporary(c, rdx);
|
||||
|
||||
MemoryOperand* low = this;
|
||||
MemoryOperand* high = memory
|
||||
(c, base, displacement + BytesPerWord, index, scale);
|
||||
(c, base, displacement + BytesPerWord, index, scale, false);
|
||||
|
||||
ax->accept(c, mov, low);
|
||||
dx->accept(c, mov, high);
|
||||
@ -1749,10 +1798,12 @@ MemoryOperand::apply(Context* c, Operation operation)
|
||||
|
||||
case pop4:
|
||||
case pop8:
|
||||
assert(c, not maybeNull);
|
||||
|
||||
if (BytesPerWord == 4 and operation == pop8) {
|
||||
MemoryOperand* low = this;
|
||||
MemoryOperand* high = memory
|
||||
(c, base, displacement + BytesPerWord, index, scale);
|
||||
(c, base, displacement + BytesPerWord, index, scale, false);
|
||||
|
||||
low->apply(c, pop);
|
||||
high->apply(c, pop);
|
||||
@ -1765,10 +1816,13 @@ MemoryOperand::apply(Context* c, Operation operation)
|
||||
|
||||
case push4:
|
||||
case push8:
|
||||
assert(c, not maybeNull);
|
||||
|
||||
if (BytesPerWord == 4 and operation == push8) {
|
||||
MemoryOperand* low = this;
|
||||
MemoryOperand* low = memory
|
||||
(c, base, displacement, index, scale, false);
|
||||
MemoryOperand* high = memory
|
||||
(c, base, displacement + BytesPerWord, index, scale);
|
||||
(c, base, displacement + BytesPerWord, index, scale, maybeNull);
|
||||
|
||||
high->apply(c, push);
|
||||
low->apply(c, push);
|
||||
@ -1785,6 +1839,8 @@ MemoryOperand::apply(Context* c, Operation operation)
|
||||
case push1:
|
||||
case push2:
|
||||
case push2z: {
|
||||
assert(c, not maybeNull);
|
||||
|
||||
RegisterOperand* tmp = temporary(c);
|
||||
switch (operation) {
|
||||
case push1:
|
||||
@ -1813,6 +1869,8 @@ void
|
||||
MemoryOperand::accept(Context* c, Operation operation,
|
||||
RegisterOperand* operand)
|
||||
{
|
||||
assert(c, not maybeNull);
|
||||
|
||||
switch (operation) {
|
||||
case and4:
|
||||
case and8:
|
||||
@ -1831,7 +1889,7 @@ MemoryOperand::accept(Context* c, Operation operation,
|
||||
dx->accept(c, mov, register_(c, operand->high(c)));
|
||||
|
||||
accept(c, add, ax);
|
||||
memory(c, base, displacement + BytesPerWord, index, scale)->accept
|
||||
memory(c, base, displacement + BytesPerWord, index, scale, false)->accept
|
||||
(c, addc, dx);
|
||||
|
||||
ax->release(c);
|
||||
@ -1880,7 +1938,7 @@ MemoryOperand::accept(Context* c, Operation operation,
|
||||
if (BytesPerWord == 4 and operation == mov8) {
|
||||
accept(c, mov, operand);
|
||||
|
||||
memory(c, base, displacement + BytesPerWord, index, scale)->accept
|
||||
memory(c, base, displacement + BytesPerWord, index, scale, false)->accept
|
||||
(c, mov, register_(c, operand->high(c)));
|
||||
} else if (BytesPerWord == 8 and operation == mov4) {
|
||||
encode(c, 0x89, operand->value(c), this, false);
|
||||
@ -1929,7 +1987,7 @@ MemoryOperand::accept(Context* c, Operation operation,
|
||||
|
||||
MemoryOperand* lowDst = this;
|
||||
MemoryOperand* highDst = memory
|
||||
(c, base, displacement + BytesPerWord, index, scale);
|
||||
(c, base, displacement + BytesPerWord, index, scale, false);
|
||||
|
||||
tmp->accept(c, mov, highSrc);
|
||||
tmp->accept(c, mul, lowDst);
|
||||
@ -2008,9 +2066,11 @@ MemoryOperand::accept(Context* c, Operation operation,
|
||||
tmp->accept(c, mov, this);
|
||||
// shld
|
||||
encode2(c, 0x0fa5, tmp->value(c), memory
|
||||
(c, base, displacement + BytesPerWord, index, scale), false);
|
||||
(c, base, displacement + BytesPerWord, index, scale, maybeNull),
|
||||
false);
|
||||
// shl
|
||||
encode(c, 0xd3, 4, this, false);
|
||||
encode(c, 0xd3, 4, memory(c, base, displacement, index, scale, false),
|
||||
false);
|
||||
|
||||
tmp->release(c);
|
||||
cx->release(c);
|
||||
@ -2034,7 +2094,8 @@ MemoryOperand::accept(Context* c, Operation operation,
|
||||
encode2(c, 0x0fad, tmp->value(c), this, false);
|
||||
// sar
|
||||
encode(c, 0xd3, 5, memory
|
||||
(c, base, displacement + BytesPerWord, index, scale), false);
|
||||
(c, base, displacement + BytesPerWord, index, scale, false),
|
||||
false);
|
||||
|
||||
tmp->release(c);
|
||||
cx->release(c);
|
||||
@ -2058,7 +2119,8 @@ MemoryOperand::accept(Context* c, Operation operation,
|
||||
encode2(c, 0x0fad, tmp->value(c), this, false);
|
||||
// shr
|
||||
encode(c, 0xd3, 7, memory
|
||||
(c, base, displacement + BytesPerWord, index, scale), false);
|
||||
(c, base, displacement + BytesPerWord, index, scale, false),
|
||||
false);
|
||||
|
||||
tmp->release(c);
|
||||
cx->release(c);
|
||||
@ -2080,7 +2142,7 @@ MemoryOperand::accept(Context* c, Operation operation,
|
||||
dx->accept(c, mov, register_(c, operand->high(c)));
|
||||
|
||||
accept(c, sub, ax);
|
||||
memory(c, base, displacement + BytesPerWord, index, scale)->accept
|
||||
memory(c, base, displacement + BytesPerWord, index, scale, false)->accept
|
||||
(c, subb, dx);
|
||||
|
||||
ax->release(c);
|
||||
@ -2109,6 +2171,8 @@ void
|
||||
MemoryOperand::accept(Context* c, Operation operation,
|
||||
ImmediateOperand* operand)
|
||||
{
|
||||
assert(c, not maybeNull);
|
||||
|
||||
switch (operation) {
|
||||
case add4:
|
||||
case add8: {
|
||||
@ -2143,6 +2207,8 @@ void
|
||||
MemoryOperand::accept(Context* c, Operation operation,
|
||||
AbsoluteOperand* operand)
|
||||
{
|
||||
assert(c, not maybeNull);
|
||||
|
||||
RegisterOperand* tmp = temporary(c);
|
||||
|
||||
tmp->accept(c, mov, operand);
|
||||
@ -2155,6 +2221,9 @@ void
|
||||
MemoryOperand::accept(Context* c, Operation operation,
|
||||
MemoryOperand* operand)
|
||||
{
|
||||
assert(c, not maybeNull);
|
||||
assert(c, not operand->maybeNull);
|
||||
|
||||
switch (operation) {
|
||||
case mov1ToW:
|
||||
case mov2ToW:
|
||||
@ -2249,33 +2318,19 @@ writeCode(Context* c)
|
||||
c->codeLength = pad(c->code.length());
|
||||
}
|
||||
|
||||
class CodePromiseTask: public Task {
|
||||
public:
|
||||
CodePromiseTask(CodePromise* promise, Task* next):
|
||||
Task(next), promise(promise)
|
||||
{ }
|
||||
|
||||
virtual void run(Context* c UNUSED, unsigned offset) {
|
||||
promise->offset = offset;
|
||||
}
|
||||
|
||||
CodePromise* promise;
|
||||
};
|
||||
|
||||
class MyCompiler: public Compiler {
|
||||
public:
|
||||
MyCompiler(System* s, void* indirectCaller):
|
||||
c(s, indirectCaller)
|
||||
{ }
|
||||
|
||||
virtual void setNullHandler(NullHandler* nullHandler) {
|
||||
assert(&c, c.nullHandler == 0);
|
||||
c.nullHandler = nullHandler;
|
||||
}
|
||||
|
||||
virtual Promise* machineIp() {
|
||||
CodePromise* p = new (c.zone.allocate(sizeof(CodePromise))) CodePromise();
|
||||
|
||||
Segment* s = currentSegment(&c);
|
||||
s->event->task = new (c.zone.allocate(sizeof(CodePromiseTask)))
|
||||
CodePromiseTask(p, s->event->task);
|
||||
|
||||
return p;
|
||||
return ::machineIp(&c);
|
||||
}
|
||||
|
||||
virtual Promise* machineIp(unsigned logicalIp) {
|
||||
@ -2662,10 +2717,11 @@ class MyCompiler: public Compiler {
|
||||
}
|
||||
|
||||
virtual Operand* memory(Operand* base, int displacement,
|
||||
Operand* index, unsigned scale)
|
||||
Operand* index, unsigned scale,
|
||||
bool maybeNull)
|
||||
{
|
||||
return ::memory(&c, static_cast<MyOperand*>(base), displacement,
|
||||
static_cast<MyOperand*>(index), scale);
|
||||
static_cast<MyOperand*>(index), scale, maybeNull);
|
||||
}
|
||||
|
||||
virtual void prologue() {
|
||||
|
@ -20,8 +20,17 @@ class Promise {
|
||||
|
||||
class Compiler {
|
||||
public:
|
||||
class NullHandler {
|
||||
public:
|
||||
virtual ~NullHandler() { }
|
||||
|
||||
virtual void handleMaybeNull(Promise* address) = 0;
|
||||
};
|
||||
|
||||
virtual ~Compiler() { }
|
||||
|
||||
virtual void setNullHandler(NullHandler*) = 0;
|
||||
|
||||
virtual Promise* machineIp() = 0;
|
||||
virtual Promise* machineIp(unsigned logicalIp) = 0;
|
||||
|
||||
@ -31,8 +40,11 @@ class Compiler {
|
||||
virtual Operand* constant(int64_t) = 0;
|
||||
virtual Operand* promiseConstant(Promise*) = 0;
|
||||
virtual Operand* absolute(Promise*) = 0;
|
||||
virtual Operand* memory(Operand* base, int displacement = 0,
|
||||
Operand* index = 0, unsigned scale = 1) = 0;
|
||||
virtual Operand* memory(Operand* base,
|
||||
int displacement = 0,
|
||||
Operand* index = 0,
|
||||
unsigned scale = 1,
|
||||
bool maybeNull = false) = 0;
|
||||
|
||||
virtual Operand* stack() = 0;
|
||||
virtual Operand* base() = 0;
|
||||
|
@ -20,6 +20,9 @@ using namespace vm;
|
||||
|
||||
namespace {
|
||||
|
||||
System::SignalHandler* segFaultHandler = 0;
|
||||
struct sigaction oldSegFaultHandler;
|
||||
|
||||
class MutexResource {
|
||||
public:
|
||||
MutexResource(pthread_mutex_t& m): m(&m) {
|
||||
@ -36,10 +39,38 @@ class MutexResource {
|
||||
|
||||
const int InterruptSignal = SIGUSR2;
|
||||
|
||||
#ifdef __x86_64__
|
||||
const int IpRegister = REG_RIP;
|
||||
const int BaseRegister = REG_RBP;
|
||||
const int StackRegister = REG_RSP;
|
||||
#elif defined __i386__
|
||||
const int IpRegister = REG_EIP;
|
||||
const int BaseRegister = REG_EBP;
|
||||
const int StackRegister = REG_ESP;
|
||||
#else
|
||||
# error unsupported architecture
|
||||
#endif
|
||||
|
||||
void
|
||||
handleSignal(int)
|
||||
handleSignal(int signal, siginfo_t* info, void* context)
|
||||
{
|
||||
// ignore
|
||||
if (signal == SIGSEGV) {
|
||||
greg_t* registers
|
||||
= static_cast<ucontext_t*>(context)->uc_mcontext.gregs;
|
||||
|
||||
bool handled = segFaultHandler->handleSignal
|
||||
(reinterpret_cast<void*>(registers[IpRegister]),
|
||||
reinterpret_cast<void*>(registers[BaseRegister]),
|
||||
reinterpret_cast<void*>(registers[StackRegister]));
|
||||
|
||||
if (not handled) {
|
||||
if (oldSegFaultHandler.sa_flags & SA_SIGINFO) {
|
||||
oldSegFaultHandler.sa_sigaction(signal, info, context);
|
||||
} else {
|
||||
oldSegFaultHandler.sa_handler(signal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void*
|
||||
@ -403,7 +434,8 @@ class MySystem: public System {
|
||||
struct sigaction sa;
|
||||
memset(&sa, 0, sizeof(struct sigaction));
|
||||
sigemptyset(&(sa.sa_mask));
|
||||
sa.sa_handler = handleSignal;
|
||||
sa.sa_flags = SA_SIGINFO;
|
||||
sa.sa_sigaction = handleSignal;
|
||||
|
||||
int rv UNUSED = sigaction(InterruptSignal, &sa, 0);
|
||||
expect(this, rv == 0);
|
||||
@ -480,6 +512,24 @@ class MySystem: public System {
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual Status handleSegFault(SignalHandler* handler) {
|
||||
if (handler) {
|
||||
segFaultHandler = handler;
|
||||
|
||||
struct sigaction sa;
|
||||
memset(&sa, 0, sizeof(struct sigaction));
|
||||
sigemptyset(&(sa.sa_mask));
|
||||
sa.sa_flags = SA_SIGINFO;
|
||||
sa.sa_sigaction = handleSignal;
|
||||
|
||||
return sigaction(SIGSEGV, &sa, &oldSegFaultHandler);
|
||||
} else if (segFaultHandler) {
|
||||
return sigaction(SIGSEGV, &oldSegFaultHandler, 0);
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types,
|
||||
unsigned count, unsigned size, unsigned returnType)
|
||||
{
|
||||
|
@ -80,6 +80,13 @@ class System: public Allocator {
|
||||
virtual void dispose() = 0;
|
||||
};
|
||||
|
||||
class SignalHandler {
|
||||
public:
|
||||
virtual ~SignalHandler() { }
|
||||
|
||||
virtual bool handleSignal(void* ip, void* base, void* stack) = 0;
|
||||
};
|
||||
|
||||
virtual ~System() { }
|
||||
|
||||
virtual bool success(Status) = 0;
|
||||
@ -87,6 +94,7 @@ class System: public Allocator {
|
||||
virtual Status start(Runnable*) = 0;
|
||||
virtual Status make(Monitor**) = 0;
|
||||
virtual Status make(Local**) = 0;
|
||||
virtual Status handleSegFault(SignalHandler* handler) = 0;
|
||||
virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types,
|
||||
unsigned count, unsigned size,
|
||||
unsigned returnType) = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user