summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
authorFred Shih <ffred@google.com>2014-06-02 11:11:52 -0700
committerFred Shih <ffred@google.com>2014-06-02 19:34:39 -0700
commit56890e2615ab3dd612f1f81c3cadab6299eceacb (patch)
tree4e164a9f5aa3582d9fc5d9051375ce87d2568cc6 /runtime
parent502a1975e146b288356e49a3af82629637da5ece (diff)
downloadandroid_art-56890e2615ab3dd612f1f81c3cadab6299eceacb.tar.gz
android_art-56890e2615ab3dd612f1f81c3cadab6299eceacb.tar.bz2
android_art-56890e2615ab3dd612f1f81c3cadab6299eceacb.zip
Modified functions to return pointers where appropriate
GetStringChars will return a pointer to the underlying char array iff it is not movable. Otherwise, it will return a copy of the char array. For consistency, the null terminating character has been removed as the specification for a jchar strings are not null terminated: http://developer.android.com/training/articles/perf-jni.html GetStringCritical will now always return a pointer to the char array. The char array is pinned and moving gc is disabled until the pointer is released. Change-Id: I19c8cbaecc1f3f723d80acec074fb8c5e2d489c3
Diffstat (limited to 'runtime')
-rw-r--r--runtime/jni_internal.cc62
-rw-r--r--runtime/jni_internal_test.cc14
2 files changed, 58 insertions, 18 deletions
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index 9ca3c85106..19ee1ffe8c 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -1933,32 +1933,66 @@ class JNI {
mirror::String* s = soa.Decode<mirror::String*>(java_string);
mirror::CharArray* chars = s->GetCharArray();
PinPrimitiveArray(soa, chars);
- if (is_copy != nullptr) {
- *is_copy = JNI_TRUE;
- }
- int32_t char_count = s->GetLength();
- int32_t offset = s->GetOffset();
- jchar* bytes = new jchar[char_count + 1];
- for (int32_t i = 0; i < char_count; i++) {
- bytes[i] = chars->Get(i + offset);
+ gc::Heap* heap = Runtime::Current()->GetHeap();
+ if (heap->IsMovableObject(chars)) {
+ if (is_copy != nullptr) {
+ *is_copy = JNI_TRUE;
+ }
+ int32_t char_count = s->GetLength();
+ int32_t offset = s->GetOffset();
+ jchar* bytes = new jchar[char_count];
+ for (int32_t i = 0; i < char_count; i++) {
+ bytes[i] = chars->Get(i + offset);
+ }
+ return bytes;
+ } else {
+ if (is_copy != nullptr) {
+ *is_copy = JNI_FALSE;
+ }
+ return static_cast<jchar*>(chars->GetData() + s->GetOffset());
}
- bytes[char_count] = '\0';
- return bytes;
}
static void ReleaseStringChars(JNIEnv* env, jstring java_string, const jchar* chars) {
CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_string);
- delete[] chars;
ScopedObjectAccess soa(env);
- UnpinPrimitiveArray(soa, soa.Decode<mirror::String*>(java_string)->GetCharArray());
+ mirror::String* s = soa.Decode<mirror::String*>(java_string);
+ mirror::CharArray* s_chars = s->GetCharArray();
+ if (chars != (s_chars->GetData() + s->GetOffset())) {
+ delete[] chars;
+ }
+ UnpinPrimitiveArray(soa, s->GetCharArray());
}
static const jchar* GetStringCritical(JNIEnv* env, jstring java_string, jboolean* is_copy) {
- return GetStringChars(env, java_string, is_copy);
+ CHECK_NON_NULL_ARGUMENT(java_string);
+ ScopedObjectAccess soa(env);
+ mirror::String* s = soa.Decode<mirror::String*>(java_string);
+ mirror::CharArray* chars = s->GetCharArray();
+ int32_t offset = s->GetOffset();
+ PinPrimitiveArray(soa, chars);
+ gc::Heap* heap = Runtime::Current()->GetHeap();
+ if (heap->IsMovableObject(chars)) {
+ StackHandleScope<1> hs(soa.Self());
+ HandleWrapper<mirror::CharArray> h(hs.NewHandleWrapper(&chars));
+ heap->IncrementDisableMovingGC(soa.Self());
+ }
+ if (is_copy != nullptr) {
+ *is_copy = JNI_FALSE;
+ }
+ return static_cast<jchar*>(chars->GetData() + offset);
}
static void ReleaseStringCritical(JNIEnv* env, jstring java_string, const jchar* chars) {
- return ReleaseStringChars(env, java_string, chars);
+ CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_string);
+ ScopedObjectAccess soa(env);
+ UnpinPrimitiveArray(soa, soa.Decode<mirror::String*>(java_string)->GetCharArray());
+ gc::Heap* heap = Runtime::Current()->GetHeap();
+ mirror::String* s = soa.Decode<mirror::String*>(java_string);
+ mirror::CharArray* s_chars = s->GetCharArray();
+ if (heap->IsMovableObject(s_chars)) {
+ heap->DecrementDisableMovingGC(soa.Self());
+ }
}
static const char* GetStringUTFChars(JNIEnv* env, jstring java_string, jboolean* is_copy) {
diff --git a/runtime/jni_internal_test.cc b/runtime/jni_internal_test.cc
index 342982708a..f182e950bd 100644
--- a/runtime/jni_internal_test.cc
+++ b/runtime/jni_internal_test.cc
@@ -18,6 +18,7 @@
#include "common_compiler_test.h"
#include "mirror/art_method-inl.h"
+#include "mirror/string-inl.h"
#include "ScopedLocalRef.h"
namespace art {
@@ -1071,6 +1072,8 @@ TEST_F(JniInternalTest, GetStringUTFChars_ReleaseStringUTFChars) {
TEST_F(JniInternalTest, GetStringChars_ReleaseStringChars) {
jstring s = env_->NewStringUTF("hello");
+ ScopedObjectAccess soa(env_);
+ mirror::String* s_m = soa.Decode<mirror::String*>(s);
ASSERT_TRUE(s != nullptr);
jchar expected[] = { 'h', 'e', 'l', 'l', 'o' };
@@ -1084,7 +1087,11 @@ TEST_F(JniInternalTest, GetStringChars_ReleaseStringChars) {
jboolean is_copy = JNI_FALSE;
chars = env_->GetStringChars(s, &is_copy);
- EXPECT_EQ(JNI_TRUE, is_copy);
+ if (Runtime::Current()->GetHeap()->IsMovableObject(s_m->GetCharArray())) {
+ EXPECT_EQ(JNI_TRUE, is_copy);
+ } else {
+ EXPECT_EQ(JNI_FALSE, is_copy);
+ }
EXPECT_EQ(expected[0], chars[0]);
EXPECT_EQ(expected[1], chars[1]);
EXPECT_EQ(expected[2], chars[2]);
@@ -1106,10 +1113,9 @@ TEST_F(JniInternalTest, GetStringCritical_ReleaseStringCritical) {
EXPECT_EQ(expected[4], chars[4]);
env_->ReleaseStringCritical(s, chars);
- jboolean is_copy = JNI_FALSE;
+ jboolean is_copy = JNI_TRUE;
chars = env_->GetStringCritical(s, &is_copy);
- // TODO: Fix GetStringCritical to use the same mechanism as GetPrimitiveArrayElementsCritical.
- EXPECT_EQ(JNI_TRUE, is_copy);
+ EXPECT_EQ(JNI_FALSE, is_copy);
EXPECT_EQ(expected[0], chars[0]);
EXPECT_EQ(expected[1], chars[1]);
EXPECT_EQ(expected[2], chars[2]);