Search in sources :

Example 16 with RVMArray

use of org.jikesrvm.classloader.RVMArray 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 17 with RVMArray

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

the class BaselineCompilerImpl method generateInlineCode.

// *************************************************************************
// MAGIC
// *************************************************************************
/*
   *  Generate inline machine instructions for special methods that cannot be
   *  implemented in java bytecodes. These instructions are generated whenever
   *  we encounter an "invokestatic" bytecode that calls a method with a
   *  signature of the form "static native Magic.xxx(...)".
   *
   * NOTE: when adding a new "methodName" to "generate()", be sure to also
   * consider how it affects the values on the stack and update
   * "checkForActualCall()" accordingly.
   * If no call is actually generated, the map will reflect the status of the
   * locals (including parameters) at the time of the call but nothing on the
   * operand stack for the call site will be mapped.
   */
/**
 * Generate inline code sequence for specified method.
 * @param methodToBeCalled method whose name indicates semantics of code to be generated
 * @return true if there was magic defined for the method
 */
private boolean generateInlineCode(MethodReference methodToBeCalled) {
    Atom methodName = methodToBeCalled.getName();
    if (methodToBeCalled.isSysCall()) {
        TypeReference[] args = methodToBeCalled.getParameterTypes();
        // (1) Set up arguments according to OS calling convention, excluding the first
        // which is not an argument to the native function but the address of the function to call
        int paramWords = methodToBeCalled.getParameterWords();
        int gp = FIRST_OS_PARAMETER_GPR.value();
        int fp = FIRST_OS_PARAMETER_FPR.value();
        int stackIndex = paramWords - 1;
        int paramBytes = ((VM.BuildFor64Addr ? args.length : paramWords) - 1) * BYTES_IN_STACKSLOT;
        int callee_param_index = -BYTES_IN_STACKSLOT - paramBytes;
        for (int i = 1; i < args.length; i++) {
            TypeReference t = args[i];
            if (t.isLongType()) {
                stackIndex -= 2;
                callee_param_index += BYTES_IN_LONG;
                if (VM.BuildFor64Addr) {
                    if (gp <= LAST_OS_PARAMETER_GPR.value()) {
                        peekLong(GPR.lookup(gp), GPR.lookup(gp), stackIndex);
                        gp++;
                    } else {
                        peekLong(S0, S0, stackIndex);
                        asm.emitSTD(S0, callee_param_index - BYTES_IN_LONG, FP);
                    }
                } else {
                    if (VM.BuildForLinux) {
                        /* NOTE: following adjustment is not stated in SVR4 ABI, but
               * was implemented in GCC.
               */
                        // if gpr is even, gpr += 1
                        gp += (gp + 1) & 0x01;
                    }
                    if (gp <= LAST_OS_PARAMETER_GPR.value()) {
                        peekInt(GPR.lookup(gp++), stackIndex);
                    }
                    // lo register := lo mem (== hi order word)
                    if (gp <= LAST_OS_PARAMETER_GPR.value()) {
                        // hi register := hi mem (== lo order word)
                        peekInt(GPR.lookup(gp++), stackIndex + 1);
                    } else {
                        peekLong(S0, S1, stackIndex);
                        asm.emitSTW(S0, callee_param_index - BYTES_IN_LONG, FP);
                        asm.emitSTW(S1, callee_param_index - BYTES_IN_INT, FP);
                    }
                }
            } else if (t.isFloatType()) {
                stackIndex -= 1;
                callee_param_index += BYTES_IN_STACKSLOT;
                if (fp <= LAST_OS_PARAMETER_FPR.value()) {
                    peekFloat(FPR.lookup(fp++), stackIndex);
                } else {
                    peekFloat(FIRST_SCRATCH_FPR, stackIndex);
                    asm.emitSTFS(FIRST_SCRATCH_FPR, callee_param_index - BYTES_IN_FLOAT, FP);
                }
            } else if (t.isDoubleType()) {
                stackIndex -= 2;
                callee_param_index += BYTES_IN_DOUBLE;
                if (fp <= LAST_OS_PARAMETER_FPR.value()) {
                    peekDouble(FPR.lookup(fp++), stackIndex);
                } else {
                    peekDouble(FIRST_SCRATCH_FPR, stackIndex);
                    asm.emitSTFD(FIRST_SCRATCH_FPR, callee_param_index - BYTES_IN_DOUBLE, FP);
                }
            } else if (t.isIntLikeType()) {
                stackIndex -= 1;
                callee_param_index += BYTES_IN_STACKSLOT;
                if (gp <= LAST_OS_PARAMETER_GPR.value()) {
                    peekInt(GPR.lookup(gp++), stackIndex);
                } else {
                    peekInt(S0, stackIndex);
                    // save int zero-extended to be sure
                    asm.emitSTAddr(S0, callee_param_index - BYTES_IN_ADDRESS, FP);
                }
            } else {
                // t is object
                stackIndex -= 1;
                callee_param_index += BYTES_IN_STACKSLOT;
                if (gp <= LAST_OS_PARAMETER_GPR.value()) {
                    peekAddr(GPR.lookup(gp++), stackIndex);
                } else {
                    peekAddr(S0, stackIndex);
                    asm.emitSTAddr(S0, callee_param_index - BYTES_IN_ADDRESS, FP);
                }
            }
        }
        if (VM.VerifyAssertions) {
            VM._assert(stackIndex == 0);
        }
        // (2) Call it
        // Load addres of function into S0
        peekAddr(S0, paramWords - 1);
        // make the call
        generateSysCall(paramBytes);
        // (3) Pop Java expression stack
        discardSlots(paramWords);
        // (4) Push return value (if any)
        TypeReference rtype = methodToBeCalled.getReturnType();
        if (rtype.isIntLikeType()) {
            pushInt(T0);
        } else if (rtype.isWordLikeType() || rtype.isReferenceType()) {
            pushAddr(T0);
        } else if (rtype.isDoubleType()) {
            pushDouble(FIRST_OS_PARAMETER_FPR);
        } else if (rtype.isFloatType()) {
            pushFloat(FIRST_OS_PARAMETER_FPR);
        } else if (rtype.isLongType()) {
            pushLong(T0, VM.BuildFor64Addr ? T0 : T1);
        }
        return true;
    }
    if (methodToBeCalled.getType() == TypeReference.Address) {
        // Address.xyz magic
        TypeReference[] types = methodToBeCalled.getParameterTypes();
        if (methodName == MagicNames.loadAddress || methodName == MagicNames.loadObjectReference || methodName == MagicNames.loadWord) {
            if (types.length == 0) {
                // pop base
                popAddr(T0);
                // *(base)
                asm.emitLAddr(T0, 0, T0);
                // push *(base)
                pushAddr(T0);
            } else {
                // pop offset
                popOffset(T1);
                // pop base
                popAddr(T0);
                // *(base+offset)
                asm.emitLAddrX(T0, T1, T0);
                // push *(base+offset)
                pushAddr(T0);
            }
            return true;
        }
        if (methodName == MagicNames.loadChar) {
            if (types.length == 0) {
                // pop base
                popAddr(T0);
                // load with zero extension.
                asm.emitLHZ(T0, 0, T0);
                // push *(base)
                pushInt(T0);
            } else {
                // pop offset
                popOffset(T1);
                // pop base
                popAddr(T0);
                // load with zero extension.
                asm.emitLHZX(T0, T1, T0);
                // push *(base+offset)
                pushInt(T0);
            }
            return true;
        }
        if (methodName == MagicNames.loadShort) {
            if (types.length == 0) {
                // pop base
                popAddr(T0);
                // load with sign extension.
                asm.emitLHA(T0, 0, T0);
                // push *(base)
                pushInt(T0);
            } else {
                // pop offset
                popOffset(T1);
                // pop base
                popAddr(T0);
                // load with sign extension.
                asm.emitLHAX(T0, T1, T0);
                // push *(base+offset)
                pushInt(T0);
            }
            return true;
        }
        if (methodName == MagicNames.loadByte) {
            if (types.length == 0) {
                // pop base
                popAddr(T0);
                // load with zero extension.
                asm.emitLBZ(T0, 0, T0);
                // sign extend
                asm.emitEXTSB(T0, T0);
                // push *(base)
                pushInt(T0);
            } else {
                // pop offset
                popOffset(T1);
                // pop base
                popAddr(T0);
                // load with zero extension.
                asm.emitLBZX(T0, T1, T0);
                // sign extend
                asm.emitEXTSB(T0, T0);
                // push *(base+offset)
                pushInt(T0);
            }
            return true;
        }
        if (methodName == MagicNames.loadInt || methodName == MagicNames.loadFloat) {
            if (types.length == 0) {
                // pop base
                popAddr(T0);
                // *(base)
                asm.emitLInt(T0, 0, T0);
                // push *(base)
                pushInt(T0);
            } else {
                // pop offset
                popOffset(T1);
                // pop base
                popAddr(T0);
                // *(base+offset)
                asm.emitLIntX(T0, T1, T0);
                // push *(base+offset)
                pushInt(T0);
            }
            return true;
        }
        if (methodName == MagicNames.loadDouble || methodName == MagicNames.loadLong) {
            if (types.length == 0) {
                // pop base
                popAddr(T1);
                // *(base)
                asm.emitLFD(F0, 0, T1);
                // push double
                pushDouble(F0);
            } else {
                // pop offset
                popOffset(T2);
                // pop base
                popAddr(T1);
                // *(base+offset)
                asm.emitLFDX(F0, T1, T2);
                // push *(base+offset)
                pushDouble(F0);
            }
            return true;
        }
        if ((methodName == MagicNames.prepareInt) || (VM.BuildFor32Addr && (methodName == MagicNames.prepareWord)) || (VM.BuildFor32Addr && (methodName == MagicNames.prepareObjectReference)) || (VM.BuildFor32Addr && (methodName == MagicNames.prepareAddress))) {
            if (types.length == 0) {
                // pop base
                popAddr(T0);
                // *(base), setting reservation address
                asm.emitLWARX(T0, GPR.R0, T0);
                // this Integer is not sign extended !!
                // push *(base+offset)
                pushInt(T0);
            } else {
                // pop offset
                popOffset(T1);
                // pop base
                popAddr(T0);
                // *(base+offset), setting reservation address
                asm.emitLWARX(T0, T1, T0);
                // this Integer is not sign extended !!
                // push *(base+offset)
                pushInt(T0);
            }
            return true;
        }
        if ((methodName == MagicNames.prepareLong) || (VM.BuildFor64Addr && (methodName == MagicNames.prepareWord)) || (VM.BuildFor64Addr && (methodName == MagicNames.prepareObjectReference)) || (VM.BuildFor64Addr && (methodName == MagicNames.prepareAddress))) {
            if (types.length == 0) {
                // pop base
                popAddr(T0);
                // *(base), setting reservation address
                asm.emitLDARX(T0, GPR.R0, T0);
                // this Integer is not sign extended !!
                // push *(base+offset)
                pushAddr(T0);
            } else {
                // pop offset
                popOffset(T1);
                // pop base
                popAddr(T0);
                if (VM.BuildFor64Addr) {
                    // *(base+offset), setting reservation address
                    asm.emitLDARX(T0, T1, T0);
                } else {
                // TODO: handle 64bit prepares in 32bit environment
                }
                // this Integer is not sign extended !!
                // push *(base+offset)
                pushAddr(T0);
            }
            return true;
        }
        if (methodName == MagicNames.attempt && ((types[0] == TypeReference.Int) || (VM.BuildFor32Addr && (types[0] == TypeReference.Address)) || (VM.BuildFor32Addr && (types[0] == TypeReference.Word)))) {
            if (types.length == 2) {
                // pop newValue
                popInt(T2);
                // ignore oldValue
                discardSlot();
                // pop base
                popAddr(T0);
                // store new value and set CR0
                asm.emitSTWCXr(T2, GPR.R0, T0);
                // T0 := false
                asm.emitLVAL(T0, 0);
                // skip, if store failed
                ForwardReference fr = asm.emitForwardBC(NE);
                // T0 := true
                asm.emitLVAL(T0, 1);
                fr.resolve(asm);
                // push success of store
                pushInt(T0);
            } else {
                // pop offset
                popOffset(T1);
                // pop newValue
                popInt(T2);
                // ignore oldValue
                discardSlot();
                // pop base
                popAddr(T0);
                // store new value and set CR0
                asm.emitSTWCXr(T2, T1, T0);
                // T0 := false
                asm.emitLVAL(T0, 0);
                // skip, if store failed
                ForwardReference fr = asm.emitForwardBC(NE);
                // T0 := true
                asm.emitLVAL(T0, 1);
                fr.resolve(asm);
                // push success of store
                pushInt(T0);
            }
            return true;
        }
        if (methodName == MagicNames.attempt && ((types[0] == TypeReference.Long) || (VM.BuildFor64Addr && (types[0] == TypeReference.Address)) || (VM.BuildFor64Addr && (types[0] == TypeReference.Word)))) {
            if (types.length == 2) {
                // pop newValue
                popAddr(T2);
                // ignore oldValue
                discardSlot();
                // pop base
                popAddr(T0);
                // store new value and set CR0
                asm.emitSTDCXr(T2, GPR.R0, T0);
                // T0 := false
                asm.emitLVAL(T0, 0);
                // skip, if store failed
                ForwardReference fr = asm.emitForwardBC(NE);
                // T0 := true
                asm.emitLVAL(T0, 1);
                fr.resolve(asm);
                // push success of store
                pushInt(T0);
            } else {
                // pop offset
                popOffset(T1);
                // pop newValue
                popAddr(T2);
                // ignore oldValue
                discardSlot();
                // pop base
                popAddr(T0);
                if (VM.BuildFor64Addr) {
                    // store new value and set CR0
                    asm.emitSTDCXr(T2, T1, T0);
                } else {
                // TODO: handle 64bit attempts in 32bit environment
                }
                // T0 := false
                asm.emitLVAL(T0, 0);
                // skip, if store failed
                ForwardReference fr = asm.emitForwardBC(NE);
                // T0 := true
                asm.emitLVAL(T0, 1);
                fr.resolve(asm);
                // push success of store
                pushInt(T0);
            }
            return true;
        }
        // ..., Address, Value, [Offset] -> ...
        if (methodName == MagicNames.store) {
            if (types[0] == TypeReference.Word || types[0] == TypeReference.ObjectReference || types[0] == TypeReference.Address) {
                if (types.length == 1) {
                    // pop newvalue
                    popAddr(T1);
                    // pop base
                    popAddr(T0);
                    // *(base) = newvalue
                    asm.emitSTAddrX(T1, GPR.R0, T0);
                } else {
                    // pop offset
                    popOffset(T1);
                    // pop newvalue
                    popAddr(T2);
                    // pop base
                    popAddr(T0);
                    // *(base+offset) = newvalue
                    asm.emitSTAddrX(T2, T1, T0);
                }
                return true;
            }
            if (types[0] == TypeReference.Byte || types[0] == TypeReference.Boolean) {
                if (types.length == 1) {
                    // pop newvalue
                    popInt(T1);
                    // pop base
                    popAddr(T0);
                    // *(base) = newvalue
                    asm.emitSTBX(T1, GPR.R0, T0);
                } else {
                    // pop offset
                    popOffset(T1);
                    // pop newvalue
                    popInt(T2);
                    // pop base
                    popAddr(T0);
                    // *(base+offset) = newvalue
                    asm.emitSTBX(T2, T1, T0);
                }
                return true;
            }
            if (types[0] == TypeReference.Int || types[0] == TypeReference.Float) {
                if (types.length == 1) {
                    // pop newvalue
                    popInt(T1);
                    // pop base
                    popAddr(T0);
                    // *(base+offset) = newvalue
                    asm.emitSTWX(T1, GPR.R0, T0);
                } else {
                    // pop offset
                    popOffset(T1);
                    // pop newvalue
                    popInt(T2);
                    // pop base
                    popAddr(T0);
                    // *(base+offset) = newvalue
                    asm.emitSTWX(T2, T1, T0);
                }
                return true;
            }
            if (types[0] == TypeReference.Short || types[0] == TypeReference.Char) {
                if (types.length == 1) {
                    // pop newvalue
                    popInt(T1);
                    // pop base
                    popAddr(T0);
                    // *(base) = newvalue
                    asm.emitSTHX(T1, GPR.R0, T0);
                } else {
                    // pop offset
                    popOffset(T1);
                    // pop newvalue
                    popInt(T2);
                    // pop base
                    popAddr(T0);
                    // *(base+offset) = newvalue
                    asm.emitSTHX(T2, T1, T0);
                }
                return true;
            }
            if (types[0] == TypeReference.Double || types[0] == TypeReference.Long) {
                if (types.length == 1) {
                    // pop newvalue low and high
                    popLong(T2, T1);
                    // pop base
                    popAddr(T0);
                    if (VM.BuildFor32Addr) {
                        // *(base) = newvalue low
                        asm.emitSTW(T2, 0, T0);
                        // *(base+4) = newvalue high
                        asm.emitSTW(T1, BYTES_IN_INT, T0);
                    } else {
                        // *(base) = newvalue
                        asm.emitSTD(T1, 0, T0);
                    }
                } else {
                    // pop offset
                    popOffset(T1);
                    // pop newvalue low and high
                    popLong(T3, T2);
                    // pop base
                    popAddr(T0);
                    if (VM.BuildFor32Addr) {
                        // *(base+offset) = newvalue low
                        asm.emitSTWX(T3, T1, T0);
                        // offset += 4
                        asm.emitADDI(T1, BYTES_IN_INT, T1);
                        // *(base+offset) = newvalue high
                        asm.emitSTWX(T2, T1, T0);
                    } else {
                        // *(base+offset) = newvalue
                        asm.emitSTDX(T2, T1, T0);
                    }
                }
                return true;
            }
        }
    }
    if (methodName == MagicNames.getFramePointer) {
        pushAddr(FP);
    } else if (methodName == MagicNames.getCallerFramePointer) {
        // pop  frame pointer of callee frame
        popAddr(T0);
        // load frame pointer of caller frame
        asm.emitLAddr(T1, STACKFRAME_FRAME_POINTER_OFFSET.toInt(), T0);
        // push frame pointer of caller frame
        pushAddr(T1);
    } else if (methodName == MagicNames.setCallerFramePointer) {
        // value
        popAddr(T1);
        // fp
        popAddr(T0);
        // *(address+SFPO) := value
        asm.emitSTAddr(T1, STACKFRAME_FRAME_POINTER_OFFSET.toInt(), T0);
    } else if (methodName == MagicNames.getCompiledMethodID) {
        // pop  frame pointer of callee frame
        popAddr(T0);
        // load compiled method id
        asm.emitLInt(T1, STACKFRAME_METHOD_ID_OFFSET.toInt(), T0);
        // push method ID
        pushInt(T1);
    } else if (methodName == MagicNames.setCompiledMethodID) {
        // value
        popInt(T1);
        // fp
        popAddr(T0);
        // *(address+SNIO) := value
        asm.emitSTW(T1, STACKFRAME_METHOD_ID_OFFSET.toInt(), T0);
    } else if (methodName == MagicNames.getNextInstructionAddress) {
        // pop  frame pointer of callee frame
        popAddr(T0);
        // load frame pointer of caller frame
        asm.emitLAddr(T1, STACKFRAME_RETURN_ADDRESS_OFFSET.toInt(), T0);
        // push frame pointer of caller frame
        pushAddr(T1);
    } else if (methodName == MagicNames.getReturnAddressLocation) {
        // pop  frame pointer of callee frame
        popAddr(T0);
        // load frame pointer of caller frame
        asm.emitLAddr(T1, STACKFRAME_FRAME_POINTER_OFFSET.toInt(), T0);
        // get location containing ret addr
        asm.emitADDI(T2, STACKFRAME_RETURN_ADDRESS_OFFSET, T1);
        // push frame pointer of caller frame
        pushAddr(T2);
    } else if (methodName == MagicNames.getTocPointer || methodName == MagicNames.getJTOC) {
        pushAddr(JTOC);
    } else if (methodName == MagicNames.getThreadRegister) {
        pushAddr(THREAD_REGISTER);
    } else if (methodName == MagicNames.setThreadRegister) {
        popAddr(THREAD_REGISTER);
    } else if (methodName == MagicNames.getTimeBase) {
        if (VM.BuildFor64Addr) {
            // T1 := time base
            asm.emitMFTB(T1);
        } else {
            int label = asm.getMachineCodeIndex();
            // T0 := time base, upper
            asm.emitMFTBU(T0);
            // T1 := time base, lower
            asm.emitMFTB(T1);
            // T2 := time base, upper
            asm.emitMFTBU(T2);
            // T0 == T2?
            asm.emitCMP(T0, T2);
            // lower rolled over, try again
            asm.emitBC(NE, label);
        }
        pushLong(T0, T1);
    } else if (methodName == MagicNames.invokeClassInitializer) {
        // t0 := address to be called
        popAddr(T0);
        asm.emitMTCTR(T0);
        // call
        asm.emitBCCTRL();
    } else if (methodName == MagicNames.invokeMethodReturningVoid) {
        // call method
        generateMethodInvocation();
    } else if (methodName == MagicNames.invokeMethodReturningInt) {
        // call method
        generateMethodInvocation();
        // push result
        pushInt(T0);
    } else if (methodName == MagicNames.invokeMethodReturningLong) {
        // call method
        generateMethodInvocation();
        // push result
        pushLong(T0, VM.BuildFor64Addr ? T0 : T1);
    } else if (methodName == MagicNames.invokeMethodReturningFloat) {
        // call method
        generateMethodInvocation();
        // push result
        pushFloat(F0);
    } else if (methodName == MagicNames.invokeMethodReturningDouble) {
        // call method
        generateMethodInvocation();
        // push result
        pushDouble(F0);
    } else if (methodName == MagicNames.invokeMethodReturningObject) {
        // call method
        generateMethodInvocation();
        // push result
        pushAddr(T0);
    } else if (methodName == MagicNames.addressArrayCreate) {
        RVMArray type = methodToBeCalled.getType().resolve().asArray();
        emit_resolved_newarray(type);
    } else if (methodName == MagicNames.addressArrayLength) {
        emit_arraylength();
    } else if (methodName == MagicNames.addressArrayGet) {
        genBoundsCheck();
        if (VM.BuildFor32Addr || methodToBeCalled.getType() == TypeReference.CodeArray) {
            // convert index to offset
            asm.emitSLWI(T1, T1, LOG_BYTES_IN_INT);
            // load desired int array element
            asm.emitLIntX(T2, T0, T1);
            pushInt(T2);
        } else {
            // convert index to offset
            asm.emitSLDI(T1, T1, LOG_BYTES_IN_ADDRESS);
            // load desired array element
            asm.emitLAddrX(T2, T0, T1);
            pushAddr(T2);
        }
    } else if (methodName == MagicNames.addressArraySet) {
        // T2 is value to store
        popAddr(T2);
        genBoundsCheck();
        if (VM.BuildFor32Addr || methodToBeCalled.getType() == TypeReference.CodeArray) {
            // convert index to offset
            asm.emitSLWI(T1, T1, LOG_BYTES_IN_INT);
            // store 32-bit value in array
            asm.emitSTWX(T2, T0, T1);
        } else {
            // convert index to offset
            asm.emitSLDI(T1, T1, LOG_BYTES_IN_ADDRESS);
            // store value in array
            asm.emitSTAddrX(T2, T0, T1);
        }
    } else if (methodName == MagicNames.getIntAtOffset) {
        // pop offset
        popOffset(T1);
        // pop object
        popAddr(T0);
        // *(object+offset)
        asm.emitLIntX(T0, T1, T0);
        // push *(object+offset)
        pushInt(T0);
    } else if (methodName == MagicNames.getFloatAtOffset) {
        // pop offset
        popOffset(T1);
        // pop object
        popAddr(T0);
        // *(object+offset)
        asm.emitLWZX(T0, T1, T0);
        // push *(object+offset),
        pushInt(T0);
    // asm.emitLFSX  (F0, T1, T0); // *(object+offset)
    // pushFloat(F0);
    } else if (methodName == MagicNames.getObjectAtOffset || methodName == MagicNames.getWordAtOffset || methodName == MagicNames.getAddressAtOffset || methodName == MagicNames.getOffsetAtOffset || methodName == MagicNames.getExtentAtOffset || methodName == MagicNames.getTIBAtOffset) {
        if (methodToBeCalled.getParameterTypes().length == 3) {
            // discard locationMetadata parameter
            discardSlot();
        }
        // pop offset
        popOffset(T1);
        // pop object
        popAddr(T0);
        // *(object+offset)
        asm.emitLAddrX(T0, T1, T0);
        // push *(object+offset)
        pushAddr(T0);
    } else if (methodName == MagicNames.getUnsignedByteAtOffset) {
        // pop offset
        popOffset(T1);
        // pop object
        popAddr(T0);
        // load byte with zero extension.
        asm.emitLBZX(T0, T1, T0);
        // push *(object+offset)
        pushInt(T0);
    } else if (methodName == MagicNames.getByteAtOffset) {
        // pop offset
        popOffset(T1);
        // pop object
        popAddr(T0);
        // load byte with zero extension.
        asm.emitLBZX(T0, T1, T0);
        // sign extend
        asm.emitEXTSB(T0, T0);
        // push *(object+offset)
        pushInt(T0);
    } else if (methodName == MagicNames.getCharAtOffset) {
        // pop offset
        popOffset(T1);
        // pop object
        popAddr(T0);
        // load char with zero extension.
        asm.emitLHZX(T0, T1, T0);
        // push *(object+offset)
        pushInt(T0);
    } else if (methodName == MagicNames.getShortAtOffset) {
        // pop offset
        popOffset(T1);
        // pop object
        popAddr(T0);
        // load short with sign extension.
        asm.emitLHAX(T0, T1, T0);
        // push *(object+offset)
        pushInt(T0);
    } else if (methodName == MagicNames.setIntAtOffset || methodName == MagicNames.setFloatAtOffset) {
        if (methodToBeCalled.getParameterTypes().length == 4) {
            // discard locationMetadata parameter
            discardSlot();
        }
        // pop newvalue
        popInt(T2);
        // pop offset
        popOffset(T1);
        // pop object
        popAddr(T0);
        // *(object+offset) = newvalue
        asm.emitSTWX(T2, T1, T0);
    } else if (methodName == MagicNames.setObjectAtOffset || methodName == MagicNames.setWordAtOffset || methodName == MagicNames.setAddressAtOffset || methodName == MagicNames.setOffsetAtOffset || methodName == MagicNames.setExtentAtOffset) {
        if (methodToBeCalled.getParameterTypes().length == 4) {
            // discard locationMetadata parameter
            discardSlot();
        }
        // pop newvalue
        popAddr(T2);
        // pop offset
        popOffset(T1);
        // pop object
        popAddr(T0);
        // *(object+offset) = newvalue
        asm.emitSTAddrX(T2, T1, T0);
    } else if (methodName == MagicNames.setByteAtOffset || methodName == MagicNames.setBooleanAtOffset) {
        if (methodToBeCalled.getParameterTypes().length == 4) {
            // discard locationMetadata parameter
            discardSlot();
        }
        // pop newvalue
        popInt(T2);
        // pop offset
        popOffset(T1);
        // pop object
        popAddr(T0);
        // *(object+offset) = newvalue
        asm.emitSTBX(T2, T1, T0);
    } else if (methodName == MagicNames.setCharAtOffset || methodName == MagicNames.setShortAtOffset) {
        if (methodToBeCalled.getParameterTypes().length == 4) {
            // discard locationMetadata parameter
            discardSlot();
        }
        // pop newvalue
        popInt(T2);
        // pop offset
        popOffset(T1);
        // pop object
        popAddr(T0);
        // *(object+offset) = newvalue
        asm.emitSTHX(T2, T1, T0);
    } else if (methodName == MagicNames.getLongAtOffset || methodName == MagicNames.getDoubleAtOffset) {
        // pop offset
        popOffset(T2);
        // pop object
        popAddr(T1);
        asm.emitLFDX(F0, T1, T2);
        pushDouble(F0);
    } else if ((methodName == MagicNames.setLongAtOffset) || (methodName == MagicNames.setDoubleAtOffset)) {
        if (methodToBeCalled.getParameterTypes().length == 4) {
            // discard locationMetadata parameter
            discardSlot();
        }
        popLong(T3, T2);
        // pop offset
        popOffset(T1);
        // pop object
        popAddr(T0);
        if (VM.BuildFor32Addr) {
            // *(object+offset) = newvalue low
            asm.emitSTWX(T3, T1, T0);
            // offset += 4
            asm.emitADDI(T1, BYTES_IN_INT, T1);
            // *(object+offset) = newvalue high
            asm.emitSTWX(T2, T1, T0);
        } else {
            // *(object+offset) = newvalue
            asm.emitSTDX(T2, T1, T0);
        }
    } else if (methodName == MagicNames.getMemoryInt) {
        // address
        popAddr(T0);
        // *address
        asm.emitLInt(T0, 0, T0);
        // *sp := *address
        pushInt(T0);
    } else if (methodName == MagicNames.getMemoryWord || methodName == MagicNames.getMemoryAddress) {
        // address
        popAddr(T0);
        // *address
        asm.emitLAddr(T0, 0, T0);
        // *sp := *address
        pushAddr(T0);
    } else if (methodName == MagicNames.setMemoryInt) {
        // value
        popInt(T1);
        // address
        popAddr(T0);
        // *address := value
        asm.emitSTW(T1, 0, T0);
    } else if (methodName == MagicNames.setMemoryWord) {
        if (methodToBeCalled.getParameterTypes().length == 3) {
            // discard locationMetadata parameter
            discardSlot();
        }
        // value
        popAddr(T1);
        // address
        popAddr(T0);
        // *address := value
        asm.emitSTAddr(T1, 0, T0);
    } else if ((methodName == MagicNames.prepareInt) || (VM.BuildFor32Addr && (methodName == MagicNames.prepareObject)) || (VM.BuildFor32Addr && (methodName == MagicNames.prepareAddress)) || (VM.BuildFor32Addr && (methodName == MagicNames.prepareWord))) {
        // pop offset
        popOffset(T1);
        // pop object
        popAddr(T0);
        // *(object+offset), setting thread's reservation address
        asm.emitLWARX(T0, T1, T0);
        // this Integer is not sign extended !!
        // push *(object+offset)
        pushInt(T0);
    } else if ((methodName == MagicNames.prepareLong) || (VM.BuildFor64Addr && (methodName == MagicNames.prepareObject)) || (VM.BuildFor64Addr && (methodName == MagicNames.prepareAddress)) || (VM.BuildFor64Addr && (methodName == MagicNames.prepareWord))) {
        // pop offset
        popOffset(T1);
        // pop object
        popAddr(T0);
        if (VM.BuildFor64Addr) {
            // *(object+offset), setting thread's reservation address
            asm.emitLDARX(T0, T1, T0);
        } else {
        // TODO: handle 64bit prepares in 32bit environment
        }
        // push *(object+offset)
        pushAddr(T0);
    } else if ((methodName == MagicNames.attemptInt) || (VM.BuildFor32Addr && (methodName == MagicNames.attemptObject)) || (VM.BuildFor32Addr && (methodName == MagicNames.attemptObjectReference)) || (VM.BuildFor32Addr && (methodName == MagicNames.attemptAddress)) || (VM.BuildFor32Addr && (methodName == MagicNames.attemptWord))) {
        // pop newValue
        popInt(T2);
        // ignore oldValue
        discardSlot();
        // pop offset
        popOffset(T1);
        // pop object
        popAddr(T0);
        // store new value and set CR0
        asm.emitSTWCXr(T2, T1, T0);
        // T0 := false
        asm.emitLVAL(T0, 0);
        // skip, if store failed
        ForwardReference fr = asm.emitForwardBC(NE);
        // T0 := true
        asm.emitLVAL(T0, 1);
        fr.resolve(asm);
        // push success of conditional store
        pushInt(T0);
    } else if (methodName == MagicNames.attemptLong) {
        // pop newValue
        popLong(T3, T2);
        // ignore oldValue which is a long and thus takes 2 slots
        discardSlots(2);
        // pop offset
        popOffset(T1);
        // pop object
        popAddr(T0);
        if (VM.BuildFor64Addr) {
            // store new value and set CR0
            asm.emitSTDCXr(T2, T1, T0);
        } else {
        // TODO: handle 64bit attempts in 32bit environment
        }
        // T0 := false
        asm.emitLVAL(T0, 0);
        // skip, if store failed
        ForwardReference fr = asm.emitForwardBC(NE);
        // T0 := true
        asm.emitLVAL(T0, 1);
        fr.resolve(asm);
        // push success of conditional store
        pushInt(T0);
    } else if (VM.BuildFor64Addr && ((methodName == MagicNames.attemptObject) || (methodName == MagicNames.attemptObjectReference) || (methodName == MagicNames.attemptAddress) || (methodName == MagicNames.attemptWord))) {
        // pop newValue
        popAddr(T2);
        // ignore oldValue
        discardSlot();
        // pop offset
        popOffset(T1);
        // pop object
        popAddr(T0);
        // store new value and set CR0
        asm.emitSTDCXr(T2, T1, T0);
        // T0 := false
        asm.emitLVAL(T0, 0);
        // skip, if store failed
        ForwardReference fr = asm.emitForwardBC(NE);
        // T0 := true
        asm.emitLVAL(T0, 1);
        fr.resolve(asm);
        // push success of conditional store
        pushInt(T0);
    } else if (methodName == MagicNames.saveThreadState) {
        // T0 := address of Registers object
        peekAddr(T0, 0);
        asm.emitLAddrToc(S0, ArchEntrypoints.saveThreadStateInstructionsField.getOffset());
        asm.emitMTCTR(S0);
        // call out of line machine code
        asm.emitBCCTRL();
        // pop arg
        discardSlot();
    } else if (methodName == MagicNames.threadSwitch) {
        // T1 := address of Registers of new thread
        peekAddr(T1, 0);
        // T0 := address of previous RVMThread object
        peekAddr(T0, 1);
        asm.emitLAddrToc(S0, ArchEntrypoints.threadSwitchInstructionsField.getOffset());
        asm.emitMTCTR(S0);
        asm.emitBCCTRL();
        // pop two args
        discardSlots(2);
    } else if (methodName == MagicNames.restoreHardwareExceptionState) {
        // T0 := address of Registers object
        peekAddr(T0, 0);
        asm.emitLAddrToc(S0, ArchEntrypoints.restoreHardwareExceptionStateInstructionsField.getOffset());
        asm.emitMTLR(S0);
        // branch to out of line machine code (does not return)
        asm.emitBCLR();
    } else if (methodName == MagicNames.returnToNewStack) {
        // FP := new stackframe
        peekAddr(FP, 0);
        // fetch...
        asm.emitLAddr(S0, STACKFRAME_RETURN_ADDRESS_OFFSET.toInt(), FP);
        // ...return address
        asm.emitMTLR(S0);
        // return to caller
        asm.emitBCLR();
    } else if (methodName == MagicNames.dynamicBridgeTo) {
        if (VM.VerifyAssertions)
            VM._assert(klass.hasDynamicBridgeAnnotation());
        // fetch parameter (address to branch to) into CT register
        // 
        peekAddr(T0, 0);
        asm.emitMTCTR(T0);
        // restore volatile and non-volatile registers
        // (note that these are only saved for "dynamic bridge" methods)
        // 
        int offset = frameSize;
        // restore non-volatile and volatile fprs
        for (int i = LAST_NONVOLATILE_FPR.value(); i >= FIRST_VOLATILE_FPR.value(); --i) {
            asm.emitLFD(FPR.lookup(i), offset -= BYTES_IN_DOUBLE, FP);
        }
        // restore non-volatile gprs
        for (int i = LAST_NONVOLATILE_GPR.value(); i >= FIRST_NONVOLATILE_GPR.value(); --i) {
            asm.emitLAddr(GPR.lookup(i), offset -= BYTES_IN_ADDRESS, FP);
        }
        // skip saved thread-id, thread, and scratch registers
        offset -= (FIRST_NONVOLATILE_GPR.value() - LAST_VOLATILE_GPR.value() - 1) * BYTES_IN_ADDRESS;
        // restore volatile gprs
        for (int i = LAST_VOLATILE_GPR.value(); i >= FIRST_VOLATILE_GPR.value(); --i) {
            asm.emitLAddr(GPR.lookup(i), offset -= BYTES_IN_ADDRESS, FP);
        }
        // pop stackframe
        asm.emitLAddr(FP, 0, FP);
        // restore link register
        asm.emitLAddr(S0, STACKFRAME_RETURN_ADDRESS_OFFSET.toInt(), FP);
        asm.emitMTLR(S0);
        // branch always, through count register
        asm.emitBCCTR();
    } else if (methodName == MagicNames.objectAsAddress || methodName == MagicNames.addressAsByteArray || methodName == MagicNames.addressAsObject || methodName == MagicNames.addressAsTIB || methodName == MagicNames.objectAsType || methodName == MagicNames.objectAsShortArray || methodName == MagicNames.objectAsIntArray || methodName == MagicNames.objectAsThread || methodName == MagicNames.floatAsIntBits || methodName == MagicNames.intBitsAsFloat || methodName == MagicNames.doubleAsLongBits || methodName == MagicNames.longBitsAsDouble) {
    // no-op (a type change, not a representation change)
    } else if (methodName == MagicNames.getObjectType) {
        // get object pointer
        popAddr(T0);
        asm.baselineEmitLoadTIB(T0, T0);
        // get "type" field from type information block
        asm.emitLAddr(T0, TIB_TYPE_INDEX << LOG_BYTES_IN_ADDRESS, T0);
        // *sp := type
        pushAddr(T0);
    } else if (methodName == MagicNames.getArrayLength) {
        // get object pointer
        popAddr(T0);
        // get array length field
        asm.emitLIntOffset(T0, T0, ObjectModel.getArrayLengthOffset());
        // *sp := length
        pushInt(T0);
    } else if (methodName == MagicNames.synchronizeInstructionCache) {
        asm.emitISYNC();
    } else if (methodName == MagicNames.pause) {
    // NO-OP
    } else if (methodName == MagicNames.combinedLoadBarrier) {
        asm.emitHWSYNC();
    } else if (methodName == MagicNames.storeStoreBarrier) {
        asm.emitSYNC();
    } else if (methodName == MagicNames.fence) {
        asm.emitHWSYNC();
    } else if (methodName == MagicNames.illegalInstruction) {
        asm.emitIllegalInstruction();
    } else if (methodName == MagicNames.dcbst) {
        // address
        popAddr(T0);
        asm.emitDCBST(GPR.R0, T0);
    } else if (methodName == MagicNames.dcbt || methodName == MagicNames.prefetch) {
        // address
        popAddr(T0);
        asm.emitDCBT(GPR.R0, T0);
    } else if (methodName == MagicNames.dcbtst) {
        // address
        popAddr(T0);
        asm.emitDCBTST(GPR.R0, T0);
    } else if (methodName == MagicNames.dcbz) {
        // address
        popAddr(T0);
        asm.emitDCBZ(GPR.R0, T0);
    } else if (methodName == MagicNames.dcbzl) {
        // address
        popAddr(T0);
        asm.emitDCBZL(GPR.R0, T0);
    } else if (methodName == MagicNames.icbi) {
        // address
        popAddr(T0);
        asm.emitICBI(GPR.R0, T0);
    } else if (methodName == MagicNames.sqrt) {
        TypeReference argType = method.getParameterTypes()[0];
        if (argType == TypeReference.Float) {
            popFloat(F0);
            asm.emitFSQRTS(F0, F0);
            pushFloat(F0);
        } else {
            if (VM.VerifyAssertions)
                VM._assert(argType == TypeReference.Double);
            popDouble(F0);
            asm.emitFSQRT(F0, F0);
            pushDouble(F0);
        }
    } else if (methodName == MagicNames.getInlineDepth || methodName == MagicNames.isConstantParameter) {
        emit_iconst(0);
    } else if (methodName == MagicNames.getCompilerLevel) {
        emit_iconst(-1);
    } else if (methodName == MagicNames.getFrameSize) {
        emit_iconst(frameSize);
    } else if (methodName == MagicNames.wordToInt || methodName == MagicNames.wordToAddress || methodName == MagicNames.wordToOffset || methodName == MagicNames.wordToObject || methodName == MagicNames.wordFromObject || methodName == MagicNames.wordToObjectReference || methodName == MagicNames.wordToExtent || methodName == MagicNames.wordToWord || methodName == MagicNames.codeArrayAsObject || methodName == MagicNames.tibAsObject) {
    // no-op
    } else if (methodName == MagicNames.wordToLong) {
        asm.emitLVAL(T0, 0);
        pushAddr(T0);
    } else if (methodName == MagicNames.wordFromInt || methodName == MagicNames.wordFromIntSignExtend) {
        if (VM.BuildFor64Addr) {
            popInt(T0);
            pushAddr(T0);
        }
    // else no-op
    } else if (methodName == MagicNames.wordFromIntZeroExtend) {
        if (VM.BuildFor64Addr) {
            asm.emitLWZ(T0, spTopOffset + BYTES_IN_STACKSLOT - BYTES_IN_INT, FP);
            pokeAddr(T0, 0);
        }
    // else no-op
    } else if (methodName == MagicNames.wordFromLong) {
        discardSlot();
    } else if (methodName == MagicNames.wordPlus) {
        if (VM.BuildFor64Addr && (methodToBeCalled.getParameterTypes()[0] == TypeReference.Int)) {
            popInt(T0);
        } else {
            popAddr(T0);
        }
        popAddr(T1);
        asm.emitADD(T2, T1, T0);
        pushAddr(T2);
    } else if (methodName == MagicNames.wordMinus || methodName == MagicNames.wordDiff) {
        if (VM.BuildFor64Addr && (methodToBeCalled.getParameterTypes()[0] == TypeReference.Int)) {
            popInt(T0);
        } else {
            popAddr(T0);
        }
        popAddr(T1);
        asm.emitSUBFC(T2, T0, T1);
        pushAddr(T2);
    } else if (methodName == MagicNames.wordEQ) {
        generateAddrComparison(false, EQ);
    } else if (methodName == MagicNames.wordNE) {
        generateAddrComparison(false, NE);
    } else if (methodName == MagicNames.wordLT) {
        generateAddrComparison(false, LT);
    } else if (methodName == MagicNames.wordLE) {
        generateAddrComparison(false, LE);
    } else if (methodName == MagicNames.wordGT) {
        generateAddrComparison(false, GT);
    } else if (methodName == MagicNames.wordGE) {
        generateAddrComparison(false, GE);
    } else if (methodName == MagicNames.wordsLT) {
        generateAddrComparison(true, LT);
    } else if (methodName == MagicNames.wordsLE) {
        generateAddrComparison(true, LE);
    } else if (methodName == MagicNames.wordsGT) {
        generateAddrComparison(true, GT);
    } else if (methodName == MagicNames.wordsGE) {
        generateAddrComparison(true, GE);
    } else if (methodName == MagicNames.wordIsZero || methodName == MagicNames.wordIsNull) {
        // unsigned comparison generating a boolean
        popAddr(T0);
        asm.emitLVAL(T1, 0);
        asm.emitLVAL(T2, 1);
        asm.emitCMPLAddr(T0, T1);
        ForwardReference fr = asm.emitForwardBC(EQ);
        asm.emitLVAL(T2, 0);
        fr.resolve(asm);
        pushInt(T2);
    } else if (methodName == MagicNames.wordIsMax) {
        // unsigned comparison generating a boolean
        popAddr(T0);
        asm.emitLVAL(T1, -1);
        asm.emitLVAL(T2, 1);
        asm.emitCMPLAddr(T0, T1);
        ForwardReference fr = asm.emitForwardBC(EQ);
        asm.emitLVAL(T2, 0);
        fr.resolve(asm);
        pushInt(T2);
    } else if (methodName == MagicNames.wordZero || methodName == MagicNames.wordNull) {
        asm.emitLVAL(T0, 0);
        pushAddr(T0);
    } else if (methodName == MagicNames.wordOne) {
        asm.emitLVAL(T0, 1);
        pushAddr(T0);
    } else if (methodName == MagicNames.wordMax) {
        asm.emitLVAL(T0, -1);
        pushAddr(T0);
    } else if (methodName == MagicNames.wordAnd) {
        popAddr(T0);
        popAddr(T1);
        asm.emitAND(T2, T1, T0);
        pushAddr(T2);
    } else if (methodName == MagicNames.wordOr) {
        popAddr(T0);
        popAddr(T1);
        asm.emitOR(T2, T1, T0);
        pushAddr(T2);
    } else if (methodName == MagicNames.wordNot) {
        popAddr(T0);
        asm.emitLVAL(T1, -1);
        asm.emitXOR(T2, T1, T0);
        pushAddr(T2);
    } else if (methodName == MagicNames.wordXor) {
        popAddr(T0);
        popAddr(T1);
        asm.emitXOR(T2, T1, T0);
        pushAddr(T2);
    } else if (methodName == MagicNames.wordLsh) {
        popInt(T0);
        popAddr(T1);
        asm.emitSLAddr(T2, T1, T0);
        pushAddr(T2);
    } else if (methodName == MagicNames.wordRshl) {
        popInt(T0);
        popAddr(T1);
        asm.emitSRAddr(T2, T1, T0);
        pushAddr(T2);
    } else if (methodName == MagicNames.wordRsha) {
        popInt(T0);
        popAddr(T1);
        asm.emitSRA_Addr(T2, T1, T0);
        pushAddr(T2);
    } else {
        return false;
    }
    return true;
}
Also used : ForwardReference(org.jikesrvm.compilers.common.assembler.ForwardReference) RVMArray(org.jikesrvm.classloader.RVMArray) TypeReference(org.jikesrvm.classloader.TypeReference) Atom(org.jikesrvm.classloader.Atom)

