• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

wurstscript / WurstScript / 203

18 Oct 2023 02:20PM UTC coverage: 63.758% (+0.3%) from 63.447%
203

push

circleci

web-flow
Update deps, improve performance, JHCR fixes (#1080)

- update dependencies
- update stdlib verison for unit tests
- only apply nullsetting when `-opt` is enabled to save some build time for testing
- minor performance improvements
- make build deterministic
- apply build map config before compilation
- hot code reload now more reliable

17246 of 27049 relevant lines covered (63.76%)

0.64 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.37
de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/translation/imoptimizer/ImOptimizer.java
1
package de.peeeq.wurstscript.translation.imoptimizer;
2

3
import com.google.common.collect.Lists;
4
import de.peeeq.wurstio.TimeTaker;
5
import de.peeeq.wurstscript.WLogger;
6
import de.peeeq.wurstscript.intermediatelang.optimizer.*;
7
import de.peeeq.wurstscript.jassIm.*;
8
import de.peeeq.wurstscript.translation.imtranslation.ImHelper;
9
import de.peeeq.wurstscript.translation.imtranslation.ImTranslator;
10
import de.peeeq.wurstscript.types.TypesHelper;
11
import de.peeeq.wurstscript.utils.Pair;
12
import de.peeeq.wurstscript.validation.TRVEHelper;
13

14
import java.util.*;
15

16
public class ImOptimizer {
17
    private int totalFunctionsRemoved = 0;
1✔
18
    private int totalGlobalsRemoved = 0;
1✔
19

20
    private static final ArrayList<OptimizerPass> localPasses = new ArrayList<>();
1✔
21
    private static final HashMap<String, Integer> totalCount = new HashMap<>();
1✔
22

23
    static {
24
        localPasses.add(new SimpleRewrites());
1✔
25
        localPasses.add(new ConstantAndCopyPropagation());
1✔
26
        localPasses.add(new UselessFunctionCallsRemover());
1✔
27
        localPasses.add(new GlobalsInliner());
1✔
28
        localPasses.add(new BranchMerger());
1✔
29
        localPasses.add(new SimpleRewrites());
1✔
30
        localPasses.add(new TempMerger());
1✔
31
        localPasses.add(new LocalMerger());
1✔
32
    }
1✔
33

34

35
    private final TimeTaker timeTaker;
36
    ImTranslator trans;
37

38
    public ImOptimizer(TimeTaker timeTaker, ImTranslator trans) {
1✔
39
        this.timeTaker = timeTaker;
1✔
40
        this.trans = trans;
1✔
41
    }
1✔
42

43
    public void optimize() {
44
        removeGarbage();
×
45
        ImCompressor compressor = new ImCompressor(trans);
×
46
        compressor.compressNames();
×
47
    }
×
48

49
    public void doInlining() {
50
        // remove garbage to reduce work for the inliner
51
        removeGarbage();
1✔
52
        GlobalsInliner globalsInliner = new GlobalsInliner();
1✔
53
        globalsInliner.optimize(trans);
1✔
54
        ImInliner inliner = new ImInliner(trans);
1✔
55
        inliner.doInlining();
1✔
56
        trans.assertProperties();
1✔
57
        // remove garbage, because inlined functions can be removed
58
        removeGarbage();
1✔
59
    }
1✔
60

61
    private int optCount = 1;
1✔
62

63
    public void localOptimizations() {
64
        totalCount.clear();
1✔
65
        removeGarbage();
1✔
66

67
        int finalItr = 0;
1✔
68
        for (int i = 1; i <= 10 && optCount > 0; i++) {
1✔
69
            optCount = 0;
1✔
70
            localPasses.forEach(pass -> {
1✔
71
                int count = timeTaker.measure(pass.getName(), () -> pass.optimize(trans));
1✔
72
                optCount += count;
1✔
73
                totalCount.put(pass.getName(), totalCount.getOrDefault(pass.getName(), 0) + count);
1✔
74
            });
1✔
75
            trans.getImProg().flatten(trans);
1✔
76
            removeGarbage();
1✔
77
            finalItr = i;
1✔
78
            WLogger.info("=== Optimization pass: " + i + " opts: " + optCount + " ===");
1✔
79
        }
80
        WLogger.info("=== Local optimizations done! Ran " + finalItr + " passes. ===");
1✔
81
        totalCount.forEach((k, v) -> WLogger.info("== " + k + ":   " + v));
1✔
82
    }
1✔
83

84
    public void doNullsetting() {
85
        NullSetter ns = new NullSetter(trans);
×
86
        ns.optimize();
×
87
        trans.assertProperties();
×
88
    }
×
89

90
    public void removeGarbage() {
91
        boolean changes = true;
1✔
92
        int iterations = 0;
1✔
93
        while (changes && iterations++ < 10) {
1✔
94
            ImProg prog = trans.imProg();
1✔
95
            trans.calculateCallRelationsAndUsedVariables();
1✔
96

97
            // keep only used variables
98
            int globalsBefore = prog.getGlobals().size();
1✔
99
            changes = prog.getGlobals().retainAll(trans.getReadVariables());
1✔
100
            int globalsAfter = prog.getGlobals().size();
1✔
101
            int globalsRemoved = globalsBefore - globalsAfter;
1✔
102
            totalGlobalsRemoved += globalsRemoved;
1✔
103
            // keep only functions reachable from main and config
104
            int functionsBefore = prog.getFunctions().size();
1✔
105
            changes |= prog.getFunctions().retainAll(trans.getUsedFunctions());
1✔
106
            int functionsAfter = prog.getFunctions().size();
1✔
107
            int functionsRemoved = functionsBefore - functionsAfter;
1✔
108
            totalFunctionsRemoved += functionsRemoved;
1✔
109
            // also consider class functions
110
            Set<ImFunction> allFunctions = new HashSet<>(prog.getFunctions());
1✔
111
            for (ImClass c : prog.getClasses()) {
1✔
112
                int classFunctionsBefore = c.getFunctions().size();
1✔
113
                changes |= c.getFunctions().retainAll(trans.getUsedFunctions());
1✔
114
                int classFunctionsAfter = c.getFunctions().size();
1✔
115
                totalFunctionsRemoved += classFunctionsBefore - classFunctionsAfter;
1✔
116
                allFunctions.addAll(c.getFunctions());
1✔
117

118
                int classFieldsBefore = c.getFields().size();
1✔
119
                changes |= c.getFields().retainAll(trans.getReadVariables());
1✔
120
                int classFieldsAfter = c.getFields().size();
1✔
121
                totalGlobalsRemoved += classFieldsBefore - classFieldsAfter;
1✔
122
            }
1✔
123
            for (ImFunction f : allFunctions) {
1✔
124
                // remove set statements to unread variables
125
                final List<Pair<ImStmt, List<ImExpr>>> replacements = Lists.newArrayList();
1✔
126
                f.accept(new ImFunction.DefaultVisitor() {
1✔
127
                    @Override
128
                    public void visit(ImSet e) {
129
                        super.visit(e);
1✔
130
                        if (e.getLeft() instanceof ImVarAccess) {
1✔
131
                            ImVarAccess va = (ImVarAccess) e.getLeft();
1✔
132
                            if (!trans.getReadVariables().contains(va.getVar()) && !TRVEHelper.protectedVariables.contains(va.getVar().getName())) {
1✔
133
                                replacements.add(Pair.create(e, Collections.singletonList(e.getRight())));
1✔
134
                            }
135
                        } else if (e.getLeft() instanceof ImVarArrayAccess) {
1✔
136
                            ImVarArrayAccess va = (ImVarArrayAccess) e.getLeft();
1✔
137
                            if (!trans.getReadVariables().contains(va.getVar()) && !TRVEHelper.protectedVariables.contains(va.getVar().getName())) {
1✔
138
                                // TODO indexes might have side effects that we need to keep
139
                                List<ImExpr> exprs = va.getIndexes().removeAll();
1✔
140
                                exprs.add(e.getRight());
1✔
141
                                replacements.add(Pair.create(e, exprs));
1✔
142
                            }
143
                        } else if (e.getLeft() instanceof ImTupleSelection) {
1✔
144
                            ImVar var = TypesHelper.getTupleVar((ImTupleSelection) e.getLeft());
1✔
145
                            if(!trans.getReadVariables().contains(var) && !TRVEHelper.protectedVariables.contains(var.getName())) {
1✔
146
                                replacements.add(Pair.create(e, Collections.singletonList(e.getRight())));
×
147
                            }
148
                        } else if(e.getLeft() instanceof ImMemberAccess) {
1✔
149
                            ImMemberAccess va = ((ImMemberAccess) e.getLeft());
1✔
150
                            if (!trans.getReadVariables().contains(va.getVar()) && !TRVEHelper.protectedVariables.contains(va.getVar().getName())) {
1✔
151
                                replacements.add(Pair.create(e, Collections.singletonList(e.getRight())));
1✔
152
                            }
153
                        }
154
                    }
1✔
155

156
                });
157
                Replacer replacer = new Replacer();
1✔
158
                for (Pair<ImStmt, List<ImExpr>> pair : replacements) {
1✔
159
                    changes = true;
1✔
160
                    ImExpr r;
161
                    if (pair.getB().size() == 1) {
1✔
162
                        r = pair.getB().get(0);
1✔
163
                        r.setParent(null);
1✔
164
                    } else {
165
                        List<ImStmt> exprs = Collections.unmodifiableList(pair.getB());
1✔
166
                        for (ImStmt expr : exprs) {
1✔
167
                            expr.setParent(null);
1✔
168
                        }
1✔
169
                        r = ImHelper.statementExprVoid(JassIm.ImStmts(exprs));
1✔
170
                    }
171
                    replacer.replace(pair.getA(), r);
1✔
172
                }
1✔
173

174
                // keep only read local variables
175
                changes |= f.getLocals().retainAll(trans.getReadVariables());
1✔
176
            }
1✔
177
        }
1✔
178
    }
1✔
179

180

181
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc