blob: 660902142b16deffa48fbaaa7f16f8be11dd4dc9 [file] [log] [blame]
Andreas Gampe36a296f2017-06-13 14:11:11 -07001/*
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
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070020#include <cstdint>
Andreas Gampe36a296f2017-06-13 14:11:11 -070021#include <cstring>
Andreas Gampe36a296f2017-06-13 14:11:11 -070022#include <string>
23
24#include "base/macros.h"
25#include "base/mutex.h"
David Sehr9e734c72018-01-04 17:56:19 -080026#include "dex/dex_file.h"
Andreas Gampe36a296f2017-06-13 14:11:11 -070027#include "lock_count_data.h"
28#include "read_barrier.h"
29#include "stack_reference.h"
30#include "verify_object.h"
31
32namespace art {
33
34namespace mirror {
Igor Murashkin2ffb7032017-11-08 13:35:21 -080035class Object;
Andreas Gampe36a296f2017-06-13 14:11:11 -070036} // namespace mirror
37
38class ArtMethod;
39class ShadowFrame;
Vladimir Marko6ec2a1b2018-05-22 15:33:48 +010040template<class MirrorType> class ObjPtr;
Andreas Gampe36a296f2017-06-13 14:11:11 -070041class Thread;
42union JValue;
43
44// Forward declaration. Just calls the destructor.
45struct ShadowFrameDeleter;
46using ShadowFrameAllocaUniquePtr = std::unique_ptr<ShadowFrame, ShadowFrameDeleter>;
47
48// ShadowFrame has 2 possible layouts:
49// - interpreter - separate VRegs and reference arrays. References are in the reference array.
50// - JNI - just VRegs, but where every VReg holds a reference.
51class ShadowFrame {
Alex Light0aa7a5a2018-10-10 15:58:14 +000052 private:
53 // Used to keep track of extra state the shadowframe has.
54 enum class FrameFlags : uint32_t {
55 // We have been requested to notify when this frame gets popped.
56 kNotifyFramePop = 1 << 0,
57 // We have been asked to pop this frame off the stack as soon as possible.
58 kForcePopFrame = 1 << 1,
59 // We have been asked to re-execute the last instruction.
60 kForceRetryInst = 1 << 2,
61 };
62
Andreas Gampe36a296f2017-06-13 14:11:11 -070063 public:
64 // Compute size of ShadowFrame in bytes assuming it has a reference array.
65 static size_t ComputeSize(uint32_t num_vregs) {
66 return sizeof(ShadowFrame) + (sizeof(uint32_t) * num_vregs) +
67 (sizeof(StackReference<mirror::Object>) * num_vregs);
68 }
69
70 // Create ShadowFrame in heap for deoptimization.
71 static ShadowFrame* CreateDeoptimizedFrame(uint32_t num_vregs, ShadowFrame* link,
72 ArtMethod* method, uint32_t dex_pc) {
73 uint8_t* memory = new uint8_t[ComputeSize(num_vregs)];
74 return CreateShadowFrameImpl(num_vregs, link, method, dex_pc, memory);
75 }
76
77 // Delete a ShadowFrame allocated on the heap for deoptimization.
78 static void DeleteDeoptimizedFrame(ShadowFrame* sf) {
79 sf->~ShadowFrame(); // Explicitly destruct.
80 uint8_t* memory = reinterpret_cast<uint8_t*>(sf);
81 delete[] memory;
82 }
83
84 // Create a shadow frame in a fresh alloca. This needs to be in the context of the caller.
85 // Inlining doesn't work, the compiler will still undo the alloca. So this needs to be a macro.
86#define CREATE_SHADOW_FRAME(num_vregs, link, method, dex_pc) ({ \
87 size_t frame_size = ShadowFrame::ComputeSize(num_vregs); \
88 void* alloca_mem = alloca(frame_size); \
89 ShadowFrameAllocaUniquePtr( \
90 ShadowFrame::CreateShadowFrameImpl((num_vregs), (link), (method), (dex_pc), \
91 (alloca_mem))); \
92 })
93
94 ~ShadowFrame() {}
95
96 // TODO(iam): Clean references array up since they're always there,
97 // we don't need to do conditionals.
98 bool HasReferenceArray() const {
99 return true;
100 }
101
102 uint32_t NumberOfVRegs() const {
103 return number_of_vregs_;
104 }
105
106 uint32_t GetDexPC() const {
Mathieu Chartierfc9555d2017-11-05 16:32:19 -0800107 return (dex_pc_ptr_ == nullptr) ? dex_pc_ : dex_pc_ptr_ - dex_instructions_;
Andreas Gampe36a296f2017-06-13 14:11:11 -0700108 }
109
110 int16_t GetCachedHotnessCountdown() const {
111 return cached_hotness_countdown_;
112 }
113
114 void SetCachedHotnessCountdown(int16_t cached_hotness_countdown) {
115 cached_hotness_countdown_ = cached_hotness_countdown;
116 }
117
118 int16_t GetHotnessCountdown() const {
119 return hotness_countdown_;
120 }
121
122 void SetHotnessCountdown(int16_t hotness_countdown) {
123 hotness_countdown_ = hotness_countdown;
124 }
125
126 void SetDexPC(uint32_t dex_pc) {
127 dex_pc_ = dex_pc;
128 dex_pc_ptr_ = nullptr;
129 }
130
131 ShadowFrame* GetLink() const {
132 return link_;
133 }
134
135 void SetLink(ShadowFrame* frame) {
136 DCHECK_NE(this, frame);
137 link_ = frame;
138 }
139
140 int32_t GetVReg(size_t i) const {
141 DCHECK_LT(i, NumberOfVRegs());
142 const uint32_t* vreg = &vregs_[i];
143 return *reinterpret_cast<const int32_t*>(vreg);
144 }
145
146 // Shorts are extended to Ints in VRegs. Interpreter intrinsics needs them as shorts.
147 int16_t GetVRegShort(size_t i) const {
148 return static_cast<int16_t>(GetVReg(i));
149 }
150
151 uint32_t* GetVRegAddr(size_t i) {
152 return &vregs_[i];
153 }
154
155 uint32_t* GetShadowRefAddr(size_t i) {
156 DCHECK(HasReferenceArray());
157 DCHECK_LT(i, NumberOfVRegs());
158 return &vregs_[i + NumberOfVRegs()];
159 }
160
Mathieu Chartierfc9555d2017-11-05 16:32:19 -0800161 const uint16_t* GetDexInstructions() const {
162 return dex_instructions_;
Andreas Gampe36a296f2017-06-13 14:11:11 -0700163 }
164
165 float GetVRegFloat(size_t i) const {
166 DCHECK_LT(i, NumberOfVRegs());
167 // NOTE: Strict-aliasing?
168 const uint32_t* vreg = &vregs_[i];
169 return *reinterpret_cast<const float*>(vreg);
170 }
171
172 int64_t GetVRegLong(size_t i) const {
David Srbeckyb8e5ad12018-08-31 07:02:02 +0100173 DCHECK_LT(i + 1, NumberOfVRegs());
Andreas Gampe36a296f2017-06-13 14:11:11 -0700174 const uint32_t* vreg = &vregs_[i];
175 typedef const int64_t unaligned_int64 __attribute__ ((aligned (4)));
176 return *reinterpret_cast<unaligned_int64*>(vreg);
177 }
178
179 double GetVRegDouble(size_t i) const {
David Srbeckyb8e5ad12018-08-31 07:02:02 +0100180 DCHECK_LT(i + 1, NumberOfVRegs());
Andreas Gampe36a296f2017-06-13 14:11:11 -0700181 const uint32_t* vreg = &vregs_[i];
182 typedef const double unaligned_double __attribute__ ((aligned (4)));
183 return *reinterpret_cast<unaligned_double*>(vreg);
184 }
185
186 // Look up the reference given its virtual register number.
187 // If this returns non-null then this does not mean the vreg is currently a reference
188 // on non-moving collectors. Check that the raw reg with GetVReg is equal to this if not certain.
189 template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
190 mirror::Object* GetVRegReference(size_t i) const REQUIRES_SHARED(Locks::mutator_lock_) {
191 DCHECK_LT(i, NumberOfVRegs());
192 mirror::Object* ref;
Nicolas Geoffray4cbfadc2018-10-10 16:09:43 +0100193 DCHECK(HasReferenceArray());
194 ref = References()[i].AsMirrorPtr();
Roland Levillaina78f5b62017-09-29 13:50:44 +0100195 ReadBarrier::MaybeAssertToSpaceInvariant(ref);
Andreas Gampe36a296f2017-06-13 14:11:11 -0700196 if (kVerifyFlags & kVerifyReads) {
197 VerifyObject(ref);
198 }
199 return ref;
200 }
201
202 // Get view of vregs as range of consecutive arguments starting at i.
203 uint32_t* GetVRegArgs(size_t i) {
204 return &vregs_[i];
205 }
206
207 void SetVReg(size_t i, int32_t val) {
208 DCHECK_LT(i, NumberOfVRegs());
209 uint32_t* vreg = &vregs_[i];
210 *reinterpret_cast<int32_t*>(vreg) = val;
211 // This is needed for moving collectors since these can update the vreg references if they
212 // happen to agree with references in the reference array.
213 if (kMovingCollector && HasReferenceArray()) {
214 References()[i].Clear();
215 }
216 }
217
218 void SetVRegFloat(size_t i, float val) {
219 DCHECK_LT(i, NumberOfVRegs());
220 uint32_t* vreg = &vregs_[i];
221 *reinterpret_cast<float*>(vreg) = val;
222 // This is needed for moving collectors since these can update the vreg references if they
223 // happen to agree with references in the reference array.
224 if (kMovingCollector && HasReferenceArray()) {
225 References()[i].Clear();
226 }
227 }
228
229 void SetVRegLong(size_t i, int64_t val) {
David Srbeckyb8e5ad12018-08-31 07:02:02 +0100230 DCHECK_LT(i + 1, NumberOfVRegs());
Andreas Gampe36a296f2017-06-13 14:11:11 -0700231 uint32_t* vreg = &vregs_[i];
232 typedef int64_t unaligned_int64 __attribute__ ((aligned (4)));
233 *reinterpret_cast<unaligned_int64*>(vreg) = val;
234 // This is needed for moving collectors since these can update the vreg references if they
235 // happen to agree with references in the reference array.
236 if (kMovingCollector && HasReferenceArray()) {
237 References()[i].Clear();
238 References()[i + 1].Clear();
239 }
240 }
241
242 void SetVRegDouble(size_t i, double val) {
David Srbeckyb8e5ad12018-08-31 07:02:02 +0100243 DCHECK_LT(i + 1, NumberOfVRegs());
Andreas Gampe36a296f2017-06-13 14:11:11 -0700244 uint32_t* vreg = &vregs_[i];
245 typedef double unaligned_double __attribute__ ((aligned (4)));
246 *reinterpret_cast<unaligned_double*>(vreg) = val;
247 // This is needed for moving collectors since these can update the vreg references if they
248 // happen to agree with references in the reference array.
249 if (kMovingCollector && HasReferenceArray()) {
250 References()[i].Clear();
251 References()[i + 1].Clear();
252 }
253 }
254
255 template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
Vladimir Marko6ec2a1b2018-05-22 15:33:48 +0100256 void SetVRegReference(size_t i, ObjPtr<mirror::Object> val)
257 REQUIRES_SHARED(Locks::mutator_lock_);
Andreas Gampe36a296f2017-06-13 14:11:11 -0700258
259 void SetMethod(ArtMethod* method) REQUIRES(Locks::mutator_lock_) {
260 DCHECK(method != nullptr);
261 DCHECK(method_ != nullptr);
262 method_ = method;
263 }
264
265 ArtMethod* GetMethod() const REQUIRES_SHARED(Locks::mutator_lock_) {
266 DCHECK(method_ != nullptr);
267 return method_;
268 }
269
270 mirror::Object* GetThisObject() const REQUIRES_SHARED(Locks::mutator_lock_);
271
272 mirror::Object* GetThisObject(uint16_t num_ins) const REQUIRES_SHARED(Locks::mutator_lock_);
273
274 bool Contains(StackReference<mirror::Object>* shadow_frame_entry_obj) const {
275 if (HasReferenceArray()) {
276 return ((&References()[0] <= shadow_frame_entry_obj) &&
277 (shadow_frame_entry_obj <= (&References()[NumberOfVRegs() - 1])));
278 } else {
279 uint32_t* shadow_frame_entry = reinterpret_cast<uint32_t*>(shadow_frame_entry_obj);
280 return ((&vregs_[0] <= shadow_frame_entry) &&
281 (shadow_frame_entry <= (&vregs_[NumberOfVRegs() - 1])));
282 }
283 }
284
285 LockCountData& GetLockCountData() {
286 return lock_count_data_;
287 }
288
David Srbecky56de89a2018-10-01 15:32:20 +0100289 static constexpr size_t LockCountDataOffset() {
Andreas Gampe36a296f2017-06-13 14:11:11 -0700290 return OFFSETOF_MEMBER(ShadowFrame, lock_count_data_);
291 }
292
David Srbecky56de89a2018-10-01 15:32:20 +0100293 static constexpr size_t LinkOffset() {
Andreas Gampe36a296f2017-06-13 14:11:11 -0700294 return OFFSETOF_MEMBER(ShadowFrame, link_);
295 }
296
David Srbecky56de89a2018-10-01 15:32:20 +0100297 static constexpr size_t MethodOffset() {
Andreas Gampe36a296f2017-06-13 14:11:11 -0700298 return OFFSETOF_MEMBER(ShadowFrame, method_);
299 }
300
David Srbecky56de89a2018-10-01 15:32:20 +0100301 static constexpr size_t DexPCOffset() {
Andreas Gampe36a296f2017-06-13 14:11:11 -0700302 return OFFSETOF_MEMBER(ShadowFrame, dex_pc_);
303 }
304
David Srbecky56de89a2018-10-01 15:32:20 +0100305 static constexpr size_t NumberOfVRegsOffset() {
Andreas Gampe36a296f2017-06-13 14:11:11 -0700306 return OFFSETOF_MEMBER(ShadowFrame, number_of_vregs_);
307 }
308
David Srbecky56de89a2018-10-01 15:32:20 +0100309 static constexpr size_t VRegsOffset() {
Andreas Gampe36a296f2017-06-13 14:11:11 -0700310 return OFFSETOF_MEMBER(ShadowFrame, vregs_);
311 }
312
David Srbecky56de89a2018-10-01 15:32:20 +0100313 static constexpr size_t ResultRegisterOffset() {
Andreas Gampe36a296f2017-06-13 14:11:11 -0700314 return OFFSETOF_MEMBER(ShadowFrame, result_register_);
315 }
316
David Srbecky56de89a2018-10-01 15:32:20 +0100317 static constexpr size_t DexPCPtrOffset() {
Andreas Gampe36a296f2017-06-13 14:11:11 -0700318 return OFFSETOF_MEMBER(ShadowFrame, dex_pc_ptr_);
319 }
320
David Srbecky56de89a2018-10-01 15:32:20 +0100321 static constexpr size_t DexInstructionsOffset() {
Mathieu Chartierfc9555d2017-11-05 16:32:19 -0800322 return OFFSETOF_MEMBER(ShadowFrame, dex_instructions_);
Andreas Gampe36a296f2017-06-13 14:11:11 -0700323 }
324
David Srbecky56de89a2018-10-01 15:32:20 +0100325 static constexpr size_t CachedHotnessCountdownOffset() {
Andreas Gampe36a296f2017-06-13 14:11:11 -0700326 return OFFSETOF_MEMBER(ShadowFrame, cached_hotness_countdown_);
327 }
328
David Srbecky56de89a2018-10-01 15:32:20 +0100329 static constexpr size_t HotnessCountdownOffset() {
Andreas Gampe36a296f2017-06-13 14:11:11 -0700330 return OFFSETOF_MEMBER(ShadowFrame, hotness_countdown_);
331 }
332
333 // Create ShadowFrame for interpreter using provided memory.
334 static ShadowFrame* CreateShadowFrameImpl(uint32_t num_vregs,
335 ShadowFrame* link,
336 ArtMethod* method,
337 uint32_t dex_pc,
338 void* memory) {
339 return new (memory) ShadowFrame(num_vregs, link, method, dex_pc, true);
340 }
341
342 const uint16_t* GetDexPCPtr() {
343 return dex_pc_ptr_;
344 }
345
346 void SetDexPCPtr(uint16_t* dex_pc_ptr) {
347 dex_pc_ptr_ = dex_pc_ptr;
348 }
349
350 JValue* GetResultRegister() {
351 return result_register_;
352 }
353
Alex Lighte814f9d2017-07-31 16:14:39 -0700354 bool NeedsNotifyPop() const {
Alex Light0aa7a5a2018-10-10 15:58:14 +0000355 return GetFrameFlag(FrameFlags::kNotifyFramePop);
Alex Lighte814f9d2017-07-31 16:14:39 -0700356 }
357
358 void SetNotifyPop(bool notify) {
Alex Light0aa7a5a2018-10-10 15:58:14 +0000359 UpdateFrameFlag(notify, FrameFlags::kNotifyFramePop);
360 }
361
362 bool GetForcePopFrame() const {
363 return GetFrameFlag(FrameFlags::kForcePopFrame);
364 }
365
366 void SetForcePopFrame(bool enable) {
367 UpdateFrameFlag(enable, FrameFlags::kForcePopFrame);
368 }
369
370 bool GetForceRetryInstruction() const {
371 return GetFrameFlag(FrameFlags::kForceRetryInst);
372 }
373
374 void SetForceRetryInstruction(bool enable) {
375 UpdateFrameFlag(enable, FrameFlags::kForceRetryInst);
Alex Lighte814f9d2017-07-31 16:14:39 -0700376 }
377
Nicolas Geoffray893147c2018-10-29 14:49:30 +0000378 void CheckConsistentVRegs() const {
379 if (kIsDebugBuild) {
380 // A shadow frame visible to GC requires the following rule: for a given vreg,
381 // its vreg reference equivalent should be the same, or null.
382 for (uint32_t i = 0; i < NumberOfVRegs(); ++i) {
383 int32_t reference_value = References()[i].AsVRegValue();
384 CHECK((GetVReg(i) == reference_value) || (reference_value == 0));
385 }
386 }
387 }
388
Andreas Gampe36a296f2017-06-13 14:11:11 -0700389 private:
390 ShadowFrame(uint32_t num_vregs, ShadowFrame* link, ArtMethod* method,
391 uint32_t dex_pc, bool has_reference_array)
392 : link_(link),
393 method_(method),
394 result_register_(nullptr),
395 dex_pc_ptr_(nullptr),
Mathieu Chartierfc9555d2017-11-05 16:32:19 -0800396 dex_instructions_(nullptr),
Andreas Gampe36a296f2017-06-13 14:11:11 -0700397 number_of_vregs_(num_vregs),
398 dex_pc_(dex_pc),
399 cached_hotness_countdown_(0),
Alex Lighte814f9d2017-07-31 16:14:39 -0700400 hotness_countdown_(0),
Alex Light0aa7a5a2018-10-10 15:58:14 +0000401 frame_flags_(0) {
Andreas Gampe36a296f2017-06-13 14:11:11 -0700402 // TODO(iam): Remove this parameter, it's an an artifact of portable removal
403 DCHECK(has_reference_array);
404 if (has_reference_array) {
405 memset(vregs_, 0, num_vregs * (sizeof(uint32_t) + sizeof(StackReference<mirror::Object>)));
406 } else {
407 memset(vregs_, 0, num_vregs * sizeof(uint32_t));
408 }
409 }
410
Alex Light0aa7a5a2018-10-10 15:58:14 +0000411 void UpdateFrameFlag(bool enable, FrameFlags flag) {
412 if (enable) {
413 frame_flags_ |= static_cast<uint32_t>(flag);
414 } else {
415 frame_flags_ &= ~static_cast<uint32_t>(flag);
416 }
417 }
418
419 bool GetFrameFlag(FrameFlags flag) const {
420 return (frame_flags_ & static_cast<uint32_t>(flag)) != 0;
421 }
422
Andreas Gampe36a296f2017-06-13 14:11:11 -0700423 const StackReference<mirror::Object>* References() const {
424 DCHECK(HasReferenceArray());
425 const uint32_t* vreg_end = &vregs_[NumberOfVRegs()];
426 return reinterpret_cast<const StackReference<mirror::Object>*>(vreg_end);
427 }
428
429 StackReference<mirror::Object>* References() {
430 return const_cast<StackReference<mirror::Object>*>(
431 const_cast<const ShadowFrame*>(this)->References());
432 }
433
434 // Link to previous shadow frame or null.
435 ShadowFrame* link_;
436 ArtMethod* method_;
437 JValue* result_register_;
438 const uint16_t* dex_pc_ptr_;
Mathieu Chartierfc9555d2017-11-05 16:32:19 -0800439 // Dex instruction base of the code item.
440 const uint16_t* dex_instructions_;
Andreas Gampe36a296f2017-06-13 14:11:11 -0700441 LockCountData lock_count_data_; // This may contain GC roots when lock counting is active.
442 const uint32_t number_of_vregs_;
443 uint32_t dex_pc_;
444 int16_t cached_hotness_countdown_;
445 int16_t hotness_countdown_;
Alex Light0aa7a5a2018-10-10 15:58:14 +0000446
447 // This is a set of ShadowFrame::FrameFlags which denote special states this frame is in.
448 // NB alignment requires that this field takes 4 bytes no matter its size. Only 3 bits are
449 // currently used.
450 uint32_t frame_flags_;
Andreas Gampe36a296f2017-06-13 14:11:11 -0700451
452 // This is a two-part array:
453 // - [0..number_of_vregs) holds the raw virtual registers, and each element here is always 4
454 // bytes.
455 // - [number_of_vregs..number_of_vregs*2) holds only reference registers. Each element here is
456 // ptr-sized.
457 // In other words when a primitive is stored in vX, the second (reference) part of the array will
458 // be null. When a reference is stored in vX, the second (reference) part of the array will be a
459 // copy of vX.
460 uint32_t vregs_[0];
461
462 DISALLOW_IMPLICIT_CONSTRUCTORS(ShadowFrame);
463};
464
465struct ShadowFrameDeleter {
466 inline void operator()(ShadowFrame* frame) {
467 if (frame != nullptr) {
468 frame->~ShadowFrame();
469 }
470 }
471};
472
473} // namespace art
474
475#endif // ART_RUNTIME_INTERPRETER_SHADOW_FRAME_H_