mirror of
https://github.com/corda/corda.git
synced 2025-01-19 11:16:54 +00:00
fix corner cases which led to crashes in JIT compiler
Compiling the entire OpenJDK class library into a bootimage revealed some corner cases which broke the compiler, including synchronization in a finally block and gotos targeting the first instruction of an unsynchronized method.
This commit is contained in:
parent
aea02e545f
commit
4f23601b56
112
src/compiler.cpp
112
src/compiler.cpp
@ -982,9 +982,30 @@ valid(Read* r)
|
|||||||
return r and r->valid();
|
return r and r->valid();
|
||||||
}
|
}
|
||||||
|
|
||||||
Read*
|
bool
|
||||||
live(Value* v)
|
hasBuddy(Context* c, Value* a, Value* b)
|
||||||
{
|
{
|
||||||
|
if (a == b) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (Value* p = a->buddy; p != a; p = p->buddy) {
|
||||||
|
if (p == b) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (++i > 1000) {
|
||||||
|
abort(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Read*
|
||||||
|
live(Context* c UNUSED, Value* v)
|
||||||
|
{
|
||||||
|
assert(c, hasBuddy(c, v->buddy, v));
|
||||||
|
|
||||||
Value* p = v;
|
Value* p = v;
|
||||||
do {
|
do {
|
||||||
if (valid(p->reads)) {
|
if (valid(p->reads)) {
|
||||||
@ -999,6 +1020,8 @@ live(Value* v)
|
|||||||
Read*
|
Read*
|
||||||
liveNext(Context* c, Value* v)
|
liveNext(Context* c, Value* v)
|
||||||
{
|
{
|
||||||
|
assert(c, hasBuddy(c, v->buddy, v));
|
||||||
|
|
||||||
Read* r = v->reads->next(c);
|
Read* r = v->reads->next(c);
|
||||||
if (valid(r)) return r;
|
if (valid(r)) return r;
|
||||||
|
|
||||||
@ -1082,7 +1105,7 @@ popRead(Context* c, Event* e UNUSED, Value* v)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Read* r = live(v);
|
Read* r = live(c, v);
|
||||||
if (r) {
|
if (r) {
|
||||||
deadBuddy(c, v, r);
|
deadBuddy(c, v, r);
|
||||||
} else {
|
} else {
|
||||||
@ -1493,7 +1516,7 @@ pickTarget(Context* c, Read* read, bool intersectRead,
|
|||||||
|
|
||||||
Value* successor = read->successor();
|
Value* successor = read->successor();
|
||||||
if (successor) {
|
if (successor) {
|
||||||
Read* r = live(successor);
|
Read* r = live(c, successor);
|
||||||
if (r) {
|
if (r) {
|
||||||
SiteMask intersection = mask;
|
SiteMask intersection = mask;
|
||||||
if (r->intersect(&intersection)) {
|
if (r->intersect(&intersection)) {
|
||||||
@ -2534,7 +2557,7 @@ steal(Context* c, Resource* r, Value* thief)
|
|||||||
{
|
{
|
||||||
r->site->freeze(c, r->value);
|
r->site->freeze(c, r->value);
|
||||||
|
|
||||||
maybeMove(c, live(r->value), false, true, StealRegisterReserveCount);
|
maybeMove(c, live(c, r->value), false, true, StealRegisterReserveCount);
|
||||||
|
|
||||||
r->site->thaw(c, r->value);
|
r->site->thaw(c, r->value);
|
||||||
}
|
}
|
||||||
@ -3360,9 +3383,9 @@ class CallEvent: public Event {
|
|||||||
|
|
||||||
clean(c, this, stackBefore, localsBefore, reads, popIndex);
|
clean(c, this, stackBefore, localsBefore, reads, popIndex);
|
||||||
|
|
||||||
if (resultSize and live(result)) {
|
if (resultSize and live(c, result)) {
|
||||||
addSite(c, result, registerSite(c, c->arch->returnLow()));
|
addSite(c, result, registerSite(c, c->arch->returnLow()));
|
||||||
if (resultSize > BytesPerWord and live(result->nextWord)) {
|
if (resultSize > BytesPerWord and live(c, result->nextWord)) {
|
||||||
addSite(c, result->nextWord, registerSite(c, c->arch->returnHigh()));
|
addSite(c, result->nextWord, registerSite(c, c->arch->returnHigh()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3446,7 +3469,7 @@ maybeMove(Context* c, BinaryOperation type, unsigned srcSize,
|
|||||||
unsigned srcSelectSize, Value* src, unsigned dstSize, Value* dst,
|
unsigned srcSelectSize, Value* src, unsigned dstSize, Value* dst,
|
||||||
const SiteMask& dstMask)
|
const SiteMask& dstMask)
|
||||||
{
|
{
|
||||||
Read* read = live(dst);
|
Read* read = live(c, dst);
|
||||||
bool isStore = read == 0;
|
bool isStore = read == 0;
|
||||||
|
|
||||||
Site* target;
|
Site* target;
|
||||||
@ -3607,8 +3630,8 @@ Site*
|
|||||||
pickSiteOrMove(Context* c, Value* src, Value* dst, Site* nextWord,
|
pickSiteOrMove(Context* c, Value* src, Value* dst, Site* nextWord,
|
||||||
unsigned index)
|
unsigned index)
|
||||||
{
|
{
|
||||||
if (live(dst)) {
|
if (live(c, dst)) {
|
||||||
Read* read = live(src);
|
Read* read = live(c, src);
|
||||||
Site* s;
|
Site* s;
|
||||||
if (nextWord) {
|
if (nextWord) {
|
||||||
s = pickMatchOrMove(c, read, nextWord, index, false);
|
s = pickMatchOrMove(c, read, nextWord, index, false);
|
||||||
@ -3727,7 +3750,7 @@ class MoveEvent: public Event {
|
|||||||
apply(c, Move, srcSelectSize, src->source, src->source,
|
apply(c, Move, srcSelectSize, src->source, src->source,
|
||||||
dstSize, dst->target, dst->target);
|
dstSize, dst->target, dst->target);
|
||||||
|
|
||||||
if (live(dst) == 0) {
|
if (live(c, dst) == 0) {
|
||||||
removeSite(c, dst, dst->target);
|
removeSite(c, dst, dst->target);
|
||||||
if (dstSize > BytesPerWord) {
|
if (dstSize > BytesPerWord) {
|
||||||
removeSite(c, dst->nextWord, dst->nextWord->target);
|
removeSite(c, dst->nextWord, dst->nextWord->target);
|
||||||
@ -3754,7 +3777,7 @@ class MoveEvent: public Event {
|
|||||||
assert(c, srcSize == BytesPerWord);
|
assert(c, srcSize == BytesPerWord);
|
||||||
assert(c, srcSelectSize == BytesPerWord);
|
assert(c, srcSelectSize == BytesPerWord);
|
||||||
|
|
||||||
if (dst->nextWord->target or live(dst->nextWord)) {
|
if (dst->nextWord->target or live(c, dst->nextWord)) {
|
||||||
assert(c, dstLowMask.typeMask & (1 << RegisterOperand));
|
assert(c, dstLowMask.typeMask & (1 << RegisterOperand));
|
||||||
|
|
||||||
Site* low = freeRegisterSite(c, dstLowMask.registerMask);
|
Site* low = freeRegisterSite(c, dstLowMask.registerMask);
|
||||||
@ -3945,12 +3968,12 @@ class CombineEvent: public Event {
|
|||||||
virtual void compile(Context* c) {
|
virtual void compile(Context* c) {
|
||||||
assert(c, first->source->type(c) == first->nextWord->source->type(c));
|
assert(c, first->source->type(c) == first->nextWord->source->type(c));
|
||||||
|
|
||||||
if (second->source->type(c) != second->nextWord->source->type(c)) {
|
// if (second->source->type(c) != second->nextWord->source->type(c)) {
|
||||||
fprintf(stderr, "%p %p %d : %p %p %d\n",
|
// fprintf(stderr, "%p %p %d : %p %p %d\n",
|
||||||
second, second->source, second->source->type(c),
|
// second, second->source, second->source->type(c),
|
||||||
second->nextWord, second->nextWord->source,
|
// second->nextWord, second->nextWord->source,
|
||||||
second->nextWord->source->type(c));
|
// second->nextWord->source->type(c));
|
||||||
}
|
// }
|
||||||
|
|
||||||
assert(c, second->source->type(c) == second->nextWord->source->type(c));
|
assert(c, second->source->type(c) == second->nextWord->source->type(c));
|
||||||
|
|
||||||
@ -4004,9 +4027,9 @@ class CombineEvent: public Event {
|
|||||||
high->thaw(c, second->nextWord);
|
high->thaw(c, second->nextWord);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (live(result)) {
|
if (live(c, result)) {
|
||||||
addSite(c, result, low);
|
addSite(c, result, low);
|
||||||
if (resultSize > lowSize and live(result->nextWord)) {
|
if (resultSize > lowSize and live(c, result->nextWord)) {
|
||||||
addSite(c, result->nextWord, high);
|
addSite(c, result->nextWord, high);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4043,11 +4066,11 @@ removeBuddy(Context* c, Value* v)
|
|||||||
|
|
||||||
assert(c, p->buddy);
|
assert(c, p->buddy);
|
||||||
|
|
||||||
if (not live(next)) {
|
if (not live(c, next)) {
|
||||||
clearSites(c, next);
|
clearSites(c, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (not live(v)) {
|
if (not live(c, v)) {
|
||||||
clearSites(c, v);
|
clearSites(c, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4420,9 +4443,9 @@ class TranslateEvent: public Event {
|
|||||||
high->thaw(c, value->nextWord);
|
high->thaw(c, value->nextWord);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (live(result)) {
|
if (live(c, result)) {
|
||||||
addSite(c, result, low);
|
addSite(c, result, low);
|
||||||
if (resultSize > lowSize and live(result->nextWord)) {
|
if (resultSize > lowSize and live(c, result->nextWord)) {
|
||||||
addSite(c, result->nextWord, high);
|
addSite(c, result->nextWord, high);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4937,7 +4960,7 @@ class FrameSiteEvent: public Event {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void compile(Context* c) {
|
virtual void compile(Context* c) {
|
||||||
if (live(value)) {
|
if (live(c, value)) {
|
||||||
addSite(c, value, frameSite(c, index));
|
addSite(c, value, frameSite(c, index));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4975,7 +4998,7 @@ visit(Context* c, Link* link)
|
|||||||
Value* v = p->value;
|
Value* v = p->value;
|
||||||
v->reads = p->read->nextTarget();
|
v->reads = p->read->nextTarget();
|
||||||
// fprintf(stderr, "next read %p for %p from %p\n", v->reads, v, p->read);
|
// fprintf(stderr, "next read %p for %p from %p\n", v->reads, v, p->read);
|
||||||
if (not live(v)) {
|
if (not live(c, v)) {
|
||||||
clearSites(c, v);
|
clearSites(c, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5238,7 +5261,7 @@ resolveOriginalSites(Context* c, Event* e, SiteRecordList* frozen,
|
|||||||
{
|
{
|
||||||
FrameIterator::Element el = it.next(c);
|
FrameIterator::Element el = it.next(c);
|
||||||
Value* v = el.value;
|
Value* v = el.value;
|
||||||
Read* r = v ? live(v) : 0;
|
Read* r = v ? live(c, v) : 0;
|
||||||
Site* s = sites[el.localIndex];
|
Site* s = sites[el.localIndex];
|
||||||
|
|
||||||
if (r) {
|
if (r) {
|
||||||
@ -5282,7 +5305,7 @@ resolveSourceSites(Context* c, Event* e, SiteRecordList* frozen, Site** sites)
|
|||||||
for (FrameIterator it(c, e->stackAfter, e->localsAfter); it.hasMore();) {
|
for (FrameIterator it(c, e->stackAfter, e->localsAfter); it.hasMore();) {
|
||||||
FrameIterator::Element el = it.next(c);
|
FrameIterator::Element el = it.next(c);
|
||||||
Value* v = el.value;
|
Value* v = el.value;
|
||||||
Read* r = live(v);
|
Read* r = live(c, v);
|
||||||
|
|
||||||
if (r and sites[el.localIndex] == 0) {
|
if (r and sites[el.localIndex] == 0) {
|
||||||
SiteMask mask((1 << RegisterOperand) | (1 << MemoryOperand),
|
SiteMask mask((1 << RegisterOperand) | (1 << MemoryOperand),
|
||||||
@ -5316,7 +5339,7 @@ resolveTargetSites(Context* c, Event* e, SiteRecordList* frozen, Site** sites)
|
|||||||
for (FrameIterator it(c, e->stackAfter, e->localsAfter); it.hasMore();) {
|
for (FrameIterator it(c, e->stackAfter, e->localsAfter); it.hasMore();) {
|
||||||
FrameIterator::Element el = it.next(c);
|
FrameIterator::Element el = it.next(c);
|
||||||
Value* v = el.value;
|
Value* v = el.value;
|
||||||
Read* r = live(v);
|
Read* r = live(c, v);
|
||||||
|
|
||||||
if (r and sites[el.localIndex] == 0) {
|
if (r and sites[el.localIndex] == 0) {
|
||||||
SiteMask mask((1 << RegisterOperand) | (1 << MemoryOperand),
|
SiteMask mask((1 << RegisterOperand) | (1 << MemoryOperand),
|
||||||
@ -5415,7 +5438,7 @@ populateSiteTables(Context* c, Event* e, SiteRecordList* frozen)
|
|||||||
void
|
void
|
||||||
setSites(Context* c, Value* v, Site* s)
|
setSites(Context* c, Value* v, Site* s)
|
||||||
{
|
{
|
||||||
assert(c, live(v));
|
assert(c, live(c, v));
|
||||||
|
|
||||||
for (; s; s = s->next) {
|
for (; s; s = s->next) {
|
||||||
addSite(c, v, s->copy(c));
|
addSite(c, v, s->copy(c));
|
||||||
@ -5444,7 +5467,7 @@ setSites(Context* c, Event* e, Site** sites)
|
|||||||
for (FrameIterator it(c, e->stackBefore, e->localsBefore); it.hasMore();) {
|
for (FrameIterator it(c, e->stackBefore, e->localsBefore); it.hasMore();) {
|
||||||
FrameIterator::Element el = it.next(c);
|
FrameIterator::Element el = it.next(c);
|
||||||
if (sites[el.localIndex]) {
|
if (sites[el.localIndex]) {
|
||||||
if (live(el.value)) {
|
if (live(c, el.value)) {
|
||||||
setSites(c, el.value, sites[el.localIndex]);
|
setSites(c, el.value, sites[el.localIndex]);
|
||||||
} else if (DebugControl) {
|
} else if (DebugControl) {
|
||||||
char buffer[256]; sitesToString(c, sites[el.localIndex], buffer, 256);
|
char buffer[256]; sitesToString(c, sites[el.localIndex], buffer, 256);
|
||||||
@ -5471,10 +5494,17 @@ void
|
|||||||
restore(Context* c, Event* e, Snapshot* snapshots)
|
restore(Context* c, Event* e, Snapshot* snapshots)
|
||||||
{
|
{
|
||||||
for (Snapshot* s = snapshots; s; s = s->next) {
|
for (Snapshot* s = snapshots; s; s = s->next) {
|
||||||
// char buffer[256]; sitesToString(c, s->sites, buffer, 256);
|
Value* v = s->value;
|
||||||
// fprintf(stderr, "restore %p buddy %p sites %s live %p\n",
|
Value* next = v->buddy;
|
||||||
// s->value, s->value->buddy, buffer, live(s->value));
|
if (v != next) {
|
||||||
|
v->buddy = v;
|
||||||
|
Value* p = next;
|
||||||
|
while (p->buddy != v) p = p->buddy;
|
||||||
|
p->buddy = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Snapshot* s = snapshots; s; s = s->next) {
|
||||||
assert(c, s->buddy);
|
assert(c, s->buddy);
|
||||||
|
|
||||||
s->value->buddy = s->buddy;
|
s->value->buddy = s->buddy;
|
||||||
@ -5483,11 +5513,15 @@ restore(Context* c, Event* e, Snapshot* snapshots)
|
|||||||
resetFrame(c, e);
|
resetFrame(c, e);
|
||||||
|
|
||||||
for (Snapshot* s = snapshots; s; s = s->next) {
|
for (Snapshot* s = snapshots; s; s = s->next) {
|
||||||
if (live(s->value)) {
|
if (live(c, s->value)) {
|
||||||
if (live(s->value) and s->sites and s->value->sites == 0) {
|
if (live(c, s->value) and s->sites and s->value->sites == 0) {
|
||||||
setSites(c, s->value, s->sites);
|
setSites(c, s->value, s->sites);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// char buffer[256]; sitesToString(c, s->sites, buffer, 256);
|
||||||
|
// fprintf(stderr, "restore %p buddy %p sites %s live %p\n",
|
||||||
|
// s->value, s->value->buddy, buffer, live(c, s->value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5554,7 +5588,7 @@ updateJunctionReads(Context* c, JunctionState* state)
|
|||||||
FrameIterator::Element e = it.next(c);
|
FrameIterator::Element e = it.next(c);
|
||||||
StubReadPair* p = state->reads + e.localIndex;
|
StubReadPair* p = state->reads + e.localIndex;
|
||||||
if (p->value and p->read->read == 0) {
|
if (p->value and p->read->read == 0) {
|
||||||
Read* r = live(e.value);
|
Read* r = live(c, e.value);
|
||||||
if (r) {
|
if (r) {
|
||||||
if (DebugReads) {
|
if (DebugReads) {
|
||||||
fprintf(stderr, "stub read %p for %p valid: %p\n",
|
fprintf(stderr, "stub read %p for %p valid: %p\n",
|
||||||
@ -5784,6 +5818,10 @@ addForkElement(Context* c, Value* v, ForkState* state, unsigned index)
|
|||||||
ForkState*
|
ForkState*
|
||||||
saveState(Context* c)
|
saveState(Context* c)
|
||||||
{
|
{
|
||||||
|
if (c->logicalCode[c->logicalIp]->lastEvent == 0) {
|
||||||
|
appendDummy(c);
|
||||||
|
}
|
||||||
|
|
||||||
unsigned elementCount = frameFootprint(c, c->stack) + count(c->saved);
|
unsigned elementCount = frameFootprint(c, c->stack) + count(c->saved);
|
||||||
|
|
||||||
ForkState* state = new
|
ForkState* state = new
|
||||||
|
@ -104,7 +104,28 @@ public class Misc {
|
|||||||
return (o == null ? default_ : o);
|
return (o == null ? default_ : o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class Zam {
|
||||||
|
public void bim() { }
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Zim {
|
||||||
|
public Object zum() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Zim zim = new Zim();
|
||||||
|
|
||||||
|
private static void zam() {
|
||||||
|
Zam z;
|
||||||
|
while ((z = (Zam) zim.zum()) != null) {
|
||||||
|
z.bim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
zam();
|
||||||
|
|
||||||
Bim bim = new Baz();
|
Bim bim = new Baz();
|
||||||
expect(bim.baz() == 42);
|
expect(bim.baz() == 42);
|
||||||
|
|
||||||
|
@ -138,6 +138,19 @@ public class Subroutine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean test5(boolean predicate) {
|
||||||
|
try {
|
||||||
|
if (predicate) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
synchronized (this) {
|
||||||
|
notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
test(false, false);
|
test(false, false);
|
||||||
test(false, true);
|
test(false, true);
|
||||||
@ -188,6 +201,9 @@ public class Subroutine {
|
|||||||
String.valueOf(test4(3));
|
String.valueOf(test4(3));
|
||||||
|
|
||||||
expect(test4(1) == 0xFABFABFABFL);
|
expect(test4(1) == 0xFABFABFABFL);
|
||||||
|
|
||||||
|
new Subroutine().test5(true);
|
||||||
|
new Subroutine().test5(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class DummyException extends RuntimeException { }
|
private static class DummyException extends RuntimeException { }
|
||||||
|
Loading…
Reference in New Issue
Block a user