private static int copyToBootImage(Object jdkObject, boolean allocOnly, int overwriteOffset,
private static Offset copyToBootImage(Object jdkObject, boolean allocOnly, Offset overwriteOffset,
  private static int copyToBootImage(Object jdkObject,                                      boolean allocOnly, int overwriteOffset,                                      Object parentObject)    throws IllegalAccessException    {      //      // Return object if it is already copied and not being overwritten      //      BootImageMap.Entry mapEntry = BootImageMap.findOrCreateEntry(jdkObject);      if (mapEntry.imageOffset != OBJECT_NOT_ALLOCATED && overwriteOffset == -1)        return mapEntry.imageOffset;      if (verbose >= 2) depth++;      //      // fetch object's type information      //      Class   jdkType = jdkObject.getClass();      VM_Type rvmType = getRvmType(jdkType);      if (rvmType == null) {        if (verbose >= 2) traverseObject(jdkObject);        if (verbose >= 2) depth--;        return OBJECT_NOT_PRESENT; // object not part of bootimage      }      //      // copy object to image      //      if (jdkType.isArray()) {        VM_Array rvmArrayType = rvmType.asArray();        //        // allocate space in image        //        int arrayCount       = Array.getLength(jdkObject);        int arrayImageOffset = (overwriteOffset == -1) ? bootImage.allocateArray(rvmArrayType, arrayCount) : overwriteOffset;        mapEntry.imageOffset = arrayImageOffset;        if (verbose >= 2) {          if (depth == depthCutoff)             say(SPACES.substring(0,depth+1), "TOO DEEP: cutting off");          else if (depth < depthCutoff) {            String tab = SPACES.substring(0,depth+1);            if (depth == 0 && jtocCount >= 0)              tab = tab + "jtoc #" + String.valueOf(jtocCount) + ": ";            int arraySize = rvmArrayType.getInstanceSize(arrayCount);            say(tab, "Copying array  ", jdkType.getName(),                 "   length=", String.valueOf(arrayCount),                (arraySize >= LARGE_ARRAY_SIZE) ? " large object!!!" : "");          }        }        VM_Type rvmElementType = rvmArrayType.getElementType();        // Show info on reachability of int arrays        //        if (false && rvmElementType.equals(VM_Type.IntType)) {          if (parentObject != null) {            Class parentObjectType = parentObject.getClass();            VM.sysWrite("Copying int array (", 4 * ((int []) jdkObject).length);            VM.sysWriteln(" bytes) from parent object of type ", parentObjectType.toString());          } else {            VM.sysWriteln("Copying int array from no parent object");          }        }        //        // copy array elements from host jdk address space into image        // recurse on values that are references        //        if (rvmElementType.isPrimitiveType()) {          // array element is logical or numeric type          if (rvmElementType.equals(VM_Type.BooleanType)) {            boolean values[] = (boolean[]) jdkObject;            for (int i = 0; i < arrayCount; ++i)              bootImage.setByte(arrayImageOffset + i, values[i] ? 1 : 0);          }          else if (rvmElementType.equals(VM_Type.ByteType)) {            byte values[] = (byte[]) jdkObject;            for (int i = 0; i < arrayCount; ++i)              bootImage.setByte(arrayImageOffset + i, values[i]);          }          else if (rvmElementType.equals(VM_Type.CharType)) {            char values[] = (char[]) jdkObject;            for (int i = 0; i < arrayCount; ++i)              bootImage.setHalfWord(arrayImageOffset + (i << LOG_BYTES_IN_CHAR), values[i]);          }          else if (rvmElementType.equals(VM_Type.ShortType)) {            short values[] = (short[]) jdkObject;            for (int i = 0; i < arrayCount; ++i)              bootImage.setHalfWord(arrayImageOffset + (i << LOG_BYTES_IN_SHORT), values[i]);          }          else if (rvmElementType.equals(VM_Type.IntType)) {            int values[] = (int[]) jdkObject;            for (int i = 0; i < arrayCount; ++i)              bootImage.setFullWord(arrayImageOffset + (i << LOG_BYTES_IN_INT), values[i]);          }          else if (rvmElementType.equals(VM_Type.LongType)) {            long values[] = (long[]) jdkObject;            for (int i = 0; i < arrayCount; ++i)              bootImage.setDoubleWord(arrayImageOffset + (i << LOG_BYTES_IN_LONG), values[i]);          }          else if (rvmElementType.equals(VM_Type.FloatType)) {            float values[] = (float[]) jdkObject;            for (int i = 0; i < arrayCount; ++i)              bootImage.setFullWord(arrayImageOffset + (i << LOG_BYTES_IN_FLOAT),                                    Float.floatToIntBits(values[i]));          }          else if (rvmElementType.equals(VM_Type.DoubleType)) {            double values[] = (double[]) jdkObject;            for (int i = 0; i < arrayCount; ++i)              bootImage.setDoubleWord(arrayImageOffset + (i << LOG_BYTES_IN_DOUBLE),                                      Double.doubleToLongBits(values[i]));          }           else            fail("unexpected primitive array type: " + rvmArrayType);        } else {          // array element is reference type          Object values[] = (Object []) jdkObject;          Class jdkClass = jdkObject.getClass();          if (!allocOnly) {            for (int i = 0; i<arrayCount; ++i) {              if (values[i] != null) {                if (verbose >= 2) traceContext.push(values[i].getClass().getName(),                                                    jdkClass.getName(), i);                int imageOffset = copyToBootImage(values[i], allocOnly, -1, jdkObject);                if (imageOffset == OBJECT_NOT_PRESENT) {                  // object not part of bootimage: install null reference                  if (verbose >= 2) traceContext.traceObjectNotInBootImage();                  bootImage.setNullAddressWord(arrayImageOffset + (i << LOG_BYTES_IN_ADDRESS));                } else {                  bootImage.setAddressWord(arrayImageOffset + (i << LOG_BYTES_IN_ADDRESS),                                           bootImageAddress.add(imageOffset).toWord());                }                if (verbose >= 2) traceContext.pop();              }            }          }        }      } else {        if (rvmType == VM_Type.AddressArrayType) {          if (verbose >= 2) depth--;          AddressArray addrArray = (AddressArray) jdkObject;          Object backing = addrArray.getBacking();          return copyMagicArrayToBootImage(backing, rvmType.asArray(), allocOnly, overwriteOffset, parentObject);        }        if (rvmType == VM_Type.ObjectReferenceArrayType) {          if (verbose >= 2) depth--;          ObjectReferenceArray orArray = (ObjectReferenceArray) jdkObject;          Object backing = orArray.getBacking();          return copyMagicArrayToBootImage(backing, rvmType.asArray(), allocOnly, overwriteOffset, parentObject);        }        if (rvmType == VM_Type.OffsetArrayType) {          if (verbose >= 2) depth--;          OffsetArray addrArray = (OffsetArray) jdkObject;          Object backing = addrArray.getBacking();          return copyMagicArrayToBootImage(backing, rvmType.asArray(), allocOnly, overwriteOffset, parentObject);        }        if (rvmType == VM_Type.WordArrayType) {          if (verbose >= 2) depth--;          WordArray addrArray = (WordArray) jdkObject;          Object backing = addrArray.getBacking();          return copyMagicArrayToBootImage(backing, rvmType.asArray(), allocOnly, overwriteOffset, parentObject);        }        if (rvmType == VM_Type.ExtentArrayType) {          if (verbose >= 2) depth--;          ExtentArray addrArray = (ExtentArray) jdkObject;          Object backing = addrArray.getBacking();          return copyMagicArrayToBootImage(backing, rvmType.asArray(), allocOnly, overwriteOffset, parentObject);        }        if (rvmType == VM_Type.CodeArrayType) {          if (verbose >= 2) depth--;          VM_CodeArray codeArray = (VM_CodeArray) jdkObject;          Object backing = codeArray.getBacking();          return copyMagicArrayToBootImage(backing, rvmType.asArray(), allocOnly, overwriteOffset, parentObject);        }        if (rvmType.isMagicType()) {          VM.sysWriteln("Unhandled copying of magic type: " + rvmType.getDescriptor().toString());          VM.sysFail("incomplete boot image support");        }        //        // allocate space in image        //        VM_Class rvmScalarType = rvmType.asClass();        int scalarImageOffset = (overwriteOffset == -1) ? bootImage.allocateScalar(rvmScalarType) : overwriteOffset;        mapEntry.imageOffset = scalarImageOffset;        if (verbose >= 2) {          if (depth == depthCutoff)             say(SPACES.substring(0,depth+1), "TOO DEEP: cutting off");          else if (depth < depthCutoff) {            String tab = SPACES.substring(0,depth+1);            if (depth == 0 && jtocCount >= 0)              tab = tab + "jtoc #" + String.valueOf(jtocCount) + " ";            int scalarSize = rvmScalarType.getInstanceSize();            say(tab, "Copying object ", jdkType.getName(),                "   size=", String.valueOf(scalarSize),                (scalarSize >= LARGE_SCALAR_SIZE) ? " large object!!!" : "");          }        }        //        // copy object fields from host jdk address space into image        // recurse on values that are references        //        VM_Field[] rvmFields = rvmScalarType.getInstanceFields();        for (int i = 0, n = rvmFields.length; i < n; ++i) {          VM_Field rvmField       = rvmFields[i];          VM_TypeReference rvmFieldType   = rvmField.getType();          int      rvmFieldOffset = scalarImageOffset + rvmField.getOffsetAsInt();          String   rvmFieldName   = rvmField.getName().toString();          Field    jdkFieldAcc    = getJdkFieldAccessor(jdkType, i, INSTANCE_FIELD);          if (jdkFieldAcc == null) {            if (verbose >= 2) traceContext.push(rvmFieldType.toString(),                                                jdkType.getName(), rvmFieldName);            if (verbose >= 2) traceContext.traceFieldNotInHostJdk();            if (verbose >= 2) traceContext.pop();            if (rvmFieldType.isPrimitiveType())              switch (rvmField.getType().getSize()) {                case 4: bootImage.setFullWord(rvmFieldOffset, 0);       break;                case 8: bootImage.setDoubleWord(rvmFieldOffset, 0L);    break;                default:fail("unexpected field type: " + rvmFieldType); break;              }            else              bootImage.setNullAddressWord(rvmFieldOffset);            continue;          }          if (rvmFieldType.isPrimitiveType()) {            // field is logical or numeric type            if (rvmFieldType.isBooleanType()) {              bootImage.setFullWord(rvmFieldOffset,                                    jdkFieldAcc.getBoolean(jdkObject) ? 1 : 0);            } else if (rvmFieldType.isByteType()) {              bootImage.setFullWord(rvmFieldOffset,                                    jdkFieldAcc.getByte(jdkObject));            } else if (rvmFieldType.isCharType()) {              bootImage.setFullWord(rvmFieldOffset,                                    jdkFieldAcc.getChar(jdkObject));            } else if (rvmFieldType.isShortType()) {              bootImage.setFullWord(rvmFieldOffset,                                    jdkFieldAcc.getShort(jdkObject));            } else if (rvmFieldType.isIntType()) {              try {                bootImage.setFullWord(rvmFieldOffset,                                      jdkFieldAcc.getInt(jdkObject));              } catch (IllegalArgumentException ex) {                System.err.println( "type " + rvmScalarType + ", field " + rvmField);                throw ex;              }            } else if (rvmFieldType.isLongType()) {              bootImage.setDoubleWord(rvmFieldOffset,                                      jdkFieldAcc.getLong(jdkObject));            } else if (rvmFieldType.isFloatType()) {              float f = jdkFieldAcc.getFloat(jdkObject);              bootImage.setFullWord(rvmFieldOffset,                                    Float.floatToIntBits(f));            } else if (rvmFieldType.isDoubleType()) {              double d = jdkFieldAcc.getDouble(jdkObject);              bootImage.setDoubleWord(rvmFieldOffset,                                      Double.doubleToLongBits(d));            } else if (rvmFieldType.equals(VM_TypeReference.Address) ||                       rvmFieldType.equals(VM_TypeReference.Word) ||                       rvmFieldType.equals(VM_TypeReference.Extent) ||                       rvmFieldType.equals(VM_TypeReference.Offset)) {              Object o = jdkFieldAcc.get(jdkObject);              String msg = " instance field " + rvmField.toString();              boolean warn = rvmFieldType.equals(VM_TypeReference.Address);              bootImage.setAddressWord(rvmFieldOffset, getWordValue(o, msg, warn));            } else {              fail("unexpected primitive field type: " + rvmFieldType);            }          } else {            // field is reference type            Object value = jdkFieldAcc.get(jdkObject);            if (!allocOnly && value != null) {              Class jdkClass = jdkFieldAcc.getDeclaringClass();              if (verbose >= 2) traceContext.push(value.getClass().getName(),                                                  jdkClass.getName(),                                                  jdkFieldAcc.getName());              int imageOffset = copyToBootImage(value, allocOnly, -1, jdkObject);              if (imageOffset == OBJECT_NOT_PRESENT) {                // object not part of bootimage: install null reference                if (verbose >= 2) traceContext.traceObjectNotInBootImage();                bootImage.setNullAddressWord(rvmFieldOffset);              } else                bootImage.setAddressWord(rvmFieldOffset,                                         bootImageAddress.add(imageOffset).toWord());              if (verbose >= 2) traceContext.pop();            }          }        }      }      //      // copy object's type information block into image, if it's not there      // already      //      if (!allocOnly) {        if (verbose >= 2) traceContext.push("", jdkObject.getClass().getName(), "tib");        int tibImageOffset = copyToBootImage(rvmType.getTypeInformationBlock(), allocOnly, -1, jdkObject);        if (verbose >= 2) traceContext.pop();        if (tibImageOffset == OBJECT_NOT_ALLOCATED)          fail("can't copy tib for " + jdkObject);        Address tibAddress = bootImageAddress.add(tibImageOffset);        VM_ObjectModel.setTIB(bootImage, mapEntry.imageOffset, tibAddress, rvmType);      }      if (verbose >= 2) depth--;      return mapEntry.imageOffset;    }