Search in sources :

Example 1 with PUTFIELD

use of org.apache.bcel.generic.PUTFIELD 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 PUTFIELD

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

the class SymbolicPointsTo method transfer.

public ContextMap<CallString, SymbolicAddressMap> transfer(InstructionHandle stmt, FlowEdge edge, ContextMap<CallString, SymbolicAddressMap> input, Interpreter<CallString, SymbolicAddressMap> interpreter, Map<InstructionHandle, ContextMap<CallString, SymbolicAddressMap>> state) {
    Context context = new Context(input.getContext());
    if (DEBUG_PRINT) {
        System.out.println("[S] " + context.callString.toStringList() + ": " + context.method() + " / " + stmt);
    }
    SymbolicAddressMap in = input.get(context.callString);
    ContextMap<CallString, SymbolicAddressMap> retval = new ContextMap<CallString, SymbolicAddressMap>(context, input);
    Instruction instruction = stmt.getInstruction();
    int newStackPtr = context.stackPtr + instruction.produceStack(context.constPool()) - instruction.consumeStack(context.constPool());
    int opcode = instruction.getOpcode();
    switch(opcode) {
        /* Constants (boring) */
        case Constants.DCONST_0:
        case Constants.DCONST_1:
        case Constants.LCONST_0:
        case Constants.LCONST_1:
        /* Instructions above need two stack slots */
        case Constants.FCONST_0:
        case Constants.FCONST_1:
        case Constants.FCONST_2:
        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:
            {
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            }
            break;
        case Constants.ACONST_NULL:
            {
                // Null -> No reference
                SymbolicAddressMap result = in.cloneFilterStack(newStackPtr);
                result.putStack(newStackPtr - 1, bsFactory.empty());
                retval.put(context.callString, result);
            }
            break;
        /* Long/Double Constants */
        case Constants.LDC2_W:
            {
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            }
            break;
        /* Int/Float/String Constants */
        case Constants.LDC:
        case Constants.LDC_W:
            {
                LDC ldc = (LDC) instruction;
                Type t = ldc.getType(context.constPool());
                if (t instanceof ReferenceType) {
                    SymbolicAddressMap result = in.cloneFilterStack(newStackPtr);
                    /* FIXME: This is overly conservative, but class pointer not available here */
                    String classContext = context.getMethodInfo().getMemberID().toString();
                    SymbolicAddress addr = SymbolicAddress.stringLiteral(classContext, ldc.getIndex());
                    result.putStack(newStackPtr - 1, bsFactory.singleton(addr));
                    retval.put(context.callString, result);
                } else {
                    retval.put(context.callString, in.cloneFilterStack(newStackPtr));
                }
            }
            break;
        case Constants.DSTORE:
        case Constants.DSTORE_0:
        case Constants.DSTORE_1:
        case Constants.DSTORE_2:
        case Constants.DSTORE_3:
        case Constants.LSTORE:
        case Constants.LSTORE_0:
        case Constants.LSTORE_1:
        case Constants.LSTORE_2:
        case Constants.LSTORE_3:
        case Constants.FSTORE:
        case Constants.FSTORE_0:
        case Constants.FSTORE_1:
        case Constants.FSTORE_2:
        case Constants.FSTORE_3:
        case Constants.ISTORE_0:
        case Constants.ISTORE_1:
        case Constants.ISTORE_2:
        case Constants.ISTORE_3:
        case Constants.ISTORE:
            {
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            }
            break;
        // 
        case Constants.ASTORE_0:
        case Constants.ASTORE_1:
        case Constants.ASTORE_2:
        case Constants.ASTORE_3:
        case Constants.ASTORE:
            {
                // copy value to local variable
                StoreInstruction instr = (StoreInstruction) instruction;
                SymbolicAddressMap result = in.cloneFilterStack(newStackPtr);
                if (DEBUG_PRINT) {
                    System.out.println(String.format("[DD] Copy: stack[%d] <- stack[%d]", instr.getIndex(), context.stackPtr - 1));
                }
                result.copyStack(in, instr.getIndex(), context.stackPtr - 1);
                retval.put(context.callString, result);
            }
            break;
        /* Load variables (boring) */
        case Constants.DLOAD_0:
        case Constants.DLOAD_1:
        case Constants.DLOAD_2:
        case Constants.DLOAD_3:
        case Constants.DLOAD:
        case Constants.LLOAD_0:
        case Constants.LLOAD_1:
        case Constants.LLOAD_2:
        case Constants.LLOAD_3:
        case Constants.LLOAD:
        /* Instructions above need two stack slots */
        case Constants.FLOAD_0:
        case Constants.FLOAD_1:
        case Constants.FLOAD_2:
        case Constants.FLOAD_3:
        case Constants.FLOAD:
        case Constants.ILOAD_0:
        case Constants.ILOAD_1:
        case Constants.ILOAD_2:
        case Constants.ILOAD_3:
        case Constants.ILOAD:
            {
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            }
            break;
        /* Floating Point Comparison (boring) */
        case Constants.DCMPG:
        case Constants.DCMPL:
        case Constants.LCMP:
        /* Instructions above need two stack slots */
        case Constants.FCMPG:
        case Constants.FCMPL:
            {
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            }
            break;
        case Constants.ALOAD_0:
        case Constants.ALOAD_1:
        case Constants.ALOAD_2:
        case Constants.ALOAD_3:
        case Constants.ALOAD:
            {
                LoadInstruction instr = (LoadInstruction) instruction;
                // copy value from local variable
                SymbolicAddressMap result = in.cloneFilterStack(newStackPtr);
                result.copyStack(in, context.stackPtr, instr.getIndex());
                retval.put(context.callString, result);
            }
            break;
        // Access Object Handle (area), top of stack
        case Constants.ARRAYLENGTH:
            {
                putResult(stmt, context, input.get(context.callString).getStack(context.stackPtr - 1));
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            }
            break;
        // Access Object Handle, second on stack
        case Constants.PUTFIELD:
            {
                PUTFIELD instr = (PUTFIELD) instruction;
                putResult(stmt, context, input.get(context.callString).getStack(context.stackPtr - 1 - instr.getType(context.constPool()).getSize()));
                SymbolicAddressMap result = in.cloneFilterStack(newStackPtr);
                // Change alias information
                if (instr.getFieldType(context.constPool()) instanceof ReferenceType) {
                    String ty = instr.getFieldType(context.constPool()).getSignature();
                    result.addAlias(ty, in.getStack(context.stackPtr - 1));
                }
                retval.put(context.callString, result);
            }
            break;
        // Access Object Handle, top of stack
        case Constants.GETFIELD:
            {
                putResult(stmt, context, input.get(context.callString).getStack(context.stackPtr - 1));
                GETFIELD instr = (GETFIELD) instruction;
                SymbolicAddressMap result = in.cloneFilterStack(newStackPtr);
                if (instr.getFieldType(context.constPool()) instanceof ReferenceType) {
                    BoundedSet<SymbolicAddress> newMapping = SymbolicAddress.fieldAccess(bsFactory, in.getStack(context.stackPtr - 1), instr.getFieldName(context.constPool()));
                    newMapping.addAll(in.getAliases(instr.getFieldType(context.constPool()).getSignature()));
                    result.putStack(context.stackPtr - 1, newMapping);
                }
                retval.put(context.callString, result);
            }
            break;
        // Handles the same way as MOV
        case Constants.PUTSTATIC:
            {
                PUTSTATIC instr = (PUTSTATIC) instruction;
                SymbolicAddressMap result = in.cloneFilterStack(newStackPtr);
                if (instr.getFieldType(context.constPool()) instanceof ReferenceType) {
                    BoundedSet<SymbolicAddress> pointers = in.getStack(context.stackPtr - 1);
                    result.putHeap(fieldSignature(context, instr), pointers);
                }
                retval.put(context.callString, result);
            }
            break;
        // Handled the same as MOV
        case Constants.GETSTATIC:
            {
                GETSTATIC instr = (GETSTATIC) instruction;
                SymbolicAddressMap result = in.cloneFilterStack(newStackPtr);
                if (instr.getFieldType(context.constPool()) instanceof ReferenceType) {
                    result.putStack(context.stackPtr, in.getHeap(fieldSignature(context, instr)));
                }
                retval.put(context.callString, result);
            }
            break;
        case Constants.LASTORE:
        case Constants.DASTORE:
        case Constants.IASTORE:
        case Constants.FASTORE:
        case Constants.CASTORE:
        case Constants.SASTORE:
        case Constants.BASTORE:
            {
                int offset = 3;
                if (opcode == Constants.LASTORE || opcode == Constants.DASTORE)
                    offset = 4;
                putResult(stmt, context, input.get(context.callString).getStack(context.stackPtr - offset));
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            }
            break;
        // changing the heap -> TOP
        case Constants.AASTORE:
            {
                putResult(stmt, context, input.get(context.callString).getStack(context.stackPtr - 3));
                AASTORE instr = (AASTORE) stmt.getInstruction();
                SymbolicAddressMap result = in.cloneFilterStack(newStackPtr);
                // Change alias information
                if (instr.getType(context.constPool()) instanceof ReferenceType) {
                    String ty = instr.getType(context.constPool()).getSignature();
                    result.addAlias(ty, in.getStack(context.stackPtr - 1));
                }
                retval.put(context.callString, result);
            }
            break;
        case Constants.DALOAD:
        case Constants.LALOAD:
        case Constants.IALOAD:
        case Constants.FALOAD:
        case Constants.CALOAD:
        case Constants.SALOAD:
        case Constants.BALOAD:
            {
                putResult(stmt, context, input.get(context.callString).getStack(context.stackPtr - 2));
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            }
            break;
        // TODO: Use index info
        case Constants.AALOAD:
            {
                putResult(stmt, context, input.get(context.callString).getStack(context.stackPtr - 2));
                //AALOAD instr = (AALOAD)instruction;
                SymbolicAddressMap result = in.cloneFilterStack(newStackPtr);
                BoundedSet<SymbolicAddress> objectMapping = in.getStack(context.stackPtr - 2);
                BoundedSet<SymbolicAddress> newMapping;
                LoopBounds bounds = interpreter.getDFATool().getLoopBounds();
                if (executedOnce.query(stmt)) {
                    newMapping = bsFactory.singleton(SymbolicAddress.newName());
                } else if (objectMapping.isSaturated() || bounds == null) {
                    newMapping = bsFactory.top();
                } else {
                    Interval interval = bounds.getArrayIndices(stmt, context.callString);
                    if (interval.hasLb() && interval.hasUb()) {
                        newMapping = bsFactory.empty();
                        for (SymbolicAddress addr : objectMapping.getSet()) {
                            for (int i = interval.getLb(); i <= interval.getUb(); i++) {
                                newMapping.add(addr.accessArray(i));
                            }
                        }
                    } else {
                        newMapping = bsFactory.top();
                    }
                }
                //				Doesn't work, but is probably stupid anyway :(
                //  			LoopBounds bounds = interpreter.getDFATool().getLoopBounds();
                //              bounds.getArraySizes().get(stmt).get(context.callString);
                //			    newMapping = bsFactory.empty();
                //				Interval[] sizeBounds = { new Interval(2,3) }; 
                //				for(Interval i : sizeBounds) {
                //					if(! i.hasUb()) {
                //						newMapping = bsFactory.top();
                //					}
                //					int ub = i.getUb();
                //					for(int j = 0; j <= ub; j++) {
                //						for(SymbolicAddress addr: objectMapping.getSet()) {
                //							newMapping.add(addr.accessArray(j));
                //						}					
                //					}
                //				}
                //			}
                result.putStack(context.stackPtr - 2, newMapping);
                retval.put(context.callString, result);
            }
            break;
        case Constants.DUP:
            {
                // copy value on stack
                SymbolicAddressMap result = in.cloneFilterStack(newStackPtr);
                result.copyStack(in, context.stackPtr, context.stackPtr - 1);
                retval.put(context.callString, result);
            }
            break;
        case Constants.DUP_X1:
            {
                // copy value on stack
                SymbolicAddressMap result = in.cloneFilterStack(context.stackPtr - 2);
                result.copyStack(in, context.stackPtr - 2, context.stackPtr - 1);
                result.copyStack(in, context.stackPtr - 1, context.stackPtr - 2);
                result.copyStack(in, context.stackPtr, context.stackPtr - 1);
                retval.put(context.callString, result);
            }
            break;
        case Constants.DUP_X2:
            {
                // copy value on stack
                SymbolicAddressMap result = in.cloneFilterStack(context.stackPtr - 3);
                result.copyStack(in, context.stackPtr - 3, context.stackPtr - 1);
                result.copyStack(in, context.stackPtr - 2, context.stackPtr - 3);
                result.copyStack(in, context.stackPtr - 1, context.stackPtr - 2);
                result.copyStack(in, context.stackPtr, context.stackPtr - 1);
                retval.put(context.callString, result);
            }
            break;
        case Constants.DUP2:
            {
                // v1,v2 -> v1,v2,v1,v2
                SymbolicAddressMap result = in.cloneFilterStack(context.stackPtr);
                result.copyStack(in, context.stackPtr, context.stackPtr - 2);
                result.copyStack(in, context.stackPtr + 1, context.stackPtr - 1);
                retval.put(context.callString, result);
            }
            break;
        case Constants.POP:
        case Constants.POP2:
            {
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            }
            break;
        case Constants.IINC:
            {
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            }
            break;
        case Constants.IADD:
        case Constants.ISUB:
        case Constants.INEG:
        case Constants.IUSHR:
        case Constants.ISHR:
        case Constants.IAND:
        case Constants.IOR:
        case Constants.IXOR:
        case Constants.IMUL:
        case Constants.IDIV:
        case Constants.IREM:
        case Constants.ISHL:
            {
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            }
            break;
        /* Long,Float and Double operations (boring) */
        case Constants.DADD:
        case Constants.DSUB:
        case Constants.DMUL:
        case Constants.DDIV:
        case Constants.DREM:
        case Constants.LADD:
        case Constants.LSUB:
        case Constants.LUSHR:
        case Constants.LSHR:
        case Constants.LAND:
        case Constants.LOR:
        case Constants.LXOR:
        case Constants.LMUL:
        case Constants.LDIV:
        case Constants.LREM:
        case Constants.LSHL:
        /* Instructions above need two stack slots */
        case Constants.DNEG:
        case Constants.LNEG:
        case Constants.FADD:
        case Constants.FSUB:
        case Constants.FNEG:
        case Constants.FMUL:
        case Constants.FDIV:
        case Constants.FREM:
            {
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            }
            break;
        /* Conversion of primitives (boring) */
        case Constants.D2F:
        case Constants.D2I:
        /* Instructions above need two stack slots */
        case Constants.D2L:
            {
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            }
            break;
        case Constants.L2F:
        case Constants.L2I:
        /* Instructions above need two stack slots */
        case Constants.L2D:
            {
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            }
            break;
        case Constants.F2D:
        case Constants.I2D:
        case Constants.F2L:
        case Constants.I2L:
        /* Instructions above need one stack slot less */
        case Constants.F2I:
        case Constants.I2B:
        case Constants.I2C:
        case Constants.I2F:
        case Constants.I2S:
            {
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            }
            break;
        case Constants.MONITORENTER:
            // not supported yet
            if (ASSUME_NO_CONC)
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            else
                retval.put(context.callString, SymbolicAddressMap.top());
            break;
        case Constants.MONITOREXIT:
            // not supported yet
            retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            break;
        case Constants.CHECKCAST:
            retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            break;
        case Constants.INSTANCEOF:
            {
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            }
            break;
        case Constants.NEW:
        case Constants.NEWARRAY:
        case Constants.ANEWARRAY:
            {
                SymbolicAddressMap result = in.cloneFilterStack(newStackPtr);
                BoundedSet<SymbolicAddress> newMapping;
                if (executedOnce.query(stmt)) {
                    newMapping = bsFactory.singleton(SymbolicAddress.newName());
                } else {
                    newMapping = bsFactory.top();
                }
                int objPtr = (instruction.getOpcode() == Constants.NEW) ? context.stackPtr : (context.stackPtr - 1);
                result.putStack(objPtr, newMapping);
                retval.put(context.callString, result);
            }
            break;
        case Constants.MULTIANEWARRAY:
            {
                // not supported yet
                retval.put(context.callString, SymbolicAddressMap.top());
            }
            break;
        case Constants.GOTO:
            retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            break;
        case Constants.IFNULL:
        case Constants.IFNONNULL:
            {
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            }
            break;
        case Constants.IF_ACMPEQ:
        case Constants.IF_ACMPNE:
            {
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            }
            break;
        case Constants.IFEQ:
        case Constants.IFNE:
        case Constants.IFLT:
        case Constants.IFGE:
        case Constants.IFLE:
        case Constants.IFGT:
            retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            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:
            retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            break;
        case Constants.LOOKUPSWITCH:
        case Constants.TABLESWITCH:
            retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            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);
                retval.put(context.callString, new SymbolicAddressMap(bsFactory));
                if (receivers == null || receivers.size() == 0) {
                    String errMsg = String.format("%s : invoke %s: %s receivers", context.method(), instruction.toString(context.constPool().getConstantPool()), (receivers == null ? "Unknown" : "No"));
                    // Get static receivers (FIXME: this just workarounds DFA bugs)
                    if (opcode == Constants.INVOKESTATIC) {
                        receivers = new HashSet<String>();
                        InvokeInstruction invInstruction = (InvokeInstruction) instruction;
                        String klass = invInstruction.getClassName(context.constPool());
                        String name = invInstruction.getMethodName(context.constPool());
                        String sig = invInstruction.getSignature(context.constPool());
                        String recv = klass + "." + name + sig;
                        Logger.getLogger(this.getClass()).info("Using static receiver: " + recv);
                        receivers.add(recv);
                    } else {
                        Logger.getLogger(this.getClass()).error(errMsg);
                        throw new AssertionError(errMsg);
                    }
                }
                if (instruction.getOpcode() == Constants.INVOKEVIRTUAL || instruction.getOpcode() == Constants.INVOKEINTERFACE) {
                    MethodInfo mi = p.getMethod(receivers.iterator().next());
                    int refPos = MethodHelper.getArgSize(mi);
                    //						mi.methodId,refPos,context.stackPtr,input.get(context.callString)));
                    try {
                        putResult(stmt, context, input.get(context.callString).getStack(context.stackPtr - refPos));
                    } catch (Error e) {
                        System.err.println("We have problems with method " + mi);
                        System.err.println(e.getMessage());
                    }
                }
                for (String methodName : receivers) {
                    doInvoke(methodName, stmt, context, input, interpreter, state, retval);
                }
            }
            break;
        case Constants.ARETURN:
            {
                SymbolicAddressMap result = in.cloneFilterStack(0);
                // store results
                result.copyStack(in, 0, context.stackPtr - 1);
                retval.put(context.callString, result);
            }
            break;
        /* The values of other return statements are not of interest here */
        case Constants.DRETURN:
        case Constants.LRETURN:
        case Constants.FRETURN:
        case Constants.IRETURN:
        case Constants.RETURN:
            {
                retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            }
            break;
        default:
            System.err.println("unknown instruction: " + stmt + " in method " + context.method());
            retval.put(context.callString, in.cloneFilterStack(newStackPtr));
            break;
    }
    // DEBUGGING
    if (DEBUG_PRINT) {
        System.out.println("[F] " + context.method() + " / " + stmt);
        System.out.println("  Stackptr: " + context.stackPtr + " -> " + newStackPtr);
        System.out.println("  Before: ");
        input.get(context.callString).print(System.out, 4);
        System.out.println("  After: ");
        retval.get(context.callString).print(System.out, 4);
    }
    context.stackPtr = newStackPtr;
    return retval;
}
Also used : HashSet(java.util.HashSet) Set(java.util.Set) BoundedSet(com.jopdesign.dfa.framework.BoundedSetFactory.BoundedSet) LDC(org.apache.bcel.generic.LDC) CallString(com.jopdesign.common.code.CallString) InvokeInstruction(org.apache.bcel.generic.InvokeInstruction) ArrayInstruction(org.apache.bcel.generic.ArrayInstruction) LoadInstruction(org.apache.bcel.generic.LoadInstruction) StoreInstruction(org.apache.bcel.generic.StoreInstruction) Instruction(org.apache.bcel.generic.Instruction) FieldInstruction(org.apache.bcel.generic.FieldInstruction) ReferenceType(org.apache.bcel.generic.ReferenceType) PUTSTATIC(org.apache.bcel.generic.PUTSTATIC) LoadInstruction(org.apache.bcel.generic.LoadInstruction) HashSet(java.util.HashSet) Context(com.jopdesign.dfa.framework.Context) DFATool(com.jopdesign.dfa.DFATool) PUTFIELD(org.apache.bcel.generic.PUTFIELD) AppInfoError(com.jopdesign.common.misc.AppInfoError) ContextMap(com.jopdesign.dfa.framework.ContextMap) CallString(com.jopdesign.common.code.CallString) GETFIELD(org.apache.bcel.generic.GETFIELD) BoundedSet(com.jopdesign.dfa.framework.BoundedSetFactory.BoundedSet) InvokeInstruction(org.apache.bcel.generic.InvokeInstruction) ReferenceType(org.apache.bcel.generic.ReferenceType) Type(org.apache.bcel.generic.Type) AASTORE(org.apache.bcel.generic.AASTORE) MethodInfo(com.jopdesign.common.MethodInfo) GETSTATIC(org.apache.bcel.generic.GETSTATIC) StoreInstruction(org.apache.bcel.generic.StoreInstruction)

