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;
}
public void mergeWith(BoxedBasicValue value) {
if (this == value) {
return;
}
if (!value.isSafeToRemove) {
propagateRemovingAsUnsafe();
}
if (!isSafeToRemove) {
value.propagateRemovingAsUnsafe();
}
public void addMergedWith(@NotNull BoxedBasicValue value) {
mergedWith.add(value);
value.mergedWith.add(this);
}
public void propagateRemovingAsUnsafe() {
isSafeToRemove = false;
@NotNull
public Iterable<BoxedBasicValue> getMergedWith() {
return mergedWith;
}
for (BoxedBasicValue value : mergedWith) {
if (value.isSafeToRemove()) {
value.propagateRemovingAsUnsafe();
}
}
public void markAsUnsafeToRemove() {
isSafeToRemove = false;
}
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.BasicValue;
import java.util.HashSet;
import java.util.Set;
class RedundantBoxingInterpreter extends BoxingInterpreter {
private static final ImmutableSet<Integer> UNSAFE_OPERATIONS_OPCODES;
@@ -44,14 +41,14 @@ class RedundantBoxingInterpreter extends BoxingInterpreter {
UNSAFE_OPERATIONS_OPCODES = unsafeOperationsOpcodesBuilder.build();
}
private final Set<BoxedBasicValue> candidatesBoxedValues = new HashSet<BoxedBasicValue>();
private final RedundantBoxedValuesCollection values = new RedundantBoxedValuesCollection();
public RedundantBoxingInterpreter(InsnList insnList) {
super(insnList);
}
private static void markValueAsDirty(@NotNull BoxedBasicValue value) {
value.propagateRemovingAsUnsafe();
private void markValueAsDirty(@NotNull BoxedBasicValue value) {
values.remove(value);
}
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 (UNSAFE_OPERATIONS_OPCODES.contains(insnNode.getOpcode())) {
markValueAsDirty((BoxedBasicValue) value);
@@ -141,7 +138,7 @@ class RedundantBoxingInterpreter extends BoxingInterpreter {
@Override
protected void onNewBoxedValue(@NotNull BoxedBasicValue value) {
candidatesBoxedValues.add(value);
values.add(value);
}
@Override
@@ -170,11 +167,11 @@ class RedundantBoxingInterpreter extends BoxingInterpreter {
protected void onMergeSuccess(
@NotNull BoxedBasicValue v, @NotNull BoxedBasicValue w
) {
v.mergeWith(w);
values.merge(v, w);
}
@NotNull
public Set<BoxedBasicValue> getCandidatesBoxedValues() {
return candidatesBoxedValues;
public RedundantBoxedValuesCollection getCandidatesBoxedValues() {
return values;
}
}
@@ -16,8 +16,6 @@
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;
@@ -44,12 +42,11 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
Analyzer<BasicValue> analyzer = new Analyzer<BasicValue>(interpreter);
Frame<BasicValue>[] frames = runAnalyzer(analyzer, internalClassName, node);
Set<BoxedBasicValue> valuesToOptimize = filterSafeToRemoveValues(interpreter.getCandidatesBoxedValues());
RedundantBoxedValuesCollection valuesToOptimize = interpreter.getCandidatesBoxedValues();
if (!valuesToOptimize.isEmpty()) {
findValuesClashingWithVariables(node, frames);
valuesToOptimize = filterSafeToRemoveValues(valuesToOptimize);
// has side effect on valuesToOptimize and frames, containing BoxedBasicValues that are unsafe to remove
removeValuesClashingWithVariables(valuesToOptimize, node, frames);
adaptLocalVariableTableForBoxedValues(node, frames);
@@ -61,16 +58,6 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
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) {
for (LocalVariableNode localVariableNode : node.localVariables) {
if (Type.getType(localVariableNode.desc).getSort() != Type.OBJECT) {
@@ -107,16 +94,20 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
}
}
private static void findValuesClashingWithVariables(
@NotNull MethodNode node, @NotNull Frame<BasicValue>[] frames
private static void removeValuesClashingWithVariables(
@NotNull RedundantBoxedValuesCollection values,
@NotNull MethodNode node,
@NotNull Frame<BasicValue>[] frames
) {
while (findValuesClashingWithVariablesPass(node, frames)) {
while (removeValuesClashingWithVariablesPass(values, node, frames)) {
// do nothing
}
}
private static boolean findValuesClashingWithVariablesPass(
@NotNull MethodNode node, @NotNull Frame<BasicValue>[] frames
private static boolean removeValuesClashingWithVariablesPass(
@NotNull RedundantBoxedValuesCollection values,
@NotNull MethodNode node,
@NotNull Frame<BasicValue>[] frames
) {
InsnList insnList = node.instructions;
boolean needToRepeat = false;
@@ -131,7 +122,7 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
int to = insnList.indexOf(localVariableNode.end) - 1;
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(
@NotNull InsnList insnList,
@NotNull Frame<BasicValue>[] frames,
@NotNull RedundantBoxedValuesCollection values,
int from, int to, int varIndex
) {
boolean wasChanges = false;
@@ -200,7 +192,7 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
}
wasChanges |= true;
((BoxedBasicValue) top).propagateRemovingAsUnsafe();
values.remove((BoxedBasicValue) top);
}
}
@@ -208,7 +200,7 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
}
@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>();
for (BoxedBasicValue value : values) {
if (value.getPrimitiveType().getSize() == 2) {
@@ -247,7 +239,7 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
}
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);