Search in sources :

Example 1 with ReturnAddressOperand

use of org.jikesrvm.compilers.opt.bc2ir.ReturnAddressOperand in project JikesRVM by JikesRVM.

the class Operand method meet.

/**
 * Meet two operands based on their positions in the operand lattice.
 * For the purposes of doing dataflow analysis, Operands can be
 * thought of as forming a lattice.
 * This function takes two operands and returns their meet (glb).
 * We use <code>null</code> to stand for bottom (the meet of
 * the two operands is an illegal value).  For exmaple,
 * meet(5.0, "hi") would evalaute to bottom.
 * Meet returns op1 iff conservativelyApproximates(op1, op2):
 * this is exploited in BC2IR to avoid doing redundant
 * work.
 * <p>
 * Unfortunately there is a fair amount of code duplication
 * between {@link #conservativelyApproximates} and
 * {@link #meet}, but factoring out the common control logic
 * is a non-trivial task.
 *
 * @param op1  the first operand to meet
 * @param op2  the second operand to meet
 * @param reg  the <code>Register</code> to use to
 *             create a new <code>RegisterOperand</code>
 *             if meeting op1 and op2 requires doing so.
 * @return the Operand that is the meet of op1 and op2.
 *         This function will return <code>null</code> when
 *         the meet evaluates to bottom.  It will return
 *         op1 when conservativelyApproximates(op1, op2)
 *         evaluates to <code>true</code>.
 */