Example 3 with PUTFIELD

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

the class CallStringReceiverTypes method transfer.

public ContextMap<CallString, Set<TypeMapping>> transfer(InstructionHandle stmt, FlowEdge edge, ContextMap<CallString, Set<TypeMapping>> input, Interpreter<CallString, Set<TypeMapping>> interpreter, Map<InstructionHandle, ContextMap<CallString, Set<TypeMapping>>> state) {
    Context context = new Context(input.getContext());
    Set<TypeMapping> in = input.get(context.callString);
    ContextMap<CallString, Set<TypeMapping>> retval = new ContextMap<CallString, Set<TypeMapping>>(context, new LinkedHashMap<CallString, Set<TypeMapping>>());
    Set<TypeMapping> result = new LinkedHashSet<TypeMapping>();
    retval.put(context.callString, result);
    Instruction instruction = stmt.getInstruction();
    switch(instruction.getOpcode()) {
        case Constants.NOP:
            result = in;
            retval.put(context.callString, result);
            break;
        case Constants.ACONST_NULL:
        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:
        case Constants.FCONST_0:
        case Constants.FCONST_1:
        case Constants.FCONST_2:
        case Constants.LCONST_0:
        case Constants.LCONST_1:
        case Constants.DCONST_0:
        case Constants.DCONST_1:
        case Constants.LDC2_W:
            result = in;
            retval.put(context.callString, result);
            break;
        case Constants.LDC:
        case Constants.LDC_W:
            {
                LDC instr = (LDC) instruction;
                result = new LinkedHashSet<TypeMapping>(in);
                retval.put(context.callString, result);
                Type type = instr.getType(context.constPool());
                if (type.equals(Type.STRING)) {
                    result.add(new TypeMapping(context.stackPtr, type.toString()));
                    String value = type.toString() + ".value";
                    String name = "char[]";
                    name += "@" + context.method() + ":" + stmt.getPosition();
                    result.add(new TypeMapping(value, name));
                }
            }
            break;
        case Constants.DUP:
            {
                for (TypeMapping m : in) {
                    result.add(m);
                    if (m.stackLoc == context.stackPtr - 1) {
                        result.add(new TypeMapping(context.stackPtr, m.type));
                    }
                }
            }
            break;
        case Constants.DUP_X1:
            {
                for (TypeMapping m : in) {
                    if (m.stackLoc < context.stackPtr - 2) {
                        result.add(m);
                    }
                    if (m.stackLoc == context.stackPtr - 1) {
                        result.add(new TypeMapping(context.stackPtr - 2, m.type));
                        result.add(new TypeMapping(context.stackPtr, m.type));
                    }
                    if (m.stackLoc == context.stackPtr - 2) {
                        result.add(new TypeMapping(context.stackPtr - 1, m.type));
                    }
                }
            }
            break;
        case Constants.DUP_X2:
            {
                for (TypeMapping m : in) {
                    if (m.stackLoc < context.stackPtr - 3) {
                        result.add(m);
                    }
                    if (m.stackLoc == context.stackPtr - 1) {
                        result.add(new TypeMapping(context.stackPtr - 3, m.type));
                        result.add(new TypeMapping(context.stackPtr, m.type));
                    }
                    if (m.stackLoc == context.stackPtr - 2) {
                        result.add(new TypeMapping(context.stackPtr - 1, m.type));
                    }
                    if (m.stackLoc == context.stackPtr - 3) {
                        result.add(new TypeMapping(context.stackPtr - 2, m.type));
                    }
                }
            }
            break;
        case Constants.DUP2:
            {
                for (TypeMapping m : in) {
                    result.add(m);
                    if (m.stackLoc == context.stackPtr - 2) {
                        result.add(new TypeMapping(context.stackPtr, m.type));
                    }
                    if (m.stackLoc == context.stackPtr - 1) {
                        result.add(new TypeMapping(context.stackPtr + 1, m.type));
                    }
                }
            }
            break;
        case Constants.DUP2_X1:
            {
                for (TypeMapping m : in) {
                    if (m.stackLoc < context.stackPtr - 3) {
                        result.add(m);
                    }
                    if (m.stackLoc == context.stackPtr - 2) {
                        result.add(new TypeMapping(context.stackPtr - 3, m.type));
                        result.add(new TypeMapping(context.stackPtr, m.type));
                    }
                    if (m.stackLoc == context.stackPtr - 1) {
                        result.add(new TypeMapping(context.stackPtr - 2, m.type));
                        result.add(new TypeMapping(context.stackPtr + 1, m.type));
                    }
                    if (m.stackLoc == context.stackPtr - 3) {
                        result.add(new TypeMapping(context.stackPtr - 1, m.type));
                    }
                }
            }
            break;
        case Constants.DUP2_X2:
            {
                for (TypeMapping m : in) {
                    if (m.stackLoc < context.stackPtr - 3) {
                        result.add(m);
                    }
                    if (m.stackLoc == context.stackPtr - 2) {
                        result.add(new TypeMapping(context.stackPtr - 4, m.type));
                        result.add(new TypeMapping(context.stackPtr, m.type));
                    }
                    if (m.stackLoc == context.stackPtr - 1) {
                        result.add(new TypeMapping(context.stackPtr - 3, m.type));
                        result.add(new TypeMapping(context.stackPtr + 1, m.type));
                    }
                    if (m.stackLoc == context.stackPtr - 4) {
                        result.add(new TypeMapping(context.stackPtr - 2, m.type));
                    }
                    if (m.stackLoc == context.stackPtr - 3) {
                        result.add(new TypeMapping(context.stackPtr - 1, m.type));
                    }
                }
            }
            break;
        case Constants.SWAP:
            {
                for (TypeMapping m : in) {
                    if (m.stackLoc < context.stackPtr - 2) {
                        result.add(m);
                    }
                    if (m.stackLoc == context.stackPtr - 2) {
                        result.add(new TypeMapping(context.stackPtr - 1, m.type));
                    }
                    if (m.stackLoc == context.stackPtr - 1) {
                        result.add(new TypeMapping(context.stackPtr - 2, m.type));
                    }
                }
            }
            break;
        case Constants.POP:
            filterSet(in, result, context.stackPtr - 1);
            break;
        case Constants.POP2:
            filterSet(in, result, context.stackPtr - 2);
            break;
        case Constants.GETFIELD:
            {
                GETFIELD instr = (GETFIELD) instruction;
                List<String> receivers = new LinkedList<String>();
                for (TypeMapping m : in) {
                    if (m.stackLoc < context.stackPtr - 1) {
                        result.add(m);
                    } else if (m.stackLoc == context.stackPtr - 1) {
                        receivers.add(m.type);
                    }
                }
                //			if (receivers.isEmpty()
                //				&& instr.getFieldType(context.constPool) != Type.INT) {
                //				System.out.println("GETFIELD not found: "+context.method+"@"+stmt+": "+instr.getFieldName(context.constPool));
                ////				System.exit(1);
                //			}
                DFATool p = interpreter.getDFATool();
                String fieldName = instr.getFieldName(context.constPool());
                for (String receiver : receivers) {
                    //String heapLoc = receiver + "." + instr.getFieldName(context.constPool);
                    //String namedLoc = receiver.split("@")[0] + "." + instr.getFieldName(context.constPool);
                    String className = receiver.split("@")[0];
                    ClassInfo classInfo = p.classForField(className, fieldName);
                    if (classInfo != null) {
                        String heapLoc = classInfo.getClassName() + "." + fieldName;
                        recordReceiver(stmt, context, heapLoc);
                        for (TypeMapping m : in) {
                            if (heapLoc.equals(m.heapLoc)) {
                                result.add(new TypeMapping(context.stackPtr - 1, m.type));
                            }
                        }
                    }
                }
            }
            break;
        case Constants.PUTFIELD:
            {
                PUTFIELD instr = (PUTFIELD) instruction;
                List<String> receivers = new LinkedList<String>();
                int fieldSize = instr.getFieldType(context.constPool()).getSize();
                for (TypeMapping m : in) {
                    if (m.stackLoc < context.stackPtr - 1 - fieldSize) {
                        result.add(m);
                    } else if (m.stackLoc == context.stackPtr - 1 - fieldSize) {
                        receivers.add(m.type);
                    }
                }
                //			if (receivers.isEmpty()) {
                //				System.out.println("PUTFIELD not found: "+context.method+"@"+stmt+": "+instr.getFieldName(context.constPool));
                ////				System.exit(-1);
                //			}
                DFATool p = interpreter.getDFATool();
                String fieldName = instr.getFieldName(context.constPool());
                for (String receiver : receivers) {
                    //String heapLoc = receiver + "." + instr.getFieldName(context.constPool);
                    //String namedLoc = receiver.split("@")[0] + "." + instr.getFieldName(context.constPool);
                    String className = receiver.split("@")[0];
                    ClassInfo classInfo = p.classForField(className, fieldName);
                    if (classInfo != null) {
                        String heapLoc = classInfo.getClassName() + "." + fieldName;
                        recordReceiver(stmt, context, heapLoc);
                        for (TypeMapping m : in) {
                            if (!heapLoc.equals(m.heapLoc) || context.threaded) {
                                result.add(m);
                            }
                            if (m.stackLoc == context.stackPtr - 1) {
                                result.add(new TypeMapping(heapLoc, m.type));
                            }
                        }
                    }
                }
                if (instr.getFieldType(context.constPool()) instanceof ReferenceType) {
                    doInvokeStatic("com.jopdesign.sys.JVM.f_putfield_ref(III)V", stmt, context, input, interpreter, state, retval);
                }
            }
            break;
        case Constants.GETSTATIC:
            {
                GETSTATIC instr = (GETSTATIC) instruction;
                DFATool p = interpreter.getDFATool();
                FieldRef ref = context.getMethodInfo().getCode().getFieldRef(instr);
                String fieldName = ref.getName();
                String className = ref.getClassName();
                ClassInfo classInfo = p.classForField(className, fieldName);
                if (classInfo != null) {
                    String heapLoc = classInfo.getClassName() + "." + fieldName;
                    recordReceiver(stmt, context, heapLoc);
                    for (TypeMapping m : in) {
                        if (m.stackLoc < context.stackPtr) {
                            result.add(m);
                        }
                        if (heapLoc.equals(m.heapLoc)) {
                            result.add(new TypeMapping(context.stackPtr, m.type));
                        }
                    }
                } else {
                //				System.out.println("GETSTATIC not found: "+heapLoc);
                //				System.exit(1);
                }
            }
            break;
        case Constants.PUTSTATIC:
            {
                PUTSTATIC instr = (PUTSTATIC) instruction;
                DFATool p = interpreter.getDFATool();
                FieldRef ref = context.getMethodInfo().getCode().getFieldRef(instr);
                String fieldName = ref.getName();
                String className = ref.getClassName();
                ClassInfo classInfo = p.classForField(className, fieldName);
                if (classInfo != null) {
                    String heapLoc = classInfo.getClassName() + "." + fieldName;
                    recordReceiver(stmt, context, heapLoc);
                    for (TypeMapping m : in) {
                        if (m.stackLoc >= 0 && m.stackLoc < context.stackPtr - 1) {
                            result.add(m);
                        } else if (m.stackLoc == -1 && (!heapLoc.equals(m.heapLoc) || context.threaded)) {
                            result.add(m);
                        }
                        if (m.stackLoc == context.stackPtr - 1) {
                            result.add(new TypeMapping(heapLoc, m.type));
                        }
                    }
                } else {
                //				System.out.println("PUTSTATIC not found: "+heapLoc);
                //				System.exit(1);
                }
                if (instr.getFieldType(context.constPool()) instanceof ReferenceType) {
                    doInvokeStatic("com.jopdesign.sys.JVM.f_putstatic_ref(II)V", stmt, context, input, interpreter, state, retval);
                }
            }
            break;
        case Constants.ARRAYLENGTH:
            for (TypeMapping m : in) {
                if (m.stackLoc < context.stackPtr - 1) {
                    result.add(m);
                }
                if (m.stackLoc == context.stackPtr - 1) {
                    recordReceiver(stmt, context, m.type);
                }
            }
            break;
        case Constants.IASTORE:
        case Constants.BASTORE:
        case Constants.CASTORE:
        case Constants.SASTORE:
        case Constants.FASTORE:
            {
                for (TypeMapping m : in) {
                    if (m.stackLoc < context.stackPtr - 3) {
                        result.add(m);
                    }
                    if (m.stackLoc == context.stackPtr - 3) {
                        recordReceiver(stmt, context, m.type);
                    }
                }
            }
            break;
        case Constants.LASTORE:
        case Constants.DASTORE:
            {
                for (TypeMapping m : in) {
                    if (m.stackLoc < context.stackPtr - 4) {
                        result.add(m);
                    }
                    if (m.stackLoc == context.stackPtr - 4) {
                        recordReceiver(stmt, context, m.type);
                    }
                }
            }
            break;
        case Constants.AASTORE:
            {
                List<String> receivers = new LinkedList<String>();
                for (TypeMapping m : in) {
                    if (m.stackLoc < context.stackPtr - 3) {
                        result.add(m);
                    } else if (m.stackLoc == context.stackPtr - 3) {
                        receivers.add(m.type);
                        recordReceiver(stmt, context, m.type);
                    }
                }
                for (String healLoc : receivers) {
                    for (TypeMapping m : in) {
                        if (m.stackLoc == context.stackPtr - 1) {
                            result.add(new TypeMapping(healLoc, m.type));
                        }
                    }
                }
                doInvokeStatic("com.jopdesign.sys.JVM.f_aastore(III)V", stmt, context, input, interpreter, state, retval);
            }
            break;
        case Constants.IALOAD:
        case Constants.BALOAD:
        case Constants.CALOAD:
        case Constants.SALOAD:
        case Constants.FALOAD:
            {
                for (TypeMapping m : in) {
                    if (m.stackLoc < context.stackPtr - 2) {
                        result.add(m);
                    }
                    if (m.stackLoc == context.stackPtr - 2) {
                        recordReceiver(stmt, context, m.type);
                    }
                }
            }
            break;
        case Constants.LALOAD:
        case Constants.DALOAD:
            {
                for (TypeMapping m : in) {
                    if (m.stackLoc < context.stackPtr - 2) {
                        result.add(m);
                    }
                    if (m.stackLoc == context.stackPtr - 2) {
                        recordReceiver(stmt, context, m.type);
                    }
                }
            }
            break;
        case Constants.AALOAD:
            {
                List<String> receivers = new LinkedList<String>();
                for (TypeMapping m : in) {
                    if (m.stackLoc < context.stackPtr - 2) {
                        result.add(m);
                    } else if (m.stackLoc == context.stackPtr - 2) {
                        receivers.add(m.type);
                        recordReceiver(stmt, context, m.type);
                    }
                }
                for (String heapLoc : receivers) {
                    for (TypeMapping m : in) {
                        if (heapLoc.equals(m.heapLoc)) {
                            result.add(new TypeMapping(context.stackPtr - 2, m.type));
                        }
                    }
                }
            }
            break;
        case Constants.NEW:
            {
                NEW instr = (NEW) instruction;
                filterSet(in, result, context.stackPtr);
                String name = instr.getType(context.constPool()).toString();
                name += "@" + context.method() + ":" + stmt.getPosition();
                result.add(new TypeMapping(context.stackPtr, name));
                doInvokeStatic("com.jopdesign.sys.JVM.f_" + stmt.getInstruction().getName() + "(I)I", stmt, context, input, interpreter, state, retval);
            }
            break;
        case Constants.ANEWARRAY:
            {
                ANEWARRAY instr = (ANEWARRAY) instruction;
                filterSet(in, result, context.stackPtr - 1);
                String name = instr.getType(context.constPool()).toString() + "[]";
                name += "@" + context.method() + ":" + stmt.getPosition();
                result.add(new TypeMapping(context.stackPtr - 1, name));
                doInvokeStatic("com.jopdesign.sys.JVM.f_" + stmt.getInstruction().getName() + "(II)I", stmt, context, input, interpreter, state, retval);
            }
            break;
        case Constants.NEWARRAY:
            {
                NEWARRAY instr = (NEWARRAY) instruction;
                filterSet(in, result, context.stackPtr - 1);
                String name = instr.getType().toString();
                name += "@" + context.method() + ":" + stmt.getPosition();
                result.add(new TypeMapping(context.stackPtr - 1, name));
                doInvokeStatic("com.jopdesign.sys.JVM.f_" + stmt.getInstruction().getName() + "(II)I", stmt, context, input, interpreter, state, retval);
            }
            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("["));
                for (int i = 1; i <= dim; i++) {
                    String type1 = type;
                    String type2 = type;
                    for (int k = 0; k < i; k++) {
                        type1 += "[]";
                    }
                    for (int k = 0; k < i - 1; k++) {
                        type2 += "[]";
                    }
                    type1 += "@" + context.method() + ":" + stmt.getPosition();
                    type2 += "@" + context.method() + ":" + stmt.getPosition();
                    result.add(new TypeMapping(type1, type2));
                }
                String name = instr.getType(context.constPool()).toString();
                name += "@" + context.method() + ":" + stmt.getPosition();
                result.add(new TypeMapping(context.stackPtr - dim, name));
                doInvokeStatic("com.jopdesign.sys.JVM.f_" + stmt.getInstruction().getName() + "()I", stmt, context, input, interpreter, state, retval);
            }
            break;
        case Constants.ILOAD_0:
        case Constants.ILOAD_1:
        case Constants.ILOAD_2:
        case Constants.ILOAD_3:
        case Constants.ILOAD:
        case Constants.FLOAD_0:
        case Constants.FLOAD_1:
        case Constants.FLOAD_2:
        case Constants.FLOAD_3:
        case Constants.FLOAD:
        case Constants.LLOAD_0:
        case Constants.LLOAD_1:
        case Constants.LLOAD_2:
        case Constants.LLOAD_3:
        case Constants.LLOAD:
        case Constants.DLOAD_0:
        case Constants.DLOAD_1:
        case Constants.DLOAD_2:
        case Constants.DLOAD_3:
        case Constants.DLOAD:
            result = in;
            retval.put(context.callString, result);
            break;
        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();
                for (TypeMapping m : in) {
                    if (m.stackLoc < context.stackPtr) {
                        result.add(m);
                    }
                    if (m.stackLoc == index) {
                        result.add(new TypeMapping(context.stackPtr, m.type));
                    }
                }
            }
            break;
        case Constants.ISTORE_0:
        case Constants.ISTORE_1:
        case Constants.ISTORE_2:
        case Constants.ISTORE_3:
        case Constants.ISTORE:
        case Constants.FSTORE_0:
        case Constants.FSTORE_1:
        case Constants.FSTORE_2:
        case Constants.FSTORE_3:
        case Constants.FSTORE:
        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:
            result = in;
            retval.put(context.callString, result);
            break;
        case Constants.ASTORE_0:
        case Constants.ASTORE_1:
        case Constants.ASTORE_2:
        case Constants.ASTORE_3:
        case Constants.ASTORE:
            {
                StoreInstruction instr = (StoreInstruction) instruction;
                int index = instr.getIndex();
                for (TypeMapping m : in) {
                    if (m.stackLoc < context.stackPtr - 1 && m.stackLoc != index) {
                        result.add(m);
                    }
                    if (m.stackLoc == context.stackPtr - 1) {
                        result.add(new TypeMapping(index, m.type));
                    }
                }
            }
            break;
        case Constants.FCMPL:
        case Constants.FCMPG:
        case Constants.LCMP:
        case Constants.DCMPL:
        case Constants.DCMPG:
            result = in;
            retval.put(context.callString, result);
            break;
        case Constants.IFEQ:
        case Constants.IFNE:
        case Constants.IFLT:
        case Constants.IFGE:
        case Constants.IFGT:
        case Constants.IFLE:
        case Constants.IFNULL:
        case Constants.IFNONNULL:
            filterSet(in, result, context.stackPtr - 1);
            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:
            filterSet(in, result, context.stackPtr - 2);
            break;
        case Constants.TABLESWITCH:
        case Constants.LOOKUPSWITCH:
            filterSet(in, result, context.stackPtr - 1);
            break;
        case Constants.GOTO:
            result = in;
            retval.put(context.callString, result);
            break;
        case Constants.IADD:
        case Constants.ISUB:
        case Constants.IMUL:
        case Constants.IDIV:
        case Constants.IREM:
        case Constants.ISHL:
        case Constants.ISHR:
        case Constants.IUSHR:
        case Constants.IAND:
        case Constants.IOR:
        case Constants.IXOR:
        case Constants.FADD:
        case Constants.FSUB:
        case Constants.FMUL:
        case Constants.FDIV:
        case Constants.FREM:
        case Constants.DADD:
        case Constants.DSUB:
        case Constants.DMUL:
        case Constants.DDIV:
        case Constants.DREM:
        case Constants.IINC:
        case Constants.INEG:
        case Constants.FNEG:
        case Constants.LNEG:
        case Constants.DNEG:
        case Constants.LADD:
        case Constants.LAND:
        case Constants.LOR:
        case Constants.LXOR:
        case Constants.LSUB:
        case Constants.LSHL:
        case Constants.LSHR:
        case Constants.LUSHR:
            result = in;
            retval.put(context.callString, result);
            break;
        case Constants.LMUL:
        case Constants.LDIV:
        case Constants.LREM:
            result = new LinkedHashSet<TypeMapping>(in);
            retval.put(context.callString, result);
            doInvokeStatic("com.jopdesign.sys.JVM.f_" + stmt.getInstruction().getName() + "(JJ)J", stmt, context, input, interpreter, state, retval);
            break;
        case Constants.I2B:
        case Constants.I2C:
        case Constants.I2S:
        case Constants.I2F:
        case Constants.F2I:
        case Constants.I2L:
        case Constants.I2D:
        case Constants.F2L:
        case Constants.F2D:
        case Constants.L2I:
        case Constants.D2I:
        case Constants.L2F:
        case Constants.D2F:
        case Constants.L2D:
        case Constants.D2L:
            result = in;
            retval.put(context.callString, result);
            break;
        case Constants.INSTANCEOF:
            filterSet(in, result, context.stackPtr - 1);
            break;
        case Constants.CHECKCAST:
            {
                DFATool p = interpreter.getDFATool();
                CHECKCAST instr = (CHECKCAST) instruction;
                for (TypeMapping m : in) {
                    if (m.stackLoc < context.stackPtr - 1) {
                        result.add(m);
                    }
                    if (m.stackLoc == context.stackPtr - 1) {
                        // check whether this class can possibly be cast
                        String constClassName = instr.getType(context.constPool()).toString();
                        ClassInfo staticClass = p.getAppInfo().getClassInfo(constClassName);
                        ClassInfo dynamicClass = p.getAppInfo().getClassInfo(m.type.split("@")[0]);
                        //					System.out.println("CHECKCAST: "+context.callString.asList()+"/"+context.method+": "+stmt+": "+constClassName+" vs "+m.type);
                        if (dynamicClass.isSubclassOf(staticClass)) {
                            result.add(m);
                        //							System.out.println("yay!");
                        }
                    }
                }
            }
            break;
        case Constants.MONITORENTER:
            filterSet(in, result, context.stackPtr - 1);
            context.syncLevel++;
            break;
        case Constants.MONITOREXIT:
            filterSet(in, result, context.stackPtr - 1);
            context.syncLevel--;
            if (context.syncLevel < 0) {
                System.err.println("Synchronization level mismatch.");
                System.exit(-1);
            }
            break;
        case Constants.INVOKEVIRTUAL:
        case Constants.INVOKEINTERFACE:
            {
                InvokeInstruction instr = (InvokeInstruction) instruction;
                int argSize = MethodHelper.getArgSize(instr, context.constPool());
                DFATool p = interpreter.getDFATool();
                MethodRef ref = context.getMethodInfo().getCode().getInvokeSite(stmt).getInvokeeRef();
                ClassInfo constClass = ref.getClassInfo();
                // find possible receiver types
                List<String> receivers = new LinkedList<String>();
                for (TypeMapping m : in) {
                    if (m.stackLoc == context.stackPtr - argSize) {
                        String clName = m.type.split("@")[0];
                        ClassInfo dynamicClass;
                        // check whether this class can possibly be a receiver
                        try {
                            dynamicClass = p.getAppInfo().getClassInfo(clName);
                        } catch (MissingClassError ex) {
                            logger.error("TRANSFER/" + instr + ": " + ex);
                            continue;
                        }
                        if ((instr instanceof INVOKEVIRTUAL && dynamicClass.isSubclassOf(constClass)) || (instr instanceof INVOKEINTERFACE && dynamicClass.isImplementationOf(constClass))) {
                            receivers.add(clName);
                        } else {
                            logger.debug(context.method() + ": class " + constClass + " is not a superclass of " + clName);
                        }
                    }
                }
                /* Get the actual set of invoked methods */
                //ArrayList<MethodInfo> invokeCandidates = new ArrayList<MethodInfo>();
                String signature = ref.getMethodSignature();
                for (String receiver : receivers) {
                    // find receiving method
                    MethodInfo impl = p.getAppInfo().getMethodInfoInherited(receiver, signature);
                    if (impl == null) {
                        throw new AppInfoError("Could not find implementation for: " + receiver + "#" + signature);
                    }
                    doInvokeVirtual(receiver, impl, stmt, context, input, interpreter, state, retval);
                }
                // add relevant information to result
                filterSet(in, result, context.stackPtr - argSize);
            }
            break;
        case Constants.INVOKESTATIC:
        case Constants.INVOKESPECIAL:
            {
                InvokeInstruction instr = (InvokeInstruction) instruction;
                int argSize = MethodHelper.getArgSize(instr, context.constPool());
                MethodRef ref = context.getMethodInfo().getCode().getInvokeSite(stmt).getInvokeeRef();
                MethodInfo impl = ref.getMethodInfo();
                if (impl == null) {
                    throw new AppInfoError("Cannot find implementation of " + ref);
                } else if (impl.isPrivate() && !impl.isStatic()) {
                    doInvokeVirtual(ref.getClassName(), impl, stmt, context, input, interpreter, state, retval);
                } else {
                    doInvokeStatic(impl.getMemberID().toString(), stmt, context, input, interpreter, state, retval);
                }
                // add relevant information to result
                filterSet(in, result, context.stackPtr - argSize);
            }
            break;
        case Constants.RETURN:
        case Constants.IRETURN:
        case Constants.FRETURN:
        case Constants.LRETURN:
        case Constants.DRETURN:
            filterSet(in, result, 0);
            break;
        case Constants.ARETURN:
            {
                for (TypeMapping m : in) {
                    if (m.stackLoc < 0) {
                        result.add(m);
                    }
                    if (m.stackLoc == context.stackPtr - 1) {
                        result.add(new TypeMapping(0, m.type));
                    }
                }
            }
            break;
        default:
            System.out.println("Unknown opcode: " + instruction.toString(context.constPool().getConstantPool()));
            System.exit(-1);
    }
    //		System.out.print(instruction+":\t{ ");
    //		for (Iterator k = result.iterator(); k.hasNext(); ) {
    //			ReceiverTypes.TypeMapping m = (ReceiverTypes.TypeMapping) k.next();
    //			if (m.stackLoc >= 0) {
    //				System.out.print("<stack[" + m.stackLoc + "], " + m.type +">, ");
    //			} else {
    //				System.out.print("<" + m.heapLoc + ", " + m.type +">, ");						
    //			}
    //		}
    //		System.out.println("}");				
    //		System.out.println("AFTER "+context.method+": "+stmt+" / "+context.callString.asList());
    //		System.out.print(stmt.getInstruction()+":\t{ ");
    //		System.out.print(context.callString.asList()+": "+retval.get(context.callString));
    //		System.out.println(" }");
    context.stackPtr += instruction.produceStack(context.constPool()) - instruction.consumeStack(context.constPool());
    return retval;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) NEW(org.apache.bcel.generic.NEW) LinkedHashSet(java.util.LinkedHashSet) Set(java.util.Set) MULTIANEWARRAY(org.apache.bcel.generic.MULTIANEWARRAY) ANEWARRAY(org.apache.bcel.generic.ANEWARRAY) CHECKCAST(org.apache.bcel.generic.CHECKCAST) LDC(org.apache.bcel.generic.LDC) CallString(com.jopdesign.common.code.CallString) InvokeInstruction(org.apache.bcel.generic.InvokeInstruction) LoadInstruction(org.apache.bcel.generic.LoadInstruction) StoreInstruction(org.apache.bcel.generic.StoreInstruction) Instruction(org.apache.bcel.generic.Instruction) ReferenceType(org.apache.bcel.generic.ReferenceType) AppInfoError(com.jopdesign.common.misc.AppInfoError) PUTSTATIC(org.apache.bcel.generic.PUTSTATIC) LoadInstruction(org.apache.bcel.generic.LoadInstruction) MethodRef(com.jopdesign.common.type.MethodRef) LinkedList(java.util.LinkedList) List(java.util.List) MissingClassError(com.jopdesign.common.misc.MissingClassError) 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) FieldRef(com.jopdesign.common.type.FieldRef) 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) InvokeInstruction(org.apache.bcel.generic.InvokeInstruction) ReferenceType(org.apache.bcel.generic.ReferenceType) Type(org.apache.bcel.generic.Type) INVOKEINTERFACE(org.apache.bcel.generic.INVOKEINTERFACE) MethodInfo(com.jopdesign.common.MethodInfo) GETSTATIC(org.apache.bcel.generic.GETSTATIC) StoreInstruction(org.apache.bcel.generic.StoreInstruction) INVOKEVIRTUAL(org.apache.bcel.generic.INVOKEVIRTUAL) ClassInfo(com.jopdesign.common.ClassInfo)

