nth attempt to clean up MyStackWalker

This commit is contained in:
Joel Dice 2008-04-23 10:33:31 -06:00
parent 9e8e4b3de7
commit d072b71c39
2 changed files with 122 additions and 67 deletions

View File

@ -40,14 +40,12 @@ class MyThread: public Thread {
public: public:
CallTrace(MyThread* t): CallTrace(MyThread* t):
t(t), t(t),
ip(t->ip),
base(t->base), base(t->base),
stack(t->stack), stack(t->stack),
nativeMethod(0), nativeMethod(0),
next(t->trace) next(t->trace)
{ {
t->trace = this; t->trace = this;
t->ip = 0;
t->base = 0; t->base = 0;
t->stack = 0; t->stack = 0;
} }
@ -55,7 +53,6 @@ class MyThread: public Thread {
~CallTrace() { ~CallTrace() {
t->stack = stack; t->stack = stack;
t->base = base; t->base = base;
t->ip = ip;
t->trace = next; t->trace = next;
} }
@ -152,6 +149,14 @@ methodForIp(MyThread* t, void* ip)
class MyStackWalker: public Processor::StackWalker { class MyStackWalker: public Processor::StackWalker {
public: public:
enum State {
Start,
Next,
Method,
NativeMethod,
Finish
};
class MyProtector: public Thread::Protector { class MyProtector: public Thread::Protector {
public: public:
MyProtector(MyStackWalker* walker): MyProtector(MyStackWalker* walker):
@ -160,7 +165,6 @@ 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->nativeMethod));
} }
MyStackWalker* walker; MyStackWalker* walker;
@ -168,114 +172,156 @@ class MyStackWalker: public Processor::StackWalker {
MyStackWalker(MyThread* t): MyStackWalker(MyThread* t):
t(t), t(t),
ip_(t->ip ? t->ip : (t->stack ? *static_cast<void**>(t->stack) : 0)), state(Start),
ip_(t->ip),
base(t->base), base(t->base),
stack(t->stack), stack(t->stack),
trace(t->trace), trace(t->trace),
nativeMethod(trace ? trace->nativeMethod : 0), method_(0),
method_(ip_ ? methodForIp(t, ip_) : 0),
protector(this) protector(this)
{ } { }
MyStackWalker(MyStackWalker* w): MyStackWalker(MyStackWalker* w):
t(w->t), t(w->t),
state(w->state),
ip_(w->ip_), ip_(w->ip_),
base(w->base), base(w->base),
stack(w->stack), stack(w->stack),
trace(w->trace), trace(w->trace),
nativeMethod(w->nativeMethod),
method_(w->method_), method_(w->method_),
protector(this) protector(this)
{ } { }
virtual void walk(Processor::StackVisitor* v) { virtual void walk(Processor::StackVisitor* v) {
if (stack == 0) { for (MyStackWalker it(this); it.valid();) {
return;
}
if (not v->visit(this)) {
return;
}
for (MyStackWalker it(this); it.next();) {
MyStackWalker walker(it); MyStackWalker walker(it);
if (not v->visit(&walker)) { if (not v->visit(&walker)) {
break; break;
} }
it.next();
} }
} }
bool next() { bool valid() {
if (nativeMethod) { while (true) {
nativeMethod = 0; // fprintf(stderr, "state: %d\n", state);
} else if (stack) { switch (state) {
stack = static_cast<void**>(base) + 1; case Start:
base = *static_cast<void**>(base); if (ip_ == 0 and stack) {
ip_ = *static_cast<void**>(stack); ip_ = *static_cast<void**>(stack);
method_ = methodForIp(t, *static_cast<void**>(stack)); }
} else {
return false; if (trace and trace->nativeMethod) {
method_ = trace->nativeMethod;
state = NativeMethod;
} else if (ip_) {
state = Next;
} else {
state = Finish;
}
break;
case Next:
if (stack) {
method_ = methodForIp(t, ip_);
if (method_) {
state = Method;
} else if (trace) {
base = trace->base;
stack = static_cast<void**>(trace->stack);
ip_ = (stack ? *static_cast<void**>(stack) : 0);
if (trace->nativeMethod) {
method_ = trace->nativeMethod;
state = NativeMethod;
} else {
trace = trace->next;
state = Next;
}
} else {
state = Finish;
}
} else {
state = Finish;
}
break;
case Method:
case NativeMethod:
return true;
case Finish:
return false;
default:
abort(t);
}
} }
}
if (method_ or nativeMethod) { void next() {
return true; switch (state) {
} else if (trace and trace->stack) { case Method:
base = trace->base; stack = static_cast<void**>(base) + 1;
stack = static_cast<void**>(trace->stack); ip_ = (stack ? *static_cast<void**>(stack) : 0);
ip_ = *static_cast<void**>(stack); base = *static_cast<void**>(base);
method_ = methodForIp(t, *static_cast<void**>(stack)); state = Next;
nativeMethod = trace->nativeMethod; break;
case NativeMethod:
trace = trace->next; trace = trace->next;
state = Next;
break;
expect(t, method_ or nativeMethod); default:
return true; abort(t);
} else {
return false;
} }
} }
virtual object method() { virtual object method() {
if (nativeMethod) { switch (state) {
return nativeMethod; case Method:
} else {
return method_; return method_;
case NativeMethod:
return trace->nativeMethod;
default:
abort(t);
} }
} }
virtual int ip() { virtual int ip() {
if (nativeMethod) { switch (state) {
return 0; case Method:
} else {
return reinterpret_cast<intptr_t>(ip_) - reinterpret_cast<intptr_t> return reinterpret_cast<intptr_t>(ip_) - reinterpret_cast<intptr_t>
(&singletonValue(t, methodCompiled(t, method_), 0)); (&singletonValue(t, methodCompiled(t, method_), 0));
case NativeMethod:
return 0;
default:
abort(t);
} }
} }
virtual unsigned count() { virtual unsigned count() {
class Visitor: public Processor::StackVisitor { unsigned count = 0;
public:
Visitor(): count(0) { }
virtual bool visit(Processor::StackWalker*) { for (MyStackWalker walker(this); walker.valid();) {
++ count; walker.next();
return true; ++ count;
} }
unsigned count; return count;
} v;
MyStackWalker walker(this);
walker.walk(&v);
return v.count;
} }
MyThread* t; MyThread* t;
State state;
void* ip_; void* ip_;
void* base; void* base;
void* stack; void* stack;
MyThread::CallTrace* trace; MyThread::CallTrace* trace;
object nativeMethod;
object method_; object method_;
MyProtector protector; MyProtector protector;
}; };
@ -1196,9 +1242,7 @@ findUnwindTarget(MyThread* t, void** targetIp, void** targetBase,
void* ip = t->ip; void* ip = t->ip;
void* base = t->base; void* base = t->base;
void** stack = static_cast<void**>(t->stack); void** stack = static_cast<void**>(t->stack);
if (ip) { if (ip == 0) {
t->ip = 0;
} else {
ip = *stack; ip = *stack;
} }
@ -4302,11 +4346,11 @@ invokeNative(MyThread* t)
{ {
if (t->trace->nativeMethod == 0) { if (t->trace->nativeMethod == 0) {
object node = findCallNode(t, *static_cast<void**>(t->stack)); object node = findCallNode(t, *static_cast<void**>(t->stack));
t->trace->nativeMethod = callNodeTarget(t, node); object target = callNodeTarget(t, node);
if (callNodeVirtualCall(t, node)) { if (callNodeVirtualCall(t, node)) {
t->trace->nativeMethod = resolveTarget target = resolveTarget(t, t->stack, target);
(t, t->stack, t->trace->nativeMethod);
} }
t->trace->nativeMethod = target;
} }
uint64_t result = 0; uint64_t result = 0;
@ -4671,6 +4715,10 @@ class SegFaultHandler: public System::SignalHandler {
if (t->state == Thread::ActiveState) { if (t->state == Thread::ActiveState) {
object node = methodForIp(t, *ip); object node = methodForIp(t, *ip);
if (node) { if (node) {
void* oldIp = t->ip;
void* oldBase = t->base;
void* oldStack = t->stack;
t->ip = *ip; t->ip = *ip;
t->base = *base; t->base = *base;
t->stack = *stack; t->stack = *stack;
@ -4682,6 +4730,11 @@ class SegFaultHandler: public System::SignalHandler {
t->tracing = false; t->tracing = false;
findUnwindTarget(t, ip, base, stack); findUnwindTarget(t, ip, base, stack);
t->ip = oldIp;
t->base = oldBase;
t->stack = oldStack;
*thread = t; *thread = t;
return true; return true;
} }
@ -5047,6 +5100,7 @@ class MyProcessor: public Processor {
or (static_cast<uint8_t*>(ip) >= native or (static_cast<uint8_t*>(ip) >= native
and static_cast<uint8_t*>(ip) < native + nativeSize)) and static_cast<uint8_t*>(ip) < native + nativeSize))
{ {
target->ip = *static_cast<void**>(stack);
target->base = base; target->base = base;
target->stack = stack; target->stack = stack;
} }

View File

@ -2832,6 +2832,7 @@ makeTrace(Thread* t, Processor::StackWalker* walker)
} }
object e = makeTraceElement(t, walker->method(), walker->ip()); object e = makeTraceElement(t, walker->method(), walker->ip());
assert(t, index < arrayLength(t, trace));
set(t, trace, ArrayBody + (index * BytesPerWord), e); set(t, trace, ArrayBody + (index * BytesPerWord), e);
++ index; ++ index;
return true; return true;