use of org.jikesrvm.classloader.RVMClass in project JikesRVM by JikesRVM.
the class BootImageWriter method createBootImageObjects.
/**
* Create (in host JDK address space) the RVM objects that will be
* needed at run time to execute enough of the virtual machine
* to dynamically load and compile the remainder of itself.<p>
*
* Side effects:
* <ul>
* <li>RVM objects are created in host JDK address space
* <li>Statics is populated
* <li>"bootImageTypes" dictionary is populated with name/type pairs
* </ul>
*
* @param typeNames names of RVM classes whose static fields will contain
* the objects comprising the virtual machine bootimage
*/
public static void createBootImageObjects(Vector<String> typeNames, String bootImageTypeNamesFile) throws IllegalAccessException {
Callbacks.notifyBootImage(typeNames.elements());
long startTime = 0;
long stopTime = 0;
//
if (verbosity.isAtLeast(SUMMARY))
say("loading");
if (profile)
startTime = System.currentTimeMillis();
for (String typeName : typeNames) {
//
if (verbosity.isAtLeast(TYPE_NAMES))
say("typeName:", typeName);
//
// create corresponding rvm type
//
RVMType type;
try {
TypeReference tRef = TypeReference.findOrCreate(typeName);
type = tRef.resolve();
} catch (NoClassDefFoundError ncdf) {
ncdf.printStackTrace(System.out);
fail(bootImageTypeNamesFile + " contains a class named \"" + typeName + "\", but we can't find a class with that name: " + ncdf);
// NOTREACHED
return;
} catch (IllegalArgumentException ila) {
/* We should've caught any illegal type names at the data validation
* stage, when we read these in. If not, though,
* TypeReference.findOrCreate() will do its own sanity check. */
ila.printStackTrace(System.out);
fail(bootImageTypeNamesFile + " is supposed to contain type names. It contains \"" + typeName + "\", which does not parse as a legal type name: " + ila);
// NOTREACHED
return;
}
type.markAsBootImageClass();
//
// convert type name from internal form to external form
// ie: Ljava/lang/Object; --> java.lang.Object
// [Ljava/lang/Object; --> [Ljava.lang.Object;
//
// NOTE: duplicate functionality. There is a method that does the same.
//
typeName = typeName.replace('/', '.');
if (typeName.startsWith("L"))
typeName = typeName.substring(1, typeName.length() - 1);
//
// record name/type pair for later lookup by getRvmType()
//
bootImageTypes.put(typeName, type);
}
if (profile) {
stopTime = System.currentTimeMillis();
System.out.println("PROF: \tloading types " + (stopTime - startTime) + " ms");
}
int typeCount = bootImageTypes.size();
JMXSupport.CLASS_LOADING_JMX_SUPPORT.setClassLoadedCountForBootimage(typeCount);
if (verbosity.isAtLeast(SUMMARY))
say(String.valueOf(typeCount), " types");
//
if (profile)
startTime = System.currentTimeMillis();
if (verbosity.isAtLeast(SUMMARY))
say("resolving");
for (RVMType type : bootImageTypes.values()) {
if (verbosity.isAtLeast(DETAILED))
say("resolving " + type);
// The resolution is supposed to be cached already.
type.resolve();
}
//
for (RVMType type : bootImageTypes.values()) {
type.allBootImageTypesResolved();
}
if (profile) {
stopTime = System.currentTimeMillis();
System.out.println("PROF: \tresolving types " + (stopTime - startTime) + " ms");
}
// Set tocRegister early so opt compiler can access it to
// perform fixed_jtoc optimization (compile static addresses into code).
// In the boot image, the bootrecord comes first followed by a
// Address array and then the TOC. To do this, we must fully
// simulate the alignment logic in the allocation code! Rather
// than replicate the allocation code here, we perform dummy
// allocations and then reset the boot image allocator.
BootRecord bootRecord = BootRecord.the_boot_record;
RVMClass rvmBRType = getRvmType(bootRecord.getClass()).asClass();
RVMArray intArrayType = RVMArray.IntArray;
// allocate storage for boot record
bootImage.allocateDataStorage(rvmBRType.getInstanceSize(), ObjectModel.getAlignment(rvmBRType), ObjectModel.getOffsetForAlignment(rvmBRType, false));
// allocate storage for JTOC (force 16byte alignment of the JTOC on Intel)
Address jtocAddress = bootImage.allocateDataStorage(intArrayType.getInstanceSize(0), VM.BuildForIA32 ? 16 : ObjectModel.getAlignment(intArrayType), ObjectModel.getOffsetForAlignment(intArrayType, false));
bootImage.resetAllocator();
bootRecord.tocRegister = jtocAddress.plus(intArrayType.getInstanceSize(Statics.middleOfTable));
// set up some stuff we need for compiling
ArchitectureFactory.initOutOfLineMachineCode();
//
if (profile)
startTime = System.currentTimeMillis();
if (verbosity.isAtLeast(SUMMARY))
say("instantiating");
if (verbosity.isAtLeast(SUMMARY))
say("setting up compilation infrastructure and pre-compiling easy cases");
CompilationOrder order = new CompilationOrder(typeCount, numThreads);
for (RVMType type : bootImageTypes.values()) {
order.addType(type);
}
order.fixUpMissingSuperClasses();
if (verbosity.isAtLeast(SUMMARY))
say(" compiling with " + numThreads + " threads");
ThreadFactory threadFactory = new KillVMonUncaughtExceptionThreadFactory();
ExecutorService threadPool = Executors.newFixedThreadPool(numThreads, threadFactory);
int runnableCount = order.getCountOfNeededWorkers();
while (runnableCount > 0) {
try {
threadPool.execute(order.getNextRunnable());
runnableCount--;
} catch (InterruptedException e) {
throw new Error("Build interrupted", e);
}
}
threadPool.shutdown();
try {
while (!threadPool.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS)) {
say("Compilation really shouldn't take this long");
}
} catch (InterruptedException e) {
throw new Error("Build interrupted", e);
}
if (BootImageWorker.instantiationFailed) {
throw new Error("Error during instantiaion");
}
if (profile) {
stopTime = System.currentTimeMillis();
System.out.println("PROF: \tinstantiating types " + (stopTime - startTime) + " ms");
}
// Free up unnecessary Statics data structures
staticsJunk = Statics.bootImageInstantiationFinished();
// Do the portion of JNIEnvironment initialization that can be done
// at bootimage writing time.
FunctionTable functionTable = BuildJNIFunctionTable.buildTable();
JNIEnvironment.initFunctionTable(functionTable);
//
if (verbosity.isAtLeast(SUMMARY))
say("field info gathering");
if (profile)
startTime = System.currentTimeMillis();
bootImageTypeFields = new HashMap<Key, FieldInfo>(typeCount);
HashSet<String> invalidEntrys = new HashSet<String>();
// First retrieve the jdk Field table for each class of interest
for (RVMType rvmType : bootImageTypes.values()) {
FieldInfo fieldInfo;
if (!rvmType.isClassType())
// arrays and primitives have no static or instance fields
continue;
Class<?> jdkType = getJdkType(rvmType);
if (jdkType == null)
// won't need the field info
continue;
Key key = new Key(jdkType);
fieldInfo = bootImageTypeFields.get(key);
if (fieldInfo != null) {
fieldInfo.rvmType = rvmType;
} else {
if (verbosity.isAtLeast(SUMMARY))
say("making fieldinfo for " + rvmType);
fieldInfo = new FieldInfo(jdkType, rvmType);
bootImageTypeFields.put(key, fieldInfo);
// Can't add them in next loop as Iterator's don't allow updates to collection
for (Class<?> cls = jdkType.getSuperclass(); cls != null; cls = cls.getSuperclass()) {
key = new Key(cls);
fieldInfo = bootImageTypeFields.get(key);
if (fieldInfo != null) {
break;
} else {
if (verbosity.isAtLeast(SUMMARY))
say("making fieldinfo for " + jdkType);
fieldInfo = new FieldInfo(cls, null);
bootImageTypeFields.put(key, fieldInfo);
}
}
}
}
// Now build the one-to-one instance and static field maps
for (FieldInfo fieldInfo : bootImageTypeFields.values()) {
RVMType rvmType = fieldInfo.rvmType;
if (rvmType == null) {
if (verbosity.isAtLeast(SUMMARY))
say("bootImageTypeField entry has no rvmType:" + fieldInfo.jdkType);
continue;
}
Class<?> jdkType = fieldInfo.jdkType;
if (verbosity.isAtLeast(SUMMARY))
say("building static and instance fieldinfo for " + rvmType);
// First the static fields
//
RVMField[] rvmFields = rvmType.getStaticFields();
fieldInfo.jdkStaticFields = new Field[rvmFields.length];
for (int j = 0; j < rvmFields.length; j++) {
String rvmName = rvmFields[j].getName().toString();
for (Field f : fieldInfo.jdkFields) {
if (f.getName().equals(rvmName)) {
fieldInfo.jdkStaticFields[j] = f;
f.setAccessible(true);
break;
}
}
}
// Now the instance fields
//
rvmFields = rvmType.getInstanceFields();
fieldInfo.jdkInstanceFields = new Field[rvmFields.length];
for (int j = 0; j < rvmFields.length; j++) {
String rvmName = rvmFields[j].getName().toString();
// We look only in the JDK type that corresponds to the
// RVMType of the field's declaring class.
// This is the only way to correctly handle private fields.
jdkType = getJdkType(rvmFields[j].getDeclaringClass());
if (jdkType == null)
continue;
FieldInfo jdkFieldInfo = bootImageTypeFields.get(new Key(jdkType));
if (jdkFieldInfo == null)
continue;
Field[] jdkFields = jdkFieldInfo.jdkFields;
for (Field f : jdkFields) {
if (f.getName().equals(rvmName)) {
fieldInfo.jdkInstanceFields[j] = f;
f.setAccessible(true);
break;
}
}
}
}
if (profile) {
stopTime = System.currentTimeMillis();
System.out.println("PROF: \tcreating type mapping " + (stopTime - startTime) + " ms");
}
//
// Create stack, thread, and processor context in which rvm will begin
// execution.
startupThread = RVMThread.setupBootThread();
byte[] stack = startupThread.getStack();
// sanity check for bootstrap loader
int idx = stack.length - 1;
if (VM.LittleEndian) {
stack[idx--] = (byte) 0xde;
stack[idx--] = (byte) 0xad;
stack[idx--] = (byte) 0xba;
stack[idx--] = (byte) 0xbe;
} else {
stack[idx--] = (byte) 0xbe;
stack[idx--] = (byte) 0xba;
stack[idx--] = (byte) 0xad;
stack[idx--] = (byte) 0xde;
}
//
// Tell RVM where to find itself at execution time.
// This may not be the same place it was at build time, ie. if image is
// moved to another machine with different directory structure.
//
BootstrapClassLoader.setBootstrapRepositories(bootImageRepositoriesAtExecutionTime);
//
if (verbosity.isAtLeast(SUMMARY))
say("populating jtoc with static fields");
if (profile)
startTime = System.currentTimeMillis();
for (RVMType rvmType : bootImageTypes.values()) {
if (verbosity.isAtLeast(SUMMARY))
say(" jtoc for ", rvmType.toString());
if (!rvmType.isClassType())
// arrays and primitives have no static fields
continue;
Class<?> jdkType = getJdkType(rvmType);
if (jdkType == null && verbosity.isAtLeast(SUMMARY)) {
say("host has no class \"" + rvmType + "\"");
}
RVMField[] rvmFields = rvmType.getStaticFields();
for (int j = 0; j < rvmFields.length; ++j) {
RVMField rvmField = rvmFields[j];
TypeReference rvmFieldType = rvmField.getType();
Offset rvmFieldOffset = rvmField.getOffset();
String rvmFieldName = rvmField.getName().toString();
Field jdkFieldAcc = null;
if (jdkType != null && jdkType.equals(java.util.concurrent.locks.AbstractQueuedSynchronizer.class)) {
RVMClass c = (RVMClass) rvmType;
if (rvmFieldName.equals("stateOffset")) {
Statics.setSlotContents(rvmFieldOffset, c.findDeclaredField(Atom.findOrCreateAsciiAtom("state")).getOffset().toLong());
continue;
} else if (rvmFieldName.equals("headOffset")) {
Statics.setSlotContents(rvmFieldOffset, c.findDeclaredField(Atom.findOrCreateAsciiAtom("head")).getOffset().toLong());
continue;
} else if (rvmFieldName.equals("tailOffset")) {
Statics.setSlotContents(rvmFieldOffset, c.findDeclaredField(Atom.findOrCreateAsciiAtom("tail")).getOffset().toLong());
continue;
} else if (rvmFieldName.equals("waitStatusOffset")) {
try {
Statics.setSlotContents(rvmFieldOffset, ((RVMClass) getRvmType(Class.forName("java.util.concurrent.locks.AbstractQueuedSynchronizer$Node"))).findDeclaredField(Atom.findOrCreateAsciiAtom("waitStatus")).getOffset().toLong());
} catch (ClassNotFoundException e) {
throw new Error(e);
}
continue;
}
} else if (jdkType != null && jdkType.equals(java.util.concurrent.locks.LockSupport.class)) {
RVMClass c = (RVMClass) rvmType;
if (rvmFieldName.equals("parkBlockerOffset")) {
Statics.setSlotContents(rvmFieldOffset, ((RVMClass) getRvmType(java.lang.Thread.class)).findDeclaredField(Atom.findOrCreateAsciiAtom("parkBlocker")).getOffset().toLong());
continue;
}
}
if (jdkType != null)
jdkFieldAcc = getJdkFieldAccessor(jdkType, j, STATIC_FIELD);
if (jdkFieldAcc == null) {
// we failed to get a reflective field accessors
if (jdkType != null) {
// we know the type - probably a private field of a java.lang class
if (!copyKnownStaticField(jdkType, rvmFieldName, rvmFieldType, rvmFieldOffset)) {
// we didn't know the field so nullify
if (verbosity.isAtLeast(DETAILED)) {
traceContext.push(rvmFieldType.toString(), jdkType.getName(), rvmFieldName);
traceContext.traceFieldNotInHostJdk();
traceContext.pop();
}
Statics.setSlotContents(rvmFieldOffset, 0);
if (!VM.runningTool)
bootImage.countNulledReference();
invalidEntrys.add(jdkType.getName());
}
} else {
// no accessor and we don't know the type so nullify
if (verbosity.isAtLeast(DETAILED)) {
traceContext.push(rvmFieldType.toString(), rvmFieldType.toString(), rvmFieldName);
traceContext.traceFieldNotInHostJdk();
traceContext.pop();
}
Statics.setSlotContents(rvmFieldOffset, 0);
if (!VM.runningTool)
bootImage.countNulledReference();
invalidEntrys.add(rvmField.getDeclaringClass().toString());
}
continue;
}
if (!Modifier.isStatic(jdkFieldAcc.getModifiers())) {
if (verbosity.isAtLeast(DETAILED))
traceContext.push(rvmFieldType.toString(), jdkType.getName(), rvmFieldName);
if (verbosity.isAtLeast(DETAILED))
traceContext.traceFieldNotStaticInHostJdk();
if (verbosity.isAtLeast(DETAILED))
traceContext.pop();
Statics.setSlotContents(rvmFieldOffset, 0);
if (!VM.runningTool)
bootImage.countNulledReference();
invalidEntrys.add(jdkType.getName());
continue;
}
if (!equalTypes(jdkFieldAcc.getType().getName(), rvmFieldType)) {
if (verbosity.isAtLeast(DETAILED))
traceContext.push(rvmFieldType.toString(), jdkType.getName(), rvmFieldName);
if (verbosity.isAtLeast(DETAILED))
traceContext.traceFieldDifferentTypeInHostJdk();
if (verbosity.isAtLeast(DETAILED))
traceContext.pop();
Statics.setSlotContents(rvmFieldOffset, 0);
if (!VM.runningTool)
bootImage.countNulledReference();
invalidEntrys.add(jdkType.getName());
continue;
}
if (verbosity.isAtLeast(DETAILED))
say(" populating jtoc slot ", String.valueOf(Statics.offsetAsSlot(rvmFieldOffset)), " with ", rvmField.toString());
if (rvmFieldType.isPrimitiveType()) {
// field is logical or numeric type
if (rvmFieldType.isBooleanType()) {
Statics.setSlotContents(rvmFieldOffset, jdkFieldAcc.getBoolean(null) ? 1 : 0);
} else if (rvmFieldType.isByteType()) {
Statics.setSlotContents(rvmFieldOffset, jdkFieldAcc.getByte(null));
} else if (rvmFieldType.isCharType()) {
Statics.setSlotContents(rvmFieldOffset, jdkFieldAcc.getChar(null));
} else if (rvmFieldType.isShortType()) {
Statics.setSlotContents(rvmFieldOffset, jdkFieldAcc.getShort(null));
} else if (rvmFieldType.isIntType()) {
Statics.setSlotContents(rvmFieldOffset, jdkFieldAcc.getInt(null));
} else if (rvmFieldType.isLongType()) {
// note: Endian issues handled in setSlotContents.
Statics.setSlotContents(rvmFieldOffset, jdkFieldAcc.getLong(null));
} else if (rvmFieldType.isFloatType()) {
float f = jdkFieldAcc.getFloat(null);
Statics.setSlotContents(rvmFieldOffset, Float.floatToIntBits(f));
} else if (rvmFieldType.isDoubleType()) {
double d = jdkFieldAcc.getDouble(null);
// note: Endian issues handled in setSlotContents.
Statics.setSlotContents(rvmFieldOffset, Double.doubleToLongBits(d));
} else if (rvmFieldType.equals(TypeReference.Address) || rvmFieldType.equals(TypeReference.Word) || rvmFieldType.equals(TypeReference.Extent) || rvmFieldType.equals(TypeReference.Offset)) {
Object o = jdkFieldAcc.get(null);
String msg = " static field " + rvmField.toString();
boolean warn = rvmFieldType.equals(TypeReference.Address);
Statics.setSlotContents(rvmFieldOffset, getWordValue(o, msg, warn));
} else {
fail("unexpected primitive field type: " + rvmFieldType);
}
} else {
// field is reference type
final Object o = jdkFieldAcc.get(null);
if (verbosity.isAtLeast(ADDRESSES))
say(" setting with ", Services.addressAsHexString(Magic.objectAsAddress(o)));
Statics.setSlotContents(rvmFieldOffset, o);
}
}
}
if (verbosity.isAtLeast(DETAILED)) {
for (final String entry : invalidEntrys) {
say("Static fields of type are invalid: ", entry);
}
}
if (profile) {
stopTime = System.currentTimeMillis();
System.out.println("PROF: \tinitializing jtoc " + (stopTime - startTime) + " ms");
}
}
use of org.jikesrvm.classloader.RVMClass in project JikesRVM by JikesRVM.
the class BC2IR method getConstantOperand.
/**
* Fetch the value of the next operand, a constant, from the bytecode
* stream.
* @param index constant pool index
* @return the value of a literal constant from the bytecode stream,
* encoding as a constant IR operand
*/
public Operand getConstantOperand(int index) {
byte desc = bcodes.getConstantType(index);
RVMClass declaringClass = bcodes.getDeclaringClass();
switch(desc) {
case CP_INT:
return ClassLoaderProxy.getIntFromConstantPool(declaringClass, index);
case CP_FLOAT:
return ClassLoaderProxy.getFloatFromConstantPool(declaringClass, index);
case CP_STRING:
return ClassLoaderProxy.getStringFromConstantPool(declaringClass, index);
case CP_LONG:
return ClassLoaderProxy.getLongFromConstantPool(declaringClass, index);
case CP_DOUBLE:
return ClassLoaderProxy.getDoubleFromConstantPool(declaringClass, index);
case CP_CLASS:
return ClassLoaderProxy.getClassFromConstantPool(declaringClass, index);
default:
if (VM.VerifyAssertions) {
String msg = "invalid literal type: 0x" + Integer.toHexString(desc);
opt_assert(VM.NOT_REACHED, msg);
}
return null;
}
}
use of org.jikesrvm.classloader.RVMClass in project JikesRVM by JikesRVM.
the class BaselineCompilerImpl method emit_invokeinterface.
@Override
protected void emit_invokeinterface(MethodReference methodRef) {
// +1 for "this" parameter
int count = methodRef.getParameterWords() + 1;
RVMMethod resolvedMethod = null;
resolvedMethod = methodRef.peekInterfaceMethod();
// do so inline.
if (VM.BuildForIMTInterfaceInvocation) {
if (methodRef.isMiranda()) {
// TODO: It's not entirely clear that we can just assume that
// the class actually implements the interface.
// However, we don't know what interface we need to be checking
// so there doesn't appear to be much else we can do here.
} else {
if (resolvedMethod == null) {
// Can't successfully resolve it at compile time.
// Call uncommon case typechecking routine to do the right thing when this code actually executes.
asm.emitLAddrToc(T0, Entrypoints.unresolvedInvokeinterfaceImplementsTestMethod.getOffset());
asm.emitMTCTR(T0);
// id of method reference we are trying to call
asm.emitLVAL(T0, methodRef.getId());
// the "this" object
peekAddr(T1, count - 1);
// throw exception, if link error
asm.emitBCCTRL();
} else {
RVMClass interfaceClass = resolvedMethod.getDeclaringClass();
int interfaceIndex = interfaceClass.getDoesImplementIndex();
int interfaceMask = interfaceClass.getDoesImplementBitMask();
// the "this" object
peekAddr(T0, count - 1);
// TIB of "this" object
asm.baselineEmitLoadTIB(T0, T0);
// implements bit vector
asm.emitLAddr(T0, TIB_DOES_IMPLEMENT_INDEX << LOG_BYTES_IN_ADDRESS, T0);
if (DynamicTypeCheck.MIN_DOES_IMPLEMENT_SIZE <= interfaceIndex) {
// must do arraybounds check of implements bit vector
// T1 gets array length
asm.emitLIntOffset(T1, T0, ObjectModel.getArrayLengthOffset());
asm.emitLVAL(T2, interfaceIndex);
asm.emitCMPL(T2, T1);
// if in bounds, jump around trap. TODO: would like to encode "y" bit that this branch is expected to be takem.
ForwardReference fr1 = asm.emitForwardBC(LT);
// encoding of TRAP_ALWAYS MUST_IMPLEMENT_INTERFACE
asm.emitTWI(31, GPR.R12, MUST_IMPLEMENT_TRAP);
fr1.resolve(asm);
}
// Test the appropriate bit and if set, branch around another trap imm
asm.emitLInt(T1, interfaceIndex << LOG_BYTES_IN_INT, T0);
if ((interfaceMask & 0xffff) == interfaceMask) {
asm.emitANDI(S0, T1, interfaceMask);
} else {
if (VM.VerifyAssertions)
VM._assert((interfaceMask & 0xffff0000) == interfaceMask);
asm.emitANDIS(S0, T1, interfaceMask);
}
// TODO: encode "y" bit that branch is likely taken.
ForwardReference fr2 = asm.emitForwardBC(NE);
// encoding of TRAP_ALWAYS MUST_IMPLEMENT_INTERFACE
asm.emitTWI(31, GPR.R12, MUST_IMPLEMENT_TRAP);
fr2.resolve(asm);
}
}
}
// (2) Emit interface invocation sequence.
if (VM.BuildForIMTInterfaceInvocation) {
InterfaceMethodSignature sig = InterfaceMethodSignature.findOrCreate(methodRef);
// T0 is "this"
genMoveParametersToRegisters(true, methodRef);
asm.baselineEmitLoadTIB(S0, T0);
// Load the IMT base into S0
asm.emitLAddr(S0, TIB_INTERFACE_DISPATCH_TABLE_INDEX << LOG_BYTES_IN_ADDRESS, S0);
// the method address
asm.emitLAddrOffset(S0, S0, sig.getIMTOffset());
asm.emitMTCTR(S0);
// pass "hidden" parameter in S1 scratch register
asm.emitLVAL(S1, sig.getId());
asm.emitBCCTRL();
} else {
int itableIndex = -1;
if (VM.BuildForITableInterfaceInvocation && resolvedMethod != null) {
// get the index of the method in the Itable
itableIndex = InterfaceInvocation.getITableIndex(resolvedMethod.getDeclaringClass(), methodRef.getName(), methodRef.getDescriptor());
}
if (itableIndex == -1) {
// itable index is not known at compile-time.
// call "invokeInterface" to resolve object + method id into method address
int methodRefId = methodRef.getId();
asm.emitLAddrToc(T0, Entrypoints.invokeInterfaceMethod.getOffset());
asm.emitMTCTR(T0);
// object
peekAddr(T0, count - 1);
// method id
asm.emitLVAL(T1, methodRefId);
// T0 := resolved method address
asm.emitBCCTRL();
asm.emitMTCTR(T0);
genMoveParametersToRegisters(true, methodRef);
asm.emitBCCTRL();
} else {
// itable index is known at compile-time.
// call "findITable" to resolve object + interface id into
// itable address
asm.emitLAddrToc(T0, Entrypoints.findItableMethod.getOffset());
asm.emitMTCTR(T0);
// object
peekAddr(T0, count - 1);
asm.baselineEmitLoadTIB(T0, T0);
// interface id
asm.emitLVAL(T1, resolvedMethod.getDeclaringClass().getInterfaceId());
// T0 := itable reference
asm.emitBCCTRL();
// T0 := the method to call
asm.emitLAddr(T0, itableIndex << LOG_BYTES_IN_ADDRESS, T0);
asm.emitMTCTR(T0);
// T0 is "this"
genMoveParametersToRegisters(true, methodRef);
asm.emitBCCTRL();
}
}
genPopParametersAndPushReturnValue(true, methodRef);
}
use of org.jikesrvm.classloader.RVMClass in project JikesRVM by JikesRVM.
the class ClassLoaderProxy method includesType.
/**
* Return Constants.YES if the parent type is defintely a supertype
* of the child type.
* <p> Return Constants.NO if the parent type is definitely not
* a supertype of the child type.
* <p> Return Constants.MAYBE if the question cannot be currently answered
* (for example if one/both of the classes is not resolved)
*
* <p> Takes into account the special 'null-type', which corresponds to a {@code null}
* constant.
*
* @param parentType parent type
* @param childType child type
* @return Constants.YES, Constants.NO, or Constants.MAYBE
*/
public static byte includesType(TypeReference parentType, TypeReference childType) {
// NOTE: The ordering of these tests is critical!
if (childType == TypeReference.NULL_TYPE) {
// Sanity assertion that a null isn't being assigned to an unboxed type
if (VM.VerifyAssertions && parentType.isReferenceType())
VM._assert(!parentType.isWordLikeType());
return parentType.isReferenceType() ? YES : NO;
} else if (parentType == TypeReference.NULL_TYPE) {
return NO;
} else if (parentType == childType) {
return YES;
} else if (parentType == TypeReference.Word && childType.isWordLikeType()) {
return YES;
} else if (parentType.isPrimitiveType() || childType.isPrimitiveType()) {
return NO;
} else if (parentType == TypeReference.JavaLangObject) {
return YES;
} else {
// Unboxed types are handled in the word and primitive type case
if (VM.VerifyAssertions) {
VM._assert(!parentType.isWordLikeType() && !childType.isWordLikeType());
}
// (which is allowed/required to load classes to answer the question).
try {
if (parentType.isArrayType()) {
if (childType == TypeReference.JavaLangObject) {
// arrays are subtypes of Object.
return MAYBE;
} else if (!childType.isArrayType()) {
return NO;
} else {
TypeReference parentET = parentType.getInnermostElementType();
if (parentET == TypeReference.JavaLangObject) {
int LHSDimension = parentType.getDimensionality();
int RHSDimension = childType.getDimensionality();
if ((RHSDimension > LHSDimension) || (RHSDimension == LHSDimension && childType.getInnermostElementType().isClassType())) {
return YES;
} else {
return NO;
}
} else {
// If the dimensionalities are not equal then the answer is NO
if (parentType.getDimensionality() == childType.getDimensionality()) {
return includesType(parentET, childType.getInnermostElementType());
} else {
return NO;
}
}
}
} else {
// parentType.isClassType()
if (!childType.isClassType()) {
// parentType is known to not be java.lang.Object.
return NO;
} else {
RVMClass childClass = (RVMClass) childType.peekType();
RVMClass parentClass = (RVMClass) parentType.peekType();
if (childClass != null && parentClass != null) {
if (parentClass.isResolved() && childClass.isResolved() || (VM.writingBootImage && parentClass.isInBootImage() && childClass.isInBootImage())) {
if (parentClass.isInterface()) {
if (RuntimeEntrypoints.isAssignableWith(parentClass, childClass)) {
return YES;
} else {
// possible that a subclass will implement parent.
return childClass.isFinal() ? NO : MAYBE;
}
} else if (childClass.isInterface()) {
// parent is a proper class, child is an interface
return MAYBE;
} else {
// parent & child are both proper classes.
if (RuntimeEntrypoints.isAssignableWith(parentClass, childClass)) {
return YES;
}
// unrelated and we can return NO.
if (childClass.isFinal()) {
return NO;
} else {
if (RuntimeEntrypoints.isAssignableWith(childClass, parentClass)) {
return MAYBE;
} else {
return NO;
}
}
}
}
}
return MAYBE;
}
}
} catch (Throwable e) {
e.printStackTrace();
OptimizingCompilerException.UNREACHABLE();
return MAYBE;
}
}
}
use of org.jikesrvm.classloader.RVMClass in project JikesRVM by JikesRVM.
the class BarrierSize method main.
public static void main(String[] args) throws Exception {
RVMClass barrierSize = JikesRVMSupport.getTypeForClass(BarrierSize.class).asClass();
barrierSize.prepareForFirstUse();
thisClass = Class.forName("BarrierSize");
emptySize = methodInstructionCount("emptyInstanceMethod", (Class[]) null);
Constraints constraints = Selected.Constraints.get();
printHeader("reference barriers");
int oFieldWriteSize = methodInstructionCount("writeToObjectField", Object.class);
int oFieldReadSize = methodInstructionCount("readFromObjectField", (Class[]) null);
printBarrierRequirement("object reference write", constraints.needsObjectReferenceWriteBarrier());
printSizeForMethod("object reference write", oFieldWriteSize);
printBarrierRequirement("object reference read", constraints.needsObjectReferenceReadBarrier());
printSizeForMethod("object reference read", oFieldReadSize);
System.out.println();
printHeader("primitive barriers");
int booleanWriteSize = methodInstructionCount("writeToBooleanField", boolean.class);
printBarrierRequirement("boolean write", constraints.needsBooleanWriteBarrier());
printSizeForMethod("boolean write", booleanWriteSize);
int booleanReadSize = methodInstructionCount("readFromBooleanField", (Class[]) null);
printBarrierRequirement("boolean read", constraints.needsBooleanWriteBarrier());
printSizeForMethod("boolean read", booleanReadSize);
int byteWriteSize = methodInstructionCount("writeToByteField", byte.class);
printBarrierRequirement("byte write", constraints.needsByteWriteBarrier());
printSizeForMethod("byte write", byteWriteSize);
int byteReadSize = methodInstructionCount("readFromByteField", (Class[]) null);
printBarrierRequirement("byte read", constraints.needsByteWriteBarrier());
printSizeForMethod("byte read", byteReadSize);
int charWriteSize = methodInstructionCount("writeToCharField", char.class);
printBarrierRequirement("char write", constraints.needsCharWriteBarrier());
printSizeForMethod("char write", charWriteSize);
int charReadSize = methodInstructionCount("readFromCharField", (Class[]) null);
printBarrierRequirement("char read", constraints.needsCharWriteBarrier());
printSizeForMethod("char read", charReadSize);
int shortWriteSize = methodInstructionCount("writeToShortField", short.class);
printBarrierRequirement("short write", constraints.needsShortWriteBarrier());
printSizeForMethod("short write", shortWriteSize);
int shortReadSize = methodInstructionCount("readFromShortField", (Class[]) null);
printBarrierRequirement("short read", constraints.needsShortWriteBarrier());
printSizeForMethod("short read", shortReadSize);
int intWriteSize = methodInstructionCount("writeToIntField", int.class);
printBarrierRequirement("int write", constraints.needsIntWriteBarrier());
printSizeForMethod("int write", intWriteSize);
int intReadSize = methodInstructionCount("readFromIntField", (Class[]) null);
printBarrierRequirement("int read", constraints.needsIntWriteBarrier());
printSizeForMethod("int read", intReadSize);
int floatWriteSize = methodInstructionCount("writeToFloatField", float.class);
printBarrierRequirement("float write", constraints.needsFloatWriteBarrier());
printSizeForMethod("float write", floatWriteSize);
int floatReadSize = methodInstructionCount("readFromFloatField", (Class[]) null);
printBarrierRequirement("float read", constraints.needsFloatWriteBarrier());
printSizeForMethod("float read", floatReadSize);
int doubleWriteSize = methodInstructionCount("writeToDoubleField", double.class);
printBarrierRequirement("double write", constraints.needsDoubleWriteBarrier());
printSizeForMethod("double write", doubleWriteSize);
int doubleReadSize = methodInstructionCount("readFromDoubleField", (Class[]) null);
printBarrierRequirement("double read", constraints.needsDoubleWriteBarrier());
printSizeForMethod("double read", doubleReadSize);
int longWriteSize = methodInstructionCount("writeToLongField", long.class);
printBarrierRequirement("long write", constraints.needsLongWriteBarrier());
printSizeForMethod("long write", longWriteSize);
int longReadSize = methodInstructionCount("readFromLongField", (Class[]) null);
printBarrierRequirement("long read", constraints.needsLongWriteBarrier());
printSizeForMethod("long read", longReadSize);
System.out.println();
printHeader("primitive array store barriers");
int booleanArrayWriteSize = methodInstructionCount("writeToBooleanArray", boolean.class);
printBarrierRequirement("boolean array write", constraints.needsBooleanWriteBarrier());
printSizeForMethod("boolean array write", booleanArrayWriteSize);
int booleanArrayReadSize = methodInstructionCount("readFromBooleanArray", (Class[]) null);
printBarrierRequirement("boolean array read", constraints.needsBooleanWriteBarrier());
printSizeForMethod("boolean array read", booleanArrayReadSize);
int byteArrayWriteSize = methodInstructionCount("writeToByteArray", byte.class);
printBarrierRequirement("byte array write", constraints.needsByteWriteBarrier());
printSizeForMethod("byte array write", byteArrayWriteSize);
int byteArrayReadSize = methodInstructionCount("readFromByteArray", (Class[]) null);
printBarrierRequirement("byte array read", constraints.needsByteWriteBarrier());
printSizeForMethod("byte array read", byteArrayReadSize);
int charArrayWriteSize = methodInstructionCount("writeToCharArray", char.class);
printBarrierRequirement("char array write", constraints.needsCharWriteBarrier());
printSizeForMethod("char array write", charArrayWriteSize);
int charArrayReadSize = methodInstructionCount("readFromCharArray", (Class[]) null);
printBarrierRequirement("char array read", constraints.needsCharWriteBarrier());
printSizeForMethod("char array read", charArrayReadSize);
int shortArrayWriteSize = methodInstructionCount("writeToShortArray", short.class);
printBarrierRequirement("short array write", constraints.needsShortWriteBarrier());
printSizeForMethod("short array write", shortArrayWriteSize);
int shortArrayReadSize = methodInstructionCount("readFromShortArray", (Class[]) null);
printBarrierRequirement("short array read", constraints.needsShortWriteBarrier());
printSizeForMethod("short array read", shortArrayReadSize);
int intArrayWriteSize = methodInstructionCount("writeToIntArray", int.class);
printBarrierRequirement("int array write", constraints.needsIntWriteBarrier());
printSizeForMethod("int array write", intArrayWriteSize);
int intArrayReadSize = methodInstructionCount("readFromIntArray", (Class[]) null);
printBarrierRequirement("int array read", constraints.needsIntWriteBarrier());
printSizeForMethod("int array read", intArrayReadSize);
int floatArrayWriteSize = methodInstructionCount("writeToFloatArray", float.class);
printBarrierRequirement("float array write", constraints.needsFloatWriteBarrier());
printSizeForMethod("float array write", floatArrayWriteSize);
int floatArrayReadSize = methodInstructionCount("readFromFloatArray", (Class[]) null);
printBarrierRequirement("float array read", constraints.needsFloatWriteBarrier());
printSizeForMethod("float array read", floatArrayReadSize);
int doubleArrayWriteSize = methodInstructionCount("writeToDoubleArray", double.class);
printBarrierRequirement("double array write", constraints.needsDoubleWriteBarrier());
printSizeForMethod("double array write", doubleArrayWriteSize);
int doubleArrayReadSize = methodInstructionCount("readFromDoubleArray", (Class[]) null);
printBarrierRequirement("double array read", constraints.needsDoubleWriteBarrier());
printSizeForMethod("double array read", doubleArrayReadSize);
int longArrayWriteSize = methodInstructionCount("writeToLongArray", long.class);
printBarrierRequirement("long array write", constraints.needsLongWriteBarrier());
printSizeForMethod("long array write", longArrayWriteSize);
int longArrayReadSize = methodInstructionCount("readFromLongArray", (Class[]) null);
printBarrierRequirement("long array read", constraints.needsLongWriteBarrier());
printSizeForMethod("long array read", longArrayReadSize);
System.out.println();
printHeader("unboxed barriers");
int addressWriteSize = methodInstructionCount("writeToAddressField", Address.class);
printBarrierRequirement("address write", constraints.needsAddressWriteBarrier());
printSizeForMethod("address write", addressWriteSize);
int addressReadSize = methodInstructionCount("readFromAddressField", (Class[]) null);
printBarrierRequirement("address read", constraints.needsAddressWriteBarrier());
printSizeForMethod("address read", addressReadSize);
int wordWriteSize = methodInstructionCount("writeToWordField", Word.class);
printBarrierRequirement("word write", constraints.needsWordWriteBarrier());
printSizeForMethod("word write", wordWriteSize);
int wordReadSize = methodInstructionCount("readFromWordField", (Class[]) null);
printBarrierRequirement("word read", constraints.needsWordWriteBarrier());
printSizeForMethod("word read", wordReadSize);
int extentWriteSize = methodInstructionCount("writeToExtentField", Extent.class);
printBarrierRequirement("extent write", constraints.needsExtentWriteBarrier());
printSizeForMethod("extent write", extentWriteSize);
int extentReadSize = methodInstructionCount("readFromExtentField", (Class[]) null);
printBarrierRequirement("extent read", constraints.needsExtentWriteBarrier());
printSizeForMethod("extent read", extentReadSize);
int offsetWriteSize = methodInstructionCount("writeToOffsetField", Offset.class);
printBarrierRequirement("offset write", constraints.needsOffsetWriteBarrier());
printSizeForMethod("offset write", offsetWriteSize);
int offsetReadSize = methodInstructionCount("readFromOffsetField", (Class[]) null);
printBarrierRequirement("offset read", constraints.needsOffsetWriteBarrier());
printSizeForMethod("offset read", offsetReadSize);
}
Aggregations