diff --git a/src/arm.cpp b/src/arm.cpp index 14528b5c59..768e1af9a7 100644 --- a/src/arm.cpp +++ b/src/arm.cpp @@ -164,13 +164,13 @@ inline int carry16(intptr_t v) { return static_cast(v) < 0 ? 1 : 0; } inline bool isOfWidth(long long i, int size) { return static_cast(i) >> size == 0; } inline bool isOfWidth(int i, int size) { return static_cast(i) >> size == 0; } -const unsigned FrameFooterSize = 2; -const unsigned FrameHeaderSize = 0; +const unsigned FrameHeaderSize = (UseFramePointer ? 2 : 1); const unsigned StackAlignmentInBytes = 8; const unsigned StackAlignmentInWords = StackAlignmentInBytes / BytesPerWord; const int ThreadRegister = 8; +const int FrameRegister = 12; const int StackRegister = 13; const int LinkRegister = 14; const int ProgramCounter = 15; @@ -1701,6 +1701,9 @@ class MyArchitecture: public Assembler::Architecture { virtual bool reserved(int register_) { switch (register_) { + case FrameRegister: + return UseFramePointer; + case LinkRegister: case StackRegister: case ThreadRegister: @@ -1781,8 +1784,8 @@ class MyArchitecture: public Assembler::Architecture { } virtual unsigned alignFrameSize(unsigned sizeInWords) { - const unsigned alignment = StackAlignmentInBytes / BytesPerWord; - return (ceiling(sizeInWords + FrameFooterSize, alignment) * alignment); + return pad(sizeInWords + FrameHeaderSize, StackAlignmentInWords) + - FrameHeaderSize; } virtual void* frameIp(void* stack) { @@ -1798,15 +1801,15 @@ class MyArchitecture: public Assembler::Architecture { } virtual unsigned frameFooterSize() { - return FrameFooterSize; + return 0; } virtual int returnAddressOffset() { - return 1; + return -1; } virtual int framePointerOffset() { - return 0; + return -2; } virtual void nextFrame(void** stack, void**) { @@ -2006,11 +2009,14 @@ class MyAssembler: public Assembler { return arch_; } - virtual void saveFrame(unsigned stackOffset, unsigned) { + virtual void saveFrame(unsigned stackOffset) { + appendFrameSizeEvent(&c, FrameSizePoison); + + // ??? Register returnAddress(LinkRegister); - Memory returnAddressDst - (StackRegister, arch_->returnAddressOffset() * BytesPerWord); - moveRM(&c, BytesPerWord, &returnAddress, BytesPerWord, &returnAddressDst); + Memory returnAddressDst(StackRegister, - BytesPerWord); + moveAndUpdateRM(&c, BytesPerWord, &returnAddress, BytesPerWord, + &returnAddressDst); Register stack(StackRegister); Memory stackDst(ThreadRegister, stackOffset); @@ -2059,33 +2065,53 @@ class MyAssembler: public Assembler { } 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); - Register stack(StackRegister); - Memory stackDst(StackRegister, -footprint * BytesPerWord); - moveAndUpdateRM(&c, BytesPerWord, &stack, BytesPerWord, &stackDst); + if (UseFramePointer) { + Register frame(FrameRegister); + Memory frameDst(StackRegister, (footprint - 2) * BytesPerWord); + moveRM(&c, BytesPerWord, &frame, BytesPerWord, &frameDst); + } } - virtual void adjustFrame(unsigned footprint) { - Register nextStack(5); - Memory stackSrc(StackRegister, 0); - moveMR(&c, BytesPerWord, &stackSrc, BytesPerWord, &nextStack); + virtual void adjustFrame(unsigned difference) { + appendFrameSizeEvent(&c, - difference); - Memory stackDst(StackRegister, -footprint * BytesPerWord); - moveAndUpdateRM(&c, BytesPerWord, &nextStack, BytesPerWord, &stackDst); + Register stack(StackRegister); + Constant differenceConstant(resolved(&c, difference * BytesPerWord)); + subCR(&c, BytesPerWord, &differenceConstant, BytesPerWord, &stack, + BytesPerWord, &stack); + + appendFrameSizeEvent(&c, difference); } - virtual void popFrame() { - Register stack(StackRegister); - Memory stackSrc(StackRegister, arch_->framePointerOffset() * BytesPerWord); - moveMR(&c, BytesPerWord, &stackSrc, BytesPerWord, &stack); + virtual void popFrame(unsigned frameFootprint) { + if (UseFramePointer) { + Register frame(FrameRegister); + Memory frameSrc(StackRegister, (frameFootprint - 1) * BytesPerWord); + moveMR(&c, BytesPerWord, &frameSrc, BytesPerWord, &frame); + } Register returnAddress(LinkRegister); - Memory returnAddressSrc(StackRegister, arch_->returnAddressOffset() * BytesPerWord); + Memory returnAddressSrc + (StackRegister, (frameFootprint - 1) * BytesPerWord); 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, @@ -2095,80 +2121,85 @@ class MyAssembler: public Assembler { { if (TailCalls) { if (offset) { + if (UseFramePointer) { + Register frame(FrameRegister); + Memory frameSrc(StackRegister, (footprint - 1) * BytesPerWord); + moveMR(&c, BytesPerWord, &frameSrc, BytesPerWord, &frame); + } + Register link(LinkRegister); Memory returnAddressSrc - (StackRegister, BytesPerWord + (footprint * BytesPerWord)); + (StackRegister, (footprint - 1) * BytesPerWord); moveMR(&c, BytesPerWord, &returnAddressSrc, BytesPerWord, &link); - Register tmp(c.client->acquireTemporary()); - Memory stackSrc(StackRegister, footprint * BytesPerWord); - moveMR(&c, BytesPerWord, &stackSrc, BytesPerWord, &tmp); + Register stack(StackRegister); + Constant footprintConstant + (resolved(&c, (footprint - offset + 1) * BytesPerWord)); + addCR(&c, BytesPerWord, &footprintConstant, BytesPerWord, &stack); - Memory stackDst(StackRegister, (footprint - offset) * BytesPerWord); - moveAndUpdateRM(&c, BytesPerWord, &tmp, BytesPerWord, &stackDst); - - c.client->releaseTemporary(tmp.low); + appendFrameSizeEvent(&c, - (frameFootprint - offset + 1)); if (returnAddressSurrogate != NoRegister) { assert(&c, offset > 0); Register ras(returnAddressSurrogate); - Memory dst(StackRegister, BytesPerWord + (offset * BytesPerWord)); + Memory dst(StackRegister, (offset - 1) * BytesPerWord); moveRM(&c, BytesPerWord, &ras, BytesPerWord, &dst); } if (framePointerSurrogate != NoRegister) { assert(&c, offset > 0); - Register fps(framePointerSurrogate); - Memory dst(StackRegister, offset * BytesPerWord); - moveRM(&c, BytesPerWord, &fps, BytesPerWord, &dst); + Register las(framePointerSurrogate); + Memory dst(StackRegister, (offset - 2) * BytesPerWord); + moveRM(&c, BytesPerWord, &las, BytesPerWord, &dst); } } else { - popFrame(); + popFrame(footprint); } } else { abort(&c); } } - virtual void popFrameAndPopArgumentsAndReturn(unsigned argumentFootprint) { - popFrame(); + virtual void popFrameAndPopArgumentsAndReturn(unsigned frameFootprint, + unsigned argumentFootprint) + { + popFrame(frameFootprint); assert(&c, argumentFootprint >= StackAlignmentInWords); assert(&c, (argumentFootprint % StackAlignmentInWords) == 0); + unsigned offset; if (TailCalls and argumentFootprint > StackAlignmentInWords) { - Register tmp(5); - Memory stackSrc(StackRegister, 0); - moveMR(&c, BytesPerWord, &stackSrc, BytesPerWord, &tmp); + offset = argumentFootprint - StackAlignmentInWords; - Memory stackDst(StackRegister, - (argumentFootprint - StackAlignmentInWords) - * BytesPerWord); - moveAndUpdateRM(&c, BytesPerWord, &tmp, BytesPerWord, &stackDst); + Register stack(StackRegister); + Constant adjustment(resolved(&c, offset * BytesPerWord)); + addCR(&c, BytesPerWord, &adjustment, BytesPerWord, &stack); + + appendFrameSizeEvent(&c, - offset); + } else { + offset = 0; } 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); - Memory stackSrc(StackRegister, 0); - moveMR(&c, BytesPerWord, &stackSrc, BytesPerWord, &tmp1); - - Register tmp2(5); - Memory newStackSrc(ThreadRegister, stackOffsetFromThread); - moveMR(&c, BytesPerWord, &newStackSrc, BytesPerWord, &tmp2); + popFrame(frameFootprint); Register stack(StackRegister); - subR(&c, BytesPerWord, &stack, &tmp2, &tmp2); - - Memory stackDst(StackRegister, 0, tmp2.low); - moveAndUpdateRM(&c, BytesPerWord, &tmp1, BytesPerWord, &stackDst); + Memory newStackSrc(ThreadRegister, stackOffsetFromThread); + moveMR(&c, BytesPerWord, &newStackSrc, BytesPerWord, &stack); return_(&c); } diff --git a/src/assembler.h b/src/assembler.h index 0cdc788ad1..7edc0b9001 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -304,11 +304,10 @@ class Assembler { virtual unsigned resolve(unsigned start, Block* next) = 0; }; - class FrameSizeEvent { + class FrameEvent { public: virtual unsigned offset() = 0; - virtual int change() = 0; - virtual FrameSizeEvent* next() = 0; + virtual FrameEvent* next() = 0; }; class Architecture { @@ -351,6 +350,10 @@ class Assembler { 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 unsigned frameHeaderSize() = 0; virtual unsigned frameReturnAddressSize() = 0; @@ -437,9 +440,9 @@ class Assembler { virtual unsigned length() = 0; - virtual unsigned frameSizeEventCount() = 0; + virtual unsigned frameEventCount() = 0; - virtual FrameSizeEvent* firstFrameSizeEvent() = 0; + virtual FrameEvent* firstFrameEvent() = 0; virtual void dispose() = 0; }; diff --git a/src/compile-x86.S b/src/compile-x86.S index 080b3ba5da..6bf13a5bfb 100644 --- a/src/compile-x86.S +++ b/src/compile-x86.S @@ -295,9 +295,9 @@ LOCAL(vmJumpAndInvoke_argumentTest): #define THREAD_STACK 2148 #define THREAD_SCRATCH 2152 - + #define CALLEE_SAVED_REGISTER_FOOTPRINT 16 - + .globl GLOBAL(vmInvoke) GLOBAL(vmInvoke): pushl %ebp diff --git a/src/compile.cpp b/src/compile.cpp index 42791ca8b4..61112a5fc0 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -153,14 +153,18 @@ class MyThread: public Thread { CallTrace* trace): Context(t, ip, stack, continuation, trace), t(t), + link(0), + javaStackLimit(0), next(t->traceContext) { t->traceContext = this; } - TraceContext(MyThread* t): + TraceContext(MyThread* t, void* link): Context(t, t->ip, t->stack, t->continuation, t->trace), t(t), + link(link), + javaStackLimit(0), next(t->traceContext) { t->traceContext = this; @@ -171,6 +175,8 @@ class MyThread: public Thread { } MyThread* t; + void* link; + void* javaStackLimit; TraceContext* next; }; @@ -414,56 +420,42 @@ getTableValue(Thread* t, object table, unsigned base, unsigned max, (&intArrayBody(t, table, base), bits, index * bits); } -unsigned -frameSize(MyThread* t, intptr_t ip, object method) +void +nextFrame(MyThread* t, void** ip, void** sp, object method, object target) { object code = methodCode(t, method); - object table = codeFrameSizeTable(t, code); - unsigned count = intArrayBody(t, table, 0); - unsigned max = alignedFrameSize(t, method); + object table = codeFrameTable(t, code); intptr_t start = codeCompiled(t, code); - int codeSize = compiledSize(start); - unsigned indexSize = ceiling(count * bitsNeeded(codeSize), 32); - - assert(t, ip >= start); - assert(t, ip <= start + codeSize); + void* link; + void* 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); + if (t->traceContext) { + link = t->traceContext->link; + javaStackLimit = t->traceContext->javaStackLimit; } else { - abort(t); + link = 0; + javaStackLimit = 0; } -} -void* -nextFrame(MyThread* t, void* ip, void* sp, object method) -{ - return reinterpret_cast(sp) + local::frameSize - (t, reinterpret_cast(ip), method) - + t->arch->frameReturnAddressSize(); + // fprintf(stderr, "nextFrame %s.%s%s target %s.%s%s\n", + // &byteArrayBody(t, className(t, methodClass(t, method)), 0), + // &byteArrayBody(t, methodName(t, method), 0), + // &byteArrayBody(t, methodSpec(t, method), 0), + // target + // ? &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(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 { @@ -486,6 +478,7 @@ class MyStackWalker: public Processor::StackWalker { virtual void visit(Heap::Visitor* v) { v->visit(&(walker->method_)); + v->visit(&(walker->target)); v->visit(&(walker->continuation)); } @@ -496,6 +489,7 @@ class MyStackWalker: public Processor::StackWalker { t(t), state(Start), method_(0), + target(0), protector(this) { if (t->traceContext) { @@ -518,6 +512,7 @@ class MyStackWalker: public Processor::StackWalker { stack(w->stack), trace(w->trace), method_(w->method_), + target(w->target), continuation(w->continuation), protector(this) { } @@ -551,6 +546,7 @@ class MyStackWalker: public Processor::StackWalker { case Next: if (stack) { + target = method_; method_ = methodForIp(t, ip_); if (method_) { state = Method; @@ -599,8 +595,7 @@ class MyStackWalker: public Processor::StackWalker { break; case Method: - stack = nextFrame(t, ip_, stack, method_); - ip_ = t->arch->frameIp(stack); + nextFrame(t, &ip_, &stack, method_, target); break; case NativeMethod: @@ -654,6 +649,7 @@ class MyStackWalker: public Processor::StackWalker { void* stack; MyThread::CallTrace* trace; object method_; + object target; object continuation; MyProtector protector; }; @@ -2028,7 +2024,7 @@ findUnwindTarget(MyThread* t, void** targetIp, void** targetStack, if (handler) { *targetIp = handler; - stack = nextFrame(t, ip, stack, method); + nextFrame(t, &ip, &stack, method, target); void** sp = static_cast(stackForFrame(t, stack, method)) + t->arch->frameReturnAddressSize(); @@ -2040,8 +2036,7 @@ findUnwindTarget(MyThread* t, void** targetIp, void** targetStack, t->exception = 0; } else { - stack = nextFrame(t, ip, stack, method); - ip = t->arch->frameIp(stack); + nextFrame(t, &ip, &stack, method, target); if (t->exception) { releaseLock(t, method, stack); @@ -2126,7 +2121,8 @@ makeCurrentContinuation(MyThread* t, void** targetIp, void** targetStack) top += argumentFootprint - alignment; } - stack = nextFrame(t, ip, stack, method); + void* nextIp = ip; + nextFrame(t, &nextIp, &stack, method, target); void** bottom = static_cast(stack) + t->arch->frameReturnAddressSize(); @@ -2156,7 +2152,7 @@ makeCurrentContinuation(MyThread* t, void** targetIp, void** targetStack) } last = c; - ip = t->arch->frameIp(stack); + ip = nextIp; target = method; } else { @@ -5224,20 +5220,21 @@ translateLineNumberTable(MyThread* t, Compiler* c, object code, intptr_t start) } object -makeFrameSizeTable(MyThread* t, Context* c, unsigned codeSize) +makeFrameTable(MyThread* t, Context* c, unsigned codeSize) { Assembler* a = c->assembler; - unsigned count = a->frameSizeEventCount(); - int max = alignedFrameSize(t, c->method); - unsigned indexSize = ceiling(count * bitsNeeded(codeSize), 32); - unsigned tableSize = ceiling(count * bitsNeeded(max), 32); - object table = makeIntArray(t, 1 + indexSize + tableSize); + unsigned count = a->frameEventCount(); + if (count == 0) { + return 0; + } + + unsigned size = ceiling(count * bitsNeeded(codeSize), 32); + object table = makeIntArray(t, 1 + size); intArrayBody(t, table, 0) = count; unsigned index = 0; - int value = 0; - for (Assembler::FrameSizeEvent* e = a->firstFrameSizeEvent(); + for (Assembler::FrameEvent* e = a->firstFrameEvent(); e; e = e->next()) { assert(t, index < count); @@ -5245,17 +5242,8 @@ makeFrameSizeTable(MyThread* t, Context* c, unsigned codeSize) unsigned offset = e->offset(); 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 + indexSize, max, index, value); - + ++ index; } @@ -5950,12 +5938,12 @@ finish(MyThread* t, Allocator* allocator, Context* context) PROTECT(t, newLineNumberTable); - object frameSizeTable = makeFrameSizeTable(t, context, codeSize); + object frameTable = makeFrameTable(t, context, codeSize); object code = methodCode(t, context->method); code = makeCode - (t, 0, newExceptionHandlerTable, newLineNumberTable, frameSizeTable, + (t, 0, newExceptionHandlerTable, newLineNumberTable, frameTable, reinterpret_cast(start), codeMaxStack(t, code), codeMaxLocals(t, code), 0); @@ -6700,6 +6688,7 @@ visitStack(MyThread* t, Heap::Visitor* v) MyThread::CallTrace* trace = t->trace; object targetMethod = (trace ? trace->targetMethod : 0); + object target = targetMethod; while (stack) { if (targetMethod) { @@ -6711,11 +6700,14 @@ visitStack(MyThread* t, Heap::Visitor* v) if (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); - ip = t->arch->frameIp(stack); + ip = nextIp; + + target = method; } else if (trace) { stack = trace->stack; ip = t->arch->frameIp(stack); @@ -6723,6 +6715,9 @@ visitStack(MyThread* t, Heap::Visitor* v) if (trace) { targetMethod = trace->targetMethod; + target = targetMethod; + } else { + target = 0; } } else { break; @@ -7665,13 +7660,14 @@ class MyProcessor: public Processor { t(t), p(p), target(target), trace(0) { } - virtual void visit(void* ip, void* stack) { - MyThread::TraceContext c(target); + virtual void visit(void* ip, void* stack, void* link) { + MyThread::TraceContext c(target, link); if (methodForIp(t, ip)) { // we caught the thread in Java code - use the register values c.ip = ip; c.stack = stack; + c.javaStackLimit = stack; } else if (target->transition) { // we caught the thread in native code while in the middle // of updating the context fields (MyThread::stack, etc.) diff --git a/src/posix.cpp b/src/posix.cpp index 590d8e65ca..8b2496ae81 100644 --- a/src/posix.cpp +++ b/src/posix.cpp @@ -834,6 +834,7 @@ handleSignal(int signal, siginfo_t* info, void* context) void* ip = reinterpret_cast(IP_REGISTER(c)); void* stack = reinterpret_cast(STACK_REGISTER(c)); void* thread = reinterpret_cast(THREAD_REGISTER(c)); + void* link = reinterpret_cast(LINK_REGISTER(c)); unsigned index; @@ -841,7 +842,7 @@ handleSignal(int signal, siginfo_t* info, void* context) case VisitSignal: { index = VisitSignalIndex; - system->threadVisitor->visit(ip, stack); + system->threadVisitor->visit(ip, stack, link); System::Thread* t = system->visitTarget; system->visitTarget = 0; diff --git a/src/system.h b/src/system.h index 8cf08ea88a..258b04f440 100644 --- a/src/system.h +++ b/src/system.h @@ -35,7 +35,7 @@ class System { class ThreadVisitor { public: - virtual void visit(void* ip, void* stack) = 0; + virtual void visit(void* ip, void* stack, void* link) = 0; }; class Runnable { diff --git a/src/types.def b/src/types.def index 7509c431a9..24d4b1854c 100644 --- a/src/types.def +++ b/src/types.def @@ -86,7 +86,7 @@ (object pool) (object exceptionHandlerTable) (object lineNumberTable) - (object frameSizeTable) + (object frameTable) (intptr_t compiled) (uint16_t maxStack) (uint16_t maxLocals) diff --git a/src/x86.cpp b/src/x86.cpp index 676c011da8..eb61e405ad 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -72,8 +72,6 @@ const int LongJumpRegister = r10; const unsigned StackAlignmentInBytes = 16; const unsigned StackAlignmentInWords = StackAlignmentInBytes / BytesPerWord; -const int FrameSizePoison = -2147483647; - bool isInt8(intptr_t v) { @@ -88,7 +86,7 @@ isInt32(intptr_t v) class Task; class AlignmentPadding; -class MyFrameSizeEvent; +class MyFrameEvent; unsigned padding(AlignmentPadding* p, unsigned index, unsigned offset, @@ -97,17 +95,14 @@ padding(AlignmentPadding* p, unsigned index, unsigned offset, class Context; class MyBlock; -void -appendFrameSizeEvent(Context* c, MyBlock* b, Promise* offset, int change); - ResolvedPromise* - resolved(Context* c, int64_t value); +resolved(Context* c, int64_t value); class MyBlock: public Assembler::Block { public: MyBlock(unsigned offset): - next(0), firstPadding(0), lastPadding(0), firstFrameSizeEvent(0), - lastFrameSizeEvent(0), offset(offset), start(~0), size(0) + next(0), firstPadding(0), lastPadding(0), firstFrameEvent(0), + lastFrameEvent(0), offset(offset), start(~0), size(0) { } virtual unsigned resolve(unsigned start, Assembler::Block* next) { @@ -120,8 +115,8 @@ class MyBlock: public Assembler::Block { MyBlock* next; AlignmentPadding* firstPadding; AlignmentPadding* lastPadding; - MyFrameSizeEvent* firstFrameSizeEvent; - MyFrameSizeEvent* lastFrameSizeEvent; + MyFrameEvent* firstFrameEvent; + MyFrameEvent* lastFrameEvent; unsigned offset; unsigned start; unsigned size; @@ -164,8 +159,8 @@ class Context { Context(System* s, Allocator* a, Zone* zone, ArchitectureContext* ac): s(s), zone(zone), client(0), code(s, a, 1024), tasks(0), result(0), firstBlock(new (zone->allocate(sizeof(MyBlock))) MyBlock(0)), - lastBlock(firstBlock), firstFrameSizeEvent(0), lastFrameSizeEvent(0), - ac(ac), frameSizeEventCount(0) + lastBlock(firstBlock), firstFrameEvent(0), lastFrameEvent(0), + ac(ac), frameEventCount(0) { } System* s; @@ -176,10 +171,10 @@ class Context { uint8_t* result; MyBlock* firstBlock; MyBlock* lastBlock; - MyFrameSizeEvent* firstFrameSizeEvent; - MyFrameSizeEvent* lastFrameSizeEvent; + MyFrameEvent* firstFrameEvent; + MyFrameEvent* lastFrameEvent; ArchitectureContext* ac; - unsigned frameSizeEventCount; + unsigned frameEventCount; }; void NO_RETURN @@ -466,52 +461,45 @@ padding(AlignmentPadding* p, unsigned start, unsigned offset, return padding; } -class MyFrameSizeEvent: public Assembler::FrameSizeEvent { +class MyFrameEvent: public Assembler::FrameEvent { public: - MyFrameSizeEvent(Context* c, Promise* offset, int change): - c(c), next_(0), offset_(offset), change_(change) + MyFrameEvent(Context* c, Promise* offset): + c(c), next_(0), offset_(offset) { } virtual unsigned offset() { return offset_->value(); } - virtual int change() { - expect(c, change_ != FrameSizePoison); - - return change_; - } - - virtual Assembler::FrameSizeEvent* next() { + virtual Assembler::FrameEvent* next() { return next_; } Context* c; - MyFrameSizeEvent* next_; + MyFrameEvent* next_; Promise* offset_; - int change_; }; 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))) - MyFrameSizeEvent(c, offset, change); + MyFrameEvent* e = new (c->zone->allocate(sizeof(MyFrameEvent))) + MyFrameEvent(c, offset); - if (b->firstFrameSizeEvent) { - b->lastFrameSizeEvent->next_ = e; + if (b->firstFrameEvent) { + b->lastFrameEvent->next_ = e; } else { - b->firstFrameSizeEvent = e; + b->firstFrameEvent = e; } - b->lastFrameSizeEvent = e; + b->lastFrameEvent = e; - ++ c->frameSizeEventCount; + ++ c->frameEventCount; } 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 @@ -2574,6 +2562,93 @@ absoluteRR(Context* c, unsigned aSize, Assembler::Register* a, 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(*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(*stack)[0]; + return; + } + + if (UseFramePointer) { + // skip preamble + start += (BytesPerWord == 4 ? 3 : 4); + + if (instruction <= start or *instruction == 0x5d) { + *ip = reinterpret_cast(*stack)[1]; + *stack = reinterpret_cast(*stack) + 1; + return; + } + } + + if (*instruction == 0xc3) { + *ip = reinterpret_cast(*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(*stack)[offset]; + *stack = reinterpret_cast(*stack) + offset; +} + void populateTables(ArchitectureContext* c) { @@ -2771,7 +2846,7 @@ class MyArchitecture: public Assembler::Architecture { } virtual unsigned argumentFootprint(unsigned footprint) { - return max(pad(footprint, StackAlignmentInWords), StackAlignmentInWords); + return local::argumentFootprint(footprint); } virtual bool argumentAlignment() { @@ -2900,6 +2975,16 @@ class MyArchitecture: public Assembler::Architecture { - 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(start), size, footprint, + frameTable, link, stackLimit, targetParameterFootprint, + ip, stack); + } + virtual void* frameIp(void* stack) { return stack ? *static_cast(stack) : 0; } @@ -3397,28 +3482,20 @@ class MyAssembler: public Assembler { apply(Move, BytesPerWord, RegisterOperand, &stack, BytesPerWord, RegisterOperand, &base); - - appendFrameSizeEvent(&c, 1); } Constant footprintConstant(resolved(&c, footprint * BytesPerWord)); apply(Subtract, BytesPerWord, ConstantOperand, &footprintConstant, BytesPerWord, RegisterOperand, &stack, BytesPerWord, RegisterOperand, &stack); - - appendFrameSizeEvent(&c, footprint); } virtual void adjustFrame(unsigned difference) { - appendFrameSizeEvent(&c, - difference); - Register stack(rsp); Constant differenceConstant(resolved(&c, difference * BytesPerWord)); apply(Subtract, BytesPerWord, ConstantOperand, &differenceConstant, BytesPerWord, RegisterOperand, &stack, BytesPerWord, RegisterOperand, &stack); - - appendFrameSizeEvent(&c, difference); } virtual void popFrame(unsigned frameFootprint) { @@ -3428,19 +3505,13 @@ class MyAssembler: public Assembler { apply(Move, BytesPerWord, RegisterOperand, &base, BytesPerWord, RegisterOperand, &stack); - appendFrameSizeEvent(&c, - frameFootprint); - popR(&c, BytesPerWord, &base); - - appendFrameSizeEvent(&c, - 1); } else { Register stack(rsp); Constant footprint(resolved(&c, frameFootprint * BytesPerWord)); apply(Add, BytesPerWord, ConstantOperand, &footprint, BytesPerWord, RegisterOperand, &stack, BytesPerWord, RegisterOperand, &stack); - - appendFrameSizeEvent(&c, - frameFootprint); } } @@ -3451,13 +3522,18 @@ class MyAssembler: public Assembler { { if (TailCalls) { if (offset) { + appendFrameEvent(&c); + 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); Memory returnAddressDst - (rsp, (frameFootprint - offset + 1) * BytesPerWord); + (rsp, (frameFootprint - offset + baseSize) * BytesPerWord); moveRM(&c, BytesPerWord, &tmp, BytesPerWord, &returnAddressDst); c.client->releaseTemporary(tmp.low); @@ -3470,11 +3546,9 @@ class MyAssembler: public Assembler { Register stack(rsp); Constant footprint - (resolved(&c, (frameFootprint - offset + 1) * BytesPerWord)); + (resolved(&c, (frameFootprint - offset + baseSize) * BytesPerWord)); addCR(&c, BytesPerWord, &footprint, BytesPerWord, &stack); - appendFrameSizeEvent(&c, - (frameFootprint - offset + 1)); - if (returnAddressSurrogate != NoRegister) { assert(&c, offset > 0); @@ -3507,6 +3581,8 @@ class MyAssembler: public Assembler { assert(&c, (argumentFootprint % StackAlignmentInWords) == 0); if (TailCalls and argumentFootprint > StackAlignmentInWords) { + appendFrameEvent(&c); + Register returnAddress(rcx); popR(&c, BytesPerWord, &returnAddress); @@ -3516,16 +3592,10 @@ class MyAssembler: public Assembler { * BytesPerWord)); addCR(&c, BytesPerWord, &adjustment, BytesPerWord, &stack); - appendFrameSizeEvent(&c, - (argumentFootprint - StackAlignmentInWords)); - jumpR(&c, BytesPerWord, &returnAddress); } else { return_(&c); } - - // todo: this is not necessary if there are no instructions to - // follow: - appendFrameSizeEvent(&c, frameFootprint); } virtual void popFrameAndUpdateStackAndReturn(unsigned frameFootprint, @@ -3536,16 +3606,10 @@ class MyAssembler: public Assembler { Register returnAddress(rcx); popR(&c, BytesPerWord, &returnAddress); - appendFrameSizeEvent(&c, -1); - Register stack(rsp); Memory stackSrc(rbx, stackOffsetFromThread); 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); } @@ -3594,13 +3658,13 @@ class MyAssembler: public Assembler { c.result = dst; for (MyBlock* b = c.firstBlock; b; b = b->next) { - if (b->firstFrameSizeEvent) { - if (c.firstFrameSizeEvent) { - c.lastFrameSizeEvent->next_ = b->firstFrameSizeEvent; + if (b->firstFrameEvent) { + if (c.firstFrameEvent) { + c.lastFrameEvent->next_ = b->firstFrameEvent; } else { - c.firstFrameSizeEvent = b->firstFrameSizeEvent; + c.firstFrameEvent = b->firstFrameEvent; } - c.lastFrameSizeEvent = b->lastFrameSizeEvent; + c.lastFrameEvent = b->lastFrameEvent; } unsigned index = 0; @@ -3656,12 +3720,12 @@ class MyAssembler: public Assembler { return c.code.length(); } - virtual unsigned frameSizeEventCount() { - return c.frameSizeEventCount; + virtual unsigned frameEventCount() { + return c.frameEventCount; } - virtual FrameSizeEvent* firstFrameSizeEvent() { - return c.firstFrameSizeEvent; + virtual FrameEvent* firstFrameEvent() { + return c.firstFrameEvent; } virtual void dispose() { diff --git a/src/x86.h b/src/x86.h index 3073d1f46c..c277168ce0 100644 --- a/src/x86.h +++ b/src/x86.h @@ -29,20 +29,20 @@ # ifdef __APPLE__ # if __DARWIN_UNIX03 && defined(_STRUCT_X86_EXCEPTION_STATE32) # 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 THREAD_REGISTER(context) (context->uc_mcontext->__ss.__ebx) +# define LINK_REGISTER(context) (context->uc_mcontext->__ss.__ecx) # else # 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 THREAD_REGISTER(context) (context->uc_mcontext->ss.ebx) +# define LINK_REGISTER(context) (context->uc_mcontext->ss.ecx) # endif # else # 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 THREAD_REGISTER(context) (context->uc_mcontext.gregs[REG_EBX]) +# define LINK_REGISTER(context) (context->uc_mcontext.gregs[REG_ECX]) # endif extern "C" uint64_t @@ -65,20 +65,20 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t*, # ifdef __APPLE__ # if __DARWIN_UNIX03 && defined(_STRUCT_X86_EXCEPTION_STATE32) # 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 THREAD_REGISTER(context) (context->uc_mcontext->__ss.__rbx) +# define LINK_REGISTER(context) (context->uc_mcontext->__ss.__rcx) # else # 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 THREAD_REGISTER(context) (context->uc_mcontext->ss.rbx) +# define LINK_REGISTER(context) (context->uc_mcontext->ss.rcx) # endif # else # 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 THREAD_REGISTER(context) (context->uc_mcontext.gregs[REG_RBX]) +# define LINK_REGISTER(context) (context->uc_mcontext.gregs[REG_RCX]) # endif extern "C" uint64_t