Example 4 with PUTFIELD

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

the class InlineHelper method needsNullpointerCheck.

/**
     * Check if an exception must be generated if the 'this' reference is null.
     * This test can return false if
     * <ul><li>There is no 'this' reference</li>
     * <li>The DFA analysis showed that the reference is never null</li>
     * <li>The inlined code will always generate an exception anyway</li>
     * <li>Generating checks has been disabled by configuration</li>
     * </ul>
     * <p>
     * The callstring does not need to start or to end at the method to optimize. However since the callstring is
     * used to check the DFA results if available, the callstring must match what the DFA expects, i.e. if
     * the DFA-results and -callstrings are updated during inlining, this callstring must not include inlined
     * invokes. Contrariwise if the DFA results are not updated during inline, the callstring must contain already
     * inlined invokes.
     * </p>
     *
     * @param callString The callstring including the invokesite of the invokee. The top invokesite does not need to
     *                   refer to an invoke instruction, and the referenced invoker method does not need to
     *                   be the method containing the invoke to inline (e.g. if the invoke to inline has
     *                   been inlined itself). However the callstring needs to match what the DFA expects.
     * @param invokee the devirtualized invokee.
     * @param analyzeCode if false, skip checking the code of the invokee.
     * @return true if a nullpointer check code should be generated.
     */
