refactor stack walking and visiting code to abstract away certain details of stack layout which are architecture-specific

This commit is contained in:
Joel Dice 2008-08-18 09:23:01 -06:00
parent 4a3be37c67
commit 9654e3445d
3 changed files with 105 additions and 85 deletions

View File

@ -184,7 +184,11 @@ class Assembler {
virtual unsigned alignFrameSize(unsigned sizeInWords) = 0;
virtual void* ipForFrame(void* stack, void* base);
virtual void* frameIp(void* stack) = 0;
virtual unsigned frameHeaderSize() = 0;
virtual unsigned frameFooterSize() = 0;
virtual void nextFrame(void** stack, void** base) = 0;
virtual void* popReturnAddress(void* stack) = 0;
virtual void plan
(UnaryOperation op,
@ -204,7 +208,8 @@ class Assembler {
unsigned cSize, uint8_t* cTypeMask, uint64_t* cRegisterMask,
bool* thunk) = 0;
virtual void dispose() = 0;
virtual void acquire() = 0;
virtual void release() = 0;
};
virtual ~Assembler() { }

View File

@ -65,26 +65,31 @@ class MyThread: public Thread {
CallTrace* next;
};
MyThread(Machine* m, object javaThread, Thread* parent):
MyThread(Machine* m, object javaThread, MyThread* parent):
Thread(m, javaThread, parent),
ip(0),
base(0),
stack(0),
trace(0),
reference(0)
{ }
reference(0),
arch(parent ? parent->arch : makeArchitecture(m->system))
{
arch->acquire();
}
void* ip;
void* base;
void* stack;
CallTrace* trace;
Reference* reference;
Assembler::Architecture* arch;
};
object
resolveThisPointer(MyThread* t, void* stack, object method)
{
return reinterpret_cast<object*>(stack)[methodParameterFootprint(t, method)];
return reinterpret_cast<object*>(stack)
[methodParameterFootprint(t, method) + t->arch->frameFooterSize()];
}
object
@ -209,7 +214,7 @@ class MyStackWalker: public Processor::StackWalker {
switch (state) {
case Start:
if (ip_ == 0) {
ip_ = t->arch->ipForFrame(stack, base);
ip_ = t->arch->frameIp(stack);
}
if (trace and trace->nativeMethod) {
@ -228,7 +233,7 @@ class MyStackWalker: public Processor::StackWalker {
} else if (trace) {
stack = trace->stack;
base = trace->base;
ip_ = t->arch->ipForFrame(stack, base);
ip_ = t->arch->frameIp(stack);
trace = trace->next;
if (trace and trace->nativeMethod) {
@ -260,7 +265,7 @@ class MyStackWalker: public Processor::StackWalker {
switch (state) {
case Method:
t->arch->nextFrame(&stack, &base);
ip_ = t->arch->ipForFrame(stack, base);
ip_ = t->arch->frameIp(stack);
break;
case NativeMethod:
@ -315,24 +320,57 @@ class MyStackWalker: public Processor::StackWalker {
MyProtector protector;
};
unsigned
localSize(MyThread* t, object method)
{
unsigned size = codeMaxLocals(t, methodCode(t, method));
if ((methodFlags(t, method) & (ACC_SYNCHRONIZED | ACC_STATIC))
== ACC_SYNCHRONIZED)
{
++ size;
}
return size;
}
unsigned
alignedFrameSize(MyThread* t, object method)
{
return t->arch->alignFrameSize
(localSize(t, method)
- methodParameterFootprint(t, method)
+ codeMaxStack(t, methodCode(t, method)));
}
unsigned
alignedFrameSizeWithParameters(MyThread* t, object method)
{
return methodParameterFootprint(t, method) + alignedFrameSize(t, method);
}
int
localOffset(MyThread* t, int v, object method)
{
return alignedFrameSize(t, method) - t->arch->frameHeaderSize() - v;
int parameterFootprint = methodParameterFootprint(t, method) * BytesPerWord;
v *= BytesPerWord;
if (v < parameterFootprint) {
return (parameterFootprint - v - BytesPerWord) + (BytesPerWord * 2);
return alignedFrameSize(t, method)
+ parameterFootprint
+ t->arch->frameFooterSize()
+ t->arch->frameHeaderSize()
- v;
} else {
return -(v + BytesPerWord - parameterFootprint);
return alignedFrameSize(t, method) - t->arch->frameHeaderSize() - v;
}
}
inline object*
localObject(MyThread* t, void* base, object method, unsigned index)
localObject(MyThread* t, void* stack, object method, unsigned index)
{
return reinterpret_cast<object*>
(static_cast<uint8_t*>(base) + localOffset(t, index, method));
(static_cast<uint8_t*>(stack) + localOffset(t, index, method));
}
class PoolElement {
@ -384,29 +422,11 @@ enum Event {
TraceEvent
};
unsigned
localSize(MyThread* t, object method)
{
unsigned size = codeMaxLocals(t, methodCode(t, method));
if ((methodFlags(t, method) & (ACC_SYNCHRONIZED | ACC_STATIC))
== ACC_SYNCHRONIZED)
{
++ size;
}
return size;
}
unsigned
alignedFrameSize(MyThread* t, object method)
{
return Assembler::alignFrameSize
(localSize(t, method) + codeMaxStack(t, methodCode(t, method)));
}
unsigned
frameMapSizeInWords(MyThread* t, object method)
{
return ceiling(alignedFrameSize(t, method), BitsPerWord) * BytesPerWord;
return ceiling(alignedFrameSizeWithParameters(t, method), BitsPerWord)
* BytesPerWord;
}
uint16_t*
@ -1153,7 +1173,7 @@ findUnwindTarget(MyThread* t, void** targetIp, void** targetBase,
void* base = t->base;
void* stack = t->stack;
if (ip == 0) {
ip = t->arch->ipForFrame(stack, base);
ip = t->arch->frameIp(stack);
}
*targetIp = 0;
@ -1168,16 +1188,12 @@ findUnwindTarget(MyThread* t, void** targetIp, void** targetBase,
unsigned parameterFootprint = methodParameterFootprint(t, method);
unsigned localFootprint = localSize(t, method);
t->arch->copyIntoFrame
(stack, base, localFootprint - parameterFootprint,
BytesPerWord, &(t->exception));
t->exception = 0;
reinterpret_cast<void**>(stack)
[alignedFrameSize(t, method) - t->arch->frameHeaderSize()
- (localFootprint - parameterFootprint - 1)]
= t->exception;
stack = t->arch->pushFrame
(stack, base,
localFootprint
- parameterFootprint
+ codeMaxStack(t, methodCode(t, method)));
t->exception = 0;
*targetIp = handler;
*targetBase = base;
@ -1195,12 +1211,12 @@ findUnwindTarget(MyThread* t, void** targetIp, void** targetBase,
}
t->arch->nextFrame(&stack, &base);
ip_ = t->arch->ipForFrame(stack, base);
ip = t->arch->frameIp(stack);
}
} else {
*targetIp = ip;
*targetBase = base;
*targetStack = stack + 1;
*targetStack = t->arch->popReturnAddress(stack);
}
}
}
@ -1758,7 +1774,7 @@ handleMonitorEvent(MyThread* t, Frame* frame, intptr_t function)
lock = frame->append(methodClass(t, method));
} else {
lock = c->memory
(c->base(), localOffset(t, savedTargetIndex(t, method), method));
(c->stack(), localOffset(t, savedTargetIndex(t, method), method));
}
c->call(c->constant(function),
@ -1782,8 +1798,8 @@ handleEntrance(MyThread* t, Frame* frame)
// save 'this' pointer in case it is overwritten.
unsigned index = savedTargetIndex(t, method);
c->store(BytesPerWord,
c->memory(c->base(), localOffset(t, 0, method)),
c->memory(c->base(), localOffset(t, index, method)));
c->memory(c->stack(), localOffset(t, 0, method)),
c->memory(c->stack(), localOffset(t, index, method)));
frame->set(index, Frame::Object);
}
@ -2586,7 +2602,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
int8_t count = codeBody(t, code, ip++);
Compiler::Operand* a = c->memory
(c->base(), localOffset(t, index, context->method));
(c->stack(), localOffset(t, index, context->method));
c->storeLocal(4, c->add(4, c->constant(count), a), index);
} break;
@ -3109,7 +3125,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
frame->trace(0, false),
BytesPerWord,
4, c->thread(), frame->append(class_), c->constant(dimensions),
c->stack());
c->stackTop());
frame->pop(dimensions);
frame->pushObject(result);
@ -3301,7 +3317,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
case ret:
c->jmp
(c->memory
(c->base(), localOffset
(c->stack(), localOffset
(t, codeBody(t, code, ip), context->method)));
return;
@ -3385,7 +3401,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
uint16_t count = codeReadInt16(t, code, ip);
Compiler::Operand* a = c->memory
(c->base(), localOffset(t, index, context->method));
(c->stack(), localOffset(t, index, context->method));
c->storeLocal(4, c->add(4, c->constant(count), a), index);
} break;
@ -3409,7 +3425,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
case ret:
c->jmp
(c->memory
(c->base(), localOffset
(c->stack(), localOffset
(t, codeReadInt16(t, code, ip), context->method)));
return;
@ -3672,7 +3688,7 @@ compareTraceElementPointers(const void* va, const void* vb)
unsigned
frameObjectMapSize(MyThread* t, object method, object map)
{
int size = alignedFrameSize(t, method);
int size = alignedFrameSizeWithParameters(t, method);
return ceiling(intArrayLength(t, map) * size, 32 + size);
}
@ -3763,7 +3779,7 @@ finish(MyThread* t, Context* context)
qsort(elements, context->traceLogCount, sizeof(TraceElement*),
compareTraceElementPointers);
unsigned size = alignedFrameSize(t, context->method);
unsigned size = alignedFrameSizeWithParameters(t, context->method);
object map = makeIntArray
(t, context->traceLogCount
+ ceiling(context->traceLogCount * size, 32),
@ -3947,7 +3963,7 @@ compile(MyThread* t, object method);
void*
compileMethod2(MyThread* t)
{
object node = findCallNode(t, t->arch->ipForFrame(t->stack, t->base));
object node = findCallNode(t, t->arch->frameIp(t->stack));
PROTECT(t, node);
object target = callNodeTarget(t, node);
@ -3970,8 +3986,7 @@ compileMethod2(MyThread* t)
(t, resolveThisPointer(t, t->stack, target)), methodOffset(t, target))
= &singletonValue(t, methodCompiled(t, target), 0);
} else {
Context context(t);
context.assembler->updateCall
t->arch->updateCall
(reinterpret_cast<void*>(callNodeAddress(t, node)),
&singletonValue(t, methodCompiled(t, target), 0));
}
@ -4035,7 +4050,7 @@ invokeNative2(MyThread* t, object method)
types[typeOffset++] = POINTER_TYPE;
uintptr_t* sp = static_cast<uintptr_t*>(t->stack)
+ methodParameterFootprint(t, method);
+ methodParameterFootprint(t, method) + t->arch->frameFooterSize();
if (methodFlags(t, method) & ACC_STATIC) {
args[argOffset++] = reinterpret_cast<uintptr_t>(&class_);
@ -4177,7 +4192,7 @@ uint64_t
invokeNative(MyThread* t)
{
if (t->trace->nativeMethod == 0) {
object node = findCallNode(t, t->arch->ipForFrame(t->stack, t->base));
object node = findCallNode(t, t->arch->frameIp(t->stack));
object target = callNodeTarget(t, node);
if (callNodeVirtualCall(t, node)) {
target = resolveTarget(t, t->stack, target);
@ -4214,7 +4229,8 @@ frameMapIndex(MyThread* t, object method, int32_t offset)
int32_t v = intArrayBody(t, map, middle);
if (offset == v) {
return (indexSize * 32) + (alignedFrameSize(t, method) * middle);
return (indexSize * 32)
+ (alignedFrameSizeWithParameters(t, method) * middle);
} else if (offset < v) {
top = middle;
} else {
@ -4226,18 +4242,14 @@ frameMapIndex(MyThread* t, object method, int32_t offset)
}
void
visitStackAndLocals(MyThread* t, Heap::Visitor* v, void* base, object method,
void* ip, void* calleeBase, unsigned argumentFootprint)
visitStackAndLocals(MyThread* t, Heap::Visitor* v, void* stack, object method,
void* ip, void* calleeStack, unsigned argumentFootprint)
{
unsigned count;
if (calleeBase) {
unsigned parameterFootprint = methodParameterFootprint(t, method);
unsigned height = static_cast<uintptr_t*>(base)
- static_cast<uintptr_t*>(calleeBase) - 2;
count = parameterFootprint + height - argumentFootprint;
if (calleeStack) {
count = alignedFrameSize(t, method) - argumentFootprint;
} else {
count = alignedFrameSize(t, method);
count = alignedFrameSizeWithParameters(t, method);
}
if (count) {
@ -4251,7 +4263,7 @@ visitStackAndLocals(MyThread* t, Heap::Visitor* v, void* base, object method,
if ((intArrayBody(t, map, j / 32)
& (static_cast<int32_t>(1) << (j % 32))))
{
v->visit(localObject(t, base, method, i));
v->visit(localObject(t, stack, method, i));
}
}
}
@ -4264,11 +4276,11 @@ visitStack(MyThread* t, Heap::Visitor* v)
void* base = t->base;
void* stack = t->stack;
if (ip == 0) {
ip = t->arch->ipForFrame(stack, base);
ip = t->arch->frameIp(stack);
}
MyThread::CallTrace* trace = t->trace;
void* calleeBase = 0;
void* calleeStack = 0;
unsigned argumentFootprint = 0;
while (stack) {
@ -4277,19 +4289,19 @@ visitStack(MyThread* t, Heap::Visitor* v)
PROTECT(t, method);
visitStackAndLocals
(t, v, base, method, ip, calleeBase, argumentFootprint);
(t, v, stack, method, ip, calleeStack, argumentFootprint);
calleeBase = base;
calleeStack = stack;
argumentFootprint = methodParameterFootprint(t, method);
t->arch->nextFrame(&stack, &base);
ip_ = t->arch->ipForFrame(stack, base);
ip = t->arch->frameIp(stack);
} else if (trace) {
calleeBase = 0;
calleeStack = 0;
argumentFootprint = 0;
stack = trace->stack;
base = trace->base;
ip_ = t->arch->ipForFrame(stack, base);
ip = t->arch->frameIp(stack);
trace = trace->next;
} else {
break;
@ -4562,7 +4574,7 @@ class MyProcessor: public Processor {
makeThread(Machine* m, object javaThread, Thread* parent)
{
MyThread* t = new (m->heap->allocate(sizeof(MyThread)))
MyThread(m, javaThread, parent);
MyThread(m, javaThread, static_cast<MyThread*>(parent));
t->init();
return t;
}
@ -4802,6 +4814,8 @@ class MyProcessor: public Processor {
vm::dispose(t, t->reference);
}
t->arch->release();
t->m->heap->free(t, sizeof(*t));
}
@ -4841,7 +4855,7 @@ class MyProcessor: public Processor {
if (static_cast<uint8_t*>(ip) >= thunkStart
and static_cast<uint8_t*>(ip) < thunkEnd)
{
target->ip = *static_cast<void**>(stack);
target->ip = t->arch->frameIp(stack);
target->base = base;
target->stack = stack;
}
@ -4933,7 +4947,7 @@ compileThunks(MyThread* t, MyProcessor* p)
a->saveFrame(difference(&(t->stack), t), difference(&(t->base), t));
Assembler::Register thread(a->thread());
Assembler::Register thread(t->arch->thread());
a->pushFrame(1, BytesPerWord, RegisterOperand, &thread);
defaultContext.promise.resolved_ = true;
@ -4944,7 +4958,7 @@ compileThunks(MyThread* t, MyProcessor* p)
a->popFrame();
Assembler::Register result(a->returnLow());
Assembler::Register result(t->arch->returnLow());
a->apply(Jump, BytesPerWord, RegisterOperand, &result);
}
@ -4954,7 +4968,7 @@ compileThunks(MyThread* t, MyProcessor* p)
a->saveFrame(difference(&(t->stack), t), difference(&(t->base), t));
Assembler::Register thread(a->thread());
Assembler::Register thread(t->arch->thread());
a->pushFrame(1, BytesPerWord, RegisterOperand, &thread);
nativeContext.promise.resolved_ = true;
@ -4974,7 +4988,7 @@ compileThunks(MyThread* t, MyProcessor* p)
a->saveFrame(difference(&(t->stack), t), difference(&(t->base), t));
Assembler::Register thread(a->thread());
Assembler::Register thread(t->arch->thread());
a->pushFrame(1, BytesPerWord, RegisterOperand, &thread);
aioobContext.promise.resolved_ = true;

View File

@ -60,9 +60,10 @@ class Compiler {
unsigned scale = 1) = 0;
virtual Operand* stack() = 0;
virtual Operand* base() = 0;
virtual Operand* thread() = 0;
virtual Operand* stackTop();
virtual Operand* label() = 0;
virtual void mark(Operand* label) = 0;