Search in sources :

Example 11 with Atom

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

the class EntrypointHelper method getMethod.

/**
 * Get description of virtual machine method.
 * @param klass class  containing method
 * @param member member name - something like "invokestatic"
 * @param descriptor member descriptor - something like "()V"
 * @return corresponding RVMMethod
 */
public static NormalMethod getMethod(Class<?> klass, String member, String descriptor) {
    if (!VM.runningVM) {
        // avoid compiling this code into the boot image
        try {
            TypeReference klassTRef = TypeReference.findOrCreate(klass);
            RVMClass cls = klassTRef.resolve().asClass();
            cls.resolve();
            Atom memName = Atom.findOrCreateAsciiAtom(member);
            Atom memDescriptor = Atom.findOrCreateAsciiAtom(descriptor);
            NormalMethod m = (NormalMethod) cls.findDeclaredMethod(memName, memDescriptor);
            if (m != null) {
                verifyPresenceOfEntrypointAnnotation(m);
                m.setRuntimeServiceMethod(true);
                return m;
            }
        } catch (Throwable t) {
            throw new Error("Entrypoints.getField: can't resolve class=" + klass + " member=" + member + " desc=" + descriptor, t);
        }
    }
    throw new Error("Entrypoints.getMethod: can't resolve class=" + klass + " method=" + member + " desc=" + descriptor);
}
Also used : NormalMethod(org.jikesrvm.classloader.NormalMethod) TypeReference(org.jikesrvm.classloader.TypeReference) Atom(org.jikesrvm.classloader.Atom) RVMClass(org.jikesrvm.classloader.RVMClass)

Example 12 with Atom

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

the class MainThread method run.

/**
 * Run "main" thread.
 * <p>
 * This code could be made a little shorter by relying on Reflection
 * to do the classloading and compilation.  We intentionally do it here
 * to give us a chance to provide error messages that are specific to
 * not being able to find the main class the user wants to run.
 * This may be a little silly, since it results in code duplication
 * just to provide debug messages in a place where very little is actually
 * likely to go wrong, but there you have it....
 */
@Override
@Entrypoint
public void run() {
    launched = true;
    if (dbg)
        VM.sysWriteln("MainThread.run() starting ");
    // Set up application class loader
    ClassLoader cl = RVMClassLoader.getApplicationClassLoader();
    setContextClassLoader(cl);
    runAgents(cl);
    if (dbg)
        VM.sysWrite("[MainThread.run() loading class to run... ");
    // find method to run
    // load class specified by args[0]
    RVMClass cls = null;
    try {
        Atom mainAtom = Atom.findOrCreateUnicodeAtom(args[0]);
        TypeReference mainClass = TypeReference.findOrCreate(cl, mainAtom.descriptorFromClassName());
        cls = mainClass.resolve().asClass();
        cls.prepareForFirstUse();
    } catch (NoClassDefFoundError e) {
        if (dbg)
            VM.sysWrite("failed.]");
        // no such class
        VM.sysWriteln(e.toString());
        return;
    }
    if (dbg)
        VM.sysWriteln("loaded.]");
    // find "main" method
    // 
    mainMethod = cls.findMainMethod();
    if (mainMethod == null) {
        // no such method
        VM.sysWriteln(cls + " doesn't have a \"public static void main(String[])\" method to execute");
        return;
    }
    if (dbg)
        VM.sysWrite("[MainThread.run() making arg list... ");
    // create "main" argument list
    // 
    String[] mainArgs = new String[args.length - 1];
    for (int i = 0, n = mainArgs.length; i < n; ++i) {
        mainArgs[i] = args[i + 1];
    }
    if (dbg)
        VM.sysWriteln("made.]");
    if (dbg)
        VM.sysWrite("[MainThread.run() compiling main(String[])... ");
    mainMethod.compile();
    if (dbg)
        VM.sysWriteln("compiled.]");
    // Notify other clients that the startup is complete.
    // 
    Callbacks.notifyStartup();
    if (dbg)
        VM.sysWriteln("[MainThread.run() invoking \"main\" method... ");
    // invoke "main" method with argument list
    Reflection.invoke(mainMethod, null, null, new Object[] { mainArgs }, true);
    if (dbg)
        VM.sysWriteln("  MainThread.run(): \"main\" method completed.]");
}
Also used : RVMClassLoader(org.jikesrvm.classloader.RVMClassLoader) TypeReference(org.jikesrvm.classloader.TypeReference) Atom(org.jikesrvm.classloader.Atom) Entrypoint(org.vmmagic.pragma.Entrypoint) RVMClass(org.jikesrvm.classloader.RVMClass) Entrypoint(org.vmmagic.pragma.Entrypoint)

Example 13 with Atom

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

the class GenerateMachineSpecificMagic method generateMagic.

/**
 * "Semantic inlining" of methods of the Magic class.
 * Based on the methodName, generate a sequence of opt instructions
 * that implement the magic, updating the stack as necessary
 *
 * @param bc2ir the bc2ir object generating the ir containing this magic
 * @param gc == bc2ir.gc
 * @param meth the RVMMethod that is the magic method
 * @return {@code true} if and only if magic was generated
 */
