Skip to content

Commit c0faaae

Browse files
committed
ensure correctness
1 parent 5a48590 commit c0faaae

2 files changed

Lines changed: 32 additions & 64 deletions

File tree

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/intermediatelang/optimizer/DispatchCheckDeduplicator.java

Lines changed: 28 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22

33
import de.peeeq.wurstscript.WurstOperator;
44
import de.peeeq.wurstscript.jassIm.*;
5+
import de.peeeq.wurstscript.translation.imoptimizer.UselessFunctionCallsRemover;
56
import de.peeeq.wurstscript.translation.imoptimizer.OptimizerPass;
67
import de.peeeq.wurstscript.translation.imtranslation.ImTranslator;
78

89
import java.util.ArrayList;
10+
import java.util.HashSet;
911
import java.util.IdentityHashMap;
1012
import java.util.Objects;
1113
import java.util.Set;
@@ -21,12 +23,14 @@ public class DispatchCheckDeduplicator implements OptimizerPass {
2123

2224
private int rewrites;
2325
private final IdentityHashMap<ImFunction, IdentityHashMap<ImVar, Boolean>> mayWriteTypeIdMemo = new IdentityHashMap<>();
26+
private SideEffectAnalyzer sideEffectAnalyzer;
2427

2528
@Override
2629
public int optimize(ImTranslator trans) {
2730
rewrites = 0;
2831
mayWriteTypeIdMemo.clear();
2932
ImProg prog = trans.getImProg();
33+
sideEffectAnalyzer = new SideEffectAnalyzer(prog);
3034
for (ImFunction f : prog.getFunctions()) {
3135
optimizeStmts(f.getBody());
3236
}
@@ -107,9 +111,6 @@ private boolean invalidatesGuard(ImStmt s, GuardPattern guard) {
107111
}
108112
if (s instanceof ImFunctionCall) {
109113
ImFunction f = ((ImFunctionCall) s).getFunc();
110-
if (isKnownNonMutatingFunction(f)) {
111-
return false;
112-
}
113114
return mayWriteTypeId(f, guard.failedCond.typeIdVar);
114115
}
115116
if (s instanceof ImMethodCall) {
@@ -130,72 +131,44 @@ private boolean mayWriteTypeId(ImFunction f, ImVar typeIdVar) {
130131
if (f == null) {
131132
return true;
132133
}
134+
if (f.isNative()) {
135+
return !UselessFunctionCallsRemover.isFunctionWithoutSideEffect(f.getName());
136+
}
137+
if (f.isExtern()) {
138+
return true;
139+
}
133140
IdentityHashMap<ImVar, Boolean> byTypeId = mayWriteTypeIdMemo.computeIfAbsent(f, k -> new IdentityHashMap<>());
134141
Boolean memo = byTypeId.get(typeIdVar);
135142
if (memo != null) {
136143
return memo;
137144
}
138-
boolean result = mayWriteTypeIdImpl(f, typeIdVar, java.util.Collections.newSetFromMap(new IdentityHashMap<>()));
145+
boolean result = mayWriteTypeIdUsingAnalysis(f, typeIdVar);
139146
byTypeId.put(typeIdVar, result);
140147
return result;
141148
}
142149

143-
private boolean isKnownNonMutatingFunction(ImFunction f) {
144-
if (f == null) return false;
145-
String n = f.getName();
146-
return "println".equals(n)
147-
|| "print".equals(n)
148-
|| "I2S".equals(n)
149-
|| "R2S".equals(n)
150-
|| "BJDebugMsg".equals(n);
151-
}
152-
153-
private boolean mayWriteTypeIdImpl(ImFunction f, ImVar typeIdVar, Set<ImFunction> visiting) {
154-
if (f.isNative()) {
155-
return true;
156-
}
157-
if (!visiting.add(f)) {
158-
return true;
159-
}
160-
final boolean[] writes = {false};
161-
f.accept(new ImFunction.DefaultVisitor() {
162-
@Override
163-
public void visit(ImSet e) {
164-
super.visit(e);
165-
ImLExpr left = e.getLeft();
166-
if (left instanceof ImVarArrayAccess && ((ImVarArrayAccess) left).getVar() == typeIdVar) {
167-
writes[0] = true;
168-
} else if (left instanceof ImVarAccess && ((ImVarAccess) left).getVar() == typeIdVar) {
169-
writes[0] = true;
170-
} else if (left instanceof ImMemberAccess && ((ImMemberAccess) left).getVar() == typeIdVar) {
171-
writes[0] = true;
172-
}
150+
private boolean mayWriteTypeIdUsingAnalysis(ImFunction f, ImVar typeIdVar) {
151+
Set<ImFunction> reachable = new HashSet<>();
152+
reachable.add(f);
153+
reachable.addAll(sideEffectAnalyzer.calledFunctions(f.getBody()));
154+
for (ImFunction g : reachable) {
155+
if (g == null) {
156+
return true;
173157
}
174-
175-
@Override
176-
public void visit(ImFunctionCall e) {
177-
super.visit(e);
178-
if (!writes[0] && mayWriteTypeIdImpl(e.getFunc(), typeIdVar, visiting)) {
179-
writes[0] = true;
180-
}
158+
if (g.isExtern()) {
159+
return true;
181160
}
182-
183-
@Override
184-
public void visit(ImMethodCall e) {
185-
super.visit(e);
186-
if (!writes[0] && mayWriteTypeIdImpl(e.getMethod().getImplementation(), typeIdVar, visiting)) {
187-
writes[0] = true;
161+
if (g.isNative()) {
162+
if (!UselessFunctionCallsRemover.isFunctionWithoutSideEffect(g.getName())) {
163+
return true;
188164
}
165+
continue;
189166
}
190-
191-
@Override
192-
public void visit(ImDealloc e) {
193-
super.visit(e);
194-
writes[0] = true;
167+
if (sideEffectAnalyzer.directlySetVariables(g.getBody()).contains(typeIdVar)) {
168+
return true;
195169
}
196-
});
197-
visiting.remove(f);
198-
return writes[0];
170+
}
171+
return false;
199172
}
200173

201174
private GuardPattern extractDispatchGuard(ImStmt stmt) {

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

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -92,31 +92,26 @@ public void repeatedCallsOnSameReceiverAreNotDispatchCachedYet() throws IOExcept
9292
testAssertOkLines(true,
9393
"package test",
9494
" native testSuccess()",
95-
" native println(string s)",
9695
" @extern native I2S(int x) returns string",
97-
" function print(int x)",
98-
" println(I2S(x))",
96+
" @extern native S2I(string x) returns int",
9997
" class A",
10098
" function bar() returns int",
101-
" println(\"helo\")",
10299
" return 1",
103100
"",
104101
" function useA(A a) returns int",
105102
" int r = 0",
106103
" r += a.bar()",
107-
" println(\"helo\")",
104+
" r += S2I(I2S(0))",
108105
" r += a.bar()",
109-
" println(\"helo\")",
106+
" r += S2I(I2S(0))",
110107
" r += a.bar()",
111-
" println(\"helo\")",
112-
" println(I2S(3))",
108+
" r += S2I(I2S(0))",
113109
" return r",
114110
"",
115111
" init",
116112
" let a = new A",
117113
" let ua = useA(a)",
118114
" if ua == 3",
119-
" print(ua)",
120115
" testSuccess()",
121116
"endpackage"
122117
);

0 commit comments

Comments
 (0)