HCIUnit get(HClass hc) { HCIUnit hciu; HClass superclass; HCIUnit superclassInfo; hciu = (HCIUnit) m_table.get(hc); if (hciu == null) { if (hc.isArray()) { // Treat arrays differently int dims = HClassUtil.dims(hc); HClass baseclass = HClassUtil.baseClass(hc); // hc is not primitive, so hc.getLinker() is safe. superclass = baseclass.isPrimitive() ? hc.getLinker().forName("java.lang.Object") : (baseclass.getDescriptor().equals("Ljava/lang/Object;") ? (HClassUtil.arrayClass(hc.getLinker(), baseclass, dims - 1)) : HClassUtil.arrayClass(hc.getLinker(), baseclass.getSuperclass(), dims)); } else { superclass = hc.getSuperclass(); } if (superclass != null) { superclassInfo = get(superclass); hciu = new HCIUnit(hc, superclassInfo); } else { hciu = new HCIUnit(hc); } m_table.put(hc, hciu); } return hciu; }
/** * create a new objectref with default field values. * * @exception InterpretedThrowable if class initializer throws an exception. */ ObjectRef(StaticState ss, HClass type) { super(ss, type); this.fields = null; this.closure = null; // Initialize our fields. for (HClass sc = type; sc != null; sc = sc.getSuperclass()) { HField[] fl = sc.getDeclaredFields(); for (int i = 0; i < fl.length; i++) if (!fl[i].isStatic()) update(fl[i], defaultValue(fl[i])); } // yay, done. }
private void extend(HClass hc) { HField[] hFields = hc.getDeclaredFields(); for (int i = 0; i < hFields.length; i++) { if (hFields[i].isStatic()) m_currentStaticFieldOffset = m_memberMap.map(hFields[i], m_currentStaticFieldOffset); else m_currentFieldOffset = m_memberMap.map(hFields[i], m_currentFieldOffset); } HMethod[] hMethods = hc.getDeclaredMethods(); for (int i = 0; i < hMethods.length; i++) { m_currentMethodOffset = m_memberMap.map(hMethods[i], m_currentMethodOffset); } }
/** Find fields which are *not* subclass-final. */ private Set findBadFields(HCodeFactory hcf, ClassHierarchy ch) { Set badFields = new HashSet(); // for each callable method... for (Iterator it = ch.callableMethods().iterator(); it.hasNext(); ) { HMethod hm = (HMethod) it.next(); HCode hc = hcf.convert(hm); if (hc == null) continue; // xxx: native methods may write fields! // construct a must-param oracle for constructors. MustParamOracle mpo = isConstructor(hm) ? new MustParamOracle(hc) : null; // examine this method for writes HClass thisClass = hc.getMethod().getDeclaringClass(); for (Iterator it2 = hc.getElementsI(); it2.hasNext(); ) { Quad q = (Quad) it2.next(); if (q instanceof SET) { SET qq = (SET) q; // ignore writes of static fields. if (qq.isStatic()) continue; // if this is a constructor, than it may write only // to fields of 'this' if (isConstructor(hm) && mpo.isMustParam(qq.objectref()) && mpo.whichMustParam(qq.objectref()) == 0) continue; // this is a permitted write. // writes by subclass methods to superclass fields are // okay. (but not writes by 'this' methods to 'this' // fields, unless the method is a constructor) if (qq.field().getDeclaringClass().isInstanceOf(thisClass) && // XXX i think the presence of the 'isConstructor' // clause here is a bug. constructor writes // should be taken care of by clause above. (isConstructor(hm) || !thisClass.equals(qq.field().getDeclaringClass()))) continue; // subclass writes are permitted. // non-permitted write! badFields.add(qq.field()); } } // on to the next! } // done! we have set of all bad (not subclass-final) fields. return Collections.unmodifiableSet(badFields); }
static final Object defaultValue(HClass ty) { if (!ty.isPrimitive()) return null; if (ty == HClass.Boolean) return new Boolean(false); if (ty == HClass.Byte) return new Byte((byte) 0); if (ty == HClass.Char) return new Character((char) 0); if (ty == HClass.Double) return new Double(0); if (ty == HClass.Float) return new Float(0); if (ty == HClass.Int) return new Integer(0); if (ty == HClass.Long) return new Long(0); if (ty == HClass.Short) return new Short((short) 0); throw new Error("Ack! What kinda default value is this?!"); }
// make a wrapped 'zero' value of the specified type. private Object makeZero(HClass hc) { if (!hc.isPrimitive()) return null; if (hc == HClass.Boolean || hc == HClass.Byte || hc == HClass.Short || hc == HClass.Char || hc == HClass.Int) return new Integer(0); if (hc == HClass.Long) return new Long(0); if (hc == HClass.Float) return new Float(0); if (hc == HClass.Double) return new Double(0); assert false : ("unknown type: " + hc); return null; }