Search in sources :

Example 1 with ANEWARRAY

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

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

Aggregations

CallString (com.jopdesign.common.code.CallString)2 DFATool (com.jopdesign.dfa.DFATool)2 Context (com.jopdesign.dfa.framework.Context)2 ContextMap (com.jopdesign.dfa.framework.ContextMap)2 LinkedHashSet (java.util.LinkedHashSet)2 Set (java.util.Set)2 ANEWARRAY (org.apache.bcel.generic.ANEWARRAY)2 GETFIELD (org.apache.bcel.generic.GETFIELD)2 GETSTATIC (org.apache.bcel.generic.GETSTATIC)2 Instruction (org.apache.bcel.generic.Instruction)2 LDC (org.apache.bcel.generic.LDC)2 LoadInstruction (org.apache.bcel.generic.LoadInstruction)2 MULTIANEWARRAY (org.apache.bcel.generic.MULTIANEWARRAY)2 NEWARRAY (org.apache.bcel.generic.NEWARRAY)2 PUTFIELD (org.apache.bcel.generic.PUTFIELD)2 PUTSTATIC (org.apache.bcel.generic.PUTSTATIC)2 ReferenceType (org.apache.bcel.generic.ReferenceType)2 StoreInstruction (org.apache.bcel.generic.StoreInstruction)2 Type (org.apache.bcel.generic.Type)2 ClassInfo (com.jopdesign.common.ClassInfo)1