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 22 #include <optional> 23 #include <string> 24 25 #include "base/locks.h" 26 #include "base/macros.h" 27 #include "deoptimization_kind.h" 28 #include "oat/stack_map.h" 29 #include "obj_ptr.h" 30 #include "quick/quick_method_frame_info.h" 31 32 namespace art HIDDEN { 33 34 namespace mirror { 35 class Object; 36 } // namespace mirror 37 38 class ArtMethod; 39 class Context; 40 class HandleScope; 41 class OatQuickMethodHeader; 42 class ShadowFrame; 43 class Thread; 44 union JValue; 45 46 // The kind of vreg being accessed in calls to Set/GetVReg. 47 enum VRegKind { 48 kReferenceVReg, 49 kIntVReg, 50 kFloatVReg, 51 kLongLoVReg, 52 kLongHiVReg, 53 kDoubleLoVReg, 54 kDoubleHiVReg, 55 kConstant, 56 kImpreciseConstant, 57 kUndefined, 58 }; 59 std::ostream& operator<<(std::ostream& os, VRegKind rhs); 60 61 /* 62 * Our current stack layout. 63 * The Dalvik registers come first, followed by the 64 * Method*, followed by other special temporaries if any, followed by 65 * regular compiler temporary. As of now we only have the Method* as 66 * as a special compiler temporary. 67 * A compiler temporary can be thought of as a virtual register that 68 * does not exist in the dex but holds intermediate values to help 69 * optimizations and code generation. A special compiler temporary is 70 * one whose location in frame is well known while non-special ones 71 * do not have a requirement on location in frame as long as code 72 * generator itself knows how to access them. 73 * 74 * TODO: Update this documentation? 75 * 76 * +-------------------------------+ 77 * | IN[ins-1] | {Note: resides in caller's frame} 78 * | . | 79 * | IN[0] | 80 * | caller's ArtMethod | ... ArtMethod* 81 * +===============================+ {Note: start of callee's frame} 82 * | core callee-save spill | {variable sized} 83 * +-------------------------------+ 84 * | fp callee-save spill | 85 * +-------------------------------+ 86 * | filler word | {For compatibility, if V[locals-1] used as wide 87 * +-------------------------------+ 88 * | V[locals-1] | 89 * | V[locals-2] | 90 * | . | 91 * | . | ... (reg == 2) 92 * | V[1] | ... (reg == 1) 93 * | V[0] | ... (reg == 0) <---- "locals_start" 94 * +-------------------------------+ 95 * | stack alignment padding | {0 to (kStackAlignWords-1) of padding} 96 * +-------------------------------+ 97 * | Compiler temp region | ... (reg >= max_num_special_temps) 98 * | . | 99 * | . | 100 * | V[max_num_special_temps + 1] | 101 * | V[max_num_special_temps + 0] | 102 * +-------------------------------+ 103 * | OUT[outs-1] | 104 * | OUT[outs-2] | 105 * | . | 106 * | OUT[0] | 107 * | ArtMethod* | ... (reg == num_total_code_regs == special_temp_value) <<== sp, 16-byte aligned 108 * +===============================+ 109 */ 110 111 class StackVisitor { 112 public: 113 // This enum defines a flag to control whether inlined frames are included 114 // when walking the stack. 115 enum class StackWalkKind { 116 kIncludeInlinedFrames, 117 kSkipInlinedFrames, 118 }; 119 120 protected: 121 EXPORT StackVisitor(Thread* thread, 122 Context* context, 123 StackWalkKind walk_kind, 124 bool check_suspended = true); 125 126 bool GetRegisterIfAccessible(uint32_t reg, DexRegisterLocation::Kind kind, uint32_t* val) const 127 REQUIRES_SHARED(Locks::mutator_lock_); 128 129 public: ~StackVisitor()130 virtual ~StackVisitor() {} 131 StackVisitor(const StackVisitor&) = default; 132 StackVisitor(StackVisitor&&) = default; 133 134 // Return 'true' if we should continue to visit more frames, 'false' to stop. 135 virtual bool VisitFrame() REQUIRES_SHARED(Locks::mutator_lock_) = 0; 136 137 enum class EXPORT CountTransitions { 138 kYes, 139 kNo, 140 }; 141 142 template <CountTransitions kCount = CountTransitions::kYes> 143 EXPORT void WalkStack(bool include_transitions = false) REQUIRES_SHARED(Locks::mutator_lock_); 144 145 // Convenience helper function to walk the stack with a lambda as a visitor. 146 template <CountTransitions kCountTransitions = CountTransitions::kYes, 147 typename T> 148 ALWAYS_INLINE static void WalkStack(const T& fn, 149 Thread* thread, 150 Context* context, 151 StackWalkKind walk_kind, 152 bool check_suspended = true, 153 bool include_transitions = false) REQUIRES_SHARED(Locks::mutator_lock_)154 REQUIRES_SHARED(Locks::mutator_lock_) { 155 class LambdaStackVisitor : public StackVisitor { 156 public: 157 LambdaStackVisitor(const T& fn, 158 Thread* thread, 159 Context* context, 160 StackWalkKind walk_kind, 161 bool check_suspended = true) 162 : StackVisitor(thread, context, walk_kind, check_suspended), fn_(fn) {} 163 164 bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) { 165 return fn_(this); 166 } 167 168 private: 169 T fn_; 170 }; 171 LambdaStackVisitor visitor(fn, thread, context, walk_kind, check_suspended); 172 visitor.template WalkStack<kCountTransitions>(include_transitions); 173 } 174 GetThread()175 Thread* GetThread() const { 176 return thread_; 177 } 178 179 EXPORT ArtMethod* GetMethod() const REQUIRES_SHARED(Locks::mutator_lock_); 180 181 // Sets this stack frame's method pointer. This requires a full lock of the MutatorLock. This 182 // doesn't work with inlined methods. 183 EXPORT void SetMethod(ArtMethod* method) REQUIRES(Locks::mutator_lock_); 184 GetOuterMethod()185 ArtMethod* GetOuterMethod() const { 186 return *GetCurrentQuickFrame(); 187 } 188 IsShadowFrame()189 bool IsShadowFrame() const { 190 return cur_shadow_frame_ != nullptr; 191 } 192 193 EXPORT uint32_t GetDexPc(bool abort_on_failure = true) const 194 REQUIRES_SHARED(Locks::mutator_lock_); 195 196 // Returns a vector of the inlined dex pcs, in order from outermost to innermost but it replaces 197 // the innermost one with `handler_dex_pc`. In essence, (outermost dex pc, mid dex pc #1, ..., mid 198 // dex pc #n-1, `handler_dex_pc`). 199 std::vector<uint32_t> ComputeDexPcList(uint32_t handler_dex_pc) const 200 REQUIRES_SHARED(Locks::mutator_lock_); 201 202 EXPORT ObjPtr<mirror::Object> GetThisObject() const REQUIRES_SHARED(Locks::mutator_lock_); 203 204 EXPORT size_t GetNativePcOffset() const REQUIRES_SHARED(Locks::mutator_lock_); 205 206 // Returns the height of the stack in the managed stack frames, including transitions. GetFrameHeight()207 size_t GetFrameHeight() REQUIRES_SHARED(Locks::mutator_lock_) { 208 return GetNumFrames() - cur_depth_ - 1; 209 } 210 211 // Returns a frame ID for JDWP use, starting from 1. GetFrameId()212 size_t GetFrameId() REQUIRES_SHARED(Locks::mutator_lock_) { 213 return GetFrameHeight() + 1; 214 } 215 GetNumFrames()216 size_t GetNumFrames() REQUIRES_SHARED(Locks::mutator_lock_) { 217 if (num_frames_ == 0) { 218 num_frames_ = ComputeNumFrames(thread_, walk_kind_); 219 } 220 return num_frames_; 221 } 222 GetFrameDepth()223 size_t GetFrameDepth() const REQUIRES_SHARED(Locks::mutator_lock_) { 224 return cur_depth_; 225 } 226 227 // Get the method and dex pc immediately after the one that's currently being visited. 228 bool GetNextMethodAndDexPc(ArtMethod** next_method, uint32_t* next_dex_pc) 229 REQUIRES_SHARED(Locks::mutator_lock_); 230 231 EXPORT bool GetVReg( 232 ArtMethod* m, 233 uint16_t vreg, 234 VRegKind kind, 235 uint32_t* val, 236 std::optional<DexRegisterLocation> location = std::optional<DexRegisterLocation>(), 237 bool need_full_register_list = false) const REQUIRES_SHARED(Locks::mutator_lock_); 238 239 EXPORT bool GetVRegPair(ArtMethod* m, 240 uint16_t vreg, 241 VRegKind kind_lo, 242 VRegKind kind_hi, 243 uint64_t* val) const REQUIRES_SHARED(Locks::mutator_lock_); 244 245 // Values will be set in debugger shadow frames. Debugger will make sure deoptimization 246 // is triggered to make the values effective. 247 EXPORT bool SetVReg(ArtMethod* m, uint16_t vreg, uint32_t new_value, VRegKind kind) 248 REQUIRES_SHARED(Locks::mutator_lock_); 249 250 // Values will be set in debugger shadow frames. Debugger will make sure deoptimization 251 // is triggered to make the values effective. 252 EXPORT bool SetVRegReference(ArtMethod* m, uint16_t vreg, ObjPtr<mirror::Object> new_value) 253 REQUIRES_SHARED(Locks::mutator_lock_); 254 255 // Values will be set in debugger shadow frames. Debugger will make sure deoptimization 256 // is triggered to make the values effective. 257 EXPORT bool SetVRegPair(ArtMethod* m, 258 uint16_t vreg, 259 uint64_t new_value, 260 VRegKind kind_lo, 261 VRegKind kind_hi) REQUIRES_SHARED(Locks::mutator_lock_); 262 263 uintptr_t* GetGPRAddress(uint32_t reg) const; 264 265 uintptr_t GetReturnPc() const REQUIRES_SHARED(Locks::mutator_lock_); 266 uintptr_t GetReturnPcAddr() const REQUIRES_SHARED(Locks::mutator_lock_); 267 268 void SetReturnPc(uintptr_t new_ret_pc) REQUIRES_SHARED(Locks::mutator_lock_); 269 IsInInlinedFrame()270 bool IsInInlinedFrame() const { 271 return !current_inline_frames_.empty(); 272 } 273 InlineDepth()274 size_t InlineDepth() const { return current_inline_frames_.size(); } 275 GetCurrentInlinedFrame()276 InlineInfo GetCurrentInlinedFrame() const { 277 return current_inline_frames_.back(); 278 } 279 GetCurrentInlinedFrames()280 const BitTableRange<InlineInfo>& GetCurrentInlinedFrames() const { 281 return current_inline_frames_; 282 } 283 GetCurrentQuickFramePc()284 uintptr_t GetCurrentQuickFramePc() const { 285 return cur_quick_frame_pc_; 286 } 287 GetCurrentQuickFrame()288 ArtMethod** GetCurrentQuickFrame() const { 289 return cur_quick_frame_; 290 } 291 GetCurrentShadowFrame()292 ShadowFrame* GetCurrentShadowFrame() const { 293 return cur_shadow_frame_; 294 } 295 296 std::string DescribeLocation() const REQUIRES_SHARED(Locks::mutator_lock_); 297 298 EXPORT static size_t ComputeNumFrames(Thread* thread, StackWalkKind walk_kind) 299 REQUIRES_SHARED(Locks::mutator_lock_); 300 301 static void DescribeStack(Thread* thread) REQUIRES_SHARED(Locks::mutator_lock_); 302 GetCurrentOatQuickMethodHeader()303 const OatQuickMethodHeader* GetCurrentOatQuickMethodHeader() const { 304 return cur_oat_quick_method_header_; 305 } 306 307 QuickMethodFrameInfo GetCurrentQuickFrameInfo() const REQUIRES_SHARED(Locks::mutator_lock_); 308 SetShouldDeoptimizeFlag(DeoptimizeFlagValue value)309 void SetShouldDeoptimizeFlag(DeoptimizeFlagValue value) REQUIRES_SHARED(Locks::mutator_lock_) { 310 uint8_t* should_deoptimize_addr = GetShouldDeoptimizeFlagAddr(); 311 *should_deoptimize_addr = *should_deoptimize_addr | static_cast<uint8_t>(value); 312 }; 313 UnsetShouldDeoptimizeFlag(DeoptimizeFlagValue value)314 void UnsetShouldDeoptimizeFlag(DeoptimizeFlagValue value) REQUIRES_SHARED(Locks::mutator_lock_) { 315 uint8_t* should_deoptimize_addr = GetShouldDeoptimizeFlagAddr(); 316 *should_deoptimize_addr = *should_deoptimize_addr & ~static_cast<uint8_t>(value); 317 }; 318 GetShouldDeoptimizeFlag()319 uint8_t GetShouldDeoptimizeFlag() const REQUIRES_SHARED(Locks::mutator_lock_) { 320 return *GetShouldDeoptimizeFlagAddr(); 321 } 322 ShouldForceDeoptForRedefinition()323 bool ShouldForceDeoptForRedefinition() const REQUIRES_SHARED(Locks::mutator_lock_) { 324 uint8_t should_deopt_flag = GetShouldDeoptimizeFlag(); 325 return (should_deopt_flag & 326 static_cast<uint8_t>(DeoptimizeFlagValue::kForceDeoptForRedefinition)) != 0; 327 } 328 329 // Return the number of dex register in the map from the outermost frame to the number of inlined 330 // frames indicated by `depth`. If `depth` is 0, grab just the registers from the outermost level. 331 // If it is greater than 0, grab as many inline frames as `depth` indicates. 332 size_t GetNumberOfRegisters(CodeInfo* code_info, int depth) const; 333 334 private: 335 // Private constructor known in the case that num_frames_ has already been computed. 336 EXPORT StackVisitor(Thread* thread, 337 Context* context, 338 StackWalkKind walk_kind, 339 size_t num_frames, 340 bool check_suspended = true) REQUIRES_SHARED(Locks::mutator_lock_); 341 IsAccessibleRegister(uint32_t reg,bool is_float)342 bool IsAccessibleRegister(uint32_t reg, bool is_float) const { 343 return is_float ? IsAccessibleFPR(reg) : IsAccessibleGPR(reg); 344 } GetRegister(uint32_t reg,bool is_float)345 uintptr_t GetRegister(uint32_t reg, bool is_float) const { 346 DCHECK(IsAccessibleRegister(reg, is_float)); 347 return is_float ? GetFPR(reg) : GetGPR(reg); 348 } 349 350 bool IsAccessibleGPR(uint32_t reg) const; 351 uintptr_t GetGPR(uint32_t reg) const; 352 353 bool IsAccessibleFPR(uint32_t reg) const; 354 uintptr_t GetFPR(uint32_t reg) const; 355 356 bool GetVRegFromDebuggerShadowFrame(uint16_t vreg, VRegKind kind, uint32_t* val) const 357 REQUIRES_SHARED(Locks::mutator_lock_); 358 bool GetVRegFromOptimizedCode(ArtMethod* m, 359 uint16_t vreg, 360 VRegKind kind, 361 uint32_t* val, 362 bool need_full_register_list = false) const 363 REQUIRES_SHARED(Locks::mutator_lock_); 364 365 bool GetVRegPairFromDebuggerShadowFrame(uint16_t vreg, 366 VRegKind kind_lo, 367 VRegKind kind_hi, 368 uint64_t* val) const 369 REQUIRES_SHARED(Locks::mutator_lock_); 370 bool GetVRegPairFromOptimizedCode(ArtMethod* m, 371 uint16_t vreg, 372 VRegKind kind_lo, 373 VRegKind kind_hi, 374 uint64_t* val) const 375 REQUIRES_SHARED(Locks::mutator_lock_); 376 bool GetVRegFromOptimizedCode(DexRegisterLocation location, uint32_t* val) const 377 REQUIRES_SHARED(Locks::mutator_lock_); 378 379 ShadowFrame* PrepareSetVReg(ArtMethod* m, uint16_t vreg, bool wide) 380 REQUIRES_SHARED(Locks::mutator_lock_); 381 382 void ValidateFrame() const REQUIRES_SHARED(Locks::mutator_lock_); 383 384 ALWAYS_INLINE CodeInfo* GetCurrentInlineInfo() const; 385 ALWAYS_INLINE StackMap* GetCurrentStackMap() const; 386 387 Thread* const thread_; 388 const StackWalkKind walk_kind_; 389 ShadowFrame* cur_shadow_frame_; 390 ArtMethod** cur_quick_frame_; 391 uintptr_t cur_quick_frame_pc_; 392 const OatQuickMethodHeader* cur_oat_quick_method_header_; 393 // Lazily computed, number of frames in the stack. 394 size_t num_frames_; 395 // Depth of the frame we're currently at. 396 size_t cur_depth_; 397 // Current inlined frames of the method we are currently at. 398 // We keep poping frames from the end as we visit the frames. 399 BitTableRange<InlineInfo> current_inline_frames_; 400 401 // Cache the most recently decoded inline info data. 402 // The 'current_inline_frames_' refers to this data, so we need to keep it alive anyway. 403 // Marked mutable since the cache fields are updated from const getters. 404 mutable std::pair<const OatQuickMethodHeader*, CodeInfo> cur_inline_info_; 405 mutable std::pair<uintptr_t, StackMap> cur_stack_map_; 406 407 uint8_t* GetShouldDeoptimizeFlagAddr() const REQUIRES_SHARED(Locks::mutator_lock_); 408 409 protected: 410 Context* const context_; 411 const bool check_suspended_; 412 }; 413 414 } // namespace art 415 416 #endif // ART_RUNTIME_STACK_H_ 417