This commit is contained in:
Joel Dice 2007-12-30 15:24:48 -07:00
parent c147ef4e5c
commit 069a760918
5 changed files with 338 additions and 100 deletions

View File

@ -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;
}

View File

@ -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() {

View File

@ -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;

View File

@ -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)
{

View File

@ -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;