diff options
Diffstat (limited to 'runtime')
| -rw-r--r-- | runtime/debugger.cc | 5 | ||||
| -rw-r--r-- | runtime/debugger.h | 1 | ||||
| -rw-r--r-- | runtime/fault_handler.cc | 4 | ||||
| -rw-r--r-- | runtime/image.cc | 2 | ||||
| -rw-r--r-- | runtime/instrumentation.cc | 9 | ||||
| -rw-r--r-- | runtime/interpreter/interpreter_intrinsics.cc | 11 | ||||
| -rw-r--r-- | runtime/intrinsics_list.h | 1 | ||||
| -rw-r--r-- | runtime/runtime_callbacks.cc | 9 | ||||
| -rw-r--r-- | runtime/runtime_callbacks.h | 9 |
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) |