mirror of
https://github.com/corda/corda.git
synced 2025-01-19 11:16:54 +00:00
bugfixes and cleanups for new stack mapping code
This commit is contained in:
parent
a755368add
commit
888dce8f3c
147
src/compile.cpp
147
src/compile.cpp
@ -19,6 +19,7 @@ namespace {
|
|||||||
const bool Verbose = true;
|
const bool Verbose = true;
|
||||||
const bool DebugNatives = false;
|
const bool DebugNatives = false;
|
||||||
const bool DebugTraces = false;
|
const bool DebugTraces = false;
|
||||||
|
const bool DebugFrameMaps = false;
|
||||||
|
|
||||||
class MyThread: public Thread {
|
class MyThread: public Thread {
|
||||||
public:
|
public:
|
||||||
@ -479,21 +480,20 @@ class Context {
|
|||||||
class Frame {
|
class Frame {
|
||||||
public:
|
public:
|
||||||
Frame(Context* context, uintptr_t* stackMap):
|
Frame(Context* context, uintptr_t* stackMap):
|
||||||
next(0),
|
|
||||||
context(context),
|
context(context),
|
||||||
t(context->t),
|
t(context->t),
|
||||||
c(context->c),
|
c(context->c),
|
||||||
stack(0),
|
stack(0),
|
||||||
stackMap(stackMap),
|
stackMap(stackMap),
|
||||||
ip(0),
|
ip(0),
|
||||||
sp(localSize(t, context->method)),
|
sp(localSize()),
|
||||||
level(0)
|
level(0)
|
||||||
{
|
{
|
||||||
memset(stackMap, 0,
|
memset(stackMap, 0,
|
||||||
stackMapSizeInWords(t, context->method) * BytesPerWord);
|
stackMapSizeInWords(t, context->method) * BytesPerWord);
|
||||||
}
|
}
|
||||||
|
|
||||||
Frame(Frame* f, uintptr_t* map):
|
Frame(Frame* f, uintptr_t* stackMap):
|
||||||
context(f->context),
|
context(f->context),
|
||||||
t(context->t),
|
t(context->t),
|
||||||
c(context->c),
|
c(context->c),
|
||||||
@ -537,7 +537,7 @@ class Frame {
|
|||||||
return localSize() + stackSize();
|
return localSize() + stackSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void mark(int index) {
|
void mark(unsigned index) {
|
||||||
assert(t, index < frameSize());
|
assert(t, index < frameSize());
|
||||||
|
|
||||||
context->eventLog.append(MarkEvent);
|
context->eventLog.append(MarkEvent);
|
||||||
@ -549,7 +549,7 @@ class Frame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear(int index) {
|
void clear(unsigned index) {
|
||||||
assert(t, index < frameSize());
|
assert(t, index < frameSize());
|
||||||
|
|
||||||
context->eventLog.append(ClearEvent);
|
context->eventLog.append(ClearEvent);
|
||||||
@ -561,7 +561,7 @@ class Frame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned get(int index) {
|
unsigned get(unsigned index) {
|
||||||
assert(t, index < frameSize());
|
assert(t, index < frameSize());
|
||||||
int si = index - localSize();
|
int si = index - localSize();
|
||||||
assert(t, si >= 0);
|
assert(t, si >= 0);
|
||||||
@ -762,7 +762,7 @@ class Frame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void swapped() {
|
void swapped() {
|
||||||
assert(t, sp - 2 >= 0);
|
assert(t, sp - 2 >= localSize());
|
||||||
|
|
||||||
bool savedBit = get(sp - 1);
|
bool savedBit = get(sp - 1);
|
||||||
if (get(sp - 2)) {
|
if (get(sp - 2)) {
|
||||||
@ -784,7 +784,7 @@ class Frame {
|
|||||||
|
|
||||||
void visitLogicalIp(unsigned ip) {
|
void visitLogicalIp(unsigned ip) {
|
||||||
context->eventLog.append(IpEvent);
|
context->eventLog.append(IpEvent);
|
||||||
context->eventLog.append16(ip);
|
context->eventLog.append2(ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
void startLogicalIp(unsigned ip) {
|
void startLogicalIp(unsigned ip) {
|
||||||
@ -862,14 +862,14 @@ class Frame {
|
|||||||
|
|
||||||
Operand* topInt() {
|
Operand* topInt() {
|
||||||
assert(t, sp >= 1);
|
assert(t, sp >= 1);
|
||||||
assert(sp - 1 >= localSize());
|
assert(t, sp - 1 >= localSize());
|
||||||
assert(t, get(sp - 1) == 0);
|
assert(t, get(sp - 1) == 0);
|
||||||
return c->stack(stack, 0);
|
return c->stack(stack, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Operand* topLong() {
|
Operand* topLong() {
|
||||||
assert(t, sp >= 2);
|
assert(t, sp >= 2);
|
||||||
assert(sp - 2 >= localSize());
|
assert(t, sp - 2 >= localSize());
|
||||||
assert(t, get(sp - 1) == 0);
|
assert(t, get(sp - 1) == 0);
|
||||||
assert(t, get(sp - 2) == 0);
|
assert(t, get(sp - 2) == 0);
|
||||||
return c->stack(stack, 0);
|
return c->stack(stack, 0);
|
||||||
@ -877,7 +877,7 @@ class Frame {
|
|||||||
|
|
||||||
Operand* topObject() {
|
Operand* topObject() {
|
||||||
assert(t, sp >= 1);
|
assert(t, sp >= 1);
|
||||||
assert(sp - 1 >= localSize());
|
assert(t, sp - 1 >= localSize());
|
||||||
assert(t, get(sp - 1) != 0);
|
assert(t, get(sp - 1) != 0);
|
||||||
return c->stack(stack, 0);
|
return c->stack(stack, 0);
|
||||||
}
|
}
|
||||||
@ -1588,7 +1588,7 @@ void
|
|||||||
compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
compile(MyThread* t, Frame* initialFrame, unsigned ip)
|
||||||
{
|
{
|
||||||
uintptr_t stackMap[stackMapSizeInWords(t, initialFrame->context->method)];
|
uintptr_t stackMap[stackMapSizeInWords(t, initialFrame->context->method)];
|
||||||
Frame myFrame(initialFrame, map);
|
Frame myFrame(initialFrame, stackMap);
|
||||||
Frame* frame = &myFrame;
|
Frame* frame = &myFrame;
|
||||||
Compiler* c = frame->c;
|
Compiler* c = frame->c;
|
||||||
Context* context = frame->context;
|
Context* context = frame->context;
|
||||||
@ -3394,7 +3394,8 @@ logCompile(const void* code, unsigned size, const char* class_,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
updateExceptionHandlerTable(MyThread* t, Compiler* c, object code)
|
updateExceptionHandlerTable(MyThread* t, Compiler* c, object code,
|
||||||
|
intptr_t start)
|
||||||
{
|
{
|
||||||
object oldTable = codeExceptionHandlerTable(t, code);
|
object oldTable = codeExceptionHandlerTable(t, code);
|
||||||
if (oldTable) {
|
if (oldTable) {
|
||||||
@ -3410,16 +3411,13 @@ updateExceptionHandlerTable(MyThread* t, Compiler* c, object code)
|
|||||||
(t, newTable, i);
|
(t, newTable, i);
|
||||||
|
|
||||||
exceptionHandlerStart(newHandler)
|
exceptionHandlerStart(newHandler)
|
||||||
= c->machineIp(exceptionHandlerStart(oldHandler))->value(c)
|
= c->machineIp(exceptionHandlerStart(oldHandler))->value(c) - start;
|
||||||
- reinterpret_cast<intptr_t>(start);
|
|
||||||
|
|
||||||
exceptionHandlerEnd(newHandler)
|
exceptionHandlerEnd(newHandler)
|
||||||
= c->machineIp(exceptionHandlerEnd(oldHandler))->value(c)
|
= c->machineIp(exceptionHandlerEnd(oldHandler))->value(c) - start;
|
||||||
- reinterpret_cast<intptr_t>(start);
|
|
||||||
|
|
||||||
exceptionHandlerIp(newHandler)
|
exceptionHandlerIp(newHandler)
|
||||||
= c->machineIp(exceptionHandlerIp(oldHandler))->value(c)
|
= c->machineIp(exceptionHandlerIp(oldHandler))->value(c) - start;
|
||||||
- reinterpret_cast<intptr_t>(start);
|
|
||||||
|
|
||||||
exceptionHandlerCatchType(newHandler)
|
exceptionHandlerCatchType(newHandler)
|
||||||
= exceptionHandlerCatchType(oldHandler);
|
= exceptionHandlerCatchType(oldHandler);
|
||||||
@ -3430,7 +3428,8 @@ updateExceptionHandlerTable(MyThread* t, Compiler* c, object code)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
updateLineNumberTable(MyThread* t, Compiler* c, object code)
|
updateLineNumberTable(MyThread* t, Compiler* c, object code,
|
||||||
|
intptr_t start)
|
||||||
{
|
{
|
||||||
object oldTable = codeLineNumberTable(t, code);
|
object oldTable = codeLineNumberTable(t, code);
|
||||||
if (oldTable) {
|
if (oldTable) {
|
||||||
@ -3444,8 +3443,7 @@ updateLineNumberTable(MyThread* t, Compiler* c, object code)
|
|||||||
LineNumber* newLine = lineNumberTableBody(t, newTable, i);
|
LineNumber* newLine = lineNumberTableBody(t, newTable, i);
|
||||||
|
|
||||||
lineNumberIp(newLine)
|
lineNumberIp(newLine)
|
||||||
= c->machineIp(lineNumberIp(oldLine))->value(c)
|
= c->machineIp(lineNumberIp(oldLine))->value(c) - start;
|
||||||
- reinterpret_cast<intptr_t>(start);
|
|
||||||
|
|
||||||
lineNumberLine(newLine) = lineNumberLine(oldLine);
|
lineNumberLine(newLine) = lineNumberLine(oldLine);
|
||||||
}
|
}
|
||||||
@ -3455,8 +3453,20 @@ updateLineNumberTable(MyThread* t, Compiler* c, object code)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
printSet(uintptr_t m)
|
||||||
|
{
|
||||||
|
for (unsigned i = 0; i < 16; ++i) {
|
||||||
|
if ((m >> i) & 1) {
|
||||||
|
fprintf(stderr, "1");
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "_");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned
|
||||||
calculateJunctions(MyThread* t, Context* context, uintptr_t* originalRoots,
|
calculateJunctions(MyThread* t, Context* context, uintptr_t* originalRoots,
|
||||||
uintptr_t* originalKnown)
|
uintptr_t* originalKnown, unsigned ei)
|
||||||
{
|
{
|
||||||
unsigned mapSize = frameMapSizeInWords(t, context->method);
|
unsigned mapSize = frameMapSizeInWords(t, context->method);
|
||||||
|
|
||||||
@ -3468,15 +3478,15 @@ calculateJunctions(MyThread* t, Context* context, uintptr_t* originalRoots,
|
|||||||
|
|
||||||
int32_t ip = -1;
|
int32_t ip = -1;
|
||||||
|
|
||||||
for (unsigned ei = 0; ei < context->eventLog.length();) {
|
while (ei < context->eventLog.length()) {
|
||||||
Event e = static_cast<Event>(context->eventLog.get(ei++));
|
Event e = static_cast<Event>(context->eventLog.get(ei++));
|
||||||
switch (e) {
|
switch (e) {
|
||||||
case PushEvent: {
|
case PushEvent: {
|
||||||
calculateJunctions(t, context, roots, known);
|
ei = calculateJunctions(t, context, roots, known, ei);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case PopEvent:
|
case PopEvent:
|
||||||
return;
|
return ei;
|
||||||
|
|
||||||
case IpEvent: {
|
case IpEvent: {
|
||||||
ip = context->eventLog.get2(ei);
|
ip = context->eventLog.get2(ei);
|
||||||
@ -3485,11 +3495,32 @@ calculateJunctions(MyThread* t, Context* context, uintptr_t* originalRoots,
|
|||||||
uintptr_t* tableRoots = context->rootTable + (ip * mapSize);
|
uintptr_t* tableRoots = context->rootTable + (ip * mapSize);
|
||||||
uintptr_t* tableKnown = context->knownTable + (ip * mapSize);
|
uintptr_t* tableKnown = context->knownTable + (ip * mapSize);
|
||||||
|
|
||||||
|
if (DebugFrameMaps) {
|
||||||
|
fprintf(stderr, " roots at ip %3d: ", ip);
|
||||||
|
printSet(*roots);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
|
||||||
|
fprintf(stderr, " known at ip %3d: ", ip);
|
||||||
|
printSet(*known);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
for (unsigned wi = 0; wi < mapSize; ++wi) {
|
for (unsigned wi = 0; wi < mapSize; ++wi) {
|
||||||
tableRoots[wi] &= ~(known[wi] & ~roots[wi]);
|
tableRoots[wi] &= ~(known[wi] & ~roots[wi]);
|
||||||
|
tableRoots[wi] |= known[wi] & roots[wi] & ~tableKnown[wi];
|
||||||
tableKnown[wi] |= known[wi];
|
tableKnown[wi] |= known[wi];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (DebugFrameMaps) {
|
||||||
|
fprintf(stderr, "table roots at ip %3d: ", ip);
|
||||||
|
printSet(*tableRoots);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
|
||||||
|
fprintf(stderr, "table known at ip %3d: ", ip);
|
||||||
|
printSet(*tableKnown);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
memset(roots, 0, mapSize * BytesPerWord);
|
memset(roots, 0, mapSize * BytesPerWord);
|
||||||
memset(known, 0, mapSize * BytesPerWord);
|
memset(known, 0, mapSize * BytesPerWord);
|
||||||
}
|
}
|
||||||
@ -3498,8 +3529,6 @@ calculateJunctions(MyThread* t, Context* context, uintptr_t* originalRoots,
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case MarkEvent: {
|
case MarkEvent: {
|
||||||
assert(t, ip >= 0);
|
|
||||||
|
|
||||||
unsigned i = context->eventLog.get2(ei);
|
unsigned i = context->eventLog.get2(ei);
|
||||||
markBit(roots, i);
|
markBit(roots, i);
|
||||||
markBit(known, i);
|
markBit(known, i);
|
||||||
@ -3508,8 +3537,6 @@ calculateJunctions(MyThread* t, Context* context, uintptr_t* originalRoots,
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case ClearEvent: {
|
case ClearEvent: {
|
||||||
assert(t, ip >= 0);
|
|
||||||
|
|
||||||
unsigned i = context->eventLog.get2(ei);
|
unsigned i = context->eventLog.get2(ei);
|
||||||
clearBit(roots, i);
|
clearBit(roots, i);
|
||||||
markBit(known, i);
|
markBit(known, i);
|
||||||
@ -3524,10 +3551,13 @@ calculateJunctions(MyThread* t, Context* context, uintptr_t* originalRoots,
|
|||||||
default: abort(t);
|
default: abort(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return ei;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
unsigned
|
||||||
updateTraceElements(MyThread* t, Context* context, uintptr_t* originalRoots)
|
updateTraceElements(MyThread* t, Context* context, uintptr_t* originalRoots,
|
||||||
|
unsigned ei)
|
||||||
{
|
{
|
||||||
unsigned mapSize = frameMapSizeInWords(t, context->method);
|
unsigned mapSize = frameMapSizeInWords(t, context->method);
|
||||||
|
|
||||||
@ -3536,15 +3566,15 @@ updateTraceElements(MyThread* t, Context* context, uintptr_t* originalRoots)
|
|||||||
|
|
||||||
int32_t ip = -1;
|
int32_t ip = -1;
|
||||||
|
|
||||||
for (unsigned ei = 0; ei < context->eventLog.length();) {
|
while (ei < context->eventLog.length()) {
|
||||||
Event e = static_cast<Event>(context->eventLog.get(ei++));
|
Event e = static_cast<Event>(context->eventLog.get(ei++));
|
||||||
switch (e) {
|
switch (e) {
|
||||||
case PushEvent: {
|
case PushEvent: {
|
||||||
updateTraceElements(t, context, roots);
|
ei = updateTraceElements(t, context, roots, ei);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case PopEvent:
|
case PopEvent:
|
||||||
return;
|
return ei;
|
||||||
|
|
||||||
case IpEvent: {
|
case IpEvent: {
|
||||||
ip = context->eventLog.get2(ei);
|
ip = context->eventLog.get2(ei);
|
||||||
@ -3562,8 +3592,6 @@ updateTraceElements(MyThread* t, Context* context, uintptr_t* originalRoots)
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case MarkEvent: {
|
case MarkEvent: {
|
||||||
assert(t, ip >= 0);
|
|
||||||
|
|
||||||
unsigned i = context->eventLog.get2(ei);
|
unsigned i = context->eventLog.get2(ei);
|
||||||
markBit(roots, i);
|
markBit(roots, i);
|
||||||
|
|
||||||
@ -3571,8 +3599,6 @@ updateTraceElements(MyThread* t, Context* context, uintptr_t* originalRoots)
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case ClearEvent: {
|
case ClearEvent: {
|
||||||
assert(t, ip >= 0);
|
|
||||||
|
|
||||||
unsigned i = context->eventLog.get2(ei);
|
unsigned i = context->eventLog.get2(ei);
|
||||||
clearBit(roots, i);
|
clearBit(roots, i);
|
||||||
|
|
||||||
@ -3581,7 +3607,13 @@ updateTraceElements(MyThread* t, Context* context, uintptr_t* originalRoots)
|
|||||||
|
|
||||||
case TraceEvent: {
|
case TraceEvent: {
|
||||||
TraceElement* te; context->eventLog.get(ei, &te, BytesPerWord);
|
TraceElement* te; context->eventLog.get(ei, &te, BytesPerWord);
|
||||||
memcpy(te->map, roots, singleMapSize * BytesPerWord);
|
memcpy(te->map, roots, mapSize * BytesPerWord);
|
||||||
|
|
||||||
|
if (DebugFrameMaps) {
|
||||||
|
fprintf(stderr, " map at ip %3d: ", ip);
|
||||||
|
printSet(*roots);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
ei += BytesPerWord;
|
ei += BytesPerWord;
|
||||||
} break;
|
} break;
|
||||||
@ -3589,6 +3621,8 @@ updateTraceElements(MyThread* t, Context* context, uintptr_t* originalRoots)
|
|||||||
default: abort(t);
|
default: abort(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return ei;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -3597,17 +3631,17 @@ calculateFrameMaps(MyThread* t, Context* context)
|
|||||||
unsigned mapSize = frameMapSizeInWords(t, context->method);
|
unsigned mapSize = frameMapSizeInWords(t, context->method);
|
||||||
|
|
||||||
uintptr_t roots[mapSize];
|
uintptr_t roots[mapSize];
|
||||||
memse(roots, 0, mapSize * BytesPerWord);
|
memset(roots, 0, mapSize * BytesPerWord);
|
||||||
|
|
||||||
uintptr_t known[mapSize];
|
uintptr_t known[mapSize];
|
||||||
memset(known, 0xFF, mapSize * BytesPerWord);
|
memset(known, 0xFF, mapSize * BytesPerWord);
|
||||||
|
|
||||||
// first pass: calculate reachable roots at instructions with more
|
// first pass: calculate reachable roots at instructions with more
|
||||||
// than one predecessor.
|
// than one predecessor.
|
||||||
calculateJunctions(t, context, roots, known);
|
calculateJunctions(t, context, roots, known, 0);
|
||||||
|
|
||||||
// second pass: update trace elements.
|
// second pass: update trace elements.
|
||||||
updateTraceElements(t, context, root);
|
updateTraceElements(t, context, roots, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
@ -3652,9 +3686,11 @@ finish(MyThread* t, Context* context, const char* name)
|
|||||||
set(t, result, SingletonBody + offset, p->value);
|
set(t, result, SingletonBody + offset, p->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateExceptionHandlerTable(t, c, methodCode(t, context->method));
|
updateExceptionHandlerTable(t, c, methodCode(t, context->method),
|
||||||
|
reinterpret_cast<intptr_t>(start));
|
||||||
|
|
||||||
updateLineNumberTable(t, c, methodCode(t, context->method));
|
updateLineNumberTable(t, c, methodCode(t, context->method),
|
||||||
|
reinterpret_cast<intptr_t>(start));
|
||||||
|
|
||||||
if (Verbose) {
|
if (Verbose) {
|
||||||
logCompile
|
logCompile
|
||||||
@ -3707,11 +3743,15 @@ compile(MyThread* t, Context* context)
|
|||||||
handleEntrance(t, &frame);
|
handleEntrance(t, &frame);
|
||||||
|
|
||||||
unsigned index = 0;
|
unsigned index = 0;
|
||||||
if ((methodFlags(t, method) & ACC_STATIC) == 0) {
|
if ((methodFlags(t, context->method) & ACC_STATIC) == 0) {
|
||||||
frame.mark(index++);
|
frame.mark(index++);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (MethodSpecIterator it(t, spec); it.hasNext();) {
|
for (MethodSpecIterator it
|
||||||
|
(t, reinterpret_cast<const char*>
|
||||||
|
(&byteArrayBody(t, methodSpec(t, context->method), 0)));
|
||||||
|
it.hasNext();)
|
||||||
|
{
|
||||||
switch (*it.next()) {
|
switch (*it.next()) {
|
||||||
case 'L':
|
case 'L':
|
||||||
case '[':
|
case '[':
|
||||||
@ -3745,10 +3785,11 @@ compile(MyThread* t, Context* context)
|
|||||||
assert(t, context->visitTable[start]);
|
assert(t, context->visitTable[start]);
|
||||||
|
|
||||||
uintptr_t stackMap[stackMapSizeInWords(t, context->method)];
|
uintptr_t stackMap[stackMapSizeInWords(t, context->method)];
|
||||||
Frame frame2(&frame, map);
|
Frame frame2(&frame, stackMap);
|
||||||
frame2.pushObject();
|
frame2.pushObject();
|
||||||
|
|
||||||
uintptr_t* roots = context->rootTable + (start * mapSize);
|
uintptr_t* roots = context->rootTable
|
||||||
|
+ (start * frameMapSizeInWords(t, context->method));
|
||||||
|
|
||||||
for (unsigned i = 0;
|
for (unsigned i = 0;
|
||||||
i < codeMaxLocals(t, methodCode(t, context->method));
|
i < codeMaxLocals(t, methodCode(t, context->method));
|
||||||
@ -3987,12 +4028,12 @@ visitStackAndLocals(MyThread* t, Heap::Visitor* v, void* base, object node,
|
|||||||
if (calleeBase) {
|
if (calleeBase) {
|
||||||
unsigned parameterFootprint = methodParameterFootprint(t, method);
|
unsigned parameterFootprint = methodParameterFootprint(t, method);
|
||||||
unsigned height = static_cast<uintptr_t*>(base)
|
unsigned height = static_cast<uintptr_t*>(base)
|
||||||
- static_cast<uintptr_t*>(calleeBase) - 1;
|
- static_cast<uintptr_t*>(calleeBase) - 2;
|
||||||
|
|
||||||
count = parameterFootprint + height - argumentFootprint;
|
count = parameterFootprint + height - argumentFootprint;
|
||||||
} else {
|
} else {
|
||||||
count = codeMaxStack(t, methodCode(t, method))
|
count = codeMaxStack(t, methodCode(t, method))
|
||||||
+ codeMaxLocals(t, methodCode(t, method))
|
+ codeMaxLocals(t, methodCode(t, method));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count) {
|
if (count) {
|
||||||
@ -4016,8 +4057,6 @@ visitStack(MyThread* t, Heap::Visitor* v)
|
|||||||
ip = *stack;
|
ip = *stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
#error "todo: don't visit arguments twice"
|
|
||||||
|
|
||||||
MyThread::CallTrace* trace = t->trace;
|
MyThread::CallTrace* trace = t->trace;
|
||||||
void* calleeBase = 0;
|
void* calleeBase = 0;
|
||||||
unsigned argumentFootprint = 0;
|
unsigned argumentFootprint = 0;
|
||||||
@ -4026,7 +4065,7 @@ visitStack(MyThread* t, Heap::Visitor* v)
|
|||||||
object node = findTraceNode(t, ip);
|
object node = findTraceNode(t, ip);
|
||||||
if (node) {
|
if (node) {
|
||||||
PROTECT(t, node);
|
PROTECT(t, node);
|
||||||
|
|
||||||
visitStackAndLocals(t, v, base, node, calleeBase, argumentFootprint);
|
visitStackAndLocals(t, v, base, node, calleeBase, argumentFootprint);
|
||||||
|
|
||||||
calleeBase = base;
|
calleeBase = base;
|
||||||
|
20
src/vector.h
20
src/vector.h
@ -98,6 +98,26 @@ class Vector {
|
|||||||
append(&v, BytesPerWord);
|
append(&v, BytesPerWord);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned get(unsigned offset) {
|
||||||
|
uint8_t v; get(offset, &v, 1);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned get2(unsigned offset) {
|
||||||
|
uint16_t v; get(offset, &v, 2);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned get4(unsigned offset) {
|
||||||
|
uint32_t v; get(offset, &v, 4);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t getAddress(unsigned offset) {
|
||||||
|
uintptr_t v; get(offset, &v, BytesPerWord);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned length() {
|
unsigned length() {
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
24
test/GC.java
24
test/GC.java
@ -28,25 +28,25 @@ public class GC {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void lifetime1(boolean predicate) {
|
private static void stackMap1(boolean predicate) {
|
||||||
if (predicate) {
|
if (predicate) {
|
||||||
Object a = null;
|
Object a = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
small();
|
System.gc();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void lifetime2(boolean predicate) {
|
private static void stackMap2(boolean predicate) {
|
||||||
if (predicate) {
|
if (predicate) {
|
||||||
int a = 42;
|
int a = 42;
|
||||||
} else {
|
} else {
|
||||||
Object a = null;
|
Object a = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
small();
|
System.gc();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void lifetime3(boolean predicate) {
|
private static void stackMap3(boolean predicate) {
|
||||||
int i = 2;
|
int i = 2;
|
||||||
if (predicate) {
|
if (predicate) {
|
||||||
Object a = null;
|
Object a = null;
|
||||||
@ -55,7 +55,7 @@ public class GC {
|
|||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
small();
|
System.gc();
|
||||||
int a = 42;
|
int a = 42;
|
||||||
-- i;
|
-- i;
|
||||||
} while (i >= 0);
|
} while (i >= 0);
|
||||||
@ -79,14 +79,14 @@ public class GC {
|
|||||||
array[1].toString();
|
array[1].toString();
|
||||||
array[2].toString();
|
array[2].toString();
|
||||||
|
|
||||||
lifetime1(true);
|
stackMap1(true);
|
||||||
lifetime1(false);
|
stackMap1(false);
|
||||||
|
|
||||||
lifetime2(true);
|
stackMap2(true);
|
||||||
lifetime2(false);
|
stackMap2(false);
|
||||||
|
|
||||||
lifetime3(true);
|
stackMap3(true);
|
||||||
lifetime3(false);
|
stackMap3(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user