summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMathieu Chartier <mathieuc@google.com>2015-06-24 17:04:17 -0700
committerMathieu Chartier <mathieuc@google.com>2015-06-24 20:03:01 -0700
commit71e46c1a2e1a8c2ef87b6137e8503dd12e18bb8d (patch)
tree4c987a661624c1d7ffea19b2beda45dbfcea73c7
parent6d20c2e2d88de0116203e2d6ba80b996f858abc1 (diff)
downloadart-71e46c1a2e1a8c2ef87b6137e8503dd12e18bb8d.zip
art-71e46c1a2e1a8c2ef87b6137e8503dd12e18bb8d.tar.gz
art-71e46c1a2e1a8c2ef87b6137e8503dd12e18bb8d.tar.bz2
Fix force copy
We now correctly pass the returned pointer back onto the release functions. Bug: 22056708 Change-Id: I1a7300d3a4522a3c81b432ec742ae1c0bd00b51e (cherry picked from commit b735bd9c04aa291d0a1bdc2c0a094a1a75ad0596)
-rw-r--r--runtime/check_jni.cc84
-rw-r--r--runtime/gc/heap.cc2
2 files changed, 42 insertions, 44 deletions
diff --git a/runtime/check_jni.cc b/runtime/check_jni.cc
index 549eac2..45fb9c4 100644
--- a/runtime/check_jni.cc
+++ b/runtime/check_jni.cc
@@ -1188,7 +1188,7 @@ class GuardedCopy {
* Create an over-sized buffer to hold the contents of "buf". Copy it in,
* filling in the area around it with guard data.
*/
- static void* Create(const void* original_buf, size_t len, bool mod_okay) {
+ static void* Create(void* original_buf, size_t len, bool mod_okay) {
const size_t new_len = LengthIncludingRedZones(len);
uint8_t* const new_buf = DebugAlloc(new_len);
@@ -1227,13 +1227,14 @@ class GuardedCopy {
* Create a guarded copy of a primitive array. Modifications to the copied
* data are allowed. Returns a pointer to the copied data.
*/
- static void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* is_copy) {
+ static void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* is_copy,
+ void* original_ptr) {
ScopedObjectAccess soa(env);
mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
size_t component_size = a->GetClass()->GetComponentSize();
size_t byte_count = a->GetLength() * component_size;
- void* result = Create(a->GetRawData(component_size, 0), byte_count, true);
+ void* result = Create(original_ptr, byte_count, true);
if (is_copy != nullptr) {
*is_copy = JNI_TRUE;
}
@@ -1244,22 +1245,22 @@ class GuardedCopy {
* Perform the array "release" operation, which may or may not copy data
* back into the managed heap, and may or may not release the underlying storage.
*/
- static void* ReleaseGuardedPACopy(const char* function_name, JNIEnv* env, jarray java_array,
- void* embedded_buf, int mode) {
+ static void* ReleaseGuardedPACopy(const char* function_name, JNIEnv* env,
+ jarray java_array ATTRIBUTE_UNUSED, void* embedded_buf,
+ int mode) {
ScopedObjectAccess soa(env);
- mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
-
if (!GuardedCopy::Check(function_name, embedded_buf, true)) {
return nullptr;
}
+ GuardedCopy* const copy = FromEmbedded(embedded_buf);
+ void* original_ptr = copy->original_ptr_;
if (mode != JNI_ABORT) {
- size_t len = FromEmbedded(embedded_buf)->original_length_;
- memcpy(a->GetRawData(a->GetClass()->GetComponentSize(), 0), embedded_buf, len);
+ memcpy(original_ptr, embedded_buf, copy->original_length_);
}
if (mode != JNI_COMMIT) {
- return Destroy(embedded_buf);
+ Destroy(embedded_buf);
}
- return embedded_buf;
+ return original_ptr;
}
@@ -1286,7 +1287,7 @@ class GuardedCopy {
}
private:
- GuardedCopy(const void* original_buf, size_t len, uLong adler) :
+ GuardedCopy(void* original_buf, size_t len, uLong adler) :
magic_(kGuardMagic), adler_(adler), original_ptr_(original_buf), original_length_(len) {
}
@@ -1414,7 +1415,7 @@ class GuardedCopy {
const uint32_t magic_;
const uLong adler_;
- const void* const original_ptr_;
+ void* const original_ptr_;
const size_t original_length_;
};
const char* const GuardedCopy::kCanary = "JNI BUFFER RED ZONE";
@@ -2307,10 +2308,11 @@ class CheckJNI {
JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
if (sc.Check(soa, true, "Eap", args)) {
JniValueType result;
- result.p = baseEnv(env)->GetPrimitiveArrayCritical(env, array, is_copy);
- if (result.p != nullptr && soa.ForceCopy()) {
- result.p = GuardedCopy::CreateGuardedPACopy(env, array, is_copy);
+ void* ptr = baseEnv(env)->GetPrimitiveArrayCritical(env, array, is_copy);
+ if (ptr != nullptr && soa.ForceCopy()) {
+ ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
}
+ result.p = ptr;
if (sc.Check(soa, false, "p", &result)) {
return const_cast<void*>(result.p);
}
@@ -2325,7 +2327,7 @@ class CheckJNI {
JniValueType args[4] = {{.E = env}, {.a = array}, {.p = carray}, {.r = mode}};
if (sc.Check(soa, true, "Eapr", args)) {
if (soa.ForceCopy()) {
- GuardedCopy::ReleaseGuardedPACopy(__FUNCTION__, env, array, carray, mode);
+ carray = GuardedCopy::ReleaseGuardedPACopy(__FUNCTION__, env, array, carray, mode);
}
baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
JniValueType result;
@@ -3062,26 +3064,26 @@ class CheckJNI {
JniValueType args[3] = {{.E = env}, {.s = string}, {.p = is_copy}};
if (sc.Check(soa, true, "Esp", args)) {
JniValueType result;
+ void* ptr;
if (utf) {
CHECK(!critical);
- result.u = baseEnv(env)->GetStringUTFChars(env, string, is_copy);
+ ptr = const_cast<char*>(baseEnv(env)->GetStringUTFChars(env, string, is_copy));
+ result.u = reinterpret_cast<char*>(ptr);
} else {
- if (critical) {
- result.p = baseEnv(env)->GetStringCritical(env, string, is_copy);
- } else {
- result.p = baseEnv(env)->GetStringChars(env, string, is_copy);
- }
+ ptr = const_cast<jchar*>(critical ? baseEnv(env)->GetStringCritical(env, string, is_copy) :
+ baseEnv(env)->GetStringChars(env, string, is_copy));
+ result.p = ptr;
}
// TODO: could we be smarter about not copying when local_is_copy?
- if (result.p != nullptr && soa.ForceCopy()) {
+ if (ptr != nullptr && soa.ForceCopy()) {
if (utf) {
size_t length_in_bytes = strlen(result.u) + 1;
result.u =
- reinterpret_cast<const char*>(GuardedCopy::Create(result.u, length_in_bytes, false));
+ reinterpret_cast<const char*>(GuardedCopy::Create(ptr, length_in_bytes, false));
} else {
size_t length_in_bytes = baseEnv(env)->GetStringLength(env, string) * 2;
result.p =
- reinterpret_cast<const jchar*>(GuardedCopy::Create(result.p, length_in_bytes, false));
+ reinterpret_cast<const jchar*>(GuardedCopy::Create(ptr, length_in_bytes, false));
}
if (is_copy != nullptr) {
*is_copy = JNI_TRUE;
@@ -3175,47 +3177,43 @@ class CheckJNI {
JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
if (sc.Check(soa, true, "Eap", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
JniValueType result;
+ void* ptr = nullptr;
switch (type) {
case Primitive::kPrimBoolean:
- result.p = baseEnv(env)->GetBooleanArrayElements(env, down_cast<jbooleanArray>(array),
- is_copy);
+ ptr = baseEnv(env)->GetBooleanArrayElements(env, down_cast<jbooleanArray>(array),
+ is_copy);
break;
case Primitive::kPrimByte:
- result.p = baseEnv(env)->GetByteArrayElements(env, down_cast<jbyteArray>(array),
- is_copy);
+ ptr = baseEnv(env)->GetByteArrayElements(env, down_cast<jbyteArray>(array), is_copy);
break;
case Primitive::kPrimChar:
- result.p = baseEnv(env)->GetCharArrayElements(env, down_cast<jcharArray>(array),
- is_copy);
+ ptr = baseEnv(env)->GetCharArrayElements(env, down_cast<jcharArray>(array), is_copy);
break;
case Primitive::kPrimShort:
- result.p = baseEnv(env)->GetShortArrayElements(env, down_cast<jshortArray>(array),
- is_copy);
+ ptr = baseEnv(env)->GetShortArrayElements(env, down_cast<jshortArray>(array), is_copy);
break;
case Primitive::kPrimInt:
- result.p = baseEnv(env)->GetIntArrayElements(env, down_cast<jintArray>(array), is_copy);
+ ptr = baseEnv(env)->GetIntArrayElements(env, down_cast<jintArray>(array), is_copy);
break;
case Primitive::kPrimLong:
- result.p = baseEnv(env)->GetLongArrayElements(env, down_cast<jlongArray>(array),
- is_copy);
+ ptr = baseEnv(env)->GetLongArrayElements(env, down_cast<jlongArray>(array), is_copy);
break;
case Primitive::kPrimFloat:
- result.p = baseEnv(env)->GetFloatArrayElements(env, down_cast<jfloatArray>(array),
- is_copy);
+ ptr = baseEnv(env)->GetFloatArrayElements(env, down_cast<jfloatArray>(array), is_copy);
break;
case Primitive::kPrimDouble:
- result.p = baseEnv(env)->GetDoubleArrayElements(env, down_cast<jdoubleArray>(array),
- is_copy);
+ ptr = baseEnv(env)->GetDoubleArrayElements(env, down_cast<jdoubleArray>(array), is_copy);
break;
default:
LOG(FATAL) << "Unexpected primitive type: " << type;
}
- if (result.p != nullptr && soa.ForceCopy()) {
- result.p = GuardedCopy::CreateGuardedPACopy(env, array, is_copy);
+ if (ptr != nullptr && soa.ForceCopy()) {
+ ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
if (is_copy != nullptr) {
*is_copy = JNI_TRUE;
}
}
+ result.p = ptr;
if (sc.Check(soa, false, "p", &result)) {
return const_cast<void*>(result.p);
}
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 57557e2..d428267 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -745,7 +745,7 @@ void Heap::IncrementDisableMovingGC(Thread* self) {
void Heap::DecrementDisableMovingGC(Thread* self) {
MutexLock mu(self, *gc_complete_lock_);
- CHECK_GE(disable_moving_gc_count_, 0U);
+ CHECK_GT(disable_moving_gc_count_, 0U);
--disable_moving_gc_count_;
}