public boolean needsNullpointerCheck(CallString callString, MethodInfo invokee, boolean analyzeCode) {
    if (inlineConfig.skipNullpointerChecks())
        return false;
    InvokeSite invokeSite = callString.top();
    // check if we have a 'this' reference anyway
    if (invokeSite.isInvokeStatic() || invokeSite.isJVMCall()) {
        return false;
    }
    // TODO check the DFA results if available
    if (jcopter.useDFA()) {
    } else if ("<init>".equals(invokee.getShortName())) {
        // the NP check in this case (and hope that compilers for languages other than Java do the same..)
        return false;
    }
    if (!analyzeCode) {
        return true;
    }
    // check if the code will always throw an exception anyway (without producing any side effects before throwing)
    ValueMapAnalysis analysis = new ValueMapAnalysis(invokee);
    analysis.loadParameters();
    InstructionList list = invokee.getCode().getInstructionList(true, false);
    for (InstructionHandle ih : list.getInstructionHandles()) {
        Instruction instr = ih.getInstruction();
        if (instr instanceof ConstantPushInstruction || instr instanceof LocalVariableInstruction) {
            analysis.transfer(instr);
        } else if (instr instanceof GETFIELD || instr instanceof PUTFIELD || instr instanceof INVOKEVIRTUAL || instr instanceof INVOKEINTERFACE || instr instanceof INVOKESPECIAL) {
            int down = instr.consumeStack(invokee.getConstantPoolGen());
            ValueInfo value = analysis.getValueTable().top(down);
            // the same way as the inlined invoke
            if (value.isThisReference()) {
                return false;
            }
            break;
        } else {
            // we ignore all other instructions (for now..)
            break;
        }
    }
    return true;
}
Also used : ValueMapAnalysis(com.jopdesign.jcopter.analysis.ValueMapAnalysis) InstructionList(org.apache.bcel.generic.InstructionList) PUTFIELD(org.apache.bcel.generic.PUTFIELD) InvokeInstruction(org.apache.bcel.generic.InvokeInstruction) ConstantPushInstruction(org.apache.bcel.generic.ConstantPushInstruction) Instruction(org.apache.bcel.generic.Instruction) FieldInstruction(org.apache.bcel.generic.FieldInstruction) LocalVariableInstruction(org.apache.bcel.generic.LocalVariableInstruction) INVOKESPECIAL(org.apache.bcel.generic.INVOKESPECIAL) InstructionHandle(org.apache.bcel.generic.InstructionHandle) GETFIELD(org.apache.bcel.generic.GETFIELD) INVOKEINTERFACE(org.apache.bcel.generic.INVOKEINTERFACE) ValueInfo(com.jopdesign.common.type.ValueInfo) LocalVariableInstruction(org.apache.bcel.generic.LocalVariableInstruction) InvokeSite(com.jopdesign.common.code.InvokeSite) ConstantPushInstruction(org.apache.bcel.generic.ConstantPushInstruction) INVOKEVIRTUAL(org.apache.bcel.generic.INVOKEVIRTUAL)

