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