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_STACK_H_ 18 #define ART_RUNTIME_STACK_H_ 19 20 #include <stdint.h> 21 #include <string> 22 23 #include "dex_file.h" 24 #include "instruction_set.h" 25 #include "mirror/object_reference.h" 26 #include "throw_location.h" 27 #include "utils.h" 28 #include "verify_object.h" 29 30 namespace art { 31 32 namespace mirror { 33 class ArtMethod; 34 class Object; 35 } // namespace mirror 36 37 class Context; 38 class ShadowFrame; 39 class HandleScope; 40 class ScopedObjectAccess; 41 class Thread; 42 43 // The kind of vreg being accessed in calls to Set/GetVReg. 44 enum VRegKind { 45 kReferenceVReg, 46 kIntVReg, 47 kFloatVReg, 48 kLongLoVReg, 49 kLongHiVReg, 50 kDoubleLoVReg, 51 kDoubleHiVReg, 52 kConstant, 53 kImpreciseConstant, 54 kUndefined, 55 }; 56 57 /** 58 * @brief Represents the virtual register numbers that denote special meaning. 59 * @details This is used to make some virtual register numbers to have specific 60 * semantic meaning. This is done so that the compiler can treat all virtual 61 * registers the same way and only special case when needed. For example, 62 * calculating SSA does not care whether a virtual register is a normal one or 63 * a compiler temporary, so it can deal with them in a consistent manner. But, 64 * for example if backend cares about temporaries because it has custom spill 65 * location, then it can special case them only then. 66 */ 67 enum VRegBaseRegNum : int { 68 /** 69 * @brief Virtual registers originating from dex have number >= 0. 70 */ 71 kVRegBaseReg = 0, 72 73 /** 74 * @brief Invalid virtual register number. 75 */ 76 kVRegInvalid = -1, 77 78 /** 79 * @brief Used to denote the base register for compiler temporaries. 80 * @details Compiler temporaries are virtual registers not originating 81 * from dex but that are created by compiler. All virtual register numbers 82 * that are <= kVRegTempBaseReg are categorized as compiler temporaries. 83 */ 84 kVRegTempBaseReg = -2, 85 86 /** 87 * @brief Base register of temporary that holds the method pointer. 88 * @details This is a special compiler temporary because it has a specific 89 * location on stack. 90 */ 91 kVRegMethodPtrBaseReg = kVRegTempBaseReg, 92 93 /** 94 * @brief Base register of non-special compiler temporary. 95 * @details A non-special compiler temporary is one whose spill location 96 * is flexible. 97 */ 98 kVRegNonSpecialTempBaseReg = -3, 99 }; 100 101 // A reference from the shadow stack to a MirrorType object within the Java heap. 102 template<class MirrorType> 103 class MANAGED StackReference : public mirror::ObjectReference<false, MirrorType> { 104 public: SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)105 StackReference<MirrorType>() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) 106 : mirror::ObjectReference<false, MirrorType>(nullptr) {} 107 FromMirrorPtr(MirrorType * p)108 static StackReference<MirrorType> FromMirrorPtr(MirrorType* p) 109 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 110 return StackReference<MirrorType>(p); 111 } 112 113 private: SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)114 StackReference<MirrorType>(MirrorType* p) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) 115 : mirror::ObjectReference<false, MirrorType>(p) {} 116 }; 117 118 // ShadowFrame has 3 possible layouts: 119 // - portable - a unified array of VRegs and references. Precise references need GC maps. 120 // - interpreter - separate VRegs and reference arrays. References are in the reference array. 121 // - JNI - just VRegs, but where every VReg holds a reference. 122 class ShadowFrame { 123 public: 124 // Compute size of ShadowFrame in bytes assuming it has a reference array. ComputeSize(uint32_t num_vregs)125 static size_t ComputeSize(uint32_t num_vregs) { 126 return sizeof(ShadowFrame) + (sizeof(uint32_t) * num_vregs) + 127 (sizeof(StackReference<mirror::Object>) * num_vregs); 128 } 129 130 // Create ShadowFrame in heap for deoptimization. Create(uint32_t num_vregs,ShadowFrame * link,mirror::ArtMethod * method,uint32_t dex_pc)131 static ShadowFrame* Create(uint32_t num_vregs, ShadowFrame* link, 132 mirror::ArtMethod* method, uint32_t dex_pc) { 133 uint8_t* memory = new uint8_t[ComputeSize(num_vregs)]; 134 return Create(num_vregs, link, method, dex_pc, memory); 135 } 136 137 // Create ShadowFrame for interpreter using provided memory. Create(uint32_t num_vregs,ShadowFrame * link,mirror::ArtMethod * method,uint32_t dex_pc,void * memory)138 static ShadowFrame* Create(uint32_t num_vregs, ShadowFrame* link, 139 mirror::ArtMethod* method, uint32_t dex_pc, void* memory) { 140 ShadowFrame* sf = new (memory) ShadowFrame(num_vregs, link, method, dex_pc, true); 141 return sf; 142 } ~ShadowFrame()143 ~ShadowFrame() {} 144 HasReferenceArray()145 bool HasReferenceArray() const { 146 #if defined(ART_USE_PORTABLE_COMPILER) 147 return (number_of_vregs_ & kHasReferenceArray) != 0; 148 #else 149 return true; 150 #endif 151 } 152 NumberOfVRegs()153 uint32_t NumberOfVRegs() const { 154 #if defined(ART_USE_PORTABLE_COMPILER) 155 return number_of_vregs_ & ~kHasReferenceArray; 156 #else 157 return number_of_vregs_; 158 #endif 159 } 160 SetNumberOfVRegs(uint32_t number_of_vregs)161 void SetNumberOfVRegs(uint32_t number_of_vregs) { 162 #if defined(ART_USE_PORTABLE_COMPILER) 163 number_of_vregs_ = number_of_vregs | (number_of_vregs_ & kHasReferenceArray); 164 #else 165 UNUSED(number_of_vregs); 166 UNIMPLEMENTED(FATAL) << "Should only be called when portable is enabled"; 167 #endif 168 } 169 GetDexPC()170 uint32_t GetDexPC() const { 171 return dex_pc_; 172 } 173 SetDexPC(uint32_t dex_pc)174 void SetDexPC(uint32_t dex_pc) { 175 dex_pc_ = dex_pc; 176 } 177 GetLink()178 ShadowFrame* GetLink() const { 179 return link_; 180 } 181 SetLink(ShadowFrame * frame)182 void SetLink(ShadowFrame* frame) { 183 DCHECK_NE(this, frame); 184 link_ = frame; 185 } 186 GetVReg(size_t i)187 int32_t GetVReg(size_t i) const { 188 DCHECK_LT(i, NumberOfVRegs()); 189 const uint32_t* vreg = &vregs_[i]; 190 return *reinterpret_cast<const int32_t*>(vreg); 191 } 192 GetVRegFloat(size_t i)193 float GetVRegFloat(size_t i) const { 194 DCHECK_LT(i, NumberOfVRegs()); 195 // NOTE: Strict-aliasing? 196 const uint32_t* vreg = &vregs_[i]; 197 return *reinterpret_cast<const float*>(vreg); 198 } 199 GetVRegLong(size_t i)200 int64_t GetVRegLong(size_t i) const { 201 DCHECK_LT(i, NumberOfVRegs()); 202 const uint32_t* vreg = &vregs_[i]; 203 // Alignment attribute required for GCC 4.8 204 typedef const int64_t unaligned_int64 __attribute__ ((aligned (4))); 205 return *reinterpret_cast<unaligned_int64*>(vreg); 206 } 207 GetVRegDouble(size_t i)208 double GetVRegDouble(size_t i) const { 209 DCHECK_LT(i, NumberOfVRegs()); 210 const uint32_t* vreg = &vregs_[i]; 211 // Alignment attribute required for GCC 4.8 212 typedef const double unaligned_double __attribute__ ((aligned (4))); 213 return *reinterpret_cast<unaligned_double*>(vreg); 214 } 215 216 template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> GetVRegReference(size_t i)217 mirror::Object* GetVRegReference(size_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 218 DCHECK_LT(i, NumberOfVRegs()); 219 mirror::Object* ref; 220 if (HasReferenceArray()) { 221 ref = References()[i].AsMirrorPtr(); 222 } else { 223 const uint32_t* vreg_ptr = &vregs_[i]; 224 ref = reinterpret_cast<const StackReference<mirror::Object>*>(vreg_ptr)->AsMirrorPtr(); 225 } 226 if (kVerifyFlags & kVerifyReads) { 227 VerifyObject(ref); 228 } 229 return ref; 230 } 231 232 // Get view of vregs as range of consecutive arguments starting at i. GetVRegArgs(size_t i)233 uint32_t* GetVRegArgs(size_t i) { 234 return &vregs_[i]; 235 } 236 SetVReg(size_t i,int32_t val)237 void SetVReg(size_t i, int32_t val) { 238 DCHECK_LT(i, NumberOfVRegs()); 239 uint32_t* vreg = &vregs_[i]; 240 *reinterpret_cast<int32_t*>(vreg) = val; 241 // This is needed for moving collectors since these can update the vreg references if they 242 // happen to agree with references in the reference array. 243 if (kMovingCollector && HasReferenceArray()) { 244 References()[i].Clear(); 245 } 246 } 247 SetVRegFloat(size_t i,float val)248 void SetVRegFloat(size_t i, float val) { 249 DCHECK_LT(i, NumberOfVRegs()); 250 uint32_t* vreg = &vregs_[i]; 251 *reinterpret_cast<float*>(vreg) = val; 252 // This is needed for moving collectors since these can update the vreg references if they 253 // happen to agree with references in the reference array. 254 if (kMovingCollector && HasReferenceArray()) { 255 References()[i].Clear(); 256 } 257 } 258 SetVRegLong(size_t i,int64_t val)259 void SetVRegLong(size_t i, int64_t val) { 260 DCHECK_LT(i, NumberOfVRegs()); 261 uint32_t* vreg = &vregs_[i]; 262 // Alignment attribute required for GCC 4.8 263 typedef int64_t unaligned_int64 __attribute__ ((aligned (4))); 264 *reinterpret_cast<unaligned_int64*>(vreg) = val; 265 // This is needed for moving collectors since these can update the vreg references if they 266 // happen to agree with references in the reference array. 267 if (kMovingCollector && HasReferenceArray()) { 268 References()[i].Clear(); 269 References()[i + 1].Clear(); 270 } 271 } 272 SetVRegDouble(size_t i,double val)273 void SetVRegDouble(size_t i, double val) { 274 DCHECK_LT(i, NumberOfVRegs()); 275 uint32_t* vreg = &vregs_[i]; 276 // Alignment attribute required for GCC 4.8 277 typedef double unaligned_double __attribute__ ((aligned (4))); 278 *reinterpret_cast<unaligned_double*>(vreg) = val; 279 // This is needed for moving collectors since these can update the vreg references if they 280 // happen to agree with references in the reference array. 281 if (kMovingCollector && HasReferenceArray()) { 282 References()[i].Clear(); 283 References()[i + 1].Clear(); 284 } 285 } 286 287 template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> SetVRegReference(size_t i,mirror::Object * val)288 void SetVRegReference(size_t i, mirror::Object* val) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 289 DCHECK_LT(i, NumberOfVRegs()); 290 if (kVerifyFlags & kVerifyWrites) { 291 VerifyObject(val); 292 } 293 uint32_t* vreg = &vregs_[i]; 294 reinterpret_cast<StackReference<mirror::Object>*>(vreg)->Assign(val); 295 if (HasReferenceArray()) { 296 References()[i].Assign(val); 297 } 298 } 299 GetMethod()300 mirror::ArtMethod* GetMethod() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 301 DCHECK(method_ != nullptr); 302 return method_; 303 } 304 GetMethodAddress()305 mirror::ArtMethod** GetMethodAddress() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 306 DCHECK(method_ != nullptr); 307 return &method_; 308 } 309 310 mirror::Object* GetThisObject() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 311 312 mirror::Object* GetThisObject(uint16_t num_ins) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 313 314 ThrowLocation GetCurrentLocationForThrow() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 315 SetMethod(mirror::ArtMethod * method)316 void SetMethod(mirror::ArtMethod* method) { 317 #if defined(ART_USE_PORTABLE_COMPILER) 318 DCHECK(method != nullptr); 319 method_ = method; 320 #else 321 UNUSED(method); 322 UNIMPLEMENTED(FATAL) << "Should only be called when portable is enabled"; 323 #endif 324 } 325 Contains(StackReference<mirror::Object> * shadow_frame_entry_obj)326 bool Contains(StackReference<mirror::Object>* shadow_frame_entry_obj) const { 327 if (HasReferenceArray()) { 328 return ((&References()[0] <= shadow_frame_entry_obj) && 329 (shadow_frame_entry_obj <= (&References()[NumberOfVRegs() - 1]))); 330 } else { 331 uint32_t* shadow_frame_entry = reinterpret_cast<uint32_t*>(shadow_frame_entry_obj); 332 return ((&vregs_[0] <= shadow_frame_entry) && 333 (shadow_frame_entry <= (&vregs_[NumberOfVRegs() - 1]))); 334 } 335 } 336 LinkOffset()337 static size_t LinkOffset() { 338 return OFFSETOF_MEMBER(ShadowFrame, link_); 339 } 340 MethodOffset()341 static size_t MethodOffset() { 342 return OFFSETOF_MEMBER(ShadowFrame, method_); 343 } 344 DexPCOffset()345 static size_t DexPCOffset() { 346 return OFFSETOF_MEMBER(ShadowFrame, dex_pc_); 347 } 348 NumberOfVRegsOffset()349 static size_t NumberOfVRegsOffset() { 350 return OFFSETOF_MEMBER(ShadowFrame, number_of_vregs_); 351 } 352 VRegsOffset()353 static size_t VRegsOffset() { 354 return OFFSETOF_MEMBER(ShadowFrame, vregs_); 355 } 356 357 private: ShadowFrame(uint32_t num_vregs,ShadowFrame * link,mirror::ArtMethod * method,uint32_t dex_pc,bool has_reference_array)358 ShadowFrame(uint32_t num_vregs, ShadowFrame* link, mirror::ArtMethod* method, 359 uint32_t dex_pc, bool has_reference_array) 360 : number_of_vregs_(num_vregs), link_(link), method_(method), dex_pc_(dex_pc) { 361 if (has_reference_array) { 362 #if defined(ART_USE_PORTABLE_COMPILER) 363 CHECK_LT(num_vregs, static_cast<uint32_t>(kHasReferenceArray)); 364 number_of_vregs_ |= kHasReferenceArray; 365 #endif 366 memset(vregs_, 0, num_vregs * (sizeof(uint32_t) + sizeof(StackReference<mirror::Object>))); 367 } else { 368 memset(vregs_, 0, num_vregs * sizeof(uint32_t)); 369 } 370 } 371 References()372 const StackReference<mirror::Object>* References() const { 373 DCHECK(HasReferenceArray()); 374 const uint32_t* vreg_end = &vregs_[NumberOfVRegs()]; 375 return reinterpret_cast<const StackReference<mirror::Object>*>(vreg_end); 376 } 377 References()378 StackReference<mirror::Object>* References() { 379 return const_cast<StackReference<mirror::Object>*>(const_cast<const ShadowFrame*>(this)->References()); 380 } 381 382 #if defined(ART_USE_PORTABLE_COMPILER) 383 enum ShadowFrameFlag { 384 kHasReferenceArray = 1ul << 31 385 }; 386 // TODO: make const in the portable case. 387 uint32_t number_of_vregs_; 388 #else 389 const uint32_t number_of_vregs_; 390 #endif 391 // Link to previous shadow frame or NULL. 392 ShadowFrame* link_; 393 mirror::ArtMethod* method_; 394 uint32_t dex_pc_; 395 uint32_t vregs_[0]; 396 397 DISALLOW_IMPLICIT_CONSTRUCTORS(ShadowFrame); 398 }; 399 400 // The managed stack is used to record fragments of managed code stacks. Managed code stacks 401 // may either be shadow frames or lists of frames using fixed frame sizes. Transition records are 402 // necessary for transitions between code using different frame layouts and transitions into native 403 // code. 404 class PACKED(4) ManagedStack { 405 public: ManagedStack()406 ManagedStack() 407 : link_(NULL), top_shadow_frame_(NULL), top_quick_frame_(NULL), top_quick_frame_pc_(0) {} 408 PushManagedStackFragment(ManagedStack * fragment)409 void PushManagedStackFragment(ManagedStack* fragment) { 410 // Copy this top fragment into given fragment. 411 memcpy(fragment, this, sizeof(ManagedStack)); 412 // Clear this fragment, which has become the top. 413 memset(this, 0, sizeof(ManagedStack)); 414 // Link our top fragment onto the given fragment. 415 link_ = fragment; 416 } 417 PopManagedStackFragment(const ManagedStack & fragment)418 void PopManagedStackFragment(const ManagedStack& fragment) { 419 DCHECK(&fragment == link_); 420 // Copy this given fragment back to the top. 421 memcpy(this, &fragment, sizeof(ManagedStack)); 422 } 423 GetLink()424 ManagedStack* GetLink() const { 425 return link_; 426 } 427 GetTopQuickFrame()428 StackReference<mirror::ArtMethod>* GetTopQuickFrame() const { 429 return top_quick_frame_; 430 } 431 SetTopQuickFrame(StackReference<mirror::ArtMethod> * top)432 void SetTopQuickFrame(StackReference<mirror::ArtMethod>* top) { 433 DCHECK(top_shadow_frame_ == NULL); 434 top_quick_frame_ = top; 435 } 436 GetTopQuickFramePc()437 uintptr_t GetTopQuickFramePc() const { 438 return top_quick_frame_pc_; 439 } 440 SetTopQuickFramePc(uintptr_t pc)441 void SetTopQuickFramePc(uintptr_t pc) { 442 DCHECK(top_shadow_frame_ == NULL); 443 top_quick_frame_pc_ = pc; 444 } 445 TopQuickFrameOffset()446 static size_t TopQuickFrameOffset() { 447 return OFFSETOF_MEMBER(ManagedStack, top_quick_frame_); 448 } 449 TopQuickFramePcOffset()450 static size_t TopQuickFramePcOffset() { 451 return OFFSETOF_MEMBER(ManagedStack, top_quick_frame_pc_); 452 } 453 PushShadowFrame(ShadowFrame * new_top_frame)454 ShadowFrame* PushShadowFrame(ShadowFrame* new_top_frame) { 455 DCHECK(top_quick_frame_ == NULL); 456 ShadowFrame* old_frame = top_shadow_frame_; 457 top_shadow_frame_ = new_top_frame; 458 new_top_frame->SetLink(old_frame); 459 return old_frame; 460 } 461 PopShadowFrame()462 ShadowFrame* PopShadowFrame() { 463 DCHECK(top_quick_frame_ == NULL); 464 CHECK(top_shadow_frame_ != NULL); 465 ShadowFrame* frame = top_shadow_frame_; 466 top_shadow_frame_ = frame->GetLink(); 467 return frame; 468 } 469 GetTopShadowFrame()470 ShadowFrame* GetTopShadowFrame() const { 471 return top_shadow_frame_; 472 } 473 SetTopShadowFrame(ShadowFrame * top)474 void SetTopShadowFrame(ShadowFrame* top) { 475 DCHECK(top_quick_frame_ == NULL); 476 top_shadow_frame_ = top; 477 } 478 TopShadowFrameOffset()479 static size_t TopShadowFrameOffset() { 480 return OFFSETOF_MEMBER(ManagedStack, top_shadow_frame_); 481 } 482 483 size_t NumJniShadowFrameReferences() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 484 485 bool ShadowFramesContain(StackReference<mirror::Object>* shadow_frame_entry) const; 486 487 private: 488 ManagedStack* link_; 489 ShadowFrame* top_shadow_frame_; 490 StackReference<mirror::ArtMethod>* top_quick_frame_; 491 uintptr_t top_quick_frame_pc_; 492 }; 493 494 class StackVisitor { 495 protected: 496 StackVisitor(Thread* thread, Context* context) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 497 498 public: ~StackVisitor()499 virtual ~StackVisitor() {} 500 501 // Return 'true' if we should continue to visit more frames, 'false' to stop. 502 virtual bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0; 503 504 void WalkStack(bool include_transitions = false) 505 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 506 GetMethod()507 mirror::ArtMethod* GetMethod() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 508 if (cur_shadow_frame_ != nullptr) { 509 return cur_shadow_frame_->GetMethod(); 510 } else if (cur_quick_frame_ != nullptr) { 511 return cur_quick_frame_->AsMirrorPtr(); 512 } else { 513 return nullptr; 514 } 515 } 516 IsShadowFrame()517 bool IsShadowFrame() const { 518 return cur_shadow_frame_ != nullptr; 519 } 520 521 uint32_t GetDexPc(bool abort_on_failure = true) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 522 523 mirror::Object* GetThisObject() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 524 525 size_t GetNativePcOffset() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 526 CalleeSaveAddress(int num,size_t frame_size)527 uintptr_t* CalleeSaveAddress(int num, size_t frame_size) const 528 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 529 // Callee saves are held at the top of the frame 530 DCHECK(GetMethod() != nullptr); 531 byte* save_addr = 532 reinterpret_cast<byte*>(cur_quick_frame_) + frame_size - ((num + 1) * kPointerSize); 533 #if defined(__i386__) || defined(__x86_64__) 534 save_addr -= kPointerSize; // account for return address 535 #endif 536 return reinterpret_cast<uintptr_t*>(save_addr); 537 } 538 539 // Returns the height of the stack in the managed stack frames, including transitions. GetFrameHeight()540 size_t GetFrameHeight() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 541 return GetNumFrames() - cur_depth_ - 1; 542 } 543 544 // Returns a frame ID for JDWP use, starting from 1. GetFrameId()545 size_t GetFrameId() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 546 return GetFrameHeight() + 1; 547 } 548 GetNumFrames()549 size_t GetNumFrames() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 550 if (num_frames_ == 0) { 551 num_frames_ = ComputeNumFrames(thread_); 552 } 553 return num_frames_; 554 } 555 GetFrameDepth()556 size_t GetFrameDepth() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 557 return cur_depth_; 558 } 559 560 // Get the method and dex pc immediately after the one that's currently being visited. 561 bool GetNextMethodAndDexPc(mirror::ArtMethod** next_method, uint32_t* next_dex_pc) 562 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 563 564 bool GetVReg(mirror::ArtMethod* m, uint16_t vreg, VRegKind kind, uint32_t* val) const 565 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 566 GetVReg(mirror::ArtMethod * m,uint16_t vreg,VRegKind kind)567 uint32_t GetVReg(mirror::ArtMethod* m, uint16_t vreg, VRegKind kind) const 568 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 569 uint32_t val; 570 bool success = GetVReg(m, vreg, kind, &val); 571 CHECK(success) << "Failed to read vreg " << vreg << " of kind " << kind; 572 return val; 573 } 574 575 bool GetVRegPair(mirror::ArtMethod* m, uint16_t vreg, VRegKind kind_lo, VRegKind kind_hi, 576 uint64_t* val) const 577 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 578 GetVRegPair(mirror::ArtMethod * m,uint16_t vreg,VRegKind kind_lo,VRegKind kind_hi)579 uint64_t GetVRegPair(mirror::ArtMethod* m, uint16_t vreg, VRegKind kind_lo, 580 VRegKind kind_hi) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 581 uint64_t val; 582 bool success = GetVRegPair(m, vreg, kind_lo, kind_hi, &val); 583 CHECK(success) << "Failed to read vreg pair " << vreg 584 << " of kind [" << kind_lo << "," << kind_hi << "]"; 585 return val; 586 } 587 588 bool SetVReg(mirror::ArtMethod* m, uint16_t vreg, uint32_t new_value, VRegKind kind) 589 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 590 591 bool SetVRegPair(mirror::ArtMethod* m, uint16_t vreg, uint64_t new_value, 592 VRegKind kind_lo, VRegKind kind_hi) 593 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 594 595 uintptr_t* GetGPRAddress(uint32_t reg) const; 596 597 // This is a fast-path for getting/setting values in a quick frame. GetVRegAddr(StackReference<mirror::ArtMethod> * cur_quick_frame,const DexFile::CodeItem * code_item,uint32_t core_spills,uint32_t fp_spills,size_t frame_size,uint16_t vreg)598 uint32_t* GetVRegAddr(StackReference<mirror::ArtMethod>* cur_quick_frame, 599 const DexFile::CodeItem* code_item, 600 uint32_t core_spills, uint32_t fp_spills, size_t frame_size, 601 uint16_t vreg) const { 602 int offset = GetVRegOffset(code_item, core_spills, fp_spills, frame_size, vreg, kRuntimeISA); 603 DCHECK_EQ(cur_quick_frame, GetCurrentQuickFrame()); 604 byte* vreg_addr = reinterpret_cast<byte*>(cur_quick_frame) + offset; 605 return reinterpret_cast<uint32_t*>(vreg_addr); 606 } 607 608 uintptr_t GetReturnPc() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 609 610 void SetReturnPc(uintptr_t new_ret_pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 611 612 /* 613 * Return sp-relative offset for a Dalvik virtual register, compiler 614 * spill or Method* in bytes using Method*. 615 * Note that (reg >= 0) refers to a Dalvik register, (reg == -1) 616 * denotes an invalid Dalvik register, (reg == -2) denotes Method* 617 * and (reg <= -3) denotes a compiler temporary. A compiler temporary 618 * can be thought of as a virtual register that does not exist in the 619 * dex but holds intermediate values to help optimizations and code 620 * generation. A special compiler temporary is one whose location 621 * in frame is well known while non-special ones do not have a requirement 622 * on location in frame as long as code generator itself knows how 623 * to access them. 624 * 625 * +---------------------------+ 626 * | IN[ins-1] | {Note: resides in caller's frame} 627 * | . | 628 * | IN[0] | 629 * | caller's ArtMethod | ... StackReference<ArtMethod> 630 * +===========================+ {Note: start of callee's frame} 631 * | core callee-save spill | {variable sized} 632 * +---------------------------+ 633 * | fp callee-save spill | 634 * +---------------------------+ 635 * | filler word | {For compatibility, if V[locals-1] used as wide 636 * +---------------------------+ 637 * | V[locals-1] | 638 * | V[locals-2] | 639 * | . | 640 * | . | ... (reg == 2) 641 * | V[1] | ... (reg == 1) 642 * | V[0] | ... (reg == 0) <---- "locals_start" 643 * +---------------------------+ 644 * | Compiler temp region | ... (reg <= -3) 645 * | | 646 * | | 647 * +---------------------------+ 648 * | stack alignment padding | {0 to (kStackAlignWords-1) of padding} 649 * +---------------------------+ 650 * | OUT[outs-1] | 651 * | OUT[outs-2] | 652 * | . | 653 * | OUT[0] | 654 * | StackReference<ArtMethod> | ... (reg == -2) <<== sp, 16-byte aligned 655 * +===========================+ 656 */ GetVRegOffset(const DexFile::CodeItem * code_item,uint32_t core_spills,uint32_t fp_spills,size_t frame_size,int reg,InstructionSet isa)657 static int GetVRegOffset(const DexFile::CodeItem* code_item, 658 uint32_t core_spills, uint32_t fp_spills, 659 size_t frame_size, int reg, InstructionSet isa) { 660 DCHECK_EQ(frame_size & (kStackAlignment - 1), 0U); 661 DCHECK_NE(reg, static_cast<int>(kVRegInvalid)); 662 int spill_size = POPCOUNT(core_spills) * GetBytesPerGprSpillLocation(isa) 663 + POPCOUNT(fp_spills) * GetBytesPerFprSpillLocation(isa) 664 + sizeof(uint32_t); // Filler. 665 int num_ins = code_item->ins_size_; 666 int num_regs = code_item->registers_size_ - num_ins; 667 int locals_start = frame_size - spill_size - num_regs * sizeof(uint32_t); 668 if (reg == static_cast<int>(kVRegMethodPtrBaseReg)) { 669 // The current method pointer corresponds to special location on stack. 670 return 0; 671 } else if (reg <= static_cast<int>(kVRegNonSpecialTempBaseReg)) { 672 /* 673 * Special temporaries may have custom locations and the logic above deals with that. 674 * However, non-special temporaries are placed relative to the locals. Since the 675 * virtual register numbers for temporaries "grow" in negative direction, reg number 676 * will always be <= to the temp base reg. Thus, the logic ensures that the first 677 * temp is at offset -4 bytes from locals, the second is at -8 bytes from locals, 678 * and so on. 679 */ 680 int relative_offset = 681 (reg + std::abs(static_cast<int>(kVRegNonSpecialTempBaseReg)) - 1) * sizeof(uint32_t); 682 return locals_start + relative_offset; 683 } else if (reg < num_regs) { 684 return locals_start + (reg * sizeof(uint32_t)); 685 } else { 686 // Handle ins. 687 return frame_size + ((reg - num_regs) * sizeof(uint32_t)) + 688 sizeof(StackReference<mirror::ArtMethod>); 689 } 690 } 691 GetOutVROffset(uint16_t out_num,InstructionSet isa)692 static int GetOutVROffset(uint16_t out_num, InstructionSet isa) { 693 // According to stack model, the first out is above the Method referernce. 694 return sizeof(StackReference<mirror::ArtMethod>) + (out_num * sizeof(uint32_t)); 695 } 696 GetCurrentQuickFramePc()697 uintptr_t GetCurrentQuickFramePc() const { 698 return cur_quick_frame_pc_; 699 } 700 GetCurrentQuickFrame()701 StackReference<mirror::ArtMethod>* GetCurrentQuickFrame() const { 702 return cur_quick_frame_; 703 } 704 GetCurrentShadowFrame()705 ShadowFrame* GetCurrentShadowFrame() const { 706 return cur_shadow_frame_; 707 } 708 GetCurrentHandleScope()709 HandleScope* GetCurrentHandleScope() const { 710 StackReference<mirror::ArtMethod>* sp = GetCurrentQuickFrame(); 711 ++sp; // Skip Method*; handle scope comes next; 712 return reinterpret_cast<HandleScope*>(sp); 713 } 714 715 std::string DescribeLocation() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 716 717 static size_t ComputeNumFrames(Thread* thread) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 718 719 static void DescribeStack(Thread* thread) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 720 721 private: 722 // Private constructor known in the case that num_frames_ has already been computed. 723 StackVisitor(Thread* thread, Context* context, size_t num_frames) 724 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 725 726 bool GetGPR(uint32_t reg, uintptr_t* val) const; 727 bool SetGPR(uint32_t reg, uintptr_t value); 728 bool GetFPR(uint32_t reg, uintptr_t* val) const; 729 bool SetFPR(uint32_t reg, uintptr_t value); 730 731 void SanityCheckFrame() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 732 733 Thread* const thread_; 734 ShadowFrame* cur_shadow_frame_; 735 StackReference<mirror::ArtMethod>* cur_quick_frame_; 736 uintptr_t cur_quick_frame_pc_; 737 // Lazily computed, number of frames in the stack. 738 size_t num_frames_; 739 // Depth of the frame we're currently at. 740 size_t cur_depth_; 741 742 protected: 743 Context* const context_; 744 }; 745 746 } // namespace art 747 748 #endif // ART_RUNTIME_STACK_H_ 749