summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVladimir Marko <vmarko@google.com>2014-07-24 17:01:58 +0100
committerVladimir Marko <vmarko@google.com>2014-07-25 15:43:48 +0100
commit4e24b9da7c5ea6e517ecdbc09aa14a0995100b7e (patch)
tree61622ae343da40c7cd853efb2abc9c6e58f09894
parentca928ba8b9e109ced2b9d72622dc34bda63ac211 (diff)
downloadart-4e24b9da7c5ea6e517ecdbc09aa14a0995100b7e.zip
art-4e24b9da7c5ea6e517ecdbc09aa14a0995100b7e.tar.gz
art-4e24b9da7c5ea6e517ecdbc09aa14a0995100b7e.tar.bz2
Fix JNI compiler frame size adjustments.
Bug: 16321952 Change-Id: I6f84a59c679e335e02a8e70944a5d0bc8d73f90b
-rw-r--r--compiler/jni/jni_compiler_test.cc27
-rw-r--r--compiler/jni/quick/jni_compiler.cc24
2 files changed, 42 insertions, 9 deletions
diff --git a/compiler/jni/jni_compiler_test.cc b/compiler/jni/jni_compiler_test.cc
index b4d863b..995ea46 100644
--- a/compiler/jni/jni_compiler_test.cc
+++ b/compiler/jni/jni_compiler_test.cc
@@ -720,10 +720,33 @@ TEST_F(JniCompilerTest, GetText) {
EXPECT_EQ(result, 42);
}
+int gJava_MyClassNatives_GetSinkProperties_calls = 0;
+jarray Java_MyClassNatives_GetSinkProperties(JNIEnv* env, jobject thisObj, jstring s) {
+ // 1 = thisObj
+ Thread* self = Thread::Current();
+ EXPECT_EQ(kNative, self->GetState());
+ Locks::mutator_lock_->AssertNotHeld(self);
+ EXPECT_EQ(self->GetJniEnv(), env);
+ EXPECT_TRUE(thisObj != nullptr);
+ EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
+ EXPECT_EQ(s, nullptr);
+ gJava_MyClassNatives_GetSinkProperties_calls++;
+ ScopedObjectAccess soa(self);
+ EXPECT_EQ(2U, self->NumStackReferences());
+ EXPECT_TRUE(self->HoldsLock(soa.Decode<mirror::Object*>(thisObj)));
+ return nullptr;
+}
+
TEST_F(JniCompilerTest, GetSinkPropertiesNative) {
TEST_DISABLED_FOR_PORTABLE();
- SetUpForTest(false, "getSinkPropertiesNative", "(Ljava/lang/String;)[Ljava/lang/Object;", nullptr);
- // This space intentionally left blank. Just testing compilation succeeds.
+ SetUpForTest(false, "getSinkPropertiesNative", "(Ljava/lang/String;)[Ljava/lang/Object;",
+ reinterpret_cast<void*>(&Java_MyClassNatives_GetSinkProperties));
+
+ EXPECT_EQ(0, gJava_MyClassNatives_GetSinkProperties_calls);
+ jarray result = down_cast<jarray>(
+ env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, nullptr));
+ EXPECT_EQ(nullptr, result);
+ EXPECT_EQ(1, gJava_MyClassNatives_GetSinkProperties_calls);
}
// This should return jclass, but we're imitating a bug pattern.
diff --git a/compiler/jni/quick/jni_compiler.cc b/compiler/jni/quick/jni_compiler.cc
index dec84f1..c38cfaf 100644
--- a/compiler/jni/quick/jni_compiler.cc
+++ b/compiler/jni/quick/jni_compiler.cc
@@ -183,9 +183,8 @@ CompiledMethod* ArtJniCompileMethodInternal(CompilerDriver* driver,
// 5. Move frame down to allow space for out going args.
const size_t main_out_arg_size = main_jni_conv->OutArgSize();
- const size_t end_out_arg_size = end_jni_conv->OutArgSize();
- const size_t max_out_arg_size = std::max(main_out_arg_size, end_out_arg_size);
- __ IncreaseFrameSize(max_out_arg_size);
+ size_t current_out_arg_size = main_out_arg_size;
+ __ IncreaseFrameSize(main_out_arg_size);
// 6. Call into appropriate JniMethodStart passing Thread* so that transition out of Runnable
// can occur. The result is the saved JNI local state that is restored by the exit call. We
@@ -244,7 +243,7 @@ CompiledMethod* ArtJniCompileMethodInternal(CompilerDriver* driver,
// NULL (which must be encoded as NULL).
// Note: we do this prior to materializing the JNIEnv* and static's jclass to
// give as many free registers for the shuffle as possible
- mr_conv->ResetIterator(FrameOffset(frame_size+main_out_arg_size));
+ mr_conv->ResetIterator(FrameOffset(frame_size + main_out_arg_size));
uint32_t args_count = 0;
while (mr_conv->HasNext()) {
args_count++;
@@ -270,7 +269,7 @@ CompiledMethod* ArtJniCompileMethodInternal(CompilerDriver* driver,
}
if (is_static) {
// Create argument for Class
- mr_conv->ResetIterator(FrameOffset(frame_size+main_out_arg_size));
+ mr_conv->ResetIterator(FrameOffset(frame_size + main_out_arg_size));
main_jni_conv->ResetIterator(FrameOffset(main_out_arg_size));
main_jni_conv->Next(); // Skip JNIEnv*
FrameOffset handle_scope_offset = main_jni_conv->CurrentParamHandleScopeEntryOffset();
@@ -333,10 +332,21 @@ CompiledMethod* ArtJniCompileMethodInternal(CompilerDriver* driver,
// Ensure doubles are 8-byte aligned for MIPS
return_save_location = FrameOffset(return_save_location.Uint32Value() + kMipsPointerSize);
}
- CHECK_LT(return_save_location.Uint32Value(), frame_size+main_out_arg_size);
+ CHECK_LT(return_save_location.Uint32Value(), frame_size + main_out_arg_size);
__ Store(return_save_location, main_jni_conv->ReturnRegister(), main_jni_conv->SizeOfReturnValue());
}
+ // Increase frame size for out args if needed by the end_jni_conv.
+ const size_t end_out_arg_size = end_jni_conv->OutArgSize();
+ if (end_out_arg_size > current_out_arg_size) {
+ size_t out_arg_size_diff = end_out_arg_size - current_out_arg_size;
+ current_out_arg_size = end_out_arg_size;
+ __ IncreaseFrameSize(out_arg_size_diff);
+ saved_cookie_offset = FrameOffset(saved_cookie_offset.SizeValue() + out_arg_size_diff);
+ locked_object_handle_scope_offset =
+ FrameOffset(locked_object_handle_scope_offset.SizeValue() + out_arg_size_diff);
+ return_save_location = FrameOffset(return_save_location.SizeValue() + out_arg_size_diff);
+ }
// thread.
end_jni_conv->ResetIterator(FrameOffset(end_out_arg_size));
ThreadOffset<4> jni_end32(-1);
@@ -403,7 +413,7 @@ CompiledMethod* ArtJniCompileMethodInternal(CompilerDriver* driver,
}
// 14. Move frame up now we're done with the out arg space.
- __ DecreaseFrameSize(max_out_arg_size);
+ __ DecreaseFrameSize(current_out_arg_size);
// 15. Process pending exceptions from JNI call or monitor exit.
__ ExceptionPoll(main_jni_conv->InterproceduralScratchRegister(), 0);