public static Operand meet(Operand op1, Operand op2, Register reg) {
    // Step 1: Handler pointer equality and bottom
    if (op1 == op2) {
        if (DBG_OPERAND_LATTICE) {
            if (op1 == null) {
                VM.sysWriteln("Both operands are bottom");
            } else {
                VM.sysWriteln("Operands are identical");
            }
        }
        return op1;
    }
    if (op1 == null) {
        if (DBG_OPERAND_LATTICE) {
            VM.sysWriteln("Op1 was already bottom");
        }
        return op1;
    }
    if (op2 == null) {
        if (DBG_OPERAND_LATTICE) {
            VM.sysWriteln("Op2 is bottom (but op1 was not)");
        }
        return op2;
    }
    // Step 2: op1 is <null> (the null constant)
    if (op1 instanceof NullConstantOperand) {
        if (op2 instanceof NullConstantOperand) {
            if (DBG_OPERAND_LATTICE) {
                VM.sysWriteln("Both operands are <null>");
            }
            return op1;
        } else {
            /*
         * XXX Opt compiler guru please check :)
         *
         * Protect this code from crashing if op2 is DUMMY.  As I understand
         * the calling code this shouldn't happen, but the case for RegisterOperand
         * handles it so I guess it's not too bad for a NullConstantOperand
         * to do so.
         *
         * -- Robin Garner 1 Feb 7
         */
            if (op2 instanceof ReturnAddressOperand || op2 == BC2IR.DUMMY) {
                if (DBG_OPERAND_LATTICE) {
                    VM.sysWriteln("Incompatabily typed operands");
                }
                // bottom
                return null;
            }
            TypeReference type2 = op2.getType();
            if (type2.isReferenceType()) {
                if (DBG_OPERAND_LATTICE) {
                    VM.sysWriteln("op1 is <null>, but op2 is other ref type");
                }
                return new RegisterOperand(reg, type2);
            } else {
                if (DBG_OPERAND_LATTICE) {
                    VM.sysWriteln("op1 is <null>, but op2 is not a ref type");
                }
                // bottom
                return null;
            }
        }
    }
    // Step 3: op1 is some other constant
    if (op1.isConstant()) {
        if (op1.similar(op2)) {
            if (DBG_OPERAND_LATTICE) {
                VM.sysWriteln("op1 and op2 are similar constants");
            }
            return op1;
        } else {
            TypeReference superType = ClassLoaderProxy.findCommonSuperclass(op1.getType(), op2.getType());
            if (superType == null) {
                if (DBG_OPERAND_LATTICE) {
                    VM.sysWriteln("op1 and op2 have incompatible types");
                }
                // bottom
                return null;
            } else {
                return new RegisterOperand(reg, superType);
            }
        }
    }
    // the various Flag bits are considered as well....
    if (op1.isRegister()) {
        RegisterOperand rop1 = op1.asRegister();
        TypeReference type1 = rop1.getType();
        if (op2.isRegister()) {
            RegisterOperand rop2 = op2.asRegister();
            TypeReference type2 = rop2.getType();
            if (type1 == type2) {
                if (DBG_OPERAND_LATTICE) {
                    VM.sysWriteln("Identically typed register operands, checking flags...");
                }
                if (rop1.hasLessConservativeFlags(rop2)) {
                    if (DBG_OPERAND_LATTICE) {
                        VM.sysWriteln("mismatch");
                    }
                    RegisterOperand res = new RegisterOperand(reg, type1, rop1.getFlags(), rop1.isPreciseType(), rop1.isDeclaredType());
                    if (rop1.getGuard() instanceof Operand && rop2.getGuard() instanceof Operand && (rop1.getGuard().similar((rop2.getGuard())))) {
                        // compatible, so preserve onto res
                        res.setGuard(rop1.getGuard());
                    }
                    res.meetInheritableFlags(rop2);
                    return res;
                } else if (BC2IR.hasLessConservativeGuard(rop1, rop2)) {
                    if (DBG_OPERAND_LATTICE) {
                        VM.sysWriteln("Operands are registers of identical type with compatible flags but with incompatible non-null guards");
                    }
                    // by not setting guard we mark as possible null
                    return new RegisterOperand(reg, type1, rop1.getFlags(), rop1.isPreciseType(), rop1.isDeclaredType());
                } else {
                    if (DBG_OPERAND_LATTICE) {
                        VM.sysWriteln("match");
                    }
                    return op1;
                }
            } else if (compatiblePrimitives(type1, type2) || ClassLoaderProxy.includesType(type1, type2) == YES) {
                if (DBG_OPERAND_LATTICE) {
                    VM.sysWrite("Compatibly typed register operands, checking flags...");
                }
                if (rop1.isPreciseType() || rop1.hasLessConservativeFlags(rop2)) {
                    if (DBG_OPERAND_LATTICE) {
                        VM.sysWriteln("mismatch");
                    }
                    RegisterOperand res = new RegisterOperand(reg, type1, rop1.getFlags(), rop1.isPreciseType(), rop1.isDeclaredType());
                    res.meetInheritableFlags(rop2);
                    // even if both op1 & op2 are precise,
                    // op1.type != op2.type, so clear it on res
                    res.clearPreciseType();
                    if (rop1.getGuard() instanceof Operand && rop2.getGuard() instanceof Operand && (rop1.getGuard().similar((rop2.getGuard())))) {
                        // it matched, so preserve onto res.
                        res.setGuard(rop1.getGuard());
                    }
                    return res;
                } else if (BC2IR.hasLessConservativeGuard(rop1, rop2)) {
                    if (DBG_OPERAND_LATTICE) {
                        VM.sysWriteln("Operands are registers of compatible type and flags but with incompatible non-null guards");
                    }
                    return new RegisterOperand(reg, type1, rop1.getFlags(), rop1.isPreciseType(), rop1.isDeclaredType());
                } else {
                    if (DBG_OPERAND_LATTICE) {
                        VM.sysWriteln("match");
                    }
                    return op1;
                }
            } else {
                if (DBG_OPERAND_LATTICE) {
                    VM.sysWriteln("Incompatibly typed register operands...(" + type1 + ", " + type2 + ")...");
                }
                TypeReference resType = ClassLoaderProxy.findCommonSuperclass(type1, type2);
                if (resType == null) {
                    if (DBG_OPERAND_LATTICE) {
                        VM.sysWriteln("no common supertype, returning bottom");
                    }
                    // bottom
                    return null;
                } else {
                    if (DBG_OPERAND_LATTICE) {
                        VM.sysWriteln("found common supertype");
                    }
                    RegisterOperand res = new RegisterOperand(reg, resType, rop1.getFlags(), false, false);
                    res.meetInheritableFlags(rop2);
                    // invalid on res
                    res.clearPreciseType();
                    // invalid on res
                    res.clearDeclaredType();
                    if (rop1.getGuard() instanceof Operand && rop2.getGuard() instanceof Operand && (rop1.getGuard().similar((rop2.getGuard())))) {
                        // it matched, so preserve onto res.
                        res.setGuard(rop1.getGuard());
                    }
                    return res;
                }
            }
        } else {
            if (op2 instanceof ReturnAddressOperand || op2 == BC2IR.DUMMY) {
                if (DBG_OPERAND_LATTICE) {
                    VM.sysWrite("Incompatibly typed operands");
                }
                // bottom
                return null;
            }
            TypeReference type2 = op2.getType();
            if (type1 == type2 || compatiblePrimitives(type1, type2) || (ClassLoaderProxy.includesType(type1, type2) == YES)) {
                if (DBG_OPERAND_LATTICE) {
                    VM.sysWrite("Compatibly typed register & other operand, checking flags...");
                }
                RegisterOperand res = rop1;
                if (res.isPreciseType() && type1 != type2) {
                    res = res.copyU2U();
                    res.clearPreciseType();
                }
                if ((rop1.getGuard() instanceof Operand) && ((type2 == TypeReference.NULL_TYPE) || (type2.isIntLikeType() && op2.asIntConstant().value == 0) || (type2.isWordLikeType() && op2.asAddressConstant().value.isZero()) || (type2.isLongType() && op2.asLongConstant().value == 0L))) {
                    res = res.copyU2U();
                    res.setGuard(null);
                }
                if (DBG_OPERAND_LATTICE) {
                    if (res == rop1) {
                        VM.sysWriteln("match");
                    } else {
                        VM.sysWriteln("mismatch");
                    }
                }
                return res;
            } else {
                if (DBG_OPERAND_LATTICE) {
                    VM.sysWrite("Incompatibly typed register & other operand...(" + type1 + ", " + type2 + ")...");
                }
                TypeReference resType = ClassLoaderProxy.findCommonSuperclass(type1, type2);
                if (resType == null) {
                    if (DBG_OPERAND_LATTICE) {
                        VM.sysWriteln("no common supertype, returning bottom");
                    }
                    // bottom
                    return null;
                } else {
                    if (DBG_OPERAND_LATTICE) {
                        VM.sysWriteln("found common supertype");
                    }
                    return new RegisterOperand(reg, resType);
                }
            }
        }
    }
    // Step 5: op1 is some IRGEN operand
    if (op1.similar(op2)) {
        if (DBG_OPERAND_LATTICE) {
            VM.sysWriteln("Compatible BC2IR.* operands");
        }
        return op1;
    } else {
        if (DBG_OPERAND_LATTICE) {
            VM.sysWriteln("Incompatible BC2IR.* operands, returning bottom");
        }
        // bottom
        return null;
    }
}
Also used : ReturnAddressOperand(org.jikesrvm.compilers.opt.bc2ir.ReturnAddressOperand) ReturnAddressOperand(org.jikesrvm.compilers.opt.bc2ir.ReturnAddressOperand) TypeReference(org.jikesrvm.classloader.TypeReference)

