1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2011 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 #ifndef ART_RUNTIME_INTERPRETER_SHADOW_FRAME_H_ 18*795d594fSAndroid Build Coastguard Worker #define ART_RUNTIME_INTERPRETER_SHADOW_FRAME_H_ 19*795d594fSAndroid Build Coastguard Worker 20*795d594fSAndroid Build Coastguard Worker #include <cstdint> 21*795d594fSAndroid Build Coastguard Worker #include <cstring> 22*795d594fSAndroid Build Coastguard Worker #include <string> 23*795d594fSAndroid Build Coastguard Worker 24*795d594fSAndroid Build Coastguard Worker #include "base/locks.h" 25*795d594fSAndroid Build Coastguard Worker #include "base/macros.h" 26*795d594fSAndroid Build Coastguard Worker #include "lock_count_data.h" 27*795d594fSAndroid Build Coastguard Worker #include "read_barrier.h" 28*795d594fSAndroid Build Coastguard Worker #include "stack_reference.h" 29*795d594fSAndroid Build Coastguard Worker #include "verify_object.h" 30*795d594fSAndroid Build Coastguard Worker 31*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN { 32*795d594fSAndroid Build Coastguard Worker 33*795d594fSAndroid Build Coastguard Worker namespace mirror { 34*795d594fSAndroid Build Coastguard Worker class Object; 35*795d594fSAndroid Build Coastguard Worker } // namespace mirror 36*795d594fSAndroid Build Coastguard Worker 37*795d594fSAndroid Build Coastguard Worker class ArtMethod; 38*795d594fSAndroid Build Coastguard Worker class ShadowFrame; 39*795d594fSAndroid Build Coastguard Worker template<class MirrorType> class ObjPtr; 40*795d594fSAndroid Build Coastguard Worker class Thread; 41*795d594fSAndroid Build Coastguard Worker union JValue; 42*795d594fSAndroid Build Coastguard Worker 43*795d594fSAndroid Build Coastguard Worker // Forward declaration. Just calls the destructor. 44*795d594fSAndroid Build Coastguard Worker struct ShadowFrameDeleter; 45*795d594fSAndroid Build Coastguard Worker using ShadowFrameAllocaUniquePtr = std::unique_ptr<ShadowFrame, ShadowFrameDeleter>; 46*795d594fSAndroid Build Coastguard Worker 47*795d594fSAndroid Build Coastguard Worker // ShadowFrame has 2 possible layouts: 48*795d594fSAndroid Build Coastguard Worker // - interpreter - separate VRegs and reference arrays. References are in the reference array. 49*795d594fSAndroid Build Coastguard Worker // - JNI - just VRegs, but where every VReg holds a reference. 50*795d594fSAndroid Build Coastguard Worker class ShadowFrame { 51*795d594fSAndroid Build Coastguard Worker private: 52*795d594fSAndroid Build Coastguard Worker // Used to keep track of extra state the shadowframe has. 53*795d594fSAndroid Build Coastguard Worker enum class FrameFlags : uint32_t { 54*795d594fSAndroid Build Coastguard Worker // We have been requested to notify when this frame gets popped. 55*795d594fSAndroid Build Coastguard Worker kNotifyFramePop = 1 << 0, 56*795d594fSAndroid Build Coastguard Worker // We have been asked to pop this frame off the stack as soon as possible. 57*795d594fSAndroid Build Coastguard Worker kForcePopFrame = 1 << 1, 58*795d594fSAndroid Build Coastguard Worker // We have been asked to re-execute the last instruction. 59*795d594fSAndroid Build Coastguard Worker kForceRetryInst = 1 << 2, 60*795d594fSAndroid Build Coastguard Worker // Mark that we expect the next frame to retry the last instruction (used by instrumentation and 61*795d594fSAndroid Build Coastguard Worker // debuggers to keep track of required events) 62*795d594fSAndroid Build Coastguard Worker kSkipMethodExitEvents = 1 << 3, 63*795d594fSAndroid Build Coastguard Worker // Used to suppress exception events caused by other instrumentation events. 64*795d594fSAndroid Build Coastguard Worker kSkipNextExceptionEvent = 1 << 4, 65*795d594fSAndroid Build Coastguard Worker // Used to specify if DexPCMoveEvents have to be reported. These events will 66*795d594fSAndroid Build Coastguard Worker // only be reported if the method has a breakpoint set. 67*795d594fSAndroid Build Coastguard Worker kNotifyDexPcMoveEvents = 1 << 5, 68*795d594fSAndroid Build Coastguard Worker // Used to specify if ExceptionHandledEvent has to be reported. When enabled these events are 69*795d594fSAndroid Build Coastguard Worker // reported when we reach the catch block after an exception was thrown. These events have to 70*795d594fSAndroid Build Coastguard Worker // be reported after the DexPCMoveEvent if enabled. 71*795d594fSAndroid Build Coastguard Worker kNotifyExceptionHandledEvent = 1 << 6, 72*795d594fSAndroid Build Coastguard Worker }; 73*795d594fSAndroid Build Coastguard Worker 74*795d594fSAndroid Build Coastguard Worker public: 75*795d594fSAndroid Build Coastguard Worker // Compute size of ShadowFrame in bytes assuming it has a reference array. ComputeSize(uint32_t num_vregs)76*795d594fSAndroid Build Coastguard Worker static size_t ComputeSize(uint32_t num_vregs) { 77*795d594fSAndroid Build Coastguard Worker return sizeof(ShadowFrame) + (sizeof(uint32_t) * num_vregs) + 78*795d594fSAndroid Build Coastguard Worker (sizeof(StackReference<mirror::Object>) * num_vregs); 79*795d594fSAndroid Build Coastguard Worker } 80*795d594fSAndroid Build Coastguard Worker 81*795d594fSAndroid Build Coastguard Worker // Create ShadowFrame in heap for deoptimization. CreateDeoptimizedFrame(uint32_t num_vregs,ArtMethod * method,uint32_t dex_pc)82*795d594fSAndroid Build Coastguard Worker static ShadowFrame* CreateDeoptimizedFrame(uint32_t num_vregs, 83*795d594fSAndroid Build Coastguard Worker ArtMethod* method, 84*795d594fSAndroid Build Coastguard Worker uint32_t dex_pc) { 85*795d594fSAndroid Build Coastguard Worker uint8_t* memory = new uint8_t[ComputeSize(num_vregs)]; 86*795d594fSAndroid Build Coastguard Worker return CreateShadowFrameImpl(num_vregs, method, dex_pc, memory); 87*795d594fSAndroid Build Coastguard Worker } 88*795d594fSAndroid Build Coastguard Worker 89*795d594fSAndroid Build Coastguard Worker // Delete a ShadowFrame allocated on the heap for deoptimization. DeleteDeoptimizedFrame(ShadowFrame * sf)90*795d594fSAndroid Build Coastguard Worker static void DeleteDeoptimizedFrame(ShadowFrame* sf) { 91*795d594fSAndroid Build Coastguard Worker sf->~ShadowFrame(); // Explicitly destruct. 92*795d594fSAndroid Build Coastguard Worker uint8_t* memory = reinterpret_cast<uint8_t*>(sf); 93*795d594fSAndroid Build Coastguard Worker delete[] memory; 94*795d594fSAndroid Build Coastguard Worker } 95*795d594fSAndroid Build Coastguard Worker 96*795d594fSAndroid Build Coastguard Worker // Create a shadow frame in a fresh alloca. This needs to be in the context of the caller. 97*795d594fSAndroid Build Coastguard Worker // Inlining doesn't work, the compiler will still undo the alloca. So this needs to be a macro. 98*795d594fSAndroid Build Coastguard Worker #define CREATE_SHADOW_FRAME(num_vregs, method, dex_pc) ({ \ 99*795d594fSAndroid Build Coastguard Worker size_t frame_size = ShadowFrame::ComputeSize(num_vregs); \ 100*795d594fSAndroid Build Coastguard Worker void* alloca_mem = alloca(frame_size); \ 101*795d594fSAndroid Build Coastguard Worker ShadowFrameAllocaUniquePtr( \ 102*795d594fSAndroid Build Coastguard Worker ShadowFrame::CreateShadowFrameImpl((num_vregs), (method), (dex_pc), (alloca_mem))); \ 103*795d594fSAndroid Build Coastguard Worker }) 104*795d594fSAndroid Build Coastguard Worker ~ShadowFrame()105*795d594fSAndroid Build Coastguard Worker ~ShadowFrame() {} 106*795d594fSAndroid Build Coastguard Worker NumberOfVRegs()107*795d594fSAndroid Build Coastguard Worker uint32_t NumberOfVRegs() const { 108*795d594fSAndroid Build Coastguard Worker return number_of_vregs_; 109*795d594fSAndroid Build Coastguard Worker } 110*795d594fSAndroid Build Coastguard Worker GetDexPC()111*795d594fSAndroid Build Coastguard Worker uint32_t GetDexPC() const { 112*795d594fSAndroid Build Coastguard Worker return (dex_pc_ptr_ == nullptr) ? dex_pc_ : dex_pc_ptr_ - dex_instructions_; 113*795d594fSAndroid Build Coastguard Worker } 114*795d594fSAndroid Build Coastguard Worker GetCachedHotnessCountdown()115*795d594fSAndroid Build Coastguard Worker int16_t GetCachedHotnessCountdown() const { 116*795d594fSAndroid Build Coastguard Worker return cached_hotness_countdown_; 117*795d594fSAndroid Build Coastguard Worker } 118*795d594fSAndroid Build Coastguard Worker SetCachedHotnessCountdown(int16_t cached_hotness_countdown)119*795d594fSAndroid Build Coastguard Worker void SetCachedHotnessCountdown(int16_t cached_hotness_countdown) { 120*795d594fSAndroid Build Coastguard Worker cached_hotness_countdown_ = cached_hotness_countdown; 121*795d594fSAndroid Build Coastguard Worker } 122*795d594fSAndroid Build Coastguard Worker GetHotnessCountdown()123*795d594fSAndroid Build Coastguard Worker int16_t GetHotnessCountdown() const { 124*795d594fSAndroid Build Coastguard Worker return hotness_countdown_; 125*795d594fSAndroid Build Coastguard Worker } 126*795d594fSAndroid Build Coastguard Worker SetHotnessCountdown(int16_t hotness_countdown)127*795d594fSAndroid Build Coastguard Worker void SetHotnessCountdown(int16_t hotness_countdown) { 128*795d594fSAndroid Build Coastguard Worker hotness_countdown_ = hotness_countdown; 129*795d594fSAndroid Build Coastguard Worker } 130*795d594fSAndroid Build Coastguard Worker SetDexPC(uint32_t dex_pc)131*795d594fSAndroid Build Coastguard Worker void SetDexPC(uint32_t dex_pc) { 132*795d594fSAndroid Build Coastguard Worker dex_pc_ = dex_pc; 133*795d594fSAndroid Build Coastguard Worker dex_pc_ptr_ = nullptr; 134*795d594fSAndroid Build Coastguard Worker } 135*795d594fSAndroid Build Coastguard Worker GetLink()136*795d594fSAndroid Build Coastguard Worker ShadowFrame* GetLink() const { 137*795d594fSAndroid Build Coastguard Worker return link_; 138*795d594fSAndroid Build Coastguard Worker } 139*795d594fSAndroid Build Coastguard Worker SetLink(ShadowFrame * frame)140*795d594fSAndroid Build Coastguard Worker void SetLink(ShadowFrame* frame) { 141*795d594fSAndroid Build Coastguard Worker DCHECK_NE(this, frame); 142*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(link_, nullptr); 143*795d594fSAndroid Build Coastguard Worker link_ = frame; 144*795d594fSAndroid Build Coastguard Worker } 145*795d594fSAndroid Build Coastguard Worker ClearLink()146*795d594fSAndroid Build Coastguard Worker void ClearLink() { 147*795d594fSAndroid Build Coastguard Worker link_ = nullptr; 148*795d594fSAndroid Build Coastguard Worker } 149*795d594fSAndroid Build Coastguard Worker GetVReg(size_t i)150*795d594fSAndroid Build Coastguard Worker int32_t GetVReg(size_t i) const { 151*795d594fSAndroid Build Coastguard Worker DCHECK_LT(i, NumberOfVRegs()); 152*795d594fSAndroid Build Coastguard Worker const uint32_t* vreg = &vregs_[i]; 153*795d594fSAndroid Build Coastguard Worker return *reinterpret_cast<const int32_t*>(vreg); 154*795d594fSAndroid Build Coastguard Worker } 155*795d594fSAndroid Build Coastguard Worker 156*795d594fSAndroid Build Coastguard Worker // Shorts are extended to Ints in VRegs. Interpreter intrinsics needs them as shorts. GetVRegShort(size_t i)157*795d594fSAndroid Build Coastguard Worker int16_t GetVRegShort(size_t i) const { 158*795d594fSAndroid Build Coastguard Worker return static_cast<int16_t>(GetVReg(i)); 159*795d594fSAndroid Build Coastguard Worker } 160*795d594fSAndroid Build Coastguard Worker GetVRegAddr(size_t i)161*795d594fSAndroid Build Coastguard Worker uint32_t* GetVRegAddr(size_t i) { 162*795d594fSAndroid Build Coastguard Worker return &vregs_[i]; 163*795d594fSAndroid Build Coastguard Worker } 164*795d594fSAndroid Build Coastguard Worker GetShadowRefAddr(size_t i)165*795d594fSAndroid Build Coastguard Worker uint32_t* GetShadowRefAddr(size_t i) { 166*795d594fSAndroid Build Coastguard Worker DCHECK_LT(i, NumberOfVRegs()); 167*795d594fSAndroid Build Coastguard Worker return &vregs_[i + NumberOfVRegs()]; 168*795d594fSAndroid Build Coastguard Worker } 169*795d594fSAndroid Build Coastguard Worker GetDexInstructions()170*795d594fSAndroid Build Coastguard Worker const uint16_t* GetDexInstructions() const { 171*795d594fSAndroid Build Coastguard Worker return dex_instructions_; 172*795d594fSAndroid Build Coastguard Worker } 173*795d594fSAndroid Build Coastguard Worker GetVRegFloat(size_t i)174*795d594fSAndroid Build Coastguard Worker float GetVRegFloat(size_t i) const { 175*795d594fSAndroid Build Coastguard Worker DCHECK_LT(i, NumberOfVRegs()); 176*795d594fSAndroid Build Coastguard Worker // NOTE: Strict-aliasing? 177*795d594fSAndroid Build Coastguard Worker const uint32_t* vreg = &vregs_[i]; 178*795d594fSAndroid Build Coastguard Worker return *reinterpret_cast<const float*>(vreg); 179*795d594fSAndroid Build Coastguard Worker } 180*795d594fSAndroid Build Coastguard Worker GetVRegLong(size_t i)181*795d594fSAndroid Build Coastguard Worker int64_t GetVRegLong(size_t i) const { 182*795d594fSAndroid Build Coastguard Worker DCHECK_LT(i + 1, NumberOfVRegs()); 183*795d594fSAndroid Build Coastguard Worker const uint32_t* vreg = &vregs_[i]; 184*795d594fSAndroid Build Coastguard Worker using unaligned_int64 __attribute__((aligned(4))) = const int64_t; 185*795d594fSAndroid Build Coastguard Worker return *reinterpret_cast<unaligned_int64*>(vreg); 186*795d594fSAndroid Build Coastguard Worker } 187*795d594fSAndroid Build Coastguard Worker GetVRegDouble(size_t i)188*795d594fSAndroid Build Coastguard Worker double GetVRegDouble(size_t i) const { 189*795d594fSAndroid Build Coastguard Worker DCHECK_LT(i + 1, NumberOfVRegs()); 190*795d594fSAndroid Build Coastguard Worker const uint32_t* vreg = &vregs_[i]; 191*795d594fSAndroid Build Coastguard Worker using unaligned_double __attribute__((aligned(4))) = const double; 192*795d594fSAndroid Build Coastguard Worker return *reinterpret_cast<unaligned_double*>(vreg); 193*795d594fSAndroid Build Coastguard Worker } 194*795d594fSAndroid Build Coastguard Worker 195*795d594fSAndroid Build Coastguard Worker // Look up the reference given its virtual register number. 196*795d594fSAndroid Build Coastguard Worker // If this returns non-null then this does not mean the vreg is currently a reference 197*795d594fSAndroid Build Coastguard Worker // on non-moving collectors. Check that the raw reg with GetVReg is equal to this if not certain. 198*795d594fSAndroid Build Coastguard Worker template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> GetVRegReference(size_t i)199*795d594fSAndroid Build Coastguard Worker mirror::Object* GetVRegReference(size_t i) const REQUIRES_SHARED(Locks::mutator_lock_) { 200*795d594fSAndroid Build Coastguard Worker DCHECK_LT(i, NumberOfVRegs()); 201*795d594fSAndroid Build Coastguard Worker mirror::Object* ref; 202*795d594fSAndroid Build Coastguard Worker ref = References()[i].AsMirrorPtr(); 203*795d594fSAndroid Build Coastguard Worker ReadBarrier::MaybeAssertToSpaceInvariant(ref); 204*795d594fSAndroid Build Coastguard Worker if (kVerifyFlags & kVerifyReads) { 205*795d594fSAndroid Build Coastguard Worker VerifyObject(ref); 206*795d594fSAndroid Build Coastguard Worker } 207*795d594fSAndroid Build Coastguard Worker return ref; 208*795d594fSAndroid Build Coastguard Worker } 209*795d594fSAndroid Build Coastguard Worker 210*795d594fSAndroid Build Coastguard Worker // Get view of vregs as range of consecutive arguments starting at i. GetVRegArgs(size_t i)211*795d594fSAndroid Build Coastguard Worker uint32_t* GetVRegArgs(size_t i) { 212*795d594fSAndroid Build Coastguard Worker return &vregs_[i]; 213*795d594fSAndroid Build Coastguard Worker } 214*795d594fSAndroid Build Coastguard Worker SetVReg(size_t i,int32_t val)215*795d594fSAndroid Build Coastguard Worker void SetVReg(size_t i, int32_t val) { 216*795d594fSAndroid Build Coastguard Worker DCHECK_LT(i, NumberOfVRegs()); 217*795d594fSAndroid Build Coastguard Worker uint32_t* vreg = &vregs_[i]; 218*795d594fSAndroid Build Coastguard Worker *reinterpret_cast<int32_t*>(vreg) = val; 219*795d594fSAndroid Build Coastguard Worker // This is needed for moving collectors since these can update the vreg references if they 220*795d594fSAndroid Build Coastguard Worker // happen to agree with references in the reference array. 221*795d594fSAndroid Build Coastguard Worker References()[i].Clear(); 222*795d594fSAndroid Build Coastguard Worker } 223*795d594fSAndroid Build Coastguard Worker SetVRegFloat(size_t i,float val)224*795d594fSAndroid Build Coastguard Worker void SetVRegFloat(size_t i, float val) { 225*795d594fSAndroid Build Coastguard Worker DCHECK_LT(i, NumberOfVRegs()); 226*795d594fSAndroid Build Coastguard Worker uint32_t* vreg = &vregs_[i]; 227*795d594fSAndroid Build Coastguard Worker *reinterpret_cast<float*>(vreg) = val; 228*795d594fSAndroid Build Coastguard Worker // This is needed for moving collectors since these can update the vreg references if they 229*795d594fSAndroid Build Coastguard Worker // happen to agree with references in the reference array. 230*795d594fSAndroid Build Coastguard Worker References()[i].Clear(); 231*795d594fSAndroid Build Coastguard Worker } 232*795d594fSAndroid Build Coastguard Worker SetVRegLong(size_t i,int64_t val)233*795d594fSAndroid Build Coastguard Worker void SetVRegLong(size_t i, int64_t val) { 234*795d594fSAndroid Build Coastguard Worker DCHECK_LT(i + 1, NumberOfVRegs()); 235*795d594fSAndroid Build Coastguard Worker uint32_t* vreg = &vregs_[i]; 236*795d594fSAndroid Build Coastguard Worker using unaligned_int64 __attribute__((aligned(4))) = int64_t; 237*795d594fSAndroid Build Coastguard Worker *reinterpret_cast<unaligned_int64*>(vreg) = val; 238*795d594fSAndroid Build Coastguard Worker // This is needed for moving collectors since these can update the vreg references if they 239*795d594fSAndroid Build Coastguard Worker // happen to agree with references in the reference array. 240*795d594fSAndroid Build Coastguard Worker References()[i].Clear(); 241*795d594fSAndroid Build Coastguard Worker References()[i + 1].Clear(); 242*795d594fSAndroid Build Coastguard Worker } 243*795d594fSAndroid Build Coastguard Worker SetVRegDouble(size_t i,double val)244*795d594fSAndroid Build Coastguard Worker void SetVRegDouble(size_t i, double val) { 245*795d594fSAndroid Build Coastguard Worker DCHECK_LT(i + 1, NumberOfVRegs()); 246*795d594fSAndroid Build Coastguard Worker uint32_t* vreg = &vregs_[i]; 247*795d594fSAndroid Build Coastguard Worker using unaligned_double __attribute__((aligned(4))) = double; 248*795d594fSAndroid Build Coastguard Worker *reinterpret_cast<unaligned_double*>(vreg) = val; 249*795d594fSAndroid Build Coastguard Worker // This is needed for moving collectors since these can update the vreg references if they 250*795d594fSAndroid Build Coastguard Worker // happen to agree with references in the reference array. 251*795d594fSAndroid Build Coastguard Worker References()[i].Clear(); 252*795d594fSAndroid Build Coastguard Worker References()[i + 1].Clear(); 253*795d594fSAndroid Build Coastguard Worker } 254*795d594fSAndroid Build Coastguard Worker 255*795d594fSAndroid Build Coastguard Worker template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> 256*795d594fSAndroid Build Coastguard Worker void SetVRegReference(size_t i, ObjPtr<mirror::Object> val) 257*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 258*795d594fSAndroid Build Coastguard Worker SetMethod(ArtMethod * method)259*795d594fSAndroid Build Coastguard Worker void SetMethod(ArtMethod* method) REQUIRES(Locks::mutator_lock_) { 260*795d594fSAndroid Build Coastguard Worker DCHECK(method != nullptr); 261*795d594fSAndroid Build Coastguard Worker DCHECK(method_ != nullptr); 262*795d594fSAndroid Build Coastguard Worker method_ = method; 263*795d594fSAndroid Build Coastguard Worker } 264*795d594fSAndroid Build Coastguard Worker GetMethod()265*795d594fSAndroid Build Coastguard Worker ArtMethod* GetMethod() const REQUIRES_SHARED(Locks::mutator_lock_) { 266*795d594fSAndroid Build Coastguard Worker DCHECK(method_ != nullptr); 267*795d594fSAndroid Build Coastguard Worker return method_; 268*795d594fSAndroid Build Coastguard Worker } 269*795d594fSAndroid Build Coastguard Worker 270*795d594fSAndroid Build Coastguard Worker mirror::Object* GetThisObject() const REQUIRES_SHARED(Locks::mutator_lock_); 271*795d594fSAndroid Build Coastguard Worker 272*795d594fSAndroid Build Coastguard Worker mirror::Object* GetThisObject(uint16_t num_ins) const REQUIRES_SHARED(Locks::mutator_lock_); 273*795d594fSAndroid Build Coastguard Worker Contains(StackReference<mirror::Object> * shadow_frame_entry_obj)274*795d594fSAndroid Build Coastguard Worker bool Contains(StackReference<mirror::Object>* shadow_frame_entry_obj) const { 275*795d594fSAndroid Build Coastguard Worker return ((&References()[0] <= shadow_frame_entry_obj) && 276*795d594fSAndroid Build Coastguard Worker (shadow_frame_entry_obj <= (&References()[NumberOfVRegs() - 1]))); 277*795d594fSAndroid Build Coastguard Worker } 278*795d594fSAndroid Build Coastguard Worker GetLockCountData()279*795d594fSAndroid Build Coastguard Worker LockCountData& GetLockCountData() { 280*795d594fSAndroid Build Coastguard Worker return lock_count_data_; 281*795d594fSAndroid Build Coastguard Worker } 282*795d594fSAndroid Build Coastguard Worker LockCountDataOffset()283*795d594fSAndroid Build Coastguard Worker static constexpr size_t LockCountDataOffset() { 284*795d594fSAndroid Build Coastguard Worker return OFFSETOF_MEMBER(ShadowFrame, lock_count_data_); 285*795d594fSAndroid Build Coastguard Worker } 286*795d594fSAndroid Build Coastguard Worker LinkOffset()287*795d594fSAndroid Build Coastguard Worker static constexpr size_t LinkOffset() { 288*795d594fSAndroid Build Coastguard Worker return OFFSETOF_MEMBER(ShadowFrame, link_); 289*795d594fSAndroid Build Coastguard Worker } 290*795d594fSAndroid Build Coastguard Worker MethodOffset()291*795d594fSAndroid Build Coastguard Worker static constexpr size_t MethodOffset() { 292*795d594fSAndroid Build Coastguard Worker return OFFSETOF_MEMBER(ShadowFrame, method_); 293*795d594fSAndroid Build Coastguard Worker } 294*795d594fSAndroid Build Coastguard Worker DexPCOffset()295*795d594fSAndroid Build Coastguard Worker static constexpr size_t DexPCOffset() { 296*795d594fSAndroid Build Coastguard Worker return OFFSETOF_MEMBER(ShadowFrame, dex_pc_); 297*795d594fSAndroid Build Coastguard Worker } 298*795d594fSAndroid Build Coastguard Worker NumberOfVRegsOffset()299*795d594fSAndroid Build Coastguard Worker static constexpr size_t NumberOfVRegsOffset() { 300*795d594fSAndroid Build Coastguard Worker return OFFSETOF_MEMBER(ShadowFrame, number_of_vregs_); 301*795d594fSAndroid Build Coastguard Worker } 302*795d594fSAndroid Build Coastguard Worker VRegsOffset()303*795d594fSAndroid Build Coastguard Worker static constexpr size_t VRegsOffset() { 304*795d594fSAndroid Build Coastguard Worker return OFFSETOF_MEMBER(ShadowFrame, vregs_); 305*795d594fSAndroid Build Coastguard Worker } 306*795d594fSAndroid Build Coastguard Worker DexPCPtrOffset()307*795d594fSAndroid Build Coastguard Worker static constexpr size_t DexPCPtrOffset() { 308*795d594fSAndroid Build Coastguard Worker return OFFSETOF_MEMBER(ShadowFrame, dex_pc_ptr_); 309*795d594fSAndroid Build Coastguard Worker } 310*795d594fSAndroid Build Coastguard Worker DexInstructionsOffset()311*795d594fSAndroid Build Coastguard Worker static constexpr size_t DexInstructionsOffset() { 312*795d594fSAndroid Build Coastguard Worker return OFFSETOF_MEMBER(ShadowFrame, dex_instructions_); 313*795d594fSAndroid Build Coastguard Worker } 314*795d594fSAndroid Build Coastguard Worker CachedHotnessCountdownOffset()315*795d594fSAndroid Build Coastguard Worker static constexpr size_t CachedHotnessCountdownOffset() { 316*795d594fSAndroid Build Coastguard Worker return OFFSETOF_MEMBER(ShadowFrame, cached_hotness_countdown_); 317*795d594fSAndroid Build Coastguard Worker } 318*795d594fSAndroid Build Coastguard Worker HotnessCountdownOffset()319*795d594fSAndroid Build Coastguard Worker static constexpr size_t HotnessCountdownOffset() { 320*795d594fSAndroid Build Coastguard Worker return OFFSETOF_MEMBER(ShadowFrame, hotness_countdown_); 321*795d594fSAndroid Build Coastguard Worker } 322*795d594fSAndroid Build Coastguard Worker 323*795d594fSAndroid Build Coastguard Worker // Create ShadowFrame for interpreter using provided memory. CreateShadowFrameImpl(uint32_t num_vregs,ArtMethod * method,uint32_t dex_pc,void * memory)324*795d594fSAndroid Build Coastguard Worker static ShadowFrame* CreateShadowFrameImpl(uint32_t num_vregs, 325*795d594fSAndroid Build Coastguard Worker ArtMethod* method, 326*795d594fSAndroid Build Coastguard Worker uint32_t dex_pc, 327*795d594fSAndroid Build Coastguard Worker void* memory) { 328*795d594fSAndroid Build Coastguard Worker return new (memory) ShadowFrame(num_vregs, method, dex_pc); 329*795d594fSAndroid Build Coastguard Worker } 330*795d594fSAndroid Build Coastguard Worker GetDexPCPtr()331*795d594fSAndroid Build Coastguard Worker const uint16_t* GetDexPCPtr() { 332*795d594fSAndroid Build Coastguard Worker return dex_pc_ptr_; 333*795d594fSAndroid Build Coastguard Worker } 334*795d594fSAndroid Build Coastguard Worker SetDexPCPtr(uint16_t * dex_pc_ptr)335*795d594fSAndroid Build Coastguard Worker void SetDexPCPtr(uint16_t* dex_pc_ptr) { 336*795d594fSAndroid Build Coastguard Worker dex_pc_ptr_ = dex_pc_ptr; 337*795d594fSAndroid Build Coastguard Worker } 338*795d594fSAndroid Build Coastguard Worker NeedsNotifyPop()339*795d594fSAndroid Build Coastguard Worker bool NeedsNotifyPop() const { 340*795d594fSAndroid Build Coastguard Worker return GetFrameFlag(FrameFlags::kNotifyFramePop); 341*795d594fSAndroid Build Coastguard Worker } 342*795d594fSAndroid Build Coastguard Worker SetNotifyPop(bool notify)343*795d594fSAndroid Build Coastguard Worker void SetNotifyPop(bool notify) { 344*795d594fSAndroid Build Coastguard Worker UpdateFrameFlag(notify, FrameFlags::kNotifyFramePop); 345*795d594fSAndroid Build Coastguard Worker } 346*795d594fSAndroid Build Coastguard Worker GetForcePopFrame()347*795d594fSAndroid Build Coastguard Worker bool GetForcePopFrame() const { 348*795d594fSAndroid Build Coastguard Worker return GetFrameFlag(FrameFlags::kForcePopFrame); 349*795d594fSAndroid Build Coastguard Worker } 350*795d594fSAndroid Build Coastguard Worker SetForcePopFrame(bool enable)351*795d594fSAndroid Build Coastguard Worker void SetForcePopFrame(bool enable) { 352*795d594fSAndroid Build Coastguard Worker UpdateFrameFlag(enable, FrameFlags::kForcePopFrame); 353*795d594fSAndroid Build Coastguard Worker } 354*795d594fSAndroid Build Coastguard Worker GetForceRetryInstruction()355*795d594fSAndroid Build Coastguard Worker bool GetForceRetryInstruction() const { 356*795d594fSAndroid Build Coastguard Worker return GetFrameFlag(FrameFlags::kForceRetryInst); 357*795d594fSAndroid Build Coastguard Worker } 358*795d594fSAndroid Build Coastguard Worker SetForceRetryInstruction(bool enable)359*795d594fSAndroid Build Coastguard Worker void SetForceRetryInstruction(bool enable) { 360*795d594fSAndroid Build Coastguard Worker UpdateFrameFlag(enable, FrameFlags::kForceRetryInst); 361*795d594fSAndroid Build Coastguard Worker } 362*795d594fSAndroid Build Coastguard Worker GetSkipMethodExitEvents()363*795d594fSAndroid Build Coastguard Worker bool GetSkipMethodExitEvents() const { 364*795d594fSAndroid Build Coastguard Worker return GetFrameFlag(FrameFlags::kSkipMethodExitEvents); 365*795d594fSAndroid Build Coastguard Worker } 366*795d594fSAndroid Build Coastguard Worker SetSkipMethodExitEvents(bool enable)367*795d594fSAndroid Build Coastguard Worker void SetSkipMethodExitEvents(bool enable) { 368*795d594fSAndroid Build Coastguard Worker UpdateFrameFlag(enable, FrameFlags::kSkipMethodExitEvents); 369*795d594fSAndroid Build Coastguard Worker } 370*795d594fSAndroid Build Coastguard Worker GetSkipNextExceptionEvent()371*795d594fSAndroid Build Coastguard Worker bool GetSkipNextExceptionEvent() const { 372*795d594fSAndroid Build Coastguard Worker return GetFrameFlag(FrameFlags::kSkipNextExceptionEvent); 373*795d594fSAndroid Build Coastguard Worker } 374*795d594fSAndroid Build Coastguard Worker SetSkipNextExceptionEvent(bool enable)375*795d594fSAndroid Build Coastguard Worker void SetSkipNextExceptionEvent(bool enable) { 376*795d594fSAndroid Build Coastguard Worker UpdateFrameFlag(enable, FrameFlags::kSkipNextExceptionEvent); 377*795d594fSAndroid Build Coastguard Worker } 378*795d594fSAndroid Build Coastguard Worker GetNotifyDexPcMoveEvents()379*795d594fSAndroid Build Coastguard Worker bool GetNotifyDexPcMoveEvents() const { 380*795d594fSAndroid Build Coastguard Worker return GetFrameFlag(FrameFlags::kNotifyDexPcMoveEvents); 381*795d594fSAndroid Build Coastguard Worker } 382*795d594fSAndroid Build Coastguard Worker SetNotifyDexPcMoveEvents(bool enable)383*795d594fSAndroid Build Coastguard Worker void SetNotifyDexPcMoveEvents(bool enable) { 384*795d594fSAndroid Build Coastguard Worker UpdateFrameFlag(enable, FrameFlags::kNotifyDexPcMoveEvents); 385*795d594fSAndroid Build Coastguard Worker } 386*795d594fSAndroid Build Coastguard Worker GetNotifyExceptionHandledEvent()387*795d594fSAndroid Build Coastguard Worker bool GetNotifyExceptionHandledEvent() const { 388*795d594fSAndroid Build Coastguard Worker return GetFrameFlag(FrameFlags::kNotifyExceptionHandledEvent); 389*795d594fSAndroid Build Coastguard Worker } 390*795d594fSAndroid Build Coastguard Worker SetNotifyExceptionHandledEvent(bool enable)391*795d594fSAndroid Build Coastguard Worker void SetNotifyExceptionHandledEvent(bool enable) { 392*795d594fSAndroid Build Coastguard Worker UpdateFrameFlag(enable, FrameFlags::kNotifyExceptionHandledEvent); 393*795d594fSAndroid Build Coastguard Worker } 394*795d594fSAndroid Build Coastguard Worker CheckConsistentVRegs()395*795d594fSAndroid Build Coastguard Worker void CheckConsistentVRegs() const { 396*795d594fSAndroid Build Coastguard Worker if (kIsDebugBuild) { 397*795d594fSAndroid Build Coastguard Worker // A shadow frame visible to GC requires the following rule: for a given vreg, 398*795d594fSAndroid Build Coastguard Worker // its vreg reference equivalent should be the same, or null. 399*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < NumberOfVRegs(); ++i) { 400*795d594fSAndroid Build Coastguard Worker int32_t reference_value = References()[i].AsVRegValue(); 401*795d594fSAndroid Build Coastguard Worker CHECK((GetVReg(i) == reference_value) || (reference_value == 0)); 402*795d594fSAndroid Build Coastguard Worker } 403*795d594fSAndroid Build Coastguard Worker } 404*795d594fSAndroid Build Coastguard Worker } 405*795d594fSAndroid Build Coastguard Worker 406*795d594fSAndroid Build Coastguard Worker private: ShadowFrame(uint32_t num_vregs,ArtMethod * method,uint32_t dex_pc)407*795d594fSAndroid Build Coastguard Worker ShadowFrame(uint32_t num_vregs, ArtMethod* method, uint32_t dex_pc) 408*795d594fSAndroid Build Coastguard Worker : link_(nullptr), 409*795d594fSAndroid Build Coastguard Worker method_(method), 410*795d594fSAndroid Build Coastguard Worker dex_pc_ptr_(nullptr), 411*795d594fSAndroid Build Coastguard Worker dex_instructions_(nullptr), 412*795d594fSAndroid Build Coastguard Worker number_of_vregs_(num_vregs), 413*795d594fSAndroid Build Coastguard Worker dex_pc_(dex_pc), 414*795d594fSAndroid Build Coastguard Worker cached_hotness_countdown_(0), 415*795d594fSAndroid Build Coastguard Worker hotness_countdown_(0), 416*795d594fSAndroid Build Coastguard Worker frame_flags_(0) { 417*795d594fSAndroid Build Coastguard Worker memset(vregs_, 0, num_vregs * (sizeof(uint32_t) + sizeof(StackReference<mirror::Object>))); 418*795d594fSAndroid Build Coastguard Worker } 419*795d594fSAndroid Build Coastguard Worker UpdateFrameFlag(bool enable,FrameFlags flag)420*795d594fSAndroid Build Coastguard Worker void UpdateFrameFlag(bool enable, FrameFlags flag) { 421*795d594fSAndroid Build Coastguard Worker if (enable) { 422*795d594fSAndroid Build Coastguard Worker frame_flags_ |= static_cast<uint32_t>(flag); 423*795d594fSAndroid Build Coastguard Worker } else { 424*795d594fSAndroid Build Coastguard Worker frame_flags_ &= ~static_cast<uint32_t>(flag); 425*795d594fSAndroid Build Coastguard Worker } 426*795d594fSAndroid Build Coastguard Worker } 427*795d594fSAndroid Build Coastguard Worker GetFrameFlag(FrameFlags flag)428*795d594fSAndroid Build Coastguard Worker bool GetFrameFlag(FrameFlags flag) const { 429*795d594fSAndroid Build Coastguard Worker return (frame_flags_ & static_cast<uint32_t>(flag)) != 0; 430*795d594fSAndroid Build Coastguard Worker } 431*795d594fSAndroid Build Coastguard Worker References()432*795d594fSAndroid Build Coastguard Worker const StackReference<mirror::Object>* References() const { 433*795d594fSAndroid Build Coastguard Worker const uint32_t* vreg_end = &vregs_[NumberOfVRegs()]; 434*795d594fSAndroid Build Coastguard Worker return reinterpret_cast<const StackReference<mirror::Object>*>(vreg_end); 435*795d594fSAndroid Build Coastguard Worker } 436*795d594fSAndroid Build Coastguard Worker References()437*795d594fSAndroid Build Coastguard Worker StackReference<mirror::Object>* References() { 438*795d594fSAndroid Build Coastguard Worker return const_cast<StackReference<mirror::Object>*>( 439*795d594fSAndroid Build Coastguard Worker const_cast<const ShadowFrame*>(this)->References()); 440*795d594fSAndroid Build Coastguard Worker } 441*795d594fSAndroid Build Coastguard Worker 442*795d594fSAndroid Build Coastguard Worker // Link to previous shadow frame or null. 443*795d594fSAndroid Build Coastguard Worker ShadowFrame* link_; 444*795d594fSAndroid Build Coastguard Worker ArtMethod* method_; 445*795d594fSAndroid Build Coastguard Worker const uint16_t* dex_pc_ptr_; 446*795d594fSAndroid Build Coastguard Worker // Dex instruction base of the code item. 447*795d594fSAndroid Build Coastguard Worker const uint16_t* dex_instructions_; 448*795d594fSAndroid Build Coastguard Worker LockCountData lock_count_data_; // This may contain GC roots when lock counting is active. 449*795d594fSAndroid Build Coastguard Worker const uint32_t number_of_vregs_; 450*795d594fSAndroid Build Coastguard Worker uint32_t dex_pc_; 451*795d594fSAndroid Build Coastguard Worker int16_t cached_hotness_countdown_; 452*795d594fSAndroid Build Coastguard Worker int16_t hotness_countdown_; 453*795d594fSAndroid Build Coastguard Worker 454*795d594fSAndroid Build Coastguard Worker // This is a set of ShadowFrame::FrameFlags which denote special states this frame is in. 455*795d594fSAndroid Build Coastguard Worker // NB alignment requires that this field takes 4 bytes no matter its size. Only 7 bits are 456*795d594fSAndroid Build Coastguard Worker // currently used. 457*795d594fSAndroid Build Coastguard Worker uint32_t frame_flags_; 458*795d594fSAndroid Build Coastguard Worker 459*795d594fSAndroid Build Coastguard Worker // This is a two-part array: 460*795d594fSAndroid Build Coastguard Worker // - [0..number_of_vregs) holds the raw virtual registers, and each element here is always 4 461*795d594fSAndroid Build Coastguard Worker // bytes. 462*795d594fSAndroid Build Coastguard Worker // - [number_of_vregs..number_of_vregs*2) holds only reference registers. Each element here is 463*795d594fSAndroid Build Coastguard Worker // ptr-sized. 464*795d594fSAndroid Build Coastguard Worker // In other words when a primitive is stored in vX, the second (reference) part of the array will 465*795d594fSAndroid Build Coastguard Worker // be null. When a reference is stored in vX, the second (reference) part of the array will be a 466*795d594fSAndroid Build Coastguard Worker // copy of vX. 467*795d594fSAndroid Build Coastguard Worker uint32_t vregs_[0]; 468*795d594fSAndroid Build Coastguard Worker 469*795d594fSAndroid Build Coastguard Worker DISALLOW_IMPLICIT_CONSTRUCTORS(ShadowFrame); 470*795d594fSAndroid Build Coastguard Worker }; 471*795d594fSAndroid Build Coastguard Worker 472*795d594fSAndroid Build Coastguard Worker struct ShadowFrameDeleter { operatorShadowFrameDeleter473*795d594fSAndroid Build Coastguard Worker inline void operator()(ShadowFrame* frame) { 474*795d594fSAndroid Build Coastguard Worker if (frame != nullptr) { 475*795d594fSAndroid Build Coastguard Worker frame->~ShadowFrame(); 476*795d594fSAndroid Build Coastguard Worker } 477*795d594fSAndroid Build Coastguard Worker } 478*795d594fSAndroid Build Coastguard Worker }; 479*795d594fSAndroid Build Coastguard Worker 480*795d594fSAndroid Build Coastguard Worker } // namespace art 481*795d594fSAndroid Build Coastguard Worker 482*795d594fSAndroid Build Coastguard Worker #endif // ART_RUNTIME_INTERPRETER_SHADOW_FRAME_H_ 483