Example 5 with PUTFIELD

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

the class JOPModel method getNativeOpCode.

/* performance hot spot */
public int getNativeOpCode(MethodInfo context, Instruction instr) {
    if (isSpecialInvoke(context, instr)) {
        INVOKESTATIC isi = (INVOKESTATIC) instr;
        String methodName = isi.getMethodName(context.getConstantPoolGen());
        return JopInstr.getNative(methodName);
    } else if (instr instanceof FieldInstruction) {
        FieldInstruction finstr = (FieldInstruction) instr;
        Type ftype = finstr.getFieldType(context.getConstantPoolGen());
        boolean isRef = ftype instanceof ReferenceType;
        boolean isLong = ftype == BasicType.LONG || ftype == BasicType.DOUBLE;
        if (finstr instanceof GETSTATIC) {
            if (isRef) {
                return JopInstr.get("getstatic_ref");
            } else if (isLong) {
                return JopInstr.get("getstatic_long");
            }
        } else if (finstr instanceof PUTSTATIC) {
            if (isRef) {
                if (!com.jopdesign.build.JOPizer.USE_RTTM) {
                    /* FIXME: This should not be hardcoded? */
                    return JopInstr.get("putstatic_ref");
                }
            } else if (isLong) {
                return JopInstr.get("putstatic_long");
            }
        } else if (finstr instanceof GETFIELD) {
            if (isRef) {
                return JopInstr.get("getfield_ref");
            } else if (isLong) {
                return JopInstr.get("getfield_long");
            }
        } else if (finstr instanceof PUTFIELD) {
            if (isRef) {
                if (!com.jopdesign.build.JOPizer.USE_RTTM) {
                    /* FIXME: This should not be hardcoded? */
                    return JopInstr.get("putfield_ref");
                }
            } else if (isLong) {
                return JopInstr.get("putfield_long");
            }
        }
        return instr.getOpcode();
    } else {
        return instr.getOpcode();
    }
}
Also used : INVOKESTATIC(org.apache.bcel.generic.INVOKESTATIC) GETFIELD(org.apache.bcel.generic.GETFIELD) ReferenceType(org.apache.bcel.generic.ReferenceType) Type(org.apache.bcel.generic.Type) ObjectType(org.apache.bcel.generic.ObjectType) BasicType(org.apache.bcel.generic.BasicType) PUTFIELD(org.apache.bcel.generic.PUTFIELD) FieldInstruction(org.apache.bcel.generic.FieldInstruction) GETSTATIC(org.apache.bcel.generic.GETSTATIC) ReferenceType(org.apache.bcel.generic.ReferenceType) PUTSTATIC(org.apache.bcel.generic.PUTSTATIC)

