diff options
-rw-r--r-- | compiler/jni/quick/jni_compiler.cc | 46 | ||||
-rw-r--r-- | compiler/oat_test.cc | 2 | ||||
-rw-r--r-- | runtime/arch/arm/entrypoints_init_arm.cc | 3 | ||||
-rw-r--r-- | runtime/arch/arm64/entrypoints_init_arm64.cc | 3 | ||||
-rw-r--r-- | runtime/arch/mips/entrypoints_init_mips.cc | 3 | ||||
-rw-r--r-- | runtime/arch/mips64/entrypoints_init_mips64.cc | 3 | ||||
-rw-r--r-- | runtime/arch/x86/entrypoints_init_x86.cc | 3 | ||||
-rw-r--r-- | runtime/arch/x86_64/entrypoints_init_x86_64.cc | 3 | ||||
-rw-r--r-- | runtime/asm_support.h | 2 | ||||
-rw-r--r-- | runtime/entrypoints/quick/quick_entrypoints.h | 6 | ||||
-rw-r--r-- | runtime/entrypoints/quick/quick_entrypoints_list.h | 4 | ||||
-rw-r--r-- | runtime/entrypoints/quick/quick_jni_entrypoints.cc | 7 | ||||
-rw-r--r-- | runtime/entrypoints_order_test.cc | 4 | ||||
-rw-r--r-- | runtime/oat.h | 2 | ||||
-rw-r--r-- | runtime/thread.cc | 1 |
15 files changed, 86 insertions, 6 deletions
diff --git a/compiler/jni/quick/jni_compiler.cc b/compiler/jni/quick/jni_compiler.cc index 6f2cb25911..a06303d23e 100644 --- a/compiler/jni/quick/jni_compiler.cc +++ b/compiler/jni/quick/jni_compiler.cc @@ -138,7 +138,8 @@ CompiledMethod* ArtJniCompileMethodInternal(CompilerDriver* driver, FrameOffset handle_scope_offset = main_jni_conv->CurrentParamHandleScopeEntryOffset(); // Check handle scope offset is within frame CHECK_LT(handle_scope_offset.Uint32Value(), frame_size); - // TODO: Insert the read barrier for this load. + // Note this LoadRef() already includes the heap poisoning negation. + // Note this LoadRef() does not include read barrier. It will be handled below. __ LoadRef(main_jni_conv->InterproceduralScratchRegister(), mr_conv->MethodRegister(), mirror::ArtMethod::DeclaringClassOffset()); __ VerifyObject(main_jni_conv->InterproceduralScratchRegister(), false); @@ -189,6 +190,49 @@ CompiledMethod* ArtJniCompileMethodInternal(CompilerDriver* driver, size_t current_out_arg_size = main_out_arg_size; __ IncreaseFrameSize(main_out_arg_size); + // Call the read barrier for the declaring class loaded from the method for a static call. + // Note that we always have outgoing param space available for at least two params. + if (kUseReadBarrier && is_static) { + ThreadOffset<4> read_barrier32 = QUICK_ENTRYPOINT_OFFSET(4, pReadBarrierJni); + ThreadOffset<8> read_barrier64 = QUICK_ENTRYPOINT_OFFSET(8, pReadBarrierJni); + main_jni_conv->ResetIterator(FrameOffset(main_out_arg_size)); + main_jni_conv->Next(); // Skip JNIEnv. + FrameOffset class_handle_scope_offset = main_jni_conv->CurrentParamHandleScopeEntryOffset(); + main_jni_conv->ResetIterator(FrameOffset(main_out_arg_size)); + // Pass the handle for the class as the first argument. + if (main_jni_conv->IsCurrentParamOnStack()) { + FrameOffset out_off = main_jni_conv->CurrentParamStackOffset(); + __ CreateHandleScopeEntry(out_off, class_handle_scope_offset, + mr_conv->InterproceduralScratchRegister(), + false); + } else { + ManagedRegister out_reg = main_jni_conv->CurrentParamRegister(); + __ CreateHandleScopeEntry(out_reg, class_handle_scope_offset, + ManagedRegister::NoRegister(), false); + } + main_jni_conv->Next(); + // Pass the current thread as the second argument and call. + if (main_jni_conv->IsCurrentParamInRegister()) { + __ GetCurrentThread(main_jni_conv->CurrentParamRegister()); + if (is_64_bit_target) { + __ Call(main_jni_conv->CurrentParamRegister(), Offset(read_barrier64), + main_jni_conv->InterproceduralScratchRegister()); + } else { + __ Call(main_jni_conv->CurrentParamRegister(), Offset(read_barrier32), + main_jni_conv->InterproceduralScratchRegister()); + } + } else { + __ GetCurrentThread(main_jni_conv->CurrentParamStackOffset(), + main_jni_conv->InterproceduralScratchRegister()); + if (is_64_bit_target) { + __ CallFromThread64(read_barrier64, main_jni_conv->InterproceduralScratchRegister()); + } else { + __ CallFromThread32(read_barrier32, main_jni_conv->InterproceduralScratchRegister()); + } + } + main_jni_conv->ResetIterator(FrameOffset(main_out_arg_size)); // Reset. + } + // 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 // abuse the JNI calling convention here, that is guaranteed to support passing 2 pointer diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc index dbdcc96fc1..a871a82d95 100644 --- a/compiler/oat_test.cc +++ b/compiler/oat_test.cc @@ -176,7 +176,7 @@ TEST_F(OatTest, OatHeaderSizeCheck) { EXPECT_EQ(72U, sizeof(OatHeader)); EXPECT_EQ(4U, sizeof(OatMethodOffsets)); EXPECT_EQ(28U, sizeof(OatQuickMethodHeader)); - EXPECT_EQ(111 * GetInstructionSetPointerSize(kRuntimeISA), sizeof(QuickEntryPoints)); + EXPECT_EQ(112 * GetInstructionSetPointerSize(kRuntimeISA), sizeof(QuickEntryPoints)); } TEST_F(OatTest, OatHeaderIsValid) { diff --git a/runtime/arch/arm/entrypoints_init_arm.cc b/runtime/arch/arm/entrypoints_init_arm.cc index f14dfc27ae..cafc868789 100644 --- a/runtime/arch/arm/entrypoints_init_arm.cc +++ b/runtime/arch/arm/entrypoints_init_arm.cc @@ -166,6 +166,9 @@ void InitEntryPoints(InterpreterEntryPoints* ipoints, JniEntryPoints* jpoints, qpoints->pThrowStackOverflow = art_quick_throw_stack_overflow; qpoints->pDeoptimize = art_quick_deoptimize; + + // Read barrier + qpoints->pReadBarrierJni = ReadBarrierJni; } } // namespace art diff --git a/runtime/arch/arm64/entrypoints_init_arm64.cc b/runtime/arch/arm64/entrypoints_init_arm64.cc index 4b12f00d0d..8c8f8d51a8 100644 --- a/runtime/arch/arm64/entrypoints_init_arm64.cc +++ b/runtime/arch/arm64/entrypoints_init_arm64.cc @@ -159,6 +159,9 @@ void InitEntryPoints(InterpreterEntryPoints* ipoints, JniEntryPoints* jpoints, // Deoptimize qpoints->pDeoptimize = art_quick_deoptimize; + + // Read barrier + qpoints->pReadBarrierJni = ReadBarrierJni; }; } // namespace art diff --git a/runtime/arch/mips/entrypoints_init_mips.cc b/runtime/arch/mips/entrypoints_init_mips.cc index a980a86135..ff04106f15 100644 --- a/runtime/arch/mips/entrypoints_init_mips.cc +++ b/runtime/arch/mips/entrypoints_init_mips.cc @@ -272,6 +272,9 @@ void InitEntryPoints(InterpreterEntryPoints* ipoints, JniEntryPoints* jpoints, static_assert(IsDirectEntrypoint(kQuickA64Load), "Non-direct C stub marked direct."); qpoints->pA64Store = QuasiAtomic::Write64; static_assert(IsDirectEntrypoint(kQuickA64Store), "Non-direct C stub marked direct."); + + qpoints->pReadBarrierJni = ReadBarrierJni; + static_assert(!IsDirectEntrypoint(kQuickReadBarrierJni), "Non-direct C stub marked direct."); }; } // namespace art diff --git a/runtime/arch/mips64/entrypoints_init_mips64.cc b/runtime/arch/mips64/entrypoints_init_mips64.cc index b328708409..321c27bf50 100644 --- a/runtime/arch/mips64/entrypoints_init_mips64.cc +++ b/runtime/arch/mips64/entrypoints_init_mips64.cc @@ -180,6 +180,9 @@ void InitEntryPoints(InterpreterEntryPoints* ipoints, JniEntryPoints* jpoints, // Atomic 64-bit load/store qpoints->pA64Load = QuasiAtomic::Read64; qpoints->pA64Store = QuasiAtomic::Write64; + + // Read barrier + qpoints->pReadBarrierJni = ReadBarrierJni; }; } // namespace art diff --git a/runtime/arch/x86/entrypoints_init_x86.cc b/runtime/arch/x86/entrypoints_init_x86.cc index a371632367..737f4d1c5b 100644 --- a/runtime/arch/x86/entrypoints_init_x86.cc +++ b/runtime/arch/x86/entrypoints_init_x86.cc @@ -138,6 +138,9 @@ void InitEntryPoints(InterpreterEntryPoints* ipoints, JniEntryPoints* jpoints, // Deoptimize qpoints->pDeoptimize = art_quick_deoptimize_from_compiled_slow_path; + + // Read barrier + qpoints->pReadBarrierJni = ReadBarrierJni; }; } // namespace art diff --git a/runtime/arch/x86_64/entrypoints_init_x86_64.cc b/runtime/arch/x86_64/entrypoints_init_x86_64.cc index 0cddec4102..d0ab9d5d49 100644 --- a/runtime/arch/x86_64/entrypoints_init_x86_64.cc +++ b/runtime/arch/x86_64/entrypoints_init_x86_64.cc @@ -142,6 +142,9 @@ void InitEntryPoints(InterpreterEntryPoints* ipoints, JniEntryPoints* jpoints, // Deoptimize qpoints->pDeoptimize = art_quick_deoptimize_from_compiled_slow_path; + + // Read barrier + qpoints->pReadBarrierJni = ReadBarrierJni; #endif // __APPLE__ }; diff --git a/runtime/asm_support.h b/runtime/asm_support.h index a115fbe0f4..004745ee43 100644 --- a/runtime/asm_support.h +++ b/runtime/asm_support.h @@ -108,7 +108,7 @@ ADD_TEST_EQ(THREAD_TOP_QUICK_FRAME_OFFSET, ADD_TEST_EQ(THREAD_SELF_OFFSET, art::Thread::SelfOffset<__SIZEOF_POINTER__>().Int32Value()) -#define THREAD_LOCAL_POS_OFFSET (THREAD_CARD_TABLE_OFFSET + 145 * __SIZEOF_POINTER__) +#define THREAD_LOCAL_POS_OFFSET (THREAD_CARD_TABLE_OFFSET + 146 * __SIZEOF_POINTER__) ADD_TEST_EQ(THREAD_LOCAL_POS_OFFSET, art::Thread::ThreadLocalPosOffset<__SIZEOF_POINTER__>().Int32Value()) #define THREAD_LOCAL_END_OFFSET (THREAD_LOCAL_POS_OFFSET + __SIZEOF_POINTER__) diff --git a/runtime/entrypoints/quick/quick_entrypoints.h b/runtime/entrypoints/quick/quick_entrypoints.h index db8c0e3c58..b72ce34648 100644 --- a/runtime/entrypoints/quick/quick_entrypoints.h +++ b/runtime/entrypoints/quick/quick_entrypoints.h @@ -32,6 +32,8 @@ class Array; class ArtMethod; class Class; class Object; +template<class MirrorType> +class CompressedReference; } // namespace mirror class Thread; @@ -65,6 +67,10 @@ extern mirror::Object* JniMethodEndWithReferenceSynchronized(jobject result, jobject locked, Thread* self) NO_THREAD_SAFETY_ANALYSIS HOT_ATTR; +extern void ReadBarrierJni(mirror::CompressedReference<mirror::Object>* handle_on_stack, + Thread* self) + NO_THREAD_SAFETY_ANALYSIS HOT_ATTR; + } // namespace art #endif // ART_RUNTIME_ENTRYPOINTS_QUICK_QUICK_ENTRYPOINTS_H_ diff --git a/runtime/entrypoints/quick/quick_entrypoints_list.h b/runtime/entrypoints/quick/quick_entrypoints_list.h index 035f57a08a..0aca58fb16 100644 --- a/runtime/entrypoints/quick/quick_entrypoints_list.h +++ b/runtime/entrypoints/quick/quick_entrypoints_list.h @@ -143,7 +143,9 @@ V(NewStringFromCodePoints, void) \ V(NewStringFromString, void) \ V(NewStringFromStringBuffer, void) \ - V(NewStringFromStringBuilder, void) + V(NewStringFromStringBuilder, void) \ +\ + V(ReadBarrierJni, void, mirror::CompressedReference<mirror::Object>*, Thread*) #endif // ART_RUNTIME_ENTRYPOINTS_QUICK_QUICK_ENTRYPOINTS_LIST_H_ #undef ART_RUNTIME_ENTRYPOINTS_QUICK_QUICK_ENTRYPOINTS_LIST_H_ // #define is only for lint. diff --git a/runtime/entrypoints/quick/quick_jni_entrypoints.cc b/runtime/entrypoints/quick/quick_jni_entrypoints.cc index e478d2a840..51817a249d 100644 --- a/runtime/entrypoints/quick/quick_jni_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_jni_entrypoints.cc @@ -22,6 +22,13 @@ namespace art { +extern void ReadBarrierJni(mirror::CompressedReference<mirror::Object>* handle_on_stack, + Thread* self ATTRIBUTE_UNUSED) { + // Call the read barrier and update the handle. + mirror::Object* to_ref = ReadBarrier::BarrierForRoot(handle_on_stack); + handle_on_stack->Assign(to_ref); +} + // Called on entry to JNI, transition out of Runnable and release share of mutator_lock_. extern uint32_t JniMethodStart(Thread* self) { JNIEnvExt* env = self->GetJniEnv(); diff --git a/runtime/entrypoints_order_test.cc b/runtime/entrypoints_order_test.cc index 1fb45f4d4d..482f656fa6 100644 --- a/runtime/entrypoints_order_test.cc +++ b/runtime/entrypoints_order_test.cc @@ -305,8 +305,10 @@ class EntrypointsOrderTest : public CommonRuntimeTest { sizeof(void*)); EXPECT_OFFSET_DIFFNP(QuickEntryPoints, pNewStringFromStringBuffer, pNewStringFromStringBuilder, sizeof(void*)); + EXPECT_OFFSET_DIFFNP(QuickEntryPoints, pNewStringFromStringBuilder, pReadBarrierJni, + sizeof(void*)); - CHECKED(OFFSETOF_MEMBER(QuickEntryPoints, pNewStringFromStringBuilder) + CHECKED(OFFSETOF_MEMBER(QuickEntryPoints, pReadBarrierJni) + sizeof(void*) == sizeof(QuickEntryPoints), QuickEntryPoints_all); } }; diff --git a/runtime/oat.h b/runtime/oat.h index a31e09a3cf..aaf442a77a 100644 --- a/runtime/oat.h +++ b/runtime/oat.h @@ -32,7 +32,7 @@ class InstructionSetFeatures; class PACKED(4) OatHeader { public: static constexpr uint8_t kOatMagic[] = { 'o', 'a', 't', '\n' }; - static constexpr uint8_t kOatVersion[] = { '0', '6', '1', '\0' }; + static constexpr uint8_t kOatVersion[] = { '0', '6', '2', '\0' }; static constexpr const char* kImageLocationKey = "image-location"; static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline"; diff --git a/runtime/thread.cc b/runtime/thread.cc index c8aad1b787..5959259276 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -2072,6 +2072,7 @@ void Thread::DumpThreadOffset(std::ostream& os, uint32_t offset) { QUICK_ENTRY_POINT_INFO(pNewStringFromString) QUICK_ENTRY_POINT_INFO(pNewStringFromStringBuffer) QUICK_ENTRY_POINT_INFO(pNewStringFromStringBuilder) + QUICK_ENTRY_POINT_INFO(pReadBarrierJni) #undef QUICK_ENTRY_POINT_INFO os << offset; |