Refactoring: reordering methods to usage places
This commit is contained in:
committed by
Alexander Udalov
parent
ebfd257408
commit
69d8d07a05
+78
-78
@@ -47,80 +47,6 @@ public class BoxingInterpreter extends OptimizationBasicInterpreter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static boolean isProgressionClass(String internalClassName) {
|
|
||||||
return RangeCodegenUtil.isRangeOrProgression(buildFqNameByInternal(internalClassName));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* e.g. for "kotlin/IntRange" it returns "Int"
|
|
||||||
*
|
|
||||||
* @param progressionClassInternalName
|
|
||||||
* @return
|
|
||||||
* @throws java.lang.AssertionError if progressionClassInternalName is not progression class internal name
|
|
||||||
*/
|
|
||||||
@NotNull
|
|
||||||
private static String getValuesTypeOfProgressionClass(String progressionClassInternalName) {
|
|
||||||
PrimitiveType type = RangeCodegenUtil.getPrimitiveRangeOrProgressionElementType(
|
|
||||||
buildFqNameByInternal(progressionClassInternalName)
|
|
||||||
);
|
|
||||||
|
|
||||||
assert type != null : "type should be not null";
|
|
||||||
|
|
||||||
return type.getTypeName().asString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isWrapperClassName(@NotNull String internalClassName) {
|
|
||||||
return JvmPrimitiveType.isWrapperClassName(
|
|
||||||
buildFqNameByInternal(internalClassName)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private static FqName buildFqNameByInternal(@NotNull String internalClassName) {
|
|
||||||
return new FqName(Type.getObjectType(internalClassName).getClassName());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isWrapperClassNameOrNumber(@NotNull String internalClassName) {
|
|
||||||
return isWrapperClassName(internalClassName) || internalClassName.equals(Type.getInternalName(Number.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isUnboxingMethodName(@NotNull String name) {
|
|
||||||
return UNBOXING_METHOD_NAMES.contains(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isUnboxing(@NotNull AbstractInsnNode insn) {
|
|
||||||
if (insn.getOpcode() != Opcodes.INVOKEVIRTUAL) return false;
|
|
||||||
|
|
||||||
MethodInsnNode methodInsn = (MethodInsnNode) insn;
|
|
||||||
|
|
||||||
return isWrapperClassNameOrNumber(methodInsn.owner) && isUnboxingMethodName(methodInsn.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isBoxing(@NotNull AbstractInsnNode insn) {
|
|
||||||
if (insn.getOpcode() != Opcodes.INVOKESTATIC) return false;
|
|
||||||
|
|
||||||
MethodInsnNode methodInsnNode = (MethodInsnNode) insn;
|
|
||||||
|
|
||||||
return isWrapperClassName(methodInsnNode.owner) && "valueOf".equals(methodInsnNode.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isIteratorMethodCallOfProgression(
|
|
||||||
@NotNull AbstractInsnNode insn, @NotNull List<? extends BasicValue> values
|
|
||||||
) {
|
|
||||||
return (insn.getOpcode() == Opcodes.INVOKEINTERFACE &&
|
|
||||||
values.get(0).getType() != null &&
|
|
||||||
isProgressionClass(values.get(0).getType().getInternalName()) &&
|
|
||||||
"iterator".equals(((MethodInsnNode) insn).name));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isNextMethodCallOfProgressionIterator(
|
|
||||||
@NotNull AbstractInsnNode insn, @NotNull List<? extends BasicValue> values
|
|
||||||
) {
|
|
||||||
return (insn.getOpcode() == Opcodes.INVOKEINTERFACE &&
|
|
||||||
values.get(0) instanceof ProgressionIteratorBasicValue &&
|
|
||||||
"next".equals(((MethodInsnNode) insn).name));
|
|
||||||
}
|
|
||||||
|
|
||||||
private final Map<Integer, BoxedBasicValue> boxingPlaces = new HashMap<Integer, BoxedBasicValue>();
|
private final Map<Integer, BoxedBasicValue> boxingPlaces = new HashMap<Integer, BoxedBasicValue>();
|
||||||
private final InsnList insnList;
|
private final InsnList insnList;
|
||||||
|
|
||||||
@@ -188,10 +114,78 @@ public class BoxingInterpreter extends OptimizationBasicInterpreter {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isExactValue(@NotNull BasicValue value) {
|
private static boolean isWrapperClassNameOrNumber(@NotNull String internalClassName) {
|
||||||
return value instanceof ProgressionIteratorBasicValue ||
|
return isWrapperClassName(internalClassName) || internalClassName.equals(Type.getInternalName(Number.class));
|
||||||
value instanceof BoxedBasicValue ||
|
}
|
||||||
(value.getType() != null && isProgressionClass(value.getType().getInternalName()));
|
|
||||||
|
private static boolean isWrapperClassName(@NotNull String internalClassName) {
|
||||||
|
return JvmPrimitiveType.isWrapperClassName(
|
||||||
|
buildFqNameByInternal(internalClassName)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static FqName buildFqNameByInternal(@NotNull String internalClassName) {
|
||||||
|
return new FqName(Type.getObjectType(internalClassName).getClassName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isUnboxing(@NotNull AbstractInsnNode insn) {
|
||||||
|
if (insn.getOpcode() != Opcodes.INVOKEVIRTUAL) return false;
|
||||||
|
|
||||||
|
MethodInsnNode methodInsn = (MethodInsnNode) insn;
|
||||||
|
|
||||||
|
return isWrapperClassNameOrNumber(methodInsn.owner) && isUnboxingMethodName(methodInsn.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isUnboxingMethodName(@NotNull String name) {
|
||||||
|
return UNBOXING_METHOD_NAMES.contains(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isBoxing(@NotNull AbstractInsnNode insn) {
|
||||||
|
if (insn.getOpcode() != Opcodes.INVOKESTATIC) return false;
|
||||||
|
|
||||||
|
MethodInsnNode methodInsnNode = (MethodInsnNode) insn;
|
||||||
|
|
||||||
|
return isWrapperClassName(methodInsnNode.owner) && "valueOf".equals(methodInsnNode.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isNextMethodCallOfProgressionIterator(
|
||||||
|
@NotNull AbstractInsnNode insn, @NotNull List<? extends BasicValue> values
|
||||||
|
) {
|
||||||
|
return (insn.getOpcode() == Opcodes.INVOKEINTERFACE &&
|
||||||
|
values.get(0) instanceof ProgressionIteratorBasicValue &&
|
||||||
|
"next".equals(((MethodInsnNode) insn).name));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isIteratorMethodCallOfProgression(
|
||||||
|
@NotNull AbstractInsnNode insn, @NotNull List<? extends BasicValue> values
|
||||||
|
) {
|
||||||
|
return (insn.getOpcode() == Opcodes.INVOKEINTERFACE &&
|
||||||
|
values.get(0).getType() != null &&
|
||||||
|
isProgressionClass(values.get(0).getType().getInternalName()) &&
|
||||||
|
"iterator".equals(((MethodInsnNode) insn).name));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isProgressionClass(String internalClassName) {
|
||||||
|
return RangeCodegenUtil.isRangeOrProgression(buildFqNameByInternal(internalClassName));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* e.g. for "kotlin/IntRange" it returns "Int"
|
||||||
|
*
|
||||||
|
* @param progressionClassInternalName
|
||||||
|
* @return
|
||||||
|
* @throws java.lang.AssertionError if progressionClassInternalName is not progression class internal name
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
private static String getValuesTypeOfProgressionClass(String progressionClassInternalName) {
|
||||||
|
PrimitiveType type = RangeCodegenUtil.getPrimitiveRangeOrProgressionElementType(
|
||||||
|
buildFqNameByInternal(progressionClassInternalName)
|
||||||
|
);
|
||||||
|
|
||||||
|
assert type != null : "type should be not null";
|
||||||
|
|
||||||
|
return type.getTypeName().asString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -203,6 +197,12 @@ public class BoxingInterpreter extends OptimizationBasicInterpreter {
|
|||||||
return super.unaryOperation(insn, value);
|
return super.unaryOperation(insn, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isExactValue(@NotNull BasicValue value) {
|
||||||
|
return value instanceof ProgressionIteratorBasicValue ||
|
||||||
|
value instanceof BoxedBasicValue ||
|
||||||
|
(value.getType() != null && isProgressionClass(value.getType().getInternalName()));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
public BasicValue merge(@NotNull BasicValue v, @NotNull BasicValue w) {
|
public BasicValue merge(@NotNull BasicValue v, @NotNull BasicValue w) {
|
||||||
|
|||||||
+21
-21
@@ -47,27 +47,6 @@ class RedundantBoxingInterpreter extends BoxingInterpreter {
|
|||||||
super(insnList);
|
super(insnList);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void markValueAsDirty(@NotNull BoxedBasicValue value) {
|
|
||||||
values.remove(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void addAssociatedInsn(@NotNull BoxedBasicValue value, @NotNull AbstractInsnNode insn) {
|
|
||||||
if (value.isSafeToRemove()) {
|
|
||||||
value.addInsn(insn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void processOperationWithBoxedValue(@Nullable BasicValue value, @NotNull AbstractInsnNode insnNode) {
|
|
||||||
if (value instanceof BoxedBasicValue) {
|
|
||||||
if (UNSAFE_OPERATIONS_OPCODES.contains(insnNode.getOpcode())) {
|
|
||||||
markValueAsDirty((BoxedBasicValue) value);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
addAssociatedInsn((BoxedBasicValue) value, insnNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BasicValue binaryOperation(
|
public BasicValue binaryOperation(
|
||||||
@NotNull AbstractInsnNode insn,
|
@NotNull AbstractInsnNode insn,
|
||||||
@@ -170,6 +149,27 @@ class RedundantBoxingInterpreter extends BoxingInterpreter {
|
|||||||
values.merge(v, w);
|
values.merge(v, w);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void processOperationWithBoxedValue(@Nullable BasicValue value, @NotNull AbstractInsnNode insnNode) {
|
||||||
|
if (value instanceof BoxedBasicValue) {
|
||||||
|
if (UNSAFE_OPERATIONS_OPCODES.contains(insnNode.getOpcode())) {
|
||||||
|
markValueAsDirty((BoxedBasicValue) value);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
addAssociatedInsn((BoxedBasicValue) value, insnNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void markValueAsDirty(@NotNull BoxedBasicValue value) {
|
||||||
|
values.remove(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void addAssociatedInsn(@NotNull BoxedBasicValue value, @NotNull AbstractInsnNode insn) {
|
||||||
|
if (value.isSafeToRemove()) {
|
||||||
|
value.addInsn(insn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public RedundantBoxedValuesCollection getCandidatesBoxedValues() {
|
public RedundantBoxedValuesCollection getCandidatesBoxedValues() {
|
||||||
return values;
|
return values;
|
||||||
|
|||||||
+17
-15
@@ -40,9 +40,11 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
|
|||||||
@Override
|
@Override
|
||||||
public void transform(@NotNull String internalClassName, @NotNull MethodNode node) {
|
public void transform(@NotNull String internalClassName, @NotNull MethodNode node) {
|
||||||
RedundantBoxingInterpreter interpreter = new RedundantBoxingInterpreter(node.instructions);
|
RedundantBoxingInterpreter interpreter = new RedundantBoxingInterpreter(node.instructions);
|
||||||
Analyzer<BasicValue> analyzer = new Analyzer<BasicValue>(interpreter);
|
Frame<BasicValue>[] frames = runAnalyzer(
|
||||||
|
new Analyzer<BasicValue>(interpreter),
|
||||||
|
internalClassName, node
|
||||||
|
);
|
||||||
|
|
||||||
Frame<BasicValue>[] frames = runAnalyzer(analyzer, internalClassName, node);
|
|
||||||
RedundantBoxedValuesCollection valuesToOptimize = interpreter.getCandidatesBoxedValues();
|
RedundantBoxedValuesCollection valuesToOptimize = interpreter.getCandidatesBoxedValues();
|
||||||
|
|
||||||
if (!valuesToOptimize.isEmpty()) {
|
if (!valuesToOptimize.isEmpty()) {
|
||||||
@@ -59,19 +61,6 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
|
|||||||
super.transform(internalClassName, node);
|
super.transform(internalClassName, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void adaptLocalVariableTableForBoxedValues(@NotNull MethodNode node, @NotNull Frame<BasicValue>[] frames) {
|
|
||||||
for (LocalVariableNode localVariableNode : node.localVariables) {
|
|
||||||
if (Type.getType(localVariableNode.desc).getSort() != Type.OBJECT) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (BasicValue value : getValuesStoredOrLoadedToVariable(localVariableNode, node, frames)) {
|
|
||||||
if (value == null || !(value instanceof BoxedBasicValue) || !((BoxedBasicValue) value).isSafeToRemove()) continue;
|
|
||||||
localVariableNode.desc = ((BoxedBasicValue) value).getPrimitiveType().getDescriptor();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void removeValuesClashingWithVariables(
|
private static void removeValuesClashingWithVariables(
|
||||||
@NotNull RedundantBoxedValuesCollection values,
|
@NotNull RedundantBoxedValuesCollection values,
|
||||||
@NotNull MethodNode node,
|
@NotNull MethodNode node,
|
||||||
@@ -128,6 +117,19 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
|
|||||||
return needToRepeat;
|
return needToRepeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void adaptLocalVariableTableForBoxedValues(@NotNull MethodNode node, @NotNull Frame<BasicValue>[] frames) {
|
||||||
|
for (LocalVariableNode localVariableNode : node.localVariables) {
|
||||||
|
if (Type.getType(localVariableNode.desc).getSort() != Type.OBJECT) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (BasicValue value : getValuesStoredOrLoadedToVariable(localVariableNode, node, frames)) {
|
||||||
|
if (value == null || !(value instanceof BoxedBasicValue) || !((BoxedBasicValue) value).isSafeToRemove()) continue;
|
||||||
|
localVariableNode.desc = ((BoxedBasicValue) value).getPrimitiveType().getDescriptor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static List<BasicValue> getValuesStoredOrLoadedToVariable(
|
private static List<BasicValue> getValuesStoredOrLoadedToVariable(
|
||||||
@NotNull LocalVariableNode localVariableNode,
|
@NotNull LocalVariableNode localVariableNode,
|
||||||
|
|||||||
Reference in New Issue
Block a user