• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 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_HANDLE_SCOPE_H_
18 #define ART_RUNTIME_HANDLE_SCOPE_H_
19 
20 #include "base/logging.h"
21 #include "base/macros.h"
22 #include "handle.h"
23 #include "stack.h"
24 #include "utils.h"
25 
26 namespace art {
27 namespace mirror {
28 class Object;
29 }
30 
31 class Thread;
32 
33 // HandleScopes are scoped objects containing a number of Handles. They are used to allocate
34 // handles, for these handles (and the objects contained within them) to be visible/roots for the
35 // GC. It is most common to stack allocate HandleScopes using StackHandleScope.
36 class PACKED(4) HandleScope {
37  public:
~HandleScope()38   ~HandleScope() {}
39 
40   // Number of references contained within this handle scope.
NumberOfReferences()41   uint32_t NumberOfReferences() const {
42     return number_of_references_;
43   }
44 
45   // We have versions with and without explicit pointer size of the following. The first two are
46   // used at runtime, so OFFSETOF_MEMBER computes the right offsets automatically. The last one
47   // takes the pointer size explicitly so that at compile time we can cross-compile correctly.
48 
49   // Returns the size of a HandleScope containing num_references handles.
SizeOf(uint32_t num_references)50   static size_t SizeOf(uint32_t num_references) {
51     size_t header_size = sizeof(HandleScope);
52     size_t data_size = sizeof(StackReference<mirror::Object>) * num_references;
53     return header_size + data_size;
54   }
55 
56   // Returns the size of a HandleScope containing num_references handles.
SizeOf(size_t pointer_size,uint32_t num_references)57   static size_t SizeOf(size_t pointer_size, uint32_t num_references) {
58     // Assume that the layout is packed.
59     size_t header_size = pointer_size + sizeof(number_of_references_);
60     size_t data_size = sizeof(StackReference<mirror::Object>) * num_references;
61     return header_size + data_size;
62   }
63 
64   // Link to previous HandleScope or null.
GetLink()65   HandleScope* GetLink() const {
66     return link_;
67   }
68 
SetLink(HandleScope * link)69   void SetLink(HandleScope* link) {
70     DCHECK_NE(this, link);
71     link_ = link;
72   }
73 
74   // Sets the number_of_references_ field for constructing tables out of raw memory. Warning: will
75   // not resize anything.
SetNumberOfReferences(uint32_t num_references)76   void SetNumberOfReferences(uint32_t num_references) {
77     number_of_references_ = num_references;
78   }
79 
GetReference(size_t i)80   mirror::Object* GetReference(size_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
81       ALWAYS_INLINE {
82     DCHECK_LT(i, number_of_references_);
83     return references_[i].AsMirrorPtr();
84   }
85 
GetHandle(size_t i)86   Handle<mirror::Object> GetHandle(size_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
87       ALWAYS_INLINE {
88     DCHECK_LT(i, number_of_references_);
89     return Handle<mirror::Object>(&references_[i]);
90   }
91 
SetReference(size_t i,mirror::Object * object)92   void SetReference(size_t i, mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
93       ALWAYS_INLINE {
94     DCHECK_LT(i, number_of_references_);
95     references_[i].Assign(object);
96   }
97 
Contains(StackReference<mirror::Object> * handle_scope_entry)98   bool Contains(StackReference<mirror::Object>* handle_scope_entry) const {
99     // A HandleScope should always contain something. One created by the
100     // jni_compiler should have a jobject/jclass as a native method is
101     // passed in a this pointer or a class
102     DCHECK_GT(number_of_references_, 0U);
103     return &references_[0] <= handle_scope_entry &&
104         handle_scope_entry <= &references_[number_of_references_ - 1];
105   }
106 
107   // Offset of link within HandleScope, used by generated code
LinkOffset(size_t pointer_size)108   static size_t LinkOffset(size_t pointer_size) {
109     return 0;
110   }
111 
112   // Offset of length within handle scope, used by generated code
NumberOfReferencesOffset(size_t pointer_size)113   static size_t NumberOfReferencesOffset(size_t pointer_size) {
114     return pointer_size;
115   }
116 
117   // Offset of link within handle scope, used by generated code
ReferencesOffset(size_t pointer_size)118   static size_t ReferencesOffset(size_t pointer_size) {
119     return pointer_size + sizeof(number_of_references_);
120   }
121 
122  protected:
HandleScope(size_t number_of_references)123   explicit HandleScope(size_t number_of_references) :
124       link_(nullptr), number_of_references_(number_of_references) {
125   }
126 
127   HandleScope* link_;
128   uint32_t number_of_references_;
129 
130   // number_of_references_ are available if this is allocated and filled in by jni_compiler.
131   StackReference<mirror::Object> references_[0];
132 
133  private:
134   template<size_t kNumReferences> friend class StackHandleScope;
135 
136   DISALLOW_COPY_AND_ASSIGN(HandleScope);
137 };
138 
139 // A wrapper which wraps around Object** and restores the pointer in the destructor.
140 // TODO: Add more functionality.
141 template<class T>
142 class HandleWrapper : public Handle<T> {
143  public:
HandleWrapper(T ** obj,const Handle<T> & handle)144   HandleWrapper(T** obj, const Handle<T>& handle)
145      : Handle<T>(handle), obj_(obj) {
146   }
147 
~HandleWrapper()148   ~HandleWrapper() {
149     *obj_ = Handle<T>::Get();
150   }
151 
152  private:
153   T** obj_;
154 };
155 
156 // Scoped handle storage of a fixed size that is usually stack allocated.
157 template<size_t kNumReferences>
158 class PACKED(4) StackHandleScope FINAL : public HandleScope {
159  public:
160   explicit StackHandleScope(Thread* self);
161   ~StackHandleScope();
162 
163   // Currently unused, using this GetReference instead of the one in HandleScope is preferred to
164   // avoid compiler optimizations incorrectly optimizing out of bound array accesses.
165   // TODO: Remove this when it is un-necessary.
GetReference(size_t i)166   mirror::Object* GetReference(size_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
167       ALWAYS_INLINE {
168     DCHECK_LT(i, number_of_references_);
169     return references_storage_[i].AsMirrorPtr();
170   }
171 
GetHandle(size_t i)172   Handle<mirror::Object> GetHandle(size_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
173       ALWAYS_INLINE {
174     DCHECK_LT(i, number_of_references_);
175     return Handle<mirror::Object>(&references_storage_[i]);
176   }
177 
SetReference(size_t i,mirror::Object * object)178   void SetReference(size_t i, mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
179       ALWAYS_INLINE {
180     DCHECK_LT(i, number_of_references_);
181     references_storage_[i].Assign(object);
182   }
183 
184   template<class T>
NewHandle(T * object)185   Handle<T> NewHandle(T* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
186     SetReference(pos_, object);
187     Handle<T> h(GetHandle(pos_));
188     pos_++;
189     return h;
190   }
191 
192   template<class T>
NewHandleWrapper(T ** object)193   HandleWrapper<T> NewHandleWrapper(T** object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
194     SetReference(pos_, *object);
195     Handle<T> h(GetHandle(pos_));
196     pos_++;
197     return HandleWrapper<T>(object, h);
198   }
199 
200  private:
201   // References_storage_ needs to be first so that it appears in the same location as
202   // HandleScope::references_.
203   StackReference<mirror::Object> references_storage_[kNumReferences];
204 
205   // The thread that the stack handle scope is a linked list upon. The stack handle scope will
206   // push and pop itself from this thread.
207   Thread* const self_;
208 
209   // Position new handles will be created.
210   size_t pos_;
211 
212   template<size_t kNumRefs> friend class StackHandleScope;
213 };
214 
215 }  // namespace art
216 
217 #endif  // ART_RUNTIME_HANDLE_SCOPE_H_
218