Example usage for org.objectweb.asm Opcodes LOOKUPSWITCH

List of usage examples for org.objectweb.asm Opcodes LOOKUPSWITCH

Introduction

In this page you can find the example usage for org.objectweb.asm Opcodes LOOKUPSWITCH.

Prototype

int LOOKUPSWITCH

To view the source code for org.objectweb.asm Opcodes LOOKUPSWITCH.

Click Source Link

Usage

From source file:com.android.tools.lint.checks.ApiDetector.java

License:Apache License

@SuppressWarnings("rawtypes") // ASM API
private static void checkSwitchBlock(ClassContext context, ClassNode classNode, FieldInsnNode field,
        MethodNode method, String name, String owner, int api, int minSdk) {
    // Switch statements on enums are tricky. The compiler will generate a method
    // which returns an array of the enum constants, indexed by their ordinal() values.
    // However, we only want to complain if the code is actually referencing one of
    // the non-available enum fields.
    ///*from  w  w w.ja  va 2s .c o  m*/
    // For the android.graphics.PorterDuff.Mode enum for example, the first few items
    // in the array are populated like this:
    //
    //   L0
    //    ALOAD 0
    //    GETSTATIC android/graphics/PorterDuff$Mode.ADD : Landroid/graphics/PorterDuff$Mode;
    //    INVOKEVIRTUAL android/graphics/PorterDuff$Mode.ordinal ()I
    //    ICONST_1
    //    IASTORE
    //   L1
    //    GOTO L3
    //   L2
    //   FRAME FULL [[I] [java/lang/NoSuchFieldError]
    //    POP
    //   L3
    //   FRAME SAME
    //    ALOAD 0
    //    GETSTATIC android/graphics/PorterDuff$Mode.CLEAR : Landroid/graphics/PorterDuff$Mode;
    //    INVOKEVIRTUAL android/graphics/PorterDuff$Mode.ordinal ()I
    //    ICONST_2
    //    IASTORE
    //    ...
    // So if we for example find that the "ADD" field isn't accessible, since it requires
    // API 11, we need to
    //   (1) First find out what its ordinal number is. We can look at the following
    //       instructions to discover this; it's the "ICONST_1" and "IASTORE" instructions.
    //       (After ICONST_5 it moves on to BIPUSH 6, BIPUSH 7, etc.)
    //   (2) Find the corresponding *usage* of this switch method. For the above enum,
    //       the switch ordinal lookup method will be called
    //         "$SWITCH_TABLE$android$graphics$PorterDuff$Mode" with desc "()[I".
    //       This means we will be looking for an invocation in some other method which looks
    //       like this:
    //         INVOKESTATIC (current class).$SWITCH_TABLE$android$graphics$PorterDuff$Mode ()[I
    //       (obviously, it can be invoked more than once)
    //       Note that it can be used more than once in this class and all sites should be
    //       checked!
    //   (3) Look up the corresponding table switch, which should look something like this:
    //        INVOKESTATIC (current class).$SWITCH_TABLE$android$graphics$PorterDuff$Mode ()[I
    //        ALOAD 0
    //        INVOKEVIRTUAL android/graphics/PorterDuff$Mode.ordinal ()I
    //        IALOAD
    //        LOOKUPSWITCH
    //          2: L1
    //          11: L2
    //          default: L3
    //       Here we need to see if the LOOKUPSWITCH instruction is referencing our target
    //       case. Above we were looking for the "ADD" case which had ordinal 1. Since this
    //       isn't explicitly referenced, we can ignore this field reference.
    AbstractInsnNode next = field.getNext();
    if (next == null || next.getOpcode() != Opcodes.INVOKEVIRTUAL) {
        return;
    }
    next = next.getNext();
    if (next == null) {
        return;
    }
    int ordinal;
    switch (next.getOpcode()) {
    case Opcodes.ICONST_0:
        ordinal = 0;
        break;
    case Opcodes.ICONST_1:
        ordinal = 1;
        break;
    case Opcodes.ICONST_2:
        ordinal = 2;
        break;
    case Opcodes.ICONST_3:
        ordinal = 3;
        break;
    case Opcodes.ICONST_4:
        ordinal = 4;
        break;
    case Opcodes.ICONST_5:
        ordinal = 5;
        break;
    case Opcodes.BIPUSH: {
        IntInsnNode iin = (IntInsnNode) next;
        ordinal = iin.operand;
        break;
    }
    default:
        return;
    }

    // Find usages of this call site
    List methodList = classNode.methods;
    for (Object m : methodList) {
        InsnList nodes = ((MethodNode) m).instructions;
        for (int i = 0, n = nodes.size(); i < n; i++) {
            AbstractInsnNode instruction = nodes.get(i);
            if (instruction.getOpcode() != Opcodes.INVOKESTATIC) {
                continue;
            }
            MethodInsnNode node = (MethodInsnNode) instruction;
            if (node.name.equals(method.name) && node.desc.equals(method.desc)
                    && node.owner.equals(classNode.name)) {
                // Find lookup switch
                AbstractInsnNode target = getNextInstruction(node);
                while (target != null) {
                    if (target.getOpcode() == Opcodes.LOOKUPSWITCH) {
                        LookupSwitchInsnNode lookup = (LookupSwitchInsnNode) target;
                        @SuppressWarnings("unchecked") // ASM API
                        List<Integer> keys = lookup.keys;
                        if (keys != null && keys.contains(ordinal)) {
                            String fqcn = ClassContext.getFqcn(owner) + '#' + name;
                            String message = String.format(
                                    "Enum value requires API level %1$d " + "(current min is %2$d): %3$s", api,
                                    minSdk, fqcn);
                            report(context, message, lookup, (MethodNode) m, name, null,
                                    SearchHints.create(FORWARD).matchJavaSymbol());

                            // Break out of the inner target search only; the switch
                            // statement could be used in other places in this class as
                            // well and we want to report all problematic usages.
                            break;
                        }
                    }
                    target = getNextInstruction(target);
                }
            }
        }
    }
}

