mirror of
https://github.com/corda/corda.git
synced 2025-06-19 15:43:52 +00:00
more work on frame-pointer-less unwinding
This fixes the tails=true build (at least for x86_64) and eliminates the need for a frame table in the tails=false build. In the tails=true build, we still need a frame table on x86(_64) to help determine whether we've caught a thread executing code to do a tail call or pop arguments off the stack. However, I've not yet written the code to actually use this table, and it is only needed to handle asynchronous unwinds via Thread.getStackTrace.
This commit is contained in:
155
src/arm.cpp
155
src/arm.cpp
@ -164,13 +164,13 @@ inline int carry16(intptr_t v) { return static_cast<int16_t>(v) < 0 ? 1 : 0; }
|
|||||||
inline bool isOfWidth(long long i, int size) { return static_cast<unsigned long long>(i) >> size == 0; }
|
inline bool isOfWidth(long long i, int size) { return static_cast<unsigned long long>(i) >> size == 0; }
|
||||||
inline bool isOfWidth(int i, int size) { return static_cast<unsigned>(i) >> size == 0; }
|
inline bool isOfWidth(int i, int size) { return static_cast<unsigned>(i) >> size == 0; }
|
||||||
|
|
||||||
const unsigned FrameFooterSize = 2;
|
const unsigned FrameHeaderSize = (UseFramePointer ? 2 : 1);
|
||||||
const unsigned FrameHeaderSize = 0;
|
|
||||||
|
|
||||||
const unsigned StackAlignmentInBytes = 8;
|
const unsigned StackAlignmentInBytes = 8;
|
||||||
const unsigned StackAlignmentInWords = StackAlignmentInBytes / BytesPerWord;
|
const unsigned StackAlignmentInWords = StackAlignmentInBytes / BytesPerWord;
|
||||||
|
|
||||||
const int ThreadRegister = 8;
|
const int ThreadRegister = 8;
|
||||||
|
const int FrameRegister = 12;
|
||||||
const int StackRegister = 13;
|
const int StackRegister = 13;
|
||||||
const int LinkRegister = 14;
|
const int LinkRegister = 14;
|
||||||
const int ProgramCounter = 15;
|
const int ProgramCounter = 15;
|
||||||
@ -1701,6 +1701,9 @@ class MyArchitecture: public Assembler::Architecture {
|
|||||||
|
|
||||||
virtual bool reserved(int register_) {
|
virtual bool reserved(int register_) {
|
||||||
switch (register_) {
|
switch (register_) {
|
||||||
|
case FrameRegister:
|
||||||
|
return UseFramePointer;
|
||||||
|
|
||||||
case LinkRegister:
|
case LinkRegister:
|
||||||
case StackRegister:
|
case StackRegister:
|
||||||
case ThreadRegister:
|
case ThreadRegister:
|
||||||
@ -1781,8 +1784,8 @@ class MyArchitecture: public Assembler::Architecture {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned alignFrameSize(unsigned sizeInWords) {
|
virtual unsigned alignFrameSize(unsigned sizeInWords) {
|
||||||
const unsigned alignment = StackAlignmentInBytes / BytesPerWord;
|
return pad(sizeInWords + FrameHeaderSize, StackAlignmentInWords)
|
||||||
return (ceiling(sizeInWords + FrameFooterSize, alignment) * alignment);
|
- FrameHeaderSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void* frameIp(void* stack) {
|
virtual void* frameIp(void* stack) {
|
||||||
@ -1798,15 +1801,15 @@ class MyArchitecture: public Assembler::Architecture {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned frameFooterSize() {
|
virtual unsigned frameFooterSize() {
|
||||||
return FrameFooterSize;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int returnAddressOffset() {
|
virtual int returnAddressOffset() {
|
||||||
return 1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int framePointerOffset() {
|
virtual int framePointerOffset() {
|
||||||
return 0;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void nextFrame(void** stack, void**) {
|
virtual void nextFrame(void** stack, void**) {
|
||||||
@ -2006,11 +2009,14 @@ class MyAssembler: public Assembler {
|
|||||||
return arch_;
|
return arch_;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void saveFrame(unsigned stackOffset, unsigned) {
|
virtual void saveFrame(unsigned stackOffset) {
|
||||||
|
appendFrameSizeEvent(&c, FrameSizePoison);
|
||||||
|
|
||||||
|
// ???
|
||||||
Register returnAddress(LinkRegister);
|
Register returnAddress(LinkRegister);
|
||||||
Memory returnAddressDst
|
Memory returnAddressDst(StackRegister, - BytesPerWord);
|
||||||
(StackRegister, arch_->returnAddressOffset() * BytesPerWord);
|
moveAndUpdateRM(&c, BytesPerWord, &returnAddress, BytesPerWord,
|
||||||
moveRM(&c, BytesPerWord, &returnAddress, BytesPerWord, &returnAddressDst);
|
&returnAddressDst);
|
||||||
|
|
||||||
Register stack(StackRegister);
|
Register stack(StackRegister);
|
||||||
Memory stackDst(ThreadRegister, stackOffset);
|
Memory stackDst(ThreadRegister, stackOffset);
|
||||||
@ -2059,33 +2065,53 @@ class MyAssembler: public Assembler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void allocateFrame(unsigned footprint) {
|
virtual void allocateFrame(unsigned footprint) {
|
||||||
Register returnAddress(LinkRegister);
|
Register stack(StackRegister);
|
||||||
|
Constant footprintConstant(resolved(&c, footprint * BytesPerWord));
|
||||||
|
subCR(&c, BytesPerWord, &footprintConstant, BytesPerWord, &stack,
|
||||||
|
BytesPerWord, &stack);
|
||||||
|
|
||||||
Memory returnAddressDst(StackRegister, arch_->returnAddressOffset() * BytesPerWord);
|
appendFrameSizeEvent(&c, footprint);
|
||||||
|
|
||||||
|
Register returnAddress(LinkRegister);
|
||||||
|
Memory returnAddressDst(StackRegister, (footprint - 1) * BytesPerWord);
|
||||||
moveRM(&c, BytesPerWord, &returnAddress, BytesPerWord, &returnAddressDst);
|
moveRM(&c, BytesPerWord, &returnAddress, BytesPerWord, &returnAddressDst);
|
||||||
|
|
||||||
Register stack(StackRegister);
|
if (UseFramePointer) {
|
||||||
Memory stackDst(StackRegister, -footprint * BytesPerWord);
|
Register frame(FrameRegister);
|
||||||
moveAndUpdateRM(&c, BytesPerWord, &stack, BytesPerWord, &stackDst);
|
Memory frameDst(StackRegister, (footprint - 2) * BytesPerWord);
|
||||||
|
moveRM(&c, BytesPerWord, &frame, BytesPerWord, &frameDst);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void adjustFrame(unsigned footprint) {
|
virtual void adjustFrame(unsigned difference) {
|
||||||
Register nextStack(5);
|
appendFrameSizeEvent(&c, - difference);
|
||||||
Memory stackSrc(StackRegister, 0);
|
|
||||||
moveMR(&c, BytesPerWord, &stackSrc, BytesPerWord, &nextStack);
|
|
||||||
|
|
||||||
Memory stackDst(StackRegister, -footprint * BytesPerWord);
|
Register stack(StackRegister);
|
||||||
moveAndUpdateRM(&c, BytesPerWord, &nextStack, BytesPerWord, &stackDst);
|
Constant differenceConstant(resolved(&c, difference * BytesPerWord));
|
||||||
|
subCR(&c, BytesPerWord, &differenceConstant, BytesPerWord, &stack,
|
||||||
|
BytesPerWord, &stack);
|
||||||
|
|
||||||
|
appendFrameSizeEvent(&c, difference);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void popFrame() {
|
virtual void popFrame(unsigned frameFootprint) {
|
||||||
Register stack(StackRegister);
|
if (UseFramePointer) {
|
||||||
Memory stackSrc(StackRegister, arch_->framePointerOffset() * BytesPerWord);
|
Register frame(FrameRegister);
|
||||||
moveMR(&c, BytesPerWord, &stackSrc, BytesPerWord, &stack);
|
Memory frameSrc(StackRegister, (frameFootprint - 1) * BytesPerWord);
|
||||||
|
moveMR(&c, BytesPerWord, &frameSrc, BytesPerWord, &frame);
|
||||||
|
}
|
||||||
|
|
||||||
Register returnAddress(LinkRegister);
|
Register returnAddress(LinkRegister);
|
||||||
Memory returnAddressSrc(StackRegister, arch_->returnAddressOffset() * BytesPerWord);
|
Memory returnAddressSrc
|
||||||
|
(StackRegister, (frameFootprint - 1) * BytesPerWord);
|
||||||
moveMR(&c, BytesPerWord, &returnAddressSrc, BytesPerWord, &returnAddress);
|
moveMR(&c, BytesPerWord, &returnAddressSrc, BytesPerWord, &returnAddress);
|
||||||
|
|
||||||
|
Register stack(StackRegister);
|
||||||
|
Constant differenceConstant(resolved(&c, frameFootprint * BytesPerWord));
|
||||||
|
addCR(&c, BytesPerWord, &differenceConstant, BytesPerWord, &stack,
|
||||||
|
BytesPerWord, &stack);
|
||||||
|
|
||||||
|
appendFrameSizeEvent(&c, - frameFootprint);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void popFrameForTailCall(unsigned footprint,
|
virtual void popFrameForTailCall(unsigned footprint,
|
||||||
@ -2095,80 +2121,85 @@ class MyAssembler: public Assembler {
|
|||||||
{
|
{
|
||||||
if (TailCalls) {
|
if (TailCalls) {
|
||||||
if (offset) {
|
if (offset) {
|
||||||
|
if (UseFramePointer) {
|
||||||
|
Register frame(FrameRegister);
|
||||||
|
Memory frameSrc(StackRegister, (footprint - 1) * BytesPerWord);
|
||||||
|
moveMR(&c, BytesPerWord, &frameSrc, BytesPerWord, &frame);
|
||||||
|
}
|
||||||
|
|
||||||
Register link(LinkRegister);
|
Register link(LinkRegister);
|
||||||
Memory returnAddressSrc
|
Memory returnAddressSrc
|
||||||
(StackRegister, BytesPerWord + (footprint * BytesPerWord));
|
(StackRegister, (footprint - 1) * BytesPerWord);
|
||||||
moveMR(&c, BytesPerWord, &returnAddressSrc, BytesPerWord, &link);
|
moveMR(&c, BytesPerWord, &returnAddressSrc, BytesPerWord, &link);
|
||||||
|
|
||||||
Register tmp(c.client->acquireTemporary());
|
Register stack(StackRegister);
|
||||||
Memory stackSrc(StackRegister, footprint * BytesPerWord);
|
Constant footprintConstant
|
||||||
moveMR(&c, BytesPerWord, &stackSrc, BytesPerWord, &tmp);
|
(resolved(&c, (footprint - offset + 1) * BytesPerWord));
|
||||||
|
addCR(&c, BytesPerWord, &footprintConstant, BytesPerWord, &stack);
|
||||||
|
|
||||||
Memory stackDst(StackRegister, (footprint - offset) * BytesPerWord);
|
appendFrameSizeEvent(&c, - (frameFootprint - offset + 1));
|
||||||
moveAndUpdateRM(&c, BytesPerWord, &tmp, BytesPerWord, &stackDst);
|
|
||||||
|
|
||||||
c.client->releaseTemporary(tmp.low);
|
|
||||||
|
|
||||||
if (returnAddressSurrogate != NoRegister) {
|
if (returnAddressSurrogate != NoRegister) {
|
||||||
assert(&c, offset > 0);
|
assert(&c, offset > 0);
|
||||||
|
|
||||||
Register ras(returnAddressSurrogate);
|
Register ras(returnAddressSurrogate);
|
||||||
Memory dst(StackRegister, BytesPerWord + (offset * BytesPerWord));
|
Memory dst(StackRegister, (offset - 1) * BytesPerWord);
|
||||||
moveRM(&c, BytesPerWord, &ras, BytesPerWord, &dst);
|
moveRM(&c, BytesPerWord, &ras, BytesPerWord, &dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (framePointerSurrogate != NoRegister) {
|
if (framePointerSurrogate != NoRegister) {
|
||||||
assert(&c, offset > 0);
|
assert(&c, offset > 0);
|
||||||
|
|
||||||
Register fps(framePointerSurrogate);
|
Register las(framePointerSurrogate);
|
||||||
Memory dst(StackRegister, offset * BytesPerWord);
|
Memory dst(StackRegister, (offset - 2) * BytesPerWord);
|
||||||
moveRM(&c, BytesPerWord, &fps, BytesPerWord, &dst);
|
moveRM(&c, BytesPerWord, &las, BytesPerWord, &dst);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
popFrame();
|
popFrame(footprint);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
abort(&c);
|
abort(&c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void popFrameAndPopArgumentsAndReturn(unsigned argumentFootprint) {
|
virtual void popFrameAndPopArgumentsAndReturn(unsigned frameFootprint,
|
||||||
popFrame();
|
unsigned argumentFootprint)
|
||||||
|
{
|
||||||
|
popFrame(frameFootprint);
|
||||||
|
|
||||||
assert(&c, argumentFootprint >= StackAlignmentInWords);
|
assert(&c, argumentFootprint >= StackAlignmentInWords);
|
||||||
assert(&c, (argumentFootprint % StackAlignmentInWords) == 0);
|
assert(&c, (argumentFootprint % StackAlignmentInWords) == 0);
|
||||||
|
|
||||||
|
unsigned offset;
|
||||||
if (TailCalls and argumentFootprint > StackAlignmentInWords) {
|
if (TailCalls and argumentFootprint > StackAlignmentInWords) {
|
||||||
Register tmp(5);
|
offset = argumentFootprint - StackAlignmentInWords;
|
||||||
Memory stackSrc(StackRegister, 0);
|
|
||||||
moveMR(&c, BytesPerWord, &stackSrc, BytesPerWord, &tmp);
|
|
||||||
|
|
||||||
Memory stackDst(StackRegister,
|
Register stack(StackRegister);
|
||||||
(argumentFootprint - StackAlignmentInWords)
|
Constant adjustment(resolved(&c, offset * BytesPerWord));
|
||||||
* BytesPerWord);
|
addCR(&c, BytesPerWord, &adjustment, BytesPerWord, &stack);
|
||||||
moveAndUpdateRM(&c, BytesPerWord, &tmp, BytesPerWord, &stackDst);
|
|
||||||
|
appendFrameSizeEvent(&c, - offset);
|
||||||
|
} else {
|
||||||
|
offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return_(&c);
|
return_(&c);
|
||||||
|
|
||||||
|
// todo: this is not necessary if there are no instructions to
|
||||||
|
// follow:
|
||||||
|
appendFrameSizeEvent(&c, frameFootprint + offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void popFrameAndUpdateStackAndReturn(unsigned stackOffsetFromThread)
|
virtual void popFrameAndUpdateStackAndReturn(unsigned frameFootprint,
|
||||||
|
unsigned stackOffsetFromThread)
|
||||||
{
|
{
|
||||||
popFrame();
|
appendFrameSizeEvent(&c, FrameSizePoison);
|
||||||
|
|
||||||
Register tmp1(6);
|
popFrame(frameFootprint);
|
||||||
Memory stackSrc(StackRegister, 0);
|
|
||||||
moveMR(&c, BytesPerWord, &stackSrc, BytesPerWord, &tmp1);
|
|
||||||
|
|
||||||
Register tmp2(5);
|
|
||||||
Memory newStackSrc(ThreadRegister, stackOffsetFromThread);
|
|
||||||
moveMR(&c, BytesPerWord, &newStackSrc, BytesPerWord, &tmp2);
|
|
||||||
|
|
||||||
Register stack(StackRegister);
|
Register stack(StackRegister);
|
||||||
subR(&c, BytesPerWord, &stack, &tmp2, &tmp2);
|
Memory newStackSrc(ThreadRegister, stackOffsetFromThread);
|
||||||
|
moveMR(&c, BytesPerWord, &newStackSrc, BytesPerWord, &stack);
|
||||||
Memory stackDst(StackRegister, 0, tmp2.low);
|
|
||||||
moveAndUpdateRM(&c, BytesPerWord, &tmp1, BytesPerWord, &stackDst);
|
|
||||||
|
|
||||||
return_(&c);
|
return_(&c);
|
||||||
}
|
}
|
||||||
|
@ -304,11 +304,10 @@ class Assembler {
|
|||||||
virtual unsigned resolve(unsigned start, Block* next) = 0;
|
virtual unsigned resolve(unsigned start, Block* next) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FrameSizeEvent {
|
class FrameEvent {
|
||||||
public:
|
public:
|
||||||
virtual unsigned offset() = 0;
|
virtual unsigned offset() = 0;
|
||||||
virtual int change() = 0;
|
virtual FrameEvent* next() = 0;
|
||||||
virtual FrameSizeEvent* next() = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Architecture {
|
class Architecture {
|
||||||
@ -351,6 +350,10 @@ class Assembler {
|
|||||||
|
|
||||||
virtual unsigned alignFrameSize(unsigned sizeInWords) = 0;
|
virtual unsigned alignFrameSize(unsigned sizeInWords) = 0;
|
||||||
|
|
||||||
|
virtual void nextFrame(void* start, unsigned size, unsigned footprint,
|
||||||
|
int32_t* frameTable, void* link, void* stackLimit,
|
||||||
|
unsigned targetParameterFootprint, void** ip,
|
||||||
|
void** stack) = 0;
|
||||||
virtual void* frameIp(void* stack) = 0;
|
virtual void* frameIp(void* stack) = 0;
|
||||||
virtual unsigned frameHeaderSize() = 0;
|
virtual unsigned frameHeaderSize() = 0;
|
||||||
virtual unsigned frameReturnAddressSize() = 0;
|
virtual unsigned frameReturnAddressSize() = 0;
|
||||||
@ -437,9 +440,9 @@ class Assembler {
|
|||||||
|
|
||||||
virtual unsigned length() = 0;
|
virtual unsigned length() = 0;
|
||||||
|
|
||||||
virtual unsigned frameSizeEventCount() = 0;
|
virtual unsigned frameEventCount() = 0;
|
||||||
|
|
||||||
virtual FrameSizeEvent* firstFrameSizeEvent() = 0;
|
virtual FrameEvent* firstFrameEvent() = 0;
|
||||||
|
|
||||||
virtual void dispose() = 0;
|
virtual void dispose() = 0;
|
||||||
};
|
};
|
||||||
|
144
src/compile.cpp
144
src/compile.cpp
@ -153,14 +153,18 @@ class MyThread: public Thread {
|
|||||||
CallTrace* trace):
|
CallTrace* trace):
|
||||||
Context(t, ip, stack, continuation, trace),
|
Context(t, ip, stack, continuation, trace),
|
||||||
t(t),
|
t(t),
|
||||||
|
link(0),
|
||||||
|
javaStackLimit(0),
|
||||||
next(t->traceContext)
|
next(t->traceContext)
|
||||||
{
|
{
|
||||||
t->traceContext = this;
|
t->traceContext = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
TraceContext(MyThread* t):
|
TraceContext(MyThread* t, void* link):
|
||||||
Context(t, t->ip, t->stack, t->continuation, t->trace),
|
Context(t, t->ip, t->stack, t->continuation, t->trace),
|
||||||
t(t),
|
t(t),
|
||||||
|
link(link),
|
||||||
|
javaStackLimit(0),
|
||||||
next(t->traceContext)
|
next(t->traceContext)
|
||||||
{
|
{
|
||||||
t->traceContext = this;
|
t->traceContext = this;
|
||||||
@ -171,6 +175,8 @@ class MyThread: public Thread {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MyThread* t;
|
MyThread* t;
|
||||||
|
void* link;
|
||||||
|
void* javaStackLimit;
|
||||||
TraceContext* next;
|
TraceContext* next;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -414,56 +420,42 @@ getTableValue(Thread* t, object table, unsigned base, unsigned max,
|
|||||||
(&intArrayBody(t, table, base), bits, index * bits);
|
(&intArrayBody(t, table, base), bits, index * bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned
|
void
|
||||||
frameSize(MyThread* t, intptr_t ip, object method)
|
nextFrame(MyThread* t, void** ip, void** sp, object method, object target)
|
||||||
{
|
{
|
||||||
object code = methodCode(t, method);
|
object code = methodCode(t, method);
|
||||||
object table = codeFrameSizeTable(t, code);
|
object table = codeFrameTable(t, code);
|
||||||
unsigned count = intArrayBody(t, table, 0);
|
|
||||||
unsigned max = alignedFrameSize(t, method);
|
|
||||||
intptr_t start = codeCompiled(t, code);
|
intptr_t start = codeCompiled(t, code);
|
||||||
int codeSize = compiledSize(start);
|
void* link;
|
||||||
unsigned indexSize = ceiling(count * bitsNeeded(codeSize), 32);
|
void* javaStackLimit;
|
||||||
|
|
||||||
assert(t, ip >= start);
|
if (t->traceContext) {
|
||||||
assert(t, ip <= start + codeSize);
|
link = t->traceContext->link;
|
||||||
|
javaStackLimit = t->traceContext->javaStackLimit;
|
||||||
unsigned offset = ip - start;
|
|
||||||
unsigned bottom = 0;
|
|
||||||
unsigned top = count;
|
|
||||||
for (unsigned span = top - bottom; span; span = top - bottom) {
|
|
||||||
unsigned middle = bottom + (span / 2);
|
|
||||||
unsigned candidate = getTableValue(t, table, 1, codeSize, middle);
|
|
||||||
|
|
||||||
if (offset >= candidate
|
|
||||||
and (middle + 1 == count
|
|
||||||
or offset < getTableValue(t, table, 1, codeSize, middle + 1)))
|
|
||||||
{
|
|
||||||
return getTableValue(t, table, 1 + indexSize, max, middle);
|
|
||||||
} else if (offset < candidate) {
|
|
||||||
top = middle;
|
|
||||||
} else if (offset > candidate) {
|
|
||||||
bottom = middle + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (top == 0) {
|
|
||||||
return 0;
|
|
||||||
} else if (top < count) {
|
|
||||||
return getTableValue(t, table, 1 + indexSize, max, top);
|
|
||||||
} else if (top == count && count > 0) {
|
|
||||||
return getTableValue(t, table, 1 + indexSize, max, top - 1);
|
|
||||||
} else {
|
} else {
|
||||||
abort(t);
|
link = 0;
|
||||||
|
javaStackLimit = 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void*
|
// fprintf(stderr, "nextFrame %s.%s%s target %s.%s%s\n",
|
||||||
nextFrame(MyThread* t, void* ip, void* sp, object method)
|
// &byteArrayBody(t, className(t, methodClass(t, method)), 0),
|
||||||
{
|
// &byteArrayBody(t, methodName(t, method), 0),
|
||||||
return reinterpret_cast<void**>(sp) + local::frameSize
|
// &byteArrayBody(t, methodSpec(t, method), 0),
|
||||||
(t, reinterpret_cast<intptr_t>(ip), method)
|
// target
|
||||||
+ t->arch->frameReturnAddressSize();
|
// ? &byteArrayBody(t, className(t, methodClass(t, target)), 0)
|
||||||
|
// : 0,
|
||||||
|
// target
|
||||||
|
// ? &byteArrayBody(t, methodName(t, target), 0)
|
||||||
|
// : 0,
|
||||||
|
// target
|
||||||
|
// ? &byteArrayBody(t, methodSpec(t, target), 0)
|
||||||
|
// : 0);
|
||||||
|
|
||||||
|
t->arch->nextFrame
|
||||||
|
(reinterpret_cast<void*>(start), compiledSize(start),
|
||||||
|
alignedFrameSize(t, method), table ? &intArrayBody(t, table, 0) : 0,
|
||||||
|
link, javaStackLimit, target ? methodParameterFootprint(t, target) : -1,
|
||||||
|
ip, sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyStackWalker: public Processor::StackWalker {
|
class MyStackWalker: public Processor::StackWalker {
|
||||||
@ -486,6 +478,7 @@ class MyStackWalker: public Processor::StackWalker {
|
|||||||
|
|
||||||
virtual void visit(Heap::Visitor* v) {
|
virtual void visit(Heap::Visitor* v) {
|
||||||
v->visit(&(walker->method_));
|
v->visit(&(walker->method_));
|
||||||
|
v->visit(&(walker->target));
|
||||||
v->visit(&(walker->continuation));
|
v->visit(&(walker->continuation));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -496,6 +489,7 @@ class MyStackWalker: public Processor::StackWalker {
|
|||||||
t(t),
|
t(t),
|
||||||
state(Start),
|
state(Start),
|
||||||
method_(0),
|
method_(0),
|
||||||
|
target(0),
|
||||||
protector(this)
|
protector(this)
|
||||||
{
|
{
|
||||||
if (t->traceContext) {
|
if (t->traceContext) {
|
||||||
@ -518,6 +512,7 @@ class MyStackWalker: public Processor::StackWalker {
|
|||||||
stack(w->stack),
|
stack(w->stack),
|
||||||
trace(w->trace),
|
trace(w->trace),
|
||||||
method_(w->method_),
|
method_(w->method_),
|
||||||
|
target(w->target),
|
||||||
continuation(w->continuation),
|
continuation(w->continuation),
|
||||||
protector(this)
|
protector(this)
|
||||||
{ }
|
{ }
|
||||||
@ -551,6 +546,7 @@ class MyStackWalker: public Processor::StackWalker {
|
|||||||
|
|
||||||
case Next:
|
case Next:
|
||||||
if (stack) {
|
if (stack) {
|
||||||
|
target = method_;
|
||||||
method_ = methodForIp(t, ip_);
|
method_ = methodForIp(t, ip_);
|
||||||
if (method_) {
|
if (method_) {
|
||||||
state = Method;
|
state = Method;
|
||||||
@ -599,8 +595,7 @@ class MyStackWalker: public Processor::StackWalker {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case Method:
|
case Method:
|
||||||
stack = nextFrame(t, ip_, stack, method_);
|
nextFrame(t, &ip_, &stack, method_, target);
|
||||||
ip_ = t->arch->frameIp(stack);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NativeMethod:
|
case NativeMethod:
|
||||||
@ -654,6 +649,7 @@ class MyStackWalker: public Processor::StackWalker {
|
|||||||
void* stack;
|
void* stack;
|
||||||
MyThread::CallTrace* trace;
|
MyThread::CallTrace* trace;
|
||||||
object method_;
|
object method_;
|
||||||
|
object target;
|
||||||
object continuation;
|
object continuation;
|
||||||
MyProtector protector;
|
MyProtector protector;
|
||||||
};
|
};
|
||||||
@ -2028,7 +2024,7 @@ findUnwindTarget(MyThread* t, void** targetIp, void** targetStack,
|
|||||||
if (handler) {
|
if (handler) {
|
||||||
*targetIp = handler;
|
*targetIp = handler;
|
||||||
|
|
||||||
stack = nextFrame(t, ip, stack, method);
|
nextFrame(t, &ip, &stack, method, target);
|
||||||
|
|
||||||
void** sp = static_cast<void**>(stackForFrame(t, stack, method))
|
void** sp = static_cast<void**>(stackForFrame(t, stack, method))
|
||||||
+ t->arch->frameReturnAddressSize();
|
+ t->arch->frameReturnAddressSize();
|
||||||
@ -2040,8 +2036,7 @@ findUnwindTarget(MyThread* t, void** targetIp, void** targetStack,
|
|||||||
|
|
||||||
t->exception = 0;
|
t->exception = 0;
|
||||||
} else {
|
} else {
|
||||||
stack = nextFrame(t, ip, stack, method);
|
nextFrame(t, &ip, &stack, method, target);
|
||||||
ip = t->arch->frameIp(stack);
|
|
||||||
|
|
||||||
if (t->exception) {
|
if (t->exception) {
|
||||||
releaseLock(t, method, stack);
|
releaseLock(t, method, stack);
|
||||||
@ -2126,7 +2121,8 @@ makeCurrentContinuation(MyThread* t, void** targetIp, void** targetStack)
|
|||||||
top += argumentFootprint - alignment;
|
top += argumentFootprint - alignment;
|
||||||
}
|
}
|
||||||
|
|
||||||
stack = nextFrame(t, ip, stack, method);
|
void* nextIp = ip;
|
||||||
|
nextFrame(t, &nextIp, &stack, method, target);
|
||||||
|
|
||||||
void** bottom = static_cast<void**>(stack)
|
void** bottom = static_cast<void**>(stack)
|
||||||
+ t->arch->frameReturnAddressSize();
|
+ t->arch->frameReturnAddressSize();
|
||||||
@ -2156,7 +2152,7 @@ makeCurrentContinuation(MyThread* t, void** targetIp, void** targetStack)
|
|||||||
}
|
}
|
||||||
last = c;
|
last = c;
|
||||||
|
|
||||||
ip = t->arch->frameIp(stack);
|
ip = nextIp;
|
||||||
|
|
||||||
target = method;
|
target = method;
|
||||||
} else {
|
} else {
|
||||||
@ -5224,20 +5220,21 @@ translateLineNumberTable(MyThread* t, Compiler* c, object code, intptr_t start)
|
|||||||
}
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
makeFrameSizeTable(MyThread* t, Context* c, unsigned codeSize)
|
makeFrameTable(MyThread* t, Context* c, unsigned codeSize)
|
||||||
{
|
{
|
||||||
Assembler* a = c->assembler;
|
Assembler* a = c->assembler;
|
||||||
unsigned count = a->frameSizeEventCount();
|
unsigned count = a->frameEventCount();
|
||||||
int max = alignedFrameSize(t, c->method);
|
if (count == 0) {
|
||||||
unsigned indexSize = ceiling(count * bitsNeeded(codeSize), 32);
|
return 0;
|
||||||
unsigned tableSize = ceiling(count * bitsNeeded(max), 32);
|
}
|
||||||
object table = makeIntArray(t, 1 + indexSize + tableSize);
|
|
||||||
|
unsigned size = ceiling(count * bitsNeeded(codeSize), 32);
|
||||||
|
object table = makeIntArray(t, 1 + size);
|
||||||
|
|
||||||
intArrayBody(t, table, 0) = count;
|
intArrayBody(t, table, 0) = count;
|
||||||
|
|
||||||
unsigned index = 0;
|
unsigned index = 0;
|
||||||
int value = 0;
|
for (Assembler::FrameEvent* e = a->firstFrameEvent();
|
||||||
for (Assembler::FrameSizeEvent* e = a->firstFrameSizeEvent();
|
|
||||||
e; e = e->next())
|
e; e = e->next())
|
||||||
{
|
{
|
||||||
assert(t, index < count);
|
assert(t, index < count);
|
||||||
@ -5245,16 +5242,7 @@ makeFrameSizeTable(MyThread* t, Context* c, unsigned codeSize)
|
|||||||
unsigned offset = e->offset();
|
unsigned offset = e->offset();
|
||||||
assert(t, offset <= codeSize);
|
assert(t, offset <= codeSize);
|
||||||
|
|
||||||
value += e->change();
|
|
||||||
|
|
||||||
fprintf(stderr, "offset %d change %d value %d\n",
|
|
||||||
offset, e->change(), value);
|
|
||||||
|
|
||||||
assert(t, value >= 0);
|
|
||||||
assert(t, value <= max);
|
|
||||||
|
|
||||||
setTableValue(t, table, 1, codeSize, index, offset);
|
setTableValue(t, table, 1, codeSize, index, offset);
|
||||||
setTableValue(t, table, 1 + indexSize, max, index, value);
|
|
||||||
|
|
||||||
++ index;
|
++ index;
|
||||||
}
|
}
|
||||||
@ -5950,12 +5938,12 @@ finish(MyThread* t, Allocator* allocator, Context* context)
|
|||||||
|
|
||||||
PROTECT(t, newLineNumberTable);
|
PROTECT(t, newLineNumberTable);
|
||||||
|
|
||||||
object frameSizeTable = makeFrameSizeTable(t, context, codeSize);
|
object frameTable = makeFrameTable(t, context, codeSize);
|
||||||
|
|
||||||
object code = methodCode(t, context->method);
|
object code = methodCode(t, context->method);
|
||||||
|
|
||||||
code = makeCode
|
code = makeCode
|
||||||
(t, 0, newExceptionHandlerTable, newLineNumberTable, frameSizeTable,
|
(t, 0, newExceptionHandlerTable, newLineNumberTable, frameTable,
|
||||||
reinterpret_cast<uintptr_t>(start), codeMaxStack(t, code),
|
reinterpret_cast<uintptr_t>(start), codeMaxStack(t, code),
|
||||||
codeMaxLocals(t, code), 0);
|
codeMaxLocals(t, code), 0);
|
||||||
|
|
||||||
@ -6700,6 +6688,7 @@ visitStack(MyThread* t, Heap::Visitor* v)
|
|||||||
|
|
||||||
MyThread::CallTrace* trace = t->trace;
|
MyThread::CallTrace* trace = t->trace;
|
||||||
object targetMethod = (trace ? trace->targetMethod : 0);
|
object targetMethod = (trace ? trace->targetMethod : 0);
|
||||||
|
object target = targetMethod;
|
||||||
|
|
||||||
while (stack) {
|
while (stack) {
|
||||||
if (targetMethod) {
|
if (targetMethod) {
|
||||||
@ -6711,11 +6700,14 @@ visitStack(MyThread* t, Heap::Visitor* v)
|
|||||||
if (method) {
|
if (method) {
|
||||||
PROTECT(t, method);
|
PROTECT(t, method);
|
||||||
|
|
||||||
stack = nextFrame(t, ip, stack, method);
|
void* nextIp = ip;
|
||||||
|
nextFrame(t, &nextIp, &stack, method, target);
|
||||||
|
|
||||||
visitStackAndLocals(t, v, stack, method, ip);
|
visitStackAndLocals(t, v, stack, method, ip);
|
||||||
|
|
||||||
ip = t->arch->frameIp(stack);
|
ip = nextIp;
|
||||||
|
|
||||||
|
target = method;
|
||||||
} else if (trace) {
|
} else if (trace) {
|
||||||
stack = trace->stack;
|
stack = trace->stack;
|
||||||
ip = t->arch->frameIp(stack);
|
ip = t->arch->frameIp(stack);
|
||||||
@ -6723,6 +6715,9 @@ visitStack(MyThread* t, Heap::Visitor* v)
|
|||||||
|
|
||||||
if (trace) {
|
if (trace) {
|
||||||
targetMethod = trace->targetMethod;
|
targetMethod = trace->targetMethod;
|
||||||
|
target = targetMethod;
|
||||||
|
} else {
|
||||||
|
target = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
@ -7665,13 +7660,14 @@ class MyProcessor: public Processor {
|
|||||||
t(t), p(p), target(target), trace(0)
|
t(t), p(p), target(target), trace(0)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual void visit(void* ip, void* stack) {
|
virtual void visit(void* ip, void* stack, void* link) {
|
||||||
MyThread::TraceContext c(target);
|
MyThread::TraceContext c(target, link);
|
||||||
|
|
||||||
if (methodForIp(t, ip)) {
|
if (methodForIp(t, ip)) {
|
||||||
// we caught the thread in Java code - use the register values
|
// we caught the thread in Java code - use the register values
|
||||||
c.ip = ip;
|
c.ip = ip;
|
||||||
c.stack = stack;
|
c.stack = stack;
|
||||||
|
c.javaStackLimit = stack;
|
||||||
} else if (target->transition) {
|
} else if (target->transition) {
|
||||||
// we caught the thread in native code while in the middle
|
// we caught the thread in native code while in the middle
|
||||||
// of updating the context fields (MyThread::stack, etc.)
|
// of updating the context fields (MyThread::stack, etc.)
|
||||||
|
@ -834,6 +834,7 @@ handleSignal(int signal, siginfo_t* info, void* context)
|
|||||||
void* ip = reinterpret_cast<void*>(IP_REGISTER(c));
|
void* ip = reinterpret_cast<void*>(IP_REGISTER(c));
|
||||||
void* stack = reinterpret_cast<void*>(STACK_REGISTER(c));
|
void* stack = reinterpret_cast<void*>(STACK_REGISTER(c));
|
||||||
void* thread = reinterpret_cast<void*>(THREAD_REGISTER(c));
|
void* thread = reinterpret_cast<void*>(THREAD_REGISTER(c));
|
||||||
|
void* link = reinterpret_cast<void*>(LINK_REGISTER(c));
|
||||||
|
|
||||||
unsigned index;
|
unsigned index;
|
||||||
|
|
||||||
@ -841,7 +842,7 @@ handleSignal(int signal, siginfo_t* info, void* context)
|
|||||||
case VisitSignal: {
|
case VisitSignal: {
|
||||||
index = VisitSignalIndex;
|
index = VisitSignalIndex;
|
||||||
|
|
||||||
system->threadVisitor->visit(ip, stack);
|
system->threadVisitor->visit(ip, stack, link);
|
||||||
|
|
||||||
System::Thread* t = system->visitTarget;
|
System::Thread* t = system->visitTarget;
|
||||||
system->visitTarget = 0;
|
system->visitTarget = 0;
|
||||||
|
@ -35,7 +35,7 @@ class System {
|
|||||||
|
|
||||||
class ThreadVisitor {
|
class ThreadVisitor {
|
||||||
public:
|
public:
|
||||||
virtual void visit(void* ip, void* stack) = 0;
|
virtual void visit(void* ip, void* stack, void* link) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Runnable {
|
class Runnable {
|
||||||
|
@ -86,7 +86,7 @@
|
|||||||
(object pool)
|
(object pool)
|
||||||
(object exceptionHandlerTable)
|
(object exceptionHandlerTable)
|
||||||
(object lineNumberTable)
|
(object lineNumberTable)
|
||||||
(object frameSizeTable)
|
(object frameTable)
|
||||||
(intptr_t compiled)
|
(intptr_t compiled)
|
||||||
(uint16_t maxStack)
|
(uint16_t maxStack)
|
||||||
(uint16_t maxLocals)
|
(uint16_t maxLocals)
|
||||||
|
222
src/x86.cpp
222
src/x86.cpp
@ -72,8 +72,6 @@ const int LongJumpRegister = r10;
|
|||||||
const unsigned StackAlignmentInBytes = 16;
|
const unsigned StackAlignmentInBytes = 16;
|
||||||
const unsigned StackAlignmentInWords = StackAlignmentInBytes / BytesPerWord;
|
const unsigned StackAlignmentInWords = StackAlignmentInBytes / BytesPerWord;
|
||||||
|
|
||||||
const int FrameSizePoison = -2147483647;
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
isInt8(intptr_t v)
|
isInt8(intptr_t v)
|
||||||
{
|
{
|
||||||
@ -88,7 +86,7 @@ isInt32(intptr_t v)
|
|||||||
|
|
||||||
class Task;
|
class Task;
|
||||||
class AlignmentPadding;
|
class AlignmentPadding;
|
||||||
class MyFrameSizeEvent;
|
class MyFrameEvent;
|
||||||
|
|
||||||
unsigned
|
unsigned
|
||||||
padding(AlignmentPadding* p, unsigned index, unsigned offset,
|
padding(AlignmentPadding* p, unsigned index, unsigned offset,
|
||||||
@ -97,17 +95,14 @@ padding(AlignmentPadding* p, unsigned index, unsigned offset,
|
|||||||
class Context;
|
class Context;
|
||||||
class MyBlock;
|
class MyBlock;
|
||||||
|
|
||||||
void
|
|
||||||
appendFrameSizeEvent(Context* c, MyBlock* b, Promise* offset, int change);
|
|
||||||
|
|
||||||
ResolvedPromise*
|
ResolvedPromise*
|
||||||
resolved(Context* c, int64_t value);
|
resolved(Context* c, int64_t value);
|
||||||
|
|
||||||
class MyBlock: public Assembler::Block {
|
class MyBlock: public Assembler::Block {
|
||||||
public:
|
public:
|
||||||
MyBlock(unsigned offset):
|
MyBlock(unsigned offset):
|
||||||
next(0), firstPadding(0), lastPadding(0), firstFrameSizeEvent(0),
|
next(0), firstPadding(0), lastPadding(0), firstFrameEvent(0),
|
||||||
lastFrameSizeEvent(0), offset(offset), start(~0), size(0)
|
lastFrameEvent(0), offset(offset), start(~0), size(0)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual unsigned resolve(unsigned start, Assembler::Block* next) {
|
virtual unsigned resolve(unsigned start, Assembler::Block* next) {
|
||||||
@ -120,8 +115,8 @@ class MyBlock: public Assembler::Block {
|
|||||||
MyBlock* next;
|
MyBlock* next;
|
||||||
AlignmentPadding* firstPadding;
|
AlignmentPadding* firstPadding;
|
||||||
AlignmentPadding* lastPadding;
|
AlignmentPadding* lastPadding;
|
||||||
MyFrameSizeEvent* firstFrameSizeEvent;
|
MyFrameEvent* firstFrameEvent;
|
||||||
MyFrameSizeEvent* lastFrameSizeEvent;
|
MyFrameEvent* lastFrameEvent;
|
||||||
unsigned offset;
|
unsigned offset;
|
||||||
unsigned start;
|
unsigned start;
|
||||||
unsigned size;
|
unsigned size;
|
||||||
@ -164,8 +159,8 @@ class Context {
|
|||||||
Context(System* s, Allocator* a, Zone* zone, ArchitectureContext* ac):
|
Context(System* s, Allocator* a, Zone* zone, ArchitectureContext* ac):
|
||||||
s(s), zone(zone), client(0), code(s, a, 1024), tasks(0), result(0),
|
s(s), zone(zone), client(0), code(s, a, 1024), tasks(0), result(0),
|
||||||
firstBlock(new (zone->allocate(sizeof(MyBlock))) MyBlock(0)),
|
firstBlock(new (zone->allocate(sizeof(MyBlock))) MyBlock(0)),
|
||||||
lastBlock(firstBlock), firstFrameSizeEvent(0), lastFrameSizeEvent(0),
|
lastBlock(firstBlock), firstFrameEvent(0), lastFrameEvent(0),
|
||||||
ac(ac), frameSizeEventCount(0)
|
ac(ac), frameEventCount(0)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
System* s;
|
System* s;
|
||||||
@ -176,10 +171,10 @@ class Context {
|
|||||||
uint8_t* result;
|
uint8_t* result;
|
||||||
MyBlock* firstBlock;
|
MyBlock* firstBlock;
|
||||||
MyBlock* lastBlock;
|
MyBlock* lastBlock;
|
||||||
MyFrameSizeEvent* firstFrameSizeEvent;
|
MyFrameEvent* firstFrameEvent;
|
||||||
MyFrameSizeEvent* lastFrameSizeEvent;
|
MyFrameEvent* lastFrameEvent;
|
||||||
ArchitectureContext* ac;
|
ArchitectureContext* ac;
|
||||||
unsigned frameSizeEventCount;
|
unsigned frameEventCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
void NO_RETURN
|
void NO_RETURN
|
||||||
@ -466,52 +461,45 @@ padding(AlignmentPadding* p, unsigned start, unsigned offset,
|
|||||||
return padding;
|
return padding;
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyFrameSizeEvent: public Assembler::FrameSizeEvent {
|
class MyFrameEvent: public Assembler::FrameEvent {
|
||||||
public:
|
public:
|
||||||
MyFrameSizeEvent(Context* c, Promise* offset, int change):
|
MyFrameEvent(Context* c, Promise* offset):
|
||||||
c(c), next_(0), offset_(offset), change_(change)
|
c(c), next_(0), offset_(offset)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual unsigned offset() {
|
virtual unsigned offset() {
|
||||||
return offset_->value();
|
return offset_->value();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int change() {
|
virtual Assembler::FrameEvent* next() {
|
||||||
expect(c, change_ != FrameSizePoison);
|
|
||||||
|
|
||||||
return change_;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual Assembler::FrameSizeEvent* next() {
|
|
||||||
return next_;
|
return next_;
|
||||||
}
|
}
|
||||||
|
|
||||||
Context* c;
|
Context* c;
|
||||||
MyFrameSizeEvent* next_;
|
MyFrameEvent* next_;
|
||||||
Promise* offset_;
|
Promise* offset_;
|
||||||
int change_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
appendFrameSizeEvent(Context* c, MyBlock* b, Promise* offset, int change)
|
appendFrameEvent(Context* c, MyBlock* b, Promise* offset)
|
||||||
{
|
{
|
||||||
MyFrameSizeEvent* e = new (c->zone->allocate(sizeof(MyFrameSizeEvent)))
|
MyFrameEvent* e = new (c->zone->allocate(sizeof(MyFrameEvent)))
|
||||||
MyFrameSizeEvent(c, offset, change);
|
MyFrameEvent(c, offset);
|
||||||
|
|
||||||
if (b->firstFrameSizeEvent) {
|
if (b->firstFrameEvent) {
|
||||||
b->lastFrameSizeEvent->next_ = e;
|
b->lastFrameEvent->next_ = e;
|
||||||
} else {
|
} else {
|
||||||
b->firstFrameSizeEvent = e;
|
b->firstFrameEvent = e;
|
||||||
}
|
}
|
||||||
b->lastFrameSizeEvent = e;
|
b->lastFrameEvent = e;
|
||||||
|
|
||||||
++ c->frameSizeEventCount;
|
++ c->frameEventCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
appendFrameSizeEvent(Context* c, int change)
|
appendFrameEvent(Context* c)
|
||||||
{
|
{
|
||||||
appendFrameSizeEvent(c, c->lastBlock, offset(c), change);
|
appendFrameEvent(c, c->lastBlock, offset(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" bool
|
extern "C" bool
|
||||||
@ -2574,6 +2562,93 @@ absoluteRR(Context* c, unsigned aSize, Assembler::Register* a,
|
|||||||
c->client->releaseTemporary(rdx);
|
c->client->releaseTemporary(rdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned
|
||||||
|
argumentFootprint(unsigned footprint)
|
||||||
|
{
|
||||||
|
return max(pad(footprint, StackAlignmentInWords), StackAlignmentInWords);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
read4(uint8_t* p)
|
||||||
|
{
|
||||||
|
uint32_t v; memcpy(&v, p, 4);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nextFrame(ArchitectureContext* c, uint8_t* start, unsigned size,
|
||||||
|
unsigned footprint, int32_t*, void*, void* stackLimit,
|
||||||
|
unsigned targetParameterFootprint, void** ip, void** stack)
|
||||||
|
{
|
||||||
|
assert(c, *ip >= start);
|
||||||
|
assert(c, *ip <= start + size);
|
||||||
|
|
||||||
|
uint8_t* instruction = static_cast<uint8_t*>(*ip);
|
||||||
|
|
||||||
|
if (BytesPerWord == 4) {
|
||||||
|
if (*start == 0x39) {
|
||||||
|
// skip stack overflow check
|
||||||
|
start += 11;
|
||||||
|
}
|
||||||
|
} else if (*start == 0x48 and start[1] == 0x39) {
|
||||||
|
// skip stack overflow check
|
||||||
|
start += 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instruction <= start) {
|
||||||
|
*ip = reinterpret_cast<void**>(*stack)[0];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UseFramePointer) {
|
||||||
|
// skip preamble
|
||||||
|
start += (BytesPerWord == 4 ? 3 : 4);
|
||||||
|
|
||||||
|
if (instruction <= start or *instruction == 0x5d) {
|
||||||
|
*ip = reinterpret_cast<void**>(*stack)[1];
|
||||||
|
*stack = reinterpret_cast<void**>(*stack) + 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*instruction == 0xc3) {
|
||||||
|
*ip = reinterpret_cast<void**>(*stack)[0];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned offset = footprint + FrameHeaderSize
|
||||||
|
- (stackLimit == *stack ? 1 : 0);
|
||||||
|
|
||||||
|
if (TailCalls) {
|
||||||
|
if (argumentFootprint(targetParameterFootprint) > StackAlignmentInWords) {
|
||||||
|
offset += argumentFootprint(targetParameterFootprint)
|
||||||
|
- StackAlignmentInWords;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BytesPerWord == 4) {
|
||||||
|
if ((*instruction == 0x83 or *instruction == 0x81)
|
||||||
|
and instruction[1] == 0xec)
|
||||||
|
{
|
||||||
|
offset
|
||||||
|
-= (*instruction == 0x83 ? instruction[2] : read4(instruction + 2))
|
||||||
|
/ BytesPerWord;
|
||||||
|
}
|
||||||
|
} else if (*instruction == 0x48
|
||||||
|
and (instruction[1] == 0x83 or instruction[1] == 0x81)
|
||||||
|
and instruction[2] == 0xec)
|
||||||
|
{
|
||||||
|
offset
|
||||||
|
-= (instruction[1] == 0x83 ? instruction[3] : read4(instruction + 3))
|
||||||
|
/ BytesPerWord;
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo: use frameTable to check for and handle tail calls
|
||||||
|
}
|
||||||
|
|
||||||
|
*ip = reinterpret_cast<void**>(*stack)[offset];
|
||||||
|
*stack = reinterpret_cast<void**>(*stack) + offset;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
populateTables(ArchitectureContext* c)
|
populateTables(ArchitectureContext* c)
|
||||||
{
|
{
|
||||||
@ -2771,7 +2846,7 @@ class MyArchitecture: public Assembler::Architecture {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned argumentFootprint(unsigned footprint) {
|
virtual unsigned argumentFootprint(unsigned footprint) {
|
||||||
return max(pad(footprint, StackAlignmentInWords), StackAlignmentInWords);
|
return local::argumentFootprint(footprint);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool argumentAlignment() {
|
virtual bool argumentAlignment() {
|
||||||
@ -2900,6 +2975,16 @@ class MyArchitecture: public Assembler::Architecture {
|
|||||||
- FrameHeaderSize;
|
- FrameHeaderSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void nextFrame(void* start, unsigned size, unsigned footprint,
|
||||||
|
int32_t* frameTable, void* link, void* stackLimit,
|
||||||
|
unsigned targetParameterFootprint, void** ip,
|
||||||
|
void** stack)
|
||||||
|
{
|
||||||
|
local::nextFrame(&c, static_cast<uint8_t*>(start), size, footprint,
|
||||||
|
frameTable, link, stackLimit, targetParameterFootprint,
|
||||||
|
ip, stack);
|
||||||
|
}
|
||||||
|
|
||||||
virtual void* frameIp(void* stack) {
|
virtual void* frameIp(void* stack) {
|
||||||
return stack ? *static_cast<void**>(stack) : 0;
|
return stack ? *static_cast<void**>(stack) : 0;
|
||||||
}
|
}
|
||||||
@ -3397,28 +3482,20 @@ class MyAssembler: public Assembler {
|
|||||||
|
|
||||||
apply(Move, BytesPerWord, RegisterOperand, &stack,
|
apply(Move, BytesPerWord, RegisterOperand, &stack,
|
||||||
BytesPerWord, RegisterOperand, &base);
|
BytesPerWord, RegisterOperand, &base);
|
||||||
|
|
||||||
appendFrameSizeEvent(&c, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Constant footprintConstant(resolved(&c, footprint * BytesPerWord));
|
Constant footprintConstant(resolved(&c, footprint * BytesPerWord));
|
||||||
apply(Subtract, BytesPerWord, ConstantOperand, &footprintConstant,
|
apply(Subtract, BytesPerWord, ConstantOperand, &footprintConstant,
|
||||||
BytesPerWord, RegisterOperand, &stack,
|
BytesPerWord, RegisterOperand, &stack,
|
||||||
BytesPerWord, RegisterOperand, &stack);
|
BytesPerWord, RegisterOperand, &stack);
|
||||||
|
|
||||||
appendFrameSizeEvent(&c, footprint);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void adjustFrame(unsigned difference) {
|
virtual void adjustFrame(unsigned difference) {
|
||||||
appendFrameSizeEvent(&c, - difference);
|
|
||||||
|
|
||||||
Register stack(rsp);
|
Register stack(rsp);
|
||||||
Constant differenceConstant(resolved(&c, difference * BytesPerWord));
|
Constant differenceConstant(resolved(&c, difference * BytesPerWord));
|
||||||
apply(Subtract, BytesPerWord, ConstantOperand, &differenceConstant,
|
apply(Subtract, BytesPerWord, ConstantOperand, &differenceConstant,
|
||||||
BytesPerWord, RegisterOperand, &stack,
|
BytesPerWord, RegisterOperand, &stack,
|
||||||
BytesPerWord, RegisterOperand, &stack);
|
BytesPerWord, RegisterOperand, &stack);
|
||||||
|
|
||||||
appendFrameSizeEvent(&c, difference);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void popFrame(unsigned frameFootprint) {
|
virtual void popFrame(unsigned frameFootprint) {
|
||||||
@ -3428,19 +3505,13 @@ class MyAssembler: public Assembler {
|
|||||||
apply(Move, BytesPerWord, RegisterOperand, &base,
|
apply(Move, BytesPerWord, RegisterOperand, &base,
|
||||||
BytesPerWord, RegisterOperand, &stack);
|
BytesPerWord, RegisterOperand, &stack);
|
||||||
|
|
||||||
appendFrameSizeEvent(&c, - frameFootprint);
|
|
||||||
|
|
||||||
popR(&c, BytesPerWord, &base);
|
popR(&c, BytesPerWord, &base);
|
||||||
|
|
||||||
appendFrameSizeEvent(&c, - 1);
|
|
||||||
} else {
|
} else {
|
||||||
Register stack(rsp);
|
Register stack(rsp);
|
||||||
Constant footprint(resolved(&c, frameFootprint * BytesPerWord));
|
Constant footprint(resolved(&c, frameFootprint * BytesPerWord));
|
||||||
apply(Add, BytesPerWord, ConstantOperand, &footprint,
|
apply(Add, BytesPerWord, ConstantOperand, &footprint,
|
||||||
BytesPerWord, RegisterOperand, &stack,
|
BytesPerWord, RegisterOperand, &stack,
|
||||||
BytesPerWord, RegisterOperand, &stack);
|
BytesPerWord, RegisterOperand, &stack);
|
||||||
|
|
||||||
appendFrameSizeEvent(&c, - frameFootprint);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3451,13 +3522,18 @@ class MyAssembler: public Assembler {
|
|||||||
{
|
{
|
||||||
if (TailCalls) {
|
if (TailCalls) {
|
||||||
if (offset) {
|
if (offset) {
|
||||||
|
appendFrameEvent(&c);
|
||||||
|
|
||||||
Register tmp(c.client->acquireTemporary());
|
Register tmp(c.client->acquireTemporary());
|
||||||
|
|
||||||
Memory returnAddressSrc(rsp, (frameFootprint + 1) * BytesPerWord);
|
unsigned baseSize = UseFramePointer ? 1 : 0;
|
||||||
|
|
||||||
|
Memory returnAddressSrc
|
||||||
|
(rsp, (frameFootprint + baseSize) * BytesPerWord);
|
||||||
moveMR(&c, BytesPerWord, &returnAddressSrc, BytesPerWord, &tmp);
|
moveMR(&c, BytesPerWord, &returnAddressSrc, BytesPerWord, &tmp);
|
||||||
|
|
||||||
Memory returnAddressDst
|
Memory returnAddressDst
|
||||||
(rsp, (frameFootprint - offset + 1) * BytesPerWord);
|
(rsp, (frameFootprint - offset + baseSize) * BytesPerWord);
|
||||||
moveRM(&c, BytesPerWord, &tmp, BytesPerWord, &returnAddressDst);
|
moveRM(&c, BytesPerWord, &tmp, BytesPerWord, &returnAddressDst);
|
||||||
|
|
||||||
c.client->releaseTemporary(tmp.low);
|
c.client->releaseTemporary(tmp.low);
|
||||||
@ -3470,11 +3546,9 @@ class MyAssembler: public Assembler {
|
|||||||
|
|
||||||
Register stack(rsp);
|
Register stack(rsp);
|
||||||
Constant footprint
|
Constant footprint
|
||||||
(resolved(&c, (frameFootprint - offset + 1) * BytesPerWord));
|
(resolved(&c, (frameFootprint - offset + baseSize) * BytesPerWord));
|
||||||
addCR(&c, BytesPerWord, &footprint, BytesPerWord, &stack);
|
addCR(&c, BytesPerWord, &footprint, BytesPerWord, &stack);
|
||||||
|
|
||||||
appendFrameSizeEvent(&c, - (frameFootprint - offset + 1));
|
|
||||||
|
|
||||||
if (returnAddressSurrogate != NoRegister) {
|
if (returnAddressSurrogate != NoRegister) {
|
||||||
assert(&c, offset > 0);
|
assert(&c, offset > 0);
|
||||||
|
|
||||||
@ -3507,6 +3581,8 @@ class MyAssembler: public Assembler {
|
|||||||
assert(&c, (argumentFootprint % StackAlignmentInWords) == 0);
|
assert(&c, (argumentFootprint % StackAlignmentInWords) == 0);
|
||||||
|
|
||||||
if (TailCalls and argumentFootprint > StackAlignmentInWords) {
|
if (TailCalls and argumentFootprint > StackAlignmentInWords) {
|
||||||
|
appendFrameEvent(&c);
|
||||||
|
|
||||||
Register returnAddress(rcx);
|
Register returnAddress(rcx);
|
||||||
popR(&c, BytesPerWord, &returnAddress);
|
popR(&c, BytesPerWord, &returnAddress);
|
||||||
|
|
||||||
@ -3516,16 +3592,10 @@ class MyAssembler: public Assembler {
|
|||||||
* BytesPerWord));
|
* BytesPerWord));
|
||||||
addCR(&c, BytesPerWord, &adjustment, BytesPerWord, &stack);
|
addCR(&c, BytesPerWord, &adjustment, BytesPerWord, &stack);
|
||||||
|
|
||||||
appendFrameSizeEvent(&c, - (argumentFootprint - StackAlignmentInWords));
|
|
||||||
|
|
||||||
jumpR(&c, BytesPerWord, &returnAddress);
|
jumpR(&c, BytesPerWord, &returnAddress);
|
||||||
} else {
|
} else {
|
||||||
return_(&c);
|
return_(&c);
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: this is not necessary if there are no instructions to
|
|
||||||
// follow:
|
|
||||||
appendFrameSizeEvent(&c, frameFootprint);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void popFrameAndUpdateStackAndReturn(unsigned frameFootprint,
|
virtual void popFrameAndUpdateStackAndReturn(unsigned frameFootprint,
|
||||||
@ -3536,16 +3606,10 @@ class MyAssembler: public Assembler {
|
|||||||
Register returnAddress(rcx);
|
Register returnAddress(rcx);
|
||||||
popR(&c, BytesPerWord, &returnAddress);
|
popR(&c, BytesPerWord, &returnAddress);
|
||||||
|
|
||||||
appendFrameSizeEvent(&c, -1);
|
|
||||||
|
|
||||||
Register stack(rsp);
|
Register stack(rsp);
|
||||||
Memory stackSrc(rbx, stackOffsetFromThread);
|
Memory stackSrc(rbx, stackOffsetFromThread);
|
||||||
moveMR(&c, BytesPerWord, &stackSrc, BytesPerWord, &stack);
|
moveMR(&c, BytesPerWord, &stackSrc, BytesPerWord, &stack);
|
||||||
|
|
||||||
// we can't statically determine the frame size at this point, so
|
|
||||||
// we poison any attempt to query for it:
|
|
||||||
appendFrameSizeEvent(&c, FrameSizePoison);
|
|
||||||
|
|
||||||
jumpR(&c, BytesPerWord, &returnAddress);
|
jumpR(&c, BytesPerWord, &returnAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3594,13 +3658,13 @@ class MyAssembler: public Assembler {
|
|||||||
c.result = dst;
|
c.result = dst;
|
||||||
|
|
||||||
for (MyBlock* b = c.firstBlock; b; b = b->next) {
|
for (MyBlock* b = c.firstBlock; b; b = b->next) {
|
||||||
if (b->firstFrameSizeEvent) {
|
if (b->firstFrameEvent) {
|
||||||
if (c.firstFrameSizeEvent) {
|
if (c.firstFrameEvent) {
|
||||||
c.lastFrameSizeEvent->next_ = b->firstFrameSizeEvent;
|
c.lastFrameEvent->next_ = b->firstFrameEvent;
|
||||||
} else {
|
} else {
|
||||||
c.firstFrameSizeEvent = b->firstFrameSizeEvent;
|
c.firstFrameEvent = b->firstFrameEvent;
|
||||||
}
|
}
|
||||||
c.lastFrameSizeEvent = b->lastFrameSizeEvent;
|
c.lastFrameEvent = b->lastFrameEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned index = 0;
|
unsigned index = 0;
|
||||||
@ -3656,12 +3720,12 @@ class MyAssembler: public Assembler {
|
|||||||
return c.code.length();
|
return c.code.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned frameSizeEventCount() {
|
virtual unsigned frameEventCount() {
|
||||||
return c.frameSizeEventCount;
|
return c.frameEventCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual FrameSizeEvent* firstFrameSizeEvent() {
|
virtual FrameEvent* firstFrameEvent() {
|
||||||
return c.firstFrameSizeEvent;
|
return c.firstFrameEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void dispose() {
|
virtual void dispose() {
|
||||||
|
12
src/x86.h
12
src/x86.h
@ -29,20 +29,20 @@
|
|||||||
# ifdef __APPLE__
|
# ifdef __APPLE__
|
||||||
# if __DARWIN_UNIX03 && defined(_STRUCT_X86_EXCEPTION_STATE32)
|
# if __DARWIN_UNIX03 && defined(_STRUCT_X86_EXCEPTION_STATE32)
|
||||||
# define IP_REGISTER(context) (context->uc_mcontext->__ss.__eip)
|
# define IP_REGISTER(context) (context->uc_mcontext->__ss.__eip)
|
||||||
# define BASE_REGISTER(context) (context->uc_mcontext->__ss.__ebp)
|
|
||||||
# define STACK_REGISTER(context) (context->uc_mcontext->__ss.__esp)
|
# define STACK_REGISTER(context) (context->uc_mcontext->__ss.__esp)
|
||||||
# define THREAD_REGISTER(context) (context->uc_mcontext->__ss.__ebx)
|
# define THREAD_REGISTER(context) (context->uc_mcontext->__ss.__ebx)
|
||||||
|
# define LINK_REGISTER(context) (context->uc_mcontext->__ss.__ecx)
|
||||||
# else
|
# else
|
||||||
# define IP_REGISTER(context) (context->uc_mcontext->ss.eip)
|
# define IP_REGISTER(context) (context->uc_mcontext->ss.eip)
|
||||||
# define BASE_REGISTER(context) (context->uc_mcontext->ss.ebp)
|
|
||||||
# define STACK_REGISTER(context) (context->uc_mcontext->ss.esp)
|
# define STACK_REGISTER(context) (context->uc_mcontext->ss.esp)
|
||||||
# define THREAD_REGISTER(context) (context->uc_mcontext->ss.ebx)
|
# define THREAD_REGISTER(context) (context->uc_mcontext->ss.ebx)
|
||||||
|
# define LINK_REGISTER(context) (context->uc_mcontext->ss.ecx)
|
||||||
# endif
|
# endif
|
||||||
# else
|
# else
|
||||||
# define IP_REGISTER(context) (context->uc_mcontext.gregs[REG_EIP])
|
# define IP_REGISTER(context) (context->uc_mcontext.gregs[REG_EIP])
|
||||||
# define BASE_REGISTER(context) (context->uc_mcontext.gregs[REG_EBP])
|
|
||||||
# define STACK_REGISTER(context) (context->uc_mcontext.gregs[REG_ESP])
|
# define STACK_REGISTER(context) (context->uc_mcontext.gregs[REG_ESP])
|
||||||
# define THREAD_REGISTER(context) (context->uc_mcontext.gregs[REG_EBX])
|
# define THREAD_REGISTER(context) (context->uc_mcontext.gregs[REG_EBX])
|
||||||
|
# define LINK_REGISTER(context) (context->uc_mcontext.gregs[REG_ECX])
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
extern "C" uint64_t
|
extern "C" uint64_t
|
||||||
@ -65,20 +65,20 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t*,
|
|||||||
# ifdef __APPLE__
|
# ifdef __APPLE__
|
||||||
# if __DARWIN_UNIX03 && defined(_STRUCT_X86_EXCEPTION_STATE32)
|
# if __DARWIN_UNIX03 && defined(_STRUCT_X86_EXCEPTION_STATE32)
|
||||||
# define IP_REGISTER(context) (context->uc_mcontext->__ss.__rip)
|
# define IP_REGISTER(context) (context->uc_mcontext->__ss.__rip)
|
||||||
# define BASE_REGISTER(context) (context->uc_mcontext->__ss.__rbp)
|
|
||||||
# define STACK_REGISTER(context) (context->uc_mcontext->__ss.__rsp)
|
# define STACK_REGISTER(context) (context->uc_mcontext->__ss.__rsp)
|
||||||
# define THREAD_REGISTER(context) (context->uc_mcontext->__ss.__rbx)
|
# define THREAD_REGISTER(context) (context->uc_mcontext->__ss.__rbx)
|
||||||
|
# define LINK_REGISTER(context) (context->uc_mcontext->__ss.__rcx)
|
||||||
# else
|
# else
|
||||||
# define IP_REGISTER(context) (context->uc_mcontext->ss.rip)
|
# define IP_REGISTER(context) (context->uc_mcontext->ss.rip)
|
||||||
# define BASE_REGISTER(context) (context->uc_mcontext->ss.rbp)
|
|
||||||
# define STACK_REGISTER(context) (context->uc_mcontext->ss.rsp)
|
# define STACK_REGISTER(context) (context->uc_mcontext->ss.rsp)
|
||||||
# define THREAD_REGISTER(context) (context->uc_mcontext->ss.rbx)
|
# define THREAD_REGISTER(context) (context->uc_mcontext->ss.rbx)
|
||||||
|
# define LINK_REGISTER(context) (context->uc_mcontext->ss.rcx)
|
||||||
# endif
|
# endif
|
||||||
# else
|
# else
|
||||||
# define IP_REGISTER(context) (context->uc_mcontext.gregs[REG_RIP])
|
# define IP_REGISTER(context) (context->uc_mcontext.gregs[REG_RIP])
|
||||||
# define BASE_REGISTER(context) (context->uc_mcontext.gregs[REG_RBP])
|
|
||||||
# define STACK_REGISTER(context) (context->uc_mcontext.gregs[REG_RSP])
|
# define STACK_REGISTER(context) (context->uc_mcontext.gregs[REG_RSP])
|
||||||
# define THREAD_REGISTER(context) (context->uc_mcontext.gregs[REG_RBX])
|
# define THREAD_REGISTER(context) (context->uc_mcontext.gregs[REG_RBX])
|
||||||
|
# define LINK_REGISTER(context) (context->uc_mcontext.gregs[REG_RCX])
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
extern "C" uint64_t
|
extern "C" uint64_t
|
||||||
|
Reference in New Issue
Block a user