bootImage.setDoubleWord(arrayImageOffset + (i << LOG_BYTES_IN_LONG), values[i]);
bootImage.setDoubleWord(arrayImageOffset.add(i << LOG_BYTES_IN_LONG), values[i]);
  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;    }