blob: d1c230fd8f7ae6ca4b8504d625c59085725cb698 [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
Andreas Gampe57943812017-12-06 21:39:13 -080024#include <android-base/logging.h>
25
Andreas Gampe513061a2017-06-01 09:17:34 -070026#include "base/macros.h"
27#include "base/mutex.h"
Vladimir Marko2196c652017-11-30 16:16:07 +000028#include "base/bit_utils.h"
Andreas Gampe513061a2017-06-01 09:17:34 -070029
30namespace art {
31
32namespace mirror {
33class Object;
34} // namespace mirror
35
36class ArtMethod;
37class ShadowFrame;
38template <typename T> class StackReference;
39
40// The managed stack is used to record fragments of managed code stacks. Managed code stacks
41// may either be shadow frames or lists of frames using fixed frame sizes. Transition records are
42// necessary for transitions between code using different frame layouts and transitions into native
43// code.
44class PACKED(4) ManagedStack {
45 public:
46 ManagedStack()
Vladimir Marko2196c652017-11-30 16:16:07 +000047 : tagged_top_quick_frame_(TaggedTopQuickFrame::CreateNotTagged(nullptr)),
48 link_(nullptr),
49 top_shadow_frame_(nullptr) {}
Andreas Gampe513061a2017-06-01 09:17:34 -070050
51 void PushManagedStackFragment(ManagedStack* fragment) {
52 // Copy this top fragment into given fragment.
53 memcpy(fragment, this, sizeof(ManagedStack));
54 // Clear this fragment, which has become the top.
55 memset(this, 0, sizeof(ManagedStack));
56 // Link our top fragment onto the given fragment.
57 link_ = fragment;
58 }
59
60 void PopManagedStackFragment(const ManagedStack& fragment) {
61 DCHECK(&fragment == link_);
62 // Copy this given fragment back to the top.
63 memcpy(this, &fragment, sizeof(ManagedStack));
64 }
65
66 ManagedStack* GetLink() const {
67 return link_;
68 }
69
Vladimir Marko2196c652017-11-30 16:16:07 +000070 ArtMethod** GetTopQuickFrameKnownNotTagged() const {
71 return tagged_top_quick_frame_.GetSpKnownNotTagged();
72 }
73
Andreas Gampe513061a2017-06-01 09:17:34 -070074 ArtMethod** GetTopQuickFrame() const {
Vladimir Marko2196c652017-11-30 16:16:07 +000075 return tagged_top_quick_frame_.GetSp();
76 }
77
78 bool GetTopQuickFrameTag() const {
79 return tagged_top_quick_frame_.GetTag();
80 }
81
82 bool HasTopQuickFrame() const {
83 return tagged_top_quick_frame_.GetTaggedSp() != 0u;
Andreas Gampe513061a2017-06-01 09:17:34 -070084 }
85
86 void SetTopQuickFrame(ArtMethod** top) {
87 DCHECK(top_shadow_frame_ == nullptr);
Vladimir Marko2196c652017-11-30 16:16:07 +000088 DCHECK_ALIGNED(top, 4u);
89 tagged_top_quick_frame_ = TaggedTopQuickFrame::CreateNotTagged(top);
Andreas Gampe513061a2017-06-01 09:17:34 -070090 }
91
Vladimir Marko2196c652017-11-30 16:16:07 +000092 void SetTopQuickFrameTagged(ArtMethod** top) {
93 DCHECK(top_shadow_frame_ == nullptr);
94 DCHECK_ALIGNED(top, 4u);
95 tagged_top_quick_frame_ = TaggedTopQuickFrame::CreateTagged(top);
96 }
97
98 static size_t TaggedTopQuickFrameOffset() {
99 return OFFSETOF_MEMBER(ManagedStack, tagged_top_quick_frame_);
Andreas Gampe513061a2017-06-01 09:17:34 -0700100 }
101
102 ALWAYS_INLINE ShadowFrame* PushShadowFrame(ShadowFrame* new_top_frame);
103 ALWAYS_INLINE ShadowFrame* PopShadowFrame();
104
105 ShadowFrame* GetTopShadowFrame() const {
106 return top_shadow_frame_;
107 }
108
Vladimir Marko2196c652017-11-30 16:16:07 +0000109 bool HasTopShadowFrame() const {
110 return GetTopShadowFrame() != nullptr;
111 }
112
Andreas Gampe513061a2017-06-01 09:17:34 -0700113 void SetTopShadowFrame(ShadowFrame* top) {
Vladimir Marko2196c652017-11-30 16:16:07 +0000114 DCHECK_EQ(tagged_top_quick_frame_.GetTaggedSp(), 0u);
Andreas Gampe513061a2017-06-01 09:17:34 -0700115 top_shadow_frame_ = top;
116 }
117
118 static size_t TopShadowFrameOffset() {
119 return OFFSETOF_MEMBER(ManagedStack, top_shadow_frame_);
120 }
121
122 size_t NumJniShadowFrameReferences() const REQUIRES_SHARED(Locks::mutator_lock_);
123
124 bool ShadowFramesContain(StackReference<mirror::Object>* shadow_frame_entry) const;
125
126 private:
Vladimir Marko2196c652017-11-30 16:16:07 +0000127 // Encodes the top quick frame (which must be at least 4-byte aligned)
128 // and a flag that marks the GenericJNI trampoline.
129 class TaggedTopQuickFrame {
130 public:
131 static TaggedTopQuickFrame CreateNotTagged(ArtMethod** sp) {
132 DCHECK_ALIGNED(sp, 4u);
133 return TaggedTopQuickFrame(reinterpret_cast<uintptr_t>(sp));
134 }
135
136 static TaggedTopQuickFrame CreateTagged(ArtMethod** sp) {
137 DCHECK_ALIGNED(sp, 4u);
138 return TaggedTopQuickFrame(reinterpret_cast<uintptr_t>(sp) | 1u);
139 }
140
141 // Get SP known to be not tagged and non-null.
142 ArtMethod** GetSpKnownNotTagged() const {
143 DCHECK(!GetTag());
144 DCHECK_NE(tagged_sp_, 0u);
145 return reinterpret_cast<ArtMethod**>(tagged_sp_);
146 }
147
148 ArtMethod** GetSp() const {
149 return reinterpret_cast<ArtMethod**>(tagged_sp_ & ~static_cast<uintptr_t>(1u));
150 }
151
152 bool GetTag() const {
153 return (tagged_sp_ & 1u) != 0u;
154 }
155
156 uintptr_t GetTaggedSp() const {
157 return tagged_sp_;
158 }
159
160 private:
161 explicit TaggedTopQuickFrame(uintptr_t tagged_sp) : tagged_sp_(tagged_sp) { }
162
163 uintptr_t tagged_sp_;
164 };
165 static_assert(sizeof(TaggedTopQuickFrame) == sizeof(uintptr_t), "TaggedTopQuickFrame size check");
166
167 TaggedTopQuickFrame tagged_top_quick_frame_;
Andreas Gampe513061a2017-06-01 09:17:34 -0700168 ManagedStack* link_;
169 ShadowFrame* top_shadow_frame_;
170};
171
172} // namespace art
173
174#endif // ART_RUNTIME_MANAGED_STACK_H_