blob: 07078ecb13f87f7c2a484750881aacee9332a928 [file] [log] [blame]
Andreas Gampe513061a2017-06-01 09:17:34 -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_MANAGED_STACK_H_
18#define ART_RUNTIME_MANAGED_STACK_H_
19
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070020#include <cstdint>
Andreas Gampe513061a2017-06-01 09:17:34 -070021#include <cstring>
Andreas Gampe513061a2017-06-01 09:17:34 -070022#include <string>
23
24#include "base/logging.h"
25#include "base/macros.h"
26#include "base/mutex.h"
Vladimir Marko2196c652017-11-30 16:16:07 +000027#include "base/bit_utils.h"
Andreas Gampe513061a2017-06-01 09:17:34 -070028
29namespace art {
30
31namespace mirror {
32class Object;
33} // namespace mirror
34
35class ArtMethod;
36class ShadowFrame;
37template <typename T> class StackReference;
38
39// The managed stack is used to record fragments of managed code stacks. Managed code stacks
40// may either be shadow frames or lists of frames using fixed frame sizes. Transition records are
41// necessary for transitions between code using different frame layouts and transitions into native
42// code.
43class PACKED(4) ManagedStack {
44 public:
45 ManagedStack()
Vladimir Marko2196c652017-11-30 16:16:07 +000046 : tagged_top_quick_frame_(TaggedTopQuickFrame::CreateNotTagged(nullptr)),
47 link_(nullptr),
48 top_shadow_frame_(nullptr) {}
Andreas Gampe513061a2017-06-01 09:17:34 -070049
50 void PushManagedStackFragment(ManagedStack* fragment) {
51 // Copy this top fragment into given fragment.
52 memcpy(fragment, this, sizeof(ManagedStack));
53 // Clear this fragment, which has become the top.
54 memset(this, 0, sizeof(ManagedStack));
55 // Link our top fragment onto the given fragment.
56 link_ = fragment;
57 }
58
59 void PopManagedStackFragment(const ManagedStack& fragment) {
60 DCHECK(&fragment == link_);
61 // Copy this given fragment back to the top.
62 memcpy(this, &fragment, sizeof(ManagedStack));
63 }
64
65 ManagedStack* GetLink() const {
66 return link_;
67 }
68
Vladimir Marko2196c652017-11-30 16:16:07 +000069 ArtMethod** GetTopQuickFrameKnownNotTagged() const {
70 return tagged_top_quick_frame_.GetSpKnownNotTagged();
71 }
72
Andreas Gampe513061a2017-06-01 09:17:34 -070073 ArtMethod** GetTopQuickFrame() const {
Vladimir Marko2196c652017-11-30 16:16:07 +000074 return tagged_top_quick_frame_.GetSp();
75 }
76
77 bool GetTopQuickFrameTag() const {
78 return tagged_top_quick_frame_.GetTag();
79 }
80
81 bool HasTopQuickFrame() const {
82 return tagged_top_quick_frame_.GetTaggedSp() != 0u;
Andreas Gampe513061a2017-06-01 09:17:34 -070083 }
84
85 void SetTopQuickFrame(ArtMethod** top) {
86 DCHECK(top_shadow_frame_ == nullptr);
Vladimir Marko2196c652017-11-30 16:16:07 +000087 DCHECK_ALIGNED(top, 4u);
88 tagged_top_quick_frame_ = TaggedTopQuickFrame::CreateNotTagged(top);
Andreas Gampe513061a2017-06-01 09:17:34 -070089 }
90
Vladimir Marko2196c652017-11-30 16:16:07 +000091 void SetTopQuickFrameTagged(ArtMethod** top) {
92 DCHECK(top_shadow_frame_ == nullptr);
93 DCHECK_ALIGNED(top, 4u);
94 tagged_top_quick_frame_ = TaggedTopQuickFrame::CreateTagged(top);
95 }
96
97 static size_t TaggedTopQuickFrameOffset() {
98 return OFFSETOF_MEMBER(ManagedStack, tagged_top_quick_frame_);
Andreas Gampe513061a2017-06-01 09:17:34 -070099 }
100
101 ALWAYS_INLINE ShadowFrame* PushShadowFrame(ShadowFrame* new_top_frame);
102 ALWAYS_INLINE ShadowFrame* PopShadowFrame();
103
104 ShadowFrame* GetTopShadowFrame() const {
105 return top_shadow_frame_;
106 }
107
Vladimir Marko2196c652017-11-30 16:16:07 +0000108 bool HasTopShadowFrame() const {
109 return GetTopShadowFrame() != nullptr;
110 }
111
Andreas Gampe513061a2017-06-01 09:17:34 -0700112 void SetTopShadowFrame(ShadowFrame* top) {
Vladimir Marko2196c652017-11-30 16:16:07 +0000113 DCHECK_EQ(tagged_top_quick_frame_.GetTaggedSp(), 0u);
Andreas Gampe513061a2017-06-01 09:17:34 -0700114 top_shadow_frame_ = top;
115 }
116
117 static size_t TopShadowFrameOffset() {
118 return OFFSETOF_MEMBER(ManagedStack, top_shadow_frame_);
119 }
120
121 size_t NumJniShadowFrameReferences() const REQUIRES_SHARED(Locks::mutator_lock_);
122
123 bool ShadowFramesContain(StackReference<mirror::Object>* shadow_frame_entry) const;
124
125 private:
Vladimir Marko2196c652017-11-30 16:16:07 +0000126 // Encodes the top quick frame (which must be at least 4-byte aligned)
127 // and a flag that marks the GenericJNI trampoline.
128 class TaggedTopQuickFrame {
129 public:
130 static TaggedTopQuickFrame CreateNotTagged(ArtMethod** sp) {
131 DCHECK_ALIGNED(sp, 4u);
132 return TaggedTopQuickFrame(reinterpret_cast<uintptr_t>(sp));
133 }
134
135 static TaggedTopQuickFrame CreateTagged(ArtMethod** sp) {
136 DCHECK_ALIGNED(sp, 4u);
137 return TaggedTopQuickFrame(reinterpret_cast<uintptr_t>(sp) | 1u);
138 }
139
140 // Get SP known to be not tagged and non-null.
141 ArtMethod** GetSpKnownNotTagged() const {
142 DCHECK(!GetTag());
143 DCHECK_NE(tagged_sp_, 0u);
144 return reinterpret_cast<ArtMethod**>(tagged_sp_);
145 }
146
147 ArtMethod** GetSp() const {
148 return reinterpret_cast<ArtMethod**>(tagged_sp_ & ~static_cast<uintptr_t>(1u));
149 }
150
151 bool GetTag() const {
152 return (tagged_sp_ & 1u) != 0u;
153 }
154
155 uintptr_t GetTaggedSp() const {
156 return tagged_sp_;
157 }
158
159 private:
160 explicit TaggedTopQuickFrame(uintptr_t tagged_sp) : tagged_sp_(tagged_sp) { }
161
162 uintptr_t tagged_sp_;
163 };
164 static_assert(sizeof(TaggedTopQuickFrame) == sizeof(uintptr_t), "TaggedTopQuickFrame size check");
165
166 TaggedTopQuickFrame tagged_top_quick_frame_;
Andreas Gampe513061a2017-06-01 09:17:34 -0700167 ManagedStack* link_;
168 ShadowFrame* top_shadow_frame_;
169};
170
171} // namespace art
172
173#endif // ART_RUNTIME_MANAGED_STACK_H_