Search in sources :

Example 96 with TypeReference

use of org.jikesrvm.classloader.TypeReference in project JikesRVM by JikesRVM.

the class CallingConvention method returnExpand.

/**
 * Expands the calling convention for a particular return instruction.
 *
 * @param ret the return instruction
 * @param ir the IR that contains the return instruction
 */
private static void returnExpand(Instruction ret, IR ir) {
    PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet().asIA32();
    if (MIR_Return.hasVal(ret)) {
        Operand symb1 = MIR_Return.getClearVal(ret);
        TypeReference type = symb1.getType();
        if (type.isFloatType() || type.isDoubleType()) {
            Register r = phys.getReturnFPR();
            RegisterOperand rOp = new RegisterOperand(r, type);
            if (SSE2_FULL) {
                if (type.isFloatType()) {
                    ret.insertBefore(MIR_Move.create(IA32_MOVSS, rOp, symb1));
                } else {
                    ret.insertBefore(MIR_Move.create(IA32_MOVSD, rOp, symb1));
                }
            } else {
                ret.insertBefore(MIR_Move.create(IA32_FMOV, rOp, symb1));
            }
            MIR_Return.setVal(ret, rOp.copyD2U());
        } else {
            Register r = phys.getFirstReturnGPR();
            RegisterOperand rOp = new RegisterOperand(r, type);
            ret.insertBefore(MIR_Move.create(IA32_MOV, rOp, symb1));
            MIR_Return.setVal(ret, rOp.copyD2U());
        }
    }
    if (MIR_Return.hasVal2(ret)) {
        if (VM.VerifyAssertions)
            VM._assert(VM.BuildFor32Addr);
        Operand symb2 = MIR_Return.getClearVal2(ret);
        TypeReference type = symb2.getType();
        Register r = phys.getSecondReturnGPR();
        RegisterOperand rOp = new RegisterOperand(r, type);
        ret.insertBefore(MIR_Move.create(IA32_MOV, rOp, symb2));
        MIR_Return.setVal2(ret, rOp.copyD2U());
    }
    // Clear the floating-point stack if dirty.
    if (!SSE2_FULL) {
        int nSave = 0;
        if (MIR_Return.hasVal(ret)) {
            Operand symb1 = MIR_Return.getClearVal(ret);
            TypeReference type = symb1.getType();
            if (type.isFloatType() || type.isDoubleType()) {
                nSave = 1;
            }
        }
        ret.insertBefore(MIR_UnaryNoRes.create(IA32_FCLEAR, IC(nSave)));
    }
    // Set the first 'Val' in the return instruction to hold an integer
    // constant which is the number of words to pop from the stack while
    // returning from this method.
    MIR_Return.setPopBytes(ret, IC(ir.incomingParameterBytes()));
}
Also used : RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Register(org.jikesrvm.compilers.opt.ir.Register) MethodOperand(org.jikesrvm.compilers.opt.ir.operand.MethodOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) IA32ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ia32.IA32ConditionOperand) StackLocationOperand(org.jikesrvm.compilers.opt.ir.operand.StackLocationOperand) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) MemoryOperand(org.jikesrvm.compilers.opt.ir.operand.MemoryOperand) GenericPhysicalRegisterSet(org.jikesrvm.compilers.opt.ir.GenericPhysicalRegisterSet) PhysicalRegisterSet(org.jikesrvm.compilers.opt.ir.ia32.PhysicalRegisterSet) TypeReference(org.jikesrvm.classloader.TypeReference)

Example 97 with TypeReference

use of org.jikesrvm.classloader.TypeReference in project JikesRVM by JikesRVM.

the class CallingConvention method expandParametersToCall.

/**
 * Explicitly copy parameters to a call into the appropriate physical
 * registers as defined by the calling convention.<p>
 *
 * Note: Assumes that ESP points to the word before the slot where the
 * first parameter should be stored.
 *
 * @param call the call instruction
 * @param ir the IR that contains the call
 * @return number of bytes necessary to hold the parameters
 */