Example 18 with RVMArray

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

the class CompiledMethods method spaceReport.

/**
 * Report on the space used by compiled code and associated mapping information
 */
public static void spaceReport() {
    int[] codeCount = new int[CompiledMethod.NUM_COMPILER_TYPES + 1];
    int[] codeBytes = new int[CompiledMethod.NUM_COMPILER_TYPES + 1];
    int[] mapBytes = new int[CompiledMethod.NUM_COMPILER_TYPES + 1];
    RVMArray codeArray = RVMType.CodeArrayType.asArray();
    for (int i = 0; i < numCompiledMethods(); i++) {
        CompiledMethod cm = getCompiledMethodUnchecked(i);
        if (cm == null || !cm.isCompiled())
            continue;
        int ct = cm.getCompilerType();
        codeCount[ct]++;
        int size = codeArray.getInstanceSize(cm.numberOfInstructions());
        codeBytes[ct] += Memory.alignUp(size, BYTES_IN_ADDRESS);
        mapBytes[ct] += cm.size();
    }
    VM.sysWriteln("Compiled code space report");
    VM.sysWriteln();
    VM.sysWriteln("  Baseline Compiler");
    VM.sysWriteln("    Number of compiled methods =         " + codeCount[CompiledMethod.BASELINE]);
    VM.sysWriteln("    Total size of code (bytes) =         " + codeBytes[CompiledMethod.BASELINE]);
    VM.sysWriteln("    Total size of mapping data (bytes) = " + mapBytes[CompiledMethod.BASELINE]);
    if (codeCount[CompiledMethod.OPT] > 0) {
        VM.sysWriteln("  Optimizing Compiler");
        VM.sysWriteln("    Number of compiled methods =         " + codeCount[CompiledMethod.OPT]);
        VM.sysWriteln("    Total size of code (bytes) =         " + codeBytes[CompiledMethod.OPT]);
        VM.sysWriteln("    Total size of mapping data (bytes) = " + mapBytes[CompiledMethod.OPT]);
    }
    if (codeCount[CompiledMethod.JNI] > 0) {
        VM.sysWriteln("  JNI Stub Compiler (Java->C stubs for native methods)");
        VM.sysWriteln("    Number of compiled methods =         " + codeCount[CompiledMethod.JNI]);
        VM.sysWriteln("    Total size of code (bytes) =         " + codeBytes[CompiledMethod.JNI]);
        VM.sysWriteln("    Total size of mapping data (bytes) = " + mapBytes[CompiledMethod.JNI]);
    }
    if (!VM.runningVM) {
        TreeMap<String, Integer> packageData = new TreeMap<String, Integer>(new Comparator<String>() {

            @Override
            public int compare(String a, String b) {
                return a.compareTo(b);
            }
        });
        for (int i = 0; i < numCompiledMethods(); ++i) {
            CompiledMethod compiledMethod = getCompiledMethodUnchecked(i);
            if (compiledMethod != null) {
                RVMMethod m = compiledMethod.getMethod();
                if (m != null && compiledMethod.isCompiled()) {
                    String packageName = m.getDeclaringClass().getPackageName();
                    int numInstructions = compiledMethod.numberOfInstructions();
                    Integer val = packageData.get(packageName);
                    if (val == null) {
                        val = numInstructions;
                    } else {
                        val = val + numInstructions;
                    }
                    packageData.put(packageName, val);
                }
            }
        }
        VM.sysWriteln("------------------------------------------------------------------------------------------");
        VM.sysWriteln("  Break down of code space usage by package (bytes):");
        VM.sysWriteln("------------------------------------------------------------------------------------------");
        Set<String> keys = packageData.keySet();
        int maxPackageNameSize = 0;
        for (String packageName : keys) {
            maxPackageNameSize = Math.max(maxPackageNameSize, packageName.length());
        }
        maxPackageNameSize++;
        for (String packageName : keys) {
            VM.sysWriteField(maxPackageNameSize, packageName);
            VM.sysWriteField(10, packageData.get(packageName));
            VM.sysWriteln();
        }
    }
}
Also used : RVMMethod(org.jikesrvm.classloader.RVMMethod) RVMArray(org.jikesrvm.classloader.RVMArray) TreeMap(java.util.TreeMap) JNICompiledMethod(org.jikesrvm.jni.JNICompiledMethod) OptCompiledMethod(org.jikesrvm.compilers.opt.runtimesupport.OptCompiledMethod)

