Home | History | Annotate | Download | only in interpreter
      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.
     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.
     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.
     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 
     93   ~ShadowFrame() {}
     94 
     95   // TODO(iam): Clean references array up since they're always there,
     96   // we don't need to do conditionals.
     97   bool HasReferenceArray() const {
     98     return true;
     99   }
    100 
    101   uint32_t NumberOfVRegs() const {
    102     return number_of_vregs_;
    103   }
    104 
    105   uint32_t GetDexPC() const {
    106     return (dex_pc_ptr_ == nullptr) ? dex_pc_ : dex_pc_ptr_ - dex_instructions_;
    107   }
    108 
    109   int16_t GetCachedHotnessCountdown() const {
    110     return cached_hotness_countdown_;
    111   }
    112 
    113   void SetCachedHotnessCountdown(int16_t cached_hotness_countdown) {
    114     cached_hotness_countdown_ = cached_hotness_countdown;
    115   }
    116 
    117   int16_t GetHotnessCountdown() const {
    118     return hotness_countdown_;
    119   }
    120 
    121   void SetHotnessCountdown(int16_t hotness_countdown) {
    122     hotness_countdown_ = hotness_countdown;
    123   }
    124 
    125   void SetDexPC(uint32_t dex_pc) {
    126     dex_pc_ = dex_pc;
    127     dex_pc_ptr_ = nullptr;
    128   }
    129 
    130   ShadowFrame* GetLink() const {
    131     return link_;
    132   }
    133 
    134   void SetLink(ShadowFrame* frame) {
    135     DCHECK_NE(this, frame);
    136     link_ = frame;
    137   }
    138 
    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.
    146   int16_t GetVRegShort(size_t i) const {
    147     return static_cast<int16_t>(GetVReg(i));
    148   }
    149 
    150   uint32_t* GetVRegAddr(size_t i) {
    151     return &vregs_[i];
    152   }
    153 
    154   uint32_t* GetShadowRefAddr(size_t i) {
    155     DCHECK(HasReferenceArray());
    156     DCHECK_LT(i, NumberOfVRegs());
    157     return &vregs_[i + NumberOfVRegs()];
    158   }
    159 
    160   const uint16_t* GetDexInstructions() const {
    161     return dex_instructions_;
    162   }
    163 
    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 
    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 
    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>
    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.
    202   uint32_t* GetVRegArgs(size_t i) {
    203     return &vregs_[i];
    204   }
    205 
    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 
    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 
    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 
    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 
    258   void SetMethod(ArtMethod* method) REQUIRES(Locks::mutator_lock_) {
    259     DCHECK(method != nullptr);
    260     DCHECK(method_ != nullptr);
    261     method_ = method;
    262   }
    263 
    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 
    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 
    284   LockCountData& GetLockCountData() {
    285     return lock_count_data_;
    286   }
    287 
    288   static constexpr size_t LockCountDataOffset() {
    289     return OFFSETOF_MEMBER(ShadowFrame, lock_count_data_);
    290   }
    291 
    292   static constexpr size_t LinkOffset() {
    293     return OFFSETOF_MEMBER(ShadowFrame, link_);
    294   }
    295 
    296   static constexpr size_t MethodOffset() {
    297     return OFFSETOF_MEMBER(ShadowFrame, method_);
    298   }
    299 
    300   static constexpr size_t DexPCOffset() {
    301     return OFFSETOF_MEMBER(ShadowFrame, dex_pc_);
    302   }
    303 
    304   static constexpr size_t NumberOfVRegsOffset() {
    305     return OFFSETOF_MEMBER(ShadowFrame, number_of_vregs_);
    306   }
    307 
    308   static constexpr size_t VRegsOffset() {
    309     return OFFSETOF_MEMBER(ShadowFrame, vregs_);
    310   }
    311 
    312   static constexpr size_t ResultRegisterOffset() {
    313     return OFFSETOF_MEMBER(ShadowFrame, result_register_);
    314   }
    315 
    316   static constexpr size_t DexPCPtrOffset() {
    317     return OFFSETOF_MEMBER(ShadowFrame, dex_pc_ptr_);
    318   }
    319 
    320   static constexpr size_t DexInstructionsOffset() {
    321     return OFFSETOF_MEMBER(ShadowFrame, dex_instructions_);
    322   }
    323 
    324   static constexpr size_t CachedHotnessCountdownOffset() {
    325     return OFFSETOF_MEMBER(ShadowFrame, cached_hotness_countdown_);
    326   }
    327 
    328   static constexpr size_t HotnessCountdownOffset() {
    329     return OFFSETOF_MEMBER(ShadowFrame, hotness_countdown_);
    330   }
    331 
    332   // Create ShadowFrame for interpreter using provided 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 
    341   const uint16_t* GetDexPCPtr() {
    342     return dex_pc_ptr_;
    343   }
    344 
    345   void SetDexPCPtr(uint16_t* dex_pc_ptr) {
    346     dex_pc_ptr_ = dex_pc_ptr;
    347   }
    348 
    349   JValue* GetResultRegister() {
    350     return result_register_;
    351   }
    352 
    353   bool NeedsNotifyPop() const {
    354     return GetFrameFlag(FrameFlags::kNotifyFramePop);
    355   }
    356 
    357   void SetNotifyPop(bool notify) {
    358     UpdateFrameFlag(notify, FrameFlags::kNotifyFramePop);
    359   }
    360 
    361   bool GetForcePopFrame() const {
    362     return GetFrameFlag(FrameFlags::kForcePopFrame);
    363   }
    364 
    365   void SetForcePopFrame(bool enable) {
    366     UpdateFrameFlag(enable, FrameFlags::kForcePopFrame);
    367   }
    368 
    369   bool GetForceRetryInstruction() const {
    370     return GetFrameFlag(FrameFlags::kForceRetryInst);
    371   }
    372 
    373   void SetForceRetryInstruction(bool enable) {
    374     UpdateFrameFlag(enable, FrameFlags::kForceRetryInst);
    375   }
    376 
    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:
    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 
    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 
    418   bool GetFrameFlag(FrameFlags flag) const {
    419     return (frame_flags_ & static_cast<uint32_t>(flag)) != 0;
    420   }
    421 
    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 
    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 {
    465   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