use of org.jikesrvm.runtime.BootRecord in project JikesRVM by JikesRVM.
the class VM method init.
// ----------------//
// implementation //
// ----------------//
/**
* Create class instances needed for boot image or initialize classes
* needed by tools.
* @param bootstrapClasspath places where VM implementation class reside
* @param bootCompilerArgs command line arguments to pass along to the
* boot compiler's init routine.
*/
@Interruptible
private static void init(String bootstrapClasspath, String[] bootCompilerArgs) {
if (VM.VerifyAssertions)
VM._assert(!VM.runningVM);
// create dummy boot record
//
BootRecord.the_boot_record = new BootRecord();
// initialize type subsystem and classloader
RVMClassLoader.init(bootstrapClasspath);
//
if (writingBootImage) {
// initialize compiler that builds boot image
BootImageCompiler.init(bootCompilerArgs);
}
RuntimeEntrypoints.init();
RVMThread.init();
}
use of org.jikesrvm.runtime.BootRecord in project JikesRVM by JikesRVM.
the class BootImageWriter method main.
/**
* Main.
* @param args command line arguments
*/
public static void main(String[] args) {
String logFile = null;
String bootImageCodeName = null;
String bootImageDataName = null;
String bootImageRMapName = null;
String bootImageMapName = null;
Vector<String> 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<Object, Class<?>> x = new java.util.HashMap<Object, Class<?>>();
x.put(x, x.getClass());
sillyhack = x;
//
for (int i = 0; i < args.length; ++i) {
// name of class library
if (args[i].equals("-classlib")) {
if (++i >= args.length)
fail("argument syntax error: Got a -classlib flag without a following class library name");
classLibrary = args[i].toLowerCase().intern();
continue;
}
// 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 = decodeAddress(args[i]);
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 = decodeAddress(args[i]);
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 = decodeAddress(args[i]);
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")) {
verbosity = verbosity.increaseBy(1);
continue;
}
// generate info by type
if (args[i].equals("-demographics")) {
demographics = true;
continue;
}
// numThreads
if (args[i].startsWith("-numThreads=")) {
int desiredThreadCount = Integer.parseInt(args[i].substring(12));
if (desiredThreadCount < 0) {
fail("numThreads must be a non-negative number, value supplied: " + desiredThreadCount);
}
// already does this so there's nothing to do here.
if (desiredThreadCount == 0)
continue;
// use the explicit value provided by the user
numThreads = desiredThreadCount;
continue;
}
// profile
if (args[i].equals("-profile")) {
profile = true;
continue;
}
// log
if (args[i].equals("-log")) {
if (++i >= args.length)
fail("argument syntax error: Got a -log flag without a following argument for the log file");
logFile = args[i];
continue;
}
// generate detailed information about traversed objects (for debugging)
if (args[i].equals("-detailed")) {
verbosity = verbosity.increaseBy(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 (verbosity.isAtLeast(Verbosity.DETAILED))
traversed = new Hashtable<Object, Integer>(500);
//
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");
// Redirect the log file
if (logFile != null) {
try {
PrintStream logFileStream = new PrintStream(logFile);
System.setOut(logFileStream);
System.setErr(logFileStream);
} catch (IOException ex) {
fail("Failed to open log file for redirecting: " + ex.getMessage());
}
}
//
try {
bootImage = new BootImage(littleEndian, verbosity.isAtLeast(Verbosity.SUMMARY), bootImageCodeName, bootImageDataName, bootImageRMapName);
} catch (IOException e) {
fail("unable to write bootImage: " + e);
}
//
// Install handler that intercepts all object address references made by
// 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();
//
if (verbosity.isAtLeast(SUMMARY))
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(System.out);
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 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 (verbosity.isAtLeast(SUMMARY))
say("Memory available: ", String.valueOf(Runtime.getRuntime().freeMemory()), " bytes out of ", String.valueOf(Runtime.getRuntime().totalMemory()), " bytes");
if (profile)
startTime = System.currentTimeMillis();
//
if (verbosity.isAtLeast(SUMMARY))
say("copying boot record");
BootRecord bootRecord = BootRecord.the_boot_record;
Address bootRecordImageAddress = Address.zero();
try {
// copy just the boot record
bootRecordImageAddress = copyToBootImage(bootRecord, true, Address.max(), null, false, AlignmentEncoding.ALIGN_CODE_NONE);
if (bootRecordImageAddress.EQ(OBJECT_NOT_PRESENT)) {
fail("can't copy boot record");
}
} catch (IllegalAccessException e) {
fail("can't copy boot record: " + e);
}
//
if (verbosity.isAtLeast(SUMMARY))
say("copying jtoc");
// Pointer to middle of JTOC
Address jtocImageAddress = Address.max();
try {
if (VM.BuildForIA32) {
// Force 16byte alignment of the JTOC on Intel
int[] slots = Statics.getSlotsAsIntArray();
jtocImageAddress = bootImage.allocateArray(RVMArray.IntArray, slots.length, false, 0, 16, AlignmentEncoding.ALIGN_CODE_NONE);
BootImageMap.Entry jtocEntry = BootImageMap.findOrCreateEntry(slots);
jtocEntry.imageAddress = jtocImageAddress;
}
jtocImageAddress = copyToBootImage(Statics.getSlotsAsIntArray(), false, jtocImageAddress, null, false, AlignmentEncoding.ALIGN_CODE_NONE);
if (jtocImageAddress.EQ(OBJECT_NOT_PRESENT)) {
fail("can't copy jtoc");
}
} catch (IllegalAccessException e) {
fail("can't copy jtoc: " + e);
}
Address jtocPtr = jtocImageAddress.plus(Statics.middleOfTable << LOG_BYTES_IN_INT);
if (jtocPtr.NE(bootRecord.tocRegister))
fail("mismatch in JTOC placement " + Services.addressAsHexString(jtocPtr) + " != " + Services.addressAsHexString(bootRecord.tocRegister));
//
if (verbosity.isAtLeast(SUMMARY))
say("copying statics");
try {
int refSlotSize = Statics.getReferenceSlotSize();
for (int i = Statics.middleOfTable + refSlotSize, n = Statics.getHighestInUseSlot(); i <= n; i += refSlotSize) {
if (!Statics.isReference(i)) {
throw new Error("Static " + i + " of " + n + " isn't reference");
}
// for diagnostic
jtocCount = i;
Offset jtocOff = Statics.slotAsOffset(i);
int objCookie;
if (VM.BuildFor32Addr)
objCookie = Statics.getSlotContentsAsInt(jtocOff);
else
objCookie = (int) Statics.getSlotContentsAsLong(jtocOff);
// if (verbose.isAtLeast(ADDRESSES))
// say(" jtoc[", String.valueOf(i), "] = ", String.valueOf(objCookie));
Object jdkObject = BootImageMap.getObject(objCookie);
if (jdkObject == null)
continue;
if (verbosity.isAtLeast(DETAILED))
traceContext.push(jdkObject.getClass().getName(), getRvmStaticField(jtocOff) + "");
copyReferenceFieldToBootImage(jtocPtr.plus(jtocOff), jdkObject, Statics.getSlotsAsIntArray(), false, false, null, null);
if (verbosity.isAtLeast(DETAILED))
traceContext.pop();
}
// Copy entries that are in the pending queue
processPendingEntries();
// Find and copy unallocated entries
for (int i = 0; i < BootImageMap.objectIdToEntry.size(); i++) {
BootImageMap.Entry mapEntry = BootImageMap.objectIdToEntry.get(i);
if (mapEntry.imageAddress.EQ(OBJECT_NOT_ALLOCATED)) {
mapEntry.imageAddress = copyToBootImage(mapEntry.jdkObject, false, Address.max(), null, false, AlignmentEncoding.ALIGN_CODE_NONE);
fixupLinkAddresses(mapEntry);
}
}
} 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");
}
//
if (verbosity.isAtLeast(SUMMARY))
say("updating boot record");
byte[] startupStack = startupThread.getStack();
CodeArray startupCode = Entrypoints.bootMethod.getCurrentEntryCodeArray();
bootRecord.spRegister = BootImageMap.getImageAddress(startupStack, true).plus(startupStack.length);
bootRecord.ipRegister = BootImageMap.getImageAddress(startupCode.getBacking(), true);
bootRecord.bootThreadOffset = Entrypoints.bootThreadField.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());
//
if (verbosity.isAtLeast(SUMMARY))
say("re-copying boot record (and its TIB)");
try {
Address newBootRecordImageAddress = copyToBootImage(bootRecord, false, bootRecordImageAddress, null, false, AlignmentEncoding.ALIGN_CODE_NONE);
if (!newBootRecordImageAddress.EQ(bootRecordImageAddress)) {
VM.sysWriteln("bootRecordImageOffset = ", bootRecordImageAddress);
VM.sysWriteln("newBootRecordImageOffset = ", newBootRecordImageAddress);
if (VM.VerifyAssertions) {
VM._assert(newBootRecordImageAddress.EQ(bootRecordImageAddress));
}
}
// Make sure pending entries are fully written out
processPendingEntries();
} catch (IllegalAccessException e) {
fail("unable to update boot record: " + e);
}
if (VM.BuildWithGCTrace) {
/* Set the values in fields updated during the build process */
Offset prevAddrOffset = Entrypoints.tracePrevAddressField.getOffset();
bootImage.setAddressWord(jtocPtr.plus(prevAddrOffset), MiscHeader.getBootImageLink().toWord(), false, false);
Offset oIDOffset = Entrypoints.traceOIDField.getOffset();
bootImage.setAddressWord(jtocPtr.plus(oIDOffset), MiscHeader.getOID(), false, false);
}
//
if (profile)
startTime = System.currentTimeMillis();
try {
bootImage.write();
} catch (IOException e) {
fail("unable to write bootImage: " + e);
}
if (profile) {
stopTime = System.currentTimeMillis();
System.out.println("PROF: writing RVM.map " + (stopTime - startTime) + " ms");
}
//
if (demographics) {
spaceReport();
}
//
if (verbosity.isAtLeast(DETAILED)) {
for (int i = FIRST_TYPE_DICTIONARY_INDEX; i < RVMType.numTypes(); ++i) {
RVMType type = RVMType.getType(i);
if (type == null)
continue;
if (!type.isResolved()) {
say("type referenced but not resolved: ", type.toString());
} else if (!type.isInstantiated()) {
say("type referenced but not instantiated: ", type.toString());
} else if (!type.isInitialized()) {
say("type referenced but not initialized: ", type.toString());
}
}
}
//
try {
if (bootImageMapName != null)
writeAddressMap(bootImageMapName);
} catch (IOException e) {
fail("unable to write address map: " + e);
}
if (verbosity.isAtLeast(SUMMARY))
say("done");
}
use of org.jikesrvm.runtime.BootRecord in project JikesRVM by JikesRVM.
the class BootImageWriter method createBootImageObjects.
/**
* 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.<p>
*
* Side effects:
* <ul>
* <li>RVM objects are created in host JDK address space
* <li>Statics is populated
* <li>"bootImageTypes" dictionary is populated with name/type pairs
* </ul>
*
* @param typeNames names of RVM classes whose static fields will contain
* the objects comprising the virtual machine bootimage
*/
public static void createBootImageObjects(Vector<String> typeNames, String bootImageTypeNamesFile) throws IllegalAccessException {
Callbacks.notifyBootImage(typeNames.elements());
long startTime = 0;
long stopTime = 0;
//
if (verbosity.isAtLeast(SUMMARY))
say("loading");
if (profile)
startTime = System.currentTimeMillis();
for (String typeName : typeNames) {
//
if (verbosity.isAtLeast(TYPE_NAMES))
say("typeName:", typeName);
//
// create corresponding rvm type
//
RVMType type;
try {
TypeReference tRef = TypeReference.findOrCreate(typeName);
type = tRef.resolve();
} catch (NoClassDefFoundError ncdf) {
ncdf.printStackTrace(System.out);
fail(bootImageTypeNamesFile + " contains a class named \"" + typeName + "\", but we can't find a class with that name: " + ncdf);
// NOTREACHED
return;
} catch (IllegalArgumentException ila) {
/* We should've caught any illegal type names at the data validation
* stage, when we read these in. If not, though,
* TypeReference.findOrCreate() will do its own sanity check. */
ila.printStackTrace(System.out);
fail(bootImageTypeNamesFile + " is supposed to contain type names. It contains \"" + typeName + "\", which does not parse as a legal type name: " + ila);
// NOTREACHED
return;
}
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 (profile) {
stopTime = System.currentTimeMillis();
System.out.println("PROF: \tloading types " + (stopTime - startTime) + " ms");
}
int typeCount = bootImageTypes.size();
JMXSupport.CLASS_LOADING_JMX_SUPPORT.setClassLoadedCountForBootimage(typeCount);
if (verbosity.isAtLeast(SUMMARY))
say(String.valueOf(typeCount), " types");
//
if (profile)
startTime = System.currentTimeMillis();
if (verbosity.isAtLeast(SUMMARY))
say("resolving");
for (RVMType type : bootImageTypes.values()) {
if (verbosity.isAtLeast(DETAILED))
say("resolving " + type);
// The resolution is supposed to be cached already.
type.resolve();
}
//
for (RVMType type : bootImageTypes.values()) {
type.allBootImageTypesResolved();
}
if (profile) {
stopTime = System.currentTimeMillis();
System.out.println("PROF: \tresolving types " + (stopTime - startTime) + " ms");
}
// 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
// Address array and then the TOC. To do this, we must fully
// simulate the alignment logic in the allocation code! Rather
// than replicate the allocation code here, we perform dummy
// allocations and then reset the boot image allocator.
BootRecord bootRecord = BootRecord.the_boot_record;
RVMClass rvmBRType = getRvmType(bootRecord.getClass()).asClass();
RVMArray intArrayType = RVMArray.IntArray;
// allocate storage for boot record
bootImage.allocateDataStorage(rvmBRType.getInstanceSize(), ObjectModel.getAlignment(rvmBRType), ObjectModel.getOffsetForAlignment(rvmBRType, false));
// allocate storage for JTOC (force 16byte alignment of the JTOC on Intel)
Address jtocAddress = bootImage.allocateDataStorage(intArrayType.getInstanceSize(0), VM.BuildForIA32 ? 16 : ObjectModel.getAlignment(intArrayType), ObjectModel.getOffsetForAlignment(intArrayType, false));
bootImage.resetAllocator();
bootRecord.tocRegister = jtocAddress.plus(intArrayType.getInstanceSize(Statics.middleOfTable));
// set up some stuff we need for compiling
ArchitectureFactory.initOutOfLineMachineCode();
//
if (profile)
startTime = System.currentTimeMillis();
if (verbosity.isAtLeast(SUMMARY))
say("instantiating");
if (verbosity.isAtLeast(SUMMARY))
say("setting up compilation infrastructure and pre-compiling easy cases");
CompilationOrder order = new CompilationOrder(typeCount, numThreads);
for (RVMType type : bootImageTypes.values()) {
order.addType(type);
}
order.fixUpMissingSuperClasses();
if (verbosity.isAtLeast(SUMMARY))
say(" compiling with " + numThreads + " threads");
ThreadFactory threadFactory = new KillVMonUncaughtExceptionThreadFactory();
ExecutorService threadPool = Executors.newFixedThreadPool(numThreads, threadFactory);
int runnableCount = order.getCountOfNeededWorkers();
while (runnableCount > 0) {
try {
threadPool.execute(order.getNextRunnable());
runnableCount--;
} catch (InterruptedException e) {
throw new Error("Build interrupted", e);
}
}
threadPool.shutdown();
try {
while (!threadPool.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS)) {
say("Compilation really shouldn't take this long");
}
} catch (InterruptedException e) {
throw new Error("Build interrupted", e);
}
if (BootImageWorker.instantiationFailed) {
throw new Error("Error during instantiaion");
}
if (profile) {
stopTime = System.currentTimeMillis();
System.out.println("PROF: \tinstantiating types " + (stopTime - startTime) + " ms");
}
// Free up unnecessary Statics data structures
staticsJunk = Statics.bootImageInstantiationFinished();
// Do the portion of JNIEnvironment initialization that can be done
// at bootimage writing time.
FunctionTable functionTable = BuildJNIFunctionTable.buildTable();
JNIEnvironment.initFunctionTable(functionTable);
//
if (verbosity.isAtLeast(SUMMARY))
say("field info gathering");
if (profile)
startTime = System.currentTimeMillis();
bootImageTypeFields = new HashMap<Key, FieldInfo>(typeCount);
HashSet<String> invalidEntrys = new HashSet<String>();
// First retrieve the jdk Field table for each class of interest
for (RVMType rvmType : bootImageTypes.values()) {
FieldInfo fieldInfo;
if (!rvmType.isClassType())
// arrays and primitives have no static or instance fields
continue;
Class<?> jdkType = getJdkType(rvmType);
if (jdkType == null)
// won't need the field info
continue;
Key key = new Key(jdkType);
fieldInfo = bootImageTypeFields.get(key);
if (fieldInfo != null) {
fieldInfo.rvmType = rvmType;
} else {
if (verbosity.isAtLeast(SUMMARY))
say("making fieldinfo for " + rvmType);
fieldInfo = new FieldInfo(jdkType, rvmType);
bootImageTypeFields.put(key, fieldInfo);
// 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 = bootImageTypeFields.get(key);
if (fieldInfo != null) {
break;
} else {
if (verbosity.isAtLeast(SUMMARY))
say("making fieldinfo for " + jdkType);
fieldInfo = new FieldInfo(cls, null);
bootImageTypeFields.put(key, fieldInfo);
}
}
}
}
// Now build the one-to-one instance and static field maps
for (FieldInfo fieldInfo : bootImageTypeFields.values()) {
RVMType rvmType = fieldInfo.rvmType;
if (rvmType == null) {
if (verbosity.isAtLeast(SUMMARY))
say("bootImageTypeField entry has no rvmType:" + fieldInfo.jdkType);
continue;
}
Class<?> jdkType = fieldInfo.jdkType;
if (verbosity.isAtLeast(SUMMARY))
say("building static and instance fieldinfo for " + rvmType);
// First the static fields
//
RVMField[] rvmFields = rvmType.getStaticFields();
fieldInfo.jdkStaticFields = new Field[rvmFields.length];
for (int j = 0; j < rvmFields.length; j++) {
String rvmName = rvmFields[j].getName().toString();
for (Field f : fieldInfo.jdkFields) {
if (f.getName().equals(rvmName)) {
fieldInfo.jdkStaticFields[j] = f;
f.setAccessible(true);
break;
}
}
}
// Now the instance fields
//
rvmFields = rvmType.getInstanceFields();
fieldInfo.jdkInstanceFields = new Field[rvmFields.length];
for (int j = 0; j < rvmFields.length; j++) {
String rvmName = rvmFields[j].getName().toString();
// We look only in the JDK type that corresponds to the
// RVMType of the field's declaring class.
// This is the only way to correctly handle private fields.
jdkType = getJdkType(rvmFields[j].getDeclaringClass());
if (jdkType == null)
continue;
FieldInfo jdkFieldInfo = bootImageTypeFields.get(new Key(jdkType));
if (jdkFieldInfo == null)
continue;
Field[] jdkFields = jdkFieldInfo.jdkFields;
for (Field f : jdkFields) {
if (f.getName().equals(rvmName)) {
fieldInfo.jdkInstanceFields[j] = f;
f.setAccessible(true);
break;
}
}
}
}
if (profile) {
stopTime = System.currentTimeMillis();
System.out.println("PROF: \tcreating type mapping " + (stopTime - startTime) + " ms");
}
//
// Create stack, thread, and processor context in which rvm will begin
// execution.
startupThread = RVMThread.setupBootThread();
byte[] stack = startupThread.getStack();
// sanity check for bootstrap loader
int idx = stack.length - 1;
if (VM.LittleEndian) {
stack[idx--] = (byte) 0xde;
stack[idx--] = (byte) 0xad;
stack[idx--] = (byte) 0xba;
stack[idx--] = (byte) 0xbe;
} else {
stack[idx--] = (byte) 0xbe;
stack[idx--] = (byte) 0xba;
stack[idx--] = (byte) 0xad;
stack[idx--] = (byte) 0xde;
}
//
// 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.
//
BootstrapClassLoader.setBootstrapRepositories(bootImageRepositoriesAtExecutionTime);
//
if (verbosity.isAtLeast(SUMMARY))
say("populating jtoc with static fields");
if (profile)
startTime = System.currentTimeMillis();
for (RVMType rvmType : bootImageTypes.values()) {
if (verbosity.isAtLeast(SUMMARY))
say(" jtoc for ", rvmType.toString());
if (!rvmType.isClassType())
// arrays and primitives have no static fields
continue;
Class<?> jdkType = getJdkType(rvmType);
if (jdkType == null && verbosity.isAtLeast(SUMMARY)) {
say("host has no class \"" + rvmType + "\"");
}
RVMField[] rvmFields = rvmType.getStaticFields();
for (int j = 0; j < rvmFields.length; ++j) {
RVMField rvmField = rvmFields[j];
TypeReference rvmFieldType = rvmField.getType();
Offset rvmFieldOffset = rvmField.getOffset();
String rvmFieldName = rvmField.getName().toString();
Field jdkFieldAcc = null;
if (jdkType != null && jdkType.equals(java.util.concurrent.locks.AbstractQueuedSynchronizer.class)) {
RVMClass c = (RVMClass) rvmType;
if (rvmFieldName.equals("stateOffset")) {
Statics.setSlotContents(rvmFieldOffset, c.findDeclaredField(Atom.findOrCreateAsciiAtom("state")).getOffset().toLong());
continue;
} else if (rvmFieldName.equals("headOffset")) {
Statics.setSlotContents(rvmFieldOffset, c.findDeclaredField(Atom.findOrCreateAsciiAtom("head")).getOffset().toLong());
continue;
} else if (rvmFieldName.equals("tailOffset")) {
Statics.setSlotContents(rvmFieldOffset, c.findDeclaredField(Atom.findOrCreateAsciiAtom("tail")).getOffset().toLong());
continue;
} else if (rvmFieldName.equals("waitStatusOffset")) {
try {
Statics.setSlotContents(rvmFieldOffset, ((RVMClass) getRvmType(Class.forName("java.util.concurrent.locks.AbstractQueuedSynchronizer$Node"))).findDeclaredField(Atom.findOrCreateAsciiAtom("waitStatus")).getOffset().toLong());
} catch (ClassNotFoundException e) {
throw new Error(e);
}
continue;
}
} else if (jdkType != null && jdkType.equals(java.util.concurrent.locks.LockSupport.class)) {
RVMClass c = (RVMClass) rvmType;
if (rvmFieldName.equals("parkBlockerOffset")) {
Statics.setSlotContents(rvmFieldOffset, ((RVMClass) getRvmType(java.lang.Thread.class)).findDeclaredField(Atom.findOrCreateAsciiAtom("parkBlocker")).getOffset().toLong());
continue;
}
}
if (jdkType != null)
jdkFieldAcc = getJdkFieldAccessor(jdkType, j, STATIC_FIELD);
if (jdkFieldAcc == null) {
// we failed to get a reflective field accessors
if (jdkType != null) {
// we know the type - probably a private field of a java.lang class
if (!copyKnownStaticField(jdkType, rvmFieldName, rvmFieldType, rvmFieldOffset)) {
// we didn't know the field so nullify
if (verbosity.isAtLeast(DETAILED)) {
traceContext.push(rvmFieldType.toString(), jdkType.getName(), rvmFieldName);
traceContext.traceFieldNotInHostJdk();
traceContext.pop();
}
Statics.setSlotContents(rvmFieldOffset, 0);
if (!VM.runningTool)
bootImage.countNulledReference();
invalidEntrys.add(jdkType.getName());
}
} else {
// no accessor and we don't know the type so nullify
if (verbosity.isAtLeast(DETAILED)) {
traceContext.push(rvmFieldType.toString(), rvmFieldType.toString(), rvmFieldName);
traceContext.traceFieldNotInHostJdk();
traceContext.pop();
}
Statics.setSlotContents(rvmFieldOffset, 0);
if (!VM.runningTool)
bootImage.countNulledReference();
invalidEntrys.add(rvmField.getDeclaringClass().toString());
}
continue;
}
if (!Modifier.isStatic(jdkFieldAcc.getModifiers())) {
if (verbosity.isAtLeast(DETAILED))
traceContext.push(rvmFieldType.toString(), jdkType.getName(), rvmFieldName);
if (verbosity.isAtLeast(DETAILED))
traceContext.traceFieldNotStaticInHostJdk();
if (verbosity.isAtLeast(DETAILED))
traceContext.pop();
Statics.setSlotContents(rvmFieldOffset, 0);
if (!VM.runningTool)
bootImage.countNulledReference();
invalidEntrys.add(jdkType.getName());
continue;
}
if (!equalTypes(jdkFieldAcc.getType().getName(), rvmFieldType)) {
if (verbosity.isAtLeast(DETAILED))
traceContext.push(rvmFieldType.toString(), jdkType.getName(), rvmFieldName);
if (verbosity.isAtLeast(DETAILED))
traceContext.traceFieldDifferentTypeInHostJdk();
if (verbosity.isAtLeast(DETAILED))
traceContext.pop();
Statics.setSlotContents(rvmFieldOffset, 0);
if (!VM.runningTool)
bootImage.countNulledReference();
invalidEntrys.add(jdkType.getName());
continue;
}
if (verbosity.isAtLeast(DETAILED))
say(" populating jtoc slot ", String.valueOf(Statics.offsetAsSlot(rvmFieldOffset)), " with ", rvmField.toString());
if (rvmFieldType.isPrimitiveType()) {
// field is logical or numeric type
if (rvmFieldType.isBooleanType()) {
Statics.setSlotContents(rvmFieldOffset, jdkFieldAcc.getBoolean(null) ? 1 : 0);
} else if (rvmFieldType.isByteType()) {
Statics.setSlotContents(rvmFieldOffset, jdkFieldAcc.getByte(null));
} else if (rvmFieldType.isCharType()) {
Statics.setSlotContents(rvmFieldOffset, jdkFieldAcc.getChar(null));
} else if (rvmFieldType.isShortType()) {
Statics.setSlotContents(rvmFieldOffset, jdkFieldAcc.getShort(null));
} else if (rvmFieldType.isIntType()) {
Statics.setSlotContents(rvmFieldOffset, jdkFieldAcc.getInt(null));
} else if (rvmFieldType.isLongType()) {
// note: Endian issues handled in setSlotContents.
Statics.setSlotContents(rvmFieldOffset, jdkFieldAcc.getLong(null));
} else if (rvmFieldType.isFloatType()) {
float f = jdkFieldAcc.getFloat(null);
Statics.setSlotContents(rvmFieldOffset, Float.floatToIntBits(f));
} else if (rvmFieldType.isDoubleType()) {
double d = jdkFieldAcc.getDouble(null);
// note: Endian issues handled in setSlotContents.
Statics.setSlotContents(rvmFieldOffset, Double.doubleToLongBits(d));
} else if (rvmFieldType.equals(TypeReference.Address) || rvmFieldType.equals(TypeReference.Word) || rvmFieldType.equals(TypeReference.Extent) || rvmFieldType.equals(TypeReference.Offset)) {
Object o = jdkFieldAcc.get(null);
String msg = " static field " + rvmField.toString();
boolean warn = rvmFieldType.equals(TypeReference.Address);
Statics.setSlotContents(rvmFieldOffset, getWordValue(o, msg, warn));
} else {
fail("unexpected primitive field type: " + rvmFieldType);
}
} else {
// field is reference type
final Object o = jdkFieldAcc.get(null);
if (verbosity.isAtLeast(ADDRESSES))
say(" setting with ", Services.addressAsHexString(Magic.objectAsAddress(o)));
Statics.setSlotContents(rvmFieldOffset, o);
}
}
}
if (verbosity.isAtLeast(DETAILED)) {
for (final String entry : invalidEntrys) {
say("Static fields of type are invalid: ", entry);
}
}
if (profile) {
stopTime = System.currentTimeMillis();
System.out.println("PROF: \tinitializing jtoc " + (stopTime - startTime) + " ms");
}
}
Aggregations