@NotNull @Override public BasicValue merge(@NotNull BasicValue v, @NotNull BasicValue w) { if (v.equals(w)) return v; if (tolerantToUninitializedValues) { if (v == StrictBasicValue.UNINITIALIZED_VALUE) return w; if (w == StrictBasicValue.UNINITIALIZED_VALUE) return v; } else if (v == StrictBasicValue.UNINITIALIZED_VALUE || w == StrictBasicValue.UNINITIALIZED_VALUE) { return StrictBasicValue.UNINITIALIZED_VALUE; } // if merge of two references then `lub` is java/lang/Object // arrays also are BasicValues with reference type's if (isReference(v) && isReference(w)) { return StrictBasicValue.REFERENCE_VALUE; } // if merge of something can be stored in int var (int, char, boolean, byte, character) if (v.getType().getOpcode(Opcodes.ISTORE) == Opcodes.ISTORE && w.getType().getOpcode(Opcodes.ISTORE) == Opcodes.ISTORE) { return StrictBasicValue.INT_VALUE; } return StrictBasicValue.UNINITIALIZED_VALUE; }
private static boolean isReference(@NotNull BasicValue v) { return v.getType().getSort() == Type.OBJECT || v.getType().getSort() == Type.ARRAY; }
@Override public BasicValue binaryOperation( @NotNull AbstractInsnNode insn, @NotNull BasicValue value1, @NotNull BasicValue value2) throws AnalyzerException { if (insn.getOpcode() == Opcodes.AALOAD) { Type arrayType = value1.getType(); if (arrayType != null && arrayType.getSort() == Type.ARRAY) { return new StrictBasicValue(arrayType.getElementType()); } } switch (insn.getOpcode()) { case IALOAD: case BALOAD: case CALOAD: case SALOAD: case IADD: case ISUB: case IMUL: case IDIV: case IREM: case ISHL: case ISHR: case IUSHR: case IAND: case IOR: case IXOR: return StrictBasicValue.INT_VALUE; case FALOAD: case FADD: case FSUB: case FMUL: case FDIV: case FREM: return StrictBasicValue.FLOAT_VALUE; case LALOAD: case LADD: case LSUB: case LMUL: case LDIV: case LREM: case LSHL: case LSHR: case LUSHR: case LAND: case LOR: case LXOR: return StrictBasicValue.LONG_VALUE; case DALOAD: case DADD: case DSUB: case DMUL: case DDIV: case DREM: return StrictBasicValue.DOUBLE_VALUE; case AALOAD: return StrictBasicValue.REFERENCE_VALUE; case LCMP: case FCMPL: case FCMPG: case DCMPL: case DCMPG: return StrictBasicValue.INT_VALUE; case IF_ICMPEQ: case IF_ICMPNE: case IF_ICMPLT: case IF_ICMPGE: case IF_ICMPGT: case IF_ICMPLE: case IF_ACMPEQ: case IF_ACMPNE: case PUTFIELD: return null; default: throw new Error("Internal error."); } }