static void invokeArray(JNIEnv* env, jlong ctxAddress, jbyteArray paramBuffer, void* returnBuffer) { Function* ctx = (Function *) j2p(ctxAddress); union { double d; long long ll; jbyte tmp[PARAM_SIZE]; } tmpStackBuffer[MAX_STACK_ARGS]; jbyte *tmpBuffer = (jbyte *) &tmpStackBuffer[0]; if (ctx->cif.nargs > 0) { if (ctx->cif.bytes > (int) sizeof(tmpStackBuffer)) { tmpBuffer = alloca_aligned(ctx->cif.bytes, MIN_ALIGN); } // calculate room needed for return address for struct returns int adj = ctx->cif.rtype->type == FFI_TYPE_STRUCT ? sizeof(void *) : 0; (*env)->GetByteArrayRegion(env, paramBuffer, 0, ctx->rawParameterSize, tmpBuffer + adj); } // For struct return values, we need to push a return value address on the parameter stack if (ctx->cif.rtype->type == FFI_TYPE_STRUCT) { *(void **) tmpBuffer = returnBuffer; } ffi_raw_call(&ctx->cif, FFI_FN(ctx->function), returnBuffer, (ffi_raw *) tmpBuffer); set_last_error(errno); }
static void invokeArray(JNIEnv* env, jlong ctxAddress, jbyteArray paramBuffer, void* returnBuffer) { Function* ctx = (Function *) j2p(ctxAddress); FFIValue tmpValue; jbyte *tmpBuffer = (jbyte *) &tmpValue; if (likely(ctx->cif.nargs > 0)) { tmpBuffer = alloca(ctx->cif.bytes); (*env)->GetByteArrayRegion(env, paramBuffer, 0, ctx->rawParameterSize, tmpBuffer); } ffi_raw_call(&ctx->cif, FFI_FN(ctx->function), returnBuffer, (ffi_raw *) tmpBuffer); SAVE_ERRNO(ctx); }
static void invokeArrayWithObjects_(JNIEnv* env, jlong ctxAddress, jbyteArray paramBuffer, jint objectCount, jint* infoBuffer, jobject* objectBuffer, void* retval) { Function* ctx = (Function *) j2p(ctxAddress); jbyte *tmpBuffer = NULL; void **ffiArgs = NULL; Array *arrays = NULL; unsigned int i, arrayCount = 0, paramBytes = 0; arrays = alloca(objectCount * sizeof(Array)); #if defined(USE_RAW) paramBytes = ctx->rawParameterSize; #else paramBytes = ctx->cif.nargs * PARAM_SIZE; #endif tmpBuffer = alloca(paramBytes); (*env)->GetByteArrayRegion(env, paramBuffer, 0, paramBytes, tmpBuffer); #ifndef USE_RAW ffiArgs = alloca(ctx->cif.nargs * sizeof(void *)); for (i = 0; i < (unsigned int) ctx->cif.nargs; ++i) { ffiArgs[i] = &tmpBuffer[i * PARAM_SIZE]; } #endif for (i = 0; i < (unsigned int) objectCount; ++i) { int type = infoBuffer[i * 3]; jsize offset = infoBuffer[(i * 3) + 1]; jsize length = infoBuffer[(i * 3) + 2]; jobject object = objectBuffer[i]; int idx = (type & com_kenai_jffi_ObjectBuffer_INDEX_MASK) >> com_kenai_jffi_ObjectBuffer_INDEX_SHIFT; void* ptr; switch (type & com_kenai_jffi_ObjectBuffer_TYPE_MASK & ~com_kenai_jffi_ObjectBuffer_PRIM_MASK) { case com_kenai_jffi_ObjectBuffer_ARRAY: if (unlikely(object == NULL)) { throwException(env, NullPointer, "null object for parameter %d", idx); goto cleanup; } else if (unlikely((type & com_kenai_jffi_ObjectBuffer_PINNED) != 0)) { ptr = jffi_getArrayCritical(env, object, offset, length, type, &arrays[arrayCount]); if (unlikely(ptr == NULL)) { goto cleanup; } } else if (true && likely(length < MAX_STACK_ARRAY)) { ptr = alloca(jffi_arraySize(length + 1, type)); if (unlikely(jffi_getArrayBuffer(env, object, offset, length, type, &arrays[arrayCount], ptr) == NULL)) { goto cleanup; } } else { ptr = jffi_getArrayHeap(env, object, offset, length, type, &arrays[arrayCount]); if (unlikely(ptr == NULL)) { goto cleanup; } } ++arrayCount; break; case com_kenai_jffi_ObjectBuffer_BUFFER: ptr = (*env)->GetDirectBufferAddress(env, object); if (unlikely(ptr == NULL)) { throwException(env, NullPointer, "Could not get direct Buffer address"); goto cleanup; } ptr = ((char *) ptr + offset); break; case com_kenai_jffi_ObjectBuffer_JNI: switch (type & com_kenai_jffi_ObjectBuffer_TYPE_MASK) { case com_kenai_jffi_ObjectBuffer_JNIENV: ptr = env; break; case com_kenai_jffi_ObjectBuffer_JNIOBJECT: ptr = (void *) object; break; default: throwException(env, IllegalArgument, "Unsupported object type: %#x", type & com_kenai_jffi_ObjectBuffer_TYPE_MASK); goto cleanup; } break; default: throwException(env, IllegalArgument, "Unsupported object type: %#x", type & com_kenai_jffi_ObjectBuffer_TYPE_MASK); goto cleanup; } #if defined(USE_RAW) *((void **)(tmpBuffer + ctx->rawParamOffsets[idx])) = ptr; #else if (unlikely(ctx->cif.arg_types[idx]->type == FFI_TYPE_STRUCT)) { ffiArgs[idx] = ptr; } else { *((void **) ffiArgs[idx]) = ptr; } #endif } #if defined(USE_RAW) // // Special case for struct return values - unroll into a ptr array and // use ffi_call, since ffi_raw_call with struct return values is undocumented. // if (unlikely(ctx->cif.rtype->type == FFI_TYPE_STRUCT)) { ffiArgs = alloca(ctx->cif.nargs * sizeof(void *)); for (i = 0; i < ctx->cif.nargs; ++i) { ffiArgs[i] = (tmpBuffer + ctx->rawParamOffsets[i]); } ffi_call(&ctx->cif, FFI_FN(ctx->function), retval, ffiArgs); } else { ffi_raw_call(&ctx->cif, FFI_FN(ctx->function), retval, (ffi_raw *) tmpBuffer); } #else ffi_call(&ctx->cif, FFI_FN(ctx->function), retval, ffiArgs); #endif SAVE_ERRNO(ctx); cleanup: /* Release any array backing memory */ for (i = 0; i < arrayCount; ++i) { if (arrays[i].release != NULL) { //printf("releasing array=%p\n", arrays[i].elems); (*arrays[i].release)(env, &arrays[i]); } } }
static void invokeArrayWithObjects_(JNIEnv* env, jlong ctxAddress, jbyteArray paramBuffer, jint objectCount, jint* infoBuffer, jobject* objectBuffer, void* retval) { Function* ctx = (Function *) j2p(ctxAddress); union { double d; long long ll; jbyte tmp[PARAM_SIZE]; } tmpStackBuffer[MAX_STACK_ARGS]; jbyte *tmpBuffer = (jbyte *) &tmpStackBuffer[0]; #if defined(USE_RAW) int rawAdj = ctx->cif.rtype->type == FFI_TYPE_STRUCT ? sizeof(void *) : 0; #else void* ffiStackArgs[MAX_STACK_ARGS], **ffiArgs = &ffiStackArgs[0]; #endif Array stackArrays[MAX_STACK_OBJECTS], *arrays = &stackArrays[0]; StackAllocator alloc; unsigned int i, arrayCount = 0; if (ctx->cif.nargs > MAX_STACK_ARGS) { tmpBuffer = alloca_aligned(ctx->cif.nargs * PARAM_SIZE, MIN_ALIGN); } #if defined(USE_RAW) (*env)->GetByteArrayRegion(env, paramBuffer, 0, ctx->rawParameterSize, tmpBuffer + rawAdj); #else if (ctx->cif.nargs > MAX_STACK_ARGS) { ffiArgs = alloca_aligned(ctx->cif.nargs * sizeof(void *), MIN_ALIGN); } for (i = 0; i < ctx->cif.nargs; ++i) { ffiArgs[i] = &tmpBuffer[i * PARAM_SIZE]; } (*env)->GetByteArrayRegion(env, paramBuffer, 0, ctx->cif.nargs * PARAM_SIZE, tmpBuffer); #endif if (objectCount > MAX_STACK_OBJECTS) { arrays = alloca_aligned(objectCount * sizeof(Array), MIN_ALIGN); } initStackAllocator(&alloc); for (i = 0; i < (unsigned int) objectCount; ++i) { int type = infoBuffer[i * 3]; jsize offset = infoBuffer[(i * 3) + 1]; jsize length = infoBuffer[(i * 3) + 2]; jobject object = objectBuffer[i]; int idx = (type & com_kenai_jffi_ObjectBuffer_INDEX_MASK) >> com_kenai_jffi_ObjectBuffer_INDEX_SHIFT; void* ptr; switch (type & com_kenai_jffi_ObjectBuffer_TYPE_MASK & ~com_kenai_jffi_ObjectBuffer_PRIM_MASK) { case com_kenai_jffi_ObjectBuffer_ARRAY: ptr = jffi_getArray(env, object, offset, length, type, &alloc, &arrays[arrayCount]); if (ptr == NULL) { throwException(env, NullPointer, "Could not allocate array"); goto cleanup; } ++arrayCount; break; case com_kenai_jffi_ObjectBuffer_BUFFER: ptr = (*env)->GetDirectBufferAddress(env, object); if (ptr == NULL) { throwException(env, NullPointer, "Could not get direct Buffer address"); goto cleanup; } ptr = ((char *) ptr + offset); break; default: throwException(env, IllegalArgument, "Unsupported object type: %#x", type & com_kenai_jffi_ObjectBuffer_TYPE_MASK); goto cleanup; } #if defined(USE_RAW) *((void **)(tmpBuffer + rawAdj + ctx->rawParamOffsets[idx])) = ptr; #else if (ctx->cif.arg_types[idx]->type == FFI_TYPE_STRUCT) { ffiArgs[idx] = ptr; } else { *((void **) ffiArgs[idx]) = ptr; } #endif } #if defined(USE_RAW) // For struct return values, we need to push a return value address on the parameter stack if (ctx->cif.rtype->type == FFI_TYPE_STRUCT) { *(void **) tmpBuffer = retval; } ffi_raw_call(&ctx->cif, FFI_FN(ctx->function), retval, (ffi_raw *) tmpBuffer); #else ffi_call(&ctx->cif, FFI_FN(ctx->function), retval, ffiArgs); #endif set_last_error(errno); cleanup: /* Release any array backing memory */ for (i = 0; i < arrayCount; ++i) { if (!arrays[i].stack || arrays[i].mode != JNI_ABORT) { //printf("releasing array=%p\n", arrays[i].result); (*arrays[i].release)(env, &arrays[i]); } } }