| 8816 | } |
| 8817 | |
| 8818 | virtual object getStackTrace(Thread* vmt, Thread* vmTarget) |
| 8819 | { |
| 8820 | MyThread* t = static_cast<MyThread*>(vmt); |
| 8821 | MyThread* target = static_cast<MyThread*>(vmTarget); |
| 8822 | MyProcessor* p = this; |
| 8823 | |
| 8824 | class Visitor : public System::ThreadVisitor { |
| 8825 | public: |
| 8826 | Visitor(MyThread* t, MyProcessor* p, MyThread* target) |
| 8827 | : t(t), p(p), target(target), trace(0) |
| 8828 | { |
| 8829 | } |
| 8830 | |
| 8831 | virtual void visit(void* ip, void* stack, void* link) |
| 8832 | { |
| 8833 | MyThread::TraceContext c(target, link); |
| 8834 | |
| 8835 | if (methodForIp(t, ip)) { |
| 8836 | // we caught the thread in Java code - use the register values |
| 8837 | c.ip = ip; |
| 8838 | c.stack = stack; |
| 8839 | c.methodIsMostRecent = true; |
| 8840 | } else if (target->transition) { |
| 8841 | // we caught the thread in native code while in the middle |
| 8842 | // of updating the context fields (MyThread::stack, etc.) |
| 8843 | static_cast<MyThread::Context&>(c) = *(target->transition); |
| 8844 | } else if (isVmInvokeUnsafeStack(ip)) { |
| 8845 | // we caught the thread in native code just after returning |
| 8846 | // from java code, but before clearing MyThread::stack |
| 8847 | // (which now contains a garbage value), and the most recent |
| 8848 | // Java frame, if any, can be found in |
| 8849 | // MyThread::continuation or MyThread::trace |
| 8850 | c.ip = 0; |
| 8851 | c.stack = 0; |
| 8852 | } else if (target->stack and (not isThunkUnsafeStack(t, ip)) |
| 8853 | and (not isVirtualThunk(t, ip))) { |
| 8854 | // we caught the thread in a thunk or native code, and the |
| 8855 | // saved stack pointer indicates the most recent Java frame |
| 8856 | // on the stack |
| 8857 | c.ip = getIp(target); |
| 8858 | c.stack = target->stack; |
| 8859 | } else if (isThunk(t, ip) or isVirtualThunk(t, ip)) { |
| 8860 | // we caught the thread in a thunk where the stack register |
| 8861 | // indicates the most recent Java frame on the stack |
| 8862 | |
| 8863 | // On e.g. x86, the return address will have already been |
| 8864 | // pushed onto the stack, in which case we use getIp to |
| 8865 | // retrieve it. On e.g. ARM, it will be in the |
| 8866 | // link register. Note that we can't just check if the link |
| 8867 | // argument is null here, since we use ecx/rcx as a |
| 8868 | // pseudo-link register on x86 for the purpose of tail |
| 8869 | // calls. |
| 8870 | c.ip = t->arch->hasLinkRegister() ? link : getIp(t, link, stack); |
| 8871 | c.stack = stack; |
| 8872 | } else { |
| 8873 | // we caught the thread in native code, and the most recent |
| 8874 | // Java frame, if any, can be found in |
| 8875 | // MyThread::continuation or MyThread::trace |