From source file:com.gargoylesoftware.js.nashorn.internal.ir.debug.NashornTextifier.java

License:Open Source License

@Override
public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels) {
    final StringBuilder sb = new StringBuilder();
    appendOpcode(sb, Opcodes.LOOKUPSWITCH).append(' ');
    for (int i = 0; i < labels.length; ++i) {
        sb.append(tab3).append(keys[i]).append(": ");
        final String to = appendLabel(sb, labels[i]);
        graph.addEdge(currentBlock, to);
        sb.append('\n');
    }//w  ww .ja  v a 2 s .c  om
    sb.append(tab3).append("default: ");
    final String to = appendLabel(sb, dflt);
    graph.addEdge(currentBlock, to);
    sb.append('\n');
    addText(sb.toString());
}

From source file:com.mebigfatguy.baremetal4j.Sourcifier.java

License:Apache License

public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
    lines.add(/*from   w  w w .jav a  2s .  co  m*/
            "\t\tBCO = " + String.format("%05d", byteOffset) + "; // " + Printer.OPCODES[Opcodes.LOOKUPSWITCH]);
    byteOffset += 1;
}

From source file:com.trigersoft.jaque.expression.ExpressionMethodVisitor.java

License:Apache License

@Override
public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
    throw notLambda(Opcodes.LOOKUPSWITCH);
}

From source file:de.loskutov.bco.asm.CommentedASMifierClassVisitor.java

License:Open Source License

@Override
public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels) {
    addIndex(Opcodes.LOOKUPSWITCH);
    super.visitLookupSwitchInsn(dflt, keys, labels);
}

From source file:de.unisb.cs.st.javaslicer.common.classRepresentation.instructions.LookupSwitchInstruction.java

License:Open Source License

public LookupSwitchInstruction(final ReadMethod readMethod, final int lineNumber,
        final LabelMarker defaultHandler, final IntegerMap<LabelMarker> handlers) {
    super(readMethod, Opcodes.LOOKUPSWITCH, lineNumber);
    this.defaultHandler = defaultHandler;
    this.handlers = handlers;
}

From source file:de.unisb.cs.st.javaslicer.common.classRepresentation.instructions.LookupSwitchInstruction.java

License:Open Source License

private LookupSwitchInstruction(final ReadMethod readMethod, final int lineNumber,
        final LabelMarker defaultHandler, final IntegerMap<LabelMarker> handlers, final int index) {
    super(readMethod, Opcodes.LOOKUPSWITCH, lineNumber, index);
    this.defaultHandler = defaultHandler;
    this.handlers = handlers;
}

From source file:de.unisb.cs.st.javaslicer.common.classRepresentation.instructions.LookupSwitchInstruction2.java

License:Open Source License

public LookupSwitchInstruction2(final ReadMethod readMethod, final int lineNumber, final int defaultHandler,
        final Map<Integer, Integer> handlers) {
    super(readMethod, Opcodes.LOOKUPSWITCH, lineNumber);
    this.defaultHandler = defaultHandler;
    this.handlers = handlers;
}

From source file:de.unisb.cs.st.javaslicer.common.classRepresentation.instructions.LookupSwitchInstruction2.java

License:Open Source License

public LookupSwitchInstruction2(final ReadMethod readMethod, final int lineNumber, final int defaultHandler,
        final Map<Integer, Integer> handlers, final int index) {
    super(readMethod, Opcodes.LOOKUPSWITCH, lineNumber, index);
    this.defaultHandler = defaultHandler;
    this.handlers = handlers;
}

From source file:edu.mit.streamjit.util.bytecode.MethodResolver.java

License:Open Source License

private void interpret(LookupSwitchInsnNode insn, FrameState frame, BBInfo block) {
    assert insn.getOpcode() == Opcodes.LOOKUPSWITCH;
    ConstantFactory cf = module.constants();
    SwitchInst inst = new SwitchInst(frame.stack.pop(), blockByInsn(insn.dflt).block);
    for (int i = 0; i < insn.keys.size(); ++i)
        inst.put(cf.getConstant((Integer) insn.keys.get(i)), blockByInsn((LabelNode) insn.labels.get(i)).block);
    block.block.instructions().add(inst);
}