Search in sources :

Example 1 with JNIEnvironment

use of org.jikesrvm.jni.JNIEnvironment in project JikesRVM by JikesRVM.

the class JNIHelpers method packageParameterFromVarArg.

/**
 * Repackage the arguments passed as a variable argument list into an array of Object,
 * used by the JNI functions CallStatic<type>MethodV
 * @param targetMethod   The target {@link RVMMethod}
 * @param argAddress an address into the C space for the array of jvalue unions;
 *                   each element is 2-word and holds the argument of the appropriate type
 * @return an Object array holding the arguments wrapped at Objects
 */
static Object[] packageParameterFromVarArg(MethodReference targetMethod, Address argAddress) {
    TypeReference[] argTypes = targetMethod.getParameterTypes();
    int argCount = argTypes.length;
    Object[] argObjectArray = new Object[argCount];
    Address vaListCopy = SysCall.sysCall.sysVaCopy(argAddress);
    JNIEnvironment env = RVMThread.getCurrentThread().getJNIEnv();
    for (int i = 0; i < argCount; i++) {
        // convert and wrap the argument according to the expected type
        if (argTypes[i].isReferenceType()) {
            argObjectArray[i] = env.getJNIRef(SysCall.sysCall.sysVaArgJobject(vaListCopy));
        } else if (argTypes[i].isIntType()) {
            argObjectArray[i] = SysCall.sysCall.sysVaArgJint(vaListCopy);
        } else if (argTypes[i].isLongType()) {
            argObjectArray[i] = SysCall.sysCall.sysVaArgJlong(vaListCopy);
        } else if (argTypes[i].isBooleanType()) {
            argObjectArray[i] = SysCall.sysCall.sysVaArgJboolean(vaListCopy);
        } else if (argTypes[i].isByteType()) {
            argObjectArray[i] = SysCall.sysCall.sysVaArgJbyte(vaListCopy);
        } else if (argTypes[i].isCharType()) {
            argObjectArray[i] = SysCall.sysCall.sysVaArgJchar(vaListCopy);
        } else if (argTypes[i].isShortType()) {
            argObjectArray[i] = SysCall.sysCall.sysVaArgJshort(vaListCopy);
        } else if (argTypes[i].isFloatType()) {
            argObjectArray[i] = SysCall.sysCall.sysVaArgJfloat(vaListCopy);
        } else {
            if (VM.VerifyAssertions)
                VM._assert(argTypes[i].isDoubleType());
            argObjectArray[i] = SysCall.sysCall.sysVaArgJdouble(vaListCopy);
        }
    }
    SysCall.sysCall.sysVaEnd(vaListCopy);
    return argObjectArray;
}
Also used : Address(org.vmmagic.unboxed.Address) JNIEnvironment(org.jikesrvm.jni.JNIEnvironment) TypeReference(org.jikesrvm.classloader.TypeReference)

Example 2 with JNIEnvironment

use of org.jikesrvm.jni.JNIEnvironment in project JikesRVM by JikesRVM.

the class JNIHelpers method packageParameterFromDotArgSVR4.

/* The method reads out parameters from registers saved in native->java glue stack frame (glueFP)
  * and the spill area of native stack frame (caller of glueFP).
  *
  * NOTE: assuming the stack frame won't get moved, (see pushVarArgToSpillArea)
  *       the row address glueFP can be replaced by offset to the stack.
  *
  * @param targetMethod, the call target
  * @param glueFP, the glue stack frame pointer
  */
