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