use of org.vmmagic.unboxed.Word in project JikesRVM by JikesRVM.
the class BootImageWriter method check.
private static void check(Word value, String msg) {
// yes, max
Word low = ObjectModel.maximumObjectRef(Address.zero()).toWord();
// we shouldn't have that many objects
Word high = Word.fromIntZeroExtend(0x10000000);
if (value.GT(low) && value.LT(high) && !value.EQ(Word.fromIntZeroExtend(32767)) && (value.LT(Word.fromIntZeroExtend(4088)) || value.GT(Word.fromIntZeroExtend(4096)))) {
say("Warning: Suspicious Address value of ", Services.addressAsHexString(value.toAddress()), " written for " + msg);
}
}
use of org.vmmagic.unboxed.Word in project JikesRVM by JikesRVM.
the class BootImageWriter method getWordValue.
private static Word getWordValue(Object addr, String msg, boolean warn) {
if (addr == null)
return Word.zero();
Word value = Word.zero();
if (addr instanceof Address) {
value = ((Address) addr).toWord();
} else if (addr instanceof ObjectReference) {
value = ((ObjectReference) addr).toAddress().toWord();
} else if (addr instanceof Word) {
value = (Word) addr;
} else if (addr instanceof Extent) {
value = ((Extent) addr).toWord();
} else if (addr instanceof Offset) {
value = ((Offset) addr).toWord();
} else {
say("Unhandled supposed address value: " + addr);
say(msg);
fail("incomplete boot image support");
}
if (warn)
check(value, msg);
return value;
}
use of org.vmmagic.unboxed.Word in project JikesRVM by JikesRVM.
the class JNIHelpers method pushVarArgToSpillArea.
/**
* This method supports var args passed from C.<p>
*
* TODO update for AIX removal
*
* In the AIX C convention, the caller keeps the first 8 words in registers and
* the rest in the spill area in the caller frame. The callee will push the values
* in registers out to the spill area of the caller frame and use the beginning
* address of this spill area as the var arg address.<p>
*
* For the JNI functions that takes var args, their prolog code will save the
* var arg in the glue frame because the values in the register may be lost by
* subsequent calls.<p>
*
* This method copies the var arg values that were saved earlier in glue frame into
* the spill area of the original caller, thereby doing the work that the callee
* normally performs in the AIX C convention..<p>
*
* NOTE: this method assumes that it is immediately above the
* invokeWithDotDotVarArg frame, the JNI frame, the glue frame and
* the C caller frame in the respective order.
* Therefore, this method will not work if called from anywhere else
* <pre>
*
* | fp | <- JNIEnvironment.pushVarArgToSpillArea
* | mid |
* | xxx |
* | |
* | |
* |------|
* | fp | <- JNIEnvironment.invokeWithDotDotVarArg frame
* | mid |
* | xxx |
* | |
* | |
* | |
* |------|
* | fp | <- JNI method frame
* | mid |
* | xxx |
* | |
* | |
* | |
* |------|
* | fp | <- glue frame
* | mid |
* + xxx +
* | r3 | volatile save area
* | r4 |
* | r5 |
* | r6 | vararg GPR[6-10]save area <- VARARG_AREA_OFFSET
* | r7 |
* | r8 |
* | r9 |
* | r10 |
* | fpr1 | vararg FPR[1-3] save area (also used as volatile FPR[1-6] save area)
* | fpr2 |
* | fpr3 |
* | fpr4 |
* | fpr5 |
* + fpr6 +
* | r13 | nonvolatile GPR[13-31] save area
* | ... |
* + r31 +
* | fpr14| nonvolatile FPR[14-31] save area
* | ... |
* | fpr31|
* |topjav| offset to preceding Java to C glue frame
* |------|
* | fp | <- Native C caller frame
* | cr |
* | lr |
* | resv |
* | resv |
* + toc +
* | 0 | spill area initially not filled
* | 1 | to be filled by this method
* | 2 |
* | 3 |
* | 4 |
* | 5 |
* | 6 |
* | 7 |
* | 8 | spill area already filled by caller
* | 9 |
* | |
* | |
* | |
* </pre>
*
* @param methodID a MemberReference id
* @param skip4Args if true, the calling JNI function has 4 args before the vararg
* if false, the calling JNI function has 3 args before the vararg
* @return the starting address of the vararg in the caller stack frame
*/
@NoInline
private static Address pushVarArgToSpillArea(int methodID, boolean skip4Args) throws Exception {
if (!(VM.BuildForPower64ELF_ABI || VM.BuildForSVR4ABI)) {
if (VM.VerifyAssertions)
VM._assert(VM.NOT_REACHED);
return Address.zero();
}
int glueFrameSize = JNI_GLUE_FRAME_SIZE;
// get the FP for this stack frame and traverse 3 frames to get to the glue frame
Address gluefp = // *.ppc.JNIHelpers.invoke*
Magic.getFramePointer().plus(StackFrameLayout.getStackFramePointerOffset()).loadAddress();
// architecture.JNIHelpers.invoke*
gluefp = gluefp.plus(StackFrameLayout.getStackFramePointerOffset()).loadAddress();
// JNIFunctions
gluefp = gluefp.plus(StackFrameLayout.getStackFramePointerOffset()).loadAddress();
// glue frame
gluefp = gluefp.plus(StackFrameLayout.getStackFramePointerOffset()).loadAddress();
// compute the offset into the area where the vararg GPR[6-10] and FPR[1-3] are saved
// skipping the args which are not part of the arguments for the target method
// For Call<type>Method functions and NewObject, skip 3 args
// For CallNonvirtual<type>Method functions, skip 4 args
Offset varargGPROffset = Offset.fromIntSignExtend(VARARG_AREA_OFFSET + (skip4Args ? BYTES_IN_ADDRESS : 0));
Offset varargFPROffset = varargGPROffset.plus(5 * BYTES_IN_ADDRESS);
// compute the offset into the spill area of the native caller frame,
// skipping the args which are not part of the arguments for the target method
// For Call<type>Method functions, skip 3 args
// For CallNonvirtual<type>Method functions, skip 4 args
Offset spillAreaLimit = Offset.fromIntSignExtend(glueFrameSize + NATIVE_FRAME_HEADER_SIZE + 8 * BYTES_IN_ADDRESS);
Offset spillAreaOffset = Offset.fromIntSignExtend(glueFrameSize + NATIVE_FRAME_HEADER_SIZE + (skip4Args ? 4 * BYTES_IN_ADDRESS : 3 * BYTES_IN_ADDRESS));
// address to return pointing to the var arg list
Address varargAddress = gluefp.plus(spillAreaOffset);
// VM.sysWrite("pushVarArgToSpillArea: var arg at " +
// Services.intAsHexString(varargAddress) + "\n");
RVMMethod targetMethod = MemberReference.getMethodRef(methodID).resolve();
TypeReference[] argTypes = targetMethod.getParameterTypes();
int argCount = argTypes.length;
for (int i = 0; i < argCount && spillAreaOffset.sLT(spillAreaLimit); i++) {
Word hiword, loword;
if (argTypes[i].isFloatingPointType()) {
// move 2 words from the vararg FPR save area into the spill area of the caller
hiword = gluefp.loadWord(varargFPROffset);
varargFPROffset = varargFPROffset.plus(BYTES_IN_ADDRESS);
if (VM.BuildFor32Addr) {
loword = gluefp.loadWord(varargFPROffset);
varargFPROffset = varargFPROffset.plus(BYTES_IN_ADDRESS);
}
gluefp.store(hiword, spillAreaOffset);
spillAreaOffset = spillAreaOffset.plus(BYTES_IN_ADDRESS);
if (VM.BuildFor32Addr) {
gluefp.store(loword, spillAreaOffset);
spillAreaOffset = spillAreaOffset.plus(BYTES_IN_ADDRESS);
}
} else if (argTypes[i].isLongType()) {
// move 2 words from the vararg GPR save area into the spill area of the caller
hiword = gluefp.loadWord(varargGPROffset);
varargGPROffset = varargGPROffset.plus(BYTES_IN_ADDRESS);
gluefp.store(hiword, spillAreaOffset);
spillAreaOffset = spillAreaOffset.plus(BYTES_IN_ADDRESS);
// this covers the case when the long value straddles the spill boundary
if (VM.BuildFor32Addr && spillAreaOffset.sLT(spillAreaLimit)) {
loword = gluefp.loadWord(varargGPROffset);
varargGPROffset = varargGPROffset.plus(BYTES_IN_ADDRESS);
gluefp.store(loword, spillAreaOffset);
spillAreaOffset = spillAreaOffset.plus(BYTES_IN_ADDRESS);
}
} else {
hiword = gluefp.loadWord(varargGPROffset);
varargGPROffset = varargGPROffset.plus(BYTES_IN_ADDRESS);
gluefp.store(hiword, spillAreaOffset);
spillAreaOffset = spillAreaOffset.plus(BYTES_IN_ADDRESS);
}
}
// return the address of the beginning of the vararg to use in invoking the target method
return varargAddress;
}
use of org.vmmagic.unboxed.Word in project JikesRVM by JikesRVM.
the class JNIGenericHelpers method packageParametersFromJValuePtr.
/**
* Repackage the arguments passed as an array of jvalue into an array of Object,
* used by the JNI functions CallStatic<type>MethodA
* @param targetMethod the target {@link MethodReference}
* @param argAddress an address into the C space for the array of jvalue unions
* @return an Object array holding the arguments wrapped at Objects
*/
protected static Object[] packageParametersFromJValuePtr(MethodReference targetMethod, Address argAddress) {
TypeReference[] argTypes = targetMethod.getParameterTypes();
int argCount = argTypes.length;
Object[] argObjectArray = new Object[argCount];
// get the JNIEnvironment for this thread in case we need to dereference any object arg
JNIEnvironment env = RVMThread.getCurrentThread().getJNIEnv();
Address addr = argAddress;
for (int i = 0; i < argCount; i++, addr = addr.plus(BYTES_IN_LONG)) {
// convert and wrap the argument according to the expected type
if (argTypes[i].isReferenceType()) {
// Avoid endianness issues by loading the whole slot
Word wholeSlot = addr.loadWord();
// for object, the arg is a JREF index, dereference to get the real object
int JREFindex = wholeSlot.toInt();
argObjectArray[i] = env.getJNIRef(JREFindex);
} else if (argTypes[i].isIntType()) {
argObjectArray[i] = addr.loadInt();
} else if (argTypes[i].isLongType()) {
argObjectArray[i] = addr.loadLong();
} else if (argTypes[i].isBooleanType()) {
// the 0/1 bit is stored in the high byte
argObjectArray[i] = addr.loadByte() != 0;
} else if (argTypes[i].isByteType()) {
// the target byte is stored in the high byte
argObjectArray[i] = addr.loadByte();
} else if (argTypes[i].isCharType()) {
// char is stored in the high 2 bytes
argObjectArray[i] = addr.loadChar();
} else if (argTypes[i].isShortType()) {
// short is stored in the high 2 bytes
argObjectArray[i] = addr.loadShort();
} else if (argTypes[i].isFloatType()) {
argObjectArray[i] = addr.loadFloat();
} else {
if (VM.VerifyAssertions)
VM._assert(argTypes[i].isDoubleType());
argObjectArray[i] = addr.loadDouble();
}
}
return argObjectArray;
}
use of org.vmmagic.unboxed.Word in project JikesRVM by JikesRVM.
the class JavaHeader method moveObject.
/**
* Copies an object to the given raw storage address.
*
* @param toObj the target object. If this is non-{@code null}, the target
* address must be {@code Address.zero()}.
* @param toAddress the target address. If this is not {@code Address.zero()},
* the target object must be {@code null}.
* @param fromObj the object to copy from
* @param numBytes the number of bytes to copy
* @return the reference of the object's copy
*/
@Inline
public static Object moveObject(Address toAddress, Object fromObj, Object toObj, int numBytes) {
if (VM.VerifyAssertions)
VM._assert(toAddress.isZero() || toObj == null);
// Default values
int copyBytes = numBytes;
int objRefOffset = OBJECT_REF_OFFSET;
Word statusWord = Word.zero();
Word hashState = HASH_STATE_UNHASHED;
if (ADDRESS_BASED_HASHING) {
// Read the hash state (used below)
statusWord = Magic.getWordAtOffset(fromObj, STATUS_OFFSET);
hashState = statusWord.and(HASH_STATE_MASK);
if (hashState.EQ(HASH_STATE_HASHED)) {
// We do not copy the hashcode, but we do allocate it
copyBytes -= HASHCODE_BYTES;
if (!DYNAMIC_HASH_OFFSET) {
// The hashcode is the first word, so we copy to object one word higher
if (toObj == null) {
toAddress = toAddress.plus(HASHCODE_BYTES);
}
}
} else if (!DYNAMIC_HASH_OFFSET && hashState.EQ(HASH_STATE_HASHED_AND_MOVED)) {
// Simple operation (no hash state change), but one word larger header
objRefOffset += HASHCODE_BYTES;
}
}
if (toObj != null) {
toAddress = Magic.objectAsAddress(toObj).minus(objRefOffset);
}
// Low memory word of source object
Address fromAddress = Magic.objectAsAddress(fromObj).minus(objRefOffset);
// Do the copy
Memory.aligned32Copy(toAddress, fromAddress, copyBytes);
if (toObj == null) {
toObj = Magic.addressAsObject(toAddress.plus(objRefOffset));
} else {
if (VM.VerifyAssertions)
VM._assert(toObj == Magic.addressAsObject(toAddress.plus(objRefOffset)));
}
// Do we need to copy the hash code?
if (hashState.EQ(HASH_STATE_HASHED)) {
int hashCode = Magic.objectAsAddress(fromObj).toWord().rshl(LOG_BYTES_IN_ADDRESS).toInt();
if (DYNAMIC_HASH_OFFSET) {
Magic.setIntAtOffset(toObj, Offset.fromIntSignExtend(numBytes - OBJECT_REF_OFFSET - HASHCODE_BYTES), hashCode);
} else {
Magic.setIntAtOffset(toObj, HASHCODE_OFFSET, (hashCode << 1) | ALIGNMENT_MASK);
}
Magic.setWordAtOffset(toObj, STATUS_OFFSET, statusWord.or(HASH_STATE_HASHED_AND_MOVED));
if (ObjectModel.HASH_STATS)
ObjectModel.hashTransition2++;
}
return toObj;
}
Aggregations