summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHiroshi Yamauchi <yamauchi@google.com>2015-05-07 10:47:27 -0700
committerHiroshi Yamauchi <yamauchi@google.com>2015-05-07 11:28:08 -0700
commit1cc71ebf333ca323ae0e130fefbce4593e385c10 (patch)
treee94897ebb36a21f1c276fc69c44f6a3522cbe093
parent35b6625c21e9304dd79700f4ff1c26a7e30d2b2d (diff)
downloadart-1cc71ebf333ca323ae0e130fefbce4593e385c10.zip
art-1cc71ebf333ca323ae0e130fefbce4593e385c10.tar.gz
art-1cc71ebf333ca323ae0e130fefbce4593e385c10.tar.bz2
Insert a read barrier in the JNI bridge.
Bug: 20720510 Bug: 12687968 Change-Id: Ia9edb614853bad45ec25d6e2142361a8bda1eccf
-rw-r--r--compiler/jni/quick/jni_compiler.cc46
-rw-r--r--compiler/oat_test.cc2
-rw-r--r--runtime/arch/arm/entrypoints_init_arm.cc3
-rw-r--r--runtime/arch/arm64/entrypoints_init_arm64.cc3
-rw-r--r--runtime/arch/mips/entrypoints_init_mips.cc3
-rw-r--r--runtime/arch/mips64/entrypoints_init_mips64.cc3
-rw-r--r--runtime/arch/x86/entrypoints_init_x86.cc3
-rw-r--r--runtime/arch/x86_64/entrypoints_init_x86_64.cc3
-rw-r--r--runtime/asm_support.h2
-rw-r--r--runtime/entrypoints/quick/quick_entrypoints.h6
-rw-r--r--runtime/entrypoints/quick/quick_entrypoints_list.h4
-rw-r--r--runtime/entrypoints/quick/quick_jni_entrypoints.cc7
-rw-r--r--runtime/entrypoints_order_test.cc4
-rw-r--r--runtime/oat.h2
-rw-r--r--runtime/thread.cc1
15 files changed, 86 insertions, 6 deletions
diff --git a/compiler/jni/quick/jni_compiler.cc b/compiler/jni/quick/jni_compiler.cc
index 6f2cb25..a06303d 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 dbdcc96..a871a82 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 f14dfc2..cafc868 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 4b12f00..8c8f8d5 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 a980a86..ff04106 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 b328708..321c27b 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 a371632..737f4d1 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 0cddec4..d0ab9d5 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 a115fbe..004745e 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 db8c0e3..b72ce34 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 035f57a..0aca58f 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 e478d2a..51817a2 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 1fb45f4..482f656 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 a31e09a..aaf442a 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 c8aad1b..5959259 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;