use of org.jikesrvm.classloader.TypeReference in project JikesRVM by JikesRVM.
the class CallingConvention method returnExpand.
/**
* Expands the calling convention for a particular return instruction.
*
* @param ret the return instruction
* @param ir the IR that contains the return instruction
*/
private static void returnExpand(Instruction ret, IR ir) {
PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet().asIA32();
if (MIR_Return.hasVal(ret)) {
Operand symb1 = MIR_Return.getClearVal(ret);
TypeReference type = symb1.getType();
if (type.isFloatType() || type.isDoubleType()) {
Register r = phys.getReturnFPR();
RegisterOperand rOp = new RegisterOperand(r, type);
if (SSE2_FULL) {
if (type.isFloatType()) {
ret.insertBefore(MIR_Move.create(IA32_MOVSS, rOp, symb1));
} else {
ret.insertBefore(MIR_Move.create(IA32_MOVSD, rOp, symb1));
}
} else {
ret.insertBefore(MIR_Move.create(IA32_FMOV, rOp, symb1));
}
MIR_Return.setVal(ret, rOp.copyD2U());
} else {
Register r = phys.getFirstReturnGPR();
RegisterOperand rOp = new RegisterOperand(r, type);
ret.insertBefore(MIR_Move.create(IA32_MOV, rOp, symb1));
MIR_Return.setVal(ret, rOp.copyD2U());
}
}
if (MIR_Return.hasVal2(ret)) {
if (VM.VerifyAssertions)
VM._assert(VM.BuildFor32Addr);
Operand symb2 = MIR_Return.getClearVal2(ret);
TypeReference type = symb2.getType();
Register r = phys.getSecondReturnGPR();
RegisterOperand rOp = new RegisterOperand(r, type);
ret.insertBefore(MIR_Move.create(IA32_MOV, rOp, symb2));
MIR_Return.setVal2(ret, rOp.copyD2U());
}
// Clear the floating-point stack if dirty.
if (!SSE2_FULL) {
int nSave = 0;
if (MIR_Return.hasVal(ret)) {
Operand symb1 = MIR_Return.getClearVal(ret);
TypeReference type = symb1.getType();
if (type.isFloatType() || type.isDoubleType()) {
nSave = 1;
}
}
ret.insertBefore(MIR_UnaryNoRes.create(IA32_FCLEAR, IC(nSave)));
}
// Set the first 'Val' in the return instruction to hold an integer
// constant which is the number of words to pop from the stack while
// returning from this method.
MIR_Return.setPopBytes(ret, IC(ir.incomingParameterBytes()));
}
use of org.jikesrvm.classloader.TypeReference in project JikesRVM by JikesRVM.
the class CallingConvention method expandParametersToCall.
/**
* Explicitly copy parameters to a call into the appropriate physical
* registers as defined by the calling convention.<p>
*
* Note: Assumes that ESP points to the word before the slot where the
* first parameter should be stored.
*
* @param call the call instruction
* @param ir the IR that contains the call
* @return number of bytes necessary to hold the parameters
*/
private static int expandParametersToCall(Instruction call, IR ir) {
int nGPRParams = 0;
int nFPRParams = 0;
PhysicalRegisterSet phys = (PhysicalRegisterSet) ir.regpool.getPhysicalRegisterSet();
// count the number FPR parameters in a pre-pass
int FPRRegisterParams = countFPRParams(call);
FPRRegisterParams = Math.min(FPRRegisterParams, PhysicalRegisterSet.getNumberOfFPRParams());
// offset, in bytes, from the SP, for the next parameter slot on the
// stack
int parameterBytes = 0;
// Require ESP to be at bottom of frame before a call,
call.insertBefore(MIR_UnaryNoRes.create(REQUIRE_ESP, IC(0)));
// walk over each parameter
// must count then before we start nulling them out!
int numParams = MIR_Call.getNumberOfParams(call);
int nParamsInRegisters = 0;
for (int i = 0; i < numParams; i++) {
Operand param = MIR_Call.getClearParam(call, i);
MIR_Call.setParam(call, i, null);
TypeReference paramType = param.getType();
if (paramType.isFloatingPointType()) {
nFPRParams++;
int size;
if (paramType.isFloatType()) {
size = BYTES_IN_FLOAT;
parameterBytes -= WORDSIZE;
} else {
size = BYTES_IN_DOUBLE;
parameterBytes -= 2 * WORDSIZE;
}
if (nFPRParams > PhysicalRegisterSet.getNumberOfFPRParams()) {
// pass the FP parameter on the stack
Operand M = new StackLocationOperand(false, parameterBytes, size);
if (SSE2_FULL) {
if (paramType.isFloatType()) {
call.insertBefore(MIR_Move.create(IA32_MOVSS, M, param));
} else {
call.insertBefore(MIR_Move.create(IA32_MOVSD, M, param));
}
} else {
call.insertBefore(MIR_Move.create(IA32_FMOV, M, param));
}
} else {
// Pass the parameter in a register.
RegisterOperand real;
if (SSE2_FULL) {
real = new RegisterOperand(phys.getFPRParam(nFPRParams - 1), paramType);
if (paramType.isFloatType()) {
call.insertBefore(MIR_Move.create(IA32_MOVSS, real, param));
} else {
call.insertBefore(MIR_Move.create(IA32_MOVSD, real, param));
}
} else {
// Note that if k FPRs are passed in registers,
// the 1st goes in F(k-1),
// the 2nd goes in F(k-2), etc...
real = new RegisterOperand(phys.getFPRParam(FPRRegisterParams - nFPRParams), paramType);
call.insertBefore(MIR_Move.create(IA32_FMOV, real, param));
}
// Record that the call now has a use of the real register.
MIR_Call.setParam(call, nParamsInRegisters++, real.copy());
}
} else {
nGPRParams++;
parameterBytes -= WORDSIZE;
if (paramIsNativeLongOn64Bit(param)) {
parameterBytes -= WORDSIZE;
}
if (nGPRParams > PhysicalRegisterSet.getNumberOfGPRParams()) {
// parameter into the appropriate stack frame location.
if (paramIsNativeLongOn64Bit(param)) {
call.insertBefore(MIR_UnaryNoRes.create(REQUIRE_ESP, IC(parameterBytes + WORDSIZE * 2)));
call.insertBefore(MIR_UnaryNoRes.create(IA32_PUSH, IC(0)));
} else {
call.insertBefore(MIR_UnaryNoRes.create(REQUIRE_ESP, IC(parameterBytes + WORDSIZE)));
}
call.insertBefore(MIR_UnaryNoRes.create(IA32_PUSH, param));
} else {
// Pass the parameter in a register.
Register phy = phys.getGPRParam(nGPRParams - 1);
RegisterOperand real = new RegisterOperand(phy, paramType);
call.insertBefore(MIR_Move.create(IA32_MOV, real, param));
// Record that the call now has a use of the real register.
MIR_Call.setParam(call, nParamsInRegisters++, real.copy());
}
}
}
return parameterBytes;
}
use of org.jikesrvm.classloader.TypeReference in project JikesRVM by JikesRVM.
the class IndexPropagationSystem method makeCell.
/**
* Create an DF_LatticeCell corresponding to an HeapVariable
* @param o the heap variable
* @return a new lattice cell corresponding to this heap variable
*/
@Override
protected DF_LatticeCell makeCell(Object o) {
if (!(o instanceof HeapVariable)) {
throw new OptimizingCompilerException("IndexPropagation:makeCell");
}
DF_LatticeCell result = null;
Object heapType = ((HeapVariable<?>) o).getHeapType();
if (heapType instanceof TypeReference) {
result = new ArrayCell((HeapVariable<?>) o);
} else {
result = new ObjectCell((HeapVariable<?>) o);
}
return result;
}
use of org.jikesrvm.classloader.TypeReference in project JikesRVM by JikesRVM.
the class BootImageWriter method copyClassToBootImage.
/**
* Write an object instantiating a class to the boot image
* @param scalarImageAddress address already allocated for object
* @param jdkObject object to write
* @param jdkType java.lang.Class of object
* @param rvmScalarType RVM class loader version of type
* @param allocOnly allocate the object only?
* @param overwriteAddress
* @param parentObject
* @param untraced
* @return
* @throws IllegalAccessException
*/
private static Address copyClassToBootImage(Address scalarImageAddress, Object jdkObject, Class<?> jdkType, RVMClass rvmScalarType, boolean allocOnly, Address overwriteAddress, Object parentObject, boolean untraced) throws IllegalAccessException {
if (verbosity.isAtLeast(DETAILED)) {
if (depth == DEPTH_CUTOFF)
say(SPACES.substring(0, depth + 1), "TOO DEEP: cutting off");
else if (depth < DEPTH_CUTOFF) {
String tab = SPACES.substring(0, depth + 1);
if (depth == 0 && jtocCount >= 0)
tab = tab + "jtoc #" + String.valueOf(jtocCount) + " ";
int scalarSize = rvmScalarType.getInstanceSize();
say(tab, "Copying object ", jdkType.getName(), " size=", String.valueOf(scalarSize), (scalarSize >= LARGE_SCALAR_SIZE) ? " large object!!!" : "");
}
}
// copy object fields from host jdk address space into image
// recurse on values that are references
RVMField[] rvmFields = rvmScalarType.getInstanceFields();
for (int i = 0; i < rvmFields.length; ++i) {
RVMField rvmField = rvmFields[i];
TypeReference rvmFieldType = rvmField.getType();
Address rvmFieldAddress = scalarImageAddress.plus(rvmField.getOffset());
String rvmFieldName = rvmField.getName().toString();
Field jdkFieldAcc = getJdkFieldAccessor(jdkType, i, INSTANCE_FIELD);
boolean untracedField = rvmField.isUntraced() || untraced;
if (jdkFieldAcc == null) {
// Field not found via reflection
if (!copyKnownInstanceField(jdkObject, rvmFieldName, rvmFieldType, rvmFieldAddress)) {
// Field wasn't a known Classpath field so write null
if (verbosity.isAtLeast(DETAILED))
traceContext.push(rvmFieldType.toString(), jdkType.getName(), rvmFieldName);
if (verbosity.isAtLeast(DETAILED))
traceContext.traceFieldNotInHostJdk();
if (verbosity.isAtLeast(DETAILED))
traceContext.pop();
if (rvmFieldType.isPrimitiveType()) {
switch(rvmField.getType().getMemoryBytes()) {
case 1:
bootImage.setByte(rvmFieldAddress, 0);
break;
case 2:
bootImage.setHalfWord(rvmFieldAddress, 0);
break;
case 4:
bootImage.setFullWord(rvmFieldAddress, 0);
break;
case 8:
bootImage.setDoubleWord(rvmFieldAddress, 0L);
break;
default:
fail("unexpected field type: " + rvmFieldType);
break;
}
} else {
bootImage.setNullAddressWord(rvmFieldAddress, !untracedField, !untracedField, false);
}
}
continue;
}
if (rvmFieldType.isPrimitiveType()) {
// field is logical or numeric type
if (rvmFieldType.isBooleanType()) {
bootImage.setByte(rvmFieldAddress, jdkFieldAcc.getBoolean(jdkObject) ? 1 : 0);
} else if (rvmFieldType.isByteType()) {
bootImage.setByte(rvmFieldAddress, jdkFieldAcc.getByte(jdkObject));
} else if (rvmFieldType.isCharType()) {
bootImage.setHalfWord(rvmFieldAddress, jdkFieldAcc.getChar(jdkObject));
} else if (rvmFieldType.isShortType()) {
bootImage.setHalfWord(rvmFieldAddress, jdkFieldAcc.getShort(jdkObject));
} else if (rvmFieldType.isIntType()) {
try {
bootImage.setFullWord(rvmFieldAddress, jdkFieldAcc.getInt(jdkObject));
} catch (IllegalArgumentException ex) {
// TODO: Harmony - clean this up
if (jdkObject instanceof java.util.WeakHashMap && rvmFieldName.equals("loadFactor")) {
// the field load factor field in Sun/Classpath is a float but
// in Harmony it has been "optimized" to an int
bootImage.setFullWord(rvmFieldAddress, 7500);
} else if (jdkObject instanceof java.lang.ref.ReferenceQueue && rvmFieldName.equals("head")) {
// Conflicting types between Harmony and Sun
bootImage.setFullWord(rvmFieldAddress, 0);
} else {
System.out.println("type " + rvmScalarType + ", field " + rvmField);
throw ex;
}
}
} else if (rvmFieldType.isLongType()) {
bootImage.setDoubleWord(rvmFieldAddress, jdkFieldAcc.getLong(jdkObject));
} else if (rvmFieldType.isFloatType()) {
float f = jdkFieldAcc.getFloat(jdkObject);
bootImage.setFullWord(rvmFieldAddress, Float.floatToIntBits(f));
} else if (rvmFieldType.isDoubleType()) {
double d = jdkFieldAcc.getDouble(jdkObject);
bootImage.setDoubleWord(rvmFieldAddress, 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(jdkObject);
String msg = " instance field " + rvmField.toString();
boolean warn = rvmFieldType.equals(TypeReference.Address);
bootImage.setAddressWord(rvmFieldAddress, getWordValue(o, msg, warn), false, false);
} else {
fail("unexpected primitive field type: " + rvmFieldType);
}
} else {
// field is reference type
Object value = jdkFieldAcc.get(jdkObject);
if (!allocOnly) {
Class<?> jdkClass = jdkFieldAcc.getDeclaringClass();
if (verbosity.isAtLeast(DETAILED)) {
String typeName = (value == null) ? "(unknown: value was null)" : value.getClass().getName();
traceContext.push(typeName, jdkClass.getName(), jdkFieldAcc.getName());
}
copyReferenceFieldToBootImage(rvmFieldAddress, value, jdkObject, !untracedField, !(untracedField || rvmField.isFinal()), rvmFieldName, rvmFieldType);
if (verbosity.isAtLeast(DETAILED)) {
traceContext.pop();
}
}
}
}
return scalarImageAddress;
}
use of org.jikesrvm.classloader.TypeReference 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");
}
}
Aggregations