Search in sources :

Example 1 with BasicValue

use of org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue in project kotlin by JetBrains.

the class RedundantBoxingMethodTransformer method getValuesStoredOrLoadedToVariable.

@NotNull
private static List<BasicValue> getValuesStoredOrLoadedToVariable(@NotNull LocalVariableNode localVariableNode, @NotNull MethodNode node, @NotNull Frame<BasicValue>[] frames) {
    List<BasicValue> values = new ArrayList<BasicValue>();
    InsnList insnList = node.instructions;
    int from = insnList.indexOf(localVariableNode.start) + 1;
    int to = insnList.indexOf(localVariableNode.end) - 1;
    Frame<BasicValue> frameForFromInstr = frames[from];
    if (frameForFromInstr != null) {
        BasicValue localVarValue = frameForFromInstr.getLocal(localVariableNode.index);
        if (localVarValue != null) {
            values.add(localVarValue);
        }
    }
    for (int i = from; i <= to; i++) {
        if (i < 0 || i >= insnList.size())
            continue;
        AbstractInsnNode insn = insnList.get(i);
        if ((insn.getOpcode() == Opcodes.ASTORE || insn.getOpcode() == Opcodes.ALOAD) && ((VarInsnNode) insn).var == localVariableNode.index) {
            if (frames[i] == null) {
                //unreachable code
                continue;
            }
            if (insn.getOpcode() == Opcodes.ASTORE) {
                values.add(frames[i].getStack(frames[i].getStackSize() - 1));
            } else {
                values.add(frames[i].getLocal(((VarInsnNode) insn).var));
            }
        }
    }
    return values;
}
Also used : StrictBasicValue(org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue) BasicValue(org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue) NotNull(org.jetbrains.annotations.NotNull)

Example 2 with BasicValue

use of org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue in project kotlin by JetBrains.

the class RedundantBoxingMethodTransformer method adaptLocalVariableTableForBoxedValues.

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 instanceof BoxedBasicValue))
                continue;
            BoxedValueDescriptor descriptor = ((BoxedBasicValue) value).getDescriptor();
            if (!descriptor.isSafeToRemove())
                continue;
            localVariableNode.desc = descriptor.getUnboxedType().getDescriptor();
        }
    }
}
Also used : StrictBasicValue(org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue) BasicValue(org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue)

Example 3 with BasicValue

use of org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue in project kotlin by JetBrains.

the class RedundantBoxingMethodTransformer method removeValuesClashingWithVariablesPass.

private static boolean removeValuesClashingWithVariablesPass(@NotNull RedundantBoxedValuesCollection values, @NotNull MethodNode node, @NotNull Frame<BasicValue>[] frames) {
    boolean needToRepeat = false;
    for (LocalVariableNode localVariableNode : node.localVariables) {
        if (Type.getType(localVariableNode.desc).getSort() != Type.OBJECT) {
            continue;
        }
        List<BasicValue> variableValues = getValuesStoredOrLoadedToVariable(localVariableNode, node, frames);
        Collection<BasicValue> boxed = CollectionsKt.filter(variableValues, new Function1<BasicValue, Boolean>() {

            @Override
            public Boolean invoke(BasicValue value) {
                return value instanceof BoxedBasicValue;
            }
        });
        if (boxed.isEmpty())
            continue;
        BoxedValueDescriptor firstBoxed = ((BoxedBasicValue) boxed.iterator().next()).getDescriptor();
        if (isUnsafeToRemoveBoxingForConnectedValues(variableValues, firstBoxed.getUnboxedType())) {
            for (BasicValue value : variableValues) {
                if (!(value instanceof BoxedBasicValue))
                    continue;
                BoxedValueDescriptor descriptor = ((BoxedBasicValue) value).getDescriptor();
                if (descriptor.isSafeToRemove()) {
                    values.remove(descriptor);
                    needToRepeat = true;
                }
            }
        }
    }
    return needToRepeat;
}
Also used : StrictBasicValue(org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue) BasicValue(org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue)

Example 4 with BasicValue

use of org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue in project kotlin by JetBrains.

the class RedundantBoxingMethodTransformer method interpretPopInstructionsForBoxedValues.

