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);
}
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.]");
}
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;
}
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;
}
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;
}
Aggregations