#include "JNIHelp.h"
#include "utils/Log.h"
+#include <stdlib.h>
#include <string.h>
#include <assert.h>
void jniSetFileDescriptorOfFD(JNIEnv* env, jobject fileDescriptor, int value) {
(*env)->SetIntField(env, fileDescriptor, gCachedFields.descriptorField, value);
}
+
+/*
+ * DO NOT USE THIS FUNCTION
+ *
+ * Get a pointer to the elements of a non-movable array.
+ *
+ * The semantics are similar to GetDirectBufferAddress. Specifically, the VM
+ * guarantees that the array will not move, and the caller must ensure that
+ * it does not continue to use the pointer after the object is collected.
+ *
+ * We currently use an illegal sequence that trips up CheckJNI when
+ * the "forcecopy" mode is enabled. We pass in a magic value to work
+ * around the problem.
+ *
+ * Returns NULL if the array is movable.
+ */
+jbyte* jniGetNonMovableArrayElements(JNIEnv* env, jarray arrayObj)
+{
+#define kNoCopyMagic 0xd5aab57f /* also in CheckJni.c */
+
+ /*
+ * Normally the "isCopy" parameter is for a return value only, so the
+ * non-CheckJNI VM will ignore whatever we pass in.
+ */
+ uint32_t noCopy = kNoCopyMagic;
+ jbyte *addr = (*env)->GetByteArrayElements(env, arrayObj,
+ (jboolean*)&noCopy);
+
+ /*
+ * The non-CheckJNI implementation only cares about the array object,
+ * so we can replace the element pointer with the magic value.
+ */
+ (*env)->ReleaseByteArrayElements(env, arrayObj, (jbyte*) kNoCopyMagic, 0);
+ return addr;
+}
NEW_PRIMITIVE_ARRAY(jdoubleArray, Double);
+/*
+ * Hack to allow forcecopy to work with jniGetNonMovableArrayElements.
+ * The code deliberately uses an invalid sequence of operations, so we
+ * need to pass it through unmodified. Review that code before making
+ * any changes here.
+ */
+#define kNoCopyMagic 0xd5aab57f
+
#define GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \
static _ctype* Check_Get##_jname##ArrayElements(JNIEnv* env, \
_ctype##Array array, jboolean* isCopy) \
CHECK_ENTER(env, kFlag_Default); \
CHECK_ARRAY(env, array); \
_ctype* result; \
+ u4 noCopy = 0; \
+ if (((JNIEnvExt*)env)->forceDataCopy && isCopy != NULL) { \
+ /* capture this before the base call tramples on it */ \
+ noCopy = *(u4*) isCopy; \
+ } \
result = BASE_ENV(env)->Get##_jname##ArrayElements(env, \
array, isCopy); \
if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) { \
- result = (_ctype*) createGuardedPACopy(env, array, isCopy); \
+ if (noCopy == kNoCopyMagic) { \
+ LOGV("FC: not copying %p %x\n", array, noCopy); \
+ } else { \
+ result = (_ctype*) createGuardedPACopy(env, array, isCopy); \
+ } \
} \
CHECK_EXIT(env); \
return result; \
CHECK_NON_NULL(env, elems); \
CHECK_RELEASE_MODE(env, mode); \
if (((JNIEnvExt*)env)->forceDataCopy) { \
- elems = (_ctype*) releaseGuardedPACopy(env, array, elems, mode);\
+ if ((uintptr_t)elems == kNoCopyMagic) { \
+ LOGV("FC: not freeing %p\n", array); \
+ elems = NULL; /* base JNI call doesn't currently need */ \
+ } else { \
+ elems = (_ctype*) releaseGuardedPACopy(env, array, elems, \
+ mode); \
+ } \
} \
BASE_ENV(env)->Release##_jname##ArrayElements(env, \
array, elems, mode); \