private static void interpretPopInstructionsForBoxedValues(@NotNull RedundantBoxingInterpreter interpreter, @NotNull MethodNode node, @NotNull Frame<BasicValue>[] frames) {
    for (int i = 0; i < node.instructions.size(); i++) {
        AbstractInsnNode insn = node.instructions.get(i);
        if ((insn.getOpcode() != Opcodes.POP && insn.getOpcode() != Opcodes.POP2) || frames[i] == null) {
            continue;
        }
        BasicValue top = frames[i].getStack(frames[i].getStackSize() - 1);
        interpreter.processPopInstruction(insn, top);
        if (top.getSize() == 1 && insn.getOpcode() == Opcodes.POP2) {
            interpreter.processPopInstruction(insn, frames[i].getStack(frames[i].getStackSize() - 2));
        }
    }
}
Also used : StrictBasicValue(org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue) BasicValue(org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue)

Example 5 with BasicValue

use of org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue in project intellij-community by JetBrains.

the class NegationInterpreter method naryOperation.

@Override
public BasicValue naryOperation(AbstractInsnNode insn, List<? extends BasicValue> values) throws AnalyzerException {
    int opCode = insn.getOpcode();
    int shift = opCode == INVOKESTATIC ? 0 : 1;
    int origin = insnIndex(insn);
    switch(opCode) {
        case INVOKESPECIAL:
        case INVOKEINTERFACE:
        case INVOKEVIRTUAL:
            BasicValue receiver = values.get(0);
            if (receiver instanceof NthParamValue) {
                dereferencedParams[((NthParamValue) receiver).n] = true;
            }
            if (receiver instanceof Trackable) {
                dereferencedValues[((Trackable) receiver).getOriginInsnIndex()] = true;
            }
        default:
    }
    switch(opCode) {
        case INVOKESTATIC:
        case INVOKESPECIAL:
        case INVOKEVIRTUAL:
        case INVOKEINTERFACE:
            boolean stable = opCode == INVOKESTATIC || opCode == INVOKESPECIAL;
            MethodInsnNode mNode = (MethodInsnNode) insn;
            Method method = new Method(mNode.owner, mNode.name, mNode.desc);
            Type retType = Type.getReturnType(mNode.desc);
            for (int i = shift; i < values.size(); i++) {
                if (values.get(i) instanceof NthParamValue) {
                    int n = ((NthParamValue) values.get(i)).n;
                    if (opCode == INVOKEINTERFACE) {
                        notNullableParams[n] = true;
                    } else {
                        Set<ParamKey> npKeys = parameterFlow[n];
                        if (npKeys == null) {
                            npKeys = new HashSet<>();
                            parameterFlow[n] = npKeys;
                        }
                        npKeys.add(new ParamKey(method, i - shift, stable));
                    }
                }
            }
            BasicValue receiver = null;
            if (shift == 1) {
                receiver = values.remove(0);
            }
            boolean thisCall = (opCode == INVOKEINTERFACE || opCode == INVOKEVIRTUAL) && receiver == ThisValue;
            return new TrackableCallValue(origin, retType, method, values, stable, thisCall);
        case MULTIANEWARRAY:
            return new NotNullValue(super.naryOperation(insn, values).getType());
        default:
    }
    return track(origin, super.naryOperation(insn, values));
}
Also used : BasicValue(org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue) Type(org.jetbrains.org.objectweb.asm.Type)

Aggregations

BasicValue (org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue)17 Frame (org.jetbrains.org.objectweb.asm.tree.analysis.Frame)5 StrictBasicValue (org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue)4 Type (org.jetbrains.org.objectweb.asm.Type)3 In (com.intellij.codeInspection.bytecodeAnalysis.Direction.In)2 Edge (com.intellij.codeInspection.bytecodeAnalysis.asm.ControlFlowGraph.Edge)2 HashSet (java.util.HashSet)2 InOut (com.intellij.codeInspection.bytecodeAnalysis.Direction.InOut)1 AnalyzerExt (com.intellij.codeInspection.bytecodeAnalysis.asm.AnalyzerExt)1 LiteAnalyzerExt (com.intellij.codeInspection.bytecodeAnalysis.asm.LiteAnalyzerExt)1 SingletonSet (com.intellij.util.SingletonSet)1 HashSet (com.intellij.util.containers.HashSet)1 PrintWriter (java.io.PrintWriter)1 Set (java.util.Set)1 NotNull (org.jetbrains.annotations.NotNull)1 ClassReader (org.jetbrains.org.objectweb.asm.ClassReader)1 AbstractInsnNode (org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode)1 ClassNode (org.jetbrains.org.objectweb.asm.tree.ClassNode)1 MethodInsnNode (org.jetbrains.org.objectweb.asm.tree.MethodInsnNode)1 MethodNode (org.jetbrains.org.objectweb.asm.tree.MethodNode)1