Search in sources :

Example 41 with RVMClass

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

Example 42 with RVMClass

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

the class BC2IR method getConstantOperand.

/**
 * Fetch the value of the next operand, a constant, from the bytecode
 * stream.
 * @param index constant pool index
 * @return the value of a literal constant from the bytecode stream,
 * encoding as a constant IR operand
 */
public Operand getConstantOperand(int index) {
    byte desc = bcodes.getConstantType(index);
    RVMClass declaringClass = bcodes.getDeclaringClass();
    switch(desc) {
        case CP_INT:
            return ClassLoaderProxy.getIntFromConstantPool(declaringClass, index);
        case CP_FLOAT:
            return ClassLoaderProxy.getFloatFromConstantPool(declaringClass, index);
        case CP_STRING:
            return ClassLoaderProxy.getStringFromConstantPool(declaringClass, index);
        case CP_LONG:
            return ClassLoaderProxy.getLongFromConstantPool(declaringClass, index);
        case CP_DOUBLE:
            return ClassLoaderProxy.getDoubleFromConstantPool(declaringClass, index);
        case CP_CLASS:
            return ClassLoaderProxy.getClassFromConstantPool(declaringClass, index);
        default:
            if (VM.VerifyAssertions) {
                String msg = "invalid literal type: 0x" + Integer.toHexString(desc);
                opt_assert(VM.NOT_REACHED, msg);
            }
            return null;
    }
}
Also used : RVMClass(org.jikesrvm.classloader.RVMClass)

Example 43 with RVMClass

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

the class BaselineCompilerImpl method emit_invokeinterface.

