dealing with ranges
This commit is contained in:
committed by
Alexander Udalov
parent
ee87b11723
commit
ed445f6488
+21
-2
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package org.jetbrains.jet.codegen.optimization.boxing;
|
package org.jetbrains.jet.codegen.optimization.boxing;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.codegen.AsmUtil;
|
import org.jetbrains.jet.codegen.AsmUtil;
|
||||||
import org.jetbrains.org.objectweb.asm.Type;
|
import org.jetbrains.org.objectweb.asm.Type;
|
||||||
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode;
|
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode;
|
||||||
@@ -28,15 +30,18 @@ import java.util.Set;
|
|||||||
|
|
||||||
public class BoxedBasicValue extends BasicValue {
|
public class BoxedBasicValue extends BasicValue {
|
||||||
private final Set<AbstractInsnNode> associatedInsns = new HashSet<AbstractInsnNode>();
|
private final Set<AbstractInsnNode> associatedInsns = new HashSet<AbstractInsnNode>();
|
||||||
|
private final AbstractInsnNode boxingInsn;
|
||||||
private final Set<Integer> associatedVariables = new HashSet<Integer>();
|
private final Set<Integer> associatedVariables = new HashSet<Integer>();
|
||||||
private final Set<BoxedBasicValue> mergedWith = new HashSet<BoxedBasicValue>();
|
private final Set<BoxedBasicValue> mergedWith = new HashSet<BoxedBasicValue>();
|
||||||
private final Type primitiveType;
|
private final Type primitiveType;
|
||||||
|
private final RangeIteratorBasicValue numberIterator;
|
||||||
private boolean isSafeToRemove = true;
|
private boolean isSafeToRemove = true;
|
||||||
|
|
||||||
public BoxedBasicValue(Type boxedType, AbstractInsnNode insnNode) {
|
public BoxedBasicValue(Type boxedType, AbstractInsnNode boxingInsn, @Nullable RangeIteratorBasicValue numberIterator) {
|
||||||
super(boxedType);
|
super(boxedType);
|
||||||
this.primitiveType = AsmUtil.unboxType(boxedType);
|
this.primitiveType = AsmUtil.unboxType(boxedType);
|
||||||
associatedInsns.add(insnNode);
|
this.boxingInsn = boxingInsn;
|
||||||
|
this.numberIterator = numberIterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -111,4 +116,18 @@ public class BoxedBasicValue extends BasicValue {
|
|||||||
public boolean isDoubleSize() {
|
public boolean isDoubleSize() {
|
||||||
return getPrimitiveType().getSize() == 2;
|
return getPrimitiveType().getSize() == 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public AbstractInsnNode getBoxingInsn() {
|
||||||
|
return boxingInsn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFromNumberIterator() {
|
||||||
|
return numberIterator != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public RangeIteratorBasicValue getNumberIterator() {
|
||||||
|
return numberIterator;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+86
-22
@@ -35,6 +35,26 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class BoxingInterpreter extends OptimizationBasicInterpreter {
|
public class BoxingInterpreter extends OptimizationBasicInterpreter {
|
||||||
|
private static boolean isProgressionClass(String internalName) {
|
||||||
|
return internalName.startsWith("kotlin/") && (
|
||||||
|
internalName.endsWith("Progression") ||
|
||||||
|
internalName.endsWith("Range")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* e.g. for "kotlin/IntRange" it returns "Int"
|
||||||
|
*
|
||||||
|
* @param progressionClassInternalName
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static String getValuesTypePartOfProgressionClass(String progressionClassInternalName) {
|
||||||
|
progressionClassInternalName = progressionClassInternalName.substring("kotlin/".length());
|
||||||
|
|
||||||
|
int cutAtTheEnd = (progressionClassInternalName.endsWith("Progression")) ? "Progression".length() : "Range".length();
|
||||||
|
return progressionClassInternalName.substring(0, progressionClassInternalName.length() - cutAtTheEnd);
|
||||||
|
}
|
||||||
|
|
||||||
private static final ImmutableSet<String> wrappersClassNames;
|
private static final ImmutableSet<String> wrappersClassNames;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
@@ -47,13 +67,6 @@ public class BoxingInterpreter extends OptimizationBasicInterpreter {
|
|||||||
wrappersClassNames = wrappersClassesBuilder.build();
|
wrappersClassNames = wrappersClassesBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Map<Integer, BoxedBasicValue> boxingPlaces = new HashMap<Integer, BoxedBasicValue>();
|
|
||||||
private final InsnList insnList;
|
|
||||||
|
|
||||||
BoxingInterpreter(InsnList insnList) {
|
|
||||||
this.insnList = insnList;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isWrapperClassName(@NotNull String owner) {
|
private static boolean isWrapperClassName(@NotNull String owner) {
|
||||||
return wrappersClassNames.contains(owner);
|
return wrappersClassNames.contains(owner);
|
||||||
}
|
}
|
||||||
@@ -86,27 +99,70 @@ public class BoxingInterpreter extends OptimizationBasicInterpreter {
|
|||||||
return isWrapperClassName(methodInsnNode.owner) && methodInsnNode.name.equals("valueOf");
|
return isWrapperClassName(methodInsnNode.owner) && methodInsnNode.name.equals("valueOf");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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()) &&
|
||||||
|
((MethodInsnNode) insn).name.equals("iterator"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isNextMethodCallOfProgressionIterator(
|
||||||
|
@NotNull AbstractInsnNode insn, @NotNull List<? extends BasicValue> values
|
||||||
|
) {
|
||||||
|
return (insn.getOpcode() == Opcodes.INVOKEINTERFACE &&
|
||||||
|
values.get(0) instanceof RangeIteratorBasicValue &&
|
||||||
|
((MethodInsnNode) insn).name.equals("next"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Map<Integer, BoxedBasicValue> boxingPlaces = new HashMap<Integer, BoxedBasicValue>();
|
||||||
|
private final InsnList insnList;
|
||||||
|
|
||||||
|
BoxingInterpreter(InsnList insnList) {
|
||||||
|
this.insnList = insnList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private BoxedBasicValue createNewBoxing(
|
||||||
|
@NotNull AbstractInsnNode insn, @NotNull Type type, @Nullable RangeIteratorBasicValue numberIterator
|
||||||
|
) {
|
||||||
|
int index = insnList.indexOf(insn);
|
||||||
|
if (!boxingPlaces.containsKey(index)) {
|
||||||
|
BoxedBasicValue boxedBasicValue = new BoxedBasicValue(type, insn, numberIterator);
|
||||||
|
onNewBoxedValue(boxedBasicValue);
|
||||||
|
boxingPlaces.put(index, boxedBasicValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
return boxingPlaces.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
public BasicValue naryOperation(@NotNull AbstractInsnNode insn, @NotNull List<? extends BasicValue> values) throws AnalyzerException {
|
public BasicValue naryOperation(@NotNull AbstractInsnNode insn, @NotNull List<? extends BasicValue> values) throws AnalyzerException {
|
||||||
BasicValue value = super.naryOperation(insn, values);
|
BasicValue value = super.naryOperation(insn, values);
|
||||||
|
|
||||||
if (isBoxing(insn)) {
|
if (isBoxing(insn)) {
|
||||||
int index = insnList.indexOf(insn);
|
return createNewBoxing(insn, value.getType(), null);
|
||||||
if (!boxingPlaces.containsKey(index)) {
|
|
||||||
BoxedBasicValue boxedBasicValue = new BoxedBasicValue(value.getType(), insn);
|
|
||||||
onNewBoxedValue(boxedBasicValue);
|
|
||||||
boxingPlaces.put(index, boxedBasicValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
return boxingPlaces.get(index);
|
|
||||||
}
|
}
|
||||||
else if (isUnboxing(insn) &&
|
else if (isUnboxing(insn) &&
|
||||||
values.get(0) instanceof BoxedBasicValue &&
|
values.get(0) instanceof BoxedBasicValue &&
|
||||||
value.getType().equals(((BoxedBasicValue) values.get(0)).getPrimitiveType())) {
|
value.getType().equals(((BoxedBasicValue) values.get(0)).getPrimitiveType())) {
|
||||||
|
|
||||||
onUnboxing((BoxedBasicValue) values.get(0), insn);
|
onUnboxing((BoxedBasicValue) values.get(0), insn);
|
||||||
}
|
}
|
||||||
|
else if (isIteratorMethodCallOfProgression(insn, values)) {
|
||||||
|
return new RangeIteratorBasicValue(
|
||||||
|
getValuesTypePartOfProgressionClass(values.get(0).getType().getInternalName())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if (isNextMethodCallOfProgressionIterator(insn, values)) {
|
||||||
|
RangeIteratorBasicValue numberIterator = (RangeIteratorBasicValue) values.get(0);
|
||||||
|
return createNewBoxing(
|
||||||
|
insn,
|
||||||
|
AsmUtil.boxType(numberIterator.getValuesPrimitiveType()),
|
||||||
|
numberIterator
|
||||||
|
);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
for (BasicValue arg : values) {
|
for (BasicValue arg : values) {
|
||||||
if (arg instanceof BoxedBasicValue) {
|
if (arg instanceof BoxedBasicValue) {
|
||||||
@@ -118,10 +174,15 @@ public class BoxingInterpreter extends OptimizationBasicInterpreter {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isExactValue(@NotNull BasicValue value) {
|
||||||
|
return value instanceof RangeIteratorBasicValue ||
|
||||||
|
value instanceof BoxedBasicValue ||
|
||||||
|
(value.getType() != null && isProgressionClass(value.getType().getInternalName()));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
|
||||||
public BasicValue unaryOperation(@NotNull AbstractInsnNode insn, @NotNull BasicValue value) throws AnalyzerException {
|
public BasicValue unaryOperation(@NotNull AbstractInsnNode insn, @NotNull BasicValue value) throws AnalyzerException {
|
||||||
if (insn.getOpcode() == Opcodes.CHECKCAST && value instanceof BoxedBasicValue) {
|
if (insn.getOpcode() == Opcodes.CHECKCAST && isExactValue(value)) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,16 +193,16 @@ public class BoxingInterpreter extends OptimizationBasicInterpreter {
|
|||||||
@NotNull
|
@NotNull
|
||||||
public BasicValue merge(@NotNull BasicValue v, @NotNull BasicValue w) {
|
public BasicValue merge(@NotNull BasicValue v, @NotNull BasicValue w) {
|
||||||
if (v instanceof BoxedBasicValue && ((BoxedBasicValue) v).typeEquals(w)) {
|
if (v instanceof BoxedBasicValue && ((BoxedBasicValue) v).typeEquals(w)) {
|
||||||
((BoxedBasicValue) v).mergeWith((BoxedBasicValue) w);
|
onMergeSuccess((BoxedBasicValue) v, (BoxedBasicValue) w);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (v instanceof BoxedBasicValue) {
|
if (v instanceof BoxedBasicValue && w != BasicValue.UNINITIALIZED_VALUE) {
|
||||||
onMergeFail((BoxedBasicValue) v);
|
onMergeFail((BoxedBasicValue) v);
|
||||||
v = new BasicValue(v.getType());
|
v = new BasicValue(v.getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (w instanceof BoxedBasicValue) {
|
if (w instanceof BoxedBasicValue && v != BasicValue.UNINITIALIZED_VALUE) {
|
||||||
onMergeFail((BoxedBasicValue) w);
|
onMergeFail((BoxedBasicValue) w);
|
||||||
w = new BasicValue(w.getType());
|
w = new BasicValue(w.getType());
|
||||||
}
|
}
|
||||||
@@ -149,7 +210,6 @@ public class BoxingInterpreter extends OptimizationBasicInterpreter {
|
|||||||
return super.merge(v, w);
|
return super.merge(v, w);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected void onNewBoxedValue(@NotNull BoxedBasicValue value) {
|
protected void onNewBoxedValue(@NotNull BoxedBasicValue value) {
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -165,4 +225,8 @@ public class BoxingInterpreter extends OptimizationBasicInterpreter {
|
|||||||
protected void onMergeFail(@NotNull BoxedBasicValue value) {
|
protected void onMergeFail(@NotNull BoxedBasicValue value) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void onMergeSuccess(@NotNull BoxedBasicValue v, @NotNull BoxedBasicValue w) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+89
@@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* 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 org.jetbrains.org.objectweb.asm.Type;
|
||||||
|
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue;
|
||||||
|
|
||||||
|
public class RangeIteratorBasicValue extends BasicValue {
|
||||||
|
private static Type getValuesType(@NotNull String valuesTypeName) {
|
||||||
|
if (valuesTypeName.equals("Byte")) {
|
||||||
|
return Type.BYTE_TYPE;
|
||||||
|
}
|
||||||
|
if (valuesTypeName.equals("Char")) {
|
||||||
|
return Type.CHAR_TYPE;
|
||||||
|
}
|
||||||
|
if (valuesTypeName.equals("Short")) {
|
||||||
|
return Type.SHORT_TYPE;
|
||||||
|
}
|
||||||
|
if (valuesTypeName.equals("Int")) {
|
||||||
|
return Type.INT_TYPE;
|
||||||
|
}
|
||||||
|
if (valuesTypeName.equals("Long")) {
|
||||||
|
return Type.LONG_TYPE;
|
||||||
|
}
|
||||||
|
if (valuesTypeName.equals("Float")) {
|
||||||
|
return Type.FLOAT_TYPE;
|
||||||
|
}
|
||||||
|
if (valuesTypeName.equals("Double")) {
|
||||||
|
return Type.DOUBLE_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new RuntimeException("Unexpected type " + valuesTypeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Type valuesPrimitiveType;
|
||||||
|
private final String valuesPrimitiveTypeName;
|
||||||
|
|
||||||
|
public RangeIteratorBasicValue(@NotNull String valuesPrimitiveTypeName) {
|
||||||
|
super(Type.getObjectType("kotlin/" + valuesPrimitiveTypeName + "Iterator"));
|
||||||
|
this.valuesPrimitiveType = getValuesType(valuesPrimitiveTypeName);
|
||||||
|
this.valuesPrimitiveTypeName = valuesPrimitiveTypeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type getValuesPrimitiveType() {
|
||||||
|
return valuesPrimitiveType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValuesPrimitiveTypeName() {
|
||||||
|
return valuesPrimitiveTypeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
if (!super.equals(o)) return false;
|
||||||
|
|
||||||
|
RangeIteratorBasicValue value = (RangeIteratorBasicValue) o;
|
||||||
|
|
||||||
|
if (!valuesPrimitiveType.equals(value.valuesPrimitiveType)) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public String getNextMethodName() {
|
||||||
|
return "next" + getValuesPrimitiveTypeName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public String getNextMethodDesc() {
|
||||||
|
return "()" + getValuesPrimitiveType().getDescriptor();
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
@@ -138,6 +138,13 @@ class RedundantBoxingInterpreter extends BoxingInterpreter {
|
|||||||
markValueAsDirty(v);
|
markValueAsDirty(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onMergeSuccess(
|
||||||
|
@NotNull BoxedBasicValue v, @NotNull BoxedBasicValue w
|
||||||
|
) {
|
||||||
|
v.mergeWith(w);
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public Set<BoxedBasicValue> getCandidatesBoxedValues() {
|
public Set<BoxedBasicValue> getCandidatesBoxedValues() {
|
||||||
return candidatesBoxedValues;
|
return candidatesBoxedValues;
|
||||||
|
|||||||
+32
-2
@@ -50,7 +50,7 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
|
|||||||
|
|
||||||
adaptLocalVariableTableForBoxedValues(node, frames);
|
adaptLocalVariableTableForBoxedValues(node, frames);
|
||||||
|
|
||||||
int[] remapping = variablesRemapping(valuesToOptimize, node);
|
int[] remapping = buildVariablesRemapping(valuesToOptimize, node);
|
||||||
applyVariablesRemapping(node, remapping);
|
applyVariablesRemapping(node, remapping);
|
||||||
|
|
||||||
adaptInstructionsForBoxedValues(node, frames, valuesToOptimize);
|
adaptInstructionsForBoxedValues(node, frames, valuesToOptimize);
|
||||||
@@ -206,7 +206,7 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static int[] variablesRemapping(@NotNull Iterable<BoxedBasicValue> values, @NotNull MethodNode node) {
|
private static int[] buildVariablesRemapping(@NotNull Iterable<BoxedBasicValue> values, @NotNull MethodNode node) {
|
||||||
Set<Integer> longTypesVars = new HashSet<Integer>();
|
Set<Integer> longTypesVars = new HashSet<Integer>();
|
||||||
for (BoxedBasicValue value : values) {
|
for (BoxedBasicValue value : values) {
|
||||||
if (value.getPrimitiveType().getSize() == 2) {
|
if (value.getPrimitiveType().getSize() == 2) {
|
||||||
@@ -271,11 +271,41 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void adaptInstructionsForBoxedValue(@NotNull MethodNode node, @NotNull BoxedBasicValue value) {
|
private static void adaptInstructionsForBoxedValue(@NotNull MethodNode node, @NotNull BoxedBasicValue value) {
|
||||||
|
adaptBoxingInstruction(node, value);
|
||||||
|
|
||||||
for (AbstractInsnNode insn : value.getAssociatedInsns()) {
|
for (AbstractInsnNode insn : value.getAssociatedInsns()) {
|
||||||
adaptInstruction(node, insn, value);
|
adaptInstruction(node, insn, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void adaptBoxingInstruction(@NotNull MethodNode node, @NotNull BoxedBasicValue value) {
|
||||||
|
if (!value.isFromNumberIterator()) {
|
||||||
|
node.instructions.remove(value.getBoxingInsn());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RangeIteratorBasicValue iterator = value.getNumberIterator();
|
||||||
|
assert iterator != null : "iterator should not be null because isFromNumberIterator returns true";
|
||||||
|
|
||||||
|
//add checkcast to kotlin/<T>Iterator before next() call
|
||||||
|
node.instructions.insertBefore(
|
||||||
|
value.getBoxingInsn(),
|
||||||
|
new TypeInsnNode(Opcodes.CHECKCAST, iterator.getType().getInternalName())
|
||||||
|
);
|
||||||
|
|
||||||
|
//invoke concrete method (kotlin/<T>iteraror.next<T>())
|
||||||
|
node.instructions.set(
|
||||||
|
value.getBoxingInsn(),
|
||||||
|
new MethodInsnNode(
|
||||||
|
Opcodes.INVOKEVIRTUAL,
|
||||||
|
iterator.getType().getInternalName(),
|
||||||
|
iterator.getNextMethodName(),
|
||||||
|
iterator.getNextMethodDesc(),
|
||||||
|
false
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void adaptInstruction(
|
private static void adaptInstruction(
|
||||||
@NotNull MethodNode node, @NotNull AbstractInsnNode insn, @NotNull BoxedBasicValue value
|
@NotNull MethodNode node, @NotNull AbstractInsnNode insn, @NotNull BoxedBasicValue value
|
||||||
) {
|
) {
|
||||||
|
|||||||
Reference in New Issue
Block a user