Home | History | Annotate | Download | only in runtime
      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 "base/macros.h"
     24 #include "base/mutex.h"
     25 #include "quick/quick_method_frame_info.h"
     26 
     27 namespace art {
     28 
     29 namespace mirror {
     30   class Object;
     31 }  // namespace mirror
     32 
     33 class ArtMethod;
     34 class Context;
     35 class HandleScope;
     36 class OatQuickMethodHeader;
     37 class ShadowFrame;
     38 class Thread;
     39 union JValue;
     40 
     41 // The kind of vreg being accessed in calls to Set/GetVReg.
     42 enum VRegKind {
     43   kReferenceVReg,
     44   kIntVReg,
     45   kFloatVReg,
     46   kLongLoVReg,
     47   kLongHiVReg,
     48   kDoubleLoVReg,
     49   kDoubleHiVReg,
     50   kConstant,
     51   kImpreciseConstant,
     52   kUndefined,
     53 };
     54 std::ostream& operator<<(std::ostream& os, const VRegKind& rhs);
     55 
     56 // Size in bytes of the should_deoptimize flag on stack.
     57 // We just need 4 bytes for our purpose regardless of the architecture. Frame size
     58 // calculation will automatically do alignment for the final frame size.
     59 static constexpr size_t kShouldDeoptimizeFlagSize = 4;
     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   StackVisitor(Thread* thread,
    122                Context* context,
    123                StackWalkKind walk_kind,
    124                bool check_suspended = true);
    125 
    126   bool GetRegisterIfAccessible(uint32_t reg, VRegKind kind, uint32_t* val) const
    127       REQUIRES_SHARED(Locks::mutator_lock_);
    128 
    129  public:
    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 CountTransitions {
    138     kYes,
    139     kNo,
    140   };
    141 
    142   template <CountTransitions kCount = CountTransitions::kYes>
    143   void WalkStack(bool include_transitions = false)
    144       REQUIRES_SHARED(Locks::mutator_lock_);
    145 
    146   Thread* GetThread() const {
    147     return thread_;
    148   }
    149 
    150   ArtMethod* GetMethod() const REQUIRES_SHARED(Locks::mutator_lock_);
    151 
    152   // Sets this stack frame's method pointer. This requires a full lock of the MutatorLock. This
    153   // doesn't work with inlined methods.
    154   void SetMethod(ArtMethod* method) REQUIRES(Locks::mutator_lock_);
    155 
    156   ArtMethod* GetOuterMethod() const {
    157     return *GetCurrentQuickFrame();
    158   }
    159 
    160   bool IsShadowFrame() const {
    161     return cur_shadow_frame_ != nullptr;
    162   }
    163 
    164   uint32_t GetDexPc(bool abort_on_failure = true) const REQUIRES_SHARED(Locks::mutator_lock_);
    165 
    166   mirror::Object* GetThisObject() const REQUIRES_SHARED(Locks::mutator_lock_);
    167 
    168   size_t GetNativePcOffset() const REQUIRES_SHARED(Locks::mutator_lock_);
    169 
    170   // Returns the height of the stack in the managed stack frames, including transitions.
    171   size_t GetFrameHeight() REQUIRES_SHARED(Locks::mutator_lock_) {
    172     return GetNumFrames() - cur_depth_ - 1;
    173   }
    174 
    175   // Returns a frame ID for JDWP use, starting from 1.
    176   size_t GetFrameId() REQUIRES_SHARED(Locks::mutator_lock_) {
    177     return GetFrameHeight() + 1;
    178   }
    179 
    180   size_t GetNumFrames() REQUIRES_SHARED(Locks::mutator_lock_) {
    181     if (num_frames_ == 0) {
    182       num_frames_ = ComputeNumFrames(thread_, walk_kind_);
    183     }
    184     return num_frames_;
    185   }
    186 
    187   size_t GetFrameDepth() const REQUIRES_SHARED(Locks::mutator_lock_) {
    188     return cur_depth_;
    189   }
    190 
    191   // Get the method and dex pc immediately after the one that's currently being visited.
    192   bool GetNextMethodAndDexPc(ArtMethod** next_method, uint32_t* next_dex_pc)
    193       REQUIRES_SHARED(Locks::mutator_lock_);
    194 
    195   bool GetVReg(ArtMethod* m, uint16_t vreg, VRegKind kind, uint32_t* val) const
    196       REQUIRES_SHARED(Locks::mutator_lock_);
    197 
    198   bool GetVRegPair(ArtMethod* m, uint16_t vreg, VRegKind kind_lo, VRegKind kind_hi,
    199                    uint64_t* val) const
    200       REQUIRES_SHARED(Locks::mutator_lock_);
    201 
    202   // Values will be set in debugger shadow frames. Debugger will make sure deoptimization
    203   // is triggered to make the values effective.
    204   bool SetVReg(ArtMethod* m, uint16_t vreg, uint32_t new_value, VRegKind kind)
    205       REQUIRES_SHARED(Locks::mutator_lock_);
    206 
    207   // Values will be set in debugger shadow frames. Debugger will make sure deoptimization
    208   // is triggered to make the values effective.
    209   bool SetVRegPair(ArtMethod* m,
    210                    uint16_t vreg,
    211                    uint64_t new_value,
    212                    VRegKind kind_lo,
    213                    VRegKind kind_hi)
    214       REQUIRES_SHARED(Locks::mutator_lock_);
    215 
    216   uintptr_t* GetGPRAddress(uint32_t reg) const;
    217 
    218   uintptr_t GetReturnPc() const REQUIRES_SHARED(Locks::mutator_lock_);
    219 
    220   void SetReturnPc(uintptr_t new_ret_pc) REQUIRES_SHARED(Locks::mutator_lock_);
    221 
    222   bool IsInInlinedFrame() const {
    223     return current_inlining_depth_ != 0;
    224   }
    225 
    226   size_t GetCurrentInliningDepth() const {
    227     return current_inlining_depth_;
    228   }
    229 
    230   uintptr_t GetCurrentQuickFramePc() const {
    231     return cur_quick_frame_pc_;
    232   }
    233 
    234   ArtMethod** GetCurrentQuickFrame() const {
    235     return cur_quick_frame_;
    236   }
    237 
    238   ShadowFrame* GetCurrentShadowFrame() const {
    239     return cur_shadow_frame_;
    240   }
    241 
    242   HandleScope* GetCurrentHandleScope(size_t pointer_size) const {
    243     ArtMethod** sp = GetCurrentQuickFrame();
    244     // Skip ArtMethod*; handle scope comes next;
    245     return reinterpret_cast<HandleScope*>(reinterpret_cast<uintptr_t>(sp) + pointer_size);
    246   }
    247 
    248   std::string DescribeLocation() const REQUIRES_SHARED(Locks::mutator_lock_);
    249 
    250   static size_t ComputeNumFrames(Thread* thread, StackWalkKind walk_kind)
    251       REQUIRES_SHARED(Locks::mutator_lock_);
    252 
    253   static void DescribeStack(Thread* thread) REQUIRES_SHARED(Locks::mutator_lock_);
    254 
    255   const OatQuickMethodHeader* GetCurrentOatQuickMethodHeader() const {
    256     return cur_oat_quick_method_header_;
    257   }
    258 
    259   QuickMethodFrameInfo GetCurrentQuickFrameInfo() const REQUIRES_SHARED(Locks::mutator_lock_);
    260 
    261  private:
    262   // Private constructor known in the case that num_frames_ has already been computed.
    263   StackVisitor(Thread* thread,
    264                Context* context,
    265                StackWalkKind walk_kind,
    266                size_t num_frames,
    267                bool check_suspended = true)
    268       REQUIRES_SHARED(Locks::mutator_lock_);
    269 
    270   bool IsAccessibleRegister(uint32_t reg, bool is_float) const {
    271     return is_float ? IsAccessibleFPR(reg) : IsAccessibleGPR(reg);
    272   }
    273   uintptr_t GetRegister(uint32_t reg, bool is_float) const {
    274     DCHECK(IsAccessibleRegister(reg, is_float));
    275     return is_float ? GetFPR(reg) : GetGPR(reg);
    276   }
    277 
    278   bool IsAccessibleGPR(uint32_t reg) const;
    279   uintptr_t GetGPR(uint32_t reg) const;
    280 
    281   bool IsAccessibleFPR(uint32_t reg) const;
    282   uintptr_t GetFPR(uint32_t reg) const;
    283 
    284   bool GetVRegFromDebuggerShadowFrame(uint16_t vreg, VRegKind kind, uint32_t* val) const
    285       REQUIRES_SHARED(Locks::mutator_lock_);
    286   bool GetVRegFromOptimizedCode(ArtMethod* m, uint16_t vreg, VRegKind kind,
    287                                 uint32_t* val) const
    288       REQUIRES_SHARED(Locks::mutator_lock_);
    289 
    290   bool GetVRegPairFromDebuggerShadowFrame(uint16_t vreg, VRegKind kind_lo, VRegKind kind_hi,
    291                                           uint64_t* val) const
    292       REQUIRES_SHARED(Locks::mutator_lock_);
    293   bool GetVRegPairFromOptimizedCode(ArtMethod* m, uint16_t vreg,
    294                                     VRegKind kind_lo, VRegKind kind_hi,
    295                                     uint64_t* val) const
    296       REQUIRES_SHARED(Locks::mutator_lock_);
    297   bool GetRegisterPairIfAccessible(uint32_t reg_lo, uint32_t reg_hi, VRegKind kind_lo,
    298                                    uint64_t* val) const
    299       REQUIRES_SHARED(Locks::mutator_lock_);
    300 
    301   void SanityCheckFrame() const REQUIRES_SHARED(Locks::mutator_lock_);
    302 
    303   Thread* const thread_;
    304   const StackWalkKind walk_kind_;
    305   ShadowFrame* cur_shadow_frame_;
    306   ArtMethod** cur_quick_frame_;
    307   uintptr_t cur_quick_frame_pc_;
    308   const OatQuickMethodHeader* cur_oat_quick_method_header_;
    309   // Lazily computed, number of frames in the stack.
    310   size_t num_frames_;
    311   // Depth of the frame we're currently at.
    312   size_t cur_depth_;
    313   // Current inlining depth of the method we are currently at.
    314   // 0 if there is no inlined frame.
    315   size_t current_inlining_depth_;
    316 
    317  protected:
    318   Context* const context_;
    319   const bool check_suspended_;
    320 };
    321 
    322 }  // namespace art
    323 
    324 #endif  // ART_RUNTIME_STACK_H_
    325