From cb3eef4b86a330d49c02cba1609d3b83032479ca Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Wed, 9 Jul 2014 11:56:23 +0400 Subject: [PATCH] Optimization of type conversion with boxed values (transform Integer.valueOf(x). .. .longValue() -> I2L and etc) --- .../optimization/boxing/BoxedBasicValue.java | 11 +++++++++ .../boxing/BoxingInterpreter.java | 7 +++--- .../boxing/RedundantBoxingInterpreter.java | 11 +++++++-- .../RedundantBoxingMethodTransformer.java | 23 +++++++++++++++++++ 4 files changed, 46 insertions(+), 6 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/optimization/boxing/BoxedBasicValue.java b/compiler/backend/src/org/jetbrains/jet/codegen/optimization/boxing/BoxedBasicValue.java index f529df402bb..be077a25e28 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/optimization/boxing/BoxedBasicValue.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/optimization/boxing/BoxedBasicValue.java @@ -16,6 +16,7 @@ package org.jetbrains.jet.codegen.optimization.boxing; +import com.intellij.openapi.util.Pair; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.codegen.AsmUtil; @@ -30,6 +31,7 @@ import java.util.Set; public class BoxedBasicValue extends BasicValue { private final Set associatedInsns = new HashSet(); + private final Set> unboxingWithCastInsns = new HashSet>(); private final AbstractInsnNode boxingInsn; private final Set associatedVariables = new HashSet(); private final Set mergedWith = new HashSet(); @@ -134,4 +136,13 @@ public class BoxedBasicValue extends BasicValue { public ProgressionIteratorBasicValue getProgressionIterator() { return progressionIterator; } + + public void addUnboxingWithCastTo(@NotNull AbstractInsnNode insn, @NotNull Type type) { + unboxingWithCastInsns.add(Pair.create(insn, type)); + } + + @NotNull + public Set> getUnboxingWithCastInsns() { + return unboxingWithCastInsns; + } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/optimization/boxing/BoxingInterpreter.java b/compiler/backend/src/org/jetbrains/jet/codegen/optimization/boxing/BoxingInterpreter.java index a01b9a41d48..15f352d7550 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/optimization/boxing/BoxingInterpreter.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/optimization/boxing/BoxingInterpreter.java @@ -156,9 +156,8 @@ public class BoxingInterpreter extends OptimizationBasicInterpreter { return createNewBoxing(insn, value.getType(), null); } else if (isUnboxing(insn) && - firstArg instanceof BoxedBasicValue && - value.getType().equals(((BoxedBasicValue) firstArg).getPrimitiveType())) { - onUnboxing((BoxedBasicValue) firstArg, insn); + firstArg instanceof BoxedBasicValue) { + onUnboxing(insn, (BoxedBasicValue) firstArg, value.getType()); } else if (isIteratorMethodCallOfProgression(insn, values)) { 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) { } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/optimization/boxing/RedundantBoxingInterpreter.java b/compiler/backend/src/org/jetbrains/jet/codegen/optimization/boxing/RedundantBoxingInterpreter.java index aa2e51573c0..293aad513b2 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/optimization/boxing/RedundantBoxingInterpreter.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/optimization/boxing/RedundantBoxingInterpreter.java @@ -20,8 +20,10 @@ import com.google.common.collect.ImmutableSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; 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.InsnList; +import org.jetbrains.org.objectweb.asm.tree.TypeInsnNode; 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.BasicValue; @@ -144,9 +146,14 @@ class RedundantBoxingInterpreter extends BoxingInterpreter { @Override 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 diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/optimization/boxing/RedundantBoxingMethodTransformer.java b/compiler/backend/src/org/jetbrains/jet/codegen/optimization/boxing/RedundantBoxingMethodTransformer.java index 586d20c8397..5d95387abb6 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/optimization/boxing/RedundantBoxingMethodTransformer.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/optimization/boxing/RedundantBoxingMethodTransformer.java @@ -18,10 +18,13 @@ package org.jetbrains.jet.codegen.optimization.boxing; import com.google.common.base.Predicate; import com.google.common.collect.Collections2; +import com.intellij.openapi.util.Pair; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.codegen.optimization.OptimizationUtils; import org.jetbrains.jet.codegen.optimization.transformer.MethodTransformer; import org.jetbrains.org.objectweb.asm.Opcodes; 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.analysis.Analyzer; 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) { adaptBoxingInstruction(node, value); + for (Pair cast : value.getUnboxingWithCastInsns()) { + adaptCastInstruction(node, value, cast); + } + for (AbstractInsnNode insn : value.getAssociatedInsns()) { 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 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( @NotNull MethodNode node, @NotNull AbstractInsnNode insn, @NotNull BoxedBasicValue value ) {