Example 2 with ReturnAddressOperand

use of org.jikesrvm.compilers.opt.bc2ir.ReturnAddressOperand in project JikesRVM by JikesRVM.

the class Operand method conservativelyApproximates.

/**
 * Compare two operands based on their positions in the operand lattice.
 * For the purposes of doing dataflow analysis, Operands can be
 * thought of as forming a lattice.
 * This function compares two operands and returns whether or
 * not op1 is a conservative approximation of op2.
 * Or in other words, if conservativelyApproximates(op1, op2)
 * then meet(op1, op2) = op1.
 * Note that lattices are partial orders, so it is quite
 * possible for both conservativelyApproximates(op1, op2)
 * and conservativelyApproximates(op2, op1) to return false.
 *
 * @param op1 the first operand to compare
 * @param op2 the second operand to compare
 * @return <code>true</code> if op1 conservatively approximates op2 or
 *         <code>false</code> if it does not.
 */
public static boolean conservativelyApproximates(Operand op1, Operand op2) {
    // Step 1: Handle pointer equality and bottom
    if (op1 == op2) {
        if (DBG_OPERAND_LATTICE) {
            if (op2 == null) {
                VM.sysWriteln("operands are both bottom therefore trivially true");
            } else {
                VM.sysWriteln("operands are identical therefore trivially true");
            }
        }
        return true;
    }
    if (op1 == null) {
        if (DBG_OPERAND_LATTICE) {
            VM.sysWriteln("op1 is bottom, therefore trivially true");
        }
        return true;
    }
    if (op2 == null) {
        if (DBG_OPERAND_LATTICE) {
            VM.sysWriteln("op2 is bottom, therefore trivially false");
        }
        return false;
    }
    // Step 2: op1 is a constant but op2 is not the same constant
    if (op1.isConstant()) {
        if (op1.similar(op2)) {
            if (DBG_OPERAND_LATTICE) {
                VM.sysWriteln("operands are similar constants");
            }
            return true;
        } else {
            if (DBG_OPERAND_LATTICE) {
                VM.sysWriteln("op1 is a constant but op2 is not the same constant");
            }
            return false;
        }
    }
    // various Flag bits are considered as well....
    if (op1.isRegister()) {
        RegisterOperand rop1 = op1.asRegister();
        TypeReference type1 = rop1.getType();
        if (op2.isRegister()) {
            RegisterOperand rop2 = op2.asRegister();
            TypeReference type2 = rop2.getType();
            if (type1 == type2) {
                if (rop1.hasLessConservativeFlags(rop2)) {
                    if (DBG_OPERAND_LATTICE) {
                        VM.sysWriteln("Operands are registers of identical type, but incompatible flags");
                    }
                    return false;
                } else if (BC2IR.hasLessConservativeGuard(rop1, rop2)) {
                    if (DBG_OPERAND_LATTICE) {
                        VM.sysWriteln("Operands are registers of identical type, but with incompatible non-null guards");
                    }
                    return false;
                } else {
                    if (DBG_OPERAND_LATTICE) {
                        VM.sysWriteln("Operands are compatible register operands");
                    }
                    return true;
                }
            } else if (compatiblePrimitives(type1, type2) || ClassLoaderProxy.includesType(type1, type2) == YES) {
                // types are ok, only have to worry about the flags
                if (rop1.isPreciseType() || rop1.hasLessConservativeFlags(rop2)) {
                    if (DBG_OPERAND_LATTICE) {
                        VM.sysWriteln("Flag mismatch between type compatible register operands");
                    }
                    return false;
                } else if (BC2IR.hasLessConservativeGuard(rop1, rop2)) {
                    if (DBG_OPERAND_LATTICE) {
                        VM.sysWriteln("Non-null guard mismatch between type compatible register operands");
                    }
                    return false;
                } else {
                    if (DBG_OPERAND_LATTICE) {
                        VM.sysWriteln("Operands are compatible register operands");
                    }
                    return true;
                }
            } else {
                if (DBG_OPERAND_LATTICE) {
                    VM.sysWriteln("Operands are type incompatible register operands");
                }
                return false;
            }
        } else {
            // op2 is not a register
            if (op2 instanceof ReturnAddressOperand || op2 == BC2IR.DUMMY) {
                if (DBG_OPERAND_LATTICE) {
                    VM.sysWriteln("Operands are incompatibale values");
                }
                return false;
            }
            TypeReference type2 = op2.getType();
            if (type1 == type2 || compatiblePrimitives(type1, type2) || (ClassLoaderProxy.includesType(type1, type2) == YES)) {
                // only have to consider state of op1's flags.  Types are ok.
                if (rop1.isPreciseType() && (type1 != type2)) {
                    if (DBG_OPERAND_LATTICE) {
                        VM.sysWriteln("op1 preciseType bit will be incorrect");
                    }
                    return false;
                }
                if ((rop1.getGuard() instanceof Operand) && ((type2 == TypeReference.NULL_TYPE) || (type2.isIntLikeType() && op2.asIntConstant().value == 0) || (type2.isWordLikeType() && op2.asAddressConstant().value.EQ(Address.zero())) || (type2.isLongType() && op2.asLongConstant().value == 0L))) {
                    if (DBG_OPERAND_LATTICE) {
                        VM.sysWriteln("op1 non null guard will be incorrect");
                    }
                    return false;
                }
                if (DBG_OPERAND_LATTICE) {
                    VM.sysWriteln("(Constant) op2 was compatible with register op1");
                }
                return true;
            } else {
                if (DBG_OPERAND_LATTICE) {
                    VM.sysWriteln("Op2 not compatible with register op1");
                }
                return false;
            }
        }
    }
    // Step 4: op1 is a IRGEN operand of some form
    if (op1.similar(op2)) {
        if (DBG_OPERAND_LATTICE) {
            VM.sysWriteln("Compatible BC2IR.* operands");
        }
        return true;
    } else {
        if (DBG_OPERAND_LATTICE) {
            VM.sysWriteln("Incompatible BC2IR.* operands");
        }
        return false;
    }
}
Also used : ReturnAddressOperand(org.jikesrvm.compilers.opt.bc2ir.ReturnAddressOperand) ReturnAddressOperand(org.jikesrvm.compilers.opt.bc2ir.ReturnAddressOperand) TypeReference(org.jikesrvm.classloader.TypeReference)

Aggregations

TypeReference (org.jikesrvm.classloader.TypeReference)2 ReturnAddressOperand (org.jikesrvm.compilers.opt.bc2ir.ReturnAddressOperand)2