blob: 3f6b729644cef8a4c97a10b988ee216695912055 [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
Andreas Gampe7fbc4a52018-11-28 08:26:47 -080024#include "base/locks.h"
Andreas Gampe36a296f2017-06-13 14:11:11 -070025#include "base/macros.h"
Andreas Gampe36a296f2017-06-13 14:11:11 -070026#include "lock_count_data.h"
27#include "read_barrier.h"
28#include "stack_reference.h"
29#include "verify_object.h"
30
31namespace art {
32
33namespace mirror {
Igor Murashkin2ffb7032017-11-08 13:35:21 -080034class Object;
Andreas Gampe36a296f2017-06-13 14:11:11 -070035} // namespace mirror
36
37class ArtMethod;
38class ShadowFrame;
Vladimir Marko6ec2a1b2018-05-22 15:33:48 +010039template<class MirrorType> class ObjPtr;
Andreas Gampe36a296f2017-06-13 14:11:11 -070040class Thread;
41union JValue;
42
43// Forward declaration. Just calls the destructor.
44struct ShadowFrameDeleter;
45using 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.
50class ShadowFrame {
Alex Light0aa7a5a2018-10-10 15:58:14 +000051 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
Andreas Gampe36a296f2017-06-13 14:11:11 -070062 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 {
Mathieu Chartierfc9555d2017-11-05 16:32:19 -0800106 return (dex_pc_ptr_ == nullptr) ? dex_pc_ : dex_pc_ptr_ - dex_instructions_;
Andreas Gampe36a296f2017-06-13 14:11:11 -0700107 }
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
Mathieu Chartierfc9555d2017-11-05 16:32:19 -0800160 const uint16_t* GetDexInstructions() const {
161 return dex_instructions_;
Andreas Gampe36a296f2017-06-13 14:11:11 -0700162 }
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 {
David Srbeckyb8e5ad12018-08-31 07:02:02 +0100172 DCHECK_LT(i + 1, NumberOfVRegs());
Andreas Gampe36a296f2017-06-13 14:11:11 -0700173 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 {
David Srbeckyb8e5ad12018-08-31 07:02:02 +0100179 DCHECK_LT(i + 1, NumberOfVRegs());
Andreas Gampe36a296f2017-06-13 14:11:11 -0700180 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;
Nicolas Geoffray4cbfadc2018-10-10 16:09:43 +0100192 DCHECK(HasReferenceArray());
193 ref = References()[i].AsMirrorPtr();
Roland Levillaina78f5b62017-09-29 13:50:44 +0100194 ReadBarrier::MaybeAssertToSpaceInvariant(ref);
Andreas Gampe36a296f2017-06-13 14:11:11 -0700195 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) {
David Srbeckyb8e5ad12018-08-31 07:02:02 +0100229 DCHECK_LT(i + 1, NumberOfVRegs());
Andreas Gampe36a296f2017-06-13 14:11:11 -0700230 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) {
David Srbeckyb8e5ad12018-08-31 07:02:02 +0100242 DCHECK_LT(i + 1, NumberOfVRegs());
Andreas Gampe36a296f2017-06-13 14:11:11 -0700243 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>
Vladimir Marko6ec2a1b2018-05-22 15:33:48 +0100255 void SetVRegReference(size_t i, ObjPtr<mirror::Object> val)
256 REQUIRES_SHARED(Locks::mutator_lock_);
Andreas Gampe36a296f2017-06-13 14:11:11 -0700257
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
David Srbecky56de89a2018-10-01 15:32:20 +0100288 static constexpr size_t LockCountDataOffset() {
Andreas Gampe36a296f2017-06-13 14:11:11 -0700289 return OFFSETOF_MEMBER(ShadowFrame, lock_count_data_);
290 }
291
David Srbecky56de89a2018-10-01 15:32:20 +0100292 static constexpr size_t LinkOffset() {
Andreas Gampe36a296f2017-06-13 14:11:11 -0700293 return OFFSETOF_MEMBER(ShadowFrame, link_);
294 }
295
David Srbecky56de89a2018-10-01 15:32:20 +0100296 static constexpr size_t MethodOffset() {
Andreas Gampe36a296f2017-06-13 14:11:11 -0700297 return OFFSETOF_MEMBER(ShadowFrame, method_);
298 }
299
David Srbecky56de89a2018-10-01 15:32:20 +0100300 static constexpr size_t DexPCOffset() {
Andreas Gampe36a296f2017-06-13 14:11:11 -0700301 return OFFSETOF_MEMBER(ShadowFrame, dex_pc_);
302 }
303
David Srbecky56de89a2018-10-01 15:32:20 +0100304 static constexpr size_t NumberOfVRegsOffset() {
Andreas Gampe36a296f2017-06-13 14:11:11 -0700305 return OFFSETOF_MEMBER(ShadowFrame, number_of_vregs_);
306 }
307
David Srbecky56de89a2018-10-01 15:32:20 +0100308 static constexpr size_t VRegsOffset() {
Andreas Gampe36a296f2017-06-13 14:11:11 -0700309 return OFFSETOF_MEMBER(ShadowFrame, vregs_);
310 }
311
David Srbecky56de89a2018-10-01 15:32:20 +0100312 static constexpr size_t ResultRegisterOffset() {
Andreas Gampe36a296f2017-06-13 14:11:11 -0700313 return OFFSETOF_MEMBER(ShadowFrame, result_register_);
314 }
315
David Srbecky56de89a2018-10-01 15:32:20 +0100316 static constexpr size_t DexPCPtrOffset() {
Andreas Gampe36a296f2017-06-13 14:11:11 -0700317 return OFFSETOF_MEMBER(ShadowFrame, dex_pc_ptr_);
318 }
319
David Srbecky56de89a2018-10-01 15:32:20 +0100320 static constexpr size_t DexInstructionsOffset() {
Mathieu Chartierfc9555d2017-11-05 16:32:19 -0800321 return OFFSETOF_MEMBER(ShadowFrame, dex_instructions_);
Andreas Gampe36a296f2017-06-13 14:11:11 -0700322 }
323
David Srbecky56de89a2018-10-01 15:32:20 +0100324 static constexpr size_t CachedHotnessCountdownOffset() {
Andreas Gampe36a296f2017-06-13 14:11:11 -0700325 return OFFSETOF_MEMBER(ShadowFrame, cached_hotness_countdown_);
326 }
327
David Srbecky56de89a2018-10-01 15:32:20 +0100328 static constexpr size_t HotnessCountdownOffset() {
Andreas Gampe36a296f2017-06-13 14:11:11 -0700329 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
Alex Lighte814f9d2017-07-31 16:14:39 -0700353 bool NeedsNotifyPop() const {
Alex Light0aa7a5a2018-10-10 15:58:14 +0000354 return GetFrameFlag(FrameFlags::kNotifyFramePop);
Alex Lighte814f9d2017-07-31 16:14:39 -0700355 }
356
357 void SetNotifyPop(bool notify) {
Alex Light0aa7a5a2018-10-10 15:58:14 +0000358 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);
Alex Lighte814f9d2017-07-31 16:14:39 -0700375 }
376
Nicolas Geoffray893147c2018-10-29 14:49:30 +0000377 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
Andreas Gampe36a296f2017-06-13 14:11:11 -0700388 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),
Mathieu Chartierfc9555d2017-11-05 16:32:19 -0800395 dex_instructions_(nullptr),
Andreas Gampe36a296f2017-06-13 14:11:11 -0700396 number_of_vregs_(num_vregs),
397 dex_pc_(dex_pc),
398 cached_hotness_countdown_(0),
Alex Lighte814f9d2017-07-31 16:14:39 -0700399 hotness_countdown_(0),
Alex Light0aa7a5a2018-10-10 15:58:14 +0000400 frame_flags_(0) {
Andreas Gampe36a296f2017-06-13 14:11:11 -0700401 // 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
Alex Light0aa7a5a2018-10-10 15:58:14 +0000410 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
Andreas Gampe36a296f2017-06-13 14:11:11 -0700422 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_;
Mathieu Chartierfc9555d2017-11-05 16:32:19 -0800438 // Dex instruction base of the code item.
439 const uint16_t* dex_instructions_;
Andreas Gampe36a296f2017-06-13 14:11:11 -0700440 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_;
Alex Light0aa7a5a2018-10-10 15:58:14 +0000445
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_;
Andreas Gampe36a296f2017-06-13 14:11:11 -0700450
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
464struct 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_