@Override
protected void emit_invokeinterface(MethodReference methodRef) {
    // +1 for "this" parameter
    int count = methodRef.getParameterWords() + 1;
    RVMMethod resolvedMethod = null;
    resolvedMethod = methodRef.peekInterfaceMethod();
    // do so inline.
    if (VM.BuildForIMTInterfaceInvocation) {
        if (methodRef.isMiranda()) {
        // TODO: It's not entirely clear that we can just assume that
        // the class actually implements the interface.
        // However, we don't know what interface we need to be checking
        // so there doesn't appear to be much else we can do here.
        } else {
            if (resolvedMethod == null) {
                // Can't successfully resolve it at compile time.
                // Call uncommon case typechecking routine to do the right thing when this code actually executes.
                asm.emitLAddrToc(T0, Entrypoints.unresolvedInvokeinterfaceImplementsTestMethod.getOffset());
                asm.emitMTCTR(T0);
                // id of method reference we are trying to call
                asm.emitLVAL(T0, methodRef.getId());
                // the "this" object
                peekAddr(T1, count - 1);
                // throw exception, if link error
                asm.emitBCCTRL();
            } else {
                RVMClass interfaceClass = resolvedMethod.getDeclaringClass();
                int interfaceIndex = interfaceClass.getDoesImplementIndex();
                int interfaceMask = interfaceClass.getDoesImplementBitMask();
                // the "this" object
                peekAddr(T0, count - 1);
                // TIB of "this" object
                asm.baselineEmitLoadTIB(T0, T0);
                // implements bit vector
                asm.emitLAddr(T0, TIB_DOES_IMPLEMENT_INDEX << LOG_BYTES_IN_ADDRESS, T0);
                if (DynamicTypeCheck.MIN_DOES_IMPLEMENT_SIZE <= interfaceIndex) {
                    // must do arraybounds check of implements bit vector
                    // T1 gets array length
                    asm.emitLIntOffset(T1, T0, ObjectModel.getArrayLengthOffset());
                    asm.emitLVAL(T2, interfaceIndex);
                    asm.emitCMPL(T2, T1);
                    // if in bounds, jump around trap.  TODO: would like to encode "y" bit that this branch is expected to be takem.
                    ForwardReference fr1 = asm.emitForwardBC(LT);
                    // encoding of TRAP_ALWAYS MUST_IMPLEMENT_INTERFACE
                    asm.emitTWI(31, GPR.R12, MUST_IMPLEMENT_TRAP);
                    fr1.resolve(asm);
                }
                // Test the appropriate bit and if set, branch around another trap imm
                asm.emitLInt(T1, interfaceIndex << LOG_BYTES_IN_INT, T0);
                if ((interfaceMask & 0xffff) == interfaceMask) {
                    asm.emitANDI(S0, T1, interfaceMask);
                } else {
                    if (VM.VerifyAssertions)
                        VM._assert((interfaceMask & 0xffff0000) == interfaceMask);
                    asm.emitANDIS(S0, T1, interfaceMask);
                }
                // TODO: encode "y" bit that branch is likely taken.
                ForwardReference fr2 = asm.emitForwardBC(NE);
                // encoding of TRAP_ALWAYS MUST_IMPLEMENT_INTERFACE
                asm.emitTWI(31, GPR.R12, MUST_IMPLEMENT_TRAP);
                fr2.resolve(asm);
            }
        }
    }
    // (2) Emit interface invocation sequence.
    if (VM.BuildForIMTInterfaceInvocation) {
        InterfaceMethodSignature sig = InterfaceMethodSignature.findOrCreate(methodRef);
        // T0 is "this"
        genMoveParametersToRegisters(true, methodRef);
        asm.baselineEmitLoadTIB(S0, T0);
        // Load the IMT base into S0
        asm.emitLAddr(S0, TIB_INTERFACE_DISPATCH_TABLE_INDEX << LOG_BYTES_IN_ADDRESS, S0);
        // the method address
        asm.emitLAddrOffset(S0, S0, sig.getIMTOffset());
        asm.emitMTCTR(S0);
        // pass "hidden" parameter in S1 scratch  register
        asm.emitLVAL(S1, sig.getId());
        asm.emitBCCTRL();
    } else {
        int itableIndex = -1;
        if (VM.BuildForITableInterfaceInvocation && resolvedMethod != null) {
            // get the index of the method in the Itable
            itableIndex = InterfaceInvocation.getITableIndex(resolvedMethod.getDeclaringClass(), methodRef.getName(), methodRef.getDescriptor());
        }
        if (itableIndex == -1) {
            // itable index is not known at compile-time.
            // call "invokeInterface" to resolve object + method id into method address
            int methodRefId = methodRef.getId();
            asm.emitLAddrToc(T0, Entrypoints.invokeInterfaceMethod.getOffset());
            asm.emitMTCTR(T0);
            // object
            peekAddr(T0, count - 1);
            // method id
            asm.emitLVAL(T1, methodRefId);
            // T0 := resolved method address
            asm.emitBCCTRL();
            asm.emitMTCTR(T0);
            genMoveParametersToRegisters(true, methodRef);
            asm.emitBCCTRL();
        } else {
            // itable index is known at compile-time.
            // call "findITable" to resolve object + interface id into
            // itable address
            asm.emitLAddrToc(T0, Entrypoints.findItableMethod.getOffset());
            asm.emitMTCTR(T0);
            // object
            peekAddr(T0, count - 1);
            asm.baselineEmitLoadTIB(T0, T0);
            // interface id
            asm.emitLVAL(T1, resolvedMethod.getDeclaringClass().getInterfaceId());
            // T0 := itable reference
            asm.emitBCCTRL();
            // T0 := the method to call
            asm.emitLAddr(T0, itableIndex << LOG_BYTES_IN_ADDRESS, T0);
            asm.emitMTCTR(T0);
            // T0 is "this"
            genMoveParametersToRegisters(true, methodRef);
            asm.emitBCCTRL();
        }
    }
    genPopParametersAndPushReturnValue(true, methodRef);
}
Also used : ForwardReference(org.jikesrvm.compilers.common.assembler.ForwardReference) InterfaceMethodSignature(org.jikesrvm.classloader.InterfaceMethodSignature) RVMMethod(org.jikesrvm.classloader.RVMMethod) RVMClass(org.jikesrvm.classloader.RVMClass)

Example 44 with RVMClass

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

the class ClassLoaderProxy method includesType.