private static int expandParametersToCall(Instruction call, IR ir) {
    int nGPRParams = 0;
    int nFPRParams = 0;
    PhysicalRegisterSet phys = (PhysicalRegisterSet) ir.regpool.getPhysicalRegisterSet();
    // count the number FPR parameters in a pre-pass
    int FPRRegisterParams = countFPRParams(call);
    FPRRegisterParams = Math.min(FPRRegisterParams, PhysicalRegisterSet.getNumberOfFPRParams());
    // offset, in bytes, from the SP, for the next parameter slot on the
    // stack
    int parameterBytes = 0;
    // Require ESP to be at bottom of frame before a call,
    call.insertBefore(MIR_UnaryNoRes.create(REQUIRE_ESP, IC(0)));
    // walk over each parameter
    // must count then before we start nulling them out!
    int numParams = MIR_Call.getNumberOfParams(call);
    int nParamsInRegisters = 0;
    for (int i = 0; i < numParams; i++) {
        Operand param = MIR_Call.getClearParam(call, i);
        MIR_Call.setParam(call, i, null);
        TypeReference paramType = param.getType();
        if (paramType.isFloatingPointType()) {
            nFPRParams++;
            int size;
            if (paramType.isFloatType()) {
                size = BYTES_IN_FLOAT;
                parameterBytes -= WORDSIZE;
            } else {
                size = BYTES_IN_DOUBLE;
                parameterBytes -= 2 * WORDSIZE;
            }
            if (nFPRParams > PhysicalRegisterSet.getNumberOfFPRParams()) {
                // pass the FP parameter on the stack
                Operand M = new StackLocationOperand(false, parameterBytes, size);
                if (SSE2_FULL) {
                    if (paramType.isFloatType()) {
                        call.insertBefore(MIR_Move.create(IA32_MOVSS, M, param));
                    } else {
                        call.insertBefore(MIR_Move.create(IA32_MOVSD, M, param));
                    }
                } else {
                    call.insertBefore(MIR_Move.create(IA32_FMOV, M, param));
                }
            } else {
                // Pass the parameter in a register.
                RegisterOperand real;
                if (SSE2_FULL) {
                    real = new RegisterOperand(phys.getFPRParam(nFPRParams - 1), paramType);
                    if (paramType.isFloatType()) {
                        call.insertBefore(MIR_Move.create(IA32_MOVSS, real, param));
                    } else {
                        call.insertBefore(MIR_Move.create(IA32_MOVSD, real, param));
                    }
                } else {
                    // Note that if k FPRs are passed in registers,
                    // the 1st goes in F(k-1),
                    // the 2nd goes in F(k-2), etc...
                    real = new RegisterOperand(phys.getFPRParam(FPRRegisterParams - nFPRParams), paramType);
                    call.insertBefore(MIR_Move.create(IA32_FMOV, real, param));
                }
                // Record that the call now has a use of the real register.
                MIR_Call.setParam(call, nParamsInRegisters++, real.copy());
            }
        } else {
            nGPRParams++;
            parameterBytes -= WORDSIZE;
            if (paramIsNativeLongOn64Bit(param)) {
                parameterBytes -= WORDSIZE;
            }
            if (nGPRParams > PhysicalRegisterSet.getNumberOfGPRParams()) {
                // parameter into the appropriate stack frame location.
                if (paramIsNativeLongOn64Bit(param)) {
                    call.insertBefore(MIR_UnaryNoRes.create(REQUIRE_ESP, IC(parameterBytes + WORDSIZE * 2)));
                    call.insertBefore(MIR_UnaryNoRes.create(IA32_PUSH, IC(0)));
                } else {
                    call.insertBefore(MIR_UnaryNoRes.create(REQUIRE_ESP, IC(parameterBytes + WORDSIZE)));
                }
                call.insertBefore(MIR_UnaryNoRes.create(IA32_PUSH, param));
            } else {
                // Pass the parameter in a register.
                Register phy = phys.getGPRParam(nGPRParams - 1);
                RegisterOperand real = new RegisterOperand(phy, paramType);
                call.insertBefore(MIR_Move.create(IA32_MOV, real, param));
                // Record that the call now has a use of the real register.
                MIR_Call.setParam(call, nParamsInRegisters++, real.copy());
            }
        }
    }
    return parameterBytes;
}
Also used : RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Register(org.jikesrvm.compilers.opt.ir.Register) MethodOperand(org.jikesrvm.compilers.opt.ir.operand.MethodOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) IA32ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ia32.IA32ConditionOperand) StackLocationOperand(org.jikesrvm.compilers.opt.ir.operand.StackLocationOperand) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) MemoryOperand(org.jikesrvm.compilers.opt.ir.operand.MemoryOperand) GenericPhysicalRegisterSet(org.jikesrvm.compilers.opt.ir.GenericPhysicalRegisterSet) PhysicalRegisterSet(org.jikesrvm.compilers.opt.ir.ia32.PhysicalRegisterSet) TypeReference(org.jikesrvm.classloader.TypeReference) StackLocationOperand(org.jikesrvm.compilers.opt.ir.operand.StackLocationOperand)

Example 98 with TypeReference

use of org.jikesrvm.classloader.TypeReference in project JikesRVM by JikesRVM.

the class IndexPropagationSystem method makeCell.

/**
 * Create an DF_LatticeCell corresponding to an HeapVariable
 * @param o the heap variable
 * @return a new lattice cell corresponding to this heap variable
 */
