if (verbose >= 2) say("resolving " + type);
  public static void createBootImageObjects(Vector typeNames,					    String bootImageTypeNamesFile)     throws IllegalAccessException, ClassNotFoundException   {      VM_Callbacks.notifyBootImage(typeNames.elements());      //      // Create types.      //      if (verbose >= 1) say("loading");      // verbose = 4;		// debug XXX            for (Enumeration e = typeNames.elements(); e.hasMoreElements(); ) {        //        // get type name        //        String typeName = (String) e.nextElement();	if (verbose >= 4)	  say("typeName:", typeName);	        //        // create corresponding rvm type        //	VM_Type type;		try {	  VM_TypeReference tRef = VM_TypeReference.findOrCreate(typeName);	  type = tRef.resolve();	} catch (NoClassDefFoundError ncdf) {	  ncdf.printStackTrace();	  fail(bootImageTypeNamesFile	       + " contains a class named \"" 	       + typeName + "\", but we can't find a class with that name: "	       + ncdf);	  return;		// NOTREACHED	} catch (IllegalArgumentException ila) {	  /* We should've caught any illegal type names at the data validation	   * stage, when we read these in.  If not, though, 	   * VM_TypeReference.findOrCreate() will do its own sanity check.  */	  ila.printStackTrace();	  fail(bootImageTypeNamesFile	       + " is supposed to contain type names.  It contains \"" 	       + typeName + "\", which does not parse as a legal type name: "	       + ila);	  return;		// NOTREACHED	}	type.markAsBootImageClass();        //        // convert type name from internal form to external form        // ie:    Ljava/lang/Object;   -->     java.lang.Object        //       [Ljava/lang/Object;   -->   [Ljava.lang.Object;        //        // NOTE: duplicate functionality.  There is a method that does the same.        //        typeName = typeName.replace('/','.');        if (typeName.startsWith("L"))          typeName = typeName.substring(1, typeName.length() - 1);        //        // record name/type pair for later lookup by getRvmType()        //        bootImageTypes.put(typeName, type);      }      if (verbose >= 1) say(String.valueOf(bootImageTypes.size()), " types");      //      // Lay out fields and method tables.      //      if (verbose >= 1) say("resolving");      for (Enumeration e = bootImageTypes.elements(); e.hasMoreElements(); ) {        VM_Type type = (VM_Type) e.nextElement();        // if (verbose >= 1) say("resolving ", type);	// The resolution is supposed to be cached already.        type.resolve();      }      // Set tocRegister early so opt compiler can access it to      //   perform fixed_jtoc optimization (compile static addresses into code).      // In the boot image, the bootrecord comes first followed by a VM_Address array and then the TOC.      //       VM_BootRecord bootRecord = VM_BootRecord.the_boot_record;      VM_Class rvmBRType = getRvmType(bootRecord.getClass()).asClass();      VM_Array intArrayType =  VM_Array.getPrimitiveArrayType(10);      bootRecord.tocRegister = VM_Address.fromInt(bootImageAddress + rvmBRType.getInstanceSize() + intArrayType.getInstanceSize(0));      //      // Compile methods and populate jtoc with literals, TIBs, and machine code.      //      if (verbose >= 1) say("instantiating");      if (PARALLELIZE < 1) {	int count = 0;	for (Enumeration e = bootImageTypes.elements(); e.hasMoreElements(); ) {	    VM_Type type = (VM_Type) e.nextElement();	    count++;	    if (verbose >= 1) say(count + " instantiating " + type);	    type.instantiate();	}      }      else {        if (verbose >= 1) say("parallelizing with " + PARALLELIZE + " threads");	BootImageWorker.startup(bootImageTypes.elements());	BootImageWorker [] workers = new BootImageWorker[PARALLELIZE];	for (int i=0; i<workers.length; i++) {	  workers[i].id = i;	  workers[i].start();	}	try {	  for (int i=0; i<workers.length; i++)	    workers[i].join();	}	catch (InterruptedException ie) {	    say("InterruptedException while instantiating");	}      }      //      // Collect the VM class Field to JDK class Field correspondence      // This will be needed when building the images of each object instance      // and for processing the static fields of the boot image classes      //      if (verbose >= 1) say("field info gathering");      bootImageTypeFields = new HashMap(bootImageTypes.size());      // First retrieve the jdk Field table for each class of interest      for (Enumeration e = bootImageTypes.elements(); e.hasMoreElements(); ) {        VM_Type rvmType = (VM_Type) e.nextElement();        FieldInfo fieldInfo;        if (!rvmType.isClassType())          continue; // arrays and primitives have no static or instance fields        Class jdkType = getJdkType(rvmType);        if (jdkType == null)          continue;  // won't need the field info        Key key   = new Key(jdkType);        fieldInfo = (FieldInfo)bootImageTypeFields.get(key);        if (fieldInfo != null) {          fieldInfo.rvmType = rvmType;        } else {          if (verbose >= 1) say("making fieldinfo for " + rvmType);          fieldInfo = new FieldInfo();          fieldInfo.jdkFields = jdkType.getDeclaredFields();          fieldInfo.jdkType = jdkType;          fieldInfo.rvmType = rvmType;          bootImageTypeFields.put(key, fieldInfo);          // Now do all the superclasses if they don't already exist          // Can't add them in next loop as Iterator's don't allow updates to collection          for (Class cls = jdkType.getSuperclass(); cls != null; cls = cls.getSuperclass()) {            key = new Key(cls);            fieldInfo = (FieldInfo)bootImageTypeFields.get(key);            if (fieldInfo != null) {              break;              } else {              if (verbose >= 1) say("making fieldinfo for " + jdkType);              fieldInfo = new FieldInfo();              fieldInfo.jdkFields = cls.getDeclaredFields();              fieldInfo.jdkType = cls;              fieldInfo.rvmType = null;                  bootImageTypeFields.put(key, fieldInfo);            }          }        }      }      // Now build the one-to-one instance and static field maps      for (Iterator iter = bootImageTypeFields.values().iterator(); iter.hasNext();) {        FieldInfo fieldInfo = (FieldInfo)iter.next();        VM_Type rvmType = fieldInfo.rvmType;        if (rvmType == null) {          if (verbose >= 1) say("bootImageTypeField entry has no rvmType:"+fieldInfo.jdkType);          continue;         }        Class jdkType   = fieldInfo.jdkType;        if (verbose >= 1) say("building static and instance fieldinfo for " + rvmType);        // First the statics        VM_Field rvmFields[] = rvmType.getStaticFields();        fieldInfo.jdkStaticFields = new Field[rvmFields.length];        //        // Search order:        // nextField helps us try to speedup locating the        // right field in the jdk's Field list. Turns out most of        // the time the jdk list is in the exact opposite order.        // So start at the end of the list and search forward.        // The next search should start from where we left off.         // If the first loop doesn't find the item, we'll need to         // search the fields we skipped in the second loop        //        int nextField = fieldInfo.jdkFields.length-1;        for (int j = 0; j < rvmFields.length; j++) {          boolean found = false;          String  rvmName = rvmFields[j].getName().toString();          for (int k = nextField; k >= 0; k--) {            Field f = fieldInfo.jdkFields[k];            if (f.getName().equals(rvmName)) {              fieldInfo.jdkStaticFields[j] = f;              f.setAccessible(true);              found = true;              nextField = k-1;              break;            }          }          if (!found) {            for (int k = nextField+1; k < fieldInfo.jdkFields.length; k++) {              Field f = fieldInfo.jdkFields[k];              if (f.getName().equals(rvmName)) {                fieldInfo.jdkStaticFields[j] = f;                f.setAccessible(true);                found = true;                nextField = fieldInfo.jdkFields.length-1;                break;              }            }	                if (!found) {              // Some fields just don't exist in JDK version              fieldInfo.jdkStaticFields[j] = null;            }          }        }        //        // Now the instance fields        // The search order is again organized in what seems to be        // the best for speed. With instance fields we need to search        // the superclasses too. Once a field is found in a fieldtable        // we try to start the search for the next field in the same        // field table starting from where we left off. If it is not        // in the current field table we try the superclasses's fieldtables        // If that doesn't work, we must try again but starting from        // the original jdktype.        //        rvmFields = rvmType.getInstanceFields();        fieldInfo.jdkInstanceFields = new Field[rvmFields.length];        Field[] jdkFields = fieldInfo.jdkFields;        nextField = jdkFields.length-1;        for (int j = 0; j < rvmFields.length; j++) {          boolean found = false;          String  rvmName = rvmFields[j].getName().toString();          while (!found && jdkType != null) {            for (int k = nextField; k >= 0; k--) {              Field f = jdkFields[k];              if (f.getName().equals(rvmName)) {                fieldInfo.jdkInstanceFields[j] = f;                f.setAccessible(true);                found = true;                nextField = k-1;                break;              }            }            if (!found) {              // Try the part of the field table we missed              for (int k = nextField+1; k < jdkFields.length; k++) {                Field f = jdkFields[k];                if (f.getName().equals(rvmName)) {                  fieldInfo.jdkInstanceFields[j] = f;                  f.setAccessible(true);                  found = true;                  // Order seems unpredicable, so do a full search for                  // next field                  nextField = jdkFields.length-1;                  break;                }              }            }            // If not found try field array from next superclass            if (!found) {              jdkType = jdkType.getSuperclass();              if (jdkType != null) {                Key key = new Key(jdkType);                FieldInfo superFieldInfo = (FieldInfo)bootImageTypeFields.get(key);                jdkFields = superFieldInfo.jdkFields;                nextField = jdkFields.length-1;              }            }          }          if (!found) {            // go back to basics and start search from beginning.            jdkType = fieldInfo.jdkType;            FieldInfo jdkFieldInfo = fieldInfo;            for (jdkType = fieldInfo.jdkType; jdkType != null && !found;                  jdkType = jdkType.getSuperclass(),                  jdkFieldInfo = (jdkType!=null) ? (FieldInfo)bootImageTypeFields.get(new Key(jdkType)) : null) {              jdkFields = jdkFieldInfo.jdkFields;              for (int k = 0; k < jdkFields.length; k++) {                Field f = jdkFields[k];                if (f.getName().equals(rvmName)) {                  fieldInfo.jdkInstanceFields[j] = f;                  f.setAccessible(true);                  found = true;                  // Turns out the next field is often in this table too                  // so remember where we left off.                  nextField = k-1;                  break;                }              }            }            if (!found) {              fieldInfo.jdkInstanceFields[j] = null;              // Best to start search for next field from beginning              jdkType = fieldInfo.jdkType;              jdkFields = fieldInfo.jdkFields;              nextField = jdkFields.length-1;              found = true;            }          }        }      }      //      // Create stack, thread, and processor context in which rvm will begin      // execution.      //      int initProc = VM_Scheduler.PRIMORDIAL_PROCESSOR_ID;      VM_Thread startupThread = new VM_Thread(new int[STACK_SIZE_BOOT >> 2]);      VM_Scheduler.processors[initProc].activeThread = startupThread;      // sanity check for bootstrap loader      startupThread.stack[(STACK_SIZE_BOOT >> 2) - 1] = 0xdeadbabe;      //      // Tell rvm where to find itself at execution time.      // This may not be the same place it was at build time, ie. if image is      // moved to another machine with different directory structure.      //      VM_ClassLoader.setVmRepositories(bootImageRepositoriesAtExecutionTime);      //      // Finally, populate jtoc with static field values.      // This is equivalent to the VM_Class.initialize() phase that would have      // executed each class's static constructors at run time.  We simulate      // this by copying statics created in the host rvm into the appropriate      // slots of the jtoc.      //      if (verbose >= 1) say("populating jtoc with static fields");      for (Enumeration e = bootImageTypes.elements(); e.hasMoreElements(); ) {        VM_Type rvmType = (VM_Type) e.nextElement();        if (verbose >= 1) say("  jtoc for ", rvmType.toString());        if (!rvmType.isClassType())          continue; // arrays and primitives have no static fields        Class jdkType = getJdkType(rvmType);        if (jdkType == null && verbose >= 1) {          say("host has no class \"" + rvmType + "\"");        }        VM_Field rvmFields[] = rvmType.getStaticFields();        for (int j = 0; j < rvmFields.length; ++j) {          VM_Field rvmField     = rvmFields[j];          VM_TypeReference rvmFieldType = rvmField.getType();          int      rvmFieldSlot = (rvmField.getOffset() >>> 2);          String   rvmFieldName = rvmField.getName().toString();          Field    jdkFieldAcc  = null;          if (jdkType != null)             jdkFieldAcc = getJdkFieldAccessor(jdkType, j, STATIC_FIELD);          if (jdkFieldAcc == null) {            if (jdkType != null) {              if (verbose >= 1) traceContext.push(rvmFieldType.toString(),                                                  jdkType.getName(), rvmFieldName);              if (verbose >= 1) traceContext.traceFieldNotInHostJdk();              if (verbose >= 1) traceContext.pop();            }            VM_Statics.setSlotContents(rvmFieldSlot, 0);            if (!VM.runningTool)              bootImage.countNulledReference();            continue;          }          if (verbose >= 2)             say("    populating jtoc slot ", String.valueOf(rvmFieldSlot),                 " with ", rvmField.toString());          if (rvmFieldType.isPrimitiveType()) {            // field is logical or numeric type            if (rvmFieldType.isBooleanType()) {              VM_Statics.setSlotContents(rvmFieldSlot,                                         jdkFieldAcc.getBoolean(null) ? 1 : 0);	    } else if (rvmFieldType.isByteType()) {              VM_Statics.setSlotContents(rvmFieldSlot, jdkFieldAcc.getByte(null));	    } else if (rvmFieldType.isCharType()) {              VM_Statics.setSlotContents(rvmFieldSlot, jdkFieldAcc.getChar(null));            } else if (rvmFieldType.isShortType()) {              VM_Statics.setSlotContents(rvmFieldSlot, jdkFieldAcc.getShort(null));	    } else if (rvmFieldType.isIntType()) {              try {                VM_Statics.setSlotContents(rvmFieldSlot,                                           jdkFieldAcc.getInt(null));              } catch (IllegalArgumentException ex) {                System.err.println( "type " + rvmType + ", field " + rvmField);                throw ex;              }	    } else if (rvmFieldType.isLongType()) {              // note: Endian issues handled in setSlotContents.              VM_Statics.setSlotContents(rvmFieldSlot,                                         jdkFieldAcc.getLong(null));            } else if (rvmFieldType.isFloatType()) {              float f = jdkFieldAcc.getFloat(null);              VM_Statics.setSlotContents(rvmFieldSlot,                                         Float.floatToIntBits(f));            } else if (rvmFieldType.isDoubleType()) {              double d = jdkFieldAcc.getDouble(null);              // note: Endian issues handled in setSlotContents.              VM_Statics.setSlotContents(rvmFieldSlot,                                         Double.doubleToLongBits(d));            } else if (rvmFieldType.equals(VM_TypeReference.Address)) {              Object o = jdkFieldAcc.get(null);              VM_Address addr = (VM_Address) o;              String msg = " static field " + rvmField.toString();	      VM_Statics.setSlotContents(rvmFieldSlot, getAddressValue(addr, msg, true));  // int or long            } else if (rvmFieldType.equals(VM_TypeReference.Word)) {              VM_Word w = (VM_Word) jdkFieldAcc.get(null);              VM_Statics.setSlotContents(rvmFieldSlot, w.toInt());            } else if (rvmFieldType.equals(VM_TypeReference.Offset)) {              VM_Offset o = (VM_Offset) jdkFieldAcc.get(null);              VM_Statics.setSlotContents(rvmFieldSlot, o.toInt());            } else if (rvmFieldType.equals(VM_TypeReference.Extent)) {              VM_Extent ex = (VM_Extent) jdkFieldAcc.get(null);              VM_Statics.setSlotContents(rvmFieldSlot, ex.toInt());            } else {              fail("unexpected primitive field type: " + rvmFieldType);	    }          } else {            // field is reference type            Object o = jdkFieldAcc.get(null);            if (verbose >= 3)              say("       setting with ", String.valueOf(VM_Magic.objectAsAddress(o).toInt()));            //-#if RVM_FOR_32_ADDR	    VM_Statics.setSlotContents(rvmFieldSlot,                                       VM_Magic.objectAsAddress(o).toInt());	    //-#endif            //-#if RVM_FOR_64_ADDR	    VM_Statics.setSlotContents(rvmFieldSlot,                                       VM_Magic.objectAsAddress(o).toLong());	    //-#endif          }        }      }    }