Example 19 with RVMArray

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

the class VMInstrumentationImpl method getObjectSize.

static long getObjectSize(Object objectToSize) {
    Class<?> cl = objectToSize.getClass();
    RVMType vmType = java.lang.JikesRVMSupport.getTypeForClass(cl);
    if (cl.isArray()) {
        RVMArray vmArray = (RVMArray) vmType;
        int nelements = java.lang.reflect.Array.getLength(objectToSize);
        return vmArray.getInstanceSize(nelements);
    } else {
        RVMClass vmClass = (RVMClass) vmType;
        return vmClass.getInstanceSize();
    }
}
Also used : RVMArray(org.jikesrvm.classloader.RVMArray) RVMType(org.jikesrvm.classloader.RVMType) RVMClass(org.jikesrvm.classloader.RVMClass)

Example 20 with RVMArray

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

the class DynamicTypeCheckExpansion method generateValueProducingTypeCheck.

/**
 * Generate a value-producing dynamic type check.
 * This routine assumes that the CFG and code order are
 * already correctly established.
 * This routine must either remove s or mutuate it.
 *
 * @param s        The Instruction that is to be replaced by
 *                  a value producing type check
 * @param ir       The IR containing the instruction to be expanded.
 * @param RHSobj   The RegisterOperand containing the rhs object.
 * @param LHStype  The RVMType to be tested against.
 * @param RHStib   The Operand containing the TIB of the rhs.
 * @param result   The RegisterOperand that the result of dynamic
 *                 type check is to be stored in.
 * @return the opt instruction immediately before the
 *         instruction to continue expansion.
 */
