mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-23 00:24:11 -08:00
Add escape analysis
This commit is contained in:
parent
6781dd0abb
commit
e4fab2be41
|
@ -22,10 +22,6 @@ import java.util.Arrays;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class GraphBuilder {
|
||||
private GraphImpl builtGraph;
|
||||
private List<IntSet> addedEdges = new ArrayList<>();
|
||||
|
|
367
core/src/main/java/org/teavm/model/analysis/EscapeAnalysis.java
Normal file
367
core/src/main/java/org/teavm/model/analysis/EscapeAnalysis.java
Normal file
|
@ -0,0 +1,367 @@
|
|||
/*
|
||||
* Copyright 2017 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.analysis;
|
||||
|
||||
import com.carrotsearch.hppc.IntArrayDeque;
|
||||
import com.carrotsearch.hppc.IntDeque;
|
||||
import com.carrotsearch.hppc.IntOpenHashSet;
|
||||
import com.carrotsearch.hppc.IntSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.BitSet;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import org.teavm.common.DisjointSet;
|
||||
import org.teavm.common.Graph;
|
||||
import org.teavm.common.GraphBuilder;
|
||||
import org.teavm.model.BasicBlock;
|
||||
import org.teavm.model.ClassReader;
|
||||
import org.teavm.model.ClassReaderSource;
|
||||
import org.teavm.model.FieldReader;
|
||||
import org.teavm.model.FieldReference;
|
||||
import org.teavm.model.Incoming;
|
||||
import org.teavm.model.Instruction;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.Phi;
|
||||
import org.teavm.model.Program;
|
||||
import org.teavm.model.TryCatchBlock;
|
||||
import org.teavm.model.Variable;
|
||||
import org.teavm.model.instructions.AbstractInstructionVisitor;
|
||||
import org.teavm.model.instructions.AssignInstruction;
|
||||
import org.teavm.model.instructions.BinaryBranchingInstruction;
|
||||
import org.teavm.model.instructions.BranchingInstruction;
|
||||
import org.teavm.model.instructions.CastInstruction;
|
||||
import org.teavm.model.instructions.ClassConstantInstruction;
|
||||
import org.teavm.model.instructions.CloneArrayInstruction;
|
||||
import org.teavm.model.instructions.ConstructInstruction;
|
||||
import org.teavm.model.instructions.ExitInstruction;
|
||||
import org.teavm.model.instructions.GetElementInstruction;
|
||||
import org.teavm.model.instructions.GetFieldInstruction;
|
||||
import org.teavm.model.instructions.InvokeInstruction;
|
||||
import org.teavm.model.instructions.IsInstanceInstruction;
|
||||
import org.teavm.model.instructions.MonitorEnterInstruction;
|
||||
import org.teavm.model.instructions.MonitorExitInstruction;
|
||||
import org.teavm.model.instructions.NullCheckInstruction;
|
||||
import org.teavm.model.instructions.NullConstantInstruction;
|
||||
import org.teavm.model.instructions.PutElementInstruction;
|
||||
import org.teavm.model.instructions.PutFieldInstruction;
|
||||
import org.teavm.model.instructions.RaiseInstruction;
|
||||
import org.teavm.model.instructions.StringConstantInstruction;
|
||||
import org.teavm.model.instructions.UnwrapArrayInstruction;
|
||||
import org.teavm.model.util.InstructionTransitionExtractor;
|
||||
import org.teavm.model.util.LivenessAnalyzer;
|
||||
import org.teavm.model.util.UsageExtractor;
|
||||
|
||||
public class EscapeAnalysis {
|
||||
private ClassReaderSource classSource;
|
||||
private int[] definitionClasses;
|
||||
private boolean[] escapingVars;
|
||||
private FieldReference[][] fields;
|
||||
|
||||
public EscapeAnalysis(ClassReaderSource classSource) {
|
||||
this.classSource = classSource;
|
||||
}
|
||||
|
||||
public void analyze(Program program, MethodReference methodReference) {
|
||||
InstructionEscapeVisitor visitor = new InstructionEscapeVisitor(program.variableCount(), classSource);
|
||||
for (int i = 0; i <= methodReference.parameterCount(); ++i) {
|
||||
visitor.escapingVars[i] = true;
|
||||
}
|
||||
|
||||
for (BasicBlock block : program.getBasicBlocks()) {
|
||||
for (Instruction insn : block) {
|
||||
insn.acceptVisitor(visitor);
|
||||
}
|
||||
if (block.getExceptionVariable() != null) {
|
||||
visitor.escapingVars[block.getExceptionVariable().getIndex()] = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
definitionClasses = visitor.definitionClasses.pack(program.variableCount());
|
||||
escapingVars = new boolean[program.variableCount()];
|
||||
for (int i = 0; i < program.variableCount(); ++i) {
|
||||
if (visitor.escapingVars[i]) {
|
||||
escapingVars[definitionClasses[i]] = true;
|
||||
}
|
||||
}
|
||||
analyzePhis(program);
|
||||
|
||||
fields = packFields(visitor.fields);
|
||||
}
|
||||
|
||||
public boolean escapes(int var) {
|
||||
return escapingVars[definitionClasses[var]];
|
||||
}
|
||||
|
||||
public FieldReference[] getFields(int var) {
|
||||
FieldReference[] varFields = fields[definitionClasses[var]];
|
||||
return varFields != null ? varFields.clone() : null;
|
||||
}
|
||||
|
||||
private void analyzePhis(Program program) {
|
||||
LivenessAnalyzer livenessAnalyzer = new LivenessAnalyzer();
|
||||
livenessAnalyzer.analyze(program);
|
||||
|
||||
GraphBuilder graphBuilder = new GraphBuilder(program.variableCount());
|
||||
IntDeque queue = new IntArrayDeque();
|
||||
for (BasicBlock block : program.getBasicBlocks()) {
|
||||
IntSet sharedIncomingVars = new IntOpenHashSet();
|
||||
BitSet usedVars = getUsedVarsInBlock(livenessAnalyzer, block);
|
||||
for (Phi phi : block.getPhis()) {
|
||||
for (Incoming incoming : phi.getIncomings()) {
|
||||
int var = incoming.getValue().getIndex();
|
||||
graphBuilder.addEdge(var, phi.getReceiver().getIndex());
|
||||
if (escapingVars[definitionClasses[var]] || !sharedIncomingVars.add(var) || usedVars.get(var)) {
|
||||
queue.addLast(var);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Graph graph = graphBuilder.build();
|
||||
|
||||
IntSet visited = new IntOpenHashSet();
|
||||
while (!queue.isEmpty()) {
|
||||
int var = queue.removeFirst();
|
||||
if (visited.add(var)) {
|
||||
escapingVars[definitionClasses[var]] = true;
|
||||
for (int successor : graph.outgoingEdges(var)) {
|
||||
queue.addLast(successor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private BitSet getUsedVarsInBlock(LivenessAnalyzer liveness, BasicBlock block) {
|
||||
BitSet usedVars = new BitSet();
|
||||
InstructionTransitionExtractor transitionExtractor = new InstructionTransitionExtractor();
|
||||
block.getLastInstruction().acceptVisitor(transitionExtractor);
|
||||
for (BasicBlock successor : transitionExtractor.getTargets()) {
|
||||
usedVars.or(liveness.liveIn(successor.getIndex()));
|
||||
}
|
||||
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
|
||||
usedVars.or(liveness.liveIn(tryCatch.getHandler().getIndex()));
|
||||
}
|
||||
|
||||
UsageExtractor useExtractor = new UsageExtractor();
|
||||
for (Instruction instruction : block) {
|
||||
instruction.acceptVisitor(useExtractor);
|
||||
for (Variable variable : useExtractor.getUsedVariables()) {
|
||||
usedVars.set(variable.getIndex());
|
||||
}
|
||||
}
|
||||
return usedVars;
|
||||
}
|
||||
|
||||
private FieldReference[][] packFields(List<Set<FieldReference>> fields) {
|
||||
List<Set<FieldReference>> joinedFields = new ArrayList<>(Collections.nCopies(fields.size(), null));
|
||||
|
||||
for (int i = 0; i < fields.size(); ++i) {
|
||||
if (fields.get(i) == null) {
|
||||
continue;
|
||||
}
|
||||
int j = definitionClasses[i];
|
||||
Set<FieldReference> fieldSet = joinedFields.get(j);
|
||||
if (fieldSet == null) {
|
||||
fieldSet = new LinkedHashSet<>();
|
||||
joinedFields.set(j, fieldSet);
|
||||
}
|
||||
fieldSet.addAll(fields.get(i));
|
||||
}
|
||||
|
||||
FieldReference[][] packedFields = new FieldReference[fields.size()][];
|
||||
for (int i = 0; i < packedFields.length; ++i) {
|
||||
if (joinedFields.get(i) != null) {
|
||||
packedFields[i] = joinedFields.get(i).toArray(new FieldReference[0]);
|
||||
}
|
||||
}
|
||||
return packedFields;
|
||||
}
|
||||
|
||||
private static class InstructionEscapeVisitor extends AbstractInstructionVisitor {
|
||||
ClassReaderSource classSource;
|
||||
DisjointSet definitionClasses;
|
||||
boolean[] escapingVars;
|
||||
List<Set<FieldReference>> fields;
|
||||
|
||||
public InstructionEscapeVisitor(int variableCount, ClassReaderSource classSource) {
|
||||
this.classSource = classSource;
|
||||
fields = new ArrayList<>(Collections.nCopies(variableCount, null));
|
||||
definitionClasses = new DisjointSet();
|
||||
for (int i = 0; i < variableCount; ++i) {
|
||||
definitionClasses.create();
|
||||
}
|
||||
escapingVars = new boolean[variableCount];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ConstructInstruction insn) {
|
||||
ClassReader cls = classSource.get(insn.getType());
|
||||
if (cls == null) {
|
||||
escapingVars[insn.getReceiver().getIndex()] = true;
|
||||
}
|
||||
|
||||
while (cls != null) {
|
||||
for (FieldReader field : cls.getFields()) {
|
||||
addField(insn.getReceiver(), field.getReference());
|
||||
}
|
||||
cls = cls.getParent() != null ? classSource.get(cls.getParent()) : null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(NullConstantInstruction insn) {
|
||||
escapingVars[insn.getReceiver().getIndex()] = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ClassConstantInstruction insn) {
|
||||
escapingVars[insn.getReceiver().getIndex()] = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(StringConstantInstruction insn) {
|
||||
escapingVars[insn.getReceiver().getIndex()] = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(CloneArrayInstruction insn) {
|
||||
escapingVars[insn.getArray().getIndex()] = true;
|
||||
escapingVars[insn.getReceiver().getIndex()] = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(UnwrapArrayInstruction insn) {
|
||||
definitionClasses.union(insn.getReceiver().getIndex(), insn.getArray().getIndex());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(AssignInstruction insn) {
|
||||
definitionClasses.union(insn.getReceiver().getIndex(), insn.getAssignee().getIndex());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(CastInstruction insn) {
|
||||
escapingVars[insn.getReceiver().getIndex()] = true;
|
||||
escapingVars[insn.getValue().getIndex()] = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ExitInstruction insn) {
|
||||
if (insn.getValueToReturn() != null) {
|
||||
escapingVars[insn.getValueToReturn().getIndex()] = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RaiseInstruction insn) {
|
||||
escapingVars[insn.getException().getIndex()] = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(GetFieldInstruction insn) {
|
||||
escapingVars[insn.getReceiver().getIndex()] = true;
|
||||
addField(insn.getInstance(), insn.getField());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(PutFieldInstruction insn) {
|
||||
escapingVars[insn.getValue().getIndex()] = true;
|
||||
addField(insn.getInstance(), insn.getField());
|
||||
}
|
||||
|
||||
private void addField(Variable instance, FieldReference field) {
|
||||
if (instance == null) {
|
||||
return;
|
||||
}
|
||||
Set<FieldReference> fieldSet = fields.get(instance.getIndex());
|
||||
if (fieldSet == null) {
|
||||
fieldSet = new LinkedHashSet<>();
|
||||
fields.set(instance.getIndex(), fieldSet);
|
||||
}
|
||||
fieldSet.add(field);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(GetElementInstruction insn) {
|
||||
escapingVars[insn.getReceiver().getIndex()] = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(PutElementInstruction insn) {
|
||||
escapingVars[insn.getValue().getIndex()] = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(InvokeInstruction insn) {
|
||||
if (insn.getInstance() != null) {
|
||||
escapingVars[insn.getInstance().getIndex()] = true;
|
||||
}
|
||||
for (Variable arg : insn.getArguments()) {
|
||||
escapingVars[arg.getIndex()] = true;
|
||||
}
|
||||
if (insn.getReceiver() != null) {
|
||||
escapingVars[insn.getReceiver().getIndex()] = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(IsInstanceInstruction insn) {
|
||||
escapingVars[insn.getValue().getIndex()] = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(NullCheckInstruction insn) {
|
||||
definitionClasses.union(insn.getValue().getIndex(), insn.getReceiver().getIndex());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(MonitorEnterInstruction insn) {
|
||||
escapingVars[insn.getObjectRef().getIndex()] = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(MonitorExitInstruction insn) {
|
||||
escapingVars[insn.getObjectRef().getIndex()] = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BranchingInstruction insn) {
|
||||
switch (insn.getCondition()) {
|
||||
case NULL:
|
||||
case NOT_NULL:
|
||||
escapingVars[insn.getOperand().getIndex()] = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BinaryBranchingInstruction insn) {
|
||||
switch (insn.getCondition()) {
|
||||
case REFERENCE_EQUAL:
|
||||
case REFERENCE_NOT_EQUAL:
|
||||
escapingVars[insn.getFirstOperand().getIndex()] = true;
|
||||
escapingVars[insn.getSecondOperand().getIndex()] = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,10 +18,6 @@ package org.teavm.model.instructions;
|
|||
import org.teavm.model.Instruction;
|
||||
import org.teavm.model.Variable;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class NullConstantInstruction extends Instruction {
|
||||
private Variable receiver;
|
||||
|
||||
|
|
|
@ -0,0 +1,245 @@
|
|||
/*
|
||||
* Copyright 2017 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 java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.teavm.model.BasicBlock;
|
||||
import org.teavm.model.ClassReaderSource;
|
||||
import org.teavm.model.FieldReader;
|
||||
import org.teavm.model.FieldReference;
|
||||
import org.teavm.model.Incoming;
|
||||
import org.teavm.model.Instruction;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.Phi;
|
||||
import org.teavm.model.Program;
|
||||
import org.teavm.model.ValueType;
|
||||
import org.teavm.model.Variable;
|
||||
import org.teavm.model.analysis.EscapeAnalysis;
|
||||
import org.teavm.model.instructions.AbstractInstructionVisitor;
|
||||
import org.teavm.model.instructions.AssignInstruction;
|
||||
import org.teavm.model.instructions.ConstructInstruction;
|
||||
import org.teavm.model.instructions.DoubleConstantInstruction;
|
||||
import org.teavm.model.instructions.FloatConstantInstruction;
|
||||
import org.teavm.model.instructions.GetFieldInstruction;
|
||||
import org.teavm.model.instructions.IntegerConstantInstruction;
|
||||
import org.teavm.model.instructions.LongConstantInstruction;
|
||||
import org.teavm.model.instructions.NullConstantInstruction;
|
||||
import org.teavm.model.instructions.PutFieldInstruction;
|
||||
import org.teavm.model.util.PhiUpdater;
|
||||
|
||||
public class ScalarReplacement implements MethodOptimization {
|
||||
@Override
|
||||
public boolean optimize(MethodOptimizationContext context, Program program) {
|
||||
boolean changed = false;
|
||||
while (performOnce(context, program)) {
|
||||
changed = true;
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
private boolean performOnce(MethodOptimizationContext context, Program program) {
|
||||
List<Map<FieldReference, Variable>> fieldMappings = new ArrayList<>(
|
||||
Collections.nCopies(program.variableCount(), null));
|
||||
|
||||
MethodReference methodReference = context.getMethod().getReference();
|
||||
EscapeAnalysis escapeAnalysis = new EscapeAnalysis(context.getClassSource());
|
||||
escapeAnalysis.analyze(program, methodReference);
|
||||
boolean canPerform = false;
|
||||
for (int i = 0; i < fieldMappings.size(); ++i) {
|
||||
FieldReference[] fields = escapeAnalysis.getFields(i);
|
||||
if (!escapeAnalysis.escapes(i) && fields != null) {
|
||||
Map<FieldReference, Variable> fieldMapping = new LinkedHashMap<>();
|
||||
for (FieldReference field : fields) {
|
||||
fieldMapping.put(field, program.createVariable());
|
||||
}
|
||||
fieldMappings.set(i, fieldMapping);
|
||||
canPerform = true;
|
||||
}
|
||||
}
|
||||
if (!canPerform) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ScalarReplacementVisitor visitor = new ScalarReplacementVisitor(escapeAnalysis, context.getClassSource(),
|
||||
fieldMappings);
|
||||
for (BasicBlock block : program.getBasicBlocks()) {
|
||||
for (Instruction instruction : block) {
|
||||
instruction.acceptVisitor(visitor);
|
||||
}
|
||||
List<Phi> additionalPhis = new ArrayList<>();
|
||||
for (int i = 0; i < block.getPhis().size(); ++i) {
|
||||
Phi phi = block.getPhis().get(i);
|
||||
if (escapeAnalysis.escapes(phi.getReceiver().getIndex())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FieldReference[] fields = escapeAnalysis.getFields(phi.getReceiver().getIndex());
|
||||
if (fields == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (FieldReference field : fields) {
|
||||
boolean allIncomingsInitialized = true;
|
||||
for (Incoming incoming : phi.getIncomings()) {
|
||||
if (fieldMappings.get(incoming.getValue().getIndex()).get(field) == null) {
|
||||
allIncomingsInitialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!allIncomingsInitialized) {
|
||||
continue;
|
||||
}
|
||||
Phi phiReplacement = new Phi();
|
||||
phiReplacement.setReceiver(fieldMappings.get(phi.getReceiver().getIndex()).get(field));
|
||||
|
||||
for (Incoming incoming : phi.getIncomings()) {
|
||||
Incoming incomingReplacement = new Incoming();
|
||||
incomingReplacement.setSource(incoming.getSource());
|
||||
incomingReplacement.setValue(fieldMappings.get(incoming.getValue().getIndex()).get(field));
|
||||
phiReplacement.getIncomings().add(incomingReplacement);
|
||||
}
|
||||
|
||||
additionalPhis.add(phi);
|
||||
}
|
||||
block.getPhis().remove(i--);
|
||||
}
|
||||
block.getPhis().addAll(additionalPhis);
|
||||
}
|
||||
|
||||
Variable[] arguments = new Variable[methodReference.parameterCount() + 1];
|
||||
for (int i = 0; i < arguments.length; ++i) {
|
||||
arguments[i] = program.variableAt(i);
|
||||
}
|
||||
new PhiUpdater().updatePhis(program, arguments);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static class ScalarReplacementVisitor extends AbstractInstructionVisitor {
|
||||
private EscapeAnalysis escapeAnalysis;
|
||||
private ClassReaderSource classSource;
|
||||
private List<Map<FieldReference, Variable>> fieldMappings;
|
||||
|
||||
public ScalarReplacementVisitor(EscapeAnalysis escapeAnalysis, ClassReaderSource classSource,
|
||||
List<Map<FieldReference, Variable>> fieldMappings) {
|
||||
this.escapeAnalysis = escapeAnalysis;
|
||||
this.classSource = classSource;
|
||||
this.fieldMappings = fieldMappings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ConstructInstruction insn) {
|
||||
int var = insn.getReceiver().getIndex();
|
||||
if (!escapeAnalysis.escapes(var) && escapeAnalysis.getFields(var) != null) {
|
||||
for (FieldReference fieldRef : escapeAnalysis.getFields(var)) {
|
||||
FieldReader field = classSource.resolve(fieldRef);
|
||||
Variable receiver = fieldMappings.get(insn.getReceiver().getIndex()).get(fieldRef);
|
||||
Instruction initializer = generateDefaultValue(field.getType(), receiver);
|
||||
initializer.setLocation(initializer.getLocation());
|
||||
insn.insertPrevious(initializer);
|
||||
}
|
||||
insn.delete();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(GetFieldInstruction insn) {
|
||||
if (insn.getInstance() != null && !escapeAnalysis.escapes(insn.getInstance().getIndex())) {
|
||||
Variable var = fieldMappings.get(insn.getInstance().getIndex()).get(insn.getField());
|
||||
AssignInstruction assignment = new AssignInstruction();
|
||||
assignment.setReceiver(insn.getReceiver());
|
||||
assignment.setAssignee(var);
|
||||
assignment.setLocation(insn.getLocation());
|
||||
insn.replace(assignment);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(PutFieldInstruction insn) {
|
||||
if (insn.getInstance() != null && !escapeAnalysis.escapes(insn.getInstance().getIndex())) {
|
||||
Variable var = fieldMappings.get(insn.getInstance().getIndex()).get(insn.getField());
|
||||
AssignInstruction assignment = new AssignInstruction();
|
||||
assignment.setReceiver(var);
|
||||
assignment.setAssignee(insn.getValue());
|
||||
assignment.setLocation(insn.getLocation());
|
||||
insn.replace(assignment);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(AssignInstruction insn) {
|
||||
if (escapeAnalysis.escapes(insn.getAssignee().getIndex())) {
|
||||
return;
|
||||
}
|
||||
|
||||
FieldReference[] fields = escapeAnalysis.getFields(insn.getReceiver().getIndex());
|
||||
if (fields == null) {
|
||||
return;
|
||||
}
|
||||
for (FieldReference field : fields) {
|
||||
Variable assignee = fieldMappings.get(insn.getAssignee().getIndex()).get(field);
|
||||
if (assignee == null) {
|
||||
continue;
|
||||
}
|
||||
Variable receiver = fieldMappings.get(insn.getReceiver().getIndex()).get(field);
|
||||
AssignInstruction assignment = new AssignInstruction();
|
||||
assignment.setReceiver(receiver);
|
||||
assignment.setAssignee(assignee);
|
||||
assignment.setLocation(insn.getLocation());
|
||||
insn.insertPrevious(assignment);
|
||||
}
|
||||
insn.delete();
|
||||
}
|
||||
|
||||
private Instruction generateDefaultValue(ValueType type, Variable receiver) {
|
||||
if (type instanceof ValueType.Primitive) {
|
||||
switch (((ValueType.Primitive) type).getKind()) {
|
||||
case BOOLEAN:
|
||||
case BYTE:
|
||||
case SHORT:
|
||||
case CHARACTER:
|
||||
case INTEGER: {
|
||||
IntegerConstantInstruction insn = new IntegerConstantInstruction();
|
||||
insn.setReceiver(receiver);
|
||||
return insn;
|
||||
}
|
||||
case LONG: {
|
||||
LongConstantInstruction insn = new LongConstantInstruction();
|
||||
insn.setReceiver(receiver);
|
||||
return insn;
|
||||
}
|
||||
case FLOAT: {
|
||||
FloatConstantInstruction insn = new FloatConstantInstruction();
|
||||
insn.setReceiver(receiver);
|
||||
return insn;
|
||||
}
|
||||
case DOUBLE: {
|
||||
DoubleConstantInstruction insn = new DoubleConstantInstruction();
|
||||
insn.setReceiver(receiver);
|
||||
return insn;
|
||||
}
|
||||
}
|
||||
}
|
||||
NullConstantInstruction insn = new NullConstantInstruction();
|
||||
insn.setReceiver(receiver);
|
||||
return insn;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -60,6 +60,7 @@ import org.teavm.model.optimization.LoopInvariantMotion;
|
|||
import org.teavm.model.optimization.MethodOptimization;
|
||||
import org.teavm.model.optimization.MethodOptimizationContext;
|
||||
import org.teavm.model.optimization.RedundantJumpElimination;
|
||||
import org.teavm.model.optimization.ScalarReplacement;
|
||||
import org.teavm.model.optimization.UnreachableBasicBlockElimination;
|
||||
import org.teavm.model.optimization.UnusedVariableElimination;
|
||||
import org.teavm.model.text.ListingBuilder;
|
||||
|
@ -551,6 +552,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
|||
optimizations.add(new RedundantJumpElimination());
|
||||
optimizations.add(new ArrayUnwrapMotion());
|
||||
if (optimizationLevel.ordinal() >= TeaVMOptimizationLevel.ADVANCED.ordinal()) {
|
||||
optimizations.add(new ScalarReplacement());
|
||||
//optimizations.add(new LoopInversion());
|
||||
optimizations.add(new LoopInvariantMotion());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user