use of org.jikesrvm.classloader.RVMArray in project JikesRVM by JikesRVM.
the class BootImageWriter method createBootImageObjects.
/**
* Create (in host JDK address space) the RVM objects that will be
* needed at run time to execute enough of the virtual machine
* to dynamically load and compile the remainder of itself.<p>
*
* Side effects:
* <ul>
* <li>RVM objects are created in host JDK address space
* <li>Statics is populated
* <li>"bootImageTypes" dictionary is populated with name/type pairs
* </ul>
*
* @param typeNames names of RVM classes whose static fields will contain
* the objects comprising the virtual machine bootimage
*/
public static void createBootImageObjects(Vector<String> typeNames, String bootImageTypeNamesFile) throws IllegalAccessException {
Callbacks.notifyBootImage(typeNames.elements());
long startTime = 0;
long stopTime = 0;
//
if (verbosity.isAtLeast(SUMMARY))
say("loading");
if (profile)
startTime = System.currentTimeMillis();
for (String typeName : typeNames) {
//
if (verbosity.isAtLeast(TYPE_NAMES))
say("typeName:", typeName);
//
// create corresponding rvm type
//
RVMType type;
try {
TypeReference tRef = TypeReference.findOrCreate(typeName);
type = tRef.resolve();
} catch (NoClassDefFoundError ncdf) {
ncdf.printStackTrace(System.out);
fail(bootImageTypeNamesFile + " contains a class named \"" + typeName + "\", but we can't find a class with that name: " + ncdf);
// NOTREACHED
return;
} catch (IllegalArgumentException ila) {
/* We should've caught any illegal type names at the data validation
* stage, when we read these in. If not, though,
* TypeReference.findOrCreate() will do its own sanity check. */
ila.printStackTrace(System.out);
fail(bootImageTypeNamesFile + " is supposed to contain type names. It contains \"" + typeName + "\", which does not parse as a legal type name: " + ila);
// NOTREACHED
return;
}
type.markAsBootImageClass();
//
// convert type name from internal form to external form
// ie: Ljava/lang/Object; --> java.lang.Object
// [Ljava/lang/Object; --> [Ljava.lang.Object;
//
// NOTE: duplicate functionality. There is a method that does the same.
//
typeName = typeName.replace('/', '.');
if (typeName.startsWith("L"))
typeName = typeName.substring(1, typeName.length() - 1);
//
// record name/type pair for later lookup by getRvmType()
//
bootImageTypes.put(typeName, type);
}
if (profile) {
stopTime = System.currentTimeMillis();
System.out.println("PROF: \tloading types " + (stopTime - startTime) + " ms");
}
int typeCount = bootImageTypes.size();
JMXSupport.CLASS_LOADING_JMX_SUPPORT.setClassLoadedCountForBootimage(typeCount);
if (verbosity.isAtLeast(SUMMARY))
say(String.valueOf(typeCount), " types");
//
if (profile)
startTime = System.currentTimeMillis();
if (verbosity.isAtLeast(SUMMARY))
say("resolving");
for (RVMType type : bootImageTypes.values()) {
if (verbosity.isAtLeast(DETAILED))
say("resolving " + type);
// The resolution is supposed to be cached already.
type.resolve();
}
//
for (RVMType type : bootImageTypes.values()) {
type.allBootImageTypesResolved();
}
if (profile) {
stopTime = System.currentTimeMillis();
System.out.println("PROF: \tresolving types " + (stopTime - startTime) + " ms");
}
// Set tocRegister early so opt compiler can access it to
// perform fixed_jtoc optimization (compile static addresses into code).
// In the boot image, the bootrecord comes first followed by a
// Address array and then the TOC. To do this, we must fully
// simulate the alignment logic in the allocation code! Rather
// than replicate the allocation code here, we perform dummy
// allocations and then reset the boot image allocator.
BootRecord bootRecord = BootRecord.the_boot_record;
RVMClass rvmBRType = getRvmType(bootRecord.getClass()).asClass();
RVMArray intArrayType = RVMArray.IntArray;
// allocate storage for boot record
bootImage.allocateDataStorage(rvmBRType.getInstanceSize(), ObjectModel.getAlignment(rvmBRType), ObjectModel.getOffsetForAlignment(rvmBRType, false));
// allocate storage for JTOC (force 16byte alignment of the JTOC on Intel)
Address jtocAddress = bootImage.allocateDataStorage(intArrayType.getInstanceSize(0), VM.BuildForIA32 ? 16 : ObjectModel.getAlignment(intArrayType), ObjectModel.getOffsetForAlignment(intArrayType, false));
bootImage.resetAllocator();
bootRecord.tocRegister = jtocAddress.plus(intArrayType.getInstanceSize(Statics.middleOfTable));
// set up some stuff we need for compiling
ArchitectureFactory.initOutOfLineMachineCode();
//
if (profile)
startTime = System.currentTimeMillis();
if (verbosity.isAtLeast(SUMMARY))
say("instantiating");
if (verbosity.isAtLeast(SUMMARY))
say("setting up compilation infrastructure and pre-compiling easy cases");
CompilationOrder order = new CompilationOrder(typeCount, numThreads);
for (RVMType type : bootImageTypes.values()) {
order.addType(type);
}
order.fixUpMissingSuperClasses();
if (verbosity.isAtLeast(SUMMARY))
say(" compiling with " + numThreads + " threads");
ThreadFactory threadFactory = new KillVMonUncaughtExceptionThreadFactory();
ExecutorService threadPool = Executors.newFixedThreadPool(numThreads, threadFactory);
int runnableCount = order.getCountOfNeededWorkers();
while (runnableCount > 0) {
try {
threadPool.execute(order.getNextRunnable());
runnableCount--;
} catch (InterruptedException e) {
throw new Error("Build interrupted", e);
}
}
threadPool.shutdown();
try {
while (!threadPool.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS)) {
say("Compilation really shouldn't take this long");
}
} catch (InterruptedException e) {
throw new Error("Build interrupted", e);
}
if (BootImageWorker.instantiationFailed) {
throw new Error("Error during instantiaion");
}
if (profile) {
stopTime = System.currentTimeMillis();
System.out.println("PROF: \tinstantiating types " + (stopTime - startTime) + " ms");
}
// Free up unnecessary Statics data structures
staticsJunk = Statics.bootImageInstantiationFinished();
// Do the portion of JNIEnvironment initialization that can be done
// at bootimage writing time.
FunctionTable functionTable = BuildJNIFunctionTable.buildTable();
JNIEnvironment.initFunctionTable(functionTable);
//
if (verbosity.isAtLeast(SUMMARY))
say("field info gathering");
if (profile)
startTime = System.currentTimeMillis();
bootImageTypeFields = new HashMap<Key, FieldInfo>(typeCount);
HashSet<String> invalidEntrys = new HashSet<String>();
// First retrieve the jdk Field table for each class of interest
for (RVMType rvmType : bootImageTypes.values()) {
FieldInfo fieldInfo;
if (!rvmType.isClassType())
// arrays and primitives have no static or instance fields
continue;
Class<?> jdkType = getJdkType(rvmType);
if (jdkType == null)
// won't need the field info
continue;
Key key = new Key(jdkType);
fieldInfo = bootImageTypeFields.get(key);
if (fieldInfo != null) {
fieldInfo.rvmType = rvmType;
} else {
if (verbosity.isAtLeast(SUMMARY))
say("making fieldinfo for " + rvmType);
fieldInfo = new FieldInfo(jdkType, rvmType);
bootImageTypeFields.put(key, fieldInfo);
// Can't add them in next loop as Iterator's don't allow updates to collection
for (Class<?> cls = jdkType.getSuperclass(); cls != null; cls = cls.getSuperclass()) {
key = new Key(cls);
fieldInfo = bootImageTypeFields.get(key);
if (fieldInfo != null) {
break;
} else {
if (verbosity.isAtLeast(SUMMARY))
say("making fieldinfo for " + jdkType);
fieldInfo = new FieldInfo(cls, null);
bootImageTypeFields.put(key, fieldInfo);
}
}
}
}
// Now build the one-to-one instance and static field maps
for (FieldInfo fieldInfo : bootImageTypeFields.values()) {
RVMType rvmType = fieldInfo.rvmType;
if (rvmType == null) {
if (verbosity.isAtLeast(SUMMARY))
say("bootImageTypeField entry has no rvmType:" + fieldInfo.jdkType);
continue;
}
Class<?> jdkType = fieldInfo.jdkType;
if (verbosity.isAtLeast(SUMMARY))
say("building static and instance fieldinfo for " + rvmType);
// First the static fields
//
RVMField[] rvmFields = rvmType.getStaticFields();
fieldInfo.jdkStaticFields = new Field[rvmFields.length];
for (int j = 0; j < rvmFields.length; j++) {
String rvmName = rvmFields[j].getName().toString();
for (Field f : fieldInfo.jdkFields) {
if (f.getName().equals(rvmName)) {
fieldInfo.jdkStaticFields[j] = f;
f.setAccessible(true);
break;
}
}
}
// Now the instance fields
//
rvmFields = rvmType.getInstanceFields();
fieldInfo.jdkInstanceFields = new Field[rvmFields.length];
for (int j = 0; j < rvmFields.length; j++) {
String rvmName = rvmFields[j].getName().toString();
// We look only in the JDK type that corresponds to the
// RVMType of the field's declaring class.
// This is the only way to correctly handle private fields.
jdkType = getJdkType(rvmFields[j].getDeclaringClass());
if (jdkType == null)
continue;
FieldInfo jdkFieldInfo = bootImageTypeFields.get(new Key(jdkType));
if (jdkFieldInfo == null)
continue;
Field[] jdkFields = jdkFieldInfo.jdkFields;
for (Field f : jdkFields) {
if (f.getName().equals(rvmName)) {
fieldInfo.jdkInstanceFields[j] = f;
f.setAccessible(true);
break;
}
}
}
}
if (profile) {
stopTime = System.currentTimeMillis();
System.out.println("PROF: \tcreating type mapping " + (stopTime - startTime) + " ms");
}
//
// Create stack, thread, and processor context in which rvm will begin
// execution.
startupThread = RVMThread.setupBootThread();
byte[] stack = startupThread.getStack();
// sanity check for bootstrap loader
int idx = stack.length - 1;
if (VM.LittleEndian) {
stack[idx--] = (byte) 0xde;
stack[idx--] = (byte) 0xad;
stack[idx--] = (byte) 0xba;
stack[idx--] = (byte) 0xbe;
} else {
stack[idx--] = (byte) 0xbe;
stack[idx--] = (byte) 0xba;
stack[idx--] = (byte) 0xad;
stack[idx--] = (byte) 0xde;
}
//
// Tell RVM where to find itself at execution time.
// This may not be the same place it was at build time, ie. if image is
// moved to another machine with different directory structure.
//
BootstrapClassLoader.setBootstrapRepositories(bootImageRepositoriesAtExecutionTime);
//
if (verbosity.isAtLeast(SUMMARY))
say("populating jtoc with static fields");
if (profile)
startTime = System.currentTimeMillis();
for (RVMType rvmType : bootImageTypes.values()) {
if (verbosity.isAtLeast(SUMMARY))
say(" jtoc for ", rvmType.toString());
if (!rvmType.isClassType())
// arrays and primitives have no static fields
continue;
Class<?> jdkType = getJdkType(rvmType);
if (jdkType == null && verbosity.isAtLeast(SUMMARY)) {
say("host has no class \"" + rvmType + "\"");
}
RVMField[] rvmFields = rvmType.getStaticFields();
for (int j = 0; j < rvmFields.length; ++j) {
RVMField rvmField = rvmFields[j];
TypeReference rvmFieldType = rvmField.getType();
Offset rvmFieldOffset = rvmField.getOffset();
String rvmFieldName = rvmField.getName().toString();
Field jdkFieldAcc = null;
if (jdkType != null && jdkType.equals(java.util.concurrent.locks.AbstractQueuedSynchronizer.class)) {
RVMClass c = (RVMClass) rvmType;
if (rvmFieldName.equals("stateOffset")) {
Statics.setSlotContents(rvmFieldOffset, c.findDeclaredField(Atom.findOrCreateAsciiAtom("state")).getOffset().toLong());
continue;
} else if (rvmFieldName.equals("headOffset")) {
Statics.setSlotContents(rvmFieldOffset, c.findDeclaredField(Atom.findOrCreateAsciiAtom("head")).getOffset().toLong());
continue;
} else if (rvmFieldName.equals("tailOffset")) {
Statics.setSlotContents(rvmFieldOffset, c.findDeclaredField(Atom.findOrCreateAsciiAtom("tail")).getOffset().toLong());
continue;
} else if (rvmFieldName.equals("waitStatusOffset")) {
try {
Statics.setSlotContents(rvmFieldOffset, ((RVMClass) getRvmType(Class.forName("java.util.concurrent.locks.AbstractQueuedSynchronizer$Node"))).findDeclaredField(Atom.findOrCreateAsciiAtom("waitStatus")).getOffset().toLong());
} catch (ClassNotFoundException e) {
throw new Error(e);
}
continue;
}
} else if (jdkType != null && jdkType.equals(java.util.concurrent.locks.LockSupport.class)) {
RVMClass c = (RVMClass) rvmType;
if (rvmFieldName.equals("parkBlockerOffset")) {
Statics.setSlotContents(rvmFieldOffset, ((RVMClass) getRvmType(java.lang.Thread.class)).findDeclaredField(Atom.findOrCreateAsciiAtom("parkBlocker")).getOffset().toLong());
continue;
}
}
if (jdkType != null)
jdkFieldAcc = getJdkFieldAccessor(jdkType, j, STATIC_FIELD);
if (jdkFieldAcc == null) {
// we failed to get a reflective field accessors
if (jdkType != null) {
// we know the type - probably a private field of a java.lang class
if (!copyKnownStaticField(jdkType, rvmFieldName, rvmFieldType, rvmFieldOffset)) {
// we didn't know the field so nullify
if (verbosity.isAtLeast(DETAILED)) {
traceContext.push(rvmFieldType.toString(), jdkType.getName(), rvmFieldName);
traceContext.traceFieldNotInHostJdk();
traceContext.pop();
}
Statics.setSlotContents(rvmFieldOffset, 0);
if (!VM.runningTool)
bootImage.countNulledReference();
invalidEntrys.add(jdkType.getName());
}
} else {
// no accessor and we don't know the type so nullify
if (verbosity.isAtLeast(DETAILED)) {
traceContext.push(rvmFieldType.toString(), rvmFieldType.toString(), rvmFieldName);
traceContext.traceFieldNotInHostJdk();
traceContext.pop();
}
Statics.setSlotContents(rvmFieldOffset, 0);
if (!VM.runningTool)
bootImage.countNulledReference();
invalidEntrys.add(rvmField.getDeclaringClass().toString());
}
continue;
}
if (!Modifier.isStatic(jdkFieldAcc.getModifiers())) {
if (verbosity.isAtLeast(DETAILED))
traceContext.push(rvmFieldType.toString(), jdkType.getName(), rvmFieldName);
if (verbosity.isAtLeast(DETAILED))
traceContext.traceFieldNotStaticInHostJdk();
if (verbosity.isAtLeast(DETAILED))
traceContext.pop();
Statics.setSlotContents(rvmFieldOffset, 0);
if (!VM.runningTool)
bootImage.countNulledReference();
invalidEntrys.add(jdkType.getName());
continue;
}
if (!equalTypes(jdkFieldAcc.getType().getName(), rvmFieldType)) {
if (verbosity.isAtLeast(DETAILED))
traceContext.push(rvmFieldType.toString(), jdkType.getName(), rvmFieldName);
if (verbosity.isAtLeast(DETAILED))
traceContext.traceFieldDifferentTypeInHostJdk();
if (verbosity.isAtLeast(DETAILED))
traceContext.pop();
Statics.setSlotContents(rvmFieldOffset, 0);
if (!VM.runningTool)
bootImage.countNulledReference();
invalidEntrys.add(jdkType.getName());
continue;
}
if (verbosity.isAtLeast(DETAILED))
say(" populating jtoc slot ", String.valueOf(Statics.offsetAsSlot(rvmFieldOffset)), " with ", rvmField.toString());
if (rvmFieldType.isPrimitiveType()) {
// field is logical or numeric type
if (rvmFieldType.isBooleanType()) {
Statics.setSlotContents(rvmFieldOffset, jdkFieldAcc.getBoolean(null) ? 1 : 0);
} else if (rvmFieldType.isByteType()) {
Statics.setSlotContents(rvmFieldOffset, jdkFieldAcc.getByte(null));
} else if (rvmFieldType.isCharType()) {
Statics.setSlotContents(rvmFieldOffset, jdkFieldAcc.getChar(null));
} else if (rvmFieldType.isShortType()) {
Statics.setSlotContents(rvmFieldOffset, jdkFieldAcc.getShort(null));
} else if (rvmFieldType.isIntType()) {
Statics.setSlotContents(rvmFieldOffset, jdkFieldAcc.getInt(null));
} else if (rvmFieldType.isLongType()) {
// note: Endian issues handled in setSlotContents.
Statics.setSlotContents(rvmFieldOffset, jdkFieldAcc.getLong(null));
} else if (rvmFieldType.isFloatType()) {
float f = jdkFieldAcc.getFloat(null);
Statics.setSlotContents(rvmFieldOffset, Float.floatToIntBits(f));
} else if (rvmFieldType.isDoubleType()) {
double d = jdkFieldAcc.getDouble(null);
// note: Endian issues handled in setSlotContents.
Statics.setSlotContents(rvmFieldOffset, Double.doubleToLongBits(d));
} else if (rvmFieldType.equals(TypeReference.Address) || rvmFieldType.equals(TypeReference.Word) || rvmFieldType.equals(TypeReference.Extent) || rvmFieldType.equals(TypeReference.Offset)) {
Object o = jdkFieldAcc.get(null);
String msg = " static field " + rvmField.toString();
boolean warn = rvmFieldType.equals(TypeReference.Address);
Statics.setSlotContents(rvmFieldOffset, getWordValue(o, msg, warn));
} else {
fail("unexpected primitive field type: " + rvmFieldType);
}
} else {
// field is reference type
final Object o = jdkFieldAcc.get(null);
if (verbosity.isAtLeast(ADDRESSES))
say(" setting with ", Services.addressAsHexString(Magic.objectAsAddress(o)));
Statics.setSlotContents(rvmFieldOffset, o);
}
}
}
if (verbosity.isAtLeast(DETAILED)) {
for (final String entry : invalidEntrys) {
say("Static fields of type are invalid: ", entry);
}
}
if (profile) {
stopTime = System.currentTimeMillis();
System.out.println("PROF: \tinitializing jtoc " + (stopTime - startTime) + " ms");
}
}
use of org.jikesrvm.classloader.RVMArray in project JikesRVM by JikesRVM.
the class BaselineCompilerImpl method generateInlineCode.
// *************************************************************************
// MAGIC
// *************************************************************************
/*
* Generate inline machine instructions for special methods that cannot be
* implemented in java bytecodes. These instructions are generated whenever
* we encounter an "invokestatic" bytecode that calls a method with a
* signature of the form "static native Magic.xxx(...)".
*
* NOTE: when adding a new "methodName" to "generate()", be sure to also
* consider how it affects the values on the stack and update
* "checkForActualCall()" accordingly.
* If no call is actually generated, the map will reflect the status of the
* locals (including parameters) at the time of the call but nothing on the
* operand stack for the call site will be mapped.
*/
/**
* Generate inline code sequence for specified method.
* @param methodToBeCalled method whose name indicates semantics of code to be generated
* @return true if there was magic defined for the method
*/
private boolean generateInlineCode(MethodReference methodToBeCalled) {
Atom methodName = methodToBeCalled.getName();
if (methodToBeCalled.isSysCall()) {
TypeReference[] args = methodToBeCalled.getParameterTypes();
// (1) Set up arguments according to OS calling convention, excluding the first
// which is not an argument to the native function but the address of the function to call
int paramWords = methodToBeCalled.getParameterWords();
int gp = FIRST_OS_PARAMETER_GPR.value();
int fp = FIRST_OS_PARAMETER_FPR.value();
int stackIndex = paramWords - 1;
int paramBytes = ((VM.BuildFor64Addr ? args.length : paramWords) - 1) * BYTES_IN_STACKSLOT;
int callee_param_index = -BYTES_IN_STACKSLOT - paramBytes;
for (int i = 1; i < args.length; i++) {
TypeReference t = args[i];
if (t.isLongType()) {
stackIndex -= 2;
callee_param_index += BYTES_IN_LONG;
if (VM.BuildFor64Addr) {
if (gp <= LAST_OS_PARAMETER_GPR.value()) {
peekLong(GPR.lookup(gp), GPR.lookup(gp), stackIndex);
gp++;
} else {
peekLong(S0, S0, stackIndex);
asm.emitSTD(S0, callee_param_index - BYTES_IN_LONG, FP);
}
} else {
if (VM.BuildForLinux) {
/* NOTE: following adjustment is not stated in SVR4 ABI, but
* was implemented in GCC.
*/
// if gpr is even, gpr += 1
gp += (gp + 1) & 0x01;
}
if (gp <= LAST_OS_PARAMETER_GPR.value()) {
peekInt(GPR.lookup(gp++), stackIndex);
}
// lo register := lo mem (== hi order word)
if (gp <= LAST_OS_PARAMETER_GPR.value()) {
// hi register := hi mem (== lo order word)
peekInt(GPR.lookup(gp++), stackIndex + 1);
} else {
peekLong(S0, S1, stackIndex);
asm.emitSTW(S0, callee_param_index - BYTES_IN_LONG, FP);
asm.emitSTW(S1, callee_param_index - BYTES_IN_INT, FP);
}
}
} else if (t.isFloatType()) {
stackIndex -= 1;
callee_param_index += BYTES_IN_STACKSLOT;
if (fp <= LAST_OS_PARAMETER_FPR.value()) {
peekFloat(FPR.lookup(fp++), stackIndex);
} else {
peekFloat(FIRST_SCRATCH_FPR, stackIndex);
asm.emitSTFS(FIRST_SCRATCH_FPR, callee_param_index - BYTES_IN_FLOAT, FP);
}
} else if (t.isDoubleType()) {
stackIndex -= 2;
callee_param_index += BYTES_IN_DOUBLE;
if (fp <= LAST_OS_PARAMETER_FPR.value()) {
peekDouble(FPR.lookup(fp++), stackIndex);
} else {
peekDouble(FIRST_SCRATCH_FPR, stackIndex);
asm.emitSTFD(FIRST_SCRATCH_FPR, callee_param_index - BYTES_IN_DOUBLE, FP);
}
} else if (t.isIntLikeType()) {
stackIndex -= 1;
callee_param_index += BYTES_IN_STACKSLOT;
if (gp <= LAST_OS_PARAMETER_GPR.value()) {
peekInt(GPR.lookup(gp++), stackIndex);
} else {
peekInt(S0, stackIndex);
// save int zero-extended to be sure
asm.emitSTAddr(S0, callee_param_index - BYTES_IN_ADDRESS, FP);
}
} else {
// t is object
stackIndex -= 1;
callee_param_index += BYTES_IN_STACKSLOT;
if (gp <= LAST_OS_PARAMETER_GPR.value()) {
peekAddr(GPR.lookup(gp++), stackIndex);
} else {
peekAddr(S0, stackIndex);
asm.emitSTAddr(S0, callee_param_index - BYTES_IN_ADDRESS, FP);
}
}
}
if (VM.VerifyAssertions) {
VM._assert(stackIndex == 0);
}
// (2) Call it
// Load addres of function into S0
peekAddr(S0, paramWords - 1);
// make the call
generateSysCall(paramBytes);
// (3) Pop Java expression stack
discardSlots(paramWords);
// (4) Push return value (if any)
TypeReference rtype = methodToBeCalled.getReturnType();
if (rtype.isIntLikeType()) {
pushInt(T0);
} else if (rtype.isWordLikeType() || rtype.isReferenceType()) {
pushAddr(T0);
} else if (rtype.isDoubleType()) {
pushDouble(FIRST_OS_PARAMETER_FPR);
} else if (rtype.isFloatType()) {
pushFloat(FIRST_OS_PARAMETER_FPR);
} else if (rtype.isLongType()) {
pushLong(T0, VM.BuildFor64Addr ? T0 : T1);
}
return true;
}
if (methodToBeCalled.getType() == TypeReference.Address) {
// Address.xyz magic
TypeReference[] types = methodToBeCalled.getParameterTypes();
if (methodName == MagicNames.loadAddress || methodName == MagicNames.loadObjectReference || methodName == MagicNames.loadWord) {
if (types.length == 0) {
// pop base
popAddr(T0);
// *(base)
asm.emitLAddr(T0, 0, T0);
// push *(base)
pushAddr(T0);
} else {
// pop offset
popOffset(T1);
// pop base
popAddr(T0);
// *(base+offset)
asm.emitLAddrX(T0, T1, T0);
// push *(base+offset)
pushAddr(T0);
}
return true;
}
if (methodName == MagicNames.loadChar) {
if (types.length == 0) {
// pop base
popAddr(T0);
// load with zero extension.
asm.emitLHZ(T0, 0, T0);
// push *(base)
pushInt(T0);
} else {
// pop offset
popOffset(T1);
// pop base
popAddr(T0);
// load with zero extension.
asm.emitLHZX(T0, T1, T0);
// push *(base+offset)
pushInt(T0);
}
return true;
}
if (methodName == MagicNames.loadShort) {
if (types.length == 0) {
// pop base
popAddr(T0);
// load with sign extension.
asm.emitLHA(T0, 0, T0);
// push *(base)
pushInt(T0);
} else {
// pop offset
popOffset(T1);
// pop base
popAddr(T0);
// load with sign extension.
asm.emitLHAX(T0, T1, T0);
// push *(base+offset)
pushInt(T0);
}
return true;
}
if (methodName == MagicNames.loadByte) {
if (types.length == 0) {
// pop base
popAddr(T0);
// load with zero extension.
asm.emitLBZ(T0, 0, T0);
// sign extend
asm.emitEXTSB(T0, T0);
// push *(base)
pushInt(T0);
} else {
// pop offset
popOffset(T1);
// pop base
popAddr(T0);
// load with zero extension.
asm.emitLBZX(T0, T1, T0);
// sign extend
asm.emitEXTSB(T0, T0);
// push *(base+offset)
pushInt(T0);
}
return true;
}
if (methodName == MagicNames.loadInt || methodName == MagicNames.loadFloat) {
if (types.length == 0) {
// pop base
popAddr(T0);
// *(base)
asm.emitLInt(T0, 0, T0);
// push *(base)
pushInt(T0);
} else {
// pop offset
popOffset(T1);
// pop base
popAddr(T0);
// *(base+offset)
asm.emitLIntX(T0, T1, T0);
// push *(base+offset)
pushInt(T0);
}
return true;
}
if (methodName == MagicNames.loadDouble || methodName == MagicNames.loadLong) {
if (types.length == 0) {
// pop base
popAddr(T1);
// *(base)
asm.emitLFD(F0, 0, T1);
// push double
pushDouble(F0);
} else {
// pop offset
popOffset(T2);
// pop base
popAddr(T1);
// *(base+offset)
asm.emitLFDX(F0, T1, T2);
// push *(base+offset)
pushDouble(F0);
}
return true;
}
if ((methodName == MagicNames.prepareInt) || (VM.BuildFor32Addr && (methodName == MagicNames.prepareWord)) || (VM.BuildFor32Addr && (methodName == MagicNames.prepareObjectReference)) || (VM.BuildFor32Addr && (methodName == MagicNames.prepareAddress))) {
if (types.length == 0) {
// pop base
popAddr(T0);
// *(base), setting reservation address
asm.emitLWARX(T0, GPR.R0, T0);
// this Integer is not sign extended !!
// push *(base+offset)
pushInt(T0);
} else {
// pop offset
popOffset(T1);
// pop base
popAddr(T0);
// *(base+offset), setting reservation address
asm.emitLWARX(T0, T1, T0);
// this Integer is not sign extended !!
// push *(base+offset)
pushInt(T0);
}
return true;
}
if ((methodName == MagicNames.prepareLong) || (VM.BuildFor64Addr && (methodName == MagicNames.prepareWord)) || (VM.BuildFor64Addr && (methodName == MagicNames.prepareObjectReference)) || (VM.BuildFor64Addr && (methodName == MagicNames.prepareAddress))) {
if (types.length == 0) {
// pop base
popAddr(T0);
// *(base), setting reservation address
asm.emitLDARX(T0, GPR.R0, T0);
// this Integer is not sign extended !!
// push *(base+offset)
pushAddr(T0);
} else {
// pop offset
popOffset(T1);
// pop base
popAddr(T0);
if (VM.BuildFor64Addr) {
// *(base+offset), setting reservation address
asm.emitLDARX(T0, T1, T0);
} else {
// TODO: handle 64bit prepares in 32bit environment
}
// this Integer is not sign extended !!
// push *(base+offset)
pushAddr(T0);
}
return true;
}
if (methodName == MagicNames.attempt && ((types[0] == TypeReference.Int) || (VM.BuildFor32Addr && (types[0] == TypeReference.Address)) || (VM.BuildFor32Addr && (types[0] == TypeReference.Word)))) {
if (types.length == 2) {
// pop newValue
popInt(T2);
// ignore oldValue
discardSlot();
// pop base
popAddr(T0);
// store new value and set CR0
asm.emitSTWCXr(T2, GPR.R0, T0);
// T0 := false
asm.emitLVAL(T0, 0);
// skip, if store failed
ForwardReference fr = asm.emitForwardBC(NE);
// T0 := true
asm.emitLVAL(T0, 1);
fr.resolve(asm);
// push success of store
pushInt(T0);
} else {
// pop offset
popOffset(T1);
// pop newValue
popInt(T2);
// ignore oldValue
discardSlot();
// pop base
popAddr(T0);
// store new value and set CR0
asm.emitSTWCXr(T2, T1, T0);
// T0 := false
asm.emitLVAL(T0, 0);
// skip, if store failed
ForwardReference fr = asm.emitForwardBC(NE);
// T0 := true
asm.emitLVAL(T0, 1);
fr.resolve(asm);
// push success of store
pushInt(T0);
}
return true;
}
if (methodName == MagicNames.attempt && ((types[0] == TypeReference.Long) || (VM.BuildFor64Addr && (types[0] == TypeReference.Address)) || (VM.BuildFor64Addr && (types[0] == TypeReference.Word)))) {
if (types.length == 2) {
// pop newValue
popAddr(T2);
// ignore oldValue
discardSlot();
// pop base
popAddr(T0);
// store new value and set CR0
asm.emitSTDCXr(T2, GPR.R0, T0);
// T0 := false
asm.emitLVAL(T0, 0);
// skip, if store failed
ForwardReference fr = asm.emitForwardBC(NE);
// T0 := true
asm.emitLVAL(T0, 1);
fr.resolve(asm);
// push success of store
pushInt(T0);
} else {
// pop offset
popOffset(T1);
// pop newValue
popAddr(T2);
// ignore oldValue
discardSlot();
// pop base
popAddr(T0);
if (VM.BuildFor64Addr) {
// store new value and set CR0
asm.emitSTDCXr(T2, T1, T0);
} else {
// TODO: handle 64bit attempts in 32bit environment
}
// T0 := false
asm.emitLVAL(T0, 0);
// skip, if store failed
ForwardReference fr = asm.emitForwardBC(NE);
// T0 := true
asm.emitLVAL(T0, 1);
fr.resolve(asm);
// push success of store
pushInt(T0);
}
return true;
}
// ..., Address, Value, [Offset] -> ...
if (methodName == MagicNames.store) {
if (types[0] == TypeReference.Word || types[0] == TypeReference.ObjectReference || types[0] == TypeReference.Address) {
if (types.length == 1) {
// pop newvalue
popAddr(T1);
// pop base
popAddr(T0);
// *(base) = newvalue
asm.emitSTAddrX(T1, GPR.R0, T0);
} else {
// pop offset
popOffset(T1);
// pop newvalue
popAddr(T2);
// pop base
popAddr(T0);
// *(base+offset) = newvalue
asm.emitSTAddrX(T2, T1, T0);
}
return true;
}
if (types[0] == TypeReference.Byte || types[0] == TypeReference.Boolean) {
if (types.length == 1) {
// pop newvalue
popInt(T1);
// pop base
popAddr(T0);
// *(base) = newvalue
asm.emitSTBX(T1, GPR.R0, T0);
} else {
// pop offset
popOffset(T1);
// pop newvalue
popInt(T2);
// pop base
popAddr(T0);
// *(base+offset) = newvalue
asm.emitSTBX(T2, T1, T0);
}
return true;
}
if (types[0] == TypeReference.Int || types[0] == TypeReference.Float) {
if (types.length == 1) {
// pop newvalue
popInt(T1);
// pop base
popAddr(T0);
// *(base+offset) = newvalue
asm.emitSTWX(T1, GPR.R0, T0);
} else {
// pop offset
popOffset(T1);
// pop newvalue
popInt(T2);
// pop base
popAddr(T0);
// *(base+offset) = newvalue
asm.emitSTWX(T2, T1, T0);
}
return true;
}
if (types[0] == TypeReference.Short || types[0] == TypeReference.Char) {
if (types.length == 1) {
// pop newvalue
popInt(T1);
// pop base
popAddr(T0);
// *(base) = newvalue
asm.emitSTHX(T1, GPR.R0, T0);
} else {
// pop offset
popOffset(T1);
// pop newvalue
popInt(T2);
// pop base
popAddr(T0);
// *(base+offset) = newvalue
asm.emitSTHX(T2, T1, T0);
}
return true;
}
if (types[0] == TypeReference.Double || types[0] == TypeReference.Long) {
if (types.length == 1) {
// pop newvalue low and high
popLong(T2, T1);
// pop base
popAddr(T0);
if (VM.BuildFor32Addr) {
// *(base) = newvalue low
asm.emitSTW(T2, 0, T0);
// *(base+4) = newvalue high
asm.emitSTW(T1, BYTES_IN_INT, T0);
} else {
// *(base) = newvalue
asm.emitSTD(T1, 0, T0);
}
} else {
// pop offset
popOffset(T1);
// pop newvalue low and high
popLong(T3, T2);
// pop base
popAddr(T0);
if (VM.BuildFor32Addr) {
// *(base+offset) = newvalue low
asm.emitSTWX(T3, T1, T0);
// offset += 4
asm.emitADDI(T1, BYTES_IN_INT, T1);
// *(base+offset) = newvalue high
asm.emitSTWX(T2, T1, T0);
} else {
// *(base+offset) = newvalue
asm.emitSTDX(T2, T1, T0);
}
}
return true;
}
}
}
if (methodName == MagicNames.getFramePointer) {
pushAddr(FP);
} else if (methodName == MagicNames.getCallerFramePointer) {
// pop frame pointer of callee frame
popAddr(T0);
// load frame pointer of caller frame
asm.emitLAddr(T1, STACKFRAME_FRAME_POINTER_OFFSET.toInt(), T0);
// push frame pointer of caller frame
pushAddr(T1);
} else if (methodName == MagicNames.setCallerFramePointer) {
// value
popAddr(T1);
// fp
popAddr(T0);
// *(address+SFPO) := value
asm.emitSTAddr(T1, STACKFRAME_FRAME_POINTER_OFFSET.toInt(), T0);
} else if (methodName == MagicNames.getCompiledMethodID) {
// pop frame pointer of callee frame
popAddr(T0);
// load compiled method id
asm.emitLInt(T1, STACKFRAME_METHOD_ID_OFFSET.toInt(), T0);
// push method ID
pushInt(T1);
} else if (methodName == MagicNames.setCompiledMethodID) {
// value
popInt(T1);
// fp
popAddr(T0);
// *(address+SNIO) := value
asm.emitSTW(T1, STACKFRAME_METHOD_ID_OFFSET.toInt(), T0);
} else if (methodName == MagicNames.getNextInstructionAddress) {
// pop frame pointer of callee frame
popAddr(T0);
// load frame pointer of caller frame
asm.emitLAddr(T1, STACKFRAME_RETURN_ADDRESS_OFFSET.toInt(), T0);
// push frame pointer of caller frame
pushAddr(T1);
} else if (methodName == MagicNames.getReturnAddressLocation) {
// pop frame pointer of callee frame
popAddr(T0);
// load frame pointer of caller frame
asm.emitLAddr(T1, STACKFRAME_FRAME_POINTER_OFFSET.toInt(), T0);
// get location containing ret addr
asm.emitADDI(T2, STACKFRAME_RETURN_ADDRESS_OFFSET, T1);
// push frame pointer of caller frame
pushAddr(T2);
} else if (methodName == MagicNames.getTocPointer || methodName == MagicNames.getJTOC) {
pushAddr(JTOC);
} else if (methodName == MagicNames.getThreadRegister) {
pushAddr(THREAD_REGISTER);
} else if (methodName == MagicNames.setThreadRegister) {
popAddr(THREAD_REGISTER);
} else if (methodName == MagicNames.getTimeBase) {
if (VM.BuildFor64Addr) {
// T1 := time base
asm.emitMFTB(T1);
} else {
int label = asm.getMachineCodeIndex();
// T0 := time base, upper
asm.emitMFTBU(T0);
// T1 := time base, lower
asm.emitMFTB(T1);
// T2 := time base, upper
asm.emitMFTBU(T2);
// T0 == T2?
asm.emitCMP(T0, T2);
// lower rolled over, try again
asm.emitBC(NE, label);
}
pushLong(T0, T1);
} else if (methodName == MagicNames.invokeClassInitializer) {
// t0 := address to be called
popAddr(T0);
asm.emitMTCTR(T0);
// call
asm.emitBCCTRL();
} else if (methodName == MagicNames.invokeMethodReturningVoid) {
// call method
generateMethodInvocation();
} else if (methodName == MagicNames.invokeMethodReturningInt) {
// call method
generateMethodInvocation();
// push result
pushInt(T0);
} else if (methodName == MagicNames.invokeMethodReturningLong) {
// call method
generateMethodInvocation();
// push result
pushLong(T0, VM.BuildFor64Addr ? T0 : T1);
} else if (methodName == MagicNames.invokeMethodReturningFloat) {
// call method
generateMethodInvocation();
// push result
pushFloat(F0);
} else if (methodName == MagicNames.invokeMethodReturningDouble) {
// call method
generateMethodInvocation();
// push result
pushDouble(F0);
} else if (methodName == MagicNames.invokeMethodReturningObject) {
// call method
generateMethodInvocation();
// push result
pushAddr(T0);
} else if (methodName == MagicNames.addressArrayCreate) {
RVMArray type = methodToBeCalled.getType().resolve().asArray();
emit_resolved_newarray(type);
} else if (methodName == MagicNames.addressArrayLength) {
emit_arraylength();
} else if (methodName == MagicNames.addressArrayGet) {
genBoundsCheck();
if (VM.BuildFor32Addr || methodToBeCalled.getType() == TypeReference.CodeArray) {
// convert index to offset
asm.emitSLWI(T1, T1, LOG_BYTES_IN_INT);
// load desired int array element
asm.emitLIntX(T2, T0, T1);
pushInt(T2);
} else {
// convert index to offset
asm.emitSLDI(T1, T1, LOG_BYTES_IN_ADDRESS);
// load desired array element
asm.emitLAddrX(T2, T0, T1);
pushAddr(T2);
}
} else if (methodName == MagicNames.addressArraySet) {
// T2 is value to store
popAddr(T2);
genBoundsCheck();
if (VM.BuildFor32Addr || methodToBeCalled.getType() == TypeReference.CodeArray) {
// convert index to offset
asm.emitSLWI(T1, T1, LOG_BYTES_IN_INT);
// store 32-bit value in array
asm.emitSTWX(T2, T0, T1);
} else {
// convert index to offset
asm.emitSLDI(T1, T1, LOG_BYTES_IN_ADDRESS);
// store value in array
asm.emitSTAddrX(T2, T0, T1);
}
} else if (methodName == MagicNames.getIntAtOffset) {
// pop offset
popOffset(T1);
// pop object
popAddr(T0);
// *(object+offset)
asm.emitLIntX(T0, T1, T0);
// push *(object+offset)
pushInt(T0);
} else if (methodName == MagicNames.getFloatAtOffset) {
// pop offset
popOffset(T1);
// pop object
popAddr(T0);
// *(object+offset)
asm.emitLWZX(T0, T1, T0);
// push *(object+offset),
pushInt(T0);
// asm.emitLFSX (F0, T1, T0); // *(object+offset)
// pushFloat(F0);
} else if (methodName == MagicNames.getObjectAtOffset || methodName == MagicNames.getWordAtOffset || methodName == MagicNames.getAddressAtOffset || methodName == MagicNames.getOffsetAtOffset || methodName == MagicNames.getExtentAtOffset || methodName == MagicNames.getTIBAtOffset) {
if (methodToBeCalled.getParameterTypes().length == 3) {
// discard locationMetadata parameter
discardSlot();
}
// pop offset
popOffset(T1);
// pop object
popAddr(T0);
// *(object+offset)
asm.emitLAddrX(T0, T1, T0);
// push *(object+offset)
pushAddr(T0);
} else if (methodName == MagicNames.getUnsignedByteAtOffset) {
// pop offset
popOffset(T1);
// pop object
popAddr(T0);
// load byte with zero extension.
asm.emitLBZX(T0, T1, T0);
// push *(object+offset)
pushInt(T0);
} else if (methodName == MagicNames.getByteAtOffset) {
// pop offset
popOffset(T1);
// pop object
popAddr(T0);
// load byte with zero extension.
asm.emitLBZX(T0, T1, T0);
// sign extend
asm.emitEXTSB(T0, T0);
// push *(object+offset)
pushInt(T0);
} else if (methodName == MagicNames.getCharAtOffset) {
// pop offset
popOffset(T1);
// pop object
popAddr(T0);
// load char with zero extension.
asm.emitLHZX(T0, T1, T0);
// push *(object+offset)
pushInt(T0);
} else if (methodName == MagicNames.getShortAtOffset) {
// pop offset
popOffset(T1);
// pop object
popAddr(T0);
// load short with sign extension.
asm.emitLHAX(T0, T1, T0);
// push *(object+offset)
pushInt(T0);
} else if (methodName == MagicNames.setIntAtOffset || methodName == MagicNames.setFloatAtOffset) {
if (methodToBeCalled.getParameterTypes().length == 4) {
// discard locationMetadata parameter
discardSlot();
}
// pop newvalue
popInt(T2);
// pop offset
popOffset(T1);
// pop object
popAddr(T0);
// *(object+offset) = newvalue
asm.emitSTWX(T2, T1, T0);
} else if (methodName == MagicNames.setObjectAtOffset || methodName == MagicNames.setWordAtOffset || methodName == MagicNames.setAddressAtOffset || methodName == MagicNames.setOffsetAtOffset || methodName == MagicNames.setExtentAtOffset) {
if (methodToBeCalled.getParameterTypes().length == 4) {
// discard locationMetadata parameter
discardSlot();
}
// pop newvalue
popAddr(T2);
// pop offset
popOffset(T1);
// pop object
popAddr(T0);
// *(object+offset) = newvalue
asm.emitSTAddrX(T2, T1, T0);
} else if (methodName == MagicNames.setByteAtOffset || methodName == MagicNames.setBooleanAtOffset) {
if (methodToBeCalled.getParameterTypes().length == 4) {
// discard locationMetadata parameter
discardSlot();
}
// pop newvalue
popInt(T2);
// pop offset
popOffset(T1);
// pop object
popAddr(T0);
// *(object+offset) = newvalue
asm.emitSTBX(T2, T1, T0);
} else if (methodName == MagicNames.setCharAtOffset || methodName == MagicNames.setShortAtOffset) {
if (methodToBeCalled.getParameterTypes().length == 4) {
// discard locationMetadata parameter
discardSlot();
}
// pop newvalue
popInt(T2);
// pop offset
popOffset(T1);
// pop object
popAddr(T0);
// *(object+offset) = newvalue
asm.emitSTHX(T2, T1, T0);
} else if (methodName == MagicNames.getLongAtOffset || methodName == MagicNames.getDoubleAtOffset) {
// pop offset
popOffset(T2);
// pop object
popAddr(T1);
asm.emitLFDX(F0, T1, T2);
pushDouble(F0);
} else if ((methodName == MagicNames.setLongAtOffset) || (methodName == MagicNames.setDoubleAtOffset)) {
if (methodToBeCalled.getParameterTypes().length == 4) {
// discard locationMetadata parameter
discardSlot();
}
popLong(T3, T2);
// pop offset
popOffset(T1);
// pop object
popAddr(T0);
if (VM.BuildFor32Addr) {
// *(object+offset) = newvalue low
asm.emitSTWX(T3, T1, T0);
// offset += 4
asm.emitADDI(T1, BYTES_IN_INT, T1);
// *(object+offset) = newvalue high
asm.emitSTWX(T2, T1, T0);
} else {
// *(object+offset) = newvalue
asm.emitSTDX(T2, T1, T0);
}
} else if (methodName == MagicNames.getMemoryInt) {
// address
popAddr(T0);
// *address
asm.emitLInt(T0, 0, T0);
// *sp := *address
pushInt(T0);
} else if (methodName == MagicNames.getMemoryWord || methodName == MagicNames.getMemoryAddress) {
// address
popAddr(T0);
// *address
asm.emitLAddr(T0, 0, T0);
// *sp := *address
pushAddr(T0);
} else if (methodName == MagicNames.setMemoryInt) {
// value
popInt(T1);
// address
popAddr(T0);
// *address := value
asm.emitSTW(T1, 0, T0);
} else if (methodName == MagicNames.setMemoryWord) {
if (methodToBeCalled.getParameterTypes().length == 3) {
// discard locationMetadata parameter
discardSlot();
}
// value
popAddr(T1);
// address
popAddr(T0);
// *address := value
asm.emitSTAddr(T1, 0, T0);
} else if ((methodName == MagicNames.prepareInt) || (VM.BuildFor32Addr && (methodName == MagicNames.prepareObject)) || (VM.BuildFor32Addr && (methodName == MagicNames.prepareAddress)) || (VM.BuildFor32Addr && (methodName == MagicNames.prepareWord))) {
// pop offset
popOffset(T1);
// pop object
popAddr(T0);
// *(object+offset), setting thread's reservation address
asm.emitLWARX(T0, T1, T0);
// this Integer is not sign extended !!
// push *(object+offset)
pushInt(T0);
} else if ((methodName == MagicNames.prepareLong) || (VM.BuildFor64Addr && (methodName == MagicNames.prepareObject)) || (VM.BuildFor64Addr && (methodName == MagicNames.prepareAddress)) || (VM.BuildFor64Addr && (methodName == MagicNames.prepareWord))) {
// pop offset
popOffset(T1);
// pop object
popAddr(T0);
if (VM.BuildFor64Addr) {
// *(object+offset), setting thread's reservation address
asm.emitLDARX(T0, T1, T0);
} else {
// TODO: handle 64bit prepares in 32bit environment
}
// push *(object+offset)
pushAddr(T0);
} else if ((methodName == MagicNames.attemptInt) || (VM.BuildFor32Addr && (methodName == MagicNames.attemptObject)) || (VM.BuildFor32Addr && (methodName == MagicNames.attemptObjectReference)) || (VM.BuildFor32Addr && (methodName == MagicNames.attemptAddress)) || (VM.BuildFor32Addr && (methodName == MagicNames.attemptWord))) {
// pop newValue
popInt(T2);
// ignore oldValue
discardSlot();
// pop offset
popOffset(T1);
// pop object
popAddr(T0);
// store new value and set CR0
asm.emitSTWCXr(T2, T1, T0);
// T0 := false
asm.emitLVAL(T0, 0);
// skip, if store failed
ForwardReference fr = asm.emitForwardBC(NE);
// T0 := true
asm.emitLVAL(T0, 1);
fr.resolve(asm);
// push success of conditional store
pushInt(T0);
} else if (methodName == MagicNames.attemptLong) {
// pop newValue
popLong(T3, T2);
// ignore oldValue which is a long and thus takes 2 slots
discardSlots(2);
// pop offset
popOffset(T1);
// pop object
popAddr(T0);
if (VM.BuildFor64Addr) {
// store new value and set CR0
asm.emitSTDCXr(T2, T1, T0);
} else {
// TODO: handle 64bit attempts in 32bit environment
}
// T0 := false
asm.emitLVAL(T0, 0);
// skip, if store failed
ForwardReference fr = asm.emitForwardBC(NE);
// T0 := true
asm.emitLVAL(T0, 1);
fr.resolve(asm);
// push success of conditional store
pushInt(T0);
} else if (VM.BuildFor64Addr && ((methodName == MagicNames.attemptObject) || (methodName == MagicNames.attemptObjectReference) || (methodName == MagicNames.attemptAddress) || (methodName == MagicNames.attemptWord))) {
// pop newValue
popAddr(T2);
// ignore oldValue
discardSlot();
// pop offset
popOffset(T1);
// pop object
popAddr(T0);
// store new value and set CR0
asm.emitSTDCXr(T2, T1, T0);
// T0 := false
asm.emitLVAL(T0, 0);
// skip, if store failed
ForwardReference fr = asm.emitForwardBC(NE);
// T0 := true
asm.emitLVAL(T0, 1);
fr.resolve(asm);
// push success of conditional store
pushInt(T0);
} else if (methodName == MagicNames.saveThreadState) {
// T0 := address of Registers object
peekAddr(T0, 0);
asm.emitLAddrToc(S0, ArchEntrypoints.saveThreadStateInstructionsField.getOffset());
asm.emitMTCTR(S0);
// call out of line machine code
asm.emitBCCTRL();
// pop arg
discardSlot();
} else if (methodName == MagicNames.threadSwitch) {
// T1 := address of Registers of new thread
peekAddr(T1, 0);
// T0 := address of previous RVMThread object
peekAddr(T0, 1);
asm.emitLAddrToc(S0, ArchEntrypoints.threadSwitchInstructionsField.getOffset());
asm.emitMTCTR(S0);
asm.emitBCCTRL();
// pop two args
discardSlots(2);
} else if (methodName == MagicNames.restoreHardwareExceptionState) {
// T0 := address of Registers object
peekAddr(T0, 0);
asm.emitLAddrToc(S0, ArchEntrypoints.restoreHardwareExceptionStateInstructionsField.getOffset());
asm.emitMTLR(S0);
// branch to out of line machine code (does not return)
asm.emitBCLR();
} else if (methodName == MagicNames.returnToNewStack) {
// FP := new stackframe
peekAddr(FP, 0);
// fetch...
asm.emitLAddr(S0, STACKFRAME_RETURN_ADDRESS_OFFSET.toInt(), FP);
// ...return address
asm.emitMTLR(S0);
// return to caller
asm.emitBCLR();
} else if (methodName == MagicNames.dynamicBridgeTo) {
if (VM.VerifyAssertions)
VM._assert(klass.hasDynamicBridgeAnnotation());
// fetch parameter (address to branch to) into CT register
//
peekAddr(T0, 0);
asm.emitMTCTR(T0);
// restore volatile and non-volatile registers
// (note that these are only saved for "dynamic bridge" methods)
//
int offset = frameSize;
// restore non-volatile and volatile fprs
for (int i = LAST_NONVOLATILE_FPR.value(); i >= FIRST_VOLATILE_FPR.value(); --i) {
asm.emitLFD(FPR.lookup(i), offset -= BYTES_IN_DOUBLE, FP);
}
// restore non-volatile gprs
for (int i = LAST_NONVOLATILE_GPR.value(); i >= FIRST_NONVOLATILE_GPR.value(); --i) {
asm.emitLAddr(GPR.lookup(i), offset -= BYTES_IN_ADDRESS, FP);
}
// skip saved thread-id, thread, and scratch registers
offset -= (FIRST_NONVOLATILE_GPR.value() - LAST_VOLATILE_GPR.value() - 1) * BYTES_IN_ADDRESS;
// restore volatile gprs
for (int i = LAST_VOLATILE_GPR.value(); i >= FIRST_VOLATILE_GPR.value(); --i) {
asm.emitLAddr(GPR.lookup(i), offset -= BYTES_IN_ADDRESS, FP);
}
// pop stackframe
asm.emitLAddr(FP, 0, FP);
// restore link register
asm.emitLAddr(S0, STACKFRAME_RETURN_ADDRESS_OFFSET.toInt(), FP);
asm.emitMTLR(S0);
// branch always, through count register
asm.emitBCCTR();
} else if (methodName == MagicNames.objectAsAddress || methodName == MagicNames.addressAsByteArray || methodName == MagicNames.addressAsObject || methodName == MagicNames.addressAsTIB || methodName == MagicNames.objectAsType || methodName == MagicNames.objectAsShortArray || methodName == MagicNames.objectAsIntArray || methodName == MagicNames.objectAsThread || methodName == MagicNames.floatAsIntBits || methodName == MagicNames.intBitsAsFloat || methodName == MagicNames.doubleAsLongBits || methodName == MagicNames.longBitsAsDouble) {
// no-op (a type change, not a representation change)
} else if (methodName == MagicNames.getObjectType) {
// get object pointer
popAddr(T0);
asm.baselineEmitLoadTIB(T0, T0);
// get "type" field from type information block
asm.emitLAddr(T0, TIB_TYPE_INDEX << LOG_BYTES_IN_ADDRESS, T0);
// *sp := type
pushAddr(T0);
} else if (methodName == MagicNames.getArrayLength) {
// get object pointer
popAddr(T0);
// get array length field
asm.emitLIntOffset(T0, T0, ObjectModel.getArrayLengthOffset());
// *sp := length
pushInt(T0);
} else if (methodName == MagicNames.synchronizeInstructionCache) {
asm.emitISYNC();
} else if (methodName == MagicNames.pause) {
// NO-OP
} else if (methodName == MagicNames.combinedLoadBarrier) {
asm.emitHWSYNC();
} else if (methodName == MagicNames.storeStoreBarrier) {
asm.emitSYNC();
} else if (methodName == MagicNames.fence) {
asm.emitHWSYNC();
} else if (methodName == MagicNames.illegalInstruction) {
asm.emitIllegalInstruction();
} else if (methodName == MagicNames.dcbst) {
// address
popAddr(T0);
asm.emitDCBST(GPR.R0, T0);
} else if (methodName == MagicNames.dcbt || methodName == MagicNames.prefetch) {
// address
popAddr(T0);
asm.emitDCBT(GPR.R0, T0);
} else if (methodName == MagicNames.dcbtst) {
// address
popAddr(T0);
asm.emitDCBTST(GPR.R0, T0);
} else if (methodName == MagicNames.dcbz) {
// address
popAddr(T0);
asm.emitDCBZ(GPR.R0, T0);
} else if (methodName == MagicNames.dcbzl) {
// address
popAddr(T0);
asm.emitDCBZL(GPR.R0, T0);
} else if (methodName == MagicNames.icbi) {
// address
popAddr(T0);
asm.emitICBI(GPR.R0, T0);
} else if (methodName == MagicNames.sqrt) {
TypeReference argType = method.getParameterTypes()[0];
if (argType == TypeReference.Float) {
popFloat(F0);
asm.emitFSQRTS(F0, F0);
pushFloat(F0);
} else {
if (VM.VerifyAssertions)
VM._assert(argType == TypeReference.Double);
popDouble(F0);
asm.emitFSQRT(F0, F0);
pushDouble(F0);
}
} else if (methodName == MagicNames.getInlineDepth || methodName == MagicNames.isConstantParameter) {
emit_iconst(0);
} else if (methodName == MagicNames.getCompilerLevel) {
emit_iconst(-1);
} else if (methodName == MagicNames.getFrameSize) {
emit_iconst(frameSize);
} else if (methodName == MagicNames.wordToInt || methodName == MagicNames.wordToAddress || methodName == MagicNames.wordToOffset || methodName == MagicNames.wordToObject || methodName == MagicNames.wordFromObject || methodName == MagicNames.wordToObjectReference || methodName == MagicNames.wordToExtent || methodName == MagicNames.wordToWord || methodName == MagicNames.codeArrayAsObject || methodName == MagicNames.tibAsObject) {
// no-op
} else if (methodName == MagicNames.wordToLong) {
asm.emitLVAL(T0, 0);
pushAddr(T0);
} else if (methodName == MagicNames.wordFromInt || methodName == MagicNames.wordFromIntSignExtend) {
if (VM.BuildFor64Addr) {
popInt(T0);
pushAddr(T0);
}
// else no-op
} else if (methodName == MagicNames.wordFromIntZeroExtend) {
if (VM.BuildFor64Addr) {
asm.emitLWZ(T0, spTopOffset + BYTES_IN_STACKSLOT - BYTES_IN_INT, FP);
pokeAddr(T0, 0);
}
// else no-op
} else if (methodName == MagicNames.wordFromLong) {
discardSlot();
} else if (methodName == MagicNames.wordPlus) {
if (VM.BuildFor64Addr && (methodToBeCalled.getParameterTypes()[0] == TypeReference.Int)) {
popInt(T0);
} else {
popAddr(T0);
}
popAddr(T1);
asm.emitADD(T2, T1, T0);
pushAddr(T2);
} else if (methodName == MagicNames.wordMinus || methodName == MagicNames.wordDiff) {
if (VM.BuildFor64Addr && (methodToBeCalled.getParameterTypes()[0] == TypeReference.Int)) {
popInt(T0);
} else {
popAddr(T0);
}
popAddr(T1);
asm.emitSUBFC(T2, T0, T1);
pushAddr(T2);
} else if (methodName == MagicNames.wordEQ) {
generateAddrComparison(false, EQ);
} else if (methodName == MagicNames.wordNE) {
generateAddrComparison(false, NE);
} else if (methodName == MagicNames.wordLT) {
generateAddrComparison(false, LT);
} else if (methodName == MagicNames.wordLE) {
generateAddrComparison(false, LE);
} else if (methodName == MagicNames.wordGT) {
generateAddrComparison(false, GT);
} else if (methodName == MagicNames.wordGE) {
generateAddrComparison(false, GE);
} else if (methodName == MagicNames.wordsLT) {
generateAddrComparison(true, LT);
} else if (methodName == MagicNames.wordsLE) {
generateAddrComparison(true, LE);
} else if (methodName == MagicNames.wordsGT) {
generateAddrComparison(true, GT);
} else if (methodName == MagicNames.wordsGE) {
generateAddrComparison(true, GE);
} else if (methodName == MagicNames.wordIsZero || methodName == MagicNames.wordIsNull) {
// unsigned comparison generating a boolean
popAddr(T0);
asm.emitLVAL(T1, 0);
asm.emitLVAL(T2, 1);
asm.emitCMPLAddr(T0, T1);
ForwardReference fr = asm.emitForwardBC(EQ);
asm.emitLVAL(T2, 0);
fr.resolve(asm);
pushInt(T2);
} else if (methodName == MagicNames.wordIsMax) {
// unsigned comparison generating a boolean
popAddr(T0);
asm.emitLVAL(T1, -1);
asm.emitLVAL(T2, 1);
asm.emitCMPLAddr(T0, T1);
ForwardReference fr = asm.emitForwardBC(EQ);
asm.emitLVAL(T2, 0);
fr.resolve(asm);
pushInt(T2);
} else if (methodName == MagicNames.wordZero || methodName == MagicNames.wordNull) {
asm.emitLVAL(T0, 0);
pushAddr(T0);
} else if (methodName == MagicNames.wordOne) {
asm.emitLVAL(T0, 1);
pushAddr(T0);
} else if (methodName == MagicNames.wordMax) {
asm.emitLVAL(T0, -1);
pushAddr(T0);
} else if (methodName == MagicNames.wordAnd) {
popAddr(T0);
popAddr(T1);
asm.emitAND(T2, T1, T0);
pushAddr(T2);
} else if (methodName == MagicNames.wordOr) {
popAddr(T0);
popAddr(T1);
asm.emitOR(T2, T1, T0);
pushAddr(T2);
} else if (methodName == MagicNames.wordNot) {
popAddr(T0);
asm.emitLVAL(T1, -1);
asm.emitXOR(T2, T1, T0);
pushAddr(T2);
} else if (methodName == MagicNames.wordXor) {
popAddr(T0);
popAddr(T1);
asm.emitXOR(T2, T1, T0);
pushAddr(T2);
} else if (methodName == MagicNames.wordLsh) {
popInt(T0);
popAddr(T1);
asm.emitSLAddr(T2, T1, T0);
pushAddr(T2);
} else if (methodName == MagicNames.wordRshl) {
popInt(T0);
popAddr(T1);
asm.emitSRAddr(T2, T1, T0);
pushAddr(T2);
} else if (methodName == MagicNames.wordRsha) {
popInt(T0);
popAddr(T1);
asm.emitSRA_Addr(T2, T1, T0);
pushAddr(T2);
} else {
return false;
}
return true;
}
use of org.jikesrvm.classloader.RVMArray in project JikesRVM by JikesRVM.
the class CompiledMethods method spaceReport.
/**
* Report on the space used by compiled code and associated mapping information
*/
public static void spaceReport() {
int[] codeCount = new int[CompiledMethod.NUM_COMPILER_TYPES + 1];
int[] codeBytes = new int[CompiledMethod.NUM_COMPILER_TYPES + 1];
int[] mapBytes = new int[CompiledMethod.NUM_COMPILER_TYPES + 1];
RVMArray codeArray = RVMType.CodeArrayType.asArray();
for (int i = 0; i < numCompiledMethods(); i++) {
CompiledMethod cm = getCompiledMethodUnchecked(i);
if (cm == null || !cm.isCompiled())
continue;
int ct = cm.getCompilerType();
codeCount[ct]++;
int size = codeArray.getInstanceSize(cm.numberOfInstructions());
codeBytes[ct] += Memory.alignUp(size, BYTES_IN_ADDRESS);
mapBytes[ct] += cm.size();
}
VM.sysWriteln("Compiled code space report");
VM.sysWriteln();
VM.sysWriteln(" Baseline Compiler");
VM.sysWriteln(" Number of compiled methods = " + codeCount[CompiledMethod.BASELINE]);
VM.sysWriteln(" Total size of code (bytes) = " + codeBytes[CompiledMethod.BASELINE]);
VM.sysWriteln(" Total size of mapping data (bytes) = " + mapBytes[CompiledMethod.BASELINE]);
if (codeCount[CompiledMethod.OPT] > 0) {
VM.sysWriteln(" Optimizing Compiler");
VM.sysWriteln(" Number of compiled methods = " + codeCount[CompiledMethod.OPT]);
VM.sysWriteln(" Total size of code (bytes) = " + codeBytes[CompiledMethod.OPT]);
VM.sysWriteln(" Total size of mapping data (bytes) = " + mapBytes[CompiledMethod.OPT]);
}
if (codeCount[CompiledMethod.JNI] > 0) {
VM.sysWriteln(" JNI Stub Compiler (Java->C stubs for native methods)");
VM.sysWriteln(" Number of compiled methods = " + codeCount[CompiledMethod.JNI]);
VM.sysWriteln(" Total size of code (bytes) = " + codeBytes[CompiledMethod.JNI]);
VM.sysWriteln(" Total size of mapping data (bytes) = " + mapBytes[CompiledMethod.JNI]);
}
if (!VM.runningVM) {
TreeMap<String, Integer> packageData = new TreeMap<String, Integer>(new Comparator<String>() {
@Override
public int compare(String a, String b) {
return a.compareTo(b);
}
});
for (int i = 0; i < numCompiledMethods(); ++i) {
CompiledMethod compiledMethod = getCompiledMethodUnchecked(i);
if (compiledMethod != null) {
RVMMethod m = compiledMethod.getMethod();
if (m != null && compiledMethod.isCompiled()) {
String packageName = m.getDeclaringClass().getPackageName();
int numInstructions = compiledMethod.numberOfInstructions();
Integer val = packageData.get(packageName);
if (val == null) {
val = numInstructions;
} else {
val = val + numInstructions;
}
packageData.put(packageName, val);
}
}
}
VM.sysWriteln("------------------------------------------------------------------------------------------");
VM.sysWriteln(" Break down of code space usage by package (bytes):");
VM.sysWriteln("------------------------------------------------------------------------------------------");
Set<String> keys = packageData.keySet();
int maxPackageNameSize = 0;
for (String packageName : keys) {
maxPackageNameSize = Math.max(maxPackageNameSize, packageName.length());
}
maxPackageNameSize++;
for (String packageName : keys) {
VM.sysWriteField(maxPackageNameSize, packageName);
VM.sysWriteField(10, packageData.get(packageName));
VM.sysWriteln();
}
}
}
use of org.jikesrvm.classloader.RVMArray in project JikesRVM by JikesRVM.
the class VMInstrumentationImpl method getObjectSize.
static long getObjectSize(Object objectToSize) {
Class<?> cl = objectToSize.getClass();
RVMType vmType = java.lang.JikesRVMSupport.getTypeForClass(cl);
if (cl.isArray()) {
RVMArray vmArray = (RVMArray) vmType;
int nelements = java.lang.reflect.Array.getLength(objectToSize);
return vmArray.getInstanceSize(nelements);
} else {
RVMClass vmClass = (RVMClass) vmType;
return vmClass.getInstanceSize();
}
}
use of org.jikesrvm.classloader.RVMArray in project JikesRVM by JikesRVM.
the class DynamicTypeCheckExpansion method generateValueProducingTypeCheck.
/**
* Generate a value-producing dynamic type check.
* This routine assumes that the CFG and code order are
* already correctly established.
* This routine must either remove s or mutuate it.
*
* @param s The Instruction that is to be replaced by
* a value producing type check
* @param ir The IR containing the instruction to be expanded.
* @param RHSobj The RegisterOperand containing the rhs object.
* @param LHStype The RVMType to be tested against.
* @param RHStib The Operand containing the TIB of the rhs.
* @param result The RegisterOperand that the result of dynamic
* type check is to be stored in.
* @return the opt instruction immediately before the
* instruction to continue expansion.
*/
private static Instruction generateValueProducingTypeCheck(Instruction s, IR ir, Operand RHSobj, TypeReference LHStype, Operand RHStib, RegisterOperand result) {
// Is LHStype a class?
if (LHStype.isClassType()) {
RVMClass LHSclass = (RVMClass) LHStype.peekType();
if (LHSclass != null && LHSclass.isResolved()) {
// resolved class or interface
if (LHSclass.isInterface()) {
// A resolved interface (case 4)
int interfaceIndex = LHSclass.getDoesImplementIndex();
int interfaceMask = LHSclass.getDoesImplementBitMask();
RegisterOperand doesImpl = InsertUnary(s, ir, GET_DOES_IMPLEMENT_FROM_TIB, TypeReference.IntArray, RHStib);
RegisterOperand entry = InsertLoadOffset(s, ir, INT_LOAD, TypeReference.Int, doesImpl, Offset.fromIntZeroExtend(interfaceIndex << 2), new LocationOperand(TypeReference.Int), TG());
RegisterOperand bit = insertBinary(s, ir, INT_AND, TypeReference.Int, entry, IC(interfaceMask));
// save to use the cheaper ADDR version of BOOLEAN_CMP
s.insertBefore(BooleanCmp.create(BOOLEAN_CMP_ADDR, result, bit, AC(Address.zero()), ConditionOperand.NOT_EQUAL(), new BranchProfileOperand()));
if (DynamicTypeCheck.MIN_DOES_IMPLEMENT_SIZE <= interfaceIndex) {
RegisterOperand doesImplLength = InsertGuardedUnary(s, ir, ARRAYLENGTH, TypeReference.Int, doesImpl.copy(), TG());
RegisterOperand boundscheck = ir.regpool.makeTempInt();
// save to use the cheaper ADDR version of BOOLEAN_CMP
s.insertBefore(BooleanCmp.create(BOOLEAN_CMP_ADDR, boundscheck, doesImplLength, AC(Address.fromIntSignExtend(interfaceIndex)), ConditionOperand.GREATER(), new BranchProfileOperand()));
s.insertBefore(Binary.create(INT_AND, result.copyD2D(), result.copyD2U(), boundscheck.copyD2U()));
}
Instruction continueAt = s.prevInstructionInCodeOrder();
s.remove();
return continueAt;
} else {
// A resolved class (cases 5 and 6 in DynamicTypeCheck)
if (LHSclass.isFinal()) {
// For a final class, we can do a PTR compare of
// rhsTIB and the TIB of the class
Operand classTIB = getTIB(s, ir, LHSclass);
BooleanCmp.mutate(s, BOOLEAN_CMP_ADDR, result, RHStib, classTIB, ConditionOperand.EQUAL(), new BranchProfileOperand());
return s.prevInstructionInCodeOrder();
} else {
// Do the full blown case 5 or 6 typecheck.
int LHSDepth = LHSclass.getTypeDepth();
int LHSId = LHSclass.getId();
RegisterOperand superclassIds = InsertUnary(s, ir, GET_SUPERCLASS_IDS_FROM_TIB, TypeReference.ShortArray, RHStib);
RegisterOperand refCandidate = InsertLoadOffset(s, ir, USHORT_LOAD, TypeReference.Short, superclassIds, Offset.fromIntZeroExtend(LHSDepth << 1), new LocationOperand(TypeReference.Short), TG());
// save to use the cheaper ADDR version of BOOLEAN_CMP
s.insertBefore(BooleanCmp.create(BOOLEAN_CMP_ADDR, result, refCandidate, AC(Address.fromIntZeroExtend(LHSId)), ConditionOperand.EQUAL(), new BranchProfileOperand()));
if (DynamicTypeCheck.MIN_SUPERCLASS_IDS_SIZE <= LHSDepth) {
RegisterOperand superclassIdsLength = InsertGuardedUnary(s, ir, ARRAYLENGTH, TypeReference.Int, superclassIds.copyD2U(), TG());
RegisterOperand boundscheck = ir.regpool.makeTempInt();
// save to use the cheaper ADDR version of BOOLEAN_CMP
s.insertBefore(BooleanCmp.create(BOOLEAN_CMP_ADDR, boundscheck, superclassIdsLength, AC(Address.fromIntSignExtend(LHSDepth)), ConditionOperand.GREATER(), new BranchProfileOperand()));
s.insertBefore(Binary.create(INT_AND, result.copyD2D(), result.copyD2U(), boundscheck.copyD2U()));
}
Instruction continueAt = s.prevInstructionInCodeOrder();
s.remove();
return continueAt;
}
}
} else {
// A non-resolved class or interface.
// We expect these to be extremely uncommon in opt code in AOS.
// Mutate s into a call to RuntimeEntrypoints.instanceOf
RVMMethod target = Entrypoints.instanceOfMethod;
Call.mutate2(s, CALL, result, AC(target.getOffset()), MethodOperand.STATIC(target), RHSobj, IC(LHStype.getId()));
return callHelper(s, ir);
}
}
if (LHStype.isArrayType()) {
// Case 2 of DynamicTypeCheck: LHS is an array.
RVMArray LHSArray = (RVMArray) LHStype.peekType();
if (LHSArray != null) {
RVMType innermostElementType = LHSArray.getInnermostElementType();
if (innermostElementType.isPrimitiveType() || innermostElementType.isUnboxedType() || (innermostElementType.asClass().isResolved() && innermostElementType.asClass().isFinal())) {
// [^k of primitive or [^k of final class. Just like final classes,
// a PTR compare of rhsTIB and the TIB of the class gives the answer.
Operand classTIB = getTIB(s, ir, LHSArray);
BooleanCmp.mutate(s, BOOLEAN_CMP_ADDR, result, RHStib, classTIB, ConditionOperand.EQUAL(), new BranchProfileOperand());
return s;
}
}
// and do the real work there.
return convertToBranchingTypeCheck(s, ir, RHSobj, LHStype, RHStib, result);
}
OptimizingCompilerException.UNREACHABLE();
return null;
}
Aggregations