Search in sources :

Example 1 with IINC

use of org.apache.bcel.generic.IINC in project jop by jop-devel.

the class LoopBounds method transfer.

public ContextMap<CallString, Map<Location, ValueMapping>> transfer(InstructionHandle stmt, FlowEdge edge, ContextMap<CallString, Map<Location, ValueMapping>> input, Interpreter<CallString, Map<Location, ValueMapping>> interpreter, Map<InstructionHandle, ContextMap<CallString, Map<Location, ValueMapping>>> state) {
    Context context = new Context(input.getContext());
    Map<Location, ValueMapping> in = (Map<Location, ValueMapping>) input.get(context.callString);
    ContextMap<CallString, Map<Location, ValueMapping>> retval = new ContextMap<CallString, Map<Location, ValueMapping>>(context, new LinkedHashMap<CallString, Map<Location, ValueMapping>>());
    Instruction instruction = stmt.getInstruction();
    // shortcut for infeasible paths
    if (in == null) {
        context.stackPtr += instruction.produceStack(context.constPool()) - instruction.consumeStack(context.constPool());
        return retval;
    }
    Map<Location, ValueMapping> result = new LinkedHashMap<Location, ValueMapping>();
    retval.put(context.callString, result);
    switch(instruction.getOpcode()) {
        case Constants.ICONST_M1:
        case Constants.ICONST_0:
        case Constants.ICONST_1:
        case Constants.ICONST_2:
        case Constants.ICONST_3:
        case Constants.ICONST_4:
        case Constants.ICONST_5:
        case Constants.BIPUSH:
        case Constants.SIPUSH:
            {
                ConstantPushInstruction instr = (ConstantPushInstruction) instruction;
                result = new LinkedHashMap<Location, ValueMapping>(in);
                retval.put(context.callString, result);
                int value = instr.getValue().intValue();
                result.put(new Location(context.stackPtr), new ValueMapping(value));
            }
            break;
        case Constants.ACONST_NULL:
            result = in;
            retval.put(context.callString, result);
            break;
        case Constants.LDC:
        case Constants.LDC_W:
            {
                LDC instr = (LDC) instruction;
                result = new LinkedHashMap<Location, ValueMapping>(in);
                retval.put(context.callString, result);
                Type type = instr.getType(context.constPool());
                if (type.equals(Type.INT)) {
                    Integer value = (Integer) instr.getValue(context.constPool());
                    result.put(new Location(context.stackPtr), new ValueMapping(value));
                } else if (type.equals(Type.STRING)) {
                    String value = (String) instr.getValue(context.constPool());
                    String name = "char[]";
                    name += "@" + context.method() + ":" + stmt.getPosition();
                    result.put(new Location(name + ".length"), new ValueMapping(value.length()));
                //				System.out.println(name+": \""+value+"\"");				
                }
            }
            break;
        case Constants.LDC2_W:
            result = in;
            retval.put(context.callString, result);
            break;
        case Constants.ISTORE_0:
        case Constants.ISTORE_1:
        case Constants.ISTORE_2:
        case Constants.ISTORE_3:
        case Constants.ISTORE:
            {
                StoreInstruction instr = (StoreInstruction) instruction;
                int index = instr.getIndex();
                for (Location l : in.keySet()) {
                    if (l.stackLoc < context.stackPtr - 1 && l.stackLoc != index) {
                        result.put(l, in.get(l));
                    }
                    if (l.stackLoc == context.stackPtr - 1) {
                        ValueMapping v = new ValueMapping(in.get(l), true);
                        if (in.get(l).source == null || in.get(l).source.stackLoc != index) {
                            v.defscope = ValueMapping.scope;
                        }
                        result.put(new Location(index), v);
                    }
                }
            }
            break;
        case Constants.ASTORE_0:
        case Constants.ASTORE_1:
        case Constants.ASTORE_2:
        case Constants.ASTORE_3:
        case Constants.ASTORE:
            result = in;
            retval.put(context.callString, result);
            break;
        case Constants.LSTORE_0:
        case Constants.LSTORE_1:
        case Constants.LSTORE_2:
        case Constants.LSTORE_3:
        case Constants.LSTORE:
            // drop top entries to avoid clobbering
            filterSet(in, result, context.stackPtr - 2);
            break;
        case Constants.ILOAD_0:
        case Constants.ILOAD_1:
        case Constants.ILOAD_2:
        case Constants.ILOAD_3:
        case Constants.ILOAD:
            {
                LoadInstruction instr = (LoadInstruction) instruction;
                filterSet(in, result, context.stackPtr);
                int index = instr.getIndex();
                for (Location l : in.keySet()) {
                    if (l.stackLoc == index) {
                        ValueMapping m = new ValueMapping(in.get(l), true);
                        m.source = l;
                        result.put(new Location(context.stackPtr), m);
                    }
                }
            }
            break;
        case Constants.ALOAD_0:
        case Constants.ALOAD_1:
        case Constants.ALOAD_2:
        case Constants.ALOAD_3:
        case Constants.ALOAD:
            result = in;
            retval.put(context.callString, result);
            break;
        case Constants.ARRAYLENGTH:
            {
                filterSet(in, result, context.stackPtr - 1);
                DFATool p = interpreter.getDFATool();
                Set<String> receivers = p.getReceivers(stmt, context.callString);
                Location location = new Location(context.stackPtr - 1);
                boolean valid = false;
                if (receivers == null) {
                    System.out.println("no receivers at: " + context.callString.toStringList() + context.method() + stmt);
                } else {
                    for (String arrayName : receivers) {
                        ValueMapping m = in.get(new Location(arrayName + ".length"));
                        if (m != null) {
                            ValueMapping value = new ValueMapping(m, false);
                            value.join(result.get(location));
                            result.put(location, value);
                            valid = true;
                        }
                    }
                }
                if (!valid) {
                    result.put(new Location(context.stackPtr - 1), new ValueMapping());
                }
            }
            break;
        case Constants.PUTFIELD:
            {
                PUTFIELD instr = (PUTFIELD) instruction;
                int fieldSize = instr.getFieldType(context.constPool()).getSize();
                for (Location l : in.keySet()) {
                    if (l.stackLoc >= 0 && l.stackLoc < context.stackPtr - 1 - fieldSize) {
                        result.put(l, in.get(l));
                    }
                }
                //			System.out.println(context.stackPtr+","+fieldSize+": "+result);
                DFATool p = interpreter.getDFATool();
                Set<String> receivers = p.getReceivers(stmt, context.callString);
                if (receivers == null) {
                    warnNoReceiver(context, stmt);
                } else {
                    for (String fieldName : receivers) {
                        String f = fieldName.substring(fieldName.lastIndexOf("."), fieldName.length());
                        String strippedName;
                        if (fieldName.indexOf("@") >= 0) {
                            strippedName = fieldName.split("@")[0] + f;
                        } else {
                            strippedName = fieldName;
                        }
                        if (p.containsField(strippedName)) {
                            for (Location l : in.keySet()) {
                                if (l.stackLoc < 0 && !receivers.contains(l.heapLoc)) {
                                    result.put(l, in.get(l));
                                }
                                if (l.stackLoc == context.stackPtr - 1) {
                                    result.put(new Location(fieldName), new ValueMapping(in.get(l), false));
                                }
                            }
                        }
                    }
                }
            }
            break;
        case Constants.GETFIELD:
            {
                GETFIELD instr = (GETFIELD) instruction;
                filterSet(in, result, context.stackPtr - 1);
                DFATool p = interpreter.getDFATool();
                Set<String> receivers = p.getReceivers(stmt, context.callString);
                Location location = new Location(context.stackPtr - 1);
                boolean valid = false;
                if (receivers == null) {
                    warnNoReceiver(context, stmt);
                } else {
                    for (String fieldName : receivers) {
                        String f = fieldName.substring(fieldName.lastIndexOf("."), fieldName.length());
                        String strippedName;
                        if (fieldName.indexOf("@") >= 0) {
                            strippedName = fieldName.split("@")[0] + f;
                        } else {
                            strippedName = fieldName;
                        }
                        if (p.containsField(strippedName)) {
                            for (Location l : in.keySet()) {
                                if (l.heapLoc.equals(fieldName)) {
                                    ValueMapping value = new ValueMapping(in.get(l), false);
                                    value.join(result.get(location));
                                    result.put(location, value);
                                    valid = true;
                                }
                            }
                        }
                    }
                }
                if (!valid && !(instr.getFieldType(context.constPool()) instanceof ReferenceType)) {
                    result.put(new Location(context.stackPtr - 1), new ValueMapping());
                }
            }
            break;
        case Constants.PUTSTATIC:
            {
                PUTSTATIC instr = (PUTSTATIC) instruction;
                int fieldSize = instr.getFieldType(context.constPool()).getSize();
                for (Location l : in.keySet()) {
                    if (l.stackLoc >= 0 && l.stackLoc < context.stackPtr - fieldSize) {
                        result.put(l, in.get(l));
                    }
                }
                DFATool p = interpreter.getDFATool();
                Set<String> receivers = p.getReceivers(stmt, context.callString);
                for (String fieldName : receivers) {
                    if (p.containsField(fieldName)) {
                        for (Location l : in.keySet()) {
                            if (l.stackLoc < 0 && !receivers.contains(l.heapLoc)) {
                                result.put(l, in.get(l));
                            }
                            if (l.stackLoc == context.stackPtr - 1) {
                                result.put(new Location(fieldName), new ValueMapping(in.get(l), false));
                            }
                        }
                    }
                }
            }
            break;
        case Constants.GETSTATIC:
            {
                GETSTATIC instr = (GETSTATIC) instruction;
                result = new LinkedHashMap<Location, ValueMapping>(in);
                retval.put(context.callString, result);
                DFATool p = interpreter.getDFATool();
                Set<String> receivers = p.getReceivers(stmt, context.callString);
                Location location = new Location(context.stackPtr);
                boolean valid = false;
                for (String fieldName : receivers) {
                    if (p.containsField(fieldName)) {
                        for (Location l : in.keySet()) {
                            if (l.heapLoc.equals(fieldName)) {
                                ValueMapping value = new ValueMapping(in.get(l), false);
                                value.join(result.get(location));
                                result.put(location, value);
                                valid = true;
                            }
                        }
                    }
                }
                if (!valid && !(instr.getFieldType(context.constPool()) instanceof ReferenceType)) {
                    result.put(new Location(context.stackPtr), new ValueMapping());
                }
            }
            break;
        case Constants.IASTORE:
        case Constants.CASTORE:
        case Constants.SASTORE:
        case Constants.BASTORE:
            {
                for (Location l : in.keySet()) {
                    if (l.stackLoc < context.stackPtr - 3) {
                        result.put(l, in.get(l));
                    }
                }
                DFATool p = interpreter.getDFATool();
                Set<String> receivers = p.getReceivers(stmt, context.callString);
                if (receivers == null) {
                    warnNoReceiver(context, stmt);
                    break;
                }
                for (String name : receivers) {
                    for (Location l : in.keySet()) {
                        if (l.stackLoc == context.stackPtr - 1) {
                            Location loc = new Location(name);
                            ValueMapping val = new ValueMapping(in.get(l), false);
                            val.join(in.get(loc));
                            result.put(loc, val);
                        }
                    }
                }
            }
            break;
        case Constants.AASTORE:
            {
                filterSet(in, result, context.stackPtr - 3);
            }
            break;
        case Constants.IALOAD:
        case Constants.CALOAD:
        case Constants.SALOAD:
        case Constants.BALOAD:
            {
                filterSet(in, result, context.stackPtr - 2);
                DFATool p = interpreter.getDFATool();
                Location location = new Location(context.stackPtr - 2);
                boolean valid = false;
                Set<String> receivers = p.getReceivers(stmt, context.callString);
                for (String name : receivers) {
                    for (Location l : in.keySet()) {
                        if (l.heapLoc.equals(name)) {
                            ValueMapping value = new ValueMapping(in.get(l), false);
                            value.join(result.get(location));
                            result.put(location, value);
                            valid = true;
                        }
                    }
                }
                if (!valid) {
                    result.put(new Location(context.stackPtr - 2), new ValueMapping(0));
                }
            }
            break;
        case Constants.AALOAD:
            {
                ValueMapping v = in.get(new Location(context.stackPtr - 1));
                if (v == null) {
                    logger.warn("no value at: " + context.callString.toStringList() + context.method() + stmt);
                } else {
                    recordArrayIndex(stmt, context, v.assigned);
                }
                filterSet(in, result, context.stackPtr - 2);
            }
            break;
        case Constants.DUP:
            {
                for (Location l : in.keySet()) {
                    result.put(l, in.get(l));
                    if (l.stackLoc == context.stackPtr - 1) {
                        result.put(new Location(context.stackPtr), new ValueMapping(in.get(l), true));
                    }
                }
            }
            break;
        case Constants.DUP_X1:
            {
                for (Location l : in.keySet()) {
                    if (l.stackLoc < context.stackPtr - 2) {
                        result.put(l, in.get(l));
                    }
                    if (l.stackLoc == context.stackPtr - 1) {
                        result.put(new Location(context.stackPtr - 2), new ValueMapping(in.get(l), true));
                        result.put(new Location(context.stackPtr), new ValueMapping(in.get(l), true));
                    }
                    if (l.stackLoc == context.stackPtr - 2) {
                        result.put(new Location(context.stackPtr - 1), new ValueMapping(in.get(l), true));
                    }
                }
            }
            break;
        case Constants.DUP2:
            {
                for (Location l : in.keySet()) {
                    result.put(l, in.get(l));
                    if (l.stackLoc == context.stackPtr - 2) {
                        result.put(new Location(context.stackPtr), new ValueMapping(in.get(l), true));
                    }
                    if (l.stackLoc == context.stackPtr - 1) {
                        result.put(new Location(context.stackPtr + 1), new ValueMapping(in.get(l), true));
                    }
                }
            }
            break;
        case Constants.POP:
            {
                filterSet(in, result, context.stackPtr - 1);
            }
            break;
        case Constants.POP2:
            {
                filterSet(in, result, context.stackPtr - 2);
            }
            break;
        case Constants.IINC:
            {
                IINC instr = (IINC) instruction;
                int index = instr.getIndex();
                int increment = instr.getIncrement();
                for (Location l : in.keySet()) {
                    if (l.stackLoc < context.stackPtr) {
                        result.put(l, in.get(l));
                    }
                    if (l.stackLoc == index) {
                        ValueMapping m = new ValueMapping(in.get(l), true);
                        m.assigned.add(increment);
                        m.constrained.add(increment);
                        Interval operand = new Interval(increment, increment);
                        if (m.increment != null && !m.softinc) {
                            m.increment.join(operand);
                        } else if (m.increment != null && m.softinc) {
                            if ((m.increment.getLb() < 0 && operand.getUb() > 0) || (m.increment.getUb() > 0 && operand.getLb() < 0)) {
                                m.increment.join(operand);
                            } else {
                                m.increment = operand;
                            }
                            m.softinc = false;
                        } else {
                            m.increment = operand;
                            m.softinc = false;
                        }
                        result.put(l, m);
                    }
                }
            }
            break;
        case Constants.IADD:
            {
                Interval operand = new Interval();
                for (Location l : in.keySet()) {
                    if (l.stackLoc == context.stackPtr - 1) {
                        operand = in.get(l).assigned;
                    }
                }
                for (Location l : in.keySet()) {
                    if (l.stackLoc < context.stackPtr - 2) {
                        result.put(l, in.get(l));
                    } else if (l.stackLoc == context.stackPtr - 2) {
                        ValueMapping m = new ValueMapping(in.get(l), true);
                        m.assigned.add(operand);
                        m.constrained.add(operand);
                        if (m.increment != null && !m.softinc) {
                            m.increment.join(operand);
                        } else if (m.increment != null && m.softinc) {
                            if ((m.increment.getLb() < 0 && operand.getUb() > 0) || (m.increment.getUb() > 0 && operand.getLb() < 0)) {
                                m.increment.join(operand);
                            } else {
                                m.increment = operand;
                            }
                            m.softinc = false;
                        } else {
                            m.increment = operand;
                            m.softinc = false;
                        }
                        result.put(l, m);
                    }
                }
            }
            break;
        case Constants.ISUB:
            {
                Interval operand = new Interval();
                for (Location l : in.keySet()) {
                    if (l.stackLoc == context.stackPtr - 1) {
                        operand = in.get(l).assigned;
                    }
                }
                for (Location l : in.keySet()) {
                    if (l.stackLoc < context.stackPtr - 2) {
                        result.put(l, in.get(l));
                    } else if (l.stackLoc == context.stackPtr - 2) {
                        ValueMapping m = new ValueMapping(in.get(l), true);
                        m.assigned.sub(operand);
                        m.constrained.sub(operand);
                        // decrement rather than increment
                        operand.neg();
                        if (m.increment != null && !m.softinc) {
                            m.increment.join(operand);
                        } else if (m.increment != null && m.softinc) {
                            if ((m.increment.getLb() < 0 && operand.getUb() > 0) || (m.increment.getUb() > 0 && operand.getLb() < 0)) {
                                m.increment.join(operand);
                            } else {
                                m.increment = operand;
                            }
                            m.softinc = false;
                        } else {
                            m.increment = operand;
                            m.softinc = false;
                        }
                        result.put(l, m);
                    }
                }
            }
            break;
        case Constants.INEG:
            {
                for (Location l : in.keySet()) {
                    if (l.stackLoc < context.stackPtr - 1) {
                        result.put(l, in.get(l));
                    } else if (l.stackLoc == context.stackPtr - 1) {
                        ValueMapping m = new ValueMapping(in.get(l), true);
                        m.assigned.neg();
                        m.constrained.neg();
                        m.increment = new Interval();
                        result.put(l, m);
                    }
                }
            }
            break;
        case Constants.IUSHR:
            {
                Interval operand = new Interval();
                for (Location l : in.keySet()) {
                    if (l.stackLoc == context.stackPtr - 1) {
                        operand = in.get(l).assigned;
                    }
                }
                for (Location l : in.keySet()) {
                    if (l.stackLoc < context.stackPtr - 2) {
                        result.put(l, in.get(l));
                    } else if (l.stackLoc == context.stackPtr - 2) {
                        ValueMapping m = new ValueMapping(in.get(l), true);
                        m.assigned.ushr(operand);
                        m.constrained.ushr(operand);
                        m.increment = new Interval();
                        result.put(l, m);
                    }
                }
            }
            break;
        case Constants.ISHR:
            {
                Interval operand = new Interval();
                for (Location l : in.keySet()) {
                    if (l.stackLoc == context.stackPtr - 1) {
                        operand = in.get(l).assigned;
                    }
                }
                for (Location l : in.keySet()) {
                    if (l.stackLoc < context.stackPtr - 2) {
                        result.put(l, in.get(l));
                    } else if (l.stackLoc == context.stackPtr - 2) {
                        ValueMapping m = new ValueMapping(in.get(l), true);
                        m.assigned.shr(operand);
                        m.constrained.shr(operand);
                        m.increment = new Interval();
                        result.put(l, m);
                    }
                }
            }
            break;
        case Constants.IMUL:
            {
                Interval operand = new Interval();
                for (Location l : in.keySet()) {
                    if (l.stackLoc == context.stackPtr - 1) {
                        operand = in.get(l).assigned;
                    }
                }
                for (Location l : in.keySet()) {
                    if (l.stackLoc < context.stackPtr - 2) {
                        result.put(l, in.get(l));
                    } else if (l.stackLoc == context.stackPtr - 2) {
                        ValueMapping m = new ValueMapping(in.get(l), true);
                        m.assigned.mul(operand);
                        m.constrained.mul(operand);
                        m.increment = new Interval();
                        result.put(l, m);
                    }
                }
            }
            break;
        case Constants.IDIV:
            {
                Interval operand = new Interval();
                for (Location l : in.keySet()) {
                    if (l.stackLoc == context.stackPtr - 1) {
                        operand = in.get(l).assigned;
                    }
                }
                for (Location l : in.keySet()) {
                    if (l.stackLoc < context.stackPtr - 2) {
                        result.put(l, in.get(l));
                    } else if (l.stackLoc == context.stackPtr - 2) {
                        ValueMapping m = new ValueMapping(in.get(l), true);
                        m.assigned.div(operand);
                        m.constrained.div(operand);
                        m.increment = new Interval();
                        result.put(l, m);
                    }
                }
            }
            break;
        case Constants.IAND:
        case Constants.IOR:
        case Constants.IXOR:
        case Constants.IREM:
        case Constants.ISHL:
            {
                // TODO: we could be more clever for some operations
                for (Location l : in.keySet()) {
                    if (l.stackLoc < context.stackPtr - 2) {
                        result.put(l, in.get(l));
                    } else if (l.stackLoc == context.stackPtr - 2) {
                        ValueMapping m = new ValueMapping();
                        result.put(l, m);
                    }
                }
            }
            break;
        case Constants.I2B:
        case Constants.I2C:
        case Constants.I2S:
            // TODO: is this really correct?
            result = in;
            retval.put(context.callString, result);
            break;
        case Constants.MONITORENTER:
            result = in;
            retval.put(context.callString, result);
            context.syncLevel++;
            break;
        case Constants.MONITOREXIT:
            result = in;
            retval.put(context.callString, result);
            context.syncLevel--;
            if (context.syncLevel < 0) {
                System.err.println("Synchronization level mismatch.");
                System.exit(-1);
            }
            break;
        case Constants.CHECKCAST:
            result = in;
            retval.put(context.callString, result);
            break;
        case Constants.INSTANCEOF:
            {
                filterSet(in, result, context.stackPtr - 1);
                ValueMapping bool = new ValueMapping();
                bool.assigned.setLb(0);
                bool.assigned.setUb(1);
                result.put(new Location(context.stackPtr - 1), bool);
            }
            break;
        case Constants.NEW:
            {
                result = in;
                retval.put(context.callString, result);
            }
            break;
        case Constants.NEWARRAY:
            {
                NEWARRAY instr = (NEWARRAY) instruction;
                String name = instr.getType().toString();
                name += "@" + context.method() + ":" + stmt.getPosition();
                filterSet(in, result, context.stackPtr - 1);
                boolean valid = false;
                for (Location l : in.keySet()) {
                    if (l.stackLoc == context.stackPtr - 1) {
                        result.put(new Location(name + ".length"), in.get(l));
                        recordSize(stmt, context, in.get(l).assigned);
                        valid = true;
                    }
                }
                if (!valid) {
                    ValueMapping v = new ValueMapping();
                    result.put(new Location(name + ".length"), v);
                    recordSize(stmt, context, v.assigned);
                }
            }
            break;
        case Constants.ANEWARRAY:
            {
                ANEWARRAY instr = (ANEWARRAY) instruction;
                String name = instr.getType(context.constPool()).toString() + "[]";
                name += "@" + context.method() + ":" + stmt.getPosition();
                //System.out.println("NEW ARRAY: "+name);
                filterSet(in, result, context.stackPtr - 1);
                boolean valid = false;
                for (Location l : in.keySet()) {
                    if (l.stackLoc == context.stackPtr - 1) {
                        result.put(new Location(name + ".length"), in.get(l));
                        recordSize(stmt, context, in.get(l).assigned);
                        valid = true;
                    }
                }
                if (!valid) {
                    ValueMapping v = new ValueMapping();
                    result.put(new Location(name + ".length"), v);
                    recordSize(stmt, context, v.assigned);
                }
            }
            break;
        case Constants.MULTIANEWARRAY:
            {
                MULTIANEWARRAY instr = (MULTIANEWARRAY) instruction;
                int dim = instr.getDimensions();
                filterSet(in, result, context.stackPtr - dim);
                String type = instr.getType(context.constPool()).toString();
                type = type.substring(0, type.indexOf("["));
                Interval[] size = new Interval[dim];
                for (int i = 1; i <= dim; i++) {
                    String name = type;
                    for (int k = 0; k < i; k++) {
                        name += "[]";
                    }
                    name += "@" + context.method() + ":" + stmt.getPosition();
                    boolean valid = false;
                    for (Location l : in.keySet()) {
                        if (l.stackLoc == context.stackPtr - i) {
                            result.put(new Location(name + ".length"), in.get(l));
                            if (size[i - 1] != null) {
                                size[i - 1].join(in.get(l).assigned);
                            } else {
                                size[i - 1] = in.get(l).assigned;
                            }
                            valid = true;
                        }
                    }
                    if (!valid) {
                        ValueMapping v = new ValueMapping();
                        result.put(new Location(name + ".length"), v);
                        size[i - 1] = v.assigned;
                    }
                }
                recordSize(stmt, context, size);
            }
            break;
        case Constants.GOTO:
            result = in;
            retval.put(context.callString, result);
            break;
        case Constants.IFNULL:
        case Constants.IFNONNULL:
            {
                checkScope(context, stmt);
                filterSet(in, result, context.stackPtr - 1);
            }
            break;
        case Constants.IF_ACMPEQ:
        case Constants.IF_ACMPNE:
            {
                checkScope(context, stmt);
                filterSet(in, result, context.stackPtr - 2);
            }
            break;
        case Constants.IFEQ:
        case Constants.IFNE:
        case Constants.IFLT:
        case Constants.IFGE:
        case Constants.IFLE:
        case Constants.IFGT:
            checkScope(context, stmt);
            result = doIf(stmt, edge, context, in, result);
            retval.put(context.callString, result);
            break;
        case Constants.IF_ICMPEQ:
        case Constants.IF_ICMPNE:
        case Constants.IF_ICMPLT:
        case Constants.IF_ICMPGE:
        case Constants.IF_ICMPGT:
        case Constants.IF_ICMPLE:
            checkScope(context, stmt);
            result = doIfIcmp(stmt, edge, context, in, result);
            retval.put(context.callString, result);
            break;
        case Constants.LOOKUPSWITCH:
        case Constants.TABLESWITCH:
            result = in;
            retval.put(context.callString, result);
            break;
        case Constants.INVOKEVIRTUAL:
        case Constants.INVOKEINTERFACE:
        case Constants.INVOKESTATIC:
        case Constants.INVOKESPECIAL:
            {
                DFATool p = interpreter.getDFATool();
                Set<String> receivers = p.getReceivers(stmt, context.callString);
                if (receivers == null) {
                    warnUnknownReceivers(context, stmt);
                    result = in;
                    break;
                }
                for (String methodName : receivers) {
                    doInvoke(methodName, stmt, context, input, interpreter, state, retval);
                }
            }
            break;
        case Constants.ARETURN:
        case Constants.RETURN:
            {
                filterSet(in, result, 0);
            }
            break;
        case Constants.IRETURN:
            {
                filterSet(in, result, 0);
                for (Location l : in.keySet()) {
                    if (l.stackLoc == context.stackPtr - 1) {
                        result.put(new Location(0), new ValueMapping(in.get(l), false));
                    }
                }
            }
            break;
        default:
            //			System.out.println("unknown instruction: "+stmt);
            result = in;
            retval.put(context.callString, result);
            break;
    }
    //		System.out.println(stmt);
    //		System.out.print(stmt.getInstruction()+":\t{ ");
    //		if (retval != null) {
    //			for (Iterator<Map<Location, ValueMapping>> k = retval.values().iterator(); k.hasNext(); ) {
    //				Map<Location, ValueMapping> m = k.next();
    //				System.out.print(m+", ");
    //			}
    //		}
    //		System.out.println("}");
    context.stackPtr += instruction.produceStack(context.constPool()) - instruction.consumeStack(context.constPool());
    return retval;
}
Also used : Set(java.util.Set) LinkedHashSet(java.util.LinkedHashSet) MULTIANEWARRAY(org.apache.bcel.generic.MULTIANEWARRAY) ANEWARRAY(org.apache.bcel.generic.ANEWARRAY) LDC(org.apache.bcel.generic.LDC) CallString(com.jopdesign.common.code.CallString) LoadInstruction(org.apache.bcel.generic.LoadInstruction) StoreInstruction(org.apache.bcel.generic.StoreInstruction) Instruction(org.apache.bcel.generic.Instruction) ConstantPushInstruction(org.apache.bcel.generic.ConstantPushInstruction) BranchInstruction(org.apache.bcel.generic.BranchInstruction) ReferenceType(org.apache.bcel.generic.ReferenceType) LinkedHashMap(java.util.LinkedHashMap) PUTSTATIC(org.apache.bcel.generic.PUTSTATIC) LoadInstruction(org.apache.bcel.generic.LoadInstruction) Context(com.jopdesign.dfa.framework.Context) MULTIANEWARRAY(org.apache.bcel.generic.MULTIANEWARRAY) ANEWARRAY(org.apache.bcel.generic.ANEWARRAY) NEWARRAY(org.apache.bcel.generic.NEWARRAY) DFATool(com.jopdesign.dfa.DFATool) PUTFIELD(org.apache.bcel.generic.PUTFIELD) MULTIANEWARRAY(org.apache.bcel.generic.MULTIANEWARRAY) ContextMap(com.jopdesign.dfa.framework.ContextMap) CallString(com.jopdesign.common.code.CallString) GETFIELD(org.apache.bcel.generic.GETFIELD) ReferenceType(org.apache.bcel.generic.ReferenceType) Type(org.apache.bcel.generic.Type) IINC(org.apache.bcel.generic.IINC) ConstantPushInstruction(org.apache.bcel.generic.ConstantPushInstruction) GETSTATIC(org.apache.bcel.generic.GETSTATIC) Map(java.util.Map) LinkedHashMap(java.util.LinkedHashMap) ContextMap(com.jopdesign.dfa.framework.ContextMap) StoreInstruction(org.apache.bcel.generic.StoreInstruction)

