diff --git a/core/src/main/java/org/teavm/model/PreOptimizingClassHolderSource.java b/core/src/main/java/org/teavm/model/PreOptimizingClassHolderSource.java index d78821109..9b7fb15a8 100644 --- a/core/src/main/java/org/teavm/model/PreOptimizingClassHolderSource.java +++ b/core/src/main/java/org/teavm/model/PreOptimizingClassHolderSource.java @@ -37,7 +37,7 @@ public class PreOptimizingClassHolderSource implements ClassHolderSource { return null; } for (MethodHolder method : cls.getMethods()) { - new GlobalValueNumbering(true).optimize(method, method.getProgram()); + new GlobalValueNumbering(true).optimize(method.getProgram()); new UnusedVariableElimination().optimize(method, method.getProgram()); } cache.put(name, cls); diff --git a/core/src/main/java/org/teavm/model/optimization/ArrayUnwrapMotion.java b/core/src/main/java/org/teavm/model/optimization/ArrayUnwrapMotion.java index 974c32fc5..9ec4f8bfc 100644 --- a/core/src/main/java/org/teavm/model/optimization/ArrayUnwrapMotion.java +++ b/core/src/main/java/org/teavm/model/optimization/ArrayUnwrapMotion.java @@ -24,7 +24,7 @@ import org.teavm.model.util.DefinitionExtractor; public class ArrayUnwrapMotion implements MethodOptimization { @Override - public boolean optimize(MethodReader method, Program program) { + public boolean optimize(MethodOptimizationContext context, Program program) { for (int i = 0; i < program.basicBlockCount(); ++i) { optimize(program.basicBlockAt(i)); } diff --git a/core/src/main/java/org/teavm/model/optimization/ClassInitElimination.java b/core/src/main/java/org/teavm/model/optimization/ClassInitElimination.java index 5ac8c0bbc..9e93d885a 100644 --- a/core/src/main/java/org/teavm/model/optimization/ClassInitElimination.java +++ b/core/src/main/java/org/teavm/model/optimization/ClassInitElimination.java @@ -25,7 +25,6 @@ import org.teavm.common.Graph; import org.teavm.common.GraphUtils; import org.teavm.model.BasicBlock; import org.teavm.model.Instruction; -import org.teavm.model.MethodReader; import org.teavm.model.Program; import org.teavm.model.instructions.EmptyInstruction; import org.teavm.model.instructions.InitClassInstruction; @@ -34,13 +33,13 @@ import org.teavm.model.util.ProgramUtils; public class ClassInitElimination implements MethodOptimization { @Override - public boolean optimize(MethodReader method, Program program) { + public boolean optimize(MethodOptimizationContext context, Program program) { Graph cfg = ProgramUtils.buildControlFlowGraph(program); DominatorTree dom = GraphUtils.buildDominatorTree(cfg); Graph domGraph = GraphUtils.buildDominatorGraph(dom, program.basicBlockCount()); Step start = new Step(0); - start.initializedClasses.add(method.getOwnerName()); + start.initializedClasses.add(context.getMethod().getOwnerName()); Deque stack = new ArrayDeque<>(); stack.push(start); diff --git a/core/src/main/java/org/teavm/model/optimization/ConstantConditionElimination.java b/core/src/main/java/org/teavm/model/optimization/ConstantConditionElimination.java index 3aaa7c9f6..fb9303fba 100644 --- a/core/src/main/java/org/teavm/model/optimization/ConstantConditionElimination.java +++ b/core/src/main/java/org/teavm/model/optimization/ConstantConditionElimination.java @@ -17,7 +17,6 @@ package org.teavm.model.optimization; import org.teavm.model.BasicBlock; import org.teavm.model.Instruction; -import org.teavm.model.MethodReader; import org.teavm.model.Program; import org.teavm.model.instructions.BinaryBranchingCondition; import org.teavm.model.instructions.BinaryBranchingInstruction; @@ -33,7 +32,7 @@ public class ConstantConditionElimination implements MethodOptimization { private boolean[] nullConstants; @Override - public boolean optimize(MethodReader method, Program program) { + public boolean optimize(MethodOptimizationContext context, Program program) { constants = new int[program.variableCount()]; constantDefined = new boolean[program.variableCount()]; nullConstants = new boolean[program.variableCount()]; diff --git a/core/src/main/java/org/teavm/model/optimization/EmptyBlockElimination.java b/core/src/main/java/org/teavm/model/optimization/EmptyBlockElimination.java index 81901005d..fd034cb6d 100644 --- a/core/src/main/java/org/teavm/model/optimization/EmptyBlockElimination.java +++ b/core/src/main/java/org/teavm/model/optimization/EmptyBlockElimination.java @@ -16,14 +16,13 @@ package org.teavm.model.optimization; import org.teavm.model.BasicBlock; -import org.teavm.model.MethodReader; import org.teavm.model.Program; import org.teavm.model.instructions.JumpInstruction; import org.teavm.model.util.BasicBlockMapper; public class EmptyBlockElimination implements MethodOptimization { @Override - public boolean optimize(MethodReader method, final Program program) { + public boolean optimize(MethodOptimizationContext context, final Program program) { boolean affected = true; final int[] blockMapping = new int[program.basicBlockCount()]; for (int i = 0; i < blockMapping.length; ++i) { diff --git a/core/src/main/java/org/teavm/model/optimization/GlobalValueNumbering.java b/core/src/main/java/org/teavm/model/optimization/GlobalValueNumbering.java index 186ccd4aa..2a4da1ef8 100644 --- a/core/src/main/java/org/teavm/model/optimization/GlobalValueNumbering.java +++ b/core/src/main/java/org/teavm/model/optimization/GlobalValueNumbering.java @@ -46,7 +46,11 @@ public class GlobalValueNumbering implements MethodOptimization { } @Override - public boolean optimize(MethodReader method, Program program) { + public boolean optimize(MethodOptimizationContext context, Program program) { + return optimize(program); + } + + public boolean optimize(Program program) { boolean affected = false; this.program = program; knownValues.clear(); diff --git a/core/src/main/java/org/teavm/model/optimization/LoopInvariantMotion.java b/core/src/main/java/org/teavm/model/optimization/LoopInvariantMotion.java index 585bba2bf..ef2465a51 100644 --- a/core/src/main/java/org/teavm/model/optimization/LoopInvariantMotion.java +++ b/core/src/main/java/org/teavm/model/optimization/LoopInvariantMotion.java @@ -30,7 +30,7 @@ public class LoopInvariantMotion implements MethodOptimization { private Program program; @Override - public boolean optimize(MethodReader method, Program program) { + public boolean optimize(MethodOptimizationContext context, Program program) { boolean affected = false; this.program = program; graph = new LoopGraph(ProgramUtils.buildControlFlowGraph(program)); @@ -42,7 +42,7 @@ public class LoopInvariantMotion implements MethodOptimization { int[] defLocation = new int[program.variableCount()]; Arrays.fill(defLocation, -1); Instruction[] constantInstructions = new Instruction[program.variableCount()]; - for (int i = 0; i <= method.parameterCount(); ++i) { + for (int i = 0; i <= context.getMethod().parameterCount(); ++i) { defLocation[i] = 0; } for (int i = 0; i < domGraph.size(); ++i) { diff --git a/core/src/main/java/org/teavm/model/optimization/LoopInversion.java b/core/src/main/java/org/teavm/model/optimization/LoopInversion.java index 257030687..ab0d51119 100644 --- a/core/src/main/java/org/teavm/model/optimization/LoopInversion.java +++ b/core/src/main/java/org/teavm/model/optimization/LoopInversion.java @@ -20,7 +20,8 @@ import org.teavm.model.Program; public class LoopInversion implements MethodOptimization { @Override - public boolean optimize(MethodReader method, Program program) { + public boolean optimize(MethodOptimizationContext context, Program program) { + MethodReader method = context.getMethod(); return new LoopInversionImpl(method, program, method.parameterCount() + 1).apply(); } } diff --git a/core/src/main/java/org/teavm/model/optimization/LoopInversionImpl.java b/core/src/main/java/org/teavm/model/optimization/LoopInversionImpl.java index 09ca0d81b..d3404c6f9 100644 --- a/core/src/main/java/org/teavm/model/optimization/LoopInversionImpl.java +++ b/core/src/main/java/org/teavm/model/optimization/LoopInversionImpl.java @@ -152,10 +152,10 @@ class LoopInversionImpl { } private LoopWithExits getLoopWithExits(Map cache, Loop loop) { - return cache.computeIfAbsent(loop, k -> - new LoopWithExits(loop.getHead(), loop.getParent() != null - ? getLoopWithExits(cache, loop.getParent()) - : null)); + return cache.computeIfAbsent(loop, k -> { + LoopWithExits parent = loop.getParent() != null ? getLoopWithExits(cache, loop.getParent()) : null; + return new LoopWithExits(loop.getHead(), parent); + }); } private void sortLoops(LoopWithExits loop, Set visited, List target) { diff --git a/core/src/main/java/org/teavm/model/optimization/MethodOptimization.java b/core/src/main/java/org/teavm/model/optimization/MethodOptimization.java index 4ffffa9a9..d834735e7 100644 --- a/core/src/main/java/org/teavm/model/optimization/MethodOptimization.java +++ b/core/src/main/java/org/teavm/model/optimization/MethodOptimization.java @@ -15,9 +15,8 @@ */ package org.teavm.model.optimization; -import org.teavm.model.MethodReader; import org.teavm.model.Program; public interface MethodOptimization { - boolean optimize(MethodReader method, Program program); + boolean optimize(MethodOptimizationContext context, Program program); } diff --git a/core/src/main/java/org/teavm/model/optimization/MethodOptimizationContext.java b/core/src/main/java/org/teavm/model/optimization/MethodOptimizationContext.java new file mode 100644 index 000000000..0151f6e2c --- /dev/null +++ b/core/src/main/java/org/teavm/model/optimization/MethodOptimizationContext.java @@ -0,0 +1,28 @@ +/* + * Copyright 2016 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.model.optimization; + +import org.teavm.dependency.DependencyInfo; +import org.teavm.model.ClassReaderSource; +import org.teavm.model.MethodReader; + +public interface MethodOptimizationContext { + MethodReader getMethod(); + + DependencyInfo getDependencyInfo(); + + ClassReaderSource getClassSource(); +} diff --git a/core/src/main/java/org/teavm/model/optimization/RedundantJumpElimination.java b/core/src/main/java/org/teavm/model/optimization/RedundantJumpElimination.java index f7758e740..b42f56ea3 100644 --- a/core/src/main/java/org/teavm/model/optimization/RedundantJumpElimination.java +++ b/core/src/main/java/org/teavm/model/optimization/RedundantJumpElimination.java @@ -22,7 +22,6 @@ import org.teavm.common.Graph; import org.teavm.model.BasicBlock; import org.teavm.model.Incoming; import org.teavm.model.Instruction; -import org.teavm.model.MethodReader; import org.teavm.model.Phi; import org.teavm.model.Program; import org.teavm.model.TryCatchBlock; @@ -33,7 +32,7 @@ import org.teavm.model.util.ProgramUtils; public class RedundantJumpElimination implements MethodOptimization { @Override - public boolean optimize(MethodReader method, Program program) { + public boolean optimize(MethodOptimizationContext context, Program program) { Graph cfg = ProgramUtils.buildControlFlowGraph(program); int[] incomingCount = new int[cfg.size()]; Arrays.setAll(incomingCount, cfg::incomingEdgesCount); diff --git a/core/src/main/java/org/teavm/model/optimization/UnreachableBasicBlockElimination.java b/core/src/main/java/org/teavm/model/optimization/UnreachableBasicBlockElimination.java index 6df87b910..d07711b68 100644 --- a/core/src/main/java/org/teavm/model/optimization/UnreachableBasicBlockElimination.java +++ b/core/src/main/java/org/teavm/model/optimization/UnreachableBasicBlockElimination.java @@ -15,12 +15,11 @@ */ package org.teavm.model.optimization; -import org.teavm.model.MethodReader; import org.teavm.model.Program; public class UnreachableBasicBlockElimination implements MethodOptimization { @Override - public boolean optimize(MethodReader method, Program program) { + public boolean optimize(MethodOptimizationContext context, Program program) { new UnreachableBasicBlockEliminator().optimize(program); return false; } diff --git a/core/src/main/java/org/teavm/model/optimization/UnusedVariableElimination.java b/core/src/main/java/org/teavm/model/optimization/UnusedVariableElimination.java index d3b54def2..0f6f6e228 100644 --- a/core/src/main/java/org/teavm/model/optimization/UnusedVariableElimination.java +++ b/core/src/main/java/org/teavm/model/optimization/UnusedVariableElimination.java @@ -21,6 +21,10 @@ import org.teavm.model.instructions.*; public class UnusedVariableElimination implements MethodOptimization { @Override + public boolean optimize(MethodOptimizationContext context, Program program) { + return optimize(context.getMethod(), program); + } + public boolean optimize(MethodReader method, Program program) { if (method.getProgram() == null) { return false; diff --git a/core/src/main/java/org/teavm/vm/TeaVM.java b/core/src/main/java/org/teavm/vm/TeaVM.java index 71ccf7f87..8a8f75a6d 100644 --- a/core/src/main/java/org/teavm/vm/TeaVM.java +++ b/core/src/main/java/org/teavm/vm/TeaVM.java @@ -45,6 +45,7 @@ import org.teavm.model.ClassReaderSource; import org.teavm.model.ListableClassHolderSource; import org.teavm.model.ListableClassReaderSource; import org.teavm.model.MethodHolder; +import org.teavm.model.MethodReader; import org.teavm.model.MethodReference; import org.teavm.model.MutableClassHolderSource; import org.teavm.model.Program; @@ -58,6 +59,7 @@ import org.teavm.model.optimization.Inlining; import org.teavm.model.optimization.LoopInvariantMotion; import org.teavm.model.optimization.LoopInversion; import org.teavm.model.optimization.MethodOptimization; +import org.teavm.model.optimization.MethodOptimizationContext; import org.teavm.model.optimization.RedundantJumpElimination; import org.teavm.model.optimization.UnreachableBasicBlockElimination; import org.teavm.model.optimization.UnusedVariableElimination; @@ -443,8 +445,9 @@ public class TeaVM implements TeaVMHost, ServiceRepository { ClassHolder cls = classes.get(className); for (MethodHolder method : cls.getMethods()) { if (method.getProgram() != null) { + MethodOptimizationContextImpl context = new MethodOptimizationContextImpl(method, classes); inlining.apply(method.getProgram(), classes); - new UnusedVariableElimination().optimize(method, method.getProgram()); + new UnusedVariableElimination().optimize(context, method.getProgram()); } } if (wasCancelled()) { @@ -473,6 +476,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository { boolean noCache = method.getAnnotations().get(NoCache.class.getName()) != null; Program optimizedProgram = incremental && !noCache && programCache != null ? programCache.get(method.getReference()) : null; + MethodOptimizationContextImpl context = new MethodOptimizationContextImpl(method, classSource); if (optimizedProgram == null) { optimizedProgram = ProgramUtils.copy(method.getProgram()); if (optimizedProgram.basicBlockCount() > 0) { @@ -481,7 +485,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository { changed = false; for (MethodOptimization optimization : getOptimizations()) { try { - changed |= optimization.optimize(method, optimizedProgram); + changed |= optimization.optimize(context, optimizedProgram); } catch (Exception | AssertionError e) { ListingBuilder listingBuilder = new ListingBuilder(); String listing = listingBuilder.buildListing(optimizedProgram, ""); @@ -505,6 +509,31 @@ public class TeaVM implements TeaVMHost, ServiceRepository { method.setProgram(optimizedProgram); } + private class MethodOptimizationContextImpl implements MethodOptimizationContext { + private MethodReader method; + private ClassReaderSource classSource; + + public MethodOptimizationContextImpl(MethodReader method, ClassReaderSource classSource) { + this.method = method; + this.classSource = classSource; + } + + @Override + public MethodReader getMethod() { + return method; + } + + @Override + public DependencyInfo getDependencyInfo() { + return dependencyChecker; + } + + @Override + public ClassReaderSource getClassSource() { + return classSource; + } + } + private List getOptimizations() { List optimizations = new ArrayList<>(); optimizations.add(new RedundantJumpElimination());