1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2018 The Android Open Source Project 3*795d594fSAndroid Build Coastguard Worker * 4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*795d594fSAndroid Build Coastguard Worker * 8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*795d594fSAndroid Build Coastguard Worker * 10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*795d594fSAndroid Build Coastguard Worker * limitations under the License. 15*795d594fSAndroid Build Coastguard Worker */ 16*795d594fSAndroid Build Coastguard Worker 17*795d594fSAndroid Build Coastguard Worker // The interpreter function takes considerable time to compile and link. 18*795d594fSAndroid Build Coastguard Worker // We compile the explicit definitions separately to speed up the build. 19*795d594fSAndroid Build Coastguard Worker 20*795d594fSAndroid Build Coastguard Worker #include "interpreter_switch_impl-inl.h" 21*795d594fSAndroid Build Coastguard Worker 22*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN { 23*795d594fSAndroid Build Coastguard Worker namespace interpreter { 24*795d594fSAndroid Build Coastguard Worker 25*795d594fSAndroid Build Coastguard Worker // Define the helper class that does not do any transaction checks. 26*795d594fSAndroid Build Coastguard Worker class InactiveTransactionChecker { 27*795d594fSAndroid Build Coastguard Worker public: WriteConstraint(Thread * self,ObjPtr<mirror::Object> obj)28*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE static bool WriteConstraint([[maybe_unused]] Thread* self, 29*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] ObjPtr<mirror::Object> obj) 30*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) { 31*795d594fSAndroid Build Coastguard Worker return false; 32*795d594fSAndroid Build Coastguard Worker } 33*795d594fSAndroid Build Coastguard Worker WriteValueConstraint(Thread * self,ObjPtr<mirror::Object> value)34*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE static bool WriteValueConstraint([[maybe_unused]] Thread* self, 35*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] ObjPtr<mirror::Object> value) 36*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) { 37*795d594fSAndroid Build Coastguard Worker return false; 38*795d594fSAndroid Build Coastguard Worker } 39*795d594fSAndroid Build Coastguard Worker ReadConstraint(Thread * self,ObjPtr<mirror::Object> value)40*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE static bool ReadConstraint([[maybe_unused]] Thread* self, 41*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] ObjPtr<mirror::Object> value) 42*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) { 43*795d594fSAndroid Build Coastguard Worker return false; 44*795d594fSAndroid Build Coastguard Worker } 45*795d594fSAndroid Build Coastguard Worker AllocationConstraint(Thread * self,ObjPtr<mirror::Class> klass)46*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE static bool AllocationConstraint([[maybe_unused]] Thread* self, 47*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] ObjPtr<mirror::Class> klass) 48*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) { 49*795d594fSAndroid Build Coastguard Worker return false; 50*795d594fSAndroid Build Coastguard Worker } 51*795d594fSAndroid Build Coastguard Worker IsTransactionAborted()52*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE static bool IsTransactionAborted() { 53*795d594fSAndroid Build Coastguard Worker return false; 54*795d594fSAndroid Build Coastguard Worker } 55*795d594fSAndroid Build Coastguard Worker RecordArrayElementsInTransaction(ObjPtr<mirror::Object> array,int32_t count)56*795d594fSAndroid Build Coastguard Worker static void RecordArrayElementsInTransaction([[maybe_unused]] ObjPtr<mirror::Object> array, 57*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] int32_t count) 58*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {} 59*795d594fSAndroid Build Coastguard Worker RecordNewObject(ObjPtr<mirror::Object> new_object)60*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE static void RecordNewObject([[maybe_unused]] ObjPtr<mirror::Object> new_object) 61*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {} 62*795d594fSAndroid Build Coastguard Worker RecordNewArray(ObjPtr<mirror::Array> new_array)63*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE static void RecordNewArray([[maybe_unused]] ObjPtr<mirror::Array> new_array) 64*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {} 65*795d594fSAndroid Build Coastguard Worker }; 66*795d594fSAndroid Build Coastguard Worker 67*795d594fSAndroid Build Coastguard Worker class ActiveInstrumentationHandler { 68*795d594fSAndroid Build Coastguard Worker public: 69*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE WARN_UNUSED HasFieldReadListeners(const instrumentation::Instrumentation * instrumentation)70*795d594fSAndroid Build Coastguard Worker static bool HasFieldReadListeners(const instrumentation::Instrumentation* instrumentation) 71*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) { 72*795d594fSAndroid Build Coastguard Worker return instrumentation->HasFieldReadListeners(); 73*795d594fSAndroid Build Coastguard Worker } 74*795d594fSAndroid Build Coastguard Worker 75*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE WARN_UNUSED HasFieldWriteListeners(const instrumentation::Instrumentation * instrumentation)76*795d594fSAndroid Build Coastguard Worker static bool HasFieldWriteListeners(const instrumentation::Instrumentation* instrumentation) 77*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) { 78*795d594fSAndroid Build Coastguard Worker return instrumentation->HasFieldWriteListeners(); 79*795d594fSAndroid Build Coastguard Worker } 80*795d594fSAndroid Build Coastguard Worker 81*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE WARN_UNUSED HasBranchListeners(const instrumentation::Instrumentation * instrumentation)82*795d594fSAndroid Build Coastguard Worker static bool HasBranchListeners(const instrumentation::Instrumentation* instrumentation) 83*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) { 84*795d594fSAndroid Build Coastguard Worker return instrumentation->HasBranchListeners(); 85*795d594fSAndroid Build Coastguard Worker } 86*795d594fSAndroid Build Coastguard Worker 87*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE WARN_UNUSED NeedsDexPcEvents(ShadowFrame & shadow_frame)88*795d594fSAndroid Build Coastguard Worker static bool NeedsDexPcEvents(ShadowFrame& shadow_frame) 89*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) { 90*795d594fSAndroid Build Coastguard Worker DCHECK_IMPLIES(shadow_frame.GetNotifyDexPcMoveEvents(), 91*795d594fSAndroid Build Coastguard Worker Runtime::Current()->GetInstrumentation()->HasDexPcListeners()); 92*795d594fSAndroid Build Coastguard Worker return shadow_frame.GetNotifyDexPcMoveEvents(); 93*795d594fSAndroid Build Coastguard Worker } 94*795d594fSAndroid Build Coastguard Worker 95*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE WARN_UNUSED NeedsMethodExitEvent(const instrumentation::Instrumentation * instrumentation)96*795d594fSAndroid Build Coastguard Worker static bool NeedsMethodExitEvent(const instrumentation::Instrumentation* instrumentation) 97*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) { 98*795d594fSAndroid Build Coastguard Worker return interpreter::NeedsMethodExitEvent(instrumentation); 99*795d594fSAndroid Build Coastguard Worker } 100*795d594fSAndroid Build Coastguard Worker 101*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE WARN_UNUSED GetForcePopFrame(ShadowFrame & shadow_frame)102*795d594fSAndroid Build Coastguard Worker static bool GetForcePopFrame(ShadowFrame& shadow_frame) { 103*795d594fSAndroid Build Coastguard Worker DCHECK_IMPLIES(shadow_frame.GetForcePopFrame(), 104*795d594fSAndroid Build Coastguard Worker Runtime::Current()->AreNonStandardExitsEnabled()); 105*795d594fSAndroid Build Coastguard Worker return shadow_frame.GetForcePopFrame(); 106*795d594fSAndroid Build Coastguard Worker } 107*795d594fSAndroid Build Coastguard Worker 108*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE Branch(Thread * self,ArtMethod * method,uint32_t dex_pc,int32_t dex_pc_offset,const instrumentation::Instrumentation * instrumentation)109*795d594fSAndroid Build Coastguard Worker static void Branch(Thread* self, 110*795d594fSAndroid Build Coastguard Worker ArtMethod* method, 111*795d594fSAndroid Build Coastguard Worker uint32_t dex_pc, 112*795d594fSAndroid Build Coastguard Worker int32_t dex_pc_offset, 113*795d594fSAndroid Build Coastguard Worker const instrumentation::Instrumentation* instrumentation) 114*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) { 115*795d594fSAndroid Build Coastguard Worker instrumentation->Branch(self, method, dex_pc, dex_pc_offset); 116*795d594fSAndroid Build Coastguard Worker } 117*795d594fSAndroid Build Coastguard Worker ExceptionHandledEvent(Thread * self,bool is_move_exception,const instrumentation::Instrumentation * instrumentation)118*795d594fSAndroid Build Coastguard Worker static bool ExceptionHandledEvent(Thread* self, 119*795d594fSAndroid Build Coastguard Worker bool is_move_exception, 120*795d594fSAndroid Build Coastguard Worker const instrumentation::Instrumentation* instrumentation) 121*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) { 122*795d594fSAndroid Build Coastguard Worker StackHandleScope<1> hs(self); 123*795d594fSAndroid Build Coastguard Worker Handle<mirror::Throwable> exception(hs.NewHandle(self->GetException())); 124*795d594fSAndroid Build Coastguard Worker // Clear any exception while reporting the ExceptionHandled event. We should not run the handler 125*795d594fSAndroid Build Coastguard Worker // with an exception set. 126*795d594fSAndroid Build Coastguard Worker self->ClearException(); 127*795d594fSAndroid Build Coastguard Worker instrumentation->ExceptionHandledEvent(self, exception.Get()); 128*795d594fSAndroid Build Coastguard Worker // If there is an exception then that is the exception thrown by the exception handled event 129*795d594fSAndroid Build Coastguard Worker // and we should just handle the new exception. The earlier exception if any is ignored. 130*795d594fSAndroid Build Coastguard Worker if (self->IsExceptionPending()) { 131*795d594fSAndroid Build Coastguard Worker return false; // Pending exception. 132*795d594fSAndroid Build Coastguard Worker } 133*795d594fSAndroid Build Coastguard Worker 134*795d594fSAndroid Build Coastguard Worker // Restore the original exception if the instruction we are going to execute is a move exception 135*795d594fSAndroid Build Coastguard Worker // instruction. 136*795d594fSAndroid Build Coastguard Worker if (is_move_exception) { 137*795d594fSAndroid Build Coastguard Worker self->SetException(exception.Get()); 138*795d594fSAndroid Build Coastguard Worker } 139*795d594fSAndroid Build Coastguard Worker return true; 140*795d594fSAndroid Build Coastguard Worker } 141*795d594fSAndroid Build Coastguard Worker 142*795d594fSAndroid Build Coastguard Worker // Unlike most other events the DexPcMovedEvent can be sent when there is a pending exception (if 143*795d594fSAndroid Build Coastguard Worker // the next instruction is MOVE_EXCEPTION). This means it needs to be handled carefully to be able 144*795d594fSAndroid Build Coastguard Worker // to detect exceptions thrown by the DexPcMovedEvent itself. These exceptions could be thrown by 145*795d594fSAndroid Build Coastguard Worker // jvmti-agents while handling breakpoint or single step events. We had to move this into its own 146*795d594fSAndroid Build Coastguard Worker // function because it was making ExecuteSwitchImpl have too large a stack. DoDexPcMoveEvent(Thread * self,const CodeItemDataAccessor & accessor,const ShadowFrame & shadow_frame,uint32_t dex_pc,const instrumentation::Instrumentation * instrumentation,JValue * save_ref)147*795d594fSAndroid Build Coastguard Worker NO_INLINE static bool DoDexPcMoveEvent(Thread* self, 148*795d594fSAndroid Build Coastguard Worker const CodeItemDataAccessor& accessor, 149*795d594fSAndroid Build Coastguard Worker const ShadowFrame& shadow_frame, 150*795d594fSAndroid Build Coastguard Worker uint32_t dex_pc, 151*795d594fSAndroid Build Coastguard Worker const instrumentation::Instrumentation* instrumentation, 152*795d594fSAndroid Build Coastguard Worker JValue* save_ref) 153*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) { 154*795d594fSAndroid Build Coastguard Worker DCHECK(instrumentation->HasDexPcListeners()); 155*795d594fSAndroid Build Coastguard Worker StackHandleScope<2> hs(self); 156*795d594fSAndroid Build Coastguard Worker Handle<mirror::Throwable> thr(hs.NewHandle(self->GetException())); 157*795d594fSAndroid Build Coastguard Worker mirror::Object* null_obj = nullptr; 158*795d594fSAndroid Build Coastguard Worker HandleWrapper<mirror::Object> h( 159*795d594fSAndroid Build Coastguard Worker hs.NewHandleWrapper(LIKELY(save_ref == nullptr) ? &null_obj : save_ref->GetGCRoot())); 160*795d594fSAndroid Build Coastguard Worker self->ClearException(); 161*795d594fSAndroid Build Coastguard Worker instrumentation->DexPcMovedEvent(self, 162*795d594fSAndroid Build Coastguard Worker shadow_frame.GetThisObject(accessor.InsSize()), 163*795d594fSAndroid Build Coastguard Worker shadow_frame.GetMethod(), 164*795d594fSAndroid Build Coastguard Worker dex_pc); 165*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(self->IsExceptionPending())) { 166*795d594fSAndroid Build Coastguard Worker // We got a new exception in the dex-pc-moved event. 167*795d594fSAndroid Build Coastguard Worker // We just let this exception replace the old one. 168*795d594fSAndroid Build Coastguard Worker // TODO It would be good to add the old exception to the 169*795d594fSAndroid Build Coastguard Worker // suppressed exceptions of the new one if possible. 170*795d594fSAndroid Build Coastguard Worker return false; // Pending exception. 171*795d594fSAndroid Build Coastguard Worker } 172*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(!thr.IsNull())) { 173*795d594fSAndroid Build Coastguard Worker self->SetException(thr.Get()); 174*795d594fSAndroid Build Coastguard Worker } 175*795d594fSAndroid Build Coastguard Worker return true; 176*795d594fSAndroid Build Coastguard Worker } 177*795d594fSAndroid Build Coastguard Worker 178*795d594fSAndroid Build Coastguard Worker template <typename T> 179*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE WARN_UNUSED SendMethodExitEvents(Thread * self,const instrumentation::Instrumentation * instrumentation,ShadowFrame & frame,ArtMethod * method,T & result)180*795d594fSAndroid Build Coastguard Worker static bool SendMethodExitEvents( 181*795d594fSAndroid Build Coastguard Worker Thread* self, 182*795d594fSAndroid Build Coastguard Worker const instrumentation::Instrumentation* instrumentation, 183*795d594fSAndroid Build Coastguard Worker ShadowFrame& frame, 184*795d594fSAndroid Build Coastguard Worker ArtMethod* method, 185*795d594fSAndroid Build Coastguard Worker T& result) REQUIRES_SHARED(Locks::mutator_lock_) { 186*795d594fSAndroid Build Coastguard Worker return interpreter::SendMethodExitEvents(self, instrumentation, frame, method, result); 187*795d594fSAndroid Build Coastguard Worker } 188*795d594fSAndroid Build Coastguard Worker }; 189*795d594fSAndroid Build Coastguard Worker 190*795d594fSAndroid Build Coastguard Worker // Explicit definition of ExecuteSwitchImplCpp. 191*795d594fSAndroid Build Coastguard Worker template HOT_ATTR 192*795d594fSAndroid Build Coastguard Worker void ExecuteSwitchImplCpp<false>(SwitchImplContext* ctx); 193*795d594fSAndroid Build Coastguard Worker 194*795d594fSAndroid Build Coastguard Worker } // namespace interpreter 195*795d594fSAndroid Build Coastguard Worker } // namespace art 196