diff options
author | Vladimir Marko <vmarko@google.com> | 2014-07-24 17:01:58 +0100 |
---|---|---|
committer | Vladimir Marko <vmarko@google.com> | 2014-07-25 15:43:48 +0100 |
commit | 4e24b9da7c5ea6e517ecdbc09aa14a0995100b7e (patch) | |
tree | 61622ae343da40c7cd853efb2abc9c6e58f09894 | |
parent | ca928ba8b9e109ced2b9d72622dc34bda63ac211 (diff) | |
download | art-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.cc | 27 | ||||
-rw-r--r-- | compiler/jni/quick/jni_compiler.cc | 24 |
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); |