Skip to content

Commit 5524519

Browse files
committed
Root erased initializers from allocations
1 parent 937ec83 commit 5524519

2 files changed

Lines changed: 42 additions & 14 deletions

File tree

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/translation/lua/translation/RemoveGarbage.java

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ private static class Used {
3131
// methods that will be added once the class is used:
3232
private final Multimap<ImClass, ImMethod> waitingMethods = HashMultimap.create();
3333
private final Set<ImClass> classes = new HashSet<>();
34-
/** Classes named directly by reachable code, excluding canonical metadata dependencies. */
35-
private final Set<ImClass> directClasses = new HashSet<>();
34+
/** Classes which reachable code actually allocates, excluding nominal type-only references. */
35+
private final Set<ImClass> instantiatedClasses = new HashSet<>();
3636
private final Set<ImVar> vars = new HashSet<>();
3737
private final Set<ImSet> ignoredInitializers;
3838

@@ -66,8 +66,8 @@ public Set<ImClass> getClasses() {
6666
return classes;
6767
}
6868

69-
public Set<ImClass> getDirectClasses() {
70-
return directClasses;
69+
public Set<ImClass> getInstantiatedClasses() {
70+
return instantiatedClasses;
7171
}
7272

7373
public Set<ImVar> getVars() {
@@ -89,7 +89,7 @@ public void addClass(ImClass c) {
8989
// A targeted specialization has a distinct storage layout but keeps the source
9090
// class's nominal type id and instanceof identity. The canonical class is therefore
9191
// a real metadata dependency even when no source expression names it directly.
92-
visitClass(nominalClass, this, false);
92+
visitClass(nominalClass, this);
9393
}
9494
Collection<ImMethod> imMethods = waitingMethods.get(c);
9595
Iterator<ImMethod> it = imMethods.iterator();
@@ -99,6 +99,15 @@ public void addClass(ImClass c) {
9999
it.remove();
100100
}
101101
}
102+
103+
public void addInstantiatedClass(ImClass c) {
104+
if (!instantiatedClasses.add(c)) {
105+
return;
106+
}
107+
for (ImClassType superClass : c.getSuperClasses()) {
108+
addInstantiatedClass(superClass.getClassDef());
109+
}
110+
}
102111
}
103112

104113
public static void removeGarbage(ImProg prog, ImTranslator translator) {
@@ -173,7 +182,7 @@ public static void removePhantomGenericStaticInitializers(ImProg prog, ImTransla
173182
changed = false;
174183
for (ImVar original : candidates.keySet()) {
175184
ImClass owner = translator.genericStaticOwnerOf(original);
176-
if ((used.getVars().contains(original) || used.getDirectClasses().contains(owner))
185+
if ((used.getVars().contains(original) || used.getInstantiatedClasses().contains(owner))
177186
&& liveOriginals.add(original)) {
178187
changed = true;
179188
}
@@ -248,6 +257,7 @@ public void visit(ImVarArrayAccess e) {
248257
@Override
249258
public void visit(ImAlloc e) {
250259
super.visit(e);
260+
used.addInstantiatedClass(e.getClazz().getClassDef());
251261
visitClass(e.getClazz().getClassDef(), used);
252262
}
253263

@@ -305,19 +315,12 @@ private static void visitMethod(ImMethod m, Used used) {
305315
}
306316

307317
private static void visitClass(ImClass c, Used used) {
308-
visitClass(c, used, true);
309-
}
310-
311-
private static void visitClass(ImClass c, Used used, boolean direct) {
312-
if (direct) {
313-
used.getDirectClasses().add(c);
314-
}
315318
if (used.getClasses().contains(c)) {
316319
return;
317320
}
318321
used.addClass(c);
319322
for (ImClassType superClass : c.getSuperClasses()) {
320-
visitClass(superClass.getClassDef(), used, direct);
323+
visitClass(superClass.getClassDef(), used);
321324
}
322325
}
323326

de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/LuaBackendAuditTests.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,31 @@ public void tupleSpecializedStaticInitializerRunsOnceWithoutErasedInstantiation(
795795
2, countOccurrences(compiled, "bump()")); // one function declaration plus one call
796796
}
797797

798+
@Test
799+
public void tupleSpecializedTypedLocalDoesNotRootErasedInitializer() throws IOException {
800+
test().testLua(true).executeProg().lines(
801+
"package Test",
802+
"native testSuccess()",
803+
"tuple pair(int x, int y)",
804+
"int bumps",
805+
"function bump() returns int",
806+
" bumps++",
807+
" return bumps",
808+
"class Box<T:>",
809+
" static int value = bump()",
810+
" construct()",
811+
"init",
812+
" let box = new Box<pair>()",
813+
" if bumps == 1",
814+
" testSuccess()"
815+
);
816+
817+
String compiled = compiledLua(
818+
"tupleSpecializedTypedLocalDoesNotRootErasedInitializer");
819+
assertEquals("a tuple-specialized local type must not retain the erased initializer",
820+
2, countOccurrences(compiled, "bump()")); // one function declaration plus one call
821+
}
822+
798823
@Test
799824
public void tupleSpecializedStaticKeepsLiveErasedInitializer() {
800825
test().testLua(true).executeProg().lines(

0 commit comments

Comments
 (0)