public static boolean generateMagic(BC2IR bc2ir, GenerationContext gc, MethodReference meth) throws MagicNotImplementedException {
    Atom methodName = meth.getName();
    PhysicalRegisterSet phys = gc.getTemps().getPhysicalRegisterSet().asIA32();
    if (methodName == MagicNames.getESIAsThread) {
        RegisterOperand rop = gc.getTemps().makeTROp();
        bc2ir.markGuardlessNonNull(rop);
        bc2ir.push(rop);
    } else if (methodName == MagicNames.setESIAsThread) {
        Operand val = bc2ir.popRef();
        if (val instanceof RegisterOperand) {
            bc2ir.appendInstruction(Move.create(REF_MOVE, gc.getTemps().makeTROp(), val));
        } else {
            String msg = " Unexpected operand Magic.setESIAsThread";
            throw MagicNotImplementedException.UNEXPECTED(msg);
        }
    } else if (methodName == MagicNames.getFramePointer) {
        gc.forceFrameAllocation();
        RegisterOperand val = gc.getTemps().makeTemp(TypeReference.Address);
        RVMField f = ArchEntrypoints.framePointerField;
        RegisterOperand pr = new RegisterOperand(phys.getESI(), TypeReference.Address);
        bc2ir.appendInstruction(GetField.create(GETFIELD, val, pr.copy(), new AddressConstantOperand(f.getOffset()), new LocationOperand(f), new TrueGuardOperand()));
        bc2ir.push(val.copyD2U());
    } else if (methodName == MagicNames.getJTOC || methodName == MagicNames.getTocPointer) {
        TypeReference t = (methodName == MagicNames.getJTOC ? TypeReference.IntArray : TypeReference.Address);
        RegisterOperand val = gc.getTemps().makeTemp(t);
        AddressConstantOperand addr = new AddressConstantOperand(Magic.getTocPointer());
        bc2ir.appendInstruction(Move.create(REF_MOVE, val, addr));
        bc2ir.push(val.copyD2U());
    } else if (methodName == MagicNames.synchronizeInstructionCache) {
    // nothing required on Intel
    } else if (methodName == MagicNames.prefetch) {
        bc2ir.appendInstruction(CacheOp.create(PREFETCH, bc2ir.popAddress()));
    } else if (methodName == MagicNames.pause) {
        bc2ir.appendInstruction(Empty.create(PAUSE));
    } else if (methodName == MagicNames.illegalInstruction) {
        bc2ir.appendInstruction(Empty.create(ILLEGAL_INSTRUCTION));
    } else if (methodName == MagicNames.getCallerFramePointer) {
        Operand fp = bc2ir.popAddress();
        RegisterOperand val = gc.getTemps().makeTemp(TypeReference.Address);
        bc2ir.appendInstruction(Load.create(REF_LOAD, val, fp, offsetOperand(STACKFRAME_FRAME_POINTER_OFFSET), null));
        bc2ir.push(val.copyD2U());
    } else if (methodName == MagicNames.setCallerFramePointer) {
        Operand val = bc2ir.popAddress();
        Operand fp = bc2ir.popAddress();
        bc2ir.appendInstruction(Store.create(REF_STORE, val, fp, offsetOperand(STACKFRAME_FRAME_POINTER_OFFSET), null));
    } else if (methodName == MagicNames.getCompiledMethodID) {
        Operand fp = bc2ir.popAddress();
        RegisterOperand val = gc.getTemps().makeTempInt();
        bc2ir.appendInstruction(Load.create(INT_LOAD, val, fp, offsetOperand(STACKFRAME_METHOD_ID_OFFSET), null));
        bc2ir.push(val.copyD2U());
    } else if (methodName == MagicNames.setCompiledMethodID) {
        Operand val = bc2ir.popInt();
        Operand fp = bc2ir.popAddress();
        bc2ir.appendInstruction(Store.create(INT_STORE, val, fp, offsetOperand(STACKFRAME_METHOD_ID_OFFSET), null));
    } else if (methodName == MagicNames.getReturnAddressLocation) {
        Operand fp = bc2ir.popAddress();
        Instruction s = bc2ir._binaryHelper(REF_ADD, fp, offsetOperand(STACKFRAME_RETURN_ADDRESS_OFFSET), TypeReference.Address);
        bc2ir.appendInstruction(s);
    } else {
        // Distinguish between magics that we know we don't implement
        // (and never plan to implement) and those (usually new ones)
        // that we want to be warned that we don't implement.
        String msg = " Magic method not implemented: " + meth;
        if (methodName == MagicNames.returnToNewStack) {
            throw MagicNotImplementedException.EXPECTED(msg);
        } else {
            return false;
        // throw MagicNotImplementedException.UNEXPECTED(msg);
        }
    }
    return true;
}
Also used : LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) AddressConstantOperand(org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) TrueGuardOperand(org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand) LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) IRTools.offsetOperand(org.jikesrvm.compilers.opt.ir.IRTools.offsetOperand) AddressConstantOperand(org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand) PhysicalRegisterSet(org.jikesrvm.compilers.opt.ir.ia32.PhysicalRegisterSet) RVMField(org.jikesrvm.classloader.RVMField) TypeReference(org.jikesrvm.classloader.TypeReference) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) Atom(org.jikesrvm.classloader.Atom) TrueGuardOperand(org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand)

Example 14 with Atom

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

the class GenerateMagic method generateMagic.

/**
 * "Semantic inlining" of methods of the Magic class.
 * Based on the methodName, generate a sequence of opt instructions
 * that implement the magic, updating the expression stack as necessary.
 *
 * @param bc2ir the bc2ir object that is generating the
 *              ir containing this magic
 * @param gc must be bc2ir.gc
 * @param meth the RVMMethod that is the magic method
 * @return {@code true} if and only if magic was generated
 */
