From d604efd8f591c29dcda8c94e437f63652b062c9f Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 20 May 2008 13:11:42 -0600 Subject: [PATCH] fix local variable caching bug --- src/compiler.cpp | 118 +++++++++++++++++++++++++++++++++-------------- test/Misc.java | 41 ++++++++++++++++ 2 files changed, 124 insertions(+), 35 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index ddbda59956..a50d99002c 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -94,11 +94,12 @@ class State { class Local { public: Local(unsigned size, unsigned index, Value* value, Site* site, Local* next): - size(size), index(index), value(value), site(site), next(next) + size(size), index(index), reuse(true), value(value), site(site), next(next) { } unsigned size; unsigned index; + bool reuse; Value* value; Site* site; Local* next; @@ -1304,11 +1305,7 @@ void cleanStack(Context* c, Stack* stack, Local* locals, Read* reads) { for (Local* l = locals; l; l = l->next) { - clearSites(c, l->value); - } - - for (Local* l = locals; l; l = l->next) { - addSite(c, 0, l->size * BytesPerWord, l->value, l->site); + l->reuse = false; } for (Stack* s = stack; s; s = s->next) { @@ -2087,49 +2084,96 @@ appendPop(Context* c, unsigned count, bool ignore) new (c->zone->allocate(sizeof(PopEvent))) PopEvent(c, count, ignore); } +class ClobberLocalEvent: public Event { + public: + ClobberLocalEvent(Context* c, unsigned size, Local* local): + Event(c), size(size), local(local) + { } + + virtual void compile(Context* c) { + if (DebugCompile) { + fprintf(stderr, "ClobberLocalEvent.compile\n"); + } + + Value* v = local->value; + Site* s = local->site; + if (v->reads + and v->sites->next == 0 + and v->sites == s) + { + preserve(c, stack, size, v, s, v->reads); + } + removeSite(c, v, s); + } + + unsigned size; + Local* local; +}; + +void +appendClobberLocal(Context* c, unsigned size, Local* local) +{ + if (DebugAppend) { + fprintf(stderr, "appendClobberLocal\n"); + } + + new (c->zone->allocate(sizeof(ClobberLocalEvent))) + ClobberLocalEvent(c, size, local); +} + class LocalEvent: public Event { public: - LocalEvent(Context* c, unsigned size, Value* newValue, Value* oldValue, - Site* site): - Event(c), size(size), newValue(newValue), oldValue(oldValue), site(site) - { } + LocalEvent(Context* c, unsigned size, Local* oldLocal, Local* newLocal): + Event(c), size(size), oldLocal(oldLocal), newLocal(newLocal) + { + if (oldLocal) { + addRead(c, oldLocal->value, size, 0); + } + } virtual void compile(Context* c) { if (DebugCompile) { fprintf(stderr, "LocalEvent.compile\n"); } - if (oldValue) { - if (oldValue->reads - and oldValue->sites->next == 0 - and oldValue->sites == site) - { - preserve(c, stack, size, oldValue, site, oldValue->reads); + Site* sites = 0; + if (oldLocal) { + Value* v = oldLocal->value; + if (oldLocal->reuse and v->reads->next == 0) { + sites = v->sites; } - removeSite(c, oldValue, site); + + nextRead(c, v); } - if (newValue->reads) { - addSite(c, 0, size, newValue, site); + Value* v = newLocal->value; + if (v->reads) { + for (Site* s = sites; s;) { + Site* t = s->next; + if (s->type(c) != MemoryOperand) { + addSite(c, stack, size, v, s); + } + s = t; + } + + addSite(c, 0, size, v, newLocal->site); } } unsigned size; - Value* newValue; - Value* oldValue; - Site* site; + Local* oldLocal; + Local* newLocal; }; void -appendLocal(Context* c, unsigned size, Value* newValue, Value* oldValue, - Site* site) +appendLocal(Context* c, unsigned size, Local* oldLocal, Local* newLocal) { if (DebugAppend) { fprintf(stderr, "appendLocal\n"); } new (c->zone->allocate(sizeof(LocalEvent))) - LocalEvent(c, size, newValue, oldValue, site); + LocalEvent(c, size, oldLocal, newLocal); } Site* @@ -2291,23 +2335,19 @@ push(Context* c, unsigned size, Value* v) void addLocal(Context* c, unsigned size, unsigned index, Value* newValue) { - Value* oldValue; unsigned s = ceiling(size, BytesPerWord); Local* local = c->localTable[index]; if (local) { - oldValue = local->value; c->localTable[index] = c->locals = new (c->zone->allocate(sizeof(Local))) Local(s, index, newValue, local->site, c->locals); } else { - oldValue = 0; c->localTable[index] = c->locals = new (c->zone->allocate(sizeof(Local))) Local(s, index, newValue, memorySite (c, c->assembler->base(), localOffset(c, index)), c->locals); } - appendLocal(c, s * BytesPerWord, newValue, oldValue, - c->localTable[index]->site); + appendLocal(c, s * BytesPerWord, local, c->locals); } Value* @@ -2654,16 +2694,24 @@ class MyCompiler: public Compiler { virtual void storeLocal(unsigned size, Operand* src, unsigned index) { assert(&c, index < c.localFootprint); - addLocal(&c, size, index, value(&c)); + + if (c.localTable[index]) { + appendClobberLocal(&c, size, c.localTable[index]); + c.localTable[index] = 0; + } + store(size, src, memory(base(), localOffset(&c, index))); + + // todo: find out why this doesn't work and fix it: +// addLocal(&c, size, index, static_cast(src)); } virtual Operand* loadLocal(unsigned size, unsigned index) { assert(&c, index < c.localFootprint); - if (c.localTable[index] == 0) { - addLocal(&c, size, index, value(&c)); - } - return c.localTable[index]->value; + + Value* v = value(&c); + addLocal(&c, size, index, v); + return v; } virtual void store(unsigned size, Operand* src, Operand* dst) { diff --git a/test/Misc.java b/test/Misc.java index 489386a3f5..8dca62403f 100644 --- a/test/Misc.java +++ b/test/Misc.java @@ -78,7 +78,22 @@ public class Misc { return zap() + 5; } + private static class Foo { + public int a; + public int b; + public int c; + } + + private static int bar(int a, int b, int c) { + return a + b + c; + } + public static void main(String[] args) { + { Foo foo = new Foo(); + int x = foo.a + foo.b + foo.c; + bar(foo.a, foo.b, foo.c); + } + { int get_buffer = 2144642881; int bits_left = 30; int l = 9; @@ -254,9 +269,35 @@ public class Misc { expect(exception != null); } + { int[] array = new int[3]; + int i = 0; + array[i++] = 1; + array[i++] = 2; + array[i++] = 3; + + expect(array[--i] == 3); + expect(array[--i] == 2); + expect(array[--i] == 1); + } + { Object[][] array = new Object[1][1]; expect(array.length == 1); expect(array[0].length == 1); } + + { + Object a = new Object(); + Object b = new Object(); + expect(a != b); + + Object c = a; + Object d = b; + expect(c != d); + + c = (c == a) ? b : a; + d = (d == a) ? b : a; + + expect(c != d); + } } }