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 "arch/instruction_set.h" 24 #include "base/bit_utils.h" 25 #include "dex_file.h" 26 #include "gc_root.h" 27 #include "mirror/object_reference.h" 28 #include "read_barrier.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 Context; 39 class ShadowFrame; 40 class HandleScope; 41 class ScopedObjectAccess; 42 class StackVisitor; 43 class Thread; 44 45 // The kind of vreg being accessed in calls to Set/GetVReg. 46 enum VRegKind { 47 kReferenceVReg, 48 kIntVReg, 49 kFloatVReg, 50 kLongLoVReg, 51 kLongHiVReg, 52 kDoubleLoVReg, 53 kDoubleHiVReg, 54 kConstant, 55 kImpreciseConstant, 56 kUndefined, 57 }; 58 std::ostream& operator<<(std::ostream& os, const VRegKind& rhs); 59 60 // A reference from the shadow stack to a MirrorType object within the Java heap. 61 template<class MirrorType> 62 class MANAGED StackReference : public mirror::CompressedReference<MirrorType> { 63 }; 64 65 // ShadowFrame has 2 possible layouts: 66 // - interpreter - separate VRegs and reference arrays. References are in the reference array. 67 // - JNI - just VRegs, but where every VReg holds a reference. 68 class ShadowFrame { 69 public: 70 // Compute size of ShadowFrame in bytes assuming it has a reference array. ComputeSize(uint32_t num_vregs)71 static size_t ComputeSize(uint32_t num_vregs) { 72 return sizeof(ShadowFrame) + (sizeof(uint32_t) * num_vregs) + 73 (sizeof(StackReference<mirror::Object>) * num_vregs); 74 } 75 76 // Create ShadowFrame in heap for deoptimization. CreateDeoptimizedFrame(uint32_t num_vregs,ShadowFrame * link,ArtMethod * method,uint32_t dex_pc)77 static ShadowFrame* CreateDeoptimizedFrame(uint32_t num_vregs, ShadowFrame* link, 78 ArtMethod* method, uint32_t dex_pc) { 79 uint8_t* memory = new uint8_t[ComputeSize(num_vregs)]; 80 return Create(num_vregs, link, method, dex_pc, memory); 81 } 82 83 // Delete a ShadowFrame allocated on the heap for deoptimization. DeleteDeoptimizedFrame(ShadowFrame * sf)84 static void DeleteDeoptimizedFrame(ShadowFrame* sf) { 85 uint8_t* memory = reinterpret_cast<uint8_t*>(sf); 86 delete[] memory; 87 } 88 89 // Create ShadowFrame for interpreter using provided memory. Create(uint32_t num_vregs,ShadowFrame * link,ArtMethod * method,uint32_t dex_pc,void * memory)90 static ShadowFrame* Create(uint32_t num_vregs, ShadowFrame* link, 91 ArtMethod* method, uint32_t dex_pc, void* memory) { 92 ShadowFrame* sf = new (memory) ShadowFrame(num_vregs, link, method, dex_pc, true); 93 return sf; 94 } ~ShadowFrame()95 ~ShadowFrame() {} 96 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_; 107 } 108 SetDexPC(uint32_t dex_pc)109 void SetDexPC(uint32_t dex_pc) { 110 dex_pc_ = dex_pc; 111 } 112 GetLink()113 ShadowFrame* GetLink() const { 114 return link_; 115 } 116 SetLink(ShadowFrame * frame)117 void SetLink(ShadowFrame* frame) { 118 DCHECK_NE(this, frame); 119 link_ = frame; 120 } 121 GetVReg(size_t i)122 int32_t GetVReg(size_t i) const { 123 DCHECK_LT(i, NumberOfVRegs()); 124 const uint32_t* vreg = &vregs_[i]; 125 return *reinterpret_cast<const int32_t*>(vreg); 126 } 127 GetVRegFloat(size_t i)128 float GetVRegFloat(size_t i) const { 129 DCHECK_LT(i, NumberOfVRegs()); 130 // NOTE: Strict-aliasing? 131 const uint32_t* vreg = &vregs_[i]; 132 return *reinterpret_cast<const float*>(vreg); 133 } 134 GetVRegLong(size_t i)135 int64_t GetVRegLong(size_t i) const { 136 DCHECK_LT(i, NumberOfVRegs()); 137 const uint32_t* vreg = &vregs_[i]; 138 // Alignment attribute required for GCC 4.8 139 typedef const int64_t unaligned_int64 __attribute__ ((aligned (4))); 140 return *reinterpret_cast<unaligned_int64*>(vreg); 141 } 142 GetVRegDouble(size_t i)143 double GetVRegDouble(size_t i) const { 144 DCHECK_LT(i, NumberOfVRegs()); 145 const uint32_t* vreg = &vregs_[i]; 146 // Alignment attribute required for GCC 4.8 147 typedef const double unaligned_double __attribute__ ((aligned (4))); 148 return *reinterpret_cast<unaligned_double*>(vreg); 149 } 150 151 template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> GetVRegReference(size_t i)152 mirror::Object* GetVRegReference(size_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 153 DCHECK_LT(i, NumberOfVRegs()); 154 mirror::Object* ref; 155 if (HasReferenceArray()) { 156 ref = References()[i].AsMirrorPtr(); 157 } else { 158 const uint32_t* vreg_ptr = &vregs_[i]; 159 ref = reinterpret_cast<const StackReference<mirror::Object>*>(vreg_ptr)->AsMirrorPtr(); 160 } 161 if (kUseReadBarrier) { 162 ReadBarrier::AssertToSpaceInvariant(ref); 163 } 164 if (kVerifyFlags & kVerifyReads) { 165 VerifyObject(ref); 166 } 167 return ref; 168 } 169 170 // Get view of vregs as range of consecutive arguments starting at i. GetVRegArgs(size_t i)171 uint32_t* GetVRegArgs(size_t i) { 172 return &vregs_[i]; 173 } 174 SetVReg(size_t i,int32_t val)175 void SetVReg(size_t i, int32_t val) { 176 DCHECK_LT(i, NumberOfVRegs()); 177 uint32_t* vreg = &vregs_[i]; 178 *reinterpret_cast<int32_t*>(vreg) = val; 179 // This is needed for moving collectors since these can update the vreg references if they 180 // happen to agree with references in the reference array. 181 if (kMovingCollector && HasReferenceArray()) { 182 References()[i].Clear(); 183 } 184 } 185 SetVRegFloat(size_t i,float val)186 void SetVRegFloat(size_t i, float val) { 187 DCHECK_LT(i, NumberOfVRegs()); 188 uint32_t* vreg = &vregs_[i]; 189 *reinterpret_cast<float*>(vreg) = val; 190 // This is needed for moving collectors since these can update the vreg references if they 191 // happen to agree with references in the reference array. 192 if (kMovingCollector && HasReferenceArray()) { 193 References()[i].Clear(); 194 } 195 } 196 SetVRegLong(size_t i,int64_t val)197 void SetVRegLong(size_t i, int64_t val) { 198 DCHECK_LT(i, NumberOfVRegs()); 199 uint32_t* vreg = &vregs_[i]; 200 // Alignment attribute required for GCC 4.8 201 typedef int64_t unaligned_int64 __attribute__ ((aligned (4))); 202 *reinterpret_cast<unaligned_int64*>(vreg) = val; 203 // This is needed for moving collectors since these can update the vreg references if they 204 // happen to agree with references in the reference array. 205 if (kMovingCollector && HasReferenceArray()) { 206 References()[i].Clear(); 207 References()[i + 1].Clear(); 208 } 209 } 210 SetVRegDouble(size_t i,double val)211 void SetVRegDouble(size_t i, double val) { 212 DCHECK_LT(i, NumberOfVRegs()); 213 uint32_t* vreg = &vregs_[i]; 214 // Alignment attribute required for GCC 4.8 215 typedef double unaligned_double __attribute__ ((aligned (4))); 216 *reinterpret_cast<unaligned_double*>(vreg) = val; 217 // This is needed for moving collectors since these can update the vreg references if they 218 // happen to agree with references in the reference array. 219 if (kMovingCollector && HasReferenceArray()) { 220 References()[i].Clear(); 221 References()[i + 1].Clear(); 222 } 223 } 224 225 template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> SetVRegReference(size_t i,mirror::Object * val)226 void SetVRegReference(size_t i, mirror::Object* val) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 227 DCHECK_LT(i, NumberOfVRegs()); 228 if (kVerifyFlags & kVerifyWrites) { 229 VerifyObject(val); 230 } 231 if (kUseReadBarrier) { 232 ReadBarrier::AssertToSpaceInvariant(val); 233 } 234 uint32_t* vreg = &vregs_[i]; 235 reinterpret_cast<StackReference<mirror::Object>*>(vreg)->Assign(val); 236 if (HasReferenceArray()) { 237 References()[i].Assign(val); 238 } 239 } 240 GetMethod()241 ArtMethod* GetMethod() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 242 DCHECK(method_ != nullptr); 243 return method_; 244 } 245 246 mirror::Object* GetThisObject() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 247 248 mirror::Object* GetThisObject(uint16_t num_ins) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 249 Contains(StackReference<mirror::Object> * shadow_frame_entry_obj)250 bool Contains(StackReference<mirror::Object>* shadow_frame_entry_obj) const { 251 if (HasReferenceArray()) { 252 return ((&References()[0] <= shadow_frame_entry_obj) && 253 (shadow_frame_entry_obj <= (&References()[NumberOfVRegs() - 1]))); 254 } else { 255 uint32_t* shadow_frame_entry = reinterpret_cast<uint32_t*>(shadow_frame_entry_obj); 256 return ((&vregs_[0] <= shadow_frame_entry) && 257 (shadow_frame_entry <= (&vregs_[NumberOfVRegs() - 1]))); 258 } 259 } 260 LinkOffset()261 static size_t LinkOffset() { 262 return OFFSETOF_MEMBER(ShadowFrame, link_); 263 } 264 MethodOffset()265 static size_t MethodOffset() { 266 return OFFSETOF_MEMBER(ShadowFrame, method_); 267 } 268 DexPCOffset()269 static size_t DexPCOffset() { 270 return OFFSETOF_MEMBER(ShadowFrame, dex_pc_); 271 } 272 NumberOfVRegsOffset()273 static size_t NumberOfVRegsOffset() { 274 return OFFSETOF_MEMBER(ShadowFrame, number_of_vregs_); 275 } 276 VRegsOffset()277 static size_t VRegsOffset() { 278 return OFFSETOF_MEMBER(ShadowFrame, vregs_); 279 } 280 281 private: ShadowFrame(uint32_t num_vregs,ShadowFrame * link,ArtMethod * method,uint32_t dex_pc,bool has_reference_array)282 ShadowFrame(uint32_t num_vregs, ShadowFrame* link, ArtMethod* method, 283 uint32_t dex_pc, bool has_reference_array) 284 : number_of_vregs_(num_vregs), link_(link), method_(method), dex_pc_(dex_pc) { 285 if (has_reference_array) { 286 memset(vregs_, 0, num_vregs * (sizeof(uint32_t) + sizeof(StackReference<mirror::Object>))); 287 } else { 288 memset(vregs_, 0, num_vregs * sizeof(uint32_t)); 289 } 290 } 291 References()292 const StackReference<mirror::Object>* References() const { 293 DCHECK(HasReferenceArray()); 294 const uint32_t* vreg_end = &vregs_[NumberOfVRegs()]; 295 return reinterpret_cast<const StackReference<mirror::Object>*>(vreg_end); 296 } 297 References()298 StackReference<mirror::Object>* References() { 299 return const_cast<StackReference<mirror::Object>*>( 300 const_cast<const ShadowFrame*>(this)->References()); 301 } 302 303 const uint32_t number_of_vregs_; 304 // Link to previous shadow frame or null. 305 ShadowFrame* link_; 306 ArtMethod* method_; 307 uint32_t dex_pc_; 308 uint32_t vregs_[0]; 309 310 DISALLOW_IMPLICIT_CONSTRUCTORS(ShadowFrame); 311 }; 312 313 class JavaFrameRootInfo : public RootInfo { 314 public: JavaFrameRootInfo(uint32_t thread_id,const StackVisitor * stack_visitor,size_t vreg)315 JavaFrameRootInfo(uint32_t thread_id, const StackVisitor* stack_visitor, size_t vreg) 316 : RootInfo(kRootJavaFrame, thread_id), stack_visitor_(stack_visitor), vreg_(vreg) { 317 } 318 virtual void Describe(std::ostream& os) const OVERRIDE 319 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 320 321 private: 322 const StackVisitor* const stack_visitor_; 323 const size_t vreg_; 324 }; 325 326 // The managed stack is used to record fragments of managed code stacks. Managed code stacks 327 // may either be shadow frames or lists of frames using fixed frame sizes. Transition records are 328 // necessary for transitions between code using different frame layouts and transitions into native 329 // code. 330 class PACKED(4) ManagedStack { 331 public: ManagedStack()332 ManagedStack() 333 : top_quick_frame_(nullptr), link_(nullptr), top_shadow_frame_(nullptr) {} 334 PushManagedStackFragment(ManagedStack * fragment)335 void PushManagedStackFragment(ManagedStack* fragment) { 336 // Copy this top fragment into given fragment. 337 memcpy(fragment, this, sizeof(ManagedStack)); 338 // Clear this fragment, which has become the top. 339 memset(this, 0, sizeof(ManagedStack)); 340 // Link our top fragment onto the given fragment. 341 link_ = fragment; 342 } 343 PopManagedStackFragment(const ManagedStack & fragment)344 void PopManagedStackFragment(const ManagedStack& fragment) { 345 DCHECK(&fragment == link_); 346 // Copy this given fragment back to the top. 347 memcpy(this, &fragment, sizeof(ManagedStack)); 348 } 349 GetLink()350 ManagedStack* GetLink() const { 351 return link_; 352 } 353 GetTopQuickFrame()354 ArtMethod** GetTopQuickFrame() const { 355 return top_quick_frame_; 356 } 357 SetTopQuickFrame(ArtMethod ** top)358 void SetTopQuickFrame(ArtMethod** top) { 359 DCHECK(top_shadow_frame_ == nullptr); 360 top_quick_frame_ = top; 361 } 362 TopQuickFrameOffset()363 static size_t TopQuickFrameOffset() { 364 return OFFSETOF_MEMBER(ManagedStack, top_quick_frame_); 365 } 366 PushShadowFrame(ShadowFrame * new_top_frame)367 ShadowFrame* PushShadowFrame(ShadowFrame* new_top_frame) { 368 DCHECK(top_quick_frame_ == nullptr); 369 ShadowFrame* old_frame = top_shadow_frame_; 370 top_shadow_frame_ = new_top_frame; 371 new_top_frame->SetLink(old_frame); 372 return old_frame; 373 } 374 PopShadowFrame()375 ShadowFrame* PopShadowFrame() { 376 DCHECK(top_quick_frame_ == nullptr); 377 CHECK(top_shadow_frame_ != nullptr); 378 ShadowFrame* frame = top_shadow_frame_; 379 top_shadow_frame_ = frame->GetLink(); 380 return frame; 381 } 382 GetTopShadowFrame()383 ShadowFrame* GetTopShadowFrame() const { 384 return top_shadow_frame_; 385 } 386 SetTopShadowFrame(ShadowFrame * top)387 void SetTopShadowFrame(ShadowFrame* top) { 388 DCHECK(top_quick_frame_ == nullptr); 389 top_shadow_frame_ = top; 390 } 391 TopShadowFrameOffset()392 static size_t TopShadowFrameOffset() { 393 return OFFSETOF_MEMBER(ManagedStack, top_shadow_frame_); 394 } 395 396 size_t NumJniShadowFrameReferences() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 397 398 bool ShadowFramesContain(StackReference<mirror::Object>* shadow_frame_entry) const; 399 400 private: 401 ArtMethod** top_quick_frame_; 402 ManagedStack* link_; 403 ShadowFrame* top_shadow_frame_; 404 }; 405 406 class StackVisitor { 407 public: 408 // This enum defines a flag to control whether inlined frames are included 409 // when walking the stack. 410 enum class StackWalkKind { 411 kIncludeInlinedFrames, 412 kSkipInlinedFrames, 413 }; 414 415 protected: 416 StackVisitor(Thread* thread, Context* context, StackWalkKind walk_kind) 417 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 418 419 public: ~StackVisitor()420 virtual ~StackVisitor() {} 421 422 // Return 'true' if we should continue to visit more frames, 'false' to stop. 423 virtual bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0; 424 425 void WalkStack(bool include_transitions = false) 426 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 427 GetMethod()428 ArtMethod* GetMethod() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 429 if (cur_shadow_frame_ != nullptr) { 430 return cur_shadow_frame_->GetMethod(); 431 } else if (cur_quick_frame_ != nullptr) { 432 return *cur_quick_frame_; 433 } else { 434 return nullptr; 435 } 436 } 437 IsShadowFrame()438 bool IsShadowFrame() const { 439 return cur_shadow_frame_ != nullptr; 440 } 441 442 uint32_t GetDexPc(bool abort_on_failure = true) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 443 444 mirror::Object* GetThisObject() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 445 446 size_t GetNativePcOffset() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 447 CalleeSaveAddress(int num,size_t frame_size)448 uintptr_t* CalleeSaveAddress(int num, size_t frame_size) const 449 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 450 // Callee saves are held at the top of the frame 451 DCHECK(GetMethod() != nullptr); 452 uint8_t* save_addr = 453 reinterpret_cast<uint8_t*>(cur_quick_frame_) + frame_size - ((num + 1) * sizeof(void*)); 454 #if defined(__i386__) || defined(__x86_64__) 455 save_addr -= sizeof(void*); // account for return address 456 #endif 457 return reinterpret_cast<uintptr_t*>(save_addr); 458 } 459 460 // Returns the height of the stack in the managed stack frames, including transitions. GetFrameHeight()461 size_t GetFrameHeight() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 462 return GetNumFrames() - cur_depth_ - 1; 463 } 464 465 // Returns a frame ID for JDWP use, starting from 1. GetFrameId()466 size_t GetFrameId() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 467 return GetFrameHeight() + 1; 468 } 469 GetNumFrames()470 size_t GetNumFrames() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 471 if (num_frames_ == 0) { 472 num_frames_ = ComputeNumFrames(thread_, walk_kind_); 473 } 474 return num_frames_; 475 } 476 GetFrameDepth()477 size_t GetFrameDepth() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 478 return cur_depth_; 479 } 480 481 // Get the method and dex pc immediately after the one that's currently being visited. 482 bool GetNextMethodAndDexPc(ArtMethod** next_method, uint32_t* next_dex_pc) 483 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 484 485 bool IsReferenceVReg(ArtMethod* m, uint16_t vreg) 486 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 487 488 bool GetVReg(ArtMethod* m, uint16_t vreg, VRegKind kind, uint32_t* val) const 489 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 490 491 bool GetVRegPair(ArtMethod* m, uint16_t vreg, VRegKind kind_lo, VRegKind kind_hi, 492 uint64_t* val) const 493 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 494 495 bool SetVReg(ArtMethod* m, uint16_t vreg, uint32_t new_value, VRegKind kind) 496 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 497 498 bool SetVRegPair(ArtMethod* m, uint16_t vreg, uint64_t new_value, 499 VRegKind kind_lo, VRegKind kind_hi) 500 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 501 502 uintptr_t* GetGPRAddress(uint32_t reg) const; 503 504 // This is a fast-path for getting/setting values in a quick frame. GetVRegAddrFromQuickCode(ArtMethod ** cur_quick_frame,const DexFile::CodeItem * code_item,uint32_t core_spills,uint32_t fp_spills,size_t frame_size,uint16_t vreg)505 uint32_t* GetVRegAddrFromQuickCode(ArtMethod** cur_quick_frame, 506 const DexFile::CodeItem* code_item, 507 uint32_t core_spills, uint32_t fp_spills, size_t frame_size, 508 uint16_t vreg) const { 509 int offset = GetVRegOffsetFromQuickCode( 510 code_item, core_spills, fp_spills, frame_size, vreg, kRuntimeISA); 511 DCHECK_EQ(cur_quick_frame, GetCurrentQuickFrame()); 512 uint8_t* vreg_addr = reinterpret_cast<uint8_t*>(cur_quick_frame) + offset; 513 return reinterpret_cast<uint32_t*>(vreg_addr); 514 } 515 516 uintptr_t GetReturnPc() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 517 518 void SetReturnPc(uintptr_t new_ret_pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 519 520 /* 521 * Return sp-relative offset for a Dalvik virtual register, compiler 522 * spill or Method* in bytes using Method*. 523 * Note that (reg == -1) denotes an invalid Dalvik register. For the 524 * positive values, the Dalvik registers come first, followed by the 525 * Method*, followed by other special temporaries if any, followed by 526 * regular compiler temporary. As of now we only have the Method* as 527 * as a special compiler temporary. 528 * A compiler temporary can be thought of as a virtual register that 529 * does not exist in the dex but holds intermediate values to help 530 * optimizations and code generation. A special compiler temporary is 531 * one whose location in frame is well known while non-special ones 532 * do not have a requirement on location in frame as long as code 533 * generator itself knows how to access them. 534 * 535 * +-------------------------------+ 536 * | IN[ins-1] | {Note: resides in caller's frame} 537 * | . | 538 * | IN[0] | 539 * | caller's ArtMethod | ... ArtMethod* 540 * +===============================+ {Note: start of callee's frame} 541 * | core callee-save spill | {variable sized} 542 * +-------------------------------+ 543 * | fp callee-save spill | 544 * +-------------------------------+ 545 * | filler word | {For compatibility, if V[locals-1] used as wide 546 * +-------------------------------+ 547 * | V[locals-1] | 548 * | V[locals-2] | 549 * | . | 550 * | . | ... (reg == 2) 551 * | V[1] | ... (reg == 1) 552 * | V[0] | ... (reg == 0) <---- "locals_start" 553 * +-------------------------------+ 554 * | stack alignment padding | {0 to (kStackAlignWords-1) of padding} 555 * +-------------------------------+ 556 * | Compiler temp region | ... (reg >= max_num_special_temps) 557 * | . | 558 * | . | 559 * | V[max_num_special_temps + 1] | 560 * | V[max_num_special_temps + 0] | 561 * +-------------------------------+ 562 * | OUT[outs-1] | 563 * | OUT[outs-2] | 564 * | . | 565 * | OUT[0] | 566 * | ArtMethod* | ... (reg == num_total_code_regs == special_temp_value) <<== sp, 16-byte aligned 567 * +===============================+ 568 */ 569 static int GetVRegOffsetFromQuickCode(const DexFile::CodeItem* code_item, 570 uint32_t core_spills, uint32_t fp_spills, 571 size_t frame_size, int reg, InstructionSet isa); 572 GetOutVROffset(uint16_t out_num,InstructionSet isa)573 static int GetOutVROffset(uint16_t out_num, InstructionSet isa) { 574 // According to stack model, the first out is above the Method referernce. 575 return InstructionSetPointerSize(isa) + out_num * sizeof(uint32_t); 576 } 577 IsInInlinedFrame()578 bool IsInInlinedFrame() const { 579 return false; 580 } 581 GetCurrentQuickFramePc()582 uintptr_t GetCurrentQuickFramePc() const { 583 return cur_quick_frame_pc_; 584 } 585 GetCurrentQuickFrame()586 ArtMethod** GetCurrentQuickFrame() const { 587 return cur_quick_frame_; 588 } 589 GetCurrentShadowFrame()590 ShadowFrame* GetCurrentShadowFrame() const { 591 return cur_shadow_frame_; 592 } 593 GetCurrentHandleScope(size_t pointer_size)594 HandleScope* GetCurrentHandleScope(size_t pointer_size) const { 595 ArtMethod** sp = GetCurrentQuickFrame(); 596 // Skip ArtMethod*; handle scope comes next; 597 return reinterpret_cast<HandleScope*>(reinterpret_cast<uintptr_t>(sp) + pointer_size); 598 } 599 600 std::string DescribeLocation() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 601 602 static size_t ComputeNumFrames(Thread* thread, StackWalkKind walk_kind) 603 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 604 605 static void DescribeStack(Thread* thread) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 606 607 private: 608 // Private constructor known in the case that num_frames_ has already been computed. 609 StackVisitor(Thread* thread, Context* context, StackWalkKind walk_kind, size_t num_frames) 610 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 611 IsAccessibleRegister(uint32_t reg,bool is_float)612 bool IsAccessibleRegister(uint32_t reg, bool is_float) const { 613 return is_float ? IsAccessibleFPR(reg) : IsAccessibleGPR(reg); 614 } GetRegister(uint32_t reg,bool is_float)615 uintptr_t GetRegister(uint32_t reg, bool is_float) const { 616 DCHECK(IsAccessibleRegister(reg, is_float)); 617 return is_float ? GetFPR(reg) : GetGPR(reg); 618 } SetRegister(uint32_t reg,uintptr_t value,bool is_float)619 void SetRegister(uint32_t reg, uintptr_t value, bool is_float) { 620 DCHECK(IsAccessibleRegister(reg, is_float)); 621 if (is_float) { 622 SetFPR(reg, value); 623 } else { 624 SetGPR(reg, value); 625 } 626 } 627 628 bool IsAccessibleGPR(uint32_t reg) const; 629 uintptr_t GetGPR(uint32_t reg) const; 630 void SetGPR(uint32_t reg, uintptr_t value); 631 632 bool IsAccessibleFPR(uint32_t reg) const; 633 uintptr_t GetFPR(uint32_t reg) const; 634 void SetFPR(uint32_t reg, uintptr_t value); 635 636 bool GetVRegFromQuickCode(ArtMethod* m, uint16_t vreg, VRegKind kind, 637 uint32_t* val) const 638 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 639 bool GetVRegFromOptimizedCode(ArtMethod* m, uint16_t vreg, VRegKind kind, 640 uint32_t* val) const 641 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 642 bool GetRegisterIfAccessible(uint32_t reg, VRegKind kind, uint32_t* val) const 643 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 644 645 bool GetVRegPairFromQuickCode(ArtMethod* m, uint16_t vreg, VRegKind kind_lo, 646 VRegKind kind_hi, uint64_t* val) const 647 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 648 bool GetVRegPairFromOptimizedCode(ArtMethod* m, uint16_t vreg, 649 VRegKind kind_lo, VRegKind kind_hi, 650 uint64_t* val) const 651 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 652 bool GetRegisterPairIfAccessible(uint32_t reg_lo, uint32_t reg_hi, VRegKind kind_lo, 653 uint64_t* val) const 654 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 655 656 bool SetVRegFromQuickCode(ArtMethod* m, uint16_t vreg, uint32_t new_value, 657 VRegKind kind) 658 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 659 bool SetRegisterIfAccessible(uint32_t reg, uint32_t new_value, VRegKind kind) 660 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 661 662 bool SetVRegPairFromQuickCode(ArtMethod* m, uint16_t vreg, uint64_t new_value, 663 VRegKind kind_lo, VRegKind kind_hi) 664 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 665 bool SetRegisterPairIfAccessible(uint32_t reg_lo, uint32_t reg_hi, uint64_t new_value, 666 bool is_float) 667 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 668 669 void SanityCheckFrame() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 670 671 Thread* const thread_; 672 const StackWalkKind walk_kind_; 673 ShadowFrame* cur_shadow_frame_; 674 ArtMethod** cur_quick_frame_; 675 uintptr_t cur_quick_frame_pc_; 676 // Lazily computed, number of frames in the stack. 677 size_t num_frames_; 678 // Depth of the frame we're currently at. 679 size_t cur_depth_; 680 681 protected: 682 Context* const context_; 683 }; 684 685 } // namespace art 686 687 #endif // ART_RUNTIME_STACK_H_ 688