Refactoring: extracted specific logic into RedundantBoxedValuesCollection class
This commit is contained in:
committed by
Alexander Udalov
parent
cb3eef4b86
commit
0f0d07c9fe
+7
-21
@@ -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() {
|
||||||
|
|||||||
+65
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
+8
-11
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-25
@@ -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);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user