Example 2 with IINC

use of org.apache.bcel.generic.IINC in project jop by jop-devel.

the class ValueMapAnalysis method transfer.

public void transfer(Instruction instruction) {
    switch(instruction.getOpcode()) {
        case Constants.NOP:
            break;
        case Constants.ACONST_NULL:
            values.push(new ValueInfo(Type.NULL));
            break;
        case Constants.ICONST_M1:
        case Constants.ICONST_0:
        case Constants.ICONST_1:
        case Constants.ICONST_2:
        case Constants.ICONST_3:
        case Constants.ICONST_4:
        case Constants.ICONST_5:
        case Constants.BIPUSH:
        case Constants.SIPUSH:
            {
                ConstantPushInstruction instr = (ConstantPushInstruction) instruction;
                int value = instr.getValue().intValue();
                values.push(new ValueInfo(instr.getType(cpg), new ConstantIntegerInfo(value)));
                break;
            }
        case Constants.LCONST_0:
        case Constants.LCONST_1:
            {
                ConstantPushInstruction instr = (ConstantPushInstruction) instruction;
                long value = instr.getValue().longValue();
                values.push(new ValueInfo(instr.getType(cpg), new ConstantLongInfo(value)));
                break;
            }
        case Constants.FCONST_0:
        case Constants.FCONST_1:
        case Constants.FCONST_2:
            {
                ConstantPushInstruction instr = (ConstantPushInstruction) instruction;
                float value = instr.getValue().floatValue();
                values.push(new ValueInfo(instr.getType(cpg), new ConstantFloatInfo(value)));
                break;
            }
        case Constants.DCONST_0:
        case Constants.DCONST_1:
            {
                ConstantPushInstruction instr = (ConstantPushInstruction) instruction;
                double value = instr.getValue().doubleValue();
                values.push(new ValueInfo(instr.getType(cpg), new ConstantDoubleInfo(value)));
                break;
            }
        case Constants.LDC:
        case Constants.LDC_W:
        case Constants.LDC2_W:
            {
                CPInstruction instr = (CPInstruction) instruction;
                values.push(new ValueInfo(methodInfo.getClassInfo().getConstantInfo(instr.getIndex())));
                break;
            }
        case Constants.ISTORE_0:
        case Constants.ISTORE_1:
        case Constants.ISTORE_2:
        case Constants.ISTORE_3:
        case Constants.ISTORE:
        case Constants.ASTORE_0:
        case Constants.ASTORE_1:
        case Constants.ASTORE_2:
        case Constants.ASTORE_3:
        case Constants.ASTORE:
        case Constants.LSTORE_0:
        case Constants.LSTORE_1:
        case Constants.LSTORE_2:
        case Constants.LSTORE_3:
        case Constants.LSTORE:
        case Constants.DSTORE_0:
        case Constants.DSTORE_1:
        case Constants.DSTORE_2:
        case Constants.DSTORE_3:
        case Constants.DSTORE:
        case Constants.FSTORE_0:
        case Constants.FSTORE_1:
        case Constants.FSTORE_2:
        case Constants.FSTORE_3:
        case Constants.FSTORE:
            {
                StoreInstruction instr = (StoreInstruction) instruction;
                int index = instr.getIndex();
                values.setLocalValue(index, values.popValue());
                break;
            }
        case Constants.ILOAD_0:
        case Constants.ILOAD_1:
        case Constants.ILOAD_2:
        case Constants.ILOAD_3:
        case Constants.ILOAD:
        case Constants.LLOAD_0:
        case Constants.LLOAD_1:
        case Constants.LLOAD_2:
        case Constants.LLOAD_3:
        case Constants.LLOAD:
        case Constants.FLOAD_0:
        case Constants.FLOAD_1:
        case Constants.FLOAD_2:
        case Constants.FLOAD_3:
        case Constants.FLOAD:
        case Constants.DLOAD_0:
        case Constants.DLOAD_1:
        case Constants.DLOAD_2:
        case Constants.DLOAD_3:
        case Constants.DLOAD:
        case Constants.ALOAD_0:
        case Constants.ALOAD_1:
        case Constants.ALOAD_2:
        case Constants.ALOAD_3:
        case Constants.ALOAD:
            {
                LoadInstruction instr = (LoadInstruction) instruction;
                int index = instr.getIndex();
                values.push(values.getLocalValue(index));
                break;
            }
        case Constants.DUP:
            values.push(values.top());
            break;
        case Constants.DUP_X1:
            values.insert(2, values.top());
            break;
        case Constants.DUP_X2:
            values.insert(3, values.top());
        case Constants.DUP2:
            values.push(values.top(1), false);
            values.push(values.top(1), false);
            break;
        case Constants.DUP2_X1:
            values.insert(3, values.top(1));
            values.insert(3, values.top(0));
            break;
        case Constants.DUP2_X2:
            values.insert(4, values.top(1));
            values.insert(4, values.top(0));
            break;
        case Constants.POP:
            values.pop();
            break;
        case Constants.POP2:
            values.pop();
            values.pop();
            break;
        case Constants.SWAP:
            values.insert(1, values.pop());
            break;
        case Constants.IASTORE:
        case Constants.LASTORE:
        case Constants.FASTORE:
        case Constants.DASTORE:
        case Constants.CASTORE:
        case Constants.SASTORE:
        case Constants.BASTORE:
        case Constants.AASTORE:
            values.popValue();
            values.pop();
            values.pop();
            break;
        case Constants.IALOAD:
        case Constants.LALOAD:
        case Constants.FALOAD:
        case Constants.DALOAD:
        case Constants.CALOAD:
        case Constants.SALOAD:
        case Constants.BALOAD:
        case Constants.AALOAD:
            {
                values.pop();
                values.pop();
                Type t = ((ArrayInstruction) instruction).getType(cpg);
                values.push(new ValueInfo(t));
                break;
            }
        case Constants.IINC:
            {
                int i = ((IINC) instruction).getIndex();
                ValueInfo old = values.getLocalValue(i);
                if (old.isConstantValue() && old.getConstantValue() instanceof ConstantIntegerInfo) {
                    ConstantIntegerInfo value = (ConstantIntegerInfo) old.getConstantValue();
                    int newval = value.getValue() + ((IINC) instruction).getIncrement();
                    values.setLocalValue(i, new ValueInfo(new ConstantIntegerInfo(newval)));
                } else {
                    values.setLocalValue(i, new ValueInfo(Type.INT));
                }
                break;
            }
        case Constants.IADD:
        case Constants.ISUB:
        case Constants.IMUL:
        case Constants.IDIV:
        case Constants.IREM:
        case Constants.IAND:
        case Constants.IOR:
        case Constants.IXOR:
        case Constants.ISHL:
        case Constants.ISHR:
        case Constants.IUSHR:
            values.pop();
        case Constants.INEG:
            values.pop();
            values.push(new ValueInfo(Type.INT));
            break;
        case Constants.FADD:
        case Constants.FSUB:
        case Constants.FMUL:
        case Constants.FDIV:
        case Constants.FREM:
            values.pop();
        case Constants.FNEG:
            values.pop();
            values.push(new ValueInfo(Type.FLOAT));
            break;
        case Constants.LADD:
        case Constants.LSUB:
        case Constants.LMUL:
        case Constants.LDIV:
        case Constants.LREM:
        case Constants.LAND:
        case Constants.LOR:
        case Constants.LXOR:
            values.pop();
            values.pop();
        case Constants.LNEG:
            values.pop();
            values.pop();
            values.push(new ValueInfo(Type.LONG));
            break;
        case Constants.DADD:
        case Constants.DSUB:
        case Constants.DMUL:
        case Constants.DDIV:
        case Constants.DREM:
            values.pop();
            values.pop();
        case Constants.DNEG:
            values.pop();
            values.pop();
            values.push(new ValueInfo(Type.DOUBLE));
            break;
        case Constants.LSHL:
        case Constants.LSHR:
        case Constants.LUSHR:
            values.pop();
            values.pop();
            values.pop();
            values.push(new ValueInfo(Type.LONG));
            break;
        case Constants.I2B:
        case Constants.I2C:
        case Constants.I2S:
        case Constants.I2L:
        case Constants.I2F:
        case Constants.I2D:
        case Constants.L2I:
        case Constants.L2F:
        case Constants.L2D:
        case Constants.F2I:
        case Constants.F2L:
        case Constants.F2D:
        case Constants.D2I:
        case Constants.D2L:
        case Constants.D2F:
            {
                values.popValue();
                values.push(new ValueInfo(((ConversionInstruction) instruction).getType(cpg)));
                break;
            }
        case Constants.LCMP:
        case Constants.DCMPL:
        case Constants.DCMPG:
            values.pop();
            values.pop();
        case Constants.FCMPL:
        case Constants.FCMPG:
            values.pop();
            values.pop();
            values.push(new ValueInfo(Type.INT));
            break;
        case Constants.IF_ICMPEQ:
        case Constants.IF_ICMPNE:
        case Constants.IF_ICMPLT:
        case Constants.IF_ICMPGE:
        case Constants.IF_ICMPGT:
        case Constants.IF_ICMPLE:
        case Constants.IF_ACMPEQ:
        case Constants.IF_ACMPNE:
            values.pop();
        case Constants.IFEQ:
        case Constants.IFNE:
        case Constants.IFLT:
        case Constants.IFGE:
        case Constants.IFLE:
        case Constants.IFGT:
        case Constants.IFNULL:
        case Constants.IFNONNULL:
            values.pop();
            break;
        case Constants.GOTO:
        case Constants.RET:
            break;
        case Constants.JSR:
            // This is of type 'returnAddress'
            values.push(new ValueInfo(Type.INT));
            break;
        case Constants.ARETURN:
        case Constants.IRETURN:
        case Constants.LRETURN:
        case Constants.FRETURN:
        case Constants.DRETURN:
        case Constants.RETURN:
            values.clearStack();
            break;
        case Constants.LOOKUPSWITCH:
        case Constants.TABLESWITCH:
            values.pop();
            break;
        case Constants.GETFIELD:
            values.pop();
        case Constants.GETSTATIC:
            {
                FieldInstruction f = (FieldInstruction) instruction;
                ConstantFieldInfo field = (ConstantFieldInfo) methodInfo.getClassInfo().getConstantInfo(f.getIndex());
                values.push(new ValueInfo(f.getFieldType(cpg), field.getValue()));
                break;
            }
        case Constants.PUTFIELD:
            values.pop();
        case Constants.PUTSTATIC:
            {
                FieldInstruction f = (FieldInstruction) instruction;
                values.pop(f.getFieldType(cpg).getSize());
                break;
            }
        case Constants.INVOKEVIRTUAL:
        case Constants.INVOKEINTERFACE:
        case Constants.INVOKESPECIAL:
            values.pop();
        case Constants.INVOKESTATIC:
            {
                InvokeInstruction invoke = (InvokeInstruction) instruction;
                values.pop(TypeHelper.getNumSlots(invoke.getArgumentTypes(cpg)));
                values.push(new ValueInfo(invoke.getReturnType(cpg)));
                break;
            }
        case Constants.MONITORENTER:
        case Constants.MONITOREXIT:
            values.pop();
            break;
        case Constants.ATHROW:
            ValueInfo ref = values.pop();
            values.clearStack();
            values.push(ref);
            break;
        case Constants.CHECKCAST:
            break;
        case Constants.INSTANCEOF:
            values.pop();
            values.push(new ValueInfo(Type.INT));
            break;
        case Constants.NEW:
            values.push(new ValueInfo(((NEW) instruction).getType(cpg)));
            break;
        case Constants.NEWARRAY:
            {
                Type t = ((NEWARRAY) instruction).getType();
                values.push(new ValueInfo(new ArrayType(t, 1)));
                break;
            }
        case Constants.ANEWARRAY:
            {
                Type t = ((ANEWARRAY) instruction).getType(cpg);
                values.push(new ValueInfo(new ArrayType(t, 1)));
                break;
            }
        case Constants.MULTIANEWARRAY:
            {
                MULTIANEWARRAY instr = (MULTIANEWARRAY) instruction;
                values.pop(instr.getDimensions());
                values.push(new ValueInfo(new ArrayType(instr.getType(cpg), instr.getDimensions())));
                break;
            }
        case Constants.ARRAYLENGTH:
            values.pop();
            values.push(new ValueInfo(Type.INT));
            break;
        default:
            throw new AppInfoError("Instruction not supported: " + instruction);
    }
}
Also used : NEW(org.apache.bcel.generic.NEW) ConstantDoubleInfo(com.jopdesign.common.type.ConstantDoubleInfo) MULTIANEWARRAY(org.apache.bcel.generic.MULTIANEWARRAY) ConstantIntegerInfo(com.jopdesign.common.type.ConstantIntegerInfo) ConstantFloatInfo(com.jopdesign.common.type.ConstantFloatInfo) ConstantFieldInfo(com.jopdesign.common.type.ConstantFieldInfo) ConstantLongInfo(com.jopdesign.common.type.ConstantLongInfo) AppInfoError(com.jopdesign.common.misc.AppInfoError) ArrayType(org.apache.bcel.generic.ArrayType) CPInstruction(org.apache.bcel.generic.CPInstruction) InvokeInstruction(org.apache.bcel.generic.InvokeInstruction) LoadInstruction(org.apache.bcel.generic.LoadInstruction) Type(org.apache.bcel.generic.Type) ArrayType(org.apache.bcel.generic.ArrayType) ValueInfo(com.jopdesign.common.type.ValueInfo) IINC(org.apache.bcel.generic.IINC) FieldInstruction(org.apache.bcel.generic.FieldInstruction) ConstantPushInstruction(org.apache.bcel.generic.ConstantPushInstruction) StoreInstruction(org.apache.bcel.generic.StoreInstruction)

