use of org.jikesrvm.classloader.TypeReference 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;
}
}
use of org.jikesrvm.classloader.TypeReference 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;
}
}
use of org.jikesrvm.classloader.TypeReference in project JikesRVM by JikesRVM.
the class StaticFieldReader method getIntStaticFieldValue.
/**
* Returns the current contents of an int-like static field.
*
* @param field a static field
* @return the current value of the field
* @throws NoSuchFieldException when the field could not be found
*/
public static int getIntStaticFieldValue(RVMField field) throws NoSuchFieldException {
if (VM.runningVM) {
return Statics.getSlotContentsAsInt(field.getOffset());
} else {
try {
Field f = getJDKField(field);
TypeReference fieldType = field.getType();
if (fieldType.isBooleanType()) {
boolean val = f.getBoolean(null);
return val ? 1 : 0;
} else if (fieldType.isByteType()) {
return f.getByte(null);
} else if (fieldType.isShortType()) {
return f.getShort(null);
} else if (fieldType.isIntType()) {
return f.getInt(null);
} else if (fieldType.isCharType()) {
return f.getChar(null);
} else {
throw new OptimizingCompilerException("Unsupported type " + field + "\n");
}
} catch (IllegalAccessException e) {
throwOptimizingCompilerExceptionBecauseOfIllegalAccess(field, e);
} catch (IllegalArgumentException e) {
throwOptimizingCompilerExceptionBecauseOfIllegalAccess(field, e);
}
assertNotReached();
return 0;
}
}
use of org.jikesrvm.classloader.TypeReference in project JikesRVM by JikesRVM.
the class StaticFieldReader method getFieldValueAsConstant.
public static ConstantOperand getFieldValueAsConstant(RVMField field, Object obj) throws NoSuchFieldException {
if (VM.VerifyAssertions) {
boolean isFinalField = field.isFinal();
boolean isInitializedField = field.getDeclaringClass().isInitialized() || field.getDeclaringClass().isInBootImage();
if (!(isFinalField && isInitializedField)) {
String msg = "Error reading field " + field;
VM._assert(VM.NOT_REACHED, msg);
}
}
TypeReference type = field.getType();
if (VM.runningVM) {
if (type.isReferenceType() && (!type.isMagicType() || type.isUnboxedArrayType())) {
Object value = field.getObjectValueUnchecked(obj);
if (value != null) {
return new ObjectConstantOperand(value, Offset.zero());
} else {
return new NullConstantOperand();
}
} else if (type.isWordLikeType()) {
return new AddressConstantOperand(field.getWordValueUnchecked(obj).toAddress());
} else if (type.isIntType()) {
return new IntConstantOperand(field.getIntValueUnchecked(obj));
} else if (type.isBooleanType()) {
return new IntConstantOperand(field.getBooleanValueUnchecked(obj) ? 1 : 0);
} else if (type.isByteType()) {
return new IntConstantOperand(field.getByteValueUnchecked(obj));
} else if (type.isCharType()) {
return new IntConstantOperand(field.getCharValueUnchecked(obj));
} else if (type.isDoubleType()) {
return new DoubleConstantOperand(field.getDoubleValueUnchecked(obj));
} else if (type.isFloatType()) {
return new FloatConstantOperand(field.getFloatValueUnchecked(obj));
} else if (type.isLongType()) {
return new LongConstantOperand(field.getLongValueUnchecked(obj));
} else if (type.isShortType()) {
return new IntConstantOperand(field.getShortValueUnchecked(obj));
} else {
OptimizingCompilerException.UNREACHABLE("Unknown type " + type);
return null;
}
} else {
try {
String cn = field.getDeclaringClass().toString();
Field f = Class.forName(cn).getDeclaredField(field.getName().toString());
f.setAccessible(true);
if (type.isReferenceType() && (!type.isMagicType() || type.isUnboxedArrayType())) {
Object value = f.get(obj);
if (value != null) {
return new ObjectConstantOperand(value, Offset.zero());
} else {
return new NullConstantOperand();
}
} else if (type.isWordLikeType()) {
Object value = f.get(obj);
if (type.equals(TypeReference.Word))
return new AddressConstantOperand((Word) value);
else if (type.equals(TypeReference.Address))
return new AddressConstantOperand((Address) value);
else if (type.equals(TypeReference.Offset))
return new AddressConstantOperand((Offset) value);
else if (type.equals(TypeReference.Extent))
return new AddressConstantOperand((Extent) value);
else {
OptimizingCompilerException.UNREACHABLE("Unknown word type " + type);
return null;
}
} else if (type.isIntType()) {
return new IntConstantOperand(f.getInt(obj));
} else if (type.isBooleanType()) {
return new IntConstantOperand(f.getBoolean(obj) ? 1 : 0);
} else if (type.isByteType()) {
return new IntConstantOperand(f.getByte(obj));
} else if (type.isCharType()) {
return new IntConstantOperand(f.getChar(obj));
} else if (type.isDoubleType()) {
return new DoubleConstantOperand(f.getDouble(obj));
} else if (type.isFloatType()) {
return new FloatConstantOperand(f.getFloat(obj));
} else if (type.isLongType()) {
return new LongConstantOperand(f.getLong(obj));
} else if (type.isShortType()) {
return new IntConstantOperand(f.getShort(obj));
} else {
OptimizingCompilerException.UNREACHABLE(cn + "." + f.getName() + " has unknown type " + type);
return null;
}
} catch (IllegalArgumentException e) {
throwNoSuchFieldExceptionWithCause(field, e);
} catch (IllegalAccessException e) {
throwNoSuchFieldExceptionWithCause(field, e);
} catch (NoSuchFieldError e) {
throwNoSuchFieldExceptionWithCause(field, e);
} catch (ClassNotFoundException e) {
throwNoSuchFieldExceptionWithCause(field, e);
} catch (NoClassDefFoundError e) {
throwNoSuchFieldExceptionWithCause(field, e);
} catch (IllegalAccessError e) {
throwNoSuchFieldExceptionWithCause(field, e);
}
assertNotReached();
return null;
}
}
use of org.jikesrvm.classloader.TypeReference in project JikesRVM by JikesRVM.
the class StaticFieldReader method getStaticFieldValue.
/**
* Returns a constant operand with the current value of a static field.
*
* @param field the static field whose current value we want to read
* @return a constant operand representing the current value of the field.
* @throws NoSuchFieldException when the field could not be found
*/
public static ConstantOperand getStaticFieldValue(RVMField field) throws NoSuchFieldException {
if (VM.VerifyAssertions) {
boolean fieldIsReady = field.getDeclaringClass().isInitialized() || field.getDeclaringClass().isInBootImage();
boolean isFinalField = field.isFinal();
boolean isStaticField = field.isStatic();
if (!(isFinalField && isStaticField && fieldIsReady)) {
String msg = "Error reading field " + field;
VM._assert(VM.NOT_REACHED, msg);
}
}
TypeReference fieldType = field.getType();
Offset off = field.getOffset();
if ((fieldType == TypeReference.Address) || (fieldType == TypeReference.Word) || (fieldType == TypeReference.Offset) || (fieldType == TypeReference.Extent)) {
Address val = getAddressStaticFieldValue(field);
return new AddressConstantOperand(val);
} else if (fieldType.isIntLikeType()) {
int val = getIntStaticFieldValue(field);
return new IntConstantOperand(val);
} else if (fieldType.isLongType()) {
long val = getLongStaticFieldValue(field);
return new LongConstantOperand(val);
} else if (fieldType.isFloatType()) {
float val = getFloatStaticFieldValue(field);
return new FloatConstantOperand(val, off);
} else if (fieldType.isDoubleType()) {
double val = getDoubleStaticFieldValue(field);
return new DoubleConstantOperand(val, off);
} else {
// Reference type
if (VM.VerifyAssertions)
VM._assert(fieldType.isReferenceType());
Object val = getObjectStaticFieldValue(field);
if (val == null) {
return new NullConstantOperand();
} else if (fieldType == TypeReference.JavaLangString) {
return new StringConstantOperand((String) val, off);
} else if (fieldType == TypeReference.JavaLangClass) {
Class<?> klass = (Class<?>) getObjectStaticFieldValue(field);
RVMType type;
if (VM.runningVM) {
type = java.lang.JikesRVMSupport.getTypeForClass(klass);
} else {
type = TypeReference.findOrCreate(klass).resolve();
}
return new ClassConstantOperand(type.getClassForType(), off);
} else {
return new ObjectConstantOperand(val, off);
}
}
}
Aggregations