static Object[] packageParameterFromDotArgSVR4(MethodReference targetMethod, Address glueFP, boolean skip4Args) {
    if (!VM.BuildForSVR4ABI) {
        if (VM.VerifyAssertions)
            VM._assert(VM.NOT_REACHED);
        return null;
    }
    // native method's stack frame
    Address nativeFP = Magic.getCallerFramePointer(glueFP);
    TypeReference[] argTypes = targetMethod.getParameterTypes();
    int argCount = argTypes.length;
    Object[] argObjectArray = new Object[argCount];
    JNIEnvironment env = RVMThread.getCurrentThread().getJNIEnv();
    // GPR r3 - r10 and FPR f1 - f8 are saved in glue stack frame
    Address regsavearea = glueFP.plus(STACKFRAME_HEADER_SIZE);
    // spill area offset
    Address overflowarea = nativeFP.plus(NATIVE_FRAME_HEADER_SIZE);
    // overflowarea is aligned to 8 bytes
    if (VM.VerifyAssertions)
        VM._assert(overflowarea.toWord().and(Word.fromIntZeroExtend(0x07)).isZero());
    // adjust gpr and fpr to normal numbering, make life easier
    // r3 - env, r4 - cls, r5 - method id
    int gpr = (skip4Args) ? 7 : 6;
    int fpr = 1;
    // not set the starting gprs array address
    // and fpr starting array address, so we can use gpr and fpr to
    // calculate the right position to get values
    // GPR starts with r3;
    Address gprarray = regsavearea.plus(-3 * BYTES_IN_ADDRESS);
    Address fprarray = regsavearea.plus(8 * BYTES_IN_ADDRESS - 2 * BYTES_IN_ADDRESS);
    // call the common function for SVR4
    packageArgumentForSVR4(argTypes, argObjectArray, gprarray, fprarray, overflowarea, gpr, fpr, env);
    return argObjectArray;
}
Also used : Address(org.vmmagic.unboxed.Address) JNIEnvironment(org.jikesrvm.jni.JNIEnvironment) TypeReference(org.jikesrvm.classloader.TypeReference)

Example 3 with JNIEnvironment

use of org.jikesrvm.jni.JNIEnvironment in project JikesRVM by JikesRVM.

the class JNIHelpers method packageParameterFromVarArg.

/**
 * Repackage the arguments passed as a variable argument list into an array of Object,
 * used by the JNI functions CallStatic<type>MethodV
 * @param targetMethod   The target {@link RVMMethod}
 * @param argAddress an address into the C space for the array of jvalue unions;
 *                   each element is 2-word and holds the argument of the appropriate type
 * @return an Object array holding the arguments wrapped at Objects
 */
static Object[] packageParameterFromVarArg(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();
    // VM.sysWriteln("JNI packageParameterFromVarArg: packaging " + argCount + " arguments");
    Address addr = argAddress;
    for (int i = 0; i < argCount; i++) {
        long hiword = VM.BuildFor64Addr ? addr.loadLong() : (long) addr.loadInt();
        // VM.sysWrite("JNI packageParameterFromVarArg:  arg " + i + " = " + hiword +
        // " or " + Services.intAsHexString(hiword) + "\n");
        addr = addr.plus(BYTES_IN_ADDRESS);
        if (argTypes[i].isFloatType()) {
            // so we have to extract it as a double and convert it back to a float
            if (VM.BuildFor32Addr) {
                int loword = addr.loadInt();
                addr = addr.plus(BYTES_IN_ADDRESS);
                long doubleBits = (hiword << BITS_IN_INT) | (loword & 0xFFFFFFFFL);
                argObjectArray[i] = Reflection.wrapFloat((float) (Double.longBitsToDouble(doubleBits)));
            } else {
                argObjectArray[i] = Reflection.wrapFloat((float) (Double.longBitsToDouble(hiword)));
            }
        } else if (argTypes[i].isDoubleType()) {
            if (VM.BuildFor32Addr) {
                int loword = addr.loadInt();
                addr = addr.plus(BYTES_IN_ADDRESS);
                long doubleBits = (hiword << BITS_IN_INT) | (loword & 0xFFFFFFFFL);
                argObjectArray[i] = Reflection.wrapDouble(Double.longBitsToDouble(doubleBits));
            } else {
                argObjectArray[i] = Reflection.wrapDouble(Double.longBitsToDouble(hiword));
            }
        } else if (argTypes[i].isLongType()) {
            if (VM.BuildFor32Addr) {
                int loword = addr.loadInt();
                addr = addr.plus(BYTES_IN_ADDRESS);
                long longValue = (hiword << BITS_IN_INT) | (loword & 0xFFFFFFFFL);
                argObjectArray[i] = Reflection.wrapLong(longValue);
            } else {
                argObjectArray[i] = Reflection.wrapLong(hiword);
            }
        } else if (argTypes[i].isBooleanType()) {
            // the 0/1 bit is stored in the high byte
            argObjectArray[i] = Reflection.wrapBoolean((int) hiword);
        } else if (argTypes[i].isByteType()) {
            // the target byte is stored in the high byte
            argObjectArray[i] = Reflection.wrapByte((byte) hiword);
        } else if (argTypes[i].isCharType()) {
            // char is stored in the high 2 bytes
            argObjectArray[i] = Reflection.wrapChar((char) hiword);
        } else if (argTypes[i].isShortType()) {
            // short is stored in the high 2 bytes
            argObjectArray[i] = Reflection.wrapShort((short) hiword);
        } else if (argTypes[i].isReferenceType()) {
            // for object, the arg is a JREF index, dereference to get the real object
            argObjectArray[i] = env.getJNIRef((int) hiword);
        } else if (argTypes[i].isIntType()) {
            argObjectArray[i] = Reflection.wrapInt((int) hiword);
        } else {
            return null;
        }
    }
    return argObjectArray;
}
Also used : Address(org.vmmagic.unboxed.Address) JNIEnvironment(org.jikesrvm.jni.JNIEnvironment) TypeReference(org.jikesrvm.classloader.TypeReference)

