Optimization of type conversion with boxed values (transform Integer.valueOf(x). .. .longValue() -> I2L and etc)

This commit is contained in:
Denis Zharkov
2014-07-09 11:56:23 +04:00
committed by Alexander Udalov
parent 270e58cf4e
commit cb3eef4b86
4 changed files with 46 additions and 6 deletions
@@ -16,6 +16,7 @@
package org.jetbrains.jet.codegen.optimization.boxing; package org.jetbrains.jet.codegen.optimization.boxing;
import com.intellij.openapi.util.Pair;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.codegen.AsmUtil; import org.jetbrains.jet.codegen.AsmUtil;
@@ -30,6 +31,7 @@ import java.util.Set;
public class BoxedBasicValue extends BasicValue { public class BoxedBasicValue extends BasicValue {
private final Set<AbstractInsnNode> associatedInsns = new HashSet<AbstractInsnNode>(); private final Set<AbstractInsnNode> associatedInsns = new HashSet<AbstractInsnNode>();
private final Set<Pair<AbstractInsnNode, Type>> unboxingWithCastInsns = new HashSet<Pair<AbstractInsnNode, Type>>();
private final AbstractInsnNode boxingInsn; private final AbstractInsnNode boxingInsn;
private final Set<Integer> associatedVariables = new HashSet<Integer>(); private final Set<Integer> associatedVariables = new HashSet<Integer>();
private final Set<BoxedBasicValue> mergedWith = new HashSet<BoxedBasicValue>(); private final Set<BoxedBasicValue> mergedWith = new HashSet<BoxedBasicValue>();
@@ -134,4 +136,13 @@ public class BoxedBasicValue extends BasicValue {
public ProgressionIteratorBasicValue getProgressionIterator() { public ProgressionIteratorBasicValue getProgressionIterator() {
return progressionIterator; return progressionIterator;
} }
public void addUnboxingWithCastTo(@NotNull AbstractInsnNode insn, @NotNull Type type) {
unboxingWithCastInsns.add(Pair.create(insn, type));
}
@NotNull
public Set<Pair<AbstractInsnNode, Type>> getUnboxingWithCastInsns() {
return unboxingWithCastInsns;
}
} }
@@ -156,9 +156,8 @@ public class BoxingInterpreter extends OptimizationBasicInterpreter {
return createNewBoxing(insn, value.getType(), null); return createNewBoxing(insn, value.getType(), null);
} }
else if (isUnboxing(insn) && else if (isUnboxing(insn) &&
firstArg instanceof BoxedBasicValue && firstArg instanceof BoxedBasicValue) {
value.getType().equals(((BoxedBasicValue) firstArg).getPrimitiveType())) { onUnboxing(insn, (BoxedBasicValue) firstArg, value.getType());
onUnboxing((BoxedBasicValue) firstArg, insn);
} }
else if (isIteratorMethodCallOfProgression(insn, values)) { else if (isIteratorMethodCallOfProgression(insn, values)) {
return new ProgressionIteratorBasicValue( return new ProgressionIteratorBasicValue(
@@ -229,7 +228,7 @@ public class BoxingInterpreter extends OptimizationBasicInterpreter {
} }
protected void onUnboxing(@NotNull BoxedBasicValue value, @NotNull AbstractInsnNode insn) { protected void onUnboxing(@NotNull AbstractInsnNode insn, @NotNull BoxedBasicValue value, @NotNull Type resultType) {
} }
@@ -20,8 +20,10 @@ import com.google.common.collect.ImmutableSet;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.org.objectweb.asm.Opcodes; import org.jetbrains.org.objectweb.asm.Opcodes;
import org.jetbrains.org.objectweb.asm.Type;
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode; import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode;
import org.jetbrains.org.objectweb.asm.tree.InsnList; import org.jetbrains.org.objectweb.asm.tree.InsnList;
import org.jetbrains.org.objectweb.asm.tree.TypeInsnNode;
import org.jetbrains.org.objectweb.asm.tree.VarInsnNode; import org.jetbrains.org.objectweb.asm.tree.VarInsnNode;
import org.jetbrains.org.objectweb.asm.tree.analysis.AnalyzerException; import org.jetbrains.org.objectweb.asm.tree.analysis.AnalyzerException;
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue; import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue;
@@ -144,9 +146,14 @@ class RedundantBoxingInterpreter extends BoxingInterpreter {
@Override @Override
protected void onUnboxing( protected void onUnboxing(
@NotNull BoxedBasicValue value, @NotNull AbstractInsnNode insn @NotNull AbstractInsnNode insn, @NotNull BoxedBasicValue value, @NotNull Type resultType
) { ) {
addAssociatedInsn(value, insn); if (value.getPrimitiveType().equals(resultType)) {
addAssociatedInsn(value, insn);
}
else {
value.addUnboxingWithCastTo(insn, resultType);
}
} }
@Override @Override
@@ -18,10 +18,13 @@ package org.jetbrains.jet.codegen.optimization.boxing;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.collect.Collections2; import com.google.common.collect.Collections2;
import com.intellij.openapi.util.Pair;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.codegen.optimization.OptimizationUtils;
import org.jetbrains.jet.codegen.optimization.transformer.MethodTransformer; import org.jetbrains.jet.codegen.optimization.transformer.MethodTransformer;
import org.jetbrains.org.objectweb.asm.Opcodes; import org.jetbrains.org.objectweb.asm.Opcodes;
import org.jetbrains.org.objectweb.asm.Type; import org.jetbrains.org.objectweb.asm.Type;
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
import org.jetbrains.org.objectweb.asm.tree.*; import org.jetbrains.org.objectweb.asm.tree.*;
import org.jetbrains.org.objectweb.asm.tree.analysis.Analyzer; import org.jetbrains.org.objectweb.asm.tree.analysis.Analyzer;
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue; import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue;
@@ -272,6 +275,10 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
private static void adaptInstructionsForBoxedValue(@NotNull MethodNode node, @NotNull BoxedBasicValue value) { private static void adaptInstructionsForBoxedValue(@NotNull MethodNode node, @NotNull BoxedBasicValue value) {
adaptBoxingInstruction(node, value); adaptBoxingInstruction(node, value);
for (Pair<AbstractInsnNode, Type> cast : value.getUnboxingWithCastInsns()) {
adaptCastInstruction(node, value, cast);
}
for (AbstractInsnNode insn : value.getAssociatedInsns()) { for (AbstractInsnNode insn : value.getAssociatedInsns()) {
adaptInstruction(node, insn, value); adaptInstruction(node, insn, value);
} }
@@ -305,6 +312,22 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
} }
} }
private static void adaptCastInstruction(
@NotNull MethodNode node,
@NotNull BoxedBasicValue value,
@NotNull Pair<AbstractInsnNode, Type> castWithType
) {
AbstractInsnNode castInsn = castWithType.getFirst();
MethodNode castInsnsListener = new MethodNode(OptimizationUtils.API);
new InstructionAdapter(castInsnsListener).cast(value.getPrimitiveType(), castWithType.getSecond());
for (AbstractInsnNode insn : castInsnsListener.instructions.toArray()) {
node.instructions.insertBefore(castInsn, insn);
}
node.instructions.remove(castInsn);
}
private static void adaptInstruction( private static void adaptInstruction(
@NotNull MethodNode node, @NotNull AbstractInsnNode insn, @NotNull BoxedBasicValue value @NotNull MethodNode node, @NotNull AbstractInsnNode insn, @NotNull BoxedBasicValue value
) { ) {