From ebfd2574080360c29b6e7628441af9f200364eeb Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Tue, 8 Jul 2014 12:50:31 +0400 Subject: [PATCH] Refactoring: extracted common logic of working with local variable table into getValuesStoredOrLoadedToVariable --- .../RedundantBoxingMethodTransformer.java | 143 +++++++----------- 1 file changed, 54 insertions(+), 89 deletions(-) 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 bd70f44dcb7..47d779915fa 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 @@ -16,6 +16,8 @@ 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; @@ -28,8 +30,7 @@ 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.Frame; -import java.util.HashSet; -import java.util.Set; +import java.util.*; public class RedundantBoxingMethodTransformer extends MethodTransformer { public RedundantBoxingMethodTransformer(MethodTransformer methodTransformer) { @@ -64,32 +65,9 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer { continue; } - adaptLocalVariableTableEntryForBoxedValues(node, frames, localVariableNode); - } - } - - private static void adaptLocalVariableTableEntryForBoxedValues( - @NotNull MethodNode node, @NotNull Frame[] frames, @NotNull LocalVariableNode localVariableNode - ) { - InsnList insnList = node.instructions; - int from = insnList.indexOf(localVariableNode.start) + 1; - int to = insnList.indexOf(localVariableNode.end) - 1; - - for (int i = from; i <= to; i++) { - AbstractInsnNode insn = insnList.get(i); - if (insn.getOpcode() == Opcodes.ASTORE && ((VarInsnNode) insn).var == localVariableNode.index) { - if (frames[i] == null) { - return; - } - - BasicValue top = frames[i].getStack(frames[i].getStackSize() - 1); - if (!(top instanceof BoxedBasicValue) || !((BoxedBasicValue) top).isSafeToRemove()) { - return; - } - - localVariableNode.desc = ((BoxedBasicValue) top).getPrimitiveType().getDescriptor(); - - return; + for (BasicValue value : getValuesStoredOrLoadedToVariable(localVariableNode, node, frames)) { + if (value == null || !(value instanceof BoxedBasicValue) || !((BoxedBasicValue) value).isSafeToRemove()) continue; + localVariableNode.desc = ((BoxedBasicValue) value).getPrimitiveType().getDescriptor(); } } } @@ -109,7 +87,6 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer { @NotNull MethodNode node, @NotNull Frame[] frames ) { - InsnList insnList = node.instructions; boolean needToRepeat = false; for (LocalVariableNode localVariableNode : node.localVariables) { @@ -117,86 +94,74 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer { continue; } - int index = localVariableNode.index; - int from = insnList.indexOf(localVariableNode.start) + 1; - int to = insnList.indexOf(localVariableNode.end) - 1; + List usedValues = getValuesStoredOrLoadedToVariable(localVariableNode, node, frames); - if (isThereUnsafeStoreInstruction(insnList, frames, from, to, index)) { - needToRepeat |= markAllBoxedValuesStoredAsUnsafeToRemove(insnList, frames, values, from, to, index); + Collection boxed = Collections2.filter(usedValues, new Predicate() { + @Override + public boolean apply(BasicValue input) { + return input instanceof BoxedBasicValue; + } + }); + + if (boxed.isEmpty()) continue; + + final BoxedBasicValue firstBoxed = (BoxedBasicValue) boxed.iterator().next(); + + if (!Collections2.filter(usedValues, new Predicate() { + @Override + public boolean apply(BasicValue input) { + return input == null || + !(input instanceof BoxedBasicValue) || + !((BoxedBasicValue) input).isSafeToRemove() || + !((BoxedBasicValue) input).getPrimitiveType().equals(firstBoxed.getPrimitiveType()); + } + }).isEmpty()) { + for (BasicValue value : usedValues) { + if (value instanceof BoxedBasicValue && ((BoxedBasicValue) value).isSafeToRemove()) { + values.remove((BoxedBasicValue) value); + needToRepeat = true; + } + } } } return needToRepeat; } - /** - * Check if there are unsafe ASTORE instructions, that put into var something but boxed values of the same type - * - * @param insnList - * @param frames - * @param from - * @param to - * @param varIndex - * @return - */ - private static boolean isThereUnsafeStoreInstruction( - @NotNull InsnList insnList, - @NotNull Frame[] frames, - int from, int to, int varIndex + @NotNull + private static List getValuesStoredOrLoadedToVariable( + @NotNull LocalVariableNode localVariableNode, + @NotNull MethodNode node, + @NotNull Frame[] frames ) { - Type usedAsType = null; + List values = new ArrayList(); + InsnList insnList = node.instructions; + int from = insnList.indexOf(localVariableNode.start) + 1; + int to = insnList.indexOf(localVariableNode.end) - 1; for (int i = from; i <= to; i++) { - AbstractInsnNode insn = insnList.get(i); //TODO: handle exception? - if (insn.getOpcode() == Opcodes.ASTORE && ((VarInsnNode) insn).var == varIndex) { - if (frames[i] == null) { - return true; - } + if (i < 0 || i >= insnList.size()) continue; - BasicValue top = frames[i].getStack(frames[i].getStackSize() - 1); - if (!(top instanceof BoxedBasicValue) || !((BoxedBasicValue) top).isSafeToRemove()) { - return true; - } - - if (usedAsType == null) { - usedAsType = ((BoxedBasicValue) top).getPrimitiveType(); - } - - if (!usedAsType.equals(((BoxedBasicValue) top).getPrimitiveType())) { - return true; - } - } - } - - return false; - } - - private static boolean markAllBoxedValuesStoredAsUnsafeToRemove( - @NotNull InsnList insnList, - @NotNull Frame[] frames, - @NotNull RedundantBoxedValuesCollection values, - int from, int to, int varIndex - ) { - boolean wasChanges = false; - - for (int i = from; i <= to; i++) { AbstractInsnNode insn = insnList.get(i); - if (insn.getOpcode() == Opcodes.ASTORE && ((VarInsnNode) insn).var == varIndex) { + if ((insn.getOpcode() == Opcodes.ASTORE || insn.getOpcode() == Opcodes.ALOAD) && + ((VarInsnNode) insn).var == localVariableNode.index) { + + // frames[i] can be null in case of exception handlers if (frames[i] == null) { + values.add(null); continue; } - BasicValue top = frames[i].getStack(frames[i].getStackSize() - 1); - if (!(top instanceof BoxedBasicValue) || !((BoxedBasicValue) top).isSafeToRemove()) { - continue; + if (insn.getOpcode() == Opcodes.ASTORE) { + values.add(frames[i].getStack(frames[i].getStackSize() - 1)); + } + else { + values.add(frames[i].getLocal(((VarInsnNode) insn).var)); } - - wasChanges |= true; - values.remove((BoxedBasicValue) top); } } - return wasChanges; + return values; } @NotNull