static boolean generateMagic(BC2IR bc2ir, GenerationContext gc, MethodReference meth) throws MagicNotImplementedException {
    if (gc.getMethod().hasNoInlinePragma())
        gc.forceFrameAllocation();
    Atom methodName = meth.getName();
    boolean address = (meth.getType() == TypeReference.Address);
    // Address magic
    TypeReference[] types = meth.getParameterTypes();
    TypeReference returnType = meth.getReturnType();
    if (address && isLoad(methodName)) {
        // LOAD
        Operand offset = (types.length == 0) ? AC(Address.zero()) : bc2ir.popAddress();
        Operand base = bc2ir.popAddress();
        RegisterOperand result = gc.getTemps().makeTemp(returnType);
        bc2ir.appendInstruction(Load.create(getOperator(returnType, LOAD_OP), result, base, offset, null));
        bc2ir.push(result.copyD2U(), returnType);
    } else if (address && isPrepare(methodName)) {
        // PREPARE
        Operand offset = (types.length == 0) ? AC(Address.zero()) : bc2ir.popAddress();
        Operand base = bc2ir.popAddress();
        RegisterOperand result = gc.getTemps().makeTemp(returnType);
        bc2ir.appendInstruction(Prepare.create(getOperator(returnType, PREPARE_OP), result, base, offset, null));
        bc2ir.push(result.copyD2U(), returnType);
    } else if (address && methodName == MagicNames.attempt) {
        // ATTEMPT
        TypeReference attemptType = types[0];
        Operand offset = (types.length == 2) ? AC(Address.zero()) : bc2ir.popAddress();
        Operand newVal = bc2ir.pop();
        Operand oldVal = bc2ir.pop();
        Operand base = bc2ir.popAddress();
        RegisterOperand test = gc.getTemps().makeTempInt();
        bc2ir.appendInstruction(Attempt.create(getOperator(attemptType, ATTEMPT_OP), test, base, offset, oldVal, newVal, null));
        bc2ir.push(test.copyD2U(), returnType);
    } else if (address && methodName == MagicNames.store) {
        // STORE
        TypeReference storeType = types[0];
        Operand offset = (types.length == 1) ? AC(Address.zero()) : bc2ir.popAddress();
        Operand val = bc2ir.pop(storeType);
        Operand base = bc2ir.popAddress();
        bc2ir.appendInstruction(Store.create(getOperator(storeType, STORE_OP), val, base, offset, null));
    } else if (methodName == MagicNames.getThreadRegister) {
        RegisterOperand rop = gc.getTemps().makeTROp();
        bc2ir.markGuardlessNonNull(rop);
        bc2ir.push(rop);
    } else if (methodName == MagicNames.setThreadRegister) {
        Operand val = bc2ir.popRef();
        if (val instanceof RegisterOperand) {
            bc2ir.appendInstruction(Move.create(REF_MOVE, gc.getTemps().makeTROp(), val));
        } else {
            String msg = " Unexpected operand Magic.setThreadRegister";
            throw MagicNotImplementedException.UNEXPECTED(msg);
        }
    } else if (methodName == MagicNames.addressArrayCreate) {
        Instruction s = bc2ir.generateAnewarray(null, meth.getType().getArrayElementType());
        bc2ir.appendInstruction(s);
    } else if (methodName == MagicNames.addressArrayLength) {
        Operand op1 = bc2ir.pop();
        bc2ir.clearCurrentGuard();
        if (bc2ir.do_NullCheck(op1)) {
            return true;
        }
        RegisterOperand t = gc.getTemps().makeTempInt();
        Instruction s = GuardedUnary.create(ARRAYLENGTH, t, op1, bc2ir.getCurrentGuard());
        bc2ir.push(t.copyD2U());
        bc2ir.appendInstruction(s);
    } else if (methodName == MagicNames.addressArrayGet) {
        TypeReference elementType = meth.getReturnType();
        Operand index = bc2ir.popInt();
        Operand ref = bc2ir.popRef();
        RegisterOperand offsetI = gc.getTemps().makeTempInt();
        RegisterOperand offset = gc.getTemps().makeTempOffset();
        RegisterOperand result;
        if (meth.getType().isCodeArrayType()) {
            if (VM.BuildForIA32) {
                result = gc.getTemps().makeTemp(TypeReference.Byte);
                bc2ir.appendInstruction(Load.create(BYTE_LOAD, result, ref, index, new LocationOperand(elementType), new TrueGuardOperand()));
            } else if (VM.BuildForPowerPC) {
                result = gc.getTemps().makeTemp(TypeReference.Int);
                bc2ir.appendInstruction(Binary.create(INT_SHL, offsetI, index, new IntConstantOperand(LOG_BYTES_IN_INT)));
                bc2ir.appendInstruction(Unary.create(INT_2ADDRZerExt, offset, offsetI.copy()));
                bc2ir.appendInstruction(Load.create(INT_LOAD, result, ref, offset.copy(), new LocationOperand(elementType), new TrueGuardOperand()));
            }
        } else {
            result = gc.getTemps().makeTemp(elementType);
            bc2ir.appendInstruction(Binary.create(INT_SHL, offsetI, index, new IntConstantOperand(LOG_BYTES_IN_ADDRESS)));
            bc2ir.appendInstruction(Unary.create(INT_2ADDRZerExt, offset, offsetI.copy()));
            bc2ir.appendInstruction(Load.create(REF_LOAD, result, ref, offset.copy(), new LocationOperand(elementType), new TrueGuardOperand()));
        }
        bc2ir.push(result.copyD2U());
    } else if (methodName == MagicNames.addressArraySet) {
        TypeReference elementType = meth.getParameterTypes()[1];
        Operand val = bc2ir.pop();
        Operand index = bc2ir.popInt();
        Operand ref = bc2ir.popRef();
        RegisterOperand offsetI = gc.getTemps().makeTempInt();
        RegisterOperand offset = gc.getTemps().makeTempOffset();
        if (meth.getType().isCodeArrayType()) {
            if (VM.BuildForIA32) {
                bc2ir.appendInstruction(Store.create(BYTE_STORE, val, ref, index, new LocationOperand(elementType), new TrueGuardOperand()));
            } else if (VM.BuildForPowerPC) {
                bc2ir.appendInstruction(Binary.create(INT_SHL, offsetI, index, new IntConstantOperand(LOG_BYTES_IN_INT)));
                bc2ir.appendInstruction(Unary.create(INT_2ADDRZerExt, offset, offsetI.copy()));
                bc2ir.appendInstruction(Store.create(INT_STORE, val, ref, offset.copy(), new LocationOperand(elementType), new TrueGuardOperand()));
            }
        } else {
            bc2ir.appendInstruction(Binary.create(INT_SHL, offsetI, index, new IntConstantOperand(LOG_BYTES_IN_ADDRESS)));
            bc2ir.appendInstruction(Unary.create(INT_2ADDRZerExt, offset, offsetI.copy()));
            bc2ir.appendInstruction(Store.create(REF_STORE, val, ref, offset.copy(), new LocationOperand(elementType), new TrueGuardOperand()));
        }
    } else if (methodName == MagicNames.getIntAtOffset) {
        Operand offset = bc2ir.popAddress();
        Operand object = bc2ir.popRef();
        RegisterOperand val = gc.getTemps().makeTempInt();
        bc2ir.appendInstruction(Load.create(INT_LOAD, val, object, offset, null));
        bc2ir.push(val.copyD2U());
    } else if (methodName == MagicNames.setIntAtOffset) {
        LocationOperand loc = null;
        if (meth.getParameterTypes().length == 4) {
            loc = mapToMetadata(bc2ir.popInt());
        }
        Operand val = bc2ir.popInt();
        Operand offset = bc2ir.popAddress();
        Operand object = bc2ir.popRef();
        bc2ir.appendInstruction(Store.create(INT_STORE, val, object, offset, loc));
    } else if (methodName == MagicNames.getFloatAtOffset) {
        Operand offset = bc2ir.popAddress();
        Operand object = bc2ir.popRef();
        RegisterOperand val = gc.getTemps().makeTempFloat();
        bc2ir.appendInstruction(Load.create(FLOAT_LOAD, val, object, offset, null));
        bc2ir.push(val.copyD2U());
    } else if (methodName == MagicNames.setFloatAtOffset) {
        LocationOperand loc = null;
        if (meth.getParameterTypes().length == 4) {
            loc = mapToMetadata(bc2ir.popInt());
        }
        Operand val = bc2ir.popFloat();
        Operand offset = bc2ir.popAddress();
        Operand object = bc2ir.popRef();
        bc2ir.appendInstruction(Store.create(FLOAT_STORE, val, object, offset, loc));
    } else if (methodName == MagicNames.getWordAtOffset) {
        LocationOperand loc = null;
        if (meth.getParameterTypes().length == 3) {
            loc = mapToMetadata(bc2ir.popInt());
        }
        Operand offset = bc2ir.popAddress();
        Operand object = bc2ir.popRef();
        RegisterOperand val = gc.getTemps().makeTemp(TypeReference.Word);
        bc2ir.appendInstruction(Load.create(REF_LOAD, val, object, offset, loc));
        bc2ir.push(val.copyD2U());
    } else if (methodName == MagicNames.getAddressAtOffset) {
        LocationOperand loc = null;
        if (meth.getParameterTypes().length == 3) {
            loc = mapToMetadata(bc2ir.popInt());
        }
        Operand offset = bc2ir.popAddress();
        Operand object = bc2ir.popRef();
        RegisterOperand val = gc.getTemps().makeTemp(TypeReference.Address);
        bc2ir.appendInstruction(Load.create(REF_LOAD, val, object, offset, loc));
        bc2ir.push(val.copyD2U());
    } else if (methodName == MagicNames.getExtentAtOffset) {
        LocationOperand loc = null;
        if (meth.getParameterTypes().length == 3) {
            loc = mapToMetadata(bc2ir.popInt());
        }
        Operand offset = bc2ir.popAddress();
        Operand object = bc2ir.popRef();
        RegisterOperand val = gc.getTemps().makeTemp(TypeReference.Extent);
        bc2ir.appendInstruction(Load.create(REF_LOAD, val, object, offset, loc));
        bc2ir.push(val.copyD2U());
    } else if (methodName == MagicNames.getOffsetAtOffset) {
        LocationOperand loc = null;
        if (meth.getParameterTypes().length == 3) {
            loc = mapToMetadata(bc2ir.popInt());
        }
        Operand offset = bc2ir.popAddress();
        Operand object = bc2ir.popRef();
        RegisterOperand val = gc.getTemps().makeTemp(TypeReference.Offset);
        bc2ir.appendInstruction(Load.create(REF_LOAD, val, object, offset, loc));
        bc2ir.push(val.copyD2U());
    } else if (methodName == MagicNames.setWordAtOffset || methodName == MagicNames.setAddressAtOffset || methodName == MagicNames.setOffsetAtOffset || methodName == MagicNames.setExtentAtOffset) {
        LocationOperand loc = null;
        if (meth.getParameterTypes().length == 4) {
            loc = mapToMetadata(bc2ir.popInt());
        }
        Operand val = bc2ir.popRef();
        Operand offset = bc2ir.popAddress();
        Operand object = bc2ir.popRef();
        bc2ir.appendInstruction(Store.create(REF_STORE, val, object, offset, loc));
    } else if (methodName == MagicNames.getLongAtOffset) {
        Operand offset = bc2ir.popAddress();
        Operand object = bc2ir.popRef();
        RegisterOperand val = gc.getTemps().makeTempLong();
        bc2ir.appendInstruction(Load.create(LONG_LOAD, val, object, offset, null));
        bc2ir.pushDual(val.copyD2U());
    } else if (methodName == MagicNames.setLongAtOffset) {
        LocationOperand loc = null;
        if (meth.getParameterTypes().length == 4) {
            loc = mapToMetadata(bc2ir.popInt());
        }
        Operand val = bc2ir.popLong();
        Operand offset = bc2ir.popAddress();
        Operand object = bc2ir.popRef();
        bc2ir.appendInstruction(Store.create(LONG_STORE, val, object, offset, loc));
    } else if (methodName == MagicNames.getDoubleAtOffset) {
        Operand offset = bc2ir.popAddress();
        Operand object = bc2ir.popRef();
        RegisterOperand val = gc.getTemps().makeTempDouble();
        bc2ir.appendInstruction(Load.create(DOUBLE_LOAD, val, object, offset, null));
        bc2ir.pushDual(val.copyD2U());
    } else if (methodName == MagicNames.setDoubleAtOffset) {
        LocationOperand loc = null;
        if (meth.getParameterTypes().length == 4) {
            loc = mapToMetadata(bc2ir.popInt());
        }
        Operand val = bc2ir.popDouble();
        Operand offset = bc2ir.popAddress();
        Operand object = bc2ir.popRef();
        bc2ir.appendInstruction(Store.create(DOUBLE_STORE, val, object, offset, loc));
    } else if (methodName == MagicNames.getObjectAtOffset) {
        LocationOperand loc = null;
        if (meth.getParameterTypes().length == 3) {
            loc = mapToMetadata(bc2ir.popInt());
        }
        Operand offset = bc2ir.popAddress();
        Operand object = bc2ir.popRef();
        RegisterOperand val = gc.getTemps().makeTemp(TypeReference.JavaLangObject);
        bc2ir.appendInstruction(Load.create(REF_LOAD, val, object, offset, loc));
        bc2ir.push(val.copyD2U());
    } else if (methodName == MagicNames.getTIBAtOffset) {
        Operand offset = bc2ir.popAddress();
        Operand object = bc2ir.popRef();
        RegisterOperand val = gc.getTemps().makeTemp(TypeReference.TIB);
        bc2ir.appendInstruction(Load.create(REF_LOAD, val, object, offset, null));
        bc2ir.push(val.copyD2U());
    } else if (methodName == MagicNames.setObjectAtOffset) {
        LocationOperand loc = null;
        if (meth.getParameterTypes().length == 4) {
            loc = mapToMetadata(bc2ir.popInt());
        }
        Operand val = bc2ir.popRef();
        Operand offset = bc2ir.popAddress();
        Operand object = bc2ir.popRef();
        bc2ir.appendInstruction(Store.create(REF_STORE, val, object, offset, loc));
    } else if (methodName == MagicNames.getByteAtOffset) {
        Operand offset = bc2ir.popAddress();
        Operand object = bc2ir.popRef();
        RegisterOperand val = gc.getTemps().makeTemp(TypeReference.Byte);
        bc2ir.appendInstruction(Load.create(BYTE_LOAD, val, object, offset, null));
        bc2ir.push(val.copyD2U());
    } else if (methodName == MagicNames.getUnsignedByteAtOffset) {
        Operand offset = bc2ir.popAddress();
        Operand object = bc2ir.popRef();
        RegisterOperand val = gc.getTemps().makeTemp(TypeReference.Byte);
        bc2ir.appendInstruction(Load.create(UBYTE_LOAD, val, object, offset, null));
        bc2ir.push(val.copyD2U());
    } else if (methodName == MagicNames.setByteAtOffset || methodName == MagicNames.setBooleanAtOffset) {
        LocationOperand loc = null;
        if (meth.getParameterTypes().length == 4) {
            loc = mapToMetadata(bc2ir.popInt());
        }
        Operand val = bc2ir.popInt();
        Operand offset = bc2ir.popAddress();
        Operand object = bc2ir.popRef();
        bc2ir.appendInstruction(Store.create(BYTE_STORE, val, object, offset, loc));
    } else if (methodName == MagicNames.getShortAtOffset) {
        Operand offset = bc2ir.popAddress();
        Operand object = bc2ir.popRef();
        RegisterOperand val = gc.getTemps().makeTemp(TypeReference.Char);
        bc2ir.appendInstruction(Load.create(SHORT_LOAD, val, object, offset, null));
        bc2ir.push(val.copyD2U());
    } else if (methodName == MagicNames.getCharAtOffset) {
        Operand offset = bc2ir.popAddress();
        Operand object = bc2ir.popRef();
        RegisterOperand val = gc.getTemps().makeTemp(TypeReference.Char);
        bc2ir.appendInstruction(Load.create(USHORT_LOAD, val, object, offset, null));
        bc2ir.push(val.copyD2U());
    } else if (methodName == MagicNames.setCharAtOffset || methodName == MagicNames.setShortAtOffset) {
        LocationOperand loc = null;
        if (meth.getParameterTypes().length == 4) {
            loc = mapToMetadata(bc2ir.popInt());
        }
        Operand val = bc2ir.popInt();
        Operand offset = bc2ir.popAddress();
        Operand object = bc2ir.popRef();
        bc2ir.appendInstruction(Store.create(SHORT_STORE, val, object, offset, loc));
    } else if (methodName == MagicNames.getMemoryInt) {
        Operand memAddr = bc2ir.popAddress();
        RegisterOperand val = gc.getTemps().makeTempInt();
        bc2ir.appendInstruction(Load.create(INT_LOAD, val, memAddr, AC(Offset.zero()), null));
        bc2ir.push(val.copyD2U());
    } else if (methodName == MagicNames.getMemoryWord) {
        Operand memAddr = bc2ir.popAddress();
        RegisterOperand val = gc.getTemps().makeTemp(TypeReference.Word);
        bc2ir.appendInstruction(Load.create(REF_LOAD, val, memAddr, AC(Offset.zero()), null));
        bc2ir.push(val.copyD2U());
    } else if (methodName == MagicNames.getMemoryAddress) {
        Operand memAddr = bc2ir.popAddress();
        RegisterOperand val = gc.getTemps().makeTemp(TypeReference.Address);
        bc2ir.appendInstruction(Load.create(REF_LOAD, val, memAddr, AC(Offset.zero()), null));
        bc2ir.push(val.copyD2U());
    } else if (methodName == MagicNames.setMemoryInt) {
        Operand val = bc2ir.popInt();
        Operand memAddr = bc2ir.popAddress();
        bc2ir.appendInstruction(Store.create(INT_STORE, val, memAddr, AC(Offset.zero()), null));
    } else if (methodName == MagicNames.setMemoryWord) {
        Operand val = bc2ir.popRef();
        Operand memAddr = bc2ir.popAddress();
        bc2ir.appendInstruction(Store.create(REF_STORE, val, memAddr, AC(Offset.zero()), null));
    } else if (meth.isSysCall()) {
        // All methods of SysCall have the following signature:
        // callNAME(Address functionAddress, <var args to pass via native calling convention>)
        // With 64 bit PowerPC ELF ABI, functionAddress points to the function descriptor
        TypeReference[] args = meth.getParameterTypes();
        Instruction call = Call.create(SYSCALL, null, null, null, null, args.length - 1);
        for (int i = args.length - 1; i >= 1; i--) {
            Call.setParam(call, i - 1, bc2ir.pop(args[i]));
        }
        Operand functionAddress = bc2ir.pop(args[0]);
        Call.setAddress(call, functionAddress);
        if (!returnType.isVoidType()) {
            RegisterOperand op0 = gc.getTemps().makeTemp(returnType);
            Call.setResult(call, op0);
            bc2ir.push(op0.copyD2U(), returnType);
        }
        Call.setMethod(call, MethodOperand.STATIC(meth, meth.peekResolvedMethod()));
        bc2ir.appendInstruction(call);
    } else if (meth.isSpecializedInvoke()) {
        // The callsite looks like              RETURN = INVOKE (ID, OBJECT, P0, P1 .. PN)
        // And the actual method will look like RETURN = INVOKE     (OBJECT, P0, P1 .. PN)
        // Create the call instruction
        Instruction call = Call.create(CALL, null, null, null, null, types.length - 1);
        // Plumb all of the normal parameters into the call
        for (int i = types.length - 1; i >= 2; i--) {
            Call.setParam(call, i - 1, bc2ir.pop(types[i]));
        }
        // The object being specialized
        Operand objectOperand = bc2ir.pop(types[1]);
        Call.setParam(call, 0, objectOperand);
        Operand guard = BC2IR.copyGuardFromOperand(objectOperand);
        if (guard == null) {
            // it's magic, so assume that it's OK....
            guard = new TrueGuardOperand();
        }
        Call.setGuard(call, guard);
        // Load the tib of this object
        RegisterOperand tibObject = gc.getTemps().makeTemp(TypeReference.TIB);
        bc2ir.appendInstruction(GuardedUnary.create(GET_OBJ_TIB, tibObject, objectOperand.copy(), guard.copy()));
        // The index of the specialized method
        Operand methodId = bc2ir.popInt();
        // Add the base offset for specialized methods and convert from index to address
        RegisterOperand tibOffset = gc.getTemps().makeTemp(TypeReference.Int);
        bc2ir.appendInstruction(Binary.create(INT_ADD, tibOffset, methodId, new IntConstantOperand(TIB_FIRST_SPECIALIZED_METHOD_INDEX)));
        bc2ir.appendInstruction(Binary.create(INT_SHL, tibOffset.copyRO(), tibOffset.copyD2U(), new IntConstantOperand(LOG_BYTES_IN_ADDRESS)));
        // Load the code address from the TIB
        RegisterOperand codeAddress = gc.getTemps().makeTemp(TypeReference.Address);
        bc2ir.appendInstruction(Load.create(REF_LOAD, codeAddress, tibObject.copyD2U(), tibOffset.copyD2U(), null));
        Call.setAddress(call, codeAddress.copyD2U());
        if (!returnType.isVoidType()) {
            RegisterOperand op0 = gc.getTemps().makeTemp(returnType);
            Call.setResult(call, op0);
            bc2ir.push(op0.copyD2U(), returnType);
        }
        bc2ir.appendInstruction(call);
    } else if (methodName == MagicNames.objectAsType) {
        RegisterOperand reg = gc.getTemps().makeTemp(TypeReference.Type);
        bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popRef()));
        bc2ir.push(reg.copyD2U());
    } else if (methodName == MagicNames.objectAsThread) {
        RegisterOperand reg = gc.getTemps().makeTemp(TypeReference.Thread);
        bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popRef()));
        bc2ir.push(reg.copyD2U());
    } else if (methodName == MagicNames.objectAsAddress) {
        RegisterOperand reg = gc.getTemps().makeTemp(TypeReference.Address);
        bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popRef()));
        bc2ir.push(reg.copyD2U());
    } else if (methodName == MagicNames.addressAsObject) {
        RegisterOperand reg = gc.getTemps().makeTemp(TypeReference.JavaLangObject);
        bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popAddress()));
        bc2ir.push(reg.copyD2U());
    } else if (methodName == MagicNames.addressAsTIB) {
        RegisterOperand reg = gc.getTemps().makeTemp(TypeReference.TIB);
        bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popAddress()));
        bc2ir.push(reg.copyD2U());
    } else if (methodName == MagicNames.addressAsByteArray) {
        RegisterOperand reg = gc.getTemps().makeTemp(TypeReference.ByteArray);
        bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popAddress()));
        bc2ir.push(reg.copyD2U());
    } else if (methodName == MagicNames.objectAsShortArray) {
        RegisterOperand reg = gc.getTemps().makeTemp(TypeReference.ShortArray);
        bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popRef()));
        bc2ir.push(reg.copyD2U());
    } else if (methodName == MagicNames.objectAsIntArray) {
        RegisterOperand reg = gc.getTemps().makeTemp(TypeReference.IntArray);
        bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popRef()));
        bc2ir.push(reg.copyD2U());
    } else if (methodName == MagicNames.floatAsIntBits) {
        Operand val = bc2ir.popFloat();
        RegisterOperand op0 = gc.getTemps().makeTempInt();
        bc2ir.appendInstruction(Unary.create(FLOAT_AS_INT_BITS, op0, val));
        bc2ir.push(op0.copyD2U());
    } else if (methodName == MagicNames.intBitsAsFloat) {
        Operand val = bc2ir.popInt();
        RegisterOperand op0 = gc.getTemps().makeTempFloat();
        bc2ir.appendInstruction(Unary.create(INT_BITS_AS_FLOAT, op0, val));
        bc2ir.push(op0.copyD2U());
    } else if (methodName == MagicNames.doubleAsLongBits) {
        Operand val = bc2ir.popDouble();
        RegisterOperand op0 = gc.getTemps().makeTempLong();
        bc2ir.appendInstruction(Unary.create(DOUBLE_AS_LONG_BITS, op0, val));
        bc2ir.pushDual(op0.copyD2U());
    } else if (methodName == MagicNames.longBitsAsDouble) {
        Operand val = bc2ir.popLong();
        RegisterOperand op0 = gc.getTemps().makeTempDouble();
        bc2ir.appendInstruction(Unary.create(LONG_BITS_AS_DOUBLE, op0, val));
        bc2ir.pushDual(op0.copyD2U());
    } else if (methodName == MagicNames.sqrt) {
        TypeReference[] args = meth.getParameterTypes();
        if (args[0] == TypeReference.Float) {
            Operand val = bc2ir.popFloat();
            RegisterOperand op0 = gc.getTemps().makeTempFloat();
            bc2ir.appendInstruction(Unary.create(FLOAT_SQRT, op0, val));
            bc2ir.push(op0.copyD2U());
        } else if (args[0] == TypeReference.Double) {
            Operand val = bc2ir.popDouble();
            RegisterOperand op0 = gc.getTemps().makeTempDouble();
            bc2ir.appendInstruction(Unary.create(DOUBLE_SQRT, op0, val));
            bc2ir.pushDual(op0.copyD2U());
        } else {
            if (VM.VerifyAssertions)
                VM._assert(VM.NOT_REACHED, "SQRT only handles Double or Float operands");
        }
    } else if (methodName == MagicNames.getObjectType) {
        Operand val = bc2ir.popRef();
        if (val.isObjectConstant()) {
            bc2ir.push(new ObjectConstantOperand(val.getType().peekType(), Offset.zero()));
        } else {
            Operand guard = BC2IR.copyGuardFromOperand(val);
            if (guard == null) {
                // it's magic, so assume that it's OK....
                guard = new TrueGuardOperand();
            }
            RegisterOperand tibPtr = gc.getTemps().makeTemp(TypeReference.TIB);
            bc2ir.appendInstruction(GuardedUnary.create(GET_OBJ_TIB, tibPtr, val, guard));
            RegisterOperand op0;
            TypeReference argType = val.getType();
            if (argType.isArrayType()) {
                op0 = gc.getTemps().makeTemp(TypeReference.RVMArray);
            } else {
                if (argType == TypeReference.JavaLangObject || argType == TypeReference.JavaLangCloneable || argType == TypeReference.JavaIoSerializable) {
                    // could be an array or a class, so make op0 be a RVMType
                    op0 = gc.getTemps().makeTemp(TypeReference.Type);
                } else {
                    op0 = gc.getTemps().makeTemp(TypeReference.Class);
                }
            }
            bc2ir.markGuardlessNonNull(op0);
            bc2ir.appendInstruction(Unary.create(GET_TYPE_FROM_TIB, op0, tibPtr.copyD2U()));
            bc2ir.push(op0.copyD2U());
        }
    } else if (methodName == MagicNames.getArrayLength) {
        Operand val = bc2ir.popRef();
        RegisterOperand op0 = gc.getTemps().makeTempInt();
        bc2ir.appendInstruction(GuardedUnary.create(ARRAYLENGTH, op0, val, new TrueGuardOperand()));
        bc2ir.push(op0.copyD2U());
    } else if (methodName == MagicNames.invokeClassInitializer) {
        Instruction s = Call.create0(CALL, null, bc2ir.popRef(), null);
        bc2ir.appendInstruction(s);
    } else if ((methodName == MagicNames.invokeMethodReturningObject) || (methodName == MagicNames.invokeMethodReturningVoid) || (methodName == MagicNames.invokeMethodReturningLong) || (methodName == MagicNames.invokeMethodReturningDouble) || (methodName == MagicNames.invokeMethodReturningFloat) || (methodName == MagicNames.invokeMethodReturningInt)) {
        Operand spills = bc2ir.popRef();
        Operand fprmeta = bc2ir.popRef();
        Operand fprs = bc2ir.popRef();
        Operand gprs = bc2ir.popRef();
        Operand code = bc2ir.popRef();
        RegisterOperand res = null;
        if (methodName == MagicNames.invokeMethodReturningObject) {
            res = gc.getTemps().makeTemp(TypeReference.JavaLangObject);
            bc2ir.push(res.copyD2U());
        } else if (methodName == MagicNames.invokeMethodReturningLong) {
            res = gc.getTemps().makeTemp(TypeReference.Long);
            bc2ir.push(res.copyD2U(), TypeReference.Long);
        } else if (methodName == MagicNames.invokeMethodReturningDouble) {
            res = gc.getTemps().makeTempDouble();
            bc2ir.push(res.copyD2U(), TypeReference.Double);
        } else if (methodName == MagicNames.invokeMethodReturningFloat) {
            res = gc.getTemps().makeTempFloat();
            bc2ir.push(res.copyD2U(), TypeReference.Float);
        } else if (methodName == MagicNames.invokeMethodReturningInt) {
            res = gc.getTemps().makeTempInt();
            bc2ir.push(res.copyD2U());
        }
        RVMField target = ArchEntrypoints.reflectiveMethodInvokerInstructionsField;
        MethodOperand met = MethodOperand.STATIC(target);
        Instruction s = Call.create5(CALL, res, AC(target.getOffset()), met, code, gprs, fprs, fprmeta, spills);
        bc2ir.appendInstruction(s);
    } else if (methodName == MagicNames.saveThreadState) {
        Operand p1 = bc2ir.popRef();
        RVMField target = ArchEntrypoints.saveThreadStateInstructionsField;
        MethodOperand mo = MethodOperand.STATIC(target);
        bc2ir.appendInstruction(Call.create1(CALL, null, AC(target.getOffset()), mo, p1));
    } else if (methodName == MagicNames.threadSwitch) {
        Operand p2 = bc2ir.popRef();
        Operand p1 = bc2ir.popRef();
        RVMField target = ArchEntrypoints.threadSwitchInstructionsField;
        MethodOperand mo = MethodOperand.STATIC(target);
        bc2ir.appendInstruction(Call.create2(CALL, null, AC(target.getOffset()), mo, p1, p2));
    } else if (methodName == MagicNames.restoreHardwareExceptionState) {
        RVMField target = ArchEntrypoints.restoreHardwareExceptionStateInstructionsField;
        MethodOperand mo = MethodOperand.STATIC(target);
        bc2ir.appendInstruction(Call.create1(CALL, null, AC(target.getOffset()), mo, bc2ir.popRef()));
    } else if (methodName == MagicNames.prepareInt) {
        Operand offset = bc2ir.popAddress();
        Operand base = bc2ir.popRef();
        RegisterOperand val = gc.getTemps().makeTempInt();
        bc2ir.appendInstruction(Prepare.create(PREPARE_INT, val, base, offset, null));
        bc2ir.push(val.copyD2U());
    } else if (methodName == MagicNames.prepareLong) {
        Operand offset = bc2ir.popAddress();
        Operand base = bc2ir.popRef();
        RegisterOperand val = gc.getTemps().makeTempLong();
        bc2ir.appendInstruction(Prepare.create(PREPARE_LONG, val, base, offset, null));
        bc2ir.pushDual(val.copyD2U());
    } else if (methodName == MagicNames.prepareObject) {
        Operand offset = bc2ir.popAddress();
        Operand base = bc2ir.popRef();
        RegisterOperand val = gc.getTemps().makeTemp(TypeReference.JavaLangObject);
        bc2ir.appendInstruction(Prepare.create(PREPARE_ADDR, val, base, offset, null));
        bc2ir.push(val.copyD2U());
    } else if (methodName == MagicNames.prepareAddress) {
        Operand offset = bc2ir.popAddress();
        Operand base = bc2ir.popRef();
        RegisterOperand val = gc.getTemps().makeTemp(TypeReference.Address);
        bc2ir.appendInstruction(Prepare.create(PREPARE_ADDR, val, base, offset, null));
        bc2ir.push(val.copyD2U());
    } else if (methodName == MagicNames.prepareWord) {
        Operand offset = bc2ir.popAddress();
        Operand base = bc2ir.popRef();
        RegisterOperand val = gc.getTemps().makeTemp(TypeReference.Word);
        bc2ir.appendInstruction(Prepare.create(PREPARE_ADDR, val, base, offset, null));
        bc2ir.push(val.copyD2U());
    } else if (methodName == MagicNames.attemptInt) {
        Operand newVal = bc2ir.popInt();
        Operand oldVal = bc2ir.popInt();
        Operand offset = bc2ir.popAddress();
        Operand base = bc2ir.popRef();
        RegisterOperand test = gc.getTemps().makeTempBoolean();
        bc2ir.appendInstruction(Attempt.create(ATTEMPT_INT, test, base, offset, oldVal, newVal, null));
        bc2ir.push(test.copyD2U());
    } else if (methodName == MagicNames.attemptLong) {
        Operand newVal = bc2ir.popLong();
        Operand oldVal = bc2ir.popLong();
        Operand offset = bc2ir.popAddress();
        Operand base = bc2ir.popRef();
        RegisterOperand test = gc.getTemps().makeTempBoolean();
        bc2ir.appendInstruction(Attempt.create(ATTEMPT_LONG, test, base, offset, oldVal, newVal, null));
        bc2ir.push(test.copyD2U());
    } else if (methodName == MagicNames.attemptObject) {
        Operand newVal = bc2ir.popRef();
        Operand oldVal = bc2ir.popRef();
        Operand offset = bc2ir.popAddress();
        Operand base = bc2ir.popRef();
        RegisterOperand test = gc.getTemps().makeTempBoolean();
        bc2ir.appendInstruction(Attempt.create(ATTEMPT_ADDR, test, base, offset, oldVal, newVal, null));
        bc2ir.push(test.copyD2U());
    } else if (methodName == MagicNames.attemptAddress) {
        Operand newVal = bc2ir.popAddress();
        Operand oldVal = bc2ir.popAddress();
        Operand offset = bc2ir.popAddress();
        Operand base = bc2ir.popRef();
        RegisterOperand test = gc.getTemps().makeTempBoolean();
        bc2ir.appendInstruction(Attempt.create(ATTEMPT_ADDR, test, base, offset, oldVal, newVal, null));
        bc2ir.push(test.copyD2U());
    } else if (methodName == MagicNames.attemptWord) {
        Operand newVal = bc2ir.pop();
        Operand oldVal = bc2ir.pop();
        Operand offset = bc2ir.popAddress();
        Operand base = bc2ir.popRef();
        RegisterOperand test = gc.getTemps().makeTempBoolean();
        bc2ir.appendInstruction(Attempt.create(ATTEMPT_ADDR, test, base, offset, oldVal, newVal, null));
        bc2ir.push(test.copyD2U());
    } else if (methodName == MagicNames.fence) {
        bc2ir.appendInstruction(Empty.create(FENCE));
    } else if (methodName == MagicNames.combinedLoadBarrier) {
        bc2ir.appendInstruction(Empty.create(READ_CEILING));
    } else if (methodName == MagicNames.storeStoreBarrier) {
        bc2ir.appendInstruction(Empty.create(WRITE_FLOOR));
    } else if (generatePolymorphicMagic(bc2ir, gc, meth, methodName)) {
        return true;
    } else if (methodName == MagicNames.getTimeBase) {
        RegisterOperand op0 = gc.getTemps().makeTempLong();
        bc2ir.appendInstruction(Nullary.create(GET_TIME_BASE, op0));
        bc2ir.pushDual(op0.copyD2U());
    } else if (methodName == MagicNames.getInlineDepth) {
        bc2ir.push(new IntConstantOperand(gc.getInlineSequence().getInlineDepth()));
    } else if (methodName == MagicNames.getCompilerLevel) {
        bc2ir.push(new IntConstantOperand(gc.getOptions().getOptLevel()));
    } else if (methodName == MagicNames.isConstantParameter) {
        Operand requestedOperand = bc2ir.pop();
        if (!(requestedOperand instanceof IntConstantOperand)) {
            throw new OptimizingCompilerException("Must supply constant to Magic.isConstantParameter");
        }
        int requested = ((IntConstantOperand) (requestedOperand)).value;
        boolean isConstant = gc.getArguments()[requested].isConstant();
        bc2ir.push(new IntConstantOperand(isConstant ? 1 : 0));
    } else if (methodName == MagicNames.getFrameSize) {
        RegisterOperand res = gc.getTemps().makeTempInt();
        gc.forceFrameAllocation();
        bc2ir.appendInstruction(Nullary.create(FRAMESIZE, res));
        bc2ir.push(res.copyD2U());
    } else {
        // Wasn't machine-independent, so try the machine-dependent magics next.
        if (VM.BuildForIA32) {
            return org.jikesrvm.compilers.opt.bc2ir.ia32.GenerateMachineSpecificMagic.generateMagic(bc2ir, gc, meth);
        } else {
            if (VM.VerifyAssertions)
                VM._assert(VM.BuildForPowerPC);
            return org.jikesrvm.compilers.opt.bc2ir.ppc.GenerateMachineSpecificMagic.generateMagic(bc2ir, gc, meth);
        }
    }
    return true;
}
Also used : IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) MethodOperand(org.jikesrvm.compilers.opt.ir.operand.MethodOperand) TrueGuardOperand(org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) ObjectConstantOperand(org.jikesrvm.compilers.opt.ir.operand.ObjectConstantOperand) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) Atom(org.jikesrvm.classloader.Atom) TrueGuardOperand(org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand) MethodOperand(org.jikesrvm.compilers.opt.ir.operand.MethodOperand) LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) ObjectConstantOperand(org.jikesrvm.compilers.opt.ir.operand.ObjectConstantOperand) RVMField(org.jikesrvm.classloader.RVMField) TypeReference(org.jikesrvm.classloader.TypeReference) OptimizingCompilerException(org.jikesrvm.compilers.opt.OptimizingCompilerException)

