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 271acfc47fa..a802c84e8fe 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 @@ -100,14 +100,16 @@ public class BoxingInterpreter extends OptimizationBasicInterpreter { } return boxingPlaces.get(index); - } else if (isUnboxing(insn) && - values.get(0) instanceof BoxedBasicValue && - value.getType().equals(((BoxedBasicValue) values.get(0)).getPrimitiveType())) { + } + else if (isUnboxing(insn) && + values.get(0) instanceof BoxedBasicValue && + value.getType().equals(((BoxedBasicValue) values.get(0)).getPrimitiveType())) { BoxedBasicValue boxedBasicValue = (BoxedBasicValue) values.get(0); boxedBasicValue.addInsn(insn); boxedBasicValue.setWasUnboxed(true); - } else { + } + else { for (BasicValue arg : values) { if (arg instanceof BoxedBasicValue) { onMethodCallWithBoxedValue((BoxedBasicValue) arg); 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 726bf0e67b9..76ba4c92ae3 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 @@ -16,7 +16,9 @@ package org.jetbrains.jet.codegen.optimization.boxing; +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.tree.AbstractInsnNode; import org.jetbrains.org.objectweb.asm.tree.InsnList; @@ -29,12 +31,29 @@ import java.util.List; import java.util.Set; class RedundantBoxingInterpreter extends BoxingInterpreter { + private static final ImmutableSet unsafeOperationsOpcodes; + + static { + ImmutableSet.Builder unsafeOperationsOpcodesBuilder = ImmutableSet.builder(); + unsafeOperationsOpcodesBuilder.add( + Opcodes.AASTORE, Opcodes.PUTFIELD, Opcodes.PUTSTATIC, Opcodes.ARETURN + ); + + unsafeOperationsOpcodes = unsafeOperationsOpcodesBuilder.build(); + } + private final Set candidatesBoxedValues = new HashSet(); RedundantBoxingInterpreter(InsnList insnList) { super(insnList); } + private void checkIfUnsafeOperationWithBoxed(@Nullable BasicValue value, @NotNull AbstractInsnNode insnNode) { + if (value instanceof BoxedBasicValue && unsafeOperationsOpcodes.contains(insnNode.getOpcode())) { + markAsDirty((BoxedBasicValue) value); + } + } + @Override public BasicValue binaryOperation( @NotNull AbstractInsnNode insn, @@ -42,13 +61,22 @@ class RedundantBoxingInterpreter extends BoxingInterpreter { @NotNull BasicValue value2 ) throws AnalyzerException { - if (insn.getOpcode() == Opcodes.PUTFIELD && value2 instanceof BoxedBasicValue) { - markAsDirty((BoxedBasicValue) value2); - } + checkIfUnsafeOperationWithBoxed(value2, insn); return super.binaryOperation(insn, value1, value2); } + @Override + public BasicValue ternaryOperation( + @NotNull AbstractInsnNode insn, + @NotNull BasicValue value1, @NotNull BasicValue value2, @NotNull BasicValue value3 + ) throws AnalyzerException { + + checkIfUnsafeOperationWithBoxed(value3, insn); + + return super.ternaryOperation(insn, value1, value2, value3); + } + @Override protected boolean isAllowedUnaryOperationWithBoxed(int opcode) { return opcode == Opcodes.CHECKCAST;