From a412a96ff36fb0def0ce342eeb1feca9c30db32f Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Tue, 8 Jul 2014 15:25:50 +0400 Subject: [PATCH] Changed strategy from enumeration of unsafe operations to permitted + INSTANCEOF added --- .../boxing/RedundantBoxingInterpreter.java | 22 ++++---- .../RedundantBoxingMethodTransformer.java | 52 ++++++++++++------- 2 files changed, 41 insertions(+), 33 deletions(-) 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 c62aeec0342..936eb9e5ef2 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 @@ -29,17 +29,9 @@ import org.jetbrains.org.objectweb.asm.tree.analysis.AnalyzerException; import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue; class RedundantBoxingInterpreter extends BoxingInterpreter { - private static final ImmutableSet UNSAFE_OPERATIONS_OPCODES; - - static { - ImmutableSet.Builder unsafeOperationsOpcodesBuilder = ImmutableSet.builder(); - unsafeOperationsOpcodesBuilder.add( - Opcodes.AASTORE, Opcodes.PUTFIELD, Opcodes.PUTSTATIC, Opcodes.ARETURN, - Opcodes.IFNONNULL, Opcodes.IFNULL, Opcodes.IF_ACMPEQ, Opcodes.IF_ACMPNE - ); - - UNSAFE_OPERATIONS_OPCODES = unsafeOperationsOpcodesBuilder.build(); - } + private static final ImmutableSet PERMITTED_OPERATIONS_OPCODES = ImmutableSet.of( + Opcodes.ASTORE, Opcodes.ALOAD, Opcodes.POP, Opcodes.DUP, Opcodes.CHECKCAST, Opcodes.INSTANCEOF + ); private final RedundantBoxedValuesCollection values = new RedundantBoxedValuesCollection(); @@ -78,7 +70,8 @@ class RedundantBoxingInterpreter extends BoxingInterpreter { @NotNull AbstractInsnNode insn, @NotNull BasicValue value ) throws AnalyzerException { - if (insn.getOpcode() == Opcodes.CHECKCAST && value instanceof BoxedBasicValue) { + if ((insn.getOpcode() == Opcodes.CHECKCAST || insn.getOpcode() == Opcodes.INSTANCEOF) && + value instanceof BoxedBasicValue) { TypeInsnNode typeInsn = (TypeInsnNode) insn; if (!isSafeCast((BoxedBasicValue) value, typeInsn.desc)) { @@ -114,6 +107,9 @@ class RedundantBoxingInterpreter extends BoxingInterpreter { return super.copyOperation(insn, value); } + public void processPopInstruction(@NotNull AbstractInsnNode insnNode, @NotNull BasicValue value) { + processOperationWithBoxedValue(value, insnNode); + } @Override protected void onNewBoxedValue(@NotNull BoxedBasicValue value) { @@ -151,7 +147,7 @@ class RedundantBoxingInterpreter extends BoxingInterpreter { private void processOperationWithBoxedValue(@Nullable BasicValue value, @NotNull AbstractInsnNode insnNode) { if (value instanceof BoxedBasicValue) { - if (UNSAFE_OPERATIONS_OPCODES.contains(insnNode.getOpcode())) { + if (!PERMITTED_OPERATIONS_OPCODES.contains(insnNode.getOpcode())) { markValueAsDirty((BoxedBasicValue) value); } else { 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 5e45c9c3342..a03b41d3ef2 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 @@ -44,6 +44,7 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer { new Analyzer(interpreter), internalClassName, node ); + interpretPopInstructionsForBoxedValues(interpreter, node, frames); RedundantBoxedValuesCollection valuesToOptimize = interpreter.getCandidatesBoxedValues(); @@ -55,12 +56,32 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer { applyVariablesRemapping(node, buildVariablesRemapping(valuesToOptimize, node)); - adaptInstructionsForBoxedValues(node, frames, valuesToOptimize); + adaptInstructionsForBoxedValues(node, valuesToOptimize); } super.transform(internalClassName, node); } + private static void interpretPopInstructionsForBoxedValues( + @NotNull RedundantBoxingInterpreter interpreter, + @NotNull MethodNode node, + @NotNull Frame[] frames + ) { + for (int i = 0; i < node.instructions.size(); i++) { + AbstractInsnNode insn = node.instructions.get(i); + if ((insn.getOpcode() != Opcodes.POP && insn.getOpcode() != Opcodes.POP2) || frames[i] == null) { + continue; + } + + BasicValue top = frames[i].getStack(frames[i].getStackSize() - 1); + interpreter.processPopInstruction(insn, top); + + if (top.getSize() == 1 && insn.getOpcode() == Opcodes.POP2) { + interpreter.processPopInstruction(insn, frames[i].getStack(frames[i].getStackSize() - 2)); + } + } + } + private static void removeValuesClashingWithVariables( @NotNull RedundantBoxedValuesCollection values, @NotNull MethodNode node, @@ -206,31 +227,14 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer { } private static void adaptInstructionsForBoxedValues( - @NotNull MethodNode node, @NotNull Frame[] frames, @NotNull RedundantBoxedValuesCollection values + @NotNull MethodNode node, + @NotNull RedundantBoxedValuesCollection values ) { - addPopInstructionsForBoxedValues(node, frames); - for (BoxedBasicValue value : values) { adaptInstructionsForBoxedValue(node, value); } } - private static void addPopInstructionsForBoxedValues( - @NotNull MethodNode node, @NotNull Frame[] frames - ) { - for (int i = 0; i < node.instructions.size(); i++) { - AbstractInsnNode insn = node.instructions.get(i); - if (insn.getOpcode() != Opcodes.POP || frames[i] == null) { - continue; - } - - BasicValue top = frames[i].getStack(frames[i].getStackSize() - 1); - if (top instanceof BoxedBasicValue && ((BoxedBasicValue) top).isSafeToRemove()) { - ((BoxedBasicValue) top).addInsn(node.instructions.get(i)); - } - } - } - private static void adaptInstructionsForBoxedValue(@NotNull MethodNode node, @NotNull BoxedBasicValue value) { adaptBoxingInstruction(node, value); @@ -320,7 +324,15 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer { ) ); break; + case Opcodes.INSTANCEOF: + node.instructions.insertBefore( + insn, + new InsnNode(isDoubleSize ? Opcodes.POP2 : Opcodes.POP) + ); + node.instructions.set(insn, new InsnNode(Opcodes.ICONST_1)); + break; default: + // CHECKCAST or unboxing-method call node.instructions.remove(insn); } }