Search in sources :

Example 1 with BootRecord

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();
}
Also used : BootRecord(org.jikesrvm.runtime.BootRecord) Interruptible(org.vmmagic.pragma.Interruptible)

Example 2 with BootRecord

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");
}
Also used : Address(org.vmmagic.unboxed.Address) HashMap(java.util.HashMap) RVMType(org.jikesrvm.classloader.RVMType) CodeArray(org.jikesrvm.compilers.common.CodeArray) PrintStream(java.io.PrintStream) Hashtable(java.util.Hashtable) IOException(java.io.IOException) IOException(java.io.IOException) Offset(org.vmmagic.unboxed.Offset) BootRecord(org.jikesrvm.runtime.BootRecord) RVMClass(org.jikesrvm.classloader.RVMClass)

Example 3 with BootRecord

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");
    }
}
Also used : ThreadFactory(java.util.concurrent.ThreadFactory) Address(org.vmmagic.unboxed.Address) RVMType(org.jikesrvm.classloader.RVMType) RVMField(org.jikesrvm.classloader.RVMField) Field(java.lang.reflect.Field) FunctionTable(org.jikesrvm.jni.FunctionTable) RVMField(org.jikesrvm.classloader.RVMField) TypeReference(org.jikesrvm.classloader.TypeReference) HashSet(java.util.HashSet) RVMClass(org.jikesrvm.classloader.RVMClass) Offset(org.vmmagic.unboxed.Offset) RVMThread(org.jikesrvm.scheduler.RVMThread) RVMArray(org.jikesrvm.classloader.RVMArray) BootRecord(org.jikesrvm.runtime.BootRecord) ExecutorService(java.util.concurrent.ExecutorService)

Aggregations

BootRecord (org.jikesrvm.runtime.BootRecord)3 RVMClass (org.jikesrvm.classloader.RVMClass)2 RVMType (org.jikesrvm.classloader.RVMType)2 Address (org.vmmagic.unboxed.Address)2 Offset (org.vmmagic.unboxed.Offset)2 IOException (java.io.IOException)1 PrintStream (java.io.PrintStream)1 Field (java.lang.reflect.Field)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 Hashtable (java.util.Hashtable)1 ExecutorService (java.util.concurrent.ExecutorService)1 ThreadFactory (java.util.concurrent.ThreadFactory)1 RVMArray (org.jikesrvm.classloader.RVMArray)1 RVMField (org.jikesrvm.classloader.RVMField)1 TypeReference (org.jikesrvm.classloader.TypeReference)1 CodeArray (org.jikesrvm.compilers.common.CodeArray)1 FunctionTable (org.jikesrvm.jni.FunctionTable)1 RVMThread (org.jikesrvm.scheduler.RVMThread)1 Interruptible (org.vmmagic.pragma.Interruptible)1