Refactoring: extracted specific logic into RedundantBoxedValuesCollection class

This commit is contained in:
Denis Zharkov
2014-07-08 12:11:29 +04:00
committed by Alexander Udalov
parent cb3eef4b86
commit 0f0d07c9fe
4 changed files with 97 additions and 57 deletions
@@ -88,31 +88,17 @@ public class BoxedBasicValue extends BasicValue {
return primitiveType; return primitiveType;
} }
public void mergeWith(BoxedBasicValue value) { public void addMergedWith(@NotNull BoxedBasicValue value) {
if (this == value) {
return;
}
if (!value.isSafeToRemove) {
propagateRemovingAsUnsafe();
}
if (!isSafeToRemove) {
value.propagateRemovingAsUnsafe();
}
mergedWith.add(value); mergedWith.add(value);
value.mergedWith.add(this);
} }
public void propagateRemovingAsUnsafe() { @NotNull
isSafeToRemove = false; public Iterable<BoxedBasicValue> getMergedWith() {
return mergedWith;
}
for (BoxedBasicValue value : mergedWith) { public void markAsUnsafeToRemove() {
if (value.isSafeToRemove()) { isSafeToRemove = false;
value.propagateRemovingAsUnsafe();
}
}
} }
public boolean isSafeToRemove() { public boolean isSafeToRemove() {
@@ -0,0 +1,65 @@
/*
* Copyright 2010-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.codegen.optimization.boxing;
import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class RedundantBoxedValuesCollection implements Iterable<BoxedBasicValue> {
private final Set<BoxedBasicValue> safeToDeleteValues = new HashSet<BoxedBasicValue>();
public void add(@NotNull BoxedBasicValue value) {
safeToDeleteValues.add(value);
}
public void remove(@NotNull BoxedBasicValue value) {
if (safeToDeleteValues.contains(value)) {
safeToDeleteValues.remove(value);
value.markAsUnsafeToRemove();
for (BoxedBasicValue mergedValue : value.getMergedWith()) {
remove(mergedValue);
}
}
}
public void merge(@NotNull BoxedBasicValue v, @NotNull BoxedBasicValue w) {
v.addMergedWith(w);
w.addMergedWith(v);
if (v.isSafeToRemove() && !w.isSafeToRemove()) {
remove(v);
}
if (!v.isSafeToRemove() && w.isSafeToRemove()) {
remove(w);
}
}
public boolean isEmpty() {
return safeToDeleteValues.isEmpty();
}
@NotNull
@Override
public Iterator<BoxedBasicValue> iterator() {
return safeToDeleteValues.iterator();
}
}
@@ -28,9 +28,6 @@ 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;
import java.util.HashSet;
import java.util.Set;
class RedundantBoxingInterpreter extends BoxingInterpreter { class RedundantBoxingInterpreter extends BoxingInterpreter {
private static final ImmutableSet<Integer> UNSAFE_OPERATIONS_OPCODES; private static final ImmutableSet<Integer> UNSAFE_OPERATIONS_OPCODES;
@@ -44,14 +41,14 @@ class RedundantBoxingInterpreter extends BoxingInterpreter {
UNSAFE_OPERATIONS_OPCODES = unsafeOperationsOpcodesBuilder.build(); UNSAFE_OPERATIONS_OPCODES = unsafeOperationsOpcodesBuilder.build();
} }
private final Set<BoxedBasicValue> candidatesBoxedValues = new HashSet<BoxedBasicValue>(); private final RedundantBoxedValuesCollection values = new RedundantBoxedValuesCollection();
public RedundantBoxingInterpreter(InsnList insnList) { public RedundantBoxingInterpreter(InsnList insnList) {
super(insnList); super(insnList);
} }
private static void markValueAsDirty(@NotNull BoxedBasicValue value) { private void markValueAsDirty(@NotNull BoxedBasicValue value) {
value.propagateRemovingAsUnsafe(); values.remove(value);
} }
private static void addAssociatedInsn(@NotNull BoxedBasicValue value, @NotNull AbstractInsnNode insn) { private static void addAssociatedInsn(@NotNull BoxedBasicValue value, @NotNull AbstractInsnNode insn) {
@@ -60,7 +57,7 @@ class RedundantBoxingInterpreter extends BoxingInterpreter {
} }
} }
private static void processOperationWithBoxedValue(@Nullable BasicValue value, @NotNull AbstractInsnNode insnNode) { private void processOperationWithBoxedValue(@Nullable BasicValue value, @NotNull AbstractInsnNode insnNode) {
if (value instanceof BoxedBasicValue) { if (value instanceof BoxedBasicValue) {
if (UNSAFE_OPERATIONS_OPCODES.contains(insnNode.getOpcode())) { if (UNSAFE_OPERATIONS_OPCODES.contains(insnNode.getOpcode())) {
markValueAsDirty((BoxedBasicValue) value); markValueAsDirty((BoxedBasicValue) value);
@@ -141,7 +138,7 @@ class RedundantBoxingInterpreter extends BoxingInterpreter {
@Override @Override
protected void onNewBoxedValue(@NotNull BoxedBasicValue value) { protected void onNewBoxedValue(@NotNull BoxedBasicValue value) {
candidatesBoxedValues.add(value); values.add(value);
} }
@Override @Override
@@ -170,11 +167,11 @@ class RedundantBoxingInterpreter extends BoxingInterpreter {
protected void onMergeSuccess( protected void onMergeSuccess(
@NotNull BoxedBasicValue v, @NotNull BoxedBasicValue w @NotNull BoxedBasicValue v, @NotNull BoxedBasicValue w
) { ) {
v.mergeWith(w); values.merge(v, w);
} }
@NotNull @NotNull
public Set<BoxedBasicValue> getCandidatesBoxedValues() { public RedundantBoxedValuesCollection getCandidatesBoxedValues() {
return candidatesBoxedValues; return values;
} }
} }
@@ -16,8 +16,6 @@
package org.jetbrains.jet.codegen.optimization.boxing; 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 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.OptimizationUtils;
@@ -44,12 +42,11 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
Analyzer<BasicValue> analyzer = new Analyzer<BasicValue>(interpreter); Analyzer<BasicValue> analyzer = new Analyzer<BasicValue>(interpreter);
Frame<BasicValue>[] frames = runAnalyzer(analyzer, internalClassName, node); Frame<BasicValue>[] frames = runAnalyzer(analyzer, internalClassName, node);
Set<BoxedBasicValue> valuesToOptimize = filterSafeToRemoveValues(interpreter.getCandidatesBoxedValues()); RedundantBoxedValuesCollection valuesToOptimize = interpreter.getCandidatesBoxedValues();
if (!valuesToOptimize.isEmpty()) { if (!valuesToOptimize.isEmpty()) {
findValuesClashingWithVariables(node, frames); // has side effect on valuesToOptimize and frames, containing BoxedBasicValues that are unsafe to remove
removeValuesClashingWithVariables(valuesToOptimize, node, frames);
valuesToOptimize = filterSafeToRemoveValues(valuesToOptimize);
adaptLocalVariableTableForBoxedValues(node, frames); adaptLocalVariableTableForBoxedValues(node, frames);
@@ -61,16 +58,6 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
super.transform(internalClassName, node); super.transform(internalClassName, node);
} }
@NotNull
private static Set<BoxedBasicValue> filterSafeToRemoveValues(@NotNull Set<BoxedBasicValue> values) {
return new HashSet<BoxedBasicValue>(Collections2.filter(values, new Predicate<BoxedBasicValue>() {
@Override
public boolean apply(BoxedBasicValue input) {
return input.isSafeToRemove();
}
}));
}
private static void adaptLocalVariableTableForBoxedValues(@NotNull MethodNode node, @NotNull Frame<BasicValue>[] frames) { private static void adaptLocalVariableTableForBoxedValues(@NotNull MethodNode node, @NotNull Frame<BasicValue>[] frames) {
for (LocalVariableNode localVariableNode : node.localVariables) { for (LocalVariableNode localVariableNode : node.localVariables) {
if (Type.getType(localVariableNode.desc).getSort() != Type.OBJECT) { if (Type.getType(localVariableNode.desc).getSort() != Type.OBJECT) {
@@ -107,16 +94,20 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
} }
} }
private static void findValuesClashingWithVariables( private static void removeValuesClashingWithVariables(
@NotNull MethodNode node, @NotNull Frame<BasicValue>[] frames @NotNull RedundantBoxedValuesCollection values,
@NotNull MethodNode node,
@NotNull Frame<BasicValue>[] frames
) { ) {
while (findValuesClashingWithVariablesPass(node, frames)) { while (removeValuesClashingWithVariablesPass(values, node, frames)) {
// do nothing // do nothing
} }
} }
private static boolean findValuesClashingWithVariablesPass( private static boolean removeValuesClashingWithVariablesPass(
@NotNull MethodNode node, @NotNull Frame<BasicValue>[] frames @NotNull RedundantBoxedValuesCollection values,
@NotNull MethodNode node,
@NotNull Frame<BasicValue>[] frames
) { ) {
InsnList insnList = node.instructions; InsnList insnList = node.instructions;
boolean needToRepeat = false; boolean needToRepeat = false;
@@ -131,7 +122,7 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
int to = insnList.indexOf(localVariableNode.end) - 1; int to = insnList.indexOf(localVariableNode.end) - 1;
if (isThereUnsafeStoreInstruction(insnList, frames, from, to, index)) { if (isThereUnsafeStoreInstruction(insnList, frames, from, to, index)) {
needToRepeat |= markAllBoxedValuesStoredAsUnsafeToRemove(insnList, frames, from, to, index); needToRepeat |= markAllBoxedValuesStoredAsUnsafeToRemove(insnList, frames, values, from, to, index);
} }
} }
@@ -183,6 +174,7 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
private static boolean markAllBoxedValuesStoredAsUnsafeToRemove( private static boolean markAllBoxedValuesStoredAsUnsafeToRemove(
@NotNull InsnList insnList, @NotNull InsnList insnList,
@NotNull Frame<BasicValue>[] frames, @NotNull Frame<BasicValue>[] frames,
@NotNull RedundantBoxedValuesCollection values,
int from, int to, int varIndex int from, int to, int varIndex
) { ) {
boolean wasChanges = false; boolean wasChanges = false;
@@ -200,7 +192,7 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
} }
wasChanges |= true; wasChanges |= true;
((BoxedBasicValue) top).propagateRemovingAsUnsafe(); values.remove((BoxedBasicValue) top);
} }
} }
@@ -208,7 +200,7 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
} }
@NotNull @NotNull
private static int[] buildVariablesRemapping(@NotNull Iterable<BoxedBasicValue> values, @NotNull MethodNode node) { private static int[] buildVariablesRemapping(@NotNull RedundantBoxedValuesCollection values, @NotNull MethodNode node) {
Set<Integer> doubleSizedVars = new HashSet<Integer>(); Set<Integer> doubleSizedVars = new HashSet<Integer>();
for (BoxedBasicValue value : values) { for (BoxedBasicValue value : values) {
if (value.getPrimitiveType().getSize() == 2) { if (value.getPrimitiveType().getSize() == 2) {
@@ -247,7 +239,7 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
} }
private static void adaptInstructionsForBoxedValues( private static void adaptInstructionsForBoxedValues(
@NotNull MethodNode node, @NotNull Frame<BasicValue>[] frames, @NotNull Set<BoxedBasicValue> values @NotNull MethodNode node, @NotNull Frame<BasicValue>[] frames, @NotNull RedundantBoxedValuesCollection values
) { ) {
addPopInstructionsForBoxedValues(node, frames); addPopInstructionsForBoxedValues(node, frames);