/**
 * Return Constants.YES if the parent type is defintely a supertype
 *    of the child type.
 * <p> Return Constants.NO if the parent type is definitely not
 * a supertype of the child type.
 * <p> Return Constants.MAYBE if the question cannot be currently answered
 *    (for example if one/both of the classes is not resolved)
 *
 * <p> Takes into account the special 'null-type', which corresponds to a {@code null}
 * constant.
 *
 * @param parentType parent type
 * @param childType child type
 * @return Constants.YES, Constants.NO, or Constants.MAYBE
 */
public static byte includesType(TypeReference parentType, TypeReference childType) {
    // NOTE: The ordering of these tests is critical!
    if (childType == TypeReference.NULL_TYPE) {
        // Sanity assertion that a null isn't being assigned to an unboxed type
        if (VM.VerifyAssertions && parentType.isReferenceType())
            VM._assert(!parentType.isWordLikeType());
        return parentType.isReferenceType() ? YES : NO;
    } else if (parentType == TypeReference.NULL_TYPE) {
        return NO;
    } else if (parentType == childType) {
        return YES;
    } else if (parentType == TypeReference.Word && childType.isWordLikeType()) {
        return YES;
    } else if (parentType.isPrimitiveType() || childType.isPrimitiveType()) {
        return NO;
    } else if (parentType == TypeReference.JavaLangObject) {
        return YES;
    } else {
        // Unboxed types are handled in the word and primitive type case
        if (VM.VerifyAssertions) {
            VM._assert(!parentType.isWordLikeType() && !childType.isWordLikeType());
        }
        // (which is allowed/required to load classes to answer the question).
        try {
            if (parentType.isArrayType()) {
                if (childType == TypeReference.JavaLangObject) {
                    // arrays are subtypes of Object.
                    return MAYBE;
                } else if (!childType.isArrayType()) {
                    return NO;
                } else {
                    TypeReference parentET = parentType.getInnermostElementType();
                    if (parentET == TypeReference.JavaLangObject) {
                        int LHSDimension = parentType.getDimensionality();
                        int RHSDimension = childType.getDimensionality();
                        if ((RHSDimension > LHSDimension) || (RHSDimension == LHSDimension && childType.getInnermostElementType().isClassType())) {
                            return YES;
                        } else {
                            return NO;
                        }
                    } else {
                        // If the dimensionalities are not equal then the answer is NO
                        if (parentType.getDimensionality() == childType.getDimensionality()) {
                            return includesType(parentET, childType.getInnermostElementType());
                        } else {
                            return NO;
                        }
                    }
                }
            } else {
                // parentType.isClassType()
                if (!childType.isClassType()) {
                    // parentType is known to not be java.lang.Object.
                    return NO;
                } else {
                    RVMClass childClass = (RVMClass) childType.peekType();
                    RVMClass parentClass = (RVMClass) parentType.peekType();
                    if (childClass != null && parentClass != null) {
                        if (parentClass.isResolved() && childClass.isResolved() || (VM.writingBootImage && parentClass.isInBootImage() && childClass.isInBootImage())) {
                            if (parentClass.isInterface()) {
                                if (RuntimeEntrypoints.isAssignableWith(parentClass, childClass)) {
                                    return YES;
                                } else {
                                    // possible that a subclass will implement parent.
                                    return childClass.isFinal() ? NO : MAYBE;
                                }
                            } else if (childClass.isInterface()) {
                                // parent is a proper class, child is an interface
                                return MAYBE;
                            } else {
                                // parent & child are both proper classes.
                                if (RuntimeEntrypoints.isAssignableWith(parentClass, childClass)) {
                                    return YES;
                                }
                                // unrelated and we can return NO.
                                if (childClass.isFinal()) {
                                    return NO;
                                } else {
                                    if (RuntimeEntrypoints.isAssignableWith(childClass, parentClass)) {
                                        return MAYBE;
                                    } else {
                                        return NO;
                                    }
                                }
                            }
                        }
                    }
                    return MAYBE;
                }
            }
        } catch (Throwable e) {
            e.printStackTrace();
            OptimizingCompilerException.UNREACHABLE();
            return MAYBE;
        }
    }
}
Also used : TypeReference(org.jikesrvm.classloader.TypeReference) RVMClass(org.jikesrvm.classloader.RVMClass)