Example 3 with IINC

use of org.apache.bcel.generic.IINC in project jop by jop-devel.

the class ReplaceAtomicAnnotation method getModifiedArguments.

protected static SortedSet<Integer> getModifiedArguments(MethodGen method) {
    SortedSet<Integer> result = new TreeSet<Integer>();
    int arguments = getArgsCount(method);
    for (Instruction in : method.getInstructionList().getInstructions()) {
        if (in instanceof IndexedInstruction) {
            IndexedInstruction i = (IndexedInstruction) in;
            if (i.getIndex() < arguments) {
                if (i instanceof DSTORE || i instanceof LSTORE) {
                    result.add(i.getIndex());
                    result.add(i.getIndex() + 1);
                } else if (i instanceof StoreInstruction || i instanceof IINC) {
                    result.add(i.getIndex());
                }
            }
        }
    }
    return result;
}
Also used : TreeSet(java.util.TreeSet) IINC(org.apache.bcel.generic.IINC) StoreInstruction(org.apache.bcel.generic.StoreInstruction) Instruction(org.apache.bcel.generic.Instruction) BranchInstruction(org.apache.bcel.generic.BranchInstruction) IndexedInstruction(org.apache.bcel.generic.IndexedInstruction) IndexedInstruction(org.apache.bcel.generic.IndexedInstruction) LSTORE(org.apache.bcel.generic.LSTORE) StoreInstruction(org.apache.bcel.generic.StoreInstruction) DSTORE(org.apache.bcel.generic.DSTORE)