Aggregations

GETFIELD (org.apache.bcel.generic.GETFIELD)8 PUTFIELD (org.apache.bcel.generic.PUTFIELD)8 FieldInstruction (org.apache.bcel.generic.FieldInstruction)6 Instruction (org.apache.bcel.generic.Instruction)6 ReferenceType (org.apache.bcel.generic.ReferenceType)6 Type (org.apache.bcel.generic.Type)6 GETSTATIC (org.apache.bcel.generic.GETSTATIC)5 InvokeInstruction (org.apache.bcel.generic.InvokeInstruction)5 PUTSTATIC (org.apache.bcel.generic.PUTSTATIC)5 LDC (org.apache.bcel.generic.LDC)4 CallString (com.jopdesign.common.code.CallString)3 DFATool (com.jopdesign.dfa.DFATool)3 Context (com.jopdesign.dfa.framework.Context)3 ContextMap (com.jopdesign.dfa.framework.ContextMap)3 Set (java.util.Set)3 INVOKEINTERFACE (org.apache.bcel.generic.INVOKEINTERFACE)3 INVOKEVIRTUAL (org.apache.bcel.generic.INVOKEVIRTUAL)3 LoadInstruction (org.apache.bcel.generic.LoadInstruction)3 StoreInstruction (org.apache.bcel.generic.StoreInstruction)3 MethodInfo (com.jopdesign.common.MethodInfo)2