Example 4 with JNIEnvironment

use of org.jikesrvm.jni.JNIEnvironment in project JikesRVM by JikesRVM.

the class JNIHelpers method packageParameterFromVarArgSVR4.

// linux has totally different layout of va_list
// see /usr/lib/gcc-lib/powerpc-linux/xxxx/include/va-ppc.h
// 
// va_list is defined as following
// 
// struct {
// char unsigned gpr;    // compiled to 1 byte, index of gprs in saved area
// // 0 -> r3, 1 -> r4, ....
// char unsigned fpr;    // compiled to 1 byte, index to fprs in saved area
// // 0 -> fr1, 1 -> fr2, ....
// char * over_flow_area;
// char * reg_save_area;
// }
// 
// The interpretation of data can be found in PowerPC Processor ABI Supplement
// 
// The reg_save area lays out r3 - r10, f1 - f8
// 
// I am not sure if GCC understand the ABI in a right way, it saves GPRs 1 - 10
// in the area, while only gprs starting from r3 are used.
// 
// -- Feng
// 
static Object[] packageParameterFromVarArgSVR4(MethodReference targetMethod, Address argAddress) {
    if (!VM.BuildForSVR4ABI) {
        if (VM.VerifyAssertions)
            VM._assert(VM.NOT_REACHED);
        return null;
    }
    TypeReference[] argTypes = targetMethod.getParameterTypes();
    int argCount = argTypes.length;
    Object[] argObjectArray = new Object[argCount];
    JNIEnvironment env = RVMThread.getCurrentThread().getJNIEnv();
    // the va_list has following layout on PPC/Linux
    // GPR FPR 0 0   (4 bytes)
    // overflowarea  (pointer)
    // reg_save_area (pointer)
    Address va_list_addr = argAddress;
    int word1 = va_list_addr.loadWord().toInt();
    int gpr = word1 >> 24;
    int fpr = (word1 >> 16) & 0x0FF;
    Address overflowarea = va_list_addr.loadAddress(Offset.fromIntSignExtend(BYTES_IN_ADDRESS));
    Address regsavearea = va_list_addr.loadAddress(Offset.fromIntSignExtend(2 * BYTES_IN_ADDRESS));
    if (VM.BuildForSVR4ABI) {
        // overflowarea is aligned to 8 bytes
        if (VM.VerifyAssertions)
            VM._assert(overflowarea.toWord().and(Word.fromIntZeroExtend(0x07)).isZero());
    }
    // adjust gpr and fpr to normal numbering, make life easier
    gpr += 3;
    fpr += 1;
    // not set the starting gprs array address
    // and fpr starting array address, so we can use gpr and fpr to
    // calculate the right position to get values
    // GPR starts with r3;
    Address gprarray = regsavearea.plus(-3 * BYTES_IN_ADDRESS);
    Address fprarray = regsavearea.plus(8 * BYTES_IN_ADDRESS - 2 * BYTES_IN_ADDRESS);
    // call the common function for SVR4
    packageArgumentForSVR4(argTypes, argObjectArray, gprarray, fprarray, overflowarea, gpr, fpr, env);
    return argObjectArray;
}
Also used : Address(org.vmmagic.unboxed.Address) JNIEnvironment(org.jikesrvm.jni.JNIEnvironment) TypeReference(org.jikesrvm.classloader.TypeReference)

Aggregations

TypeReference (org.jikesrvm.classloader.TypeReference)4 JNIEnvironment (org.jikesrvm.jni.JNIEnvironment)4 Address (org.vmmagic.unboxed.Address)4