Example 45 with RVMClass

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

the class BarrierSize method main.

public static void main(String[] args) throws Exception {
    RVMClass barrierSize = JikesRVMSupport.getTypeForClass(BarrierSize.class).asClass();
    barrierSize.prepareForFirstUse();
    thisClass = Class.forName("BarrierSize");
    emptySize = methodInstructionCount("emptyInstanceMethod", (Class[]) null);
    Constraints constraints = Selected.Constraints.get();
    printHeader("reference barriers");
    int oFieldWriteSize = methodInstructionCount("writeToObjectField", Object.class);
    int oFieldReadSize = methodInstructionCount("readFromObjectField", (Class[]) null);
    printBarrierRequirement("object reference write", constraints.needsObjectReferenceWriteBarrier());
    printSizeForMethod("object reference write", oFieldWriteSize);
    printBarrierRequirement("object reference read", constraints.needsObjectReferenceReadBarrier());
    printSizeForMethod("object reference read", oFieldReadSize);
    System.out.println();
    printHeader("primitive barriers");
    int booleanWriteSize = methodInstructionCount("writeToBooleanField", boolean.class);
    printBarrierRequirement("boolean write", constraints.needsBooleanWriteBarrier());
    printSizeForMethod("boolean write", booleanWriteSize);
    int booleanReadSize = methodInstructionCount("readFromBooleanField", (Class[]) null);
    printBarrierRequirement("boolean read", constraints.needsBooleanWriteBarrier());
    printSizeForMethod("boolean read", booleanReadSize);
    int byteWriteSize = methodInstructionCount("writeToByteField", byte.class);
    printBarrierRequirement("byte write", constraints.needsByteWriteBarrier());
    printSizeForMethod("byte write", byteWriteSize);
    int byteReadSize = methodInstructionCount("readFromByteField", (Class[]) null);
    printBarrierRequirement("byte read", constraints.needsByteWriteBarrier());
    printSizeForMethod("byte read", byteReadSize);
    int charWriteSize = methodInstructionCount("writeToCharField", char.class);
    printBarrierRequirement("char write", constraints.needsCharWriteBarrier());
    printSizeForMethod("char write", charWriteSize);
    int charReadSize = methodInstructionCount("readFromCharField", (Class[]) null);
    printBarrierRequirement("char read", constraints.needsCharWriteBarrier());
    printSizeForMethod("char read", charReadSize);
    int shortWriteSize = methodInstructionCount("writeToShortField", short.class);
    printBarrierRequirement("short write", constraints.needsShortWriteBarrier());
    printSizeForMethod("short write", shortWriteSize);
    int shortReadSize = methodInstructionCount("readFromShortField", (Class[]) null);
    printBarrierRequirement("short read", constraints.needsShortWriteBarrier());
    printSizeForMethod("short read", shortReadSize);
    int intWriteSize = methodInstructionCount("writeToIntField", int.class);
    printBarrierRequirement("int write", constraints.needsIntWriteBarrier());
    printSizeForMethod("int write", intWriteSize);
    int intReadSize = methodInstructionCount("readFromIntField", (Class[]) null);
    printBarrierRequirement("int read", constraints.needsIntWriteBarrier());
    printSizeForMethod("int read", intReadSize);
    int floatWriteSize = methodInstructionCount("writeToFloatField", float.class);
    printBarrierRequirement("float write", constraints.needsFloatWriteBarrier());
    printSizeForMethod("float write", floatWriteSize);
    int floatReadSize = methodInstructionCount("readFromFloatField", (Class[]) null);
    printBarrierRequirement("float read", constraints.needsFloatWriteBarrier());
    printSizeForMethod("float read", floatReadSize);
    int doubleWriteSize = methodInstructionCount("writeToDoubleField", double.class);
    printBarrierRequirement("double write", constraints.needsDoubleWriteBarrier());
    printSizeForMethod("double write", doubleWriteSize);
    int doubleReadSize = methodInstructionCount("readFromDoubleField", (Class[]) null);
    printBarrierRequirement("double read", constraints.needsDoubleWriteBarrier());
    printSizeForMethod("double read", doubleReadSize);
    int longWriteSize = methodInstructionCount("writeToLongField", long.class);
    printBarrierRequirement("long write", constraints.needsLongWriteBarrier());
    printSizeForMethod("long write", longWriteSize);
    int longReadSize = methodInstructionCount("readFromLongField", (Class[]) null);
    printBarrierRequirement("long read", constraints.needsLongWriteBarrier());
    printSizeForMethod("long read", longReadSize);
    System.out.println();
    printHeader("primitive array store barriers");
    int booleanArrayWriteSize = methodInstructionCount("writeToBooleanArray", boolean.class);
    printBarrierRequirement("boolean array write", constraints.needsBooleanWriteBarrier());
    printSizeForMethod("boolean array write", booleanArrayWriteSize);
    int booleanArrayReadSize = methodInstructionCount("readFromBooleanArray", (Class[]) null);
    printBarrierRequirement("boolean array read", constraints.needsBooleanWriteBarrier());
    printSizeForMethod("boolean array read", booleanArrayReadSize);
    int byteArrayWriteSize = methodInstructionCount("writeToByteArray", byte.class);
    printBarrierRequirement("byte array write", constraints.needsByteWriteBarrier());
    printSizeForMethod("byte array write", byteArrayWriteSize);
    int byteArrayReadSize = methodInstructionCount("readFromByteArray", (Class[]) null);
    printBarrierRequirement("byte array read", constraints.needsByteWriteBarrier());
    printSizeForMethod("byte array read", byteArrayReadSize);
    int charArrayWriteSize = methodInstructionCount("writeToCharArray", char.class);
    printBarrierRequirement("char array write", constraints.needsCharWriteBarrier());
    printSizeForMethod("char array write", charArrayWriteSize);
    int charArrayReadSize = methodInstructionCount("readFromCharArray", (Class[]) null);
    printBarrierRequirement("char array read", constraints.needsCharWriteBarrier());
    printSizeForMethod("char array read", charArrayReadSize);
    int shortArrayWriteSize = methodInstructionCount("writeToShortArray", short.class);
    printBarrierRequirement("short array write", constraints.needsShortWriteBarrier());
    printSizeForMethod("short array write", shortArrayWriteSize);
    int shortArrayReadSize = methodInstructionCount("readFromShortArray", (Class[]) null);
    printBarrierRequirement("short array read", constraints.needsShortWriteBarrier());
    printSizeForMethod("short array read", shortArrayReadSize);
    int intArrayWriteSize = methodInstructionCount("writeToIntArray", int.class);
    printBarrierRequirement("int array write", constraints.needsIntWriteBarrier());
    printSizeForMethod("int array write", intArrayWriteSize);
    int intArrayReadSize = methodInstructionCount("readFromIntArray", (Class[]) null);
    printBarrierRequirement("int array read", constraints.needsIntWriteBarrier());
    printSizeForMethod("int array read", intArrayReadSize);
    int floatArrayWriteSize = methodInstructionCount("writeToFloatArray", float.class);
    printBarrierRequirement("float array write", constraints.needsFloatWriteBarrier());
    printSizeForMethod("float array write", floatArrayWriteSize);
    int floatArrayReadSize = methodInstructionCount("readFromFloatArray", (Class[]) null);
    printBarrierRequirement("float array read", constraints.needsFloatWriteBarrier());
    printSizeForMethod("float array read", floatArrayReadSize);
    int doubleArrayWriteSize = methodInstructionCount("writeToDoubleArray", double.class);
    printBarrierRequirement("double array write", constraints.needsDoubleWriteBarrier());
    printSizeForMethod("double array write", doubleArrayWriteSize);
    int doubleArrayReadSize = methodInstructionCount("readFromDoubleArray", (Class[]) null);
    printBarrierRequirement("double array read", constraints.needsDoubleWriteBarrier());
    printSizeForMethod("double array read", doubleArrayReadSize);
    int longArrayWriteSize = methodInstructionCount("writeToLongArray", long.class);
    printBarrierRequirement("long array write", constraints.needsLongWriteBarrier());
    printSizeForMethod("long array write", longArrayWriteSize);
    int longArrayReadSize = methodInstructionCount("readFromLongArray", (Class[]) null);
    printBarrierRequirement("long array read", constraints.needsLongWriteBarrier());
    printSizeForMethod("long array read", longArrayReadSize);
    System.out.println();
    printHeader("unboxed barriers");
    int addressWriteSize = methodInstructionCount("writeToAddressField", Address.class);
    printBarrierRequirement("address write", constraints.needsAddressWriteBarrier());
    printSizeForMethod("address write", addressWriteSize);
    int addressReadSize = methodInstructionCount("readFromAddressField", (Class[]) null);
    printBarrierRequirement("address read", constraints.needsAddressWriteBarrier());
    printSizeForMethod("address read", addressReadSize);
    int wordWriteSize = methodInstructionCount("writeToWordField", Word.class);
    printBarrierRequirement("word write", constraints.needsWordWriteBarrier());
    printSizeForMethod("word write", wordWriteSize);
    int wordReadSize = methodInstructionCount("readFromWordField", (Class[]) null);
    printBarrierRequirement("word read", constraints.needsWordWriteBarrier());
    printSizeForMethod("word read", wordReadSize);
    int extentWriteSize = methodInstructionCount("writeToExtentField", Extent.class);
    printBarrierRequirement("extent write", constraints.needsExtentWriteBarrier());
    printSizeForMethod("extent write", extentWriteSize);
    int extentReadSize = methodInstructionCount("readFromExtentField", (Class[]) null);
    printBarrierRequirement("extent read", constraints.needsExtentWriteBarrier());
    printSizeForMethod("extent read", extentReadSize);
    int offsetWriteSize = methodInstructionCount("writeToOffsetField", Offset.class);
    printBarrierRequirement("offset write", constraints.needsOffsetWriteBarrier());
    printSizeForMethod("offset write", offsetWriteSize);
    int offsetReadSize = methodInstructionCount("readFromOffsetField", (Class[]) null);
    printBarrierRequirement("offset read", constraints.needsOffsetWriteBarrier());
    printSizeForMethod("offset read", offsetReadSize);
}
Also used : Constraints(org.jikesrvm.mm.mminterface.Selected.Constraints) RVMClass(org.jikesrvm.classloader.RVMClass) RVMClass(org.jikesrvm.classloader.RVMClass)

