use of org.jikesrvm.objectmodel.TIB in project JikesRVM by JikesRVM.
the class Barriers method initializeObjectReferenceFields.
/**
* Initializes the reference fields of a given object reference. Most collectors
* won't need to use this method.
* <p>
* The Poisoned collector uses this method. Without using this method,
* all reference fields would be initialized to {@code Word.zero()}. However,
* the value for {@code null} in the Poisoned collector is actually
* {@code Poisoned.poison(ObjectReference.fromObject(null))}, which is
* {@code Word.one()} at the time of this writing. Not initializing the value
* to the real value of {@code null} leads to problems when the value isn't
* explicitly initialized before it is read (i.e. when the programmer relies
* on the JVM to initialize the value to {@code null}). This can occur when
* using intrinsics such as compare-and-swap.
*
* @param ref the object that has the reference field(s)
* @param tibAddr the object's type TIB
*/
@Override
public final void initializeObjectReferenceFields(ObjectReference ref, ObjectReference tibAddr) {
ObjectReference nullValue = Word.zero().toAddress().toObjectReference();
// location is actually unknown. I suppose we could try mapping the
// reference offsets to field offsets if we really needed it.
Word location = Word.zero();
TIB tib = Magic.addressAsTIB(tibAddr.toAddress());
RVMType type = tib.getType();
int[] referenceOffsets = type.getReferenceOffsets();
if (referenceOffsets == RVMType.REFARRAY_OFFSET_ARRAY) {
if (VM.VERIFY_ASSERTIONS)
VM.assertions._assert(type.isArrayType() && type.asArray().getElementType().isReferenceType());
int arrayLength = ObjectModel.getArrayLength(ref.toObject());
for (int i = 0; i < arrayLength; i++) {
Word offset = Offset.fromIntSignExtend(i << LOG_BYTES_IN_ADDRESS).toWord();
Address slotAddress = ref.toAddress().plus(i << LOG_BYTES_IN_ADDRESS);
VM.activePlan.mutator().objectReferenceWrite(ref, slotAddress, nullValue, offset, location, ARRAY_ELEMENT);
}
} else {
if (VM.VERIFY_ASSERTIONS)
VM.assertions._assert(type.isClassType() || (type.isArrayType() && !type.asArray().getElementType().isReferenceType()));
for (int i = 0; i < referenceOffsets.length; i++) {
Word offset = Offset.fromIntSignExtend(referenceOffsets[i]).toWord();
Address slotAddress = ref.toAddress().plus(referenceOffsets[i]);
VM.activePlan.mutator().objectReferenceWrite(ref, slotAddress, nullValue, offset, location, INSTANCE_FIELD);
}
}
}
use of org.jikesrvm.objectmodel.TIB in project JikesRVM by JikesRVM.
the class BootImageWriter method copyToBootImage.
/**
* Copy an object (and, recursively, any of its fields or elements that
* are references) from host jdk address space into image.
*
* @param jdkObject object to be copied
* @param allocOnly if allocOnly is true, the TIB and other reference fields are not recursively copied
* @param overwriteAddress if !overwriteAddress.isMax(), then copy object to given address
* @param parentObject
* @param untraced Do not report any fields of this object as references
* @param alignCode Alignment-encoded value (TIB allocation only)
* @return offset of copied object within image, in bytes
* (OBJECT_NOT_PRESENT --> object not copied:
* it's not part of bootimage)
*/
private static Address copyToBootImage(Object jdkObject, boolean allocOnly, Address overwriteAddress, Object parentObject, boolean untraced, int alignCode) throws IllegalAccessException {
try {
// Return object if it is already copied and not being overwritten
BootImageMap.Entry mapEntry = BootImageMap.findOrCreateEntry(jdkObject);
if ((!mapEntry.imageAddress.EQ(OBJECT_NOT_ALLOCATED)) && overwriteAddress.isMax()) {
return mapEntry.imageAddress;
}
if (verbosity.isAtLeast(DETAILED))
depth++;
// fetch object's type information
Class<?> jdkType = jdkObject.getClass();
RVMType rvmType = getRvmType(jdkType);
if (rvmType == null) {
if (verbosity.isAtLeast(DETAILED))
traverseObject(jdkObject);
if (verbosity.isAtLeast(DETAILED))
depth--;
// object not part of bootimage
return OBJECT_NOT_PRESENT;
}
// copy object to image
if (jdkType.isArray()) {
// allocate space in image prior to recursing
int arrayCount = Array.getLength(jdkObject);
RVMArray rvmArrayType = rvmType.asArray();
boolean needsIdentityHash = mapEntry.requiresIdentityHashCode();
int identityHashValue = mapEntry.getIdentityHashCode();
Address arrayImageAddress = (overwriteAddress.isMax()) ? bootImage.allocateArray(rvmArrayType, arrayCount, needsIdentityHash, identityHashValue, alignCode) : overwriteAddress;
mapEntry.imageAddress = arrayImageAddress;
mapEntry.imageAddress = copyArrayToBootImage(arrayCount, arrayImageAddress, jdkObject, jdkType, rvmArrayType, allocOnly, overwriteAddress, parentObject, untraced);
// already
if (!allocOnly) {
if (verbosity.isAtLeast(DETAILED))
traceContext.push("", jdkObject.getClass().getName(), "tib");
Address tibImageAddress = copyToBootImage(rvmType.getTypeInformationBlock(), allocOnly, Address.max(), jdkObject, false, AlignmentEncoding.ALIGN_CODE_NONE);
if (verbosity.isAtLeast(DETAILED))
traceContext.pop();
if (tibImageAddress.EQ(OBJECT_NOT_ALLOCATED)) {
fail("can't copy tib for " + jdkObject);
}
ObjectModel.setTIB(bootImage, mapEntry.imageAddress, tibImageAddress, rvmType);
}
} else if (jdkObject instanceof TIB) {
Object backing = ((RuntimeTable<?>) jdkObject).getBacking();
int alignCodeValue = ((TIB) jdkObject).getAlignData();
if (verbosity.isAtLeast(DETAILED))
say("Encoding value " + alignCodeValue + " into tib");
/* Copy the backing array, and then replace its TIB */
mapEntry.imageAddress = copyToBootImage(backing, allocOnly, overwriteAddress, jdkObject, rvmType.getTypeRef().isRuntimeTable(), alignCodeValue);
if (verbosity.isAtLeast(DETAILED))
say(String.format("TIB address = %x, encoded value = %d, requested = %d%n", mapEntry.imageAddress.toInt(), AlignmentEncoding.extractTibCode(mapEntry.imageAddress), alignCodeValue));
if (!allocOnly) {
copyTIBToBootImage(rvmType, jdkObject, mapEntry.imageAddress);
}
} else if (rvmType == RVMType.ObjectReferenceArrayType || rvmType.getTypeRef().isRuntimeTable()) {
Object backing = ((RuntimeTable<?>) jdkObject).getBacking();
/* Copy the backing array, and then replace its TIB */
mapEntry.imageAddress = copyToBootImage(backing, allocOnly, overwriteAddress, jdkObject, rvmType.getTypeRef().isRuntimeTable(), AlignmentEncoding.ALIGN_CODE_NONE);
if (!allocOnly) {
copyTIBToBootImage(rvmType, jdkObject, mapEntry.imageAddress);
}
} else if (jdkObject instanceof RuntimeTable) {
Object backing = ((RuntimeTable<?>) jdkObject).getBacking();
mapEntry.imageAddress = copyMagicArrayToBootImage(backing, rvmType.asArray(), allocOnly, overwriteAddress, parentObject);
} else if (rvmType == RVMType.CodeArrayType) {
// Handle the code array that is represented as either byte or int arrays
if (verbosity.isAtLeast(DETAILED))
depth--;
Object backing = ((CodeArray) jdkObject).getBacking();
return copyMagicArrayToBootImage(backing, rvmType.asArray(), allocOnly, overwriteAddress, parentObject);
} else if (rvmType.getTypeRef().isMagicType()) {
say("Unhandled copying of magic type: " + rvmType.getDescriptor().toString() + " in object of type " + parentObject.getClass().toString());
fail("incomplete boot image support");
} else {
// allocate space in image
if (rvmType instanceof RVMArray)
fail("This isn't a scalar " + rvmType);
RVMClass rvmScalarType = rvmType.asClass();
boolean needsIdentityHash = mapEntry.requiresIdentityHashCode();
int identityHashValue = mapEntry.getIdentityHashCode();
Address scalarImageAddress = (overwriteAddress.isMax()) ? bootImage.allocateScalar(rvmScalarType, needsIdentityHash, identityHashValue) : overwriteAddress;
mapEntry.imageAddress = scalarImageAddress;
mapEntry.imageAddress = copyClassToBootImage(scalarImageAddress, jdkObject, jdkType, rvmScalarType, allocOnly, overwriteAddress, parentObject, untraced);
// already
if (!allocOnly) {
copyTIBToBootImage(rvmType, jdkObject, mapEntry.imageAddress);
}
}
if (verbosity.isAtLeast(DETAILED))
depth--;
return mapEntry.imageAddress;
} catch (Error e) {
e = new Error(e.getMessage() + "\nwhile copying " + jdkObject + (jdkObject != null ? ":" + jdkObject.getClass() : "") + " from " + parentObject + (parentObject != null ? ":" + parentObject.getClass() : ""), e.getCause() != null ? e.getCause() : e);
throw e;
}
}
use of org.jikesrvm.objectmodel.TIB in project JikesRVM by JikesRVM.
the class BootImageWriter method copyArrayToBootImage.
/**
* Write array to boot image
* @param arrayCount
* @param arrayImageAddress
* @param jdkObject
* @param jdkType
* @param rvmArrayType
* @param allocOnly
* @param overwriteAddress
* @param parentObject
* @param untraced
* @return
* @throws IllegalAccessException
*/
private static Address copyArrayToBootImage(int arrayCount, Address arrayImageAddress, Object jdkObject, Class<?> jdkType, RVMArray rvmArrayType, 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 arraySize = rvmArrayType.getInstanceSize(arrayCount);
say(tab, "Copying array ", jdkType.getName(), " length=", String.valueOf(arrayCount), (arraySize >= LARGE_ARRAY_SIZE) ? " large object!!!" : "");
}
}
RVMType rvmElementType = rvmArrayType.getElementType();
// recurse on values that are references
if (rvmElementType.isPrimitiveType()) {
// array element is logical or numeric type
if (rvmElementType.equals(RVMType.BooleanType)) {
boolean[] values = (boolean[]) jdkObject;
for (int i = 0; i < arrayCount; ++i) bootImage.setByte(arrayImageAddress.plus(i), values[i] ? 1 : 0);
} else if (rvmElementType.equals(RVMType.ByteType)) {
byte[] values = (byte[]) jdkObject;
for (int i = 0; i < arrayCount; ++i) bootImage.setByte(arrayImageAddress.plus(i), values[i]);
} else if (rvmElementType.equals(RVMType.CharType)) {
char[] values = (char[]) jdkObject;
for (int i = 0; i < arrayCount; ++i) bootImage.setHalfWord(arrayImageAddress.plus(i << LOG_BYTES_IN_CHAR), values[i]);
} else if (rvmElementType.equals(RVMType.ShortType)) {
short[] values = (short[]) jdkObject;
for (int i = 0; i < arrayCount; ++i) bootImage.setHalfWord(arrayImageAddress.plus(i << LOG_BYTES_IN_SHORT), values[i]);
} else if (rvmElementType.equals(RVMType.IntType)) {
int[] values = (int[]) jdkObject;
for (int i = 0; i < arrayCount; ++i) bootImage.setFullWord(arrayImageAddress.plus(i << LOG_BYTES_IN_INT), values[i]);
} else if (rvmElementType.equals(RVMType.LongType)) {
long[] values = (long[]) jdkObject;
for (int i = 0; i < arrayCount; ++i) bootImage.setDoubleWord(arrayImageAddress.plus(i << LOG_BYTES_IN_LONG), values[i]);
} else if (rvmElementType.equals(RVMType.FloatType)) {
float[] values = (float[]) jdkObject;
for (int i = 0; i < arrayCount; ++i) bootImage.setFullWord(arrayImageAddress.plus(i << LOG_BYTES_IN_FLOAT), Float.floatToIntBits(values[i]));
} else if (rvmElementType.equals(RVMType.DoubleType)) {
double[] values = (double[]) jdkObject;
for (int i = 0; i < arrayCount; ++i) bootImage.setDoubleWord(arrayImageAddress.plus(i << LOG_BYTES_IN_DOUBLE), Double.doubleToLongBits(values[i]));
} else {
fail("unexpected primitive array type: " + rvmArrayType);
}
} else {
// array element is reference type
boolean isTIB = parentObject instanceof TIB;
Object[] values = (Object[]) jdkObject;
Class<?> jdkClass = jdkObject.getClass();
if (!allocOnly) {
for (int i = 0; i < arrayCount; ++i) {
if (values[i] != null) {
if (verbosity.isAtLeast(DETAILED))
traceContext.push(values[i].getClass().getName(), jdkClass.getName(), i);
if (isTIB && values[i] instanceof Word) {
bootImage.setAddressWord(arrayImageAddress.plus(i << LOG_BYTES_IN_ADDRESS), (Word) values[i], false, false);
} else if (isTIB && values[i] == LazyCompilationTrampoline.getInstructions()) {
Address codeAddress = arrayImageAddress.plus(((TIB) parentObject).lazyMethodInvokerTrampolineIndex() << LOG_BYTES_IN_ADDRESS);
bootImage.setAddressWord(arrayImageAddress.plus(i << LOG_BYTES_IN_ADDRESS), codeAddress.toWord(), false, false);
} else {
copyReferenceFieldToBootImage(arrayImageAddress.plus(i << LOG_BYTES_IN_ADDRESS), values[i], jdkObject, !untraced, !untraced, null, null);
}
if (verbosity.isAtLeast(DETAILED))
traceContext.pop();
} else {
bootImage.setNullAddressWord(arrayImageAddress.plus(i << LOG_BYTES_IN_ADDRESS), !untraced, !untraced, true);
}
}
}
}
return arrayImageAddress;
}
use of org.jikesrvm.objectmodel.TIB in project JikesRVM by JikesRVM.
the class ObjectModel method getAlignWhenCopied.
@Override
public int getAlignWhenCopied(ObjectReference object) {
TIB tib = org.jikesrvm.objectmodel.ObjectModel.getTIB(object);
RVMType type = tib.getType();
if (type.isArrayType()) {
return org.jikesrvm.objectmodel.ObjectModel.getAlignment(type.asArray(), object.toObject());
} else {
return org.jikesrvm.objectmodel.ObjectModel.getAlignment(type.asClass(), object.toObject());
}
}
use of org.jikesrvm.objectmodel.TIB in project JikesRVM by JikesRVM.
the class ObjectModel method isAcyclic.
@Override
@Inline
public boolean isAcyclic(ObjectReference typeRef) {
TIB tib = Magic.addressAsTIB(typeRef.toAddress());
RVMType type = tib.getType();
return type.isAcyclicReference();
}
Aggregations