use of org.jikesrvm.classloader.RVMMethod in project JikesRVM by JikesRVM.
the class JNIHelpers method invokeInitializer.
/**
* Common code shared by the JNI functions NewObjectA, NewObjectV, NewObject
* (object creation)
* @param cls class whose constructor is to be invoked
* @param methodID the method ID for a constructor
* @param argAddress where to find the arguments for the constructor
* @param isJvalue {@code true} if parameters are passed as a jvalue array
* @param isDotDotStyle {@code true} if the method uses varargs
* @return a new object created by the specified constructor
* @throws Exception when the reflective invocation of the constructor fails
*/
public static Object invokeInitializer(Class<?> cls, int methodID, Address argAddress, boolean isJvalue, boolean isDotDotStyle) throws Exception {
// get the parameter list as Java class
MemberReference mr = MemberReference.getMemberRef(methodID);
TypeReference tr = java.lang.JikesRVMSupport.getTypeForClass(cls).getTypeRef();
MethodReference methodRef = MemberReference.findOrCreate(tr, mr.getName(), mr.getDescriptor()).asMethodReference();
RVMMethod mth = methodRef.resolve();
Constructor<?> constMethod = java.lang.reflect.JikesRVMSupport.createConstructor(mth);
if (!mth.isPublic()) {
constMethod.setAccessible(true);
}
// Package the parameters for the constructor
Address varargAddress;
if (isDotDotStyle) {
// flag is false because this JNI function has 3 args before the var args
varargAddress = getVarArgAddress(false);
} else {
varargAddress = argAddress;
}
Object[] argObjs;
if (isJvalue) {
argObjs = packageParametersFromJValuePtr(methodRef, argAddress);
} else {
argObjs = packageParameterFromVarArg(methodRef, varargAddress);
}
// construct the new object
return constMethod.newInstance(argObjs);
}
use of org.jikesrvm.classloader.RVMMethod 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.jikesrvm.classloader.RVMMethod in project JikesRVM by JikesRVM.
the class JNIFunctions method RegisterNatives.
/**
* RegisterNatives: registers implementation of native methods
* @param env A JREF index for the JNI environment object
* @param classJREF a JREF index for the class to register native methods in
* @param methodsAddress the address of an array of native methods to be registered
* @param nmethods the number of native methods in the array
* @return 0 is successful -1 if failed
* @throws NoSuchMethodError if a specified method cannot be found or is not native
*/
private static int RegisterNatives(JNIEnvironment env, int classJREF, Address methodsAddress, int nmethods) {
if (traceJNI)
VM.sysWriteln("JNI called: RegisterNatives");
RuntimeEntrypoints.checkJNICountDownToGC();
try {
// get the target class
Class<?> jcls = (Class<?>) env.getJNIRef(classJREF);
RVMType type = java.lang.JikesRVMSupport.getTypeForClass(jcls);
if (!type.isClassType()) {
env.recordException(new NoSuchMethodError());
return 0;
}
RVMClass klass = type.asClass();
if (!klass.isInitialized()) {
RuntimeEntrypoints.initializeClassForDynamicLink(klass);
}
// Create list of methods and verify them to avoid partial success
NativeMethod[] methods = new NativeMethod[nmethods];
AddressArray symbols = AddressArray.create(nmethods);
Address curMethod = methodsAddress;
for (int i = 0; i < nmethods; i++) {
String methodString = JNIGenericHelpers.createStringFromC(curMethod.loadAddress());
Atom methodName = Atom.findOrCreateAsciiAtom(methodString);
String sigString = JNIGenericHelpers.createStringFromC(curMethod.loadAddress(Offset.fromIntSignExtend(BYTES_IN_ADDRESS)));
Atom sigName = Atom.findOrCreateAsciiAtom(sigString);
// Find the target method
RVMMethod meth = klass.findDeclaredMethod(methodName, sigName);
if (meth == null || !meth.isNative()) {
env.recordException(new NoSuchMethodError(klass + ": " + methodName + " " + sigName));
return -1;
}
methods[i] = (NativeMethod) meth;
symbols.set(i, curMethod.loadAddress(Offset.fromIntSignExtend(BYTES_IN_ADDRESS * 2)));
curMethod = curMethod.plus(3 * BYTES_IN_ADDRESS);
}
// Register methods
for (int i = 0; i < nmethods; i++) {
methods[i].registerNativeSymbol(symbols.get(i));
}
return 0;
} catch (Throwable unexpected) {
if (traceJNI)
unexpected.printStackTrace(System.err);
env.recordException(unexpected);
return -1;
}
}
use of org.jikesrvm.classloader.RVMMethod in project JikesRVM by JikesRVM.
the class JNIFunctions method GetStaticMethodID.
/**
* GetStaticMethodID: return the method ID for invocation later
* @param env A JREF index for the JNI environment object
* @param classJREF a JREF index for the class object
* @param methodNameAddress a raw address to a null-terminated string in C for the method name
* @param methodSigAddress a raw address to a null-terminated string in C for (TODO: document me)
* @return a method ID or null if it fails
* @throws NoSuchMethodError if the method is not found
* @throws ExceptionInInitializerError if the initializer fails
* @throws OutOfMemoryError if the system runs out of memory
*/
private static int GetStaticMethodID(JNIEnvironment env, int classJREF, Address methodNameAddress, Address methodSigAddress) {
if (traceJNI)
VM.sysWriteln("JNI called: GetStaticMethodID");
RuntimeEntrypoints.checkJNICountDownToGC();
try {
// obtain the names as String from the native space
String methodString = JNIGenericHelpers.createStringFromC(methodNameAddress);
Atom methodName = Atom.findOrCreateAsciiAtom(methodString);
String sigString = JNIGenericHelpers.createStringFromC(methodSigAddress);
Atom sigName = Atom.findOrCreateAsciiAtom(sigString);
// get the target class
Class<?> jcls = (Class<?>) env.getJNIRef(classJREF);
RVMType type = java.lang.JikesRVMSupport.getTypeForClass(jcls);
if (!type.isClassType()) {
env.recordException(new NoSuchMethodError());
return 0;
}
RVMClass klass = type.asClass();
if (!klass.isInitialized()) {
RuntimeEntrypoints.initializeClassForDynamicLink(klass);
}
// Find the target method
RVMMethod meth = klass.findStaticMethod(methodName, sigName);
if (meth == null) {
env.recordException(new NoSuchMethodError());
return 0;
}
if (traceJNI)
VM.sysWriteln("got method " + meth);
return meth.getId();
} catch (Throwable unexpected) {
if (traceJNI)
unexpected.printStackTrace(System.err);
env.recordException(unexpected);
return 0;
}
}
use of org.jikesrvm.classloader.RVMMethod in project JikesRVM by JikesRVM.
the class JNIFunctions method ToReflectedMethod.
/**
* ToReflectedMethod
* @param env A JREF index for the JNI environment object
* @param clsJREF The JREF index of the class from which methodID was
* derived.
* @param methodID a jmethodID to turn into a reflected method
* @param isStatic argument that is not specified in Sun's JNI 1.2 spec,
* but IS present in the 1.4.2 JDK's implementation! Our
* implementation will just ignore it, in any case. This is a
* good example of why the same entity
* shouldn't get to write both the spec and the reference
* implementation.
* @return a JREF index for the java.lang.reflect.Method or
* java.lang.reflect.Constructor object associated with methodID.
*/
private static int ToReflectedMethod(JNIEnvironment env, int clsJREF, int methodID, boolean isStatic) {
if (traceJNI)
VM.sysWriteln("JNI called: ToReflectedMethod");
RuntimeEntrypoints.checkJNICountDownToGC();
RVMMethod targetMethod = MemberReference.getMethodRef(methodID).resolve();
Object ret;
if (targetMethod.isObjectInitializer()) {
ret = java.lang.reflect.JikesRVMSupport.createConstructor(targetMethod);
} else {
ret = java.lang.reflect.JikesRVMSupport.createMethod(targetMethod);
}
return env.pushJNIRef(ret);
}
Aggregations