mirror of
https://github.com/corda/corda.git
synced 2025-01-19 11:16:54 +00:00
various bugfixes in subroutine stack mapping code
This commit is contained in:
parent
e72ff8db0b
commit
5f6f8039e6
244
src/compile.cpp
244
src/compile.cpp
@ -497,8 +497,10 @@ class SubroutineCall;
|
|||||||
|
|
||||||
class Subroutine {
|
class Subroutine {
|
||||||
public:
|
public:
|
||||||
Subroutine(unsigned ip, unsigned logIndex, Subroutine* next):
|
Subroutine(unsigned ip, unsigned logIndex, Subroutine* listNext,
|
||||||
next(next),
|
Subroutine* stackNext):
|
||||||
|
listNext(listNext),
|
||||||
|
stackNext(stackNext),
|
||||||
calls(0),
|
calls(0),
|
||||||
handle(0),
|
handle(0),
|
||||||
ip(ip),
|
ip(ip),
|
||||||
@ -509,7 +511,8 @@ class Subroutine {
|
|||||||
visited(false)
|
visited(false)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
Subroutine* next;
|
Subroutine* listNext;
|
||||||
|
Subroutine* stackNext;
|
||||||
SubroutineCall* calls;
|
SubroutineCall* calls;
|
||||||
Compiler::Subroutine* handle;
|
Compiler::Subroutine* handle;
|
||||||
unsigned ip;
|
unsigned ip;
|
||||||
@ -520,11 +523,14 @@ class Subroutine {
|
|||||||
bool visited;
|
bool visited;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SubroutinePath;
|
||||||
|
|
||||||
class SubroutineCall {
|
class SubroutineCall {
|
||||||
public:
|
public:
|
||||||
SubroutineCall(Subroutine* subroutine, Promise* returnAddress):
|
SubroutineCall(Subroutine* subroutine, Promise* returnAddress):
|
||||||
subroutine(subroutine),
|
subroutine(subroutine),
|
||||||
returnAddress(returnAddress),
|
returnAddress(returnAddress),
|
||||||
|
paths(0),
|
||||||
next(subroutine->calls)
|
next(subroutine->calls)
|
||||||
{
|
{
|
||||||
subroutine->calls = this;
|
subroutine->calls = this;
|
||||||
@ -533,23 +539,47 @@ class SubroutineCall {
|
|||||||
|
|
||||||
Subroutine* subroutine;
|
Subroutine* subroutine;
|
||||||
Promise* returnAddress;
|
Promise* returnAddress;
|
||||||
|
SubroutinePath* paths;
|
||||||
SubroutineCall* next;
|
SubroutineCall* next;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SubroutinePath {
|
class SubroutinePath {
|
||||||
public:
|
public:
|
||||||
SubroutinePath(SubroutineCall* call, SubroutinePath* next,
|
SubroutinePath(SubroutineCall* call, SubroutinePath* stackNext,
|
||||||
uintptr_t* rootTable):
|
uintptr_t* rootTable):
|
||||||
call(call),
|
call(call),
|
||||||
next(next),
|
stackNext(stackNext),
|
||||||
|
listNext(call->paths),
|
||||||
rootTable(rootTable)
|
rootTable(rootTable)
|
||||||
{ }
|
{
|
||||||
|
call->paths = this;
|
||||||
|
}
|
||||||
|
|
||||||
SubroutineCall* call;
|
SubroutineCall* call;
|
||||||
SubroutinePath* next;
|
SubroutinePath* stackNext;
|
||||||
|
SubroutinePath* listNext;
|
||||||
uintptr_t* rootTable;
|
uintptr_t* rootTable;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
print(SubroutinePath* path)
|
||||||
|
{
|
||||||
|
if (path) {
|
||||||
|
fprintf(stderr, " (");
|
||||||
|
while (true) {
|
||||||
|
fprintf(stderr, "%p", reinterpret_cast<void*>
|
||||||
|
(path->call->returnAddress->value()));
|
||||||
|
path = path->stackNext;
|
||||||
|
if (path) {
|
||||||
|
fprintf(stderr, ", ");
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(stderr, ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class SubroutineTrace {
|
class SubroutineTrace {
|
||||||
public:
|
public:
|
||||||
SubroutineTrace(SubroutinePath* path, SubroutineTrace* next):
|
SubroutineTrace(SubroutinePath* path, SubroutineTrace* next):
|
||||||
@ -567,12 +597,13 @@ class TraceElement: public TraceHandler {
|
|||||||
static const unsigned VirtualCall = 1 << 0;
|
static const unsigned VirtualCall = 1 << 0;
|
||||||
static const unsigned TailCall = 1 << 1;
|
static const unsigned TailCall = 1 << 1;
|
||||||
|
|
||||||
TraceElement(Context* context, object target,
|
TraceElement(Context* context, object target, unsigned flags,
|
||||||
unsigned flags, TraceElement* next):
|
TraceElement* next):
|
||||||
context(context),
|
context(context),
|
||||||
address(0),
|
address(0),
|
||||||
next(next),
|
next(next),
|
||||||
subroutineTrace(0),
|
subroutineTrace(0),
|
||||||
|
subroutineTraceCount(0),
|
||||||
target(target),
|
target(target),
|
||||||
argumentIndex(0),
|
argumentIndex(0),
|
||||||
flags(flags)
|
flags(flags)
|
||||||
@ -589,6 +620,7 @@ class TraceElement: public TraceHandler {
|
|||||||
Promise* address;
|
Promise* address;
|
||||||
TraceElement* next;
|
TraceElement* next;
|
||||||
SubroutineTrace* subroutineTrace;
|
SubroutineTrace* subroutineTrace;
|
||||||
|
unsigned subroutineTraceCount;
|
||||||
object target;
|
object target;
|
||||||
unsigned argumentIndex;
|
unsigned argumentIndex;
|
||||||
unsigned flags;
|
unsigned flags;
|
||||||
@ -618,7 +650,7 @@ enum Event {
|
|||||||
IpEvent,
|
IpEvent,
|
||||||
MarkEvent,
|
MarkEvent,
|
||||||
ClearEvent,
|
ClearEvent,
|
||||||
InitEvent,
|
PushExceptionHandlerEvent,
|
||||||
TraceEvent,
|
TraceEvent,
|
||||||
PushSubroutineEvent,
|
PushSubroutineEvent,
|
||||||
PopSubroutineEvent
|
PopSubroutineEvent
|
||||||
@ -633,7 +665,7 @@ frameMapSizeInBits(MyThread* t, object method)
|
|||||||
unsigned
|
unsigned
|
||||||
frameMapSizeInWords(MyThread* t, object method)
|
frameMapSizeInWords(MyThread* t, object method)
|
||||||
{
|
{
|
||||||
return ceiling(frameMapSizeInBits(t, method), BitsPerWord) * BytesPerWord;
|
return ceiling(frameMapSizeInBits(t, method), BitsPerWord);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t*
|
uint16_t*
|
||||||
@ -762,6 +794,7 @@ class Context {
|
|||||||
traceLog(0),
|
traceLog(0),
|
||||||
visitTable(makeVisitTable(t, &zone, method)),
|
visitTable(makeVisitTable(t, &zone, method)),
|
||||||
rootTable(makeRootTable(t, &zone, method)),
|
rootTable(makeRootTable(t, &zone, method)),
|
||||||
|
subroutineTable(0),
|
||||||
objectPoolCount(0),
|
objectPoolCount(0),
|
||||||
traceLogCount(0),
|
traceLogCount(0),
|
||||||
dirtyRoots(false),
|
dirtyRoots(false),
|
||||||
@ -782,6 +815,7 @@ class Context {
|
|||||||
traceLog(0),
|
traceLog(0),
|
||||||
visitTable(0),
|
visitTable(0),
|
||||||
rootTable(0),
|
rootTable(0),
|
||||||
|
subroutineTable(0),
|
||||||
objectPoolCount(0),
|
objectPoolCount(0),
|
||||||
traceLogCount(0),
|
traceLogCount(0),
|
||||||
dirtyRoots(false),
|
dirtyRoots(false),
|
||||||
@ -806,6 +840,7 @@ class Context {
|
|||||||
TraceElement* traceLog;
|
TraceElement* traceLog;
|
||||||
uint16_t* visitTable;
|
uint16_t* visitTable;
|
||||||
uintptr_t* rootTable;
|
uintptr_t* rootTable;
|
||||||
|
Subroutine** subroutineTable;
|
||||||
unsigned objectPoolCount;
|
unsigned objectPoolCount;
|
||||||
unsigned traceLogCount;
|
unsigned traceLogCount;
|
||||||
bool dirtyRoots;
|
bool dirtyRoots;
|
||||||
@ -1132,6 +1167,10 @@ class Frame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void startLogicalIp(unsigned ip) {
|
void startLogicalIp(unsigned ip) {
|
||||||
|
if (subroutine) {
|
||||||
|
context->subroutineTable[ip] = subroutine;
|
||||||
|
}
|
||||||
|
|
||||||
c->startLogicalIp(ip);
|
c->startLogicalIp(ip);
|
||||||
|
|
||||||
context->eventLog.append(IpEvent);
|
context->eventLog.append(IpEvent);
|
||||||
@ -1391,7 +1430,7 @@ class Frame {
|
|||||||
pushAddress(addressOperand(returnAddress));
|
pushAddress(addressOperand(returnAddress));
|
||||||
|
|
||||||
Subroutine* subroutine = 0;
|
Subroutine* subroutine = 0;
|
||||||
for (Subroutine* s = context->subroutines; s; s = s->next) {
|
for (Subroutine* s = context->subroutines; s; s = s->listNext) {
|
||||||
if (s->ip == ip) {
|
if (s->ip == ip) {
|
||||||
subroutine = s;
|
subroutine = s;
|
||||||
break;
|
break;
|
||||||
@ -1402,7 +1441,17 @@ class Frame {
|
|||||||
context->subroutines = subroutine = new
|
context->subroutines = subroutine = new
|
||||||
(context->zone.allocate(sizeof(Subroutine)))
|
(context->zone.allocate(sizeof(Subroutine)))
|
||||||
Subroutine(ip, context->eventLog.length() + 1 + BytesPerWord + 2,
|
Subroutine(ip, context->eventLog.length() + 1 + BytesPerWord + 2,
|
||||||
context->subroutines);
|
context->subroutines, this->subroutine);
|
||||||
|
|
||||||
|
if (context->subroutineTable == 0) {
|
||||||
|
unsigned size = codeLength(t, methodCode(t, context->method))
|
||||||
|
* sizeof(Subroutine*);
|
||||||
|
|
||||||
|
context->subroutineTable = static_cast<Subroutine**>
|
||||||
|
(context->zone.allocate(size));
|
||||||
|
|
||||||
|
memset(context->subroutineTable, 0, size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
subroutine->handle = c->startSubroutine();
|
subroutine->handle = c->startSubroutine();
|
||||||
@ -1438,6 +1487,8 @@ class Frame {
|
|||||||
context->eventLog.append(PopSubroutineEvent);
|
context->eventLog.append(PopSubroutineEvent);
|
||||||
|
|
||||||
context->eventLog.set2(nextIndexIndex, context->eventLog.length());
|
context->eventLog.set2(nextIndexIndex, context->eventLog.length());
|
||||||
|
|
||||||
|
subroutine = subroutine->stackNext;
|
||||||
}
|
}
|
||||||
|
|
||||||
Context* context;
|
Context* context;
|
||||||
@ -4448,12 +4499,29 @@ calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots,
|
|||||||
clearBit(roots, i);
|
clearBit(roots, i);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case InitEvent: {
|
case PushExceptionHandlerEvent: {
|
||||||
unsigned reference = context->eventLog.get2(eventIndex);
|
unsigned reference = context->eventLog.get2(eventIndex);
|
||||||
eventIndex += 2;
|
eventIndex += 2;
|
||||||
|
|
||||||
uintptr_t* tableRoots = context->rootTable + (reference * mapSize);
|
if (context->subroutineTable and context->subroutineTable[reference]) {
|
||||||
memcpy(roots, tableRoots, mapSize * BytesPerWord);
|
Subroutine* s = context->subroutineTable[reference];
|
||||||
|
unsigned originalEventIndex = eventIndex;
|
||||||
|
|
||||||
|
for (SubroutineCall* c = s->calls; c; c = c->next) {
|
||||||
|
for (SubroutinePath* p = c->paths; p; p = p->listNext) {
|
||||||
|
memcpy(roots, p->rootTable + (reference * mapSize),
|
||||||
|
mapSize * BytesPerWord);
|
||||||
|
|
||||||
|
eventIndex = calculateFrameMaps
|
||||||
|
(t, context, roots, originalEventIndex, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
memcpy(roots, context->rootTable + (reference * mapSize),
|
||||||
|
mapSize * BytesPerWord);
|
||||||
|
|
||||||
|
eventIndex = calculateFrameMaps(t, context, roots, eventIndex, 0);
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case TraceEvent: {
|
case TraceEvent: {
|
||||||
@ -4461,18 +4529,33 @@ calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots,
|
|||||||
if (DebugFrameMaps) {
|
if (DebugFrameMaps) {
|
||||||
fprintf(stderr, "trace roots at ip %3d: ", ip);
|
fprintf(stderr, "trace roots at ip %3d: ", ip);
|
||||||
printSet(*roots, mapSize);
|
printSet(*roots, mapSize);
|
||||||
|
if (subroutinePath) {
|
||||||
|
fprintf(stderr, " ");
|
||||||
|
print(subroutinePath);
|
||||||
|
}
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subroutinePath == 0) {
|
if (subroutinePath == 0) {
|
||||||
memcpy(te->map, roots, mapSize * BytesPerWord);
|
memcpy(te->map, roots, mapSize * BytesPerWord);
|
||||||
} else {
|
} else {
|
||||||
te->subroutineTrace = new
|
SubroutineTrace* trace = 0;
|
||||||
(context->zone.allocate
|
for (SubroutineTrace* t = te->subroutineTrace; t; t = t->next) {
|
||||||
(sizeof(SubroutineTrace) + (mapSize * BytesPerWord)))
|
if (t->path == subroutinePath) {
|
||||||
SubroutineTrace(subroutinePath, te->subroutineTrace);
|
trace = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(te->subroutineTrace->map, roots, mapSize * BytesPerWord);
|
if (trace == 0) {
|
||||||
|
te->subroutineTrace = trace = new
|
||||||
|
(context->zone.allocate
|
||||||
|
(sizeof(SubroutineTrace) + (mapSize * BytesPerWord)))
|
||||||
|
SubroutineTrace(subroutinePath, te->subroutineTrace);
|
||||||
|
|
||||||
|
++ te->subroutineTraceCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(trace->map, roots, mapSize * BytesPerWord);
|
||||||
}
|
}
|
||||||
|
|
||||||
eventIndex += BytesPerWord;
|
eventIndex += BytesPerWord;
|
||||||
@ -4487,11 +4570,21 @@ calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots,
|
|||||||
|
|
||||||
eventIndex = nextIndex;
|
eventIndex = nextIndex;
|
||||||
|
|
||||||
calculateFrameMaps
|
SubroutinePath* path = 0;
|
||||||
(t, context, roots, call->subroutine->logIndex, new
|
for (SubroutinePath* p = call->paths; p; p = p->listNext) {
|
||||||
(context->zone.allocate(sizeof(SubroutinePath)))
|
if (p->stackNext == subroutinePath) {
|
||||||
SubroutinePath(call, subroutinePath,
|
path = p;
|
||||||
makeRootTable(t, &(context->zone), context->method)));
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path == 0) {
|
||||||
|
path = new (context->zone.allocate(sizeof(SubroutinePath)))
|
||||||
|
SubroutinePath(call, subroutinePath,
|
||||||
|
makeRootTable(t, &(context->zone), context->method));
|
||||||
|
}
|
||||||
|
|
||||||
|
calculateFrameMaps(t, context, roots, call->subroutine->logIndex, path);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case PopSubroutineEvent:
|
case PopSubroutineEvent:
|
||||||
@ -4558,25 +4651,6 @@ clearBit(int32_t* dst, unsigned index)
|
|||||||
dst[index / 32] &= ~(static_cast<int32_t>(1) << (index % 32));
|
dst[index / 32] &= ~(static_cast<int32_t>(1) << (index % 32));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
print(SubroutinePath* path)
|
|
||||||
{
|
|
||||||
if (path) {
|
|
||||||
fprintf(stderr, " (");
|
|
||||||
while (true) {
|
|
||||||
fprintf(stderr, "%p", reinterpret_cast<void*>
|
|
||||||
(path->call->returnAddress->value()));
|
|
||||||
path = path->next;
|
|
||||||
if (path) {
|
|
||||||
fprintf(stderr, ", ");
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fprintf(stderr, ")");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
copyFrameMap(int32_t* dst, uintptr_t* src, unsigned mapSizeInBits,
|
copyFrameMap(int32_t* dst, uintptr_t* src, unsigned mapSizeInBits,
|
||||||
unsigned offset, TraceElement* p,
|
unsigned offset, TraceElement* p,
|
||||||
@ -4649,6 +4723,37 @@ class FrameMapTablePath {
|
|||||||
int32_t elements[0];
|
int32_t elements[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
compareInt32s(const void* va, const void* vb)
|
||||||
|
{
|
||||||
|
return *static_cast<int32_t const*>(va) - *static_cast<int32_t const*>(vb);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
compare(SubroutinePath* a, SubroutinePath* b)
|
||||||
|
{
|
||||||
|
if (a->stackNext) {
|
||||||
|
int d = compare(a->stackNext, b->stackNext);
|
||||||
|
if (d) return d;
|
||||||
|
}
|
||||||
|
int64_t av = a->call->returnAddress->value();
|
||||||
|
int64_t bv = b->call->returnAddress->value();
|
||||||
|
if (av > bv) {
|
||||||
|
return 1;
|
||||||
|
} else if (av < bv) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
compareSubroutineTracePointers(const void* va, const void* vb)
|
||||||
|
{
|
||||||
|
return compare((*static_cast<SubroutineTrace* const*>(va))->path,
|
||||||
|
(*static_cast<SubroutineTrace* const*>(vb))->path);
|
||||||
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
makeGeneralFrameMapTable(MyThread* t, Context* context, uint8_t* start,
|
makeGeneralFrameMapTable(MyThread* t, Context* context, uint8_t* start,
|
||||||
TraceElement** elements, unsigned pathFootprint,
|
TraceElement** elements, unsigned pathFootprint,
|
||||||
@ -4675,7 +4780,7 @@ makeGeneralFrameMapTable(MyThread* t, Context* context, uint8_t* start,
|
|||||||
if (p->subroutineTrace) {
|
if (p->subroutineTrace) {
|
||||||
FrameMapTablePath* previous = 0;
|
FrameMapTablePath* previous = 0;
|
||||||
Subroutine* subroutine = p->subroutineTrace->path->call->subroutine;
|
Subroutine* subroutine = p->subroutineTrace->path->call->subroutine;
|
||||||
for (Subroutine* s = subroutine; s; s = s->next) {
|
for (Subroutine* s = subroutine; s; s = s->stackNext) {
|
||||||
if (s->tableIndex == 0) {
|
if (s->tableIndex == 0) {
|
||||||
unsigned pathObjectSize = sizeof(FrameMapTablePath)
|
unsigned pathObjectSize = sizeof(FrameMapTablePath)
|
||||||
+ (sizeof(int32_t) * s->callCount);
|
+ (sizeof(int32_t) * s->callCount);
|
||||||
@ -4689,7 +4794,8 @@ makeGeneralFrameMapTable(MyThread* t, Context* context, uint8_t* start,
|
|||||||
|
|
||||||
FrameMapTablePath* current = new (body + s->tableIndex)
|
FrameMapTablePath* current = new (body + s->tableIndex)
|
||||||
FrameMapTablePath
|
FrameMapTablePath
|
||||||
(s->stackIndex, s->callCount, s->next ? s->next->tableIndex : 0);
|
(s->stackIndex, s->callCount,
|
||||||
|
s->stackNext ? s->stackNext->tableIndex : 0);
|
||||||
|
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
for (SubroutineCall* c = subroutine->calls; c; c = c->next) {
|
for (SubroutineCall* c = subroutine->calls; c; c = c->next) {
|
||||||
@ -4699,6 +4805,10 @@ makeGeneralFrameMapTable(MyThread* t, Context* context, uint8_t* start,
|
|||||||
= static_cast<intptr_t>(c->returnAddress->value())
|
= static_cast<intptr_t>(c->returnAddress->value())
|
||||||
- reinterpret_cast<intptr_t>(start);
|
- reinterpret_cast<intptr_t>(start);
|
||||||
}
|
}
|
||||||
|
assert(t, i == s->callCount);
|
||||||
|
|
||||||
|
qsort(current->elements, s->callCount, sizeof(int32_t),
|
||||||
|
compareInt32s);
|
||||||
|
|
||||||
if (previous) {
|
if (previous) {
|
||||||
previous->next = s->tableIndex;
|
previous->next = s->tableIndex;
|
||||||
@ -4712,20 +4822,34 @@ makeGeneralFrameMapTable(MyThread* t, Context* context, uint8_t* start,
|
|||||||
|
|
||||||
pathIndex = subroutine->tableIndex;
|
pathIndex = subroutine->tableIndex;
|
||||||
|
|
||||||
|
SubroutineTrace* traces[p->subroutineTraceCount];
|
||||||
|
unsigned i = 0;
|
||||||
for (SubroutineTrace* trace = p->subroutineTrace;
|
for (SubroutineTrace* trace = p->subroutineTrace;
|
||||||
trace; trace = trace->next)
|
trace; trace = trace->next)
|
||||||
{
|
{
|
||||||
assert(t, ceiling(nextMapIndex + mapSize, 32) * 4 <= pathsOffset);
|
assert(t, i < p->subroutineTraceCount);
|
||||||
|
traces[i++] = trace;
|
||||||
|
}
|
||||||
|
assert(t, i == p->subroutineTraceCount);
|
||||||
|
|
||||||
|
qsort(traces, p->subroutineTraceCount, sizeof(SubroutineTrace*),
|
||||||
|
compareSubroutineTracePointers);
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < p->subroutineTraceCount; ++i) {
|
||||||
|
assert(t, mapsOffset + ceiling(nextMapIndex + mapSize, 32) * 4
|
||||||
|
<= pathsOffset);
|
||||||
|
|
||||||
copyFrameMap(reinterpret_cast<int32_t*>(body + mapsOffset),
|
copyFrameMap(reinterpret_cast<int32_t*>(body + mapsOffset),
|
||||||
trace->map, mapSize, nextMapIndex, p, trace->path);
|
traces[i]->map, mapSize, nextMapIndex, p,
|
||||||
|
traces[i]->path);
|
||||||
|
|
||||||
nextMapIndex += mapSize;
|
nextMapIndex += mapSize;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pathIndex = 0;
|
pathIndex = 0;
|
||||||
|
|
||||||
assert(t, ceiling(nextMapIndex + mapSize, 32) * 4 <= pathsOffset);
|
assert(t, mapsOffset + ceiling(nextMapIndex + mapSize, 32) * 4
|
||||||
|
<= pathsOffset);
|
||||||
|
|
||||||
copyFrameMap(reinterpret_cast<int32_t*>(body + mapsOffset), p->map,
|
copyFrameMap(reinterpret_cast<int32_t*>(body + mapsOffset), p->map,
|
||||||
mapSize, nextMapIndex, p, 0);
|
mapSize, nextMapIndex, p, 0);
|
||||||
@ -4743,6 +4867,8 @@ makeGeneralFrameMapTable(MyThread* t, Context* context, uint8_t* start,
|
|||||||
- reinterpret_cast<intptr_t>(start), mapBase, pathIndex);
|
- reinterpret_cast<intptr_t>(start), mapBase, pathIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(t, nextMapIndex == mapCount * mapSize);
|
||||||
|
|
||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4852,17 +4978,19 @@ finish(MyThread* t, Allocator* allocator, Context* context)
|
|||||||
SubroutineTrace* trace = p->subroutineTrace;
|
SubroutineTrace* trace = p->subroutineTrace;
|
||||||
unsigned myMapCount = 1;
|
unsigned myMapCount = 1;
|
||||||
if (trace) {
|
if (trace) {
|
||||||
for (SubroutinePath* sp = trace->path; sp; sp = sp->next) {
|
for (Subroutine* s = trace->path->call->subroutine;
|
||||||
Subroutine* subroutine = sp->call->subroutine;
|
s; s = s->stackNext)
|
||||||
unsigned callCount = subroutine->callCount;
|
{
|
||||||
|
unsigned callCount = s->callCount;
|
||||||
myMapCount *= callCount;
|
myMapCount *= callCount;
|
||||||
if (not subroutine->visited) {
|
if (not s->visited) {
|
||||||
subroutine->visited = true;
|
s->visited = true;
|
||||||
pathFootprint += sizeof(FrameMapTablePath)
|
pathFootprint += sizeof(FrameMapTablePath)
|
||||||
+ (sizeof(int32_t) * callCount);
|
+ (sizeof(int32_t) * callCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mapCount += myMapCount;
|
mapCount += myMapCount;
|
||||||
|
|
||||||
elements[index++] = p;
|
elements[index++] = p;
|
||||||
@ -5002,7 +5130,7 @@ compile(MyThread* t, Allocator* allocator, Context* context)
|
|||||||
uint8_t stackMap[codeMaxStack(t, methodCode(t, context->method))];
|
uint8_t stackMap[codeMaxStack(t, methodCode(t, context->method))];
|
||||||
Frame frame2(&frame, stackMap);
|
Frame frame2(&frame, stackMap);
|
||||||
|
|
||||||
context->eventLog.append(InitEvent);
|
context->eventLog.append(PushExceptionHandlerEvent);
|
||||||
context->eventLog.append2(start);
|
context->eventLog.append2(start);
|
||||||
|
|
||||||
for (unsigned i = 1;
|
for (unsigned i = 1;
|
||||||
@ -5015,6 +5143,8 @@ compile(MyThread* t, Allocator* allocator, Context* context)
|
|||||||
compile(t, &frame2, exceptionHandlerIp(eh), start);
|
compile(t, &frame2, exceptionHandlerIp(eh), start);
|
||||||
if (UNLIKELY(t->exception)) return 0;
|
if (UNLIKELY(t->exception)) return 0;
|
||||||
|
|
||||||
|
context->eventLog.append(PopContextEvent);
|
||||||
|
|
||||||
eventIndex = calculateFrameMaps(t, context, 0, eventIndex);
|
eventIndex = calculateFrameMaps(t, context, 0, eventIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5491,7 +5621,7 @@ findFrameMapInGeneralTable(MyThread* t, void* stack, object method,
|
|||||||
|
|
||||||
if (offset == v->offset) {
|
if (offset == v->offset) {
|
||||||
*start = v->base + (findFrameMap(t, stack, method, table, v->path)
|
*start = v->base + (findFrameMap(t, stack, method, table, v->path)
|
||||||
* frameMapSizeInWords(t, method));
|
* frameMapSizeInBits(t, method));
|
||||||
return;
|
return;
|
||||||
} else if (offset < v->offset) {
|
} else if (offset < v->offset) {
|
||||||
top = middle;
|
top = middle;
|
||||||
|
@ -58,6 +58,61 @@ public class Subroutine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Object test3(int path1, int path2, int path3) {
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
switch (path1) {
|
||||||
|
case 1:
|
||||||
|
return new Object();
|
||||||
|
|
||||||
|
case 2: {
|
||||||
|
int a = 42;
|
||||||
|
return Integer.valueOf(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
throw new DummyException();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
switch (path2) {
|
||||||
|
case 1:
|
||||||
|
return new Object();
|
||||||
|
|
||||||
|
case 2: {
|
||||||
|
int a = 42;
|
||||||
|
return Integer.valueOf(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
throw new DummyException();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
switch (path3) {
|
||||||
|
case 1:
|
||||||
|
return new Object();
|
||||||
|
|
||||||
|
case 2: {
|
||||||
|
int a = 42;
|
||||||
|
return Integer.valueOf(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
throw new DummyException();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
System.gc();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
} catch (DummyException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
test(false, false);
|
test(false, false);
|
||||||
test(false, true);
|
test(false, true);
|
||||||
@ -66,6 +121,42 @@ public class Subroutine {
|
|||||||
String.valueOf(test2(1));
|
String.valueOf(test2(1));
|
||||||
String.valueOf(test2(2));
|
String.valueOf(test2(2));
|
||||||
String.valueOf(test2(3));
|
String.valueOf(test2(3));
|
||||||
|
|
||||||
|
String.valueOf(test3(1, 1, 1));
|
||||||
|
String.valueOf(test3(2, 1, 1));
|
||||||
|
String.valueOf(test3(3, 1, 1));
|
||||||
|
|
||||||
|
String.valueOf(test3(1, 2, 1));
|
||||||
|
String.valueOf(test3(2, 2, 1));
|
||||||
|
String.valueOf(test3(3, 2, 1));
|
||||||
|
|
||||||
|
String.valueOf(test3(1, 3, 1));
|
||||||
|
String.valueOf(test3(2, 3, 1));
|
||||||
|
String.valueOf(test3(3, 3, 1));
|
||||||
|
|
||||||
|
String.valueOf(test3(1, 1, 2));
|
||||||
|
String.valueOf(test3(2, 1, 2));
|
||||||
|
String.valueOf(test3(3, 1, 2));
|
||||||
|
|
||||||
|
String.valueOf(test3(1, 2, 2));
|
||||||
|
String.valueOf(test3(2, 2, 2));
|
||||||
|
String.valueOf(test3(3, 2, 2));
|
||||||
|
|
||||||
|
String.valueOf(test3(1, 3, 2));
|
||||||
|
String.valueOf(test3(2, 3, 2));
|
||||||
|
String.valueOf(test3(3, 3, 2));
|
||||||
|
|
||||||
|
String.valueOf(test3(1, 1, 3));
|
||||||
|
String.valueOf(test3(2, 1, 3));
|
||||||
|
String.valueOf(test3(3, 1, 3));
|
||||||
|
|
||||||
|
String.valueOf(test3(1, 2, 3));
|
||||||
|
String.valueOf(test3(2, 2, 3));
|
||||||
|
String.valueOf(test3(3, 2, 3));
|
||||||
|
|
||||||
|
String.valueOf(test3(1, 3, 3));
|
||||||
|
String.valueOf(test3(2, 3, 3));
|
||||||
|
String.valueOf(test3(3, 3, 3));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class DummyException extends RuntimeException { }
|
private static class DummyException extends RuntimeException { }
|
||||||
|
Loading…
Reference in New Issue
Block a user