handle subroutines properly when generating frame maps (initial sketch)

This commit is contained in:
Joel Dice 2009-06-26 15:36:04 -06:00
parent f239424930
commit b308354a3a
5 changed files with 557 additions and 177 deletions

View File

@ -493,6 +493,70 @@ class PoolElement: public Promise {
};
class Context;
class SubroutineCall;
class Subroutine {
public:
Subroutine(unsigned ip, unsigned logIndex, Subroutine* next):
next(next),
calls(0),
handle(0),
ip(ip),
logIndex(logIndex),
stackIndex(0),
callCount(0),
tableIndex(0),
visited(false)
{ }
Subroutine* next;
SubroutineCall* calls;
Compiler::Subroutine* handle;
unsigned ip;
unsigned logIndex;
unsigned stackIndex;
unsigned callCount;
unsigned tableIndex;
bool visited;
};
class SubroutineCall {
public:
SubroutineCall(Subroutine* subroutine, Promise* returnAddress):
subroutine(subroutine),
returnAddress(returnAddress),
next(subroutine->calls)
{
subroutine->calls = this;
}
Subroutine* subroutine;
Promise* returnAddress;
SubroutineCall* next;
};
class SubroutinePath {
public:
SubroutinePath(SubroutineCall* call, SubroutinePath* next):
call(call),
next(next)
{ }
SubroutineCall* call;
SubroutinePath* next;
};
class SubroutineTrace {
public:
SubroutineTrace(SubroutinePath* path, SubroutineTrace* next):
path(path),
next(next)
{ }
SubroutinePath* path;
SubroutineTrace* next;
uintptr_t map[0];
};
class TraceElement: public TraceHandler {
public:
@ -504,6 +568,7 @@ class TraceElement: public TraceHandler {
context(context),
address(0),
next(next),
subroutineTrace(0),
target(target),
argumentIndex(0),
flags(flags)
@ -519,6 +584,7 @@ class TraceElement: public TraceHandler {
Context* context;
Promise* address;
TraceElement* next;
SubroutineTrace* subroutineTrace;
object target;
unsigned argumentIndex;
unsigned flags;
@ -548,7 +614,9 @@ enum Event {
IpEvent,
MarkEvent,
ClearEvent,
TraceEvent
TraceEvent,
PushSubroutineEvent,
PopSubroutineEvent
};
unsigned
@ -685,11 +753,13 @@ class Context {
method(method),
bootContext(bootContext),
objectPool(0),
objectPoolCount(0),
subroutines(0),
traceLog(0),
traceLogCount(0),
visitTable(makeVisitTable(t, &zone, method)),
rootTable(makeRootTable(t, &zone, method)),
objectPoolCount(0),
traceLogCount(0),
dirtyRoots(false),
eventLog(t->m->system, t->m->heap, 1024),
protector(this)
{ }
@ -703,11 +773,13 @@ class Context {
method(0),
bootContext(0),
objectPool(0),
objectPoolCount(0),
subroutines(0),
traceLog(0),
traceLogCount(0),
visitTable(0),
rootTable(0),
objectPoolCount(0),
traceLogCount(0),
dirtyRoots(false),
eventLog(t->m->system, t->m->heap, 0),
protector(this)
{ }
@ -725,11 +797,12 @@ class Context {
object method;
BootContext* bootContext;
PoolElement* objectPool;
unsigned objectPoolCount;
Subroutine* subroutines;
TraceElement* traceLog;
unsigned traceLogCount;
uint16_t* visitTable;
uintptr_t* rootTable;
unsigned objectPoolCount;
unsigned traceLogCount;
bool dirtyRoots;
Vector eventLog;
MyProtector protector;
@ -1308,11 +1381,63 @@ class Frame {
return e;
}
unsigned startSubroutine(unsigned ip, Promise* returnAddress) {
pushAddress(addressOperand(returnAddress));
Subroutine* subroutine = 0;
for (Subroutine* s = context->subroutines; s; s = s->next) {
if (s->ip == ip) {
subroutine = s;
break;
}
}
if (subroutine == 0) {
context->subroutines = subroutine = new
(context->zone.allocate(sizeof(Subroutine)))
Subroutine(ip, context->eventLog.length(), context->subroutines);
}
subroutine->handle = c->startSubroutine();
this->subroutine = subroutine;
SubroutineCall* call = new
(context->zone.allocate(sizeof(SubroutineCall)))
SubroutineCall(subroutine, returnAddress);
context->eventLog.append(PushSubroutineEvent);
context->eventLog.appendAddress(call);
unsigned nextIndexIndex = context->eventLog.length();
context->eventLog.append2(0);
c->saveLocals();
return nextIndexIndex;
}
void returnFromSubroutine(unsigned returnAddressLocal) {
c->endSubroutine(subroutine->handle);
subroutine->stackIndex = localOffsetFromStack
(t, translateLocalIndex(context, 1, returnAddressLocal),
context->method);
}
void endSubroutine(unsigned nextIndexIndex) {
context->eventLog.set2(nextIndexIndex, context->eventLog.length());
c->cleanLocals();
poppedInt();
context->eventLog.append(PopSubroutineEvent);
}
Context* context;
MyThread* t;
Compiler* c;
Compiler::Subroutine* subroutine;
Subroutine* subroutine;
uint8_t* stackMap;
unsigned ip;
unsigned sp;
@ -2296,67 +2421,6 @@ handleExit(MyThread* t, Frame* frame)
(t, frame, getThunk(t, releaseMonitorForObjectThunk));
}
int
exceptionIndex(MyThread* t, object code, unsigned jsrIp, unsigned dstIp)
{
object table = codeExceptionHandlerTable(t, code);
unsigned length = exceptionHandlerTableLength(t, table);
for (unsigned i = 0; i < length; ++i) {
ExceptionHandler* eh = exceptionHandlerTableBody(t, table, i);
if (exceptionHandlerCatchType(eh) == 0) {
unsigned ip = exceptionHandlerIp(eh);
unsigned index;
switch (codeBody(t, code, ip++)) {
case astore:
index = codeBody(t, code, ip++);
break;
case astore_0:
index = 0;
break;
case astore_1:
index = 1;
break;
case astore_2:
index = 2;
break;
case astore_3:
index = 3;
break;
default: abort(t);
}
if (ip == jsrIp) {
return -1;
}
switch (codeBody(t, code, ip++)) {
case jsr: {
uint32_t offset = codeReadInt16(t, code, ip);
if ((ip - 3) + offset == dstIp) {
return index;
}
} break;
case jsr_w: {
uint32_t offset = codeReadInt32(t, code, ip);
if ((ip - 5) + offset == dstIp) {
return index;
}
} break;
default: break;
}
}
}
abort(t);
}
bool
inTryBlock(MyThread* t, object code, unsigned ip)
{
@ -3540,30 +3604,14 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
assert(t, newIp < codeLength(t, code));
int index = exceptionIndex(t, code, thisIp, newIp);
if (index >= 0) {
// store a null pointer at the same index the exception would
// be stored in the finally block so we can safely treat that
// location as a GC root. Of course, this assumes there
// wasn't already a live value there, which is something we
// should verify once we have complete data flow information
// (todo).
storeLocal(context, 1, c->constant(0), index);
frame->storedObject(translateLocalIndex(context, 1, index));
}
frame->pushAddress(frame->addressOperand(c->machineIp(ip)));
unsigned start = frame->startSubroutine(newIp, c->machineIp(ip));
c->jmp(frame->machineIp(newIp));
frame->subroutine = c->startSubroutine();
compile(t, frame, newIp);
if (UNLIKELY(t->exception)) return;
frame->poppedInt();
c->restoreFromSubroutine(frame->subroutine);
frame->endSubroutine(start);
} break;
case l2d: {
@ -4047,10 +4095,11 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
}
} break;
case ret:
c->jmp(loadLocal(context, 1, codeBody(t, code, ip)));
c->endSubroutine(frame->subroutine);
return;
case ret: {
unsigned index = codeBody(t, code, ip);
c->jmp(loadLocal(context, 1, index));
frame->returnFromSubroutine(index);
} return;
case return_:
if (needsReturnBarrier(t, context->method)) {
@ -4169,10 +4218,11 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
frame->storeLong(codeReadInt16(t, code, ip));
} break;
case ret:
c->jmp(loadLocal(context, 1, codeReadInt16(t, code, ip)));
c->endSubroutine(frame->subroutine);
return;
case ret: {
unsigned index = codeReadInt16(t, code, ip);
c->jmp(loadLocal(context, 1, index));
frame->returnFromSubroutine(index);
} return;
default: abort(t);
}
@ -4294,7 +4344,7 @@ printSet(uintptr_t m, unsigned limit)
unsigned
calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots,
unsigned eventIndex)
unsigned eventIndex, SubroutinePath* subroutinePath = 0)
{
// for each instruction with more than one predecessor, and for each
// stack position, determine if there exists a path to that
@ -4395,11 +4445,36 @@ calculateFrameMaps(MyThread* t, Context* context, uintptr_t* originalRoots,
fprintf(stderr, "\n");
}
memcpy(te->map, roots, mapSize * BytesPerWord);
if (subroutinePath == 0) {
memcpy(te->map, roots, mapSize * BytesPerWord);
} else {
te->subroutineTrace = new
(context->zone.allocate
(sizeof(SubroutineTrace) + (mapSize * BytesPerWord)))
SubroutineTrace(subroutinePath, te->subroutineTrace);
memcpy(te->subroutineTrace->map, roots, mapSize * BytesPerWord);
}
eventIndex += BytesPerWord;
} break;
case PushSubroutineEvent: {
SubroutineCall* call;
context->eventLog.get(eventIndex, &call, BytesPerWord);
eventIndex += BytesPerWord;
unsigned nextIndex = context->eventLog.get2(eventIndex);
eventIndex = nextIndex;
calculateFrameMaps
(t, context, roots, call->subroutine->logIndex, new
(context->zone.allocate(sizeof(SubroutinePath)))
SubroutinePath(call, subroutinePath));
} break;
case PopSubroutineEvent:
return static_cast<unsigned>(-1);
default: abort(t);
}
}
@ -4422,7 +4497,7 @@ compareTraceElementPointers(const void* va, const void* vb)
}
unsigned
frameObjectMapSize(MyThread* t, object method, object map)
simpleFrameMapTableSize(MyThread* t, object method, object map)
{
int size = frameMapSizeInBits(t, method);
return ceiling(intArrayLength(t, map) * size, 32 + size);
@ -4450,21 +4525,230 @@ finish(MyThread* t, Allocator* allocator, Assembler* a, const char* name)
}
void
setBit(MyThread* t, object map, unsigned count, unsigned size, unsigned i,
unsigned j)
setBit(int32_t* dst, unsigned index)
{
unsigned index = ((i * size) + j);
intArrayBody(t, map, count + (index / 32))
|= static_cast<int32_t>(1) << (index % 32);
dst[index / 32] |= static_cast<int32_t>(1) << (index % 32);
}
void
clearBit(MyThread* t, object map, unsigned count, unsigned size, unsigned i,
unsigned j)
clearBit(int32_t* dst, unsigned index)
{
unsigned index = ((i * size) + j);
intArrayBody(t, map, count + (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, "%"LLD"", path->call->returnAddress->value());
path = path->next;
if (path) {
fprintf(stderr, ", ");
} else {
break;
}
}
fprintf(stderr, ")");
}
}
void
copyFrameMap(int32_t* dst, uintptr_t* src, unsigned mapSizeInBits,
unsigned offset, TraceElement* p,
SubroutinePath* subroutinePath)
{
if (DebugFrameMaps) {
fprintf(stderr, " orig roots at ip %p: ", reinterpret_cast<void*>
(p->address->value()));
printSet(src[0], ceiling(mapSizeInBits, BitsPerWord));
print(subroutinePath);
fprintf(stderr, "\n");
fprintf(stderr, "final roots at ip %p: ", reinterpret_cast<void*>
(p->address->value()));
}
for (unsigned j = 0; j < p->argumentIndex; ++j) {
if (getBit(src, j)) {
if (DebugFrameMaps) {
fprintf(stderr, "1");
}
setBit(dst, offset + j);
} else {
if (DebugFrameMaps) {
fprintf(stderr, "_");
}
clearBit(dst, offset + j);
}
}
if (DebugFrameMaps) {
print(subroutinePath);
fprintf(stderr, "\n");
}
}
class FrameMapTableHeader {
public:
FrameMapTableHeader(unsigned indexCount):
indexCount(indexCount)
{ }
unsigned indexCount;
};
class FrameMapTableIndexElement {
public:
FrameMapTableIndexElement(int offset, unsigned base, unsigned path):
offset(offset),
base(base),
path(path)
{ }
int offset;
unsigned base;
unsigned path;
};
class FrameMapTablePath {
public:
FrameMapTablePath(unsigned stackIndex, unsigned elementCount, unsigned next):
stackIndex(stackIndex),
elementCount(elementCount),
next(next)
{ }
unsigned stackIndex;
unsigned elementCount;
unsigned next;
int32_t elements[0];
};
object
makeGeneralFrameMapTable(MyThread* t, Context* context, uint8_t* start,
TraceElement** elements, unsigned pathFootprint,
unsigned mapCount)
{
unsigned mapSize = frameMapSizeInBits(t, context->method);
unsigned indexOffset = sizeof(FrameMapTableHeader);
unsigned mapsOffset = indexOffset
+ (context->traceLogCount * sizeof(FrameMapTableIndexElement));
unsigned pathsOffset = mapsOffset + (ceiling(mapCount * mapSize, 32) * 4);
object table = makeByteArray(t, pathsOffset + pathFootprint);
int8_t* body = &byteArrayBody(t, table, 0);
new (body) FrameMapTableHeader(context->traceLogCount);
unsigned nextTableIndex = pathsOffset;
unsigned nextMapIndex = 0;
for (unsigned i = 0; i < context->traceLogCount; ++i) {
TraceElement* p = elements[i];
unsigned mapBase = nextMapIndex;
unsigned pathIndex;
if (p->subroutineTrace) {
FrameMapTablePath* previous = 0;
Subroutine* subroutine = p->subroutineTrace->path->call->subroutine;
for (Subroutine* s = subroutine; s; s = s->next) {
if (s->tableIndex != 0) {
unsigned pathObjectSize = sizeof(FrameMapTablePath)
+ (sizeof(int32_t) * s->callCount);
assert(t, nextTableIndex + pathObjectSize
<= byteArrayLength(t, table));
s->tableIndex = nextTableIndex;
nextTableIndex += pathObjectSize;
FrameMapTablePath* current = new (body + s->tableIndex)
FrameMapTablePath
(s->stackIndex, s->callCount, s->next ? s->next->tableIndex : 0);
unsigned i = 0;
for (SubroutineCall* c = subroutine->calls; c; c = c->next) {
assert(t, i < s->callCount);
current->elements[i]
= static_cast<intptr_t>(c->returnAddress->value())
- reinterpret_cast<intptr_t>(start);
}
if (previous) {
previous->next = s->tableIndex;
}
previous = current;
} else {
break;
}
}
pathIndex = subroutine->tableIndex;
for (SubroutineTrace* trace = p->subroutineTrace;
trace; trace = trace->next)
{
assert(t, ceiling(nextMapIndex + mapSize, 32) * 4 <= pathsOffset);
copyFrameMap(reinterpret_cast<int32_t*>(body + mapsOffset),
trace->map, mapSize, nextMapIndex, p, trace->path);
nextMapIndex += mapSize;
}
} else {
pathIndex = 0;
assert(t, ceiling(nextMapIndex + mapSize, 32) * 4 <= pathsOffset);
copyFrameMap(reinterpret_cast<int32_t*>(body + mapsOffset), p->map,
mapSize, nextMapIndex, p, 0);
nextMapIndex += mapSize;
}
unsigned elementIndex = indexOffset
+ (i * sizeof(FrameMapTableIndexElement));
assert(t, elementIndex + sizeof(FrameMapTableIndexElement) <= mapsOffset);
new (body + elementIndex) FrameMapTableIndexElement
(static_cast<intptr_t>(p->address->value())
- reinterpret_cast<intptr_t>(start), mapBase, pathIndex);
}
return table;
}
object
makeSimpleFrameMapTable(MyThread* t, Context* context, uint8_t* start,
TraceElement** elements)
{
unsigned mapSize = frameMapSizeInBits(t, context->method);
object table = makeIntArray
(t, context->traceLogCount
+ ceiling(context->traceLogCount * mapSize, 32));
assert(t, intArrayLength(t, table) == context->traceLogCount
+ simpleFrameMapTableSize(t, context->method, table));
for (unsigned i = 0; i < context->traceLogCount; ++i) {
TraceElement* p = elements[i];
intArrayBody(t, table, i) = static_cast<intptr_t>(p->address->value())
- reinterpret_cast<intptr_t>(start);
assert(t, context->traceLogCount + ceiling((i + 1) * mapSize, 32)
<= intArrayLength(t, table));
copyFrameMap(&intArrayBody(t, table, context->traceLogCount), p->map,
mapSize, i * mapSize, p, 0);
}
return table;
}
uint8_t*
@ -4535,9 +4819,27 @@ finish(MyThread* t, Allocator* allocator, Context* context)
if (context->traceLogCount) {
TraceElement* elements[context->traceLogCount];
unsigned index = 0;
unsigned pathFootprint = 0;
unsigned mapCount = 0;
for (TraceElement* p = context->traceLog; p; p = p->next) {
assert(t, index < context->traceLogCount);
SubroutineTrace* trace = p->subroutineTrace;
unsigned myMapCount = 1;
if (trace) {
for (SubroutinePath* sp = trace->path; sp; sp = sp->next) {
Subroutine* subroutine = sp->call->subroutine;
unsigned callCount = subroutine->callCount;
myMapCount *= callCount;
if (not subroutine->visited) {
subroutine->visited = true;
pathFootprint += sizeof(FrameMapTablePath)
+ (sizeof(int32_t) * callCount);
}
}
}
mapCount += myMapCount;
elements[index++] = p;
if (p->target) {
@ -4550,47 +4852,12 @@ finish(MyThread* t, Allocator* allocator, Context* context)
qsort(elements, context->traceLogCount, sizeof(TraceElement*),
compareTraceElementPointers);
unsigned size = frameMapSizeInBits(t, context->method);
object map = makeIntArray
(t, context->traceLogCount
+ ceiling(context->traceLogCount * size, 32));
assert(t, intArrayLength(t, map) == context->traceLogCount
+ frameObjectMapSize(t, context->method, map));
for (unsigned i = 0; i < context->traceLogCount; ++i) {
TraceElement* p = elements[i];
intArrayBody(t, map, i) = static_cast<intptr_t>(p->address->value())
- reinterpret_cast<intptr_t>(start);
if (DebugFrameMaps) {
fprintf(stderr, " orig roots at ip %p: ", reinterpret_cast<void*>
(p->address->value()));
printSet(p->map[0], frameMapSizeInWords(t, context->method));
fprintf(stderr, "\n");
fprintf(stderr, "final roots at ip %p: ", reinterpret_cast<void*>
(p->address->value()));
}
for (unsigned j = 0; j < p->argumentIndex; ++j) {
if (getBit(p->map, j)) {
if (DebugFrameMaps) {
fprintf(stderr, "1");
}
setBit(t, map, context->traceLogCount, size, i, j);
} else {
if (DebugFrameMaps) {
fprintf(stderr, "_");
}
clearBit(t, map, context->traceLogCount, size, i, j);
}
}
if (DebugFrameMaps) {
fprintf(stderr, "\n");
}
object map;
if (pathFootprint) {
map = makeGeneralFrameMapTable
(t, context, start, elements, pathFootprint, mapCount);
} else {
map = makeSimpleFrameMapTable(t, context, start, elements);
}
set(t, methodCode(t, context->method), CodePool, map);
@ -5134,21 +5401,24 @@ invokeNative(MyThread* t)
}
}
unsigned
frameMapIndex(MyThread* t, object method, int32_t offset)
void
findFrameMapInSimpleTable(MyThread* t, object method, object table,
int32_t offset, int32_t** map, unsigned* start)
{
object map = codePool(t, methodCode(t, method));
unsigned mapSize = frameObjectMapSize(t, method, map);
unsigned indexSize = intArrayLength(t, map) - mapSize;
unsigned tableSize = simpleFrameMapTableSize(t, method, table);
unsigned indexSize = intArrayLength(t, table) - tableSize;
*map = &intArrayBody(t, table, indexSize);
unsigned bottom = 0;
unsigned top = indexSize;
for (unsigned span = top - bottom; span; span = top - bottom) {
unsigned middle = bottom + (span / 2);
int32_t v = intArrayBody(t, map, middle);
int32_t v = intArrayBody(t, table, middle);
if (offset == v) {
return (indexSize * 32) + (frameMapSizeInBits(t, method) * middle);
*start = frameMapSizeInBits(t, method) * middle;
return;
} else if (offset < v) {
top = middle;
} else {
@ -5159,6 +5429,75 @@ frameMapIndex(MyThread* t, object method, int32_t offset)
abort(t);
}
unsigned
findFrameMap(MyThread* t, void* stack, object method, object table,
unsigned pathIndex)
{
if (pathIndex) {
FrameMapTablePath* path = reinterpret_cast<FrameMapTablePath*>
(&byteArrayBody(t, table, pathIndex));
void* address = static_cast<void**>(stack)[path->stackIndex];
uint8_t* base = reinterpret_cast<uint8_t*>(methodAddress(t, method));
for (unsigned i = 0; i < path->elementCount; ++i) {
if (address == base + path->elements[i]) {
return i + (path->elementCount * findFrameMap
(t, stack, method, table, path->next));
}
}
abort(t);
} else {
return 0;
}
}
void
findFrameMapInGeneralTable(MyThread* t, void* stack, object method,
object table, int32_t offset, int32_t** map,
unsigned* start)
{
FrameMapTableHeader* header = reinterpret_cast<FrameMapTableHeader*>
(&byteArrayBody(t, table, 0));
FrameMapTableIndexElement* index
= reinterpret_cast<FrameMapTableIndexElement*>
(&byteArrayBody(t, table, sizeof(FrameMapTableHeader)));
*map = reinterpret_cast<int32_t*>(index + header->indexCount);
unsigned bottom = 0;
unsigned top = header->indexCount;
for (unsigned span = top - bottom; span; span = top - bottom) {
unsigned middle = bottom + (span / 2);
FrameMapTableIndexElement* v = index + middle;
if (offset == v->offset) {
*start = v->base + findFrameMap(t, stack, method, table, v->path);
} else if (offset < v->offset) {
top = middle;
} else {
bottom = middle + 1;
}
}
abort(t);
}
void
findFrameMap(MyThread* t, void* stack, object method, int32_t offset,
int32_t** map, unsigned* start)
{
object table = codePool(t, methodCode(t, method));
if (objectClass(t, table)
== arrayBody(t, t->m->types, Machine::IntArrayType))
{
findFrameMapInSimpleTable(t, method, table, offset, map, start);
} else {
findFrameMapInGeneralTable(t, stack, method, table, offset, map, start);
}
}
void
visitStackAndLocals(MyThread* t, Heap::Visitor* v, void* frame, object method,
void* ip)
@ -5166,18 +5505,17 @@ visitStackAndLocals(MyThread* t, Heap::Visitor* v, void* frame, object method,
unsigned count = frameMapSizeInBits(t, method);
if (count) {
object map = codePool(t, methodCode(t, method));
int index = frameMapIndex
(t, method, difference
(ip, reinterpret_cast<void*>(methodAddress(t, method))));
void* stack = stackForFrame(t, frame, method);
int32_t* map;
unsigned offset;
findFrameMap
(t, stack, method, difference
(ip, reinterpret_cast<void*>(methodAddress(t, method))), &map, &offset);
for (unsigned i = 0; i < count; ++i) {
int j = index + i;
if ((intArrayBody(t, map, j / 32)
& (static_cast<int32_t>(1) << (j % 32))))
{
int j = offset + i;
if (map[j / 32] & (static_cast<int32_t>(1) << (j % 32))) {
v->visit(localObject(t, stack, method, i));
}
}
@ -5288,17 +5626,16 @@ walkContinuationBody(MyThread* t, Heap::Walker* w, object c, int start)
count -= start - first;
}
object map = codePool(t, methodCode(t, method));
int index = frameMapIndex
(t, method, difference
int32_t* map;
unsigned offset;
findFrameMap
(t, reinterpret_cast<uintptr_t*>(c) + stack, method, difference
(continuationAddress(t, c),
reinterpret_cast<void*>(methodAddress(t, method))));
reinterpret_cast<void*>(methodAddress(t, method))), &map, &offset);
for (int i = count - 1; i >= 0; --i) {
int j = index + i;
if ((intArrayBody(t, map, j / 32)
& (static_cast<int32_t>(1) << (j % 32))))
{
int j = offset + i;
if (map[j / 32] & (static_cast<int32_t>(1) << (j % 32))) {
if (not w->visit(stack + localOffsetFromStack(t, i, method))) {
return;
}

View File

@ -4016,6 +4016,31 @@ appendSaveLocals(Context* c)
SaveLocalsEvent(c));
}
class CleanLocalsEvent: public Event {
public:
CleanLocalsEvent(Context* c):
Event(c)
{ }
virtual const char* name() {
return "CleanLocalsEvent";
}
virtual void compile(Context* c) {
for (FrameIterator it(c, 0, c->locals); it.hasMore();) {
FrameIterator::Element e = it.next(c);
clean(c, e.value, 0);
}
}
};
void
appendCleanLocals(Context* c)
{
append(c, new (c->zone->allocate(sizeof(CleanLocalsEvent)))
CleanLocalsEvent(c));
}
class DummyEvent: public Event {
public:
DummyEvent(Context* c):
@ -4927,6 +4952,8 @@ class MyCompiler: public Compiler {
}
virtual void endSubroutine(Subroutine* subroutine) {
saveLocals();
static_cast<MySubroutine*>(subroutine)->forkState = ::saveState(&c);
}
@ -5038,6 +5065,13 @@ class MyCompiler: public Compiler {
}
c.logicalIp = logicalIp;
for (unsigned li = 0; li < c.localFootprint; ++li) {
Local* local = c.locals + li;
if (local->value == 0) {
initLocal(1, li);
}
}
}
virtual Promise* machineIp(unsigned logicalIp) {
@ -5333,6 +5367,10 @@ class MyCompiler: public Compiler {
appendSaveLocals(&c);
}
virtual void cleanLocals() {
appendCleanLocals(&c);
}
virtual void checkBounds(Operand* object, unsigned lengthOffset,
Operand* index, intptr_t handler)
{

View File

@ -43,7 +43,6 @@ class Compiler {
virtual Subroutine* startSubroutine() = 0;
virtual void endSubroutine(Subroutine* subroutine) = 0;
virtual void restoreFromSubroutine(Subroutine* subroutine) = 0;
virtual void init(unsigned logicalCodeSize, unsigned parameterFootprint,
unsigned localFootprint, unsigned alignedFrameSize) = 0;
@ -96,6 +95,7 @@ class Compiler {
unsigned index) = 0;
virtual Operand* loadLocal(unsigned footprint, unsigned index) = 0;
virtual void saveLocals() = 0;
virtual void cleanLocals() = 0;
virtual void checkBounds(Operand* object, unsigned lengthOffset,
Operand* index, intptr_t handler) = 0;

View File

@ -110,6 +110,11 @@ class Vector {
append(&v, BytesPerWord);
}
void set2(unsigned offset, uint16_t v) {
assert(s, offset <= position - 2);
memcpy(data + offset, &v, 2);
}
unsigned get(unsigned offset) {
uint8_t v; get(offset, &v, 1);
return v;

View File

@ -63,9 +63,9 @@ public class Subroutine {
test(false, true);
test(true, false);
test2(1);
test2(2);
test2(3);
String.valueOf(test2(1));
String.valueOf(test2(2));
String.valueOf(test2(3));
}
private static class DummyException extends RuntimeException { }