summaryrefslogtreecommitdiff
path: root/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'runtime')
-rw-r--r--runtime/debugger.cc5
-rw-r--r--runtime/debugger.h1
-rw-r--r--runtime/fault_handler.cc4
-rw-r--r--runtime/image.cc2
-rw-r--r--runtime/instrumentation.cc9
-rw-r--r--runtime/interpreter/interpreter_intrinsics.cc11
-rw-r--r--runtime/intrinsics_list.h1
-rw-r--r--runtime/runtime_callbacks.cc9
-rw-r--r--runtime/runtime_callbacks.h9
9 files changed, 46 insertions, 5 deletions
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index 99a4c77979..0481c03d52 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -364,6 +364,11 @@ bool DebuggerActiveMethodInspectionCallback::IsMethodSafeToJit(ArtMethod* m) {
return !Dbg::MethodHasAnyBreakpoints(m);
}
+bool DebuggerActiveMethodInspectionCallback::MethodNeedsDebugVersion(
+ ArtMethod* m ATTRIBUTE_UNUSED) {
+ return Dbg::IsDebuggerActive();
+}
+
void InternalDebuggerControlCallback::StartDebugger() {
// Release the mutator lock.
ScopedThreadStateChange stsc(art::Thread::Current(), kNative);
diff --git a/runtime/debugger.h b/runtime/debugger.h
index 74018137a0..e1de991812 100644
--- a/runtime/debugger.h
+++ b/runtime/debugger.h
@@ -56,6 +56,7 @@ class Thread;
struct DebuggerActiveMethodInspectionCallback : public MethodInspectionCallback {
bool IsMethodBeingInspected(ArtMethod* method) OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_);
bool IsMethodSafeToJit(ArtMethod* method) OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_);
+ bool MethodNeedsDebugVersion(ArtMethod* method) OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_);
};
struct DebuggerDdmCallback : public DdmCallback {
diff --git a/runtime/fault_handler.cc b/runtime/fault_handler.cc
index 3015b10103..671079b128 100644
--- a/runtime/fault_handler.cc
+++ b/runtime/fault_handler.cc
@@ -37,7 +37,9 @@ namespace art {
// Static fault manger object accessed by signal handler.
FaultManager fault_manager;
-extern "C" __attribute__((visibility("default"))) void art_sigsegv_fault() {
+// This needs to be NO_INLINE since some debuggers do not read the inline-info to set a breakpoint
+// if it isn't.
+extern "C" NO_INLINE __attribute__((visibility("default"))) void art_sigsegv_fault() {
// Set a breakpoint here to be informed when a SIGSEGV is unhandled by ART.
VLOG(signals)<< "Caught unknown SIGSEGV in ART fault handler - chaining to next handler.";
}
diff --git a/runtime/image.cc b/runtime/image.cc
index 0955c3a3ca..3b13d05d80 100644
--- a/runtime/image.cc
+++ b/runtime/image.cc
@@ -26,7 +26,7 @@
namespace art {
const uint8_t ImageHeader::kImageMagic[] = { 'a', 'r', 't', '\n' };
-const uint8_t ImageHeader::kImageVersion[] = { '0', '5', '5', '\0' }; // Bitstring type check off.
+const uint8_t ImageHeader::kImageVersion[] = { '0', '5', '6', '\0' }; // ReachabilityFence.
ImageHeader::ImageHeader(uint32_t image_begin,
uint32_t image_size,
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index 84a148f21c..d7f33d5e43 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -139,10 +139,13 @@ static void UpdateEntrypoints(ArtMethod* method, const void* quick_code)
bool Instrumentation::NeedDebugVersionFor(ArtMethod* method) const
REQUIRES_SHARED(Locks::mutator_lock_) {
- return Runtime::Current()->IsJavaDebuggable() &&
+ art::Runtime* runtime = Runtime::Current();
+ // If anything says we need the debug version or we are debuggable we will need the debug version
+ // of the method.
+ return (runtime->GetRuntimeCallbacks()->MethodNeedsDebugVersion(method) ||
+ runtime->IsJavaDebuggable()) &&
!method->IsNative() &&
- !method->IsProxyMethod() &&
- Runtime::Current()->GetRuntimeCallbacks()->IsMethodBeingInspected(method);
+ !method->IsProxyMethod();
}
void Instrumentation::InstallStubsForMethod(ArtMethod* method) {
diff --git a/runtime/interpreter/interpreter_intrinsics.cc b/runtime/interpreter/interpreter_intrinsics.cc
index 681a582b5d..f0cf2af7c7 100644
--- a/runtime/interpreter/interpreter_intrinsics.cc
+++ b/runtime/interpreter/interpreter_intrinsics.cc
@@ -399,6 +399,16 @@ VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleWeakCompareAndSetAcquire)
VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleWeakCompareAndSetPlain)
VAR_HANDLE_ACCESSOR_INTRINSIC(VarHandleWeakCompareAndSetRelease)
+static ALWAYS_INLINE bool MterpReachabilityFence(ShadowFrame* shadow_frame ATTRIBUTE_UNUSED,
+ const Instruction* inst ATTRIBUTE_UNUSED,
+ uint16_t inst_data ATTRIBUTE_UNUSED,
+ JValue* result_register ATTRIBUTE_UNUSED)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ // Do nothing; Its only purpose is to keep the argument reference live
+ // at preceding suspend points. That's automatic in the interpreter.
+ return true;
+}
+
// Macro to help keep track of what's left to implement.
#define UNIMPLEMENTED_CASE(name) \
case Intrinsics::k##name: \
@@ -499,6 +509,7 @@ bool MterpHandleIntrinsic(ShadowFrame* shadow_frame,
UNIMPLEMENTED_CASE(MemoryPokeIntNative /* (JI)V */)
UNIMPLEMENTED_CASE(MemoryPokeLongNative /* (JJ)V */)
UNIMPLEMENTED_CASE(MemoryPokeShortNative /* (JS)V */)
+ INTRINSIC_CASE(ReachabilityFence /* (Ljava/lang/Object;)V */)
INTRINSIC_CASE(StringCharAt)
INTRINSIC_CASE(StringCompareTo)
INTRINSIC_CASE(StringEquals)
diff --git a/runtime/intrinsics_list.h b/runtime/intrinsics_list.h
index da08793f59..2f91f5dfe0 100644
--- a/runtime/intrinsics_list.h
+++ b/runtime/intrinsics_list.h
@@ -218,6 +218,7 @@
V(VarHandleReleaseFence, kStatic, kNeedsEnvironmentOrCache, kWriteSideEffects, kNoThrow, "Ljava/lang/invoke/VarHandle;", "releaseFence", "()V") \
V(VarHandleLoadLoadFence, kStatic, kNeedsEnvironmentOrCache, kWriteSideEffects, kNoThrow, "Ljava/lang/invoke/VarHandle;", "loadLoadFence", "()V") \
V(VarHandleStoreStoreFence, kStatic, kNeedsEnvironmentOrCache, kReadSideEffects, kNoThrow, "Ljava/lang/invoke/VarHandle;", "storeStoreFence", "()V") \
+ V(ReachabilityFence, kStatic, kNeedsEnvironmentOrCache, kWriteSideEffects, kNoThrow, "Ljava/lang/ref/Reference;", "reachabilityFence", "(Ljava/lang/Object;)V") \
SIGNATURE_POLYMORPHIC_INTRINSICS_LIST(V)
#endif // ART_RUNTIME_INTRINSICS_LIST_H_
diff --git a/runtime/runtime_callbacks.cc b/runtime/runtime_callbacks.cc
index cd3c0b7c88..758917cf7e 100644
--- a/runtime/runtime_callbacks.cc
+++ b/runtime/runtime_callbacks.cc
@@ -106,6 +106,15 @@ bool RuntimeCallbacks::IsMethodBeingInspected(ArtMethod* m) {
return false;
}
+bool RuntimeCallbacks::MethodNeedsDebugVersion(ArtMethod* m) {
+ for (MethodInspectionCallback* cb : method_inspection_callbacks_) {
+ if (cb->MethodNeedsDebugVersion(m)) {
+ return true;
+ }
+ }
+ return false;
+}
+
void RuntimeCallbacks::AddThreadLifecycleCallback(ThreadLifecycleCallback* cb) {
thread_callbacks_.push_back(cb);
}
diff --git a/runtime/runtime_callbacks.h b/runtime/runtime_callbacks.h
index 24386ba14a..9f0410d102 100644
--- a/runtime/runtime_callbacks.h
+++ b/runtime/runtime_callbacks.h
@@ -130,6 +130,10 @@ class MethodInspectionCallback {
// Note that '!IsMethodSafeToJit(m) implies IsMethodBeingInspected(m)'. That is that if this
// method returns false IsMethodBeingInspected must return true.
virtual bool IsMethodSafeToJit(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) = 0;
+
+ // Returns true if we expect the method to be debuggable but are not doing anything unusual with
+ // it currently.
+ virtual bool MethodNeedsDebugVersion(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) = 0;
};
class RuntimeCallbacks {
@@ -198,6 +202,11 @@ class RuntimeCallbacks {
// entrypoint should not be changed to JITed code.
bool IsMethodSafeToJit(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_);
+ // Returns true if some MethodInspectionCallback indicates the method needs to use a debug
+ // version. This allows later code to set breakpoints or perform other actions that could be
+ // broken by some optimizations.
+ bool MethodNeedsDebugVersion(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_);
+
void AddMethodInspectionCallback(MethodInspectionCallback* cb)
REQUIRES_SHARED(Locks::mutator_lock_);
void RemoveMethodInspectionCallback(MethodInspectionCallback* cb)