Example 15 with Atom

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

Aggregations

Atom (org.jikesrvm.classloader.Atom)29 RVMClass (org.jikesrvm.classloader.RVMClass)14 RVMMethod (org.jikesrvm.classloader.RVMMethod)11 TypeReference (org.jikesrvm.classloader.TypeReference)10 RVMField (org.jikesrvm.classloader.RVMField)7 RVMType (org.jikesrvm.classloader.RVMType)5 Instruction (org.jikesrvm.compilers.opt.ir.Instruction)3 Operand (org.jikesrvm.compilers.opt.ir.operand.Operand)3 RegisterOperand (org.jikesrvm.compilers.opt.ir.operand.RegisterOperand)3 IRTools.offsetOperand (org.jikesrvm.compilers.opt.ir.IRTools.offsetOperand)2 LocationOperand (org.jikesrvm.compilers.opt.ir.operand.LocationOperand)2 TrueGuardOperand (org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand)2 Method (java.lang.reflect.Method)1 TypeVariable (java.lang.reflect.TypeVariable)1 HashSet (java.util.HashSet)1 NoSuchElementException (java.util.NoSuchElementException)1 ApplicationClassLoader (org.jikesrvm.classloader.ApplicationClassLoader)1 NativeMethod (org.jikesrvm.classloader.NativeMethod)1 NormalMethod (org.jikesrvm.classloader.NormalMethod)1 RVMArray (org.jikesrvm.classloader.RVMArray)1