Aggregations

RVMClass (org.jikesrvm.classloader.RVMClass)69 RVMMethod (org.jikesrvm.classloader.RVMMethod)28 TypeReference (org.jikesrvm.classloader.TypeReference)22 RVMType (org.jikesrvm.classloader.RVMType)20 Atom (org.jikesrvm.classloader.Atom)14 RVMField (org.jikesrvm.classloader.RVMField)11 RVMArray (org.jikesrvm.classloader.RVMArray)8 Instruction (org.jikesrvm.compilers.opt.ir.Instruction)8 IntConstantOperand (org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand)8 MethodOperand (org.jikesrvm.compilers.opt.ir.operand.MethodOperand)8 Operand (org.jikesrvm.compilers.opt.ir.operand.Operand)8 RegisterOperand (org.jikesrvm.compilers.opt.ir.operand.RegisterOperand)8 BranchProfileOperand (org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand)7 ConditionOperand (org.jikesrvm.compilers.opt.ir.operand.ConditionOperand)7 LocationOperand (org.jikesrvm.compilers.opt.ir.operand.LocationOperand)7 Address (org.vmmagic.unboxed.Address)7 NormalMethod (org.jikesrvm.classloader.NormalMethod)6 CompiledMethod (org.jikesrvm.compilers.common.CompiledMethod)6 TrapCodeOperand (org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand)6 BasicBlock (org.jikesrvm.compilers.opt.ir.BasicBlock)5