/** * Align the offsets of the fields in the class optimized for minimal object size. * * @param fields * @return The objectsize taken by all the fields */ private static final int alignInstanceFields(VmField[] fields, int slotSize) { int objectSize = 0; for (byte currentTypeSize : TYPE_SIZES) { boolean aligned = false; for (VmField f : fields) { if (!f.isStatic() && (f.getTypeSize() == currentTypeSize)) { if (!aligned) { // Align on the current type size objectSize = align(objectSize, Math.min(currentTypeSize, slotSize)); aligned = true; } final VmInstanceField fld = (VmInstanceField) f; fld.setOffset(objectSize); objectSize += currentTypeSize; } } } // Make sure the object size is 32-bit aligned return align(objectSize, 4); }
/** Do the prepare action required to instantiate this object */ protected void prepareForInstantiation() { // Step 3: Calculate the object size final VmNormalClass superCls = getSuperClass(); int sc_size = (superCls != null) ? superCls.getObjectSize() : 0; objectSize += sc_size; // System.out.println(getName() + " objsz:" + objectSize + " sc_size:" + sc_size); // Step 4a: Fix the offset for all declared non-static fields final int cnt = getNoDeclaredFields(); final int[] superRefOffsets = (superCls != null) ? superCls.getReferenceOffsets() : null; int refOffsetsSize = (superCls != null) ? superRefOffsets.length : 0; int startRefIdx = refOffsetsSize; for (int i = 0; i < cnt; i++) { final VmField field = getDeclaredField(i); // fs.resolve(loader); if (!field.isStatic()) { final VmInstanceField inf = (VmInstanceField) field; inf.resolveOffset(sc_size); if (!field.isPrimitive()) { if (!field.isAddressType()) { refOffsetsSize++; } else { // System.out.println("Found address in field " + fs.getName()); } } } } // Step 4b: Create the referenceOffsets field referenceOffsets = new int[refOffsetsSize]; if (superCls != null) { System.arraycopy(superRefOffsets, 0, referenceOffsets, 0, startRefIdx); } for (int i = 0; i < cnt; i++) { final VmField field = getDeclaredField(i); if (!field.isStatic()) { final VmInstanceField inf = (VmInstanceField) field; if (!field.isPrimitive()) { if (!field.isAddressType()) { referenceOffsets[startRefIdx++] = inf.getOffset(); } } final int off = inf.getOffset(); if (off + inf.getTypeSize() > objectSize) { throw new Error( "Invalid offset in class " + getName() + " ofs " + off + " size " + objectSize); } } } }
/** * Read the fields table * * @param cls * @param fieldDatas * @param sharedStatics * @param isolatedStatics * @param slotSize * @param pragmaFlags */ private static void createFields( VmType<?> cls, FieldData[] fieldDatas, VmSharedStatics sharedStatics, VmIsolatedStatics isolatedStatics, int slotSize, int pragmaFlags) { final int fcount = fieldDatas.length; final VmField[] ftable = new VmField[fcount]; int objectSize = 0; for (int i = 0; i < fcount; i++) { final FieldData fd = fieldDatas[i]; final boolean wide; int modifiers = fd.modifiers; final String name = fd.name; final String signature = fd.signature; switch (signature.charAt(0)) { case 'J': case 'D': modifiers = modifiers | Modifier.ACC_WIDE; wide = true; break; default: wide = false; } final boolean isstatic = (modifiers & Modifier.ACC_STATIC) != 0; final int staticsIdx; final VmField fs; final VmStatics statics; if (isstatic) { // Determine if the static field should be shared. final boolean shared = cls.isSharedStatics(); if (shared) { statics = sharedStatics; } else { statics = isolatedStatics; } // If static allocate space for it. switch (signature.charAt(0)) { case 'B': staticsIdx = statics.allocIntField(); break; case 'C': staticsIdx = statics.allocIntField(); break; case 'D': staticsIdx = statics.allocLongField(); break; case 'F': staticsIdx = statics.allocIntField(); break; case 'I': staticsIdx = statics.allocIntField(); break; case 'J': staticsIdx = statics.allocLongField(); break; case 'S': staticsIdx = statics.allocIntField(); break; case 'Z': staticsIdx = statics.allocIntField(); break; default: { if (Modifier.isAddressType(signature)) { staticsIdx = statics.allocAddressField(); } else { staticsIdx = statics.allocObjectField(); // System.out.println(NumberUtils.hex(staticsIdx) // + "\t" + cls.getName() + "." + name); } break; } } fs = new VmStaticField(name, signature, modifiers, staticsIdx, cls, slotSize, shared); } else { staticsIdx = -1; statics = null; final int fieldOffset; // Set the offset (keep in mind that this will be fixed // by ClassResolver with respect to the objectsize of the // super-class. fieldOffset = objectSize; // Increment the objectSize if (wide) objectSize += 8; else if (Modifier.isPrimitive(signature)) { objectSize += 4; } else { objectSize += slotSize; } fs = new VmInstanceField(name, signature, modifiers, fieldOffset, cls, slotSize); } ftable[i] = fs; // Read field attributes if (isstatic && (fd.constantValue != null)) { switch (signature.charAt(0)) { case 'B': case 'C': case 'I': case 'S': case 'Z': statics.setInt(staticsIdx, ((VmConstInt) fd.constantValue).intValue()); break; case 'D': final long lval = Double.doubleToRawLongBits(((VmConstDouble) fd.constantValue).doubleValue()); statics.setLong(staticsIdx, lval); break; case 'F': final int ival = Float.floatToRawIntBits(((VmConstFloat) fd.constantValue).floatValue()); statics.setInt(staticsIdx, ival); break; case 'J': statics.setLong(staticsIdx, ((VmConstLong) fd.constantValue).longValue()); break; default: // throw new IllegalArgumentException("signature " // + signature); statics.setObject(staticsIdx, fd.constantValue); break; } } fs.setRuntimeAnnotations(fd.rVisAnn); fs.setRawAnnotations(fd.rawAnnotations); } // Align the instance fields for minimal object size. if ((pragmaFlags & TypePragmaFlags.NO_FIELD_ALIGNMENT) == 0) { objectSize = alignInstanceFields(ftable, slotSize); } cls.setFieldTable(ftable); if (objectSize > 0) { ((VmNormalClass<?>) cls).setObjectSize(objectSize); } }