private static Instruction generateValueProducingTypeCheck(Instruction s, IR ir, Operand RHSobj, TypeReference LHStype, Operand RHStib, RegisterOperand result) {
    // Is LHStype a class?
    if (LHStype.isClassType()) {
        RVMClass LHSclass = (RVMClass) LHStype.peekType();
        if (LHSclass != null && LHSclass.isResolved()) {
            // resolved class or interface
            if (LHSclass.isInterface()) {
                // A resolved interface (case 4)
                int interfaceIndex = LHSclass.getDoesImplementIndex();
                int interfaceMask = LHSclass.getDoesImplementBitMask();
                RegisterOperand doesImpl = InsertUnary(s, ir, GET_DOES_IMPLEMENT_FROM_TIB, TypeReference.IntArray, RHStib);
                RegisterOperand entry = InsertLoadOffset(s, ir, INT_LOAD, TypeReference.Int, doesImpl, Offset.fromIntZeroExtend(interfaceIndex << 2), new LocationOperand(TypeReference.Int), TG());
                RegisterOperand bit = insertBinary(s, ir, INT_AND, TypeReference.Int, entry, IC(interfaceMask));
                // save to use the cheaper ADDR version of BOOLEAN_CMP
                s.insertBefore(BooleanCmp.create(BOOLEAN_CMP_ADDR, result, bit, AC(Address.zero()), ConditionOperand.NOT_EQUAL(), new BranchProfileOperand()));
                if (DynamicTypeCheck.MIN_DOES_IMPLEMENT_SIZE <= interfaceIndex) {
                    RegisterOperand doesImplLength = InsertGuardedUnary(s, ir, ARRAYLENGTH, TypeReference.Int, doesImpl.copy(), TG());
                    RegisterOperand boundscheck = ir.regpool.makeTempInt();
                    // save to use the cheaper ADDR version of BOOLEAN_CMP
                    s.insertBefore(BooleanCmp.create(BOOLEAN_CMP_ADDR, boundscheck, doesImplLength, AC(Address.fromIntSignExtend(interfaceIndex)), ConditionOperand.GREATER(), new BranchProfileOperand()));
                    s.insertBefore(Binary.create(INT_AND, result.copyD2D(), result.copyD2U(), boundscheck.copyD2U()));
                }
                Instruction continueAt = s.prevInstructionInCodeOrder();
                s.remove();
                return continueAt;
            } else {
                // A resolved class (cases 5 and 6 in DynamicTypeCheck)
                if (LHSclass.isFinal()) {
                    // For a final class, we can do a PTR compare of
                    // rhsTIB and the TIB of the class
                    Operand classTIB = getTIB(s, ir, LHSclass);
                    BooleanCmp.mutate(s, BOOLEAN_CMP_ADDR, result, RHStib, classTIB, ConditionOperand.EQUAL(), new BranchProfileOperand());
                    return s.prevInstructionInCodeOrder();
                } else {
                    // Do the full blown case 5 or 6 typecheck.
                    int LHSDepth = LHSclass.getTypeDepth();
                    int LHSId = LHSclass.getId();
                    RegisterOperand superclassIds = InsertUnary(s, ir, GET_SUPERCLASS_IDS_FROM_TIB, TypeReference.ShortArray, RHStib);
                    RegisterOperand refCandidate = InsertLoadOffset(s, ir, USHORT_LOAD, TypeReference.Short, superclassIds, Offset.fromIntZeroExtend(LHSDepth << 1), new LocationOperand(TypeReference.Short), TG());
                    // save to use the cheaper ADDR version of BOOLEAN_CMP
                    s.insertBefore(BooleanCmp.create(BOOLEAN_CMP_ADDR, result, refCandidate, AC(Address.fromIntZeroExtend(LHSId)), ConditionOperand.EQUAL(), new BranchProfileOperand()));
                    if (DynamicTypeCheck.MIN_SUPERCLASS_IDS_SIZE <= LHSDepth) {
                        RegisterOperand superclassIdsLength = InsertGuardedUnary(s, ir, ARRAYLENGTH, TypeReference.Int, superclassIds.copyD2U(), TG());
                        RegisterOperand boundscheck = ir.regpool.makeTempInt();
                        // save to use the cheaper ADDR version of BOOLEAN_CMP
                        s.insertBefore(BooleanCmp.create(BOOLEAN_CMP_ADDR, boundscheck, superclassIdsLength, AC(Address.fromIntSignExtend(LHSDepth)), ConditionOperand.GREATER(), new BranchProfileOperand()));
                        s.insertBefore(Binary.create(INT_AND, result.copyD2D(), result.copyD2U(), boundscheck.copyD2U()));
                    }
                    Instruction continueAt = s.prevInstructionInCodeOrder();
                    s.remove();
                    return continueAt;
                }
            }
        } else {
            // A non-resolved class or interface.
            // We expect these to be extremely uncommon in opt code in AOS.
            // Mutate s into a call to RuntimeEntrypoints.instanceOf
            RVMMethod target = Entrypoints.instanceOfMethod;
            Call.mutate2(s, CALL, result, AC(target.getOffset()), MethodOperand.STATIC(target), RHSobj, IC(LHStype.getId()));
            return callHelper(s, ir);
        }
    }
    if (LHStype.isArrayType()) {
        // Case 2 of DynamicTypeCheck: LHS is an array.
        RVMArray LHSArray = (RVMArray) LHStype.peekType();
        if (LHSArray != null) {
            RVMType innermostElementType = LHSArray.getInnermostElementType();
            if (innermostElementType.isPrimitiveType() || innermostElementType.isUnboxedType() || (innermostElementType.asClass().isResolved() && innermostElementType.asClass().isFinal())) {
                // [^k of primitive or [^k of final class. Just like final classes,
                // a PTR compare of rhsTIB and the TIB of the class gives the answer.
                Operand classTIB = getTIB(s, ir, LHSArray);
                BooleanCmp.mutate(s, BOOLEAN_CMP_ADDR, result, RHStib, classTIB, ConditionOperand.EQUAL(), new BranchProfileOperand());
                return s;
            }
        }
        // and do the real work there.
        return convertToBranchingTypeCheck(s, ir, RHSobj, LHStype, RHStib, result);
    }
    OptimizingCompilerException.UNREACHABLE();
    return null;
}
Also used : RVMMethod(org.jikesrvm.classloader.RVMMethod) LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) MethodOperand(org.jikesrvm.compilers.opt.ir.operand.MethodOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) TrueGuardOperand(org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) NullConstantOperand(org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) TrapCodeOperand(org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand) LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) RVMArray(org.jikesrvm.classloader.RVMArray) RVMType(org.jikesrvm.classloader.RVMType) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) RVMClass(org.jikesrvm.classloader.RVMClass)

