mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Further improvements to inliner
This commit is contained in:
parent
4de1c51e1a
commit
6790d724c7
|
@ -270,9 +270,9 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
|
|||
public void methodReached(DependencyAgent agent, MethodDependency method) {
|
||||
if (method.getReference().equals(CURRENT_THREAD)) {
|
||||
method.use();
|
||||
agent.linkMethod(new MethodReference(Thread.class, "setCurrentThread", Thread.class, void.class))
|
||||
.use();
|
||||
}
|
||||
agent.linkMethod(new MethodReference(Thread.class, "setCurrentThread", Thread.class, void.class))
|
||||
.use();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -319,7 +319,7 @@ public class Renderer implements RenderingManager {
|
|||
thisAliased = true;
|
||||
writer.append("var a").ws().append("=").ws().append("this;").ws();
|
||||
}
|
||||
if (cls.getParentName() != null) {
|
||||
if (!cls.getModifiers().contains(ElementModifier.INTERFACE) && cls.getParentName() != null) {
|
||||
writer.appendClass(cls.getParentName()).append(".call(").append(thisAliased ? "a" : "this")
|
||||
.append(");").softNewLine();
|
||||
}
|
||||
|
|
|
@ -29,36 +29,42 @@ import org.teavm.model.instructions.SwitchTableEntryReader;
|
|||
public class DefaultInliningStrategy implements InliningStrategy {
|
||||
private final int complexityThreshold;
|
||||
private final int depthThreshold;
|
||||
private final int totalComplexityThreshold;
|
||||
private final boolean onceUsedOnly;
|
||||
|
||||
public DefaultInliningStrategy(int complexityThreshold, int depthThreshold, boolean onceUsedOnly) {
|
||||
public DefaultInliningStrategy(int complexityThreshold, int depthThreshold, int totalComplexityThreshold,
|
||||
boolean onceUsedOnly) {
|
||||
this.complexityThreshold = complexityThreshold;
|
||||
this.depthThreshold = depthThreshold;
|
||||
this.totalComplexityThreshold = totalComplexityThreshold;
|
||||
this.onceUsedOnly = onceUsedOnly;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InliningStep start(MethodReference method, ProgramReader program) {
|
||||
int complexity = getComplexity(program);
|
||||
if (complexity > complexityThreshold) {
|
||||
Complexity complexity = getComplexity(program, null);
|
||||
if (complexity.score > complexityThreshold) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ComplexityHolder complexityHolder = new ComplexityHolder();
|
||||
complexityHolder.complexity = complexity;
|
||||
complexityHolder.complexity = complexity.score;
|
||||
return new InliningStepImpl(complexityHolder);
|
||||
}
|
||||
|
||||
static int getComplexity(ProgramReader program) {
|
||||
private static Complexity getComplexity(ProgramReader program, InliningContext context) {
|
||||
int complexity = 0;
|
||||
ComplexityCounter counter = new ComplexityCounter();
|
||||
ComplexityCounter counter = new ComplexityCounter(context);
|
||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||
BasicBlockReader block = program.basicBlockAt(i);
|
||||
counter.complexity = 0;
|
||||
block.readAllInstructions(counter);
|
||||
complexity += block.instructionCount() + counter.complexity;
|
||||
}
|
||||
return complexity;
|
||||
Complexity result = new Complexity();
|
||||
result.score = complexity;
|
||||
result.callsToUsedOnceMethods = counter.callsToUsedOnceMethods;
|
||||
return result;
|
||||
}
|
||||
|
||||
class InliningStepImpl implements InliningStep {
|
||||
|
@ -70,16 +76,23 @@ public class DefaultInliningStrategy implements InliningStrategy {
|
|||
|
||||
@Override
|
||||
public InliningStep tryInline(MethodReference method, ProgramReader program, InliningContext context) {
|
||||
if (context.getDepth() > depthThreshold || (onceUsedOnly && !context.isUsedOnce(method))) {
|
||||
if (context.getDepth() > depthThreshold) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int complexity = getComplexity(program);
|
||||
if (complexityHolder.complexity + complexity > complexityThreshold) {
|
||||
Complexity complexity = getComplexity(program, context);
|
||||
if (onceUsedOnly && !context.isUsedOnce(method)) {
|
||||
if (complexity.callsToUsedOnceMethods || complexity.score > 1) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (complexity.score > complexityThreshold
|
||||
|| complexityHolder.complexity + complexity.score > totalComplexityThreshold) {
|
||||
return null;
|
||||
}
|
||||
|
||||
complexityHolder.complexity += complexity;
|
||||
complexityHolder.complexity += complexity.score;
|
||||
return new InliningStepImpl(complexityHolder);
|
||||
}
|
||||
}
|
||||
|
@ -89,7 +102,13 @@ public class DefaultInliningStrategy implements InliningStrategy {
|
|||
}
|
||||
|
||||
static class ComplexityCounter extends AbstractInstructionReader {
|
||||
InliningContext context;
|
||||
int complexity;
|
||||
boolean callsToUsedOnceMethods;
|
||||
|
||||
ComplexityCounter(InliningContext context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void nop() {
|
||||
|
@ -99,9 +118,8 @@ public class DefaultInliningStrategy implements InliningStrategy {
|
|||
@Override
|
||||
public void invoke(VariableReader receiver, VariableReader instance, MethodReference method,
|
||||
List<? extends VariableReader> arguments, InvocationType type) {
|
||||
complexity++;
|
||||
if (instance != null) {
|
||||
complexity++;
|
||||
if (type == InvocationType.SPECIAL && context != null && context.isUsedOnce(method)) {
|
||||
callsToUsedOnceMethods = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,4 +151,9 @@ public class DefaultInliningStrategy implements InliningStrategy {
|
|||
complexity--;
|
||||
}
|
||||
}
|
||||
|
||||
static class Complexity {
|
||||
int score;
|
||||
boolean callsToUsedOnceMethods;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -129,6 +129,26 @@ public class Inlining {
|
|||
return usageCounter.methodUsageCount.getOrDefault(method, -1) != 0;
|
||||
}
|
||||
|
||||
public void removeUsages(Program program) {
|
||||
for (BasicBlock block : program.getBasicBlocks()) {
|
||||
for (Instruction instruction : block) {
|
||||
if (!(instruction instanceof InvokeInstruction)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
InvokeInstruction invoke = (InvokeInstruction) instruction;
|
||||
if (invoke.getType() != InvocationType.SPECIAL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int usageCount = usageCounter.methodUsageCount.getOrDefault(invoke.getMethod(), -1);
|
||||
if (usageCount > 0) {
|
||||
usageCounter.methodUsageCount.put(invoke.getMethod(), usageCount - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void apply(Program program, MethodReference method) {
|
||||
depthsByBlock = new IntArrayList(program.basicBlockCount());
|
||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||
|
@ -195,7 +215,7 @@ public class Inlining {
|
|||
splitBlock.getTryCatchBlocks().addAll(ProgramUtils.copyTryCatches(block, program));
|
||||
|
||||
invoke.delete();
|
||||
if (invoke.getInstance() == null || invoke.getMethod().getName().equals("<init>")) {
|
||||
if (invoke.getMethod().getName().equals("<init>") || invoke.getInstance() == null) {
|
||||
InitClassInstruction clinit = new InitClassInstruction();
|
||||
clinit.setClassName(invoke.getMethod().getClassName());
|
||||
block.add(clinit);
|
||||
|
@ -211,6 +231,16 @@ public class Inlining {
|
|||
Instruction insn = blockToInline.getFirstInstruction();
|
||||
insn.delete();
|
||||
inlineBlock.add(insn);
|
||||
|
||||
if (insn instanceof InvokeInstruction) {
|
||||
InvokeInstruction invokeInsn = (InvokeInstruction) insn;
|
||||
if (invokeInsn.getType() == InvocationType.SPECIAL) {
|
||||
usageCount = usageCounter.methodUsageCount.getOrDefault(invokeInsn.getMethod(), -1);
|
||||
if (usageCount >= 0) {
|
||||
usageCounter.methodUsageCount.put(invokeInsn.getMethod(), usageCount + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<Phi> phis = new ArrayList<>(blockToInline.getPhis());
|
||||
|
|
|
@ -538,15 +538,15 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
|||
}
|
||||
|
||||
private void inline(ListableClassHolderSource classes) {
|
||||
if (optimizationLevel != TeaVMOptimizationLevel.ADVANCED) {
|
||||
if (optimizationLevel != TeaVMOptimizationLevel.ADVANCED && optimizationLevel != TeaVMOptimizationLevel.FULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
InliningStrategy inliningStrategy;
|
||||
if (optimizationLevel == TeaVMOptimizationLevel.FULL) {
|
||||
inliningStrategy = new DefaultInliningStrategy(17, 7, false);
|
||||
inliningStrategy = new DefaultInliningStrategy(17, 7, 300, false);
|
||||
} else {
|
||||
inliningStrategy = new DefaultInliningStrategy(100, 5, true);
|
||||
inliningStrategy = new DefaultInliningStrategy(100, 7, 300, true);
|
||||
}
|
||||
|
||||
Inlining inlining = new Inlining(new ClassHierarchy(classes), dependencyAnalyzer, inliningStrategy,
|
||||
|
@ -561,6 +561,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
|||
|
||||
if (method.getProgram() != null) {
|
||||
if (!inlining.hasUsages(methodReference)) {
|
||||
inlining.removeUsages(method.getProgram());
|
||||
method.setProgram(null);
|
||||
} else {
|
||||
Program program = method.getProgram();
|
||||
|
|
Loading…
Reference in New Issue
Block a user