save locals to memory before executing any instruction which might trigger an exception if that instruction lies within an exception handler

This commit is contained in:
Joel Dice 2008-11-25 10:34:48 -07:00
parent 3d9e508e3e
commit eea2225176
3 changed files with 87 additions and 18 deletions

View File

@ -530,7 +530,7 @@ class Context {
Context(MyThread* t, object method):
thread(t),
zone(t->m->system, t->m->heap, 16 * 1024),
zone(t->m->system, t->m->heap, 64 * 1024),
assembler(makeAssembler(t->m->system, t->m->heap, &zone, t->arch)),
client(t),
compiler(makeCompiler(t->m->system, assembler, &zone, &client)),
@ -1860,6 +1860,24 @@ exceptionIndex(MyThread* t, object code, unsigned jsrIp, unsigned dstIp)
abort(t);
}
bool
inTryBlock(MyThread* t, object code, unsigned ip)
{
object table = codeExceptionHandlerTable(t, code);
if (table) {
unsigned length = exceptionHandlerTableLength(t, table);
for (unsigned i = 0; i < length; ++i) {
ExceptionHandler* eh = exceptionHandlerTableBody(t, table, i);
if (ip >= exceptionHandlerStart(eh)
and ip < exceptionHandlerEnd(eh))
{
return true;
}
}
}
return false;
}
void
compile(MyThread* t, Frame* initialFrame, unsigned ip,
int exceptionHandlerStart = -1);
@ -1926,6 +1944,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
Compiler::Operand* index = frame->popInt();
Compiler::Operand* array = frame->popObject();
if (inTryBlock(t, code, ip - 1)) {
c->saveLocals();
}
if (CheckArrayBounds) {
c->checkBounds(array, ArrayLength, index, reinterpret_cast<intptr_t>
(&singletonValue(t, aioobThunk(t), 0)));
@ -1982,6 +2004,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
Compiler::Operand* index = frame->popInt();
Compiler::Operand* array = frame->popObject();
if (inTryBlock(t, code, ip - 1)) {
c->saveLocals();
}
if (CheckArrayBounds) {
c->checkBounds(array, ArrayLength, index, reinterpret_cast<intptr_t>
(&singletonValue(t, aioobThunk(t), 0)));
@ -2405,6 +2431,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
table = frame->append(classStaticTable(t, fieldClass(t, field)));
} else {
table = frame->popObject();
if (inTryBlock(t, code, ip - 3)) {
c->saveLocals();
}
}
switch (fieldCode(t, field)) {
@ -3330,6 +3360,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
}
staticTable = classStaticTable(t, fieldClass(t, field));
} else if (inTryBlock(t, code, ip - 3)) {
c->saveLocals();
}
Compiler::Operand* value;
@ -3968,7 +4000,7 @@ finish(MyThread* t, Context* context)
strcmp
(reinterpret_cast<const char*>
(&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)),
"Longs") == 0 and
"Arrays") == 0 and
strcmp
(reinterpret_cast<const char*>
(&byteArrayBody(t, methodName(t, context->method), 0)),

View File

@ -2294,7 +2294,7 @@ clean(Context* c, Event* e, Stack* stack, Local* locals, Read* reads,
for (Read* r = reads; r; r = r->eventNext) {
nextRead(c, e, r->value);
}
}
}
CodePromise*
@ -2313,6 +2313,26 @@ codePromise(Context* c, Promise* offset)
void
append(Context* c, Event* e);
void
saveLocals(Context* c, Event* e)
{
for (unsigned li = 0; li < c->localFootprint; ++li) {
Local* local = e->localsBefore + li;
if (local->value) {
if (DebugReads) {
fprintf(stderr, "local save read %p of footprint %d at %d of %d\n",
local->value, local->footprint,
::frameIndex(c, li, local->footprint),
c->alignedFrameSize + c->parameterFootprint);
}
addRead(c, e, local->value, read
(c, footprintSizeInBytes(local->footprint), 1 << MemoryOperand,
0, ::frameIndex(c, li, local->footprint)));
}
}
}
class CallEvent: public Event {
public:
CallEvent(Context* c, Value* address, unsigned flags,
@ -2422,21 +2442,7 @@ class CallEvent: public Event {
frameIndex += s->footprint;
}
for (unsigned li = 0; li < c->localFootprint; ++li) {
Local* local = localsBefore + li;
if (local->value) {
if (DebugReads) {
fprintf(stderr, "local save read %p of footprint %d at %d of %d\n",
local->value, local->footprint,
::frameIndex(c, li, local->footprint),
c->alignedFrameSize + c->parameterFootprint);
}
addRead(c, this, local->value, read
(c, footprintSizeInBytes(local->footprint), 1 << MemoryOperand,
0, ::frameIndex(c, li, local->footprint)));
}
}
saveLocals(c, this);
}
virtual const char* name() {
@ -3412,6 +3418,32 @@ appendBuddy(Context* c, Value* original, Value* buddy, unsigned size)
BuddyEvent(c, original, buddy, size));
}
class SaveLocalsEvent: public Event {
public:
SaveLocalsEvent(Context* c):
Event(c)
{
saveLocals(c, this);
}
virtual const char* name() {
return "SaveLocalsEvent";
}
virtual void compile(Context* c) {
for (Read* r = reads; r; r = r->eventNext) {
nextRead(c, this, r->value);
}
}
};
void
appendSaveLocals(Context* c)
{
append(c, new (c->zone->allocate(sizeof(SaveLocalsEvent)))
SaveLocalsEvent(c));
}
class DummyEvent: public Event {
public:
DummyEvent(Context* c):
@ -4482,6 +4514,10 @@ class MyCompiler: public Compiler {
return c.locals[index].value;
}
virtual void saveLocals() {
appendSaveLocals(&c);
}
virtual void checkBounds(Operand* object, unsigned lengthOffset,
Operand* index, intptr_t handler)
{

View File

@ -92,6 +92,7 @@ class Compiler {
virtual void storeLocal(unsigned footprint, Operand* src,
unsigned index) = 0;
virtual Operand* loadLocal(unsigned footprint, unsigned index) = 0;
virtual void saveLocals() = 0;
virtual void checkBounds(Operand* object, unsigned lengthOffset,
Operand* index, intptr_t handler) = 0;