mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Improve inlining performance by caching method complexity
This commit is contained in:
parent
d4f98a57d0
commit
e48dfb27b0
|
@ -15,7 +15,9 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.model.optimization;
|
package org.teavm.model.optimization;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import org.teavm.model.BasicBlockReader;
|
import org.teavm.model.BasicBlockReader;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.model.ProgramReader;
|
import org.teavm.model.ProgramReader;
|
||||||
|
@ -32,6 +34,7 @@ public class DefaultInliningStrategy implements InliningStrategy {
|
||||||
private final int totalComplexityThreshold;
|
private final int totalComplexityThreshold;
|
||||||
private final boolean onceUsedOnly;
|
private final boolean onceUsedOnly;
|
||||||
private int getComplexityDepth;
|
private int getComplexityDepth;
|
||||||
|
private Map<MethodReference, Complexity> complexityCache = new HashMap<>();
|
||||||
|
|
||||||
public DefaultInliningStrategy(int complexityThreshold, int depthThreshold, int totalComplexityThreshold,
|
public DefaultInliningStrategy(int complexityThreshold, int depthThreshold, int totalComplexityThreshold,
|
||||||
boolean onceUsedOnly) {
|
boolean onceUsedOnly) {
|
||||||
|
@ -53,6 +56,20 @@ public class DefaultInliningStrategy implements InliningStrategy {
|
||||||
return new InliningStepImpl(complexityHolder);
|
return new InliningStepImpl(complexityHolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void methodChanged(MethodReference method) {
|
||||||
|
complexityCache.remove(method);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Complexity getComplexity(MethodReference methodRef, InliningContext context) {
|
||||||
|
var result = complexityCache.get(methodRef);
|
||||||
|
if (result == null) {
|
||||||
|
result = getComplexity(context.getProgram(methodRef), context);
|
||||||
|
complexityCache.put(methodRef, result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private Complexity getComplexity(ProgramReader program, InliningContext context) {
|
private Complexity getComplexity(ProgramReader program, InliningContext context) {
|
||||||
int complexity = 0;
|
int complexity = 0;
|
||||||
ComplexityCounter counter = new ComplexityCounter(context);
|
ComplexityCounter counter = new ComplexityCounter(context);
|
||||||
|
@ -81,7 +98,7 @@ public class DefaultInliningStrategy implements InliningStrategy {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Complexity complexity = getComplexity(program, context);
|
Complexity complexity = getComplexity(method, context);
|
||||||
if (onceUsedOnly && !context.isUsedOnce(method)) {
|
if (onceUsedOnly && !context.isUsedOnce(method)) {
|
||||||
if (complexity.callsToUsedOnceMethods || complexity.score > 1) {
|
if (complexity.callsToUsedOnceMethods || complexity.score > 1) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -125,19 +142,18 @@ public class DefaultInliningStrategy implements InliningStrategy {
|
||||||
public void invoke(VariableReader receiver, VariableReader instance, MethodReference method,
|
public void invoke(VariableReader receiver, VariableReader instance, MethodReference method,
|
||||||
List<? extends VariableReader> arguments, InvocationType type) {
|
List<? extends VariableReader> arguments, InvocationType type) {
|
||||||
if (type == InvocationType.SPECIAL && context != null && context.isUsedOnce(method)) {
|
if (type == InvocationType.SPECIAL && context != null && context.isUsedOnce(method)) {
|
||||||
ProgramReader program = context.getProgram(method);
|
if (!isTrivialCall(method)) {
|
||||||
if (!isTrivialCall(program)) {
|
|
||||||
callsToUsedOnceMethods = true;
|
callsToUsedOnceMethods = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isTrivialCall(ProgramReader program) {
|
private boolean isTrivialCall(MethodReference methodRef) {
|
||||||
if (program == null || getComplexityDepth > 10) {
|
if (context.getProgram(methodRef) == null || getComplexityDepth > 10) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
getComplexityDepth++;
|
getComplexityDepth++;
|
||||||
Complexity complexity = getComplexity(program, context);
|
Complexity complexity = getComplexity(methodRef, context);
|
||||||
getComplexityDepth--;
|
getComplexityDepth--;
|
||||||
return complexity.score <= 1 && !complexity.callsToUsedOnceMethods;
|
return complexity.score <= 1 && !complexity.callsToUsedOnceMethods;
|
||||||
}
|
}
|
||||||
|
|
|
@ -175,6 +175,7 @@ public class Inlining {
|
||||||
instructionsToSkip = null;
|
instructionsToSkip = null;
|
||||||
|
|
||||||
new UnreachableBasicBlockEliminator().optimize(program);
|
new UnreachableBasicBlockEliminator().optimize(program);
|
||||||
|
strategy.methodChanged(method);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean applyOnce(Program program, MethodReference method) {
|
private boolean applyOnce(Program program, MethodReference method) {
|
||||||
|
|
|
@ -20,4 +20,7 @@ import org.teavm.model.ProgramReader;
|
||||||
|
|
||||||
public interface InliningStrategy {
|
public interface InliningStrategy {
|
||||||
InliningStep start(MethodReference method, ProgramReader program);
|
InliningStep start(MethodReference method, ProgramReader program);
|
||||||
|
|
||||||
|
default void methodChanged(MethodReference method) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user