@Override
protected DF_LatticeCell makeCell(Object o) {
    if (!(o instanceof HeapVariable)) {
        throw new OptimizingCompilerException("IndexPropagation:makeCell");
    }
    DF_LatticeCell result = null;
    Object heapType = ((HeapVariable<?>) o).getHeapType();
    if (heapType instanceof TypeReference) {
        result = new ArrayCell((HeapVariable<?>) o);
    } else {
        result = new ObjectCell((HeapVariable<?>) o);
    }
    return result;
}
Also used : ArrayCell(org.jikesrvm.compilers.opt.ssa.IndexPropagation.ArrayCell) DF_LatticeCell(org.jikesrvm.compilers.opt.dfsolver.DF_LatticeCell) ObjectCell(org.jikesrvm.compilers.opt.ssa.IndexPropagation.ObjectCell) OptimizingCompilerException(org.jikesrvm.compilers.opt.OptimizingCompilerException) TypeReference(org.jikesrvm.classloader.TypeReference)

Example 99 with TypeReference

use of org.jikesrvm.classloader.TypeReference in project JikesRVM by JikesRVM.

the class BootImageWriter method copyClassToBootImage.

/**
 * Write an object instantiating a class to the boot image
 * @param scalarImageAddress address already allocated for object
 * @param jdkObject object to write
 * @param jdkType java.lang.Class of object
 * @param rvmScalarType RVM class loader version of type
 * @param allocOnly allocate the object only?
 * @param overwriteAddress
 * @param parentObject
 * @param untraced
 * @return
 * @throws IllegalAccessException
 */
