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