fix return address code offset calculation on ARM

We have to be careful about how we calculate return addresses on ARM
due to padding introduced by constant pools interspersed with code.
When calculating the offset of code where we're inserting a constant
pool, we want the offset of the end of the pool for jump targets, but
we want the offset just prior to the beginning of the pool (i.e. the
offset of the instruction responsible for jumping past the pool) when
calculating a return address.
This commit is contained in:
Joel Dice 2010-12-07 15:57:11 -07:00
parent 61fe7efd6d
commit 378f7086b7
5 changed files with 14 additions and 12 deletions

View File

@ -320,8 +320,8 @@ expect(Context* c, bool v)
class Offset: public Promise { class Offset: public Promise {
public: public:
Offset(Context* c, MyBlock* block, unsigned offset): Offset(Context* c, MyBlock* block, unsigned offset, bool forTrace):
c(c), block(block), offset(offset) c(c), block(block), offset(offset), forTrace(forTrace)
{ } { }
virtual bool resolved() { virtual bool resolved() {
@ -332,19 +332,20 @@ class Offset: public Promise {
assert(c, resolved()); assert(c, resolved());
unsigned o = offset - block->offset; unsigned o = offset - block->offset;
return block->start + padding(block, o) + o; return block->start + padding(block, forTrace ? o - BytesPerWord : o) + o;
} }
Context* c; Context* c;
MyBlock* block; MyBlock* block;
unsigned offset; unsigned offset;
bool forTrace;
}; };
Promise* Promise*
offset(Context* c) offset(Context* c, bool forTrace = false)
{ {
return new (c->zone->allocate(sizeof(Offset))) return new (c->zone->allocate(sizeof(Offset)))
Offset(c, c->lastBlock, c->code.length()); Offset(c, c->lastBlock, c->code.length(), forTrace);
} }
bool bool
@ -2271,8 +2272,8 @@ class MyAssembler: public Assembler {
} }
} }
virtual Promise* offset() { virtual Promise* offset(bool forTrace) {
return ::offset(&c); return ::offset(&c, forTrace);
} }
virtual Block* endBlock(bool startNew) { virtual Block* endBlock(bool startNew) {

View File

@ -414,7 +414,7 @@ class Assembler {
virtual void writeTo(uint8_t* dst) = 0; virtual void writeTo(uint8_t* dst) = 0;
virtual Promise* offset() = 0; virtual Promise* offset(bool forTrace = false) = 0;
virtual Block* endBlock(bool startNew) = 0; virtual Block* endBlock(bool startNew) = 0;

View File

@ -3098,7 +3098,8 @@ codePromise(Context* c, Event* e)
CodePromise* CodePromise*
codePromise(Context* c, Promise* offset) codePromise(Context* c, Promise* offset)
{ {
return new (c->zone->allocate(sizeof(CodePromise))) CodePromise(c, offset); return new (c->zone->allocate(sizeof(CodePromise)))
CodePromise(c, offset);
} }
void void
@ -3357,7 +3358,7 @@ class CallEvent: public Event {
apply(c, op, BytesPerWord, address->source, address->source); apply(c, op, BytesPerWord, address->source, address->source);
if (traceHandler) { if (traceHandler) {
traceHandler->handleTrace(codePromise(c, c->assembler->offset()), traceHandler->handleTrace(codePromise(c, c->assembler->offset(true)),
stackArgumentIndex); stackArgumentIndex);
} }

View File

@ -2377,7 +2377,7 @@ class MyAssembler: public Assembler {
} }
} }
virtual Promise* offset() { virtual Promise* offset(bool) {
return ::offset(&c); return ::offset(&c);
} }

View File

@ -3536,7 +3536,7 @@ class MyAssembler: public Assembler {
} }
} }
virtual Promise* offset() { virtual Promise* offset(bool) {
return local::offset(&c); return local::offset(&c);
} }