Aggregations

RVMArray (org.jikesrvm.classloader.RVMArray)32 TIB (org.jikesrvm.objectmodel.TIB)14 Entrypoint (org.vmmagic.pragma.Entrypoint)14 RVMType (org.jikesrvm.classloader.RVMType)11 RVMClass (org.jikesrvm.classloader.RVMClass)9 NoInline (org.vmmagic.pragma.NoInline)8 TypeReference (org.jikesrvm.classloader.TypeReference)7 Interruptible (org.vmmagic.pragma.Interruptible)7 RVMMethod (org.jikesrvm.classloader.RVMMethod)6 Address (org.vmmagic.unboxed.Address)6 Operand (org.jikesrvm.compilers.opt.ir.operand.Operand)4 RegisterOperand (org.jikesrvm.compilers.opt.ir.operand.RegisterOperand)4 Test (org.junit.Test)4 Instruction (org.jikesrvm.compilers.opt.ir.Instruction)3 ConditionOperand (org.jikesrvm.compilers.opt.ir.operand.ConditionOperand)3 IntConstantOperand (org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand)3 LocationOperand (org.jikesrvm.compilers.opt.ir.operand.LocationOperand)3 MethodOperand (org.jikesrvm.compilers.opt.ir.operand.MethodOperand)3 TrapCodeOperand (org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand)3 TrueGuardOperand (org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand)3