bootImage.setNullAddressWord(jtocImageAddress.plus(jtocOff), false);
bootImage.setNullAddressWord(jtocImageAddress.plus(jtocOff), false, false);
  public static void main(String args[])     throws Exception  {    String   bootImageCodeName     = null;    String   bootImageDataName     = null;    String   bootImageRMapName     = null;    String   bootImageMapName      = null;    Vector   bootImageTypeNames    = null;    String   bootImageTypeNamesFile = null;    String[] bootImageCompilerArgs = {};    //    // This may look useless, but it is not: it is a kludge to prevent    // forName blowing up.  By forcing the system to load some classes     // now, we ensure that forName does not cause security violations by    // trying to load into java.util later.    //     java.util.HashMap x = new java.util.HashMap();    x.put(x, x.getClass());    sillyhack = x;    //    // Process command line directives.    //    for (int i = 0; i < args.length; ++i) {      // name of code image file      if (args[i].equals("-oc")) {        if (++i >= args.length)          fail("argument syntax error: Got a -oc flag without a following code image file name");        bootImageCodeName = args[i];        continue;      }      // name of data image file      if (args[i].equals("-od")) {        if (++i >= args.length)          fail("argument syntax error: Got a -od flag without a following data image file name");        bootImageDataName = args[i];        continue;      }      // name of ref map image file      if (args[i].equals("-or")) {        if (++i >= args.length)          fail("argument syntax error: Got a -or flag without a following ref map file name");        bootImageRMapName = args[i];        continue;      }      // name of map file      if (args[i].equals("-m")) {        if (++i >= args.length)          fail("argument syntax error: Got a -m flag without a following bootImageMap file name");        bootImageMapName = args[i];        continue;      }      // image code start address      if (args[i].equals("-ca")) {        if (++i >= args.length)          fail("argument syntax error: Got a -ca flag without a following image address");        bootImageCodeAddress = Address.fromIntZeroExtend(Integer.decode(args[i]).intValue());        continue;      }      // image data start address      if (args[i].equals("-da")) {        if (++i >= args.length)          fail("argument syntax error: Got a -da flag without a following image address");        bootImageDataAddress = Address.fromIntZeroExtend(Integer.decode(args[i]).intValue());        continue;      }      // image ref map start address      if (args[i].equals("-ra")) {        if (++i >= args.length)          fail("argument syntax error: Got a -ra flag without a following image address");        bootImageRMapAddress = Address.fromIntZeroExtend(Integer.decode(args[i]).intValue());        continue;      }      // file containing names of types to be placed into bootimage      if (args[i].equals("-n")) {        if (++i >= args.length)          fail("argument syntax error: Got a -n flag without a following file name");                  if (bootImageTypeNamesFile != null )          fail("argument syntax error: We've already read in the bootImageTypeNames from"               + bootImageTypeNamesFile + "; just got another -n argument"               + " telling us to read them from " + args[i]);        bootImageTypeNamesFile = args[i];        continue;      }      // bootimage compiler argument      if (args[i].startsWith("-X:bc:")) {        String[] nbca = new String[bootImageCompilerArgs.length+1];        for (int j = 0; j < bootImageCompilerArgs.length; j++) {          nbca[j] = bootImageCompilerArgs[j];        }        nbca[nbca.length-1] = args[i].substring(6);        bootImageCompilerArgs = nbca;        say("compiler arg: ", bootImageCompilerArgs[nbca.length-1]);        continue;      }      // places where rvm components live, at build time      if (args[i].equals("-classpath")) {        if (++i >= args.length)          fail("argument syntax error: Got a -classpath flag without a following classpath for build-time RVM components");        bootImageRepositoriesAtBuildTime = args[i];        continue;      }      // places where rvm components live, at execution time      if (args[i].equals("-xclasspath")) {        if (++i >= args.length)          fail("argument syntax error: Got an -xclasspath flag without a following execution-time classpath for RVM components");        bootImageRepositoriesAtExecutionTime = args[i];        continue;      }      // generate trace messages while writing bootimage (for debugging)      if (args[i].equals("-trace")) {        ++verbose;        continue;      }      // generate info by type      if (args[i].equals("-demographics")) {        demographics = true;        continue;      }      // parallelize      if (args[i].startsWith("-parallelize=")) {        parallelize = Integer.parseInt(args[i].substring(13));        continue;      }      // profile      if (args[i].equals("-profile")) {        profile = true;        continue;      }      // generate detailed information about traversed objects (for debugging)      if (args[i].equals("-detailed")) {        verbose += 2;        continue;      }      // write words to bootimage in little endian format      if (args[i].equals("-littleEndian")) {        littleEndian = true;        continue;      }      fail("unrecognized command line argument: " + args[i]);    }    if (verbose >= 2)      traversed = new Hashtable(500);    //    // Check command line directives for correctness.    //    if (bootImageCodeName == null)      fail("please specify \"-oc <boot-image-code-filename>\"");    if (bootImageDataName == null)      fail("please specify \"-od <boot-image-data-filename>\"");    if (bootImageRMapName == null)      fail("please specify \"-or <boot-image-rmap-filename>\"");    if (bootImageTypeNamesFile == null)      fail("please specify \"-n <boot-image-type-names-filename>\"");    if (bootImageRepositoriesAtBuildTime == null)      fail("please specify \"-classpath <path>\"");    if (bootImageRepositoriesAtExecutionTime == null)      bootImageRepositoriesAtExecutionTime = bootImageRepositoriesAtBuildTime;    if (bootImageDataAddress.isZero())      fail("please specify boot-image address with \"-da <addr>\"");    if (!(bootImageDataAddress.toWord().and(Word.fromIntZeroExtend(0x00FFFFFF)).isZero()))      fail("please specify a boot-image address that is a multiple of 0x01000000");    if (bootImageCodeAddress.isZero())      fail("please specify boot-image address with \"-ca <addr>\"");    if (!(bootImageCodeAddress.toWord().and(Word.fromIntZeroExtend(0x00FFFFFF)).isZero()))      fail("please specify a boot-image address that is a multiple of 0x01000000");    if (bootImageRMapAddress.isZero())      fail("please specify boot-image address with \"-ra <addr>\"");    if (!(bootImageRMapAddress.toWord().and(Word.fromIntZeroExtend(0x00FFFFFF)).isZero()))      fail("please specify a boot-image address that is a multiple of 0x01000000");    //    // Initialize the bootimage.    // Do this earlier than we logically need to because we need to    // allocate a massive byte[] that will hold the bootimage in core and    // on some host JDKs it is essential to do that early while there    // is still lots of virgin storage left.     // (need to get contiguous storage before it gets fragmented by pinned objects)    //    bootImage = new BootImage(littleEndian, verbose >= 1);    //    // Install handler that intercepts all object address references made by    // VM_xxx classes executed on host jdk and substitutes a value that can be    // fixed up later when those objects are copied from host jdk to bootimage.    //    enableObjectAddressRemapper();    //    // Initialize rvm classes for use in "bootimage writing" mode.    // These rvm classes are used two ways:    //   - they are used now, by host jdk, to create the bootimage    //   - they are used later, by target rvm, to execute the bootimage    //    if (verbose >= 1) say("starting up");    //    try {      VM.initForBootImageWriter(bootImageRepositoriesAtBuildTime,                                bootImageCompilerArgs);      //    } catch (Exception e) {      //      fail("unable to initialize VM: "+e);      //    }    //    // Create (in host jdk address space) the rvm objects that will be    // needed at run time to execute enough of the virtual machine    // to dynamically load and compile the remainder of itself.    //    long startTime = 0;    long stopTime = 0;    if (profile) startTime = System.currentTimeMillis();    try {      bootImageTypeNames = readTypeNames(bootImageTypeNamesFile);    } catch (IOException e) {      fail("unable to read the type names from "+ bootImageTypeNamesFile            +": "+e);    }    if (profile) {      stopTime = System.currentTimeMillis();      System.out.println("PROF: readingTypeNames "+(stopTime-startTime)+" ms");    }          if (profile) startTime = System.currentTimeMillis();    try {      createBootImageObjects(bootImageTypeNames, bootImageTypeNamesFile);    } catch (Exception e) {      e.printStackTrace();      fail("unable to create objects: "+e);    }    if (profile) {      stopTime = System.currentTimeMillis();      System.out.println("PROF: createBootImageObjects "+(stopTime-startTime)+" ms");    }    //    // No further bootimage object references should get generated.    // If they are, they'll be assigned an objectId of "-1" (see VM_Magic)    // and will manifest themselves as an array subscript out of bounds    // error when BootImageMap attempts to look up the object references.    //    disableObjectAddressRemapper();    ////////////////////////////////////////////////////    // Copy rvm objects from host jdk into bootimage.    ////////////////////////////////////////////////////    VM.writingImage = true;    if (verbose >= 1) say("Memory available: ",                          String.valueOf(Runtime.getRuntime().freeMemory()),                          " bytes out of ",                          String.valueOf(Runtime.getRuntime().totalMemory()),                          " bytes");    if (profile) startTime = System.currentTimeMillis();    //    // First object in image must be boot record (so boot loader will know    // where to find it).  We'll write out an uninitialized record and not recurse     // to reserve the space, then go back and fill it in later.    //    if (verbose >= 1) say("copying boot record");    VM_BootRecord bootRecord = VM_BootRecord.the_boot_record;    Address bootRecordImageAddress = Address.zero();    try {      // copy just the boot record      bootRecordImageAddress = copyToBootImage(bootRecord, true, Address.max(), null);       if (bootRecordImageAddress.EQ(OBJECT_NOT_PRESENT)) {        fail("can't copy boot record");      }    } catch (IllegalAccessException e) {      fail("can't copy boot record: "+e);    }    //    // Next, copy the jtoc.    //    if (verbose >= 1) say("copying jtoc");    Address jtocImageAddress = Address.zero();    try {      jtocImageAddress = copyToBootImage(VM_Statics.getSlotsAsIntArray(), false, Address.max(), null);      if (jtocImageAddress.EQ(OBJECT_NOT_PRESENT)) {        fail("can't copy jtoc");      }    } catch (IllegalAccessException e) {      fail("can't copy jtoc: "+e);    }    if (jtocImageAddress.NE(bootRecord.tocRegister))      fail("mismatch in JTOC placement "+VM.addressAsHexString(jtocImageAddress)+" != "+ VM.addressAsHexString(bootRecord.tocRegister));    //    // Now, copy all objects reachable from jtoc, replacing each object id    // that was generated by object address remapper with the actual    // bootimage address of that object.    //    if (verbose >= 1) say("copying statics");    try {      // The following seems to crash java for some reason...      //for (int i = 0; i < VM_Statics.getNumberOfSlots(); ++i)      int refSlotSize = VM_Statics.getReferenceSlotSize();      for (int i = 0, n = VM_Statics.getNumberOfSlots(); i < n; i += refSlotSize) {        jtocCount = i; // for diagnostic        if (!VM_Statics.isReference(i))          continue;        Offset jtocOff = VM_Statics.slotAsOffset(i);        //-#if RVM_FOR_32_ADDR        int objCookie = VM_Statics.getSlotContentsAsInt(jtocOff);        //-#endif        //-#if RVM_FOR_64_ADDR        int objCookie = (int) VM_Statics.getSlotContentsAsLong(jtocOff);        //-#endif        // if (verbose >= 3)        // say("       jtoc[", String.valueOf(i), "] = ", String.valueOf(objCookie));        Object jdkObject = BootImageMap.getObject(objCookie);        if (jdkObject == null)          continue;        if (verbose >= 2) traceContext.push(jdkObject.getClass().getName(),                                            getRvmStaticFieldName(jtocOff));        Address imageAddress = copyToBootImage(jdkObject, false, Address.max(), VM_Statics.getSlotsAsIntArray());        if (imageAddress.EQ(OBJECT_NOT_PRESENT)) {          // object not part of bootimage: install null reference          if (verbose >= 2) traceContext.traceObjectNotInBootImage();          bootImage.setNullAddressWord(jtocImageAddress.plus(jtocOff), false);        } else {          bootImage.setAddressWord(jtocImageAddress.plus(jtocOff),                                   imageAddress.toWord(), false);        }        if (verbose >= 2) traceContext.pop();      }    } catch (IllegalAccessException e) {      fail("unable to copy statics: "+e);    }    jtocCount = -1;    if (profile) {      stopTime = System.currentTimeMillis();      System.out.println("PROF: filling bootimage byte[] "+(stopTime-startTime)+" ms");    }    //    // Record startup context in boot record.    //    if (verbose >= 1) say("updating boot record");    int initProc = VM_Scheduler.PRIMORDIAL_PROCESSOR_ID;    VM_Thread startupThread = VM_Scheduler.processors[initProc].activeThread;    byte[] startupStack = startupThread.stack;    VM_CodeArray startupCode  = VM_Entrypoints.bootMethod.getCurrentEntryCodeArray();    bootRecord.tiRegister  = startupThread.getLockingId();    bootRecord.spRegister  = BootImageMap.getImageAddress(startupStack, true).plus(startupStack.length);    bootRecord.ipRegister  = BootImageMap.getImageAddress(startupCode.getBacking(), true);    bootRecord.processorsOffset = VM_Entrypoints.processorsField.getOffset();    bootRecord.bootImageDataStart = bootImageDataAddress;    bootRecord.bootImageDataEnd   = bootImageDataAddress.plus(bootImage.getDataSize());    bootRecord.bootImageCodeStart = bootImageCodeAddress;    bootRecord.bootImageCodeEnd   = bootImageCodeAddress.plus(bootImage.getCodeSize());    bootRecord.bootImageRMapStart = bootImageRMapAddress;    bootRecord.bootImageRMapEnd   = bootImageRMapAddress.plus(bootImage.getRMapSize());    // Update field of boot record now by re-copying    //    if (verbose >= 1) say("re-copying boot record (and its TIB)");    try {      Address newBootRecordImageAddress = copyToBootImage(bootRecord, false, bootRecordImageAddress, null);       if (!newBootRecordImageAddress.EQ(bootRecordImageAddress)) {        VM.sysWriteln("bootRecordImageOffset = ", bootRecordImageAddress);        VM.sysWriteln("newBootRecordImageOffset = ", newBootRecordImageAddress);        VM._assert(newBootRecordImageAddress.EQ(bootRecordImageAddress));      }    } catch (IllegalAccessException e) {      fail("unable to update boot record: "+e);    }    //-#if RVM_WITH_GCTRACE    /* Set the values in fields updated during the build process */    Offset prevAddrOffset = VM_Entrypoints.tracePrevAddressField.getOffset();    bootImage.setAddressWord(jtocImageAddress.plus(prevAddrOffset),                              VM_MiscHeader.getBootImageLink().toWord(), false);    Offset oIDOffset = VM_Entrypoints.traceOIDField.getOffset();    bootImage.setAddressWord(jtocImageAddress.plus(oIDOffset),                              VM_MiscHeader.getOID(), false);    //-#endif    //    // Write image to disk.    //    if (profile) startTime = System.currentTimeMillis();    try {      bootImage.write(bootImageCodeName, bootImageDataName, bootImageRMapName);    } catch (IOException e) {      fail("unable to write bootImage: "+e);    }    if (profile) {      stopTime = System.currentTimeMillis();      System.out.println("PROF: writing RVM.map "+(stopTime-startTime)+" ms");    }    //    // Show space usage in boot image by type    //    if (demographics) {      spaceReport();    }    //    // Summarize status of types that were referenced by objects we put into    // the bootimage but which are not, themselves, in the bootimage.  Any    // such types had better not be needed to dynamically link in the    // remainder of the virtual machine at run time!    //    if (false) {      VM_Type[] types = VM_Type.getTypes();      for (int i = FIRST_TYPE_DICTIONARY_INDEX; i < types.length; ++i) {        VM_Type type = types[i];        if (type == null) continue;        if (!type.isResolved()) {          say("type referenced but not resolved: ", type.toString());          continue;        }        if (!type.isInstantiated()) {          say("type referenced but not instantiated: ", type.toString());          continue;        }        if (!type.isInitialized()) {          say("type referenced but not initialized: ", type.toString());          continue;        }      }    }    //    // Generate address map for debugging.    //    try {      if (bootImageMapName != null)        writeAddressMap(bootImageMapName);    } catch (IOException e) {      fail("unable to write address map: "+e);    }    if (verbose >= 1) say("done");  }