private static Address copyClassToBootImage(Address scalarImageAddress, Object jdkObject, Class<?> jdkType, RVMClass rvmScalarType, boolean allocOnly, Address overwriteAddress, Object parentObject, boolean untraced) throws IllegalAccessException {
    if (verbosity.isAtLeast(DETAILED)) {
        if (depth == DEPTH_CUTOFF)
            say(SPACES.substring(0, depth + 1), "TOO DEEP: cutting off");
        else if (depth < DEPTH_CUTOFF) {
            String tab = SPACES.substring(0, depth + 1);
            if (depth == 0 && jtocCount >= 0)
                tab = tab + "jtoc #" + String.valueOf(jtocCount) + " ";
            int scalarSize = rvmScalarType.getInstanceSize();
            say(tab, "Copying object ", jdkType.getName(), "   size=", String.valueOf(scalarSize), (scalarSize >= LARGE_SCALAR_SIZE) ? " large object!!!" : "");
        }
    }
    // copy object fields from host jdk address space into image
    // recurse on values that are references
    RVMField[] rvmFields = rvmScalarType.getInstanceFields();
    for (int i = 0; i < rvmFields.length; ++i) {
        RVMField rvmField = rvmFields[i];
        TypeReference rvmFieldType = rvmField.getType();
        Address rvmFieldAddress = scalarImageAddress.plus(rvmField.getOffset());
        String rvmFieldName = rvmField.getName().toString();
        Field jdkFieldAcc = getJdkFieldAccessor(jdkType, i, INSTANCE_FIELD);
        boolean untracedField = rvmField.isUntraced() || untraced;
        if (jdkFieldAcc == null) {
            // Field not found via reflection
            if (!copyKnownInstanceField(jdkObject, rvmFieldName, rvmFieldType, rvmFieldAddress)) {
                // Field wasn't a known Classpath field so write null
                if (verbosity.isAtLeast(DETAILED))
                    traceContext.push(rvmFieldType.toString(), jdkType.getName(), rvmFieldName);
                if (verbosity.isAtLeast(DETAILED))
                    traceContext.traceFieldNotInHostJdk();
                if (verbosity.isAtLeast(DETAILED))
                    traceContext.pop();
                if (rvmFieldType.isPrimitiveType()) {
                    switch(rvmField.getType().getMemoryBytes()) {
                        case 1:
                            bootImage.setByte(rvmFieldAddress, 0);
                            break;
                        case 2:
                            bootImage.setHalfWord(rvmFieldAddress, 0);
                            break;
                        case 4:
                            bootImage.setFullWord(rvmFieldAddress, 0);
                            break;
                        case 8:
                            bootImage.setDoubleWord(rvmFieldAddress, 0L);
                            break;
                        default:
                            fail("unexpected field type: " + rvmFieldType);
                            break;
                    }
                } else {
                    bootImage.setNullAddressWord(rvmFieldAddress, !untracedField, !untracedField, false);
                }
            }
            continue;
        }
        if (rvmFieldType.isPrimitiveType()) {
            // field is logical or numeric type
            if (rvmFieldType.isBooleanType()) {
                bootImage.setByte(rvmFieldAddress, jdkFieldAcc.getBoolean(jdkObject) ? 1 : 0);
            } else if (rvmFieldType.isByteType()) {
                bootImage.setByte(rvmFieldAddress, jdkFieldAcc.getByte(jdkObject));
            } else if (rvmFieldType.isCharType()) {
                bootImage.setHalfWord(rvmFieldAddress, jdkFieldAcc.getChar(jdkObject));
            } else if (rvmFieldType.isShortType()) {
                bootImage.setHalfWord(rvmFieldAddress, jdkFieldAcc.getShort(jdkObject));
            } else if (rvmFieldType.isIntType()) {
                try {
                    bootImage.setFullWord(rvmFieldAddress, jdkFieldAcc.getInt(jdkObject));
                } catch (IllegalArgumentException ex) {
                    // TODO: Harmony - clean this up
                    if (jdkObject instanceof java.util.WeakHashMap && rvmFieldName.equals("loadFactor")) {
                        // the field load factor field in Sun/Classpath is a float but
                        // in Harmony it has been "optimized" to an int
                        bootImage.setFullWord(rvmFieldAddress, 7500);
                    } else if (jdkObject instanceof java.lang.ref.ReferenceQueue && rvmFieldName.equals("head")) {
                        // Conflicting types between Harmony and Sun
                        bootImage.setFullWord(rvmFieldAddress, 0);
                    } else {
                        System.out.println("type " + rvmScalarType + ", field " + rvmField);
                        throw ex;
                    }
                }
            } else if (rvmFieldType.isLongType()) {
                bootImage.setDoubleWord(rvmFieldAddress, jdkFieldAcc.getLong(jdkObject));
            } else if (rvmFieldType.isFloatType()) {
                float f = jdkFieldAcc.getFloat(jdkObject);
                bootImage.setFullWord(rvmFieldAddress, Float.floatToIntBits(f));
            } else if (rvmFieldType.isDoubleType()) {
                double d = jdkFieldAcc.getDouble(jdkObject);
                bootImage.setDoubleWord(rvmFieldAddress, 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(jdkObject);
                String msg = " instance field " + rvmField.toString();
                boolean warn = rvmFieldType.equals(TypeReference.Address);
                bootImage.setAddressWord(rvmFieldAddress, getWordValue(o, msg, warn), false, false);
            } else {
                fail("unexpected primitive field type: " + rvmFieldType);
            }
        } else {
            // field is reference type
            Object value = jdkFieldAcc.get(jdkObject);
            if (!allocOnly) {
                Class<?> jdkClass = jdkFieldAcc.getDeclaringClass();
                if (verbosity.isAtLeast(DETAILED)) {
                    String typeName = (value == null) ? "(unknown: value was null)" : value.getClass().getName();
                    traceContext.push(typeName, jdkClass.getName(), jdkFieldAcc.getName());
                }
                copyReferenceFieldToBootImage(rvmFieldAddress, value, jdkObject, !untracedField, !(untracedField || rvmField.isFinal()), rvmFieldName, rvmFieldType);
                if (verbosity.isAtLeast(DETAILED)) {
                    traceContext.pop();
                }
            }
        }
    }
    return scalarImageAddress;
}
Also used : Address(org.vmmagic.unboxed.Address) RVMField(org.jikesrvm.classloader.RVMField) Field(java.lang.reflect.Field) RVMField(org.jikesrvm.classloader.RVMField) TypeReference(org.jikesrvm.classloader.TypeReference)

Example 100 with TypeReference

use of org.jikesrvm.classloader.TypeReference 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

TypeReference (org.jikesrvm.classloader.TypeReference)164 RegisterOperand (org.jikesrvm.compilers.opt.ir.operand.RegisterOperand)58 Operand (org.jikesrvm.compilers.opt.ir.operand.Operand)43 Instruction (org.jikesrvm.compilers.opt.ir.Instruction)38 MethodOperand (org.jikesrvm.compilers.opt.ir.operand.MethodOperand)30 BranchProfileOperand (org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand)28 TrueGuardOperand (org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand)27 IntConstantOperand (org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand)25 ConditionOperand (org.jikesrvm.compilers.opt.ir.operand.ConditionOperand)24 RVMClass (org.jikesrvm.classloader.RVMClass)23 RVMField (org.jikesrvm.classloader.RVMField)21 Register (org.jikesrvm.compilers.opt.ir.Register)21 LocationOperand (org.jikesrvm.compilers.opt.ir.operand.LocationOperand)21 NullConstantOperand (org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand)21 Address (org.vmmagic.unboxed.Address)21 RVMType (org.jikesrvm.classloader.RVMType)18 BasicBlock (org.jikesrvm.compilers.opt.ir.BasicBlock)18 AddressConstantOperand (org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand)18 TrapCodeOperand (org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand)18 RVMMethod (org.jikesrvm.classloader.RVMMethod)17