Example 4 with IINC

use of org.apache.bcel.generic.IINC in project jop by jop-devel.

the class ReplaceIinc method replace.

private void replace(MethodInfo method) {
    MethodCode mc = method.getCode();
    InstructionList il = mc.getInstructionList();
    InstructionFinder f = new InstructionFinder(il);
    for (Iterator i = f.search("IINC"); i.hasNext(); ) {
        InstructionHandle[] match = (InstructionHandle[]) i.next();
        InstructionHandle ih = match[0];
        IINC ii = (IINC) ih.getInstruction();
        int idx = ii.getIndex();
        int inc = ii.getIncrement();
        //  	    IINC rep = new IINC(idx, inc);
        ih.setInstruction(new ILOAD(idx));
        if (inc >= -1 && inc <= 5) {
            ih = il.append(ih, new ICONST(inc));
        } else if (inc >= -128 && inc < 127) {
            ih = il.append(ih, new BIPUSH((byte) inc));
        } else if (inc >= -32768 && inc < 32767) {
            ih = il.append(ih, new SIPUSH((short) inc));
        } else {
            System.out.println("IINC constant too big");
            System.exit(-1);
        }
        ih = il.append(ih, new IADD());
        ih = il.append(ih, new ISTORE(idx));
    }
    method.compile();
}
Also used : InstructionList(org.apache.bcel.generic.InstructionList) ILOAD(org.apache.bcel.generic.ILOAD) InstructionFinder(org.apache.bcel.util.InstructionFinder) BIPUSH(org.apache.bcel.generic.BIPUSH) InstructionHandle(org.apache.bcel.generic.InstructionHandle) ISTORE(org.apache.bcel.generic.ISTORE) IINC(org.apache.bcel.generic.IINC) Iterator(java.util.Iterator) IADD(org.apache.bcel.generic.IADD) MethodCode(com.jopdesign.common.MethodCode) SIPUSH(org.apache.bcel.generic.SIPUSH) ICONST(org.apache.bcel.generic.ICONST)

