use of org.jikesrvm.compilers.common.CodeArray 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.compilers.common.CodeArray in project JikesRVM by JikesRVM.
the class PostThreadSwitch method postProcess.
/**
* This method must not be inlined to keep the correctness
* This method is called at the end of threadSwitch, the caller
* is threadSwitchFrom<...>
*
* @param myThread the currently running thread
*/
@NoInline
public static void postProcess(RVMThread myThread) {
/* We need to generate thread specific code and install new code.
* We have to make sure that no GC happens from here and before
* the new code get executed.
*/
// add branch instruction from CTR.
CodeArray bridge = myThread.bridgeInstructions;
Address bridgeaddr = Magic.objectAsAddress(bridge);
if (VM.TraceOnStackReplacement) {
VM.sysWriteln("osr post processing");
}
Offset offset = myThread.tsFPOffset.plus(STACKFRAME_RETURN_ADDRESS_OFFSET);
Magic.objectAsAddress(myThread.getStack()).store(bridgeaddr, offset);
myThread.tsFPOffset = Offset.zero();
myThread.isWaitingForOsr = false;
myThread.bridgeInstructions = null;
// no GC should happen until the glue code gets executed.
}
use of org.jikesrvm.compilers.common.CodeArray in project JikesRVM by JikesRVM.
the class InterfaceMethodConflictResolver method createStub.
/**
* Creates a conflict resolution stub for the set of interface method signatures {@code l}.
* @param sigIds ids of elements in {@code l}
* @param targets target methods of elements in {@code l}
* @return code that implements the stub
*/
public static CodeArray createStub(int[] sigIds, RVMMethod[] targets) {
// (1) Create an assembler.
int numEntries = sigIds.length;
// pretend each entry is a bytecode
Assembler asm = new Assembler(numEntries);
// (2) signatures must be in ascending order (to build binary search tree).
if (VM.VerifyAssertions) {
for (int i = 1; i < sigIds.length; i++) {
VM._assert(sigIds[i - 1] < sigIds[i]);
}
}
// (3) Assign synthetic bytecode numbers to each switch such that we'll generate them
// in ascending order. This lets us use the general forward branching mechanisms
// of the Assembler.
int[] bcIndices = new int[numEntries];
assignBytecodeIndices(0, bcIndices, 0, numEntries - 1);
// (4) Generate the stub.
insertStubPrologue(asm);
insertStubCase(asm, sigIds, targets, bcIndices, 0, numEntries - 1);
CodeArray stub = asm.getMachineCodes();
// (5) synchronize icache with generated machine code that was written through dcache
if (VM.runningVM)
Memory.sync(Magic.objectAsAddress(stub), stub.length() << LG_INSTRUCTION_WIDTH);
return stub;
}
use of org.jikesrvm.compilers.common.CodeArray in project JikesRVM by JikesRVM.
the class DynamicLinker method lazyMethodInvoker.
/**
* Resolve, compile if necessary, and invoke a method.
* <pre>
* Taken: nothing (calling context is implicit)
* Returned: does not return (method dispatch table is updated and method is executed)
* </pre>
*/
@Entrypoint
static void lazyMethodInvoker() {
DynamicLink dl = DL_Helper.resolveDynamicInvocation();
RVMMethod targMethod = DL_Helper.resolveMethodRef(dl);
DL_Helper.compileMethod(dl, targMethod);
CodeArray code = targMethod.getCurrentEntryCodeArray();
// restore parameters and invoke
Magic.dynamicBridgeTo(code);
// does not return here
if (VM.VerifyAssertions)
VM._assert(NOT_REACHED);
}
use of org.jikesrvm.compilers.common.CodeArray in project JikesRVM by JikesRVM.
the class RVMType method updateArrayMethods.
/**
* Updates the TIB for all array types with the newly (re)compiled method.
*
* @param m the method that was recompiled. Must be a virtual method
* declared by {@code java.lang.Object}.
*/
static synchronized void updateArrayMethods(RVMMethod m) {
if (VM.VerifyAssertions)
VM._assert(m.getDeclaringClass().isJavaLangObjectType());
if (VM.VerifyAssertions)
VM._assert(!m.isStatic());
// Start at slot 1 since nextId is initialized to 1
for (int i = 1; i <= numTypes(); i++) {
RVMType type = RVMType.getType(i);
if (type.isArrayType() && type.isResolved()) {
TIB arrayTIB = type.getTypeInformationBlock();
TIB objectTIB = RVMType.JavaLangObjectType.getTypeInformationBlock();
Offset virtualMethodOffset = m.getOffset();
CodeArray virtualMethod = objectTIB.getVirtualMethod(virtualMethodOffset);
arrayTIB.setVirtualMethod(virtualMethodOffset, virtualMethod);
}
}
}
Aggregations