Aggregations

IINC (org.apache.bcel.generic.IINC)4 StoreInstruction (org.apache.bcel.generic.StoreInstruction)3 BranchInstruction (org.apache.bcel.generic.BranchInstruction)2 ConstantPushInstruction (org.apache.bcel.generic.ConstantPushInstruction)2 Instruction (org.apache.bcel.generic.Instruction)2 LoadInstruction (org.apache.bcel.generic.LoadInstruction)2 MULTIANEWARRAY (org.apache.bcel.generic.MULTIANEWARRAY)2 Type (org.apache.bcel.generic.Type)2 MethodCode (com.jopdesign.common.MethodCode)1 CallString (com.jopdesign.common.code.CallString)1 AppInfoError (com.jopdesign.common.misc.AppInfoError)1 ConstantDoubleInfo (com.jopdesign.common.type.ConstantDoubleInfo)1 ConstantFieldInfo (com.jopdesign.common.type.ConstantFieldInfo)1 ConstantFloatInfo (com.jopdesign.common.type.ConstantFloatInfo)1 ConstantIntegerInfo (com.jopdesign.common.type.ConstantIntegerInfo)1 ConstantLongInfo (com.jopdesign.common.type.ConstantLongInfo)1 ValueInfo (com.jopdesign.common.type.ValueInfo)1 DFATool (com.jopdesign.dfa.DFATool)1 Context (com.jopdesign.dfa.framework.Context)1 ContextMap (com.jopdesign.dfa.framework.ContextMap)1