Mercurial > hg > truffle
comparison src/share/vm/runtime/handles.hpp @ 0:a61af66fc99e jdk7-b24
Initial load
author | duke |
---|---|
date | Sat, 01 Dec 2007 00:00:00 +0000 |
parents | |
children | c89f86385056 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:a61af66fc99e |
---|---|
1 /* | |
2 * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. | |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
20 * CA 95054 USA or visit www.sun.com if you need additional information or | |
21 * have any questions. | |
22 * | |
23 */ | |
24 | |
25 //------------------------------------------------------------------------------------------------------------------------ | |
26 // In order to preserve oops during garbage collection, they should be | |
27 // allocated and passed around via Handles within the VM. A handle is | |
28 // simply an extra indirection allocated in a thread local handle area. | |
29 // | |
30 // A handle is a ValueObj, so it can be passed around as a value, can | |
31 // be used as a parameter w/o using &-passing, and can be returned as a | |
32 // return value. | |
33 // | |
34 // oop parameters and return types should be Handles whenever feasible. | |
35 // | |
36 // Handles are declared in a straight-forward manner, e.g. | |
37 // | |
38 // oop obj = ...; | |
39 // Handle h1(obj); // allocate new handle | |
40 // Handle h2(thread, obj); // faster allocation when current thread is known | |
41 // Handle h3; // declare handle only, no allocation occurs | |
42 // ... | |
43 // h3 = h1; // make h3 refer to same indirection as h1 | |
44 // oop obj2 = h2(); // get handle value | |
45 // h1->print(); // invoking operation on oop | |
46 // | |
47 // Handles are specialized for different oop types to provide extra type | |
48 // information and avoid unnecessary casting. For each oop type xxxOop | |
49 // there is a corresponding handle called xxxHandle, e.g. | |
50 // | |
51 // oop Handle | |
52 // methodOop methodHandle | |
53 // instanceOop instanceHandle | |
54 // | |
55 // For klassOops, it is often useful to model the Klass hierarchy in order | |
56 // to get access to the klass_part without casting. For each xxxKlass there | |
57 // is a corresponding handle called xxxKlassHandle, e.g. | |
58 // | |
59 // klassOop Klass KlassHandle | |
60 // klassOop methodKlass methodKlassHandle | |
61 // klassOop instanceKlass instanceKlassHandle | |
62 // | |
63 | |
64 //------------------------------------------------------------------------------------------------------------------------ | |
65 // Base class for all handles. Provides overloading of frequently | |
66 // used operators for ease of use. | |
67 | |
68 class Handle VALUE_OBJ_CLASS_SPEC { | |
69 private: | |
70 oop* _handle; | |
71 | |
72 protected: | |
73 oop obj() const { return _handle == NULL ? (oop)NULL : *_handle; } | |
74 oop non_null_obj() const { assert(_handle != NULL, "resolving NULL handle"); return *_handle; } | |
75 | |
76 public: | |
77 // Constructors | |
78 Handle() { _handle = NULL; } | |
79 Handle(oop obj); | |
80 #ifndef ASSERT | |
81 Handle(Thread* thread, oop obj); | |
82 #else | |
83 // Don't inline body with assert for current thread | |
84 Handle(Thread* thread, oop obj); | |
85 #endif // ASSERT | |
86 | |
87 // General access | |
88 oop operator () () const { return obj(); } | |
89 oop operator -> () const { return non_null_obj(); } | |
90 bool operator == (oop o) const { return obj() == o; } | |
91 bool operator == (const Handle& h) const { return obj() == h.obj(); } | |
92 | |
93 // Null checks | |
94 bool is_null() const { return _handle == NULL; } | |
95 bool not_null() const { return _handle != NULL; } | |
96 | |
97 // Debugging | |
98 void print() { obj()->print(); } | |
99 | |
100 // Direct interface, use very sparingly. | |
101 // Used by JavaCalls to quickly convert handles and to create handles static data structures. | |
102 // Constructor takes a dummy argument to prevent unintentional type conversion in C++. | |
103 Handle(oop *handle, bool dummy) { _handle = handle; } | |
104 | |
105 // Raw handle access. Allows easy duplication of Handles. This can be very unsafe | |
106 // since duplicates is only valid as long as original handle is alive. | |
107 oop* raw_value() { return _handle; } | |
108 static oop raw_resolve(oop *handle) { return handle == NULL ? (oop)NULL : *handle; } | |
109 }; | |
110 | |
111 | |
112 //------------------------------------------------------------------------------------------------------------------------ | |
113 // Base class for Handles containing klassOops. Provides overloading of frequently | |
114 // used operators for ease of use and typed access to the Klass part. | |
115 class KlassHandle: public Handle { | |
116 protected: | |
117 klassOop obj() const { return (klassOop)Handle::obj(); } | |
118 klassOop non_null_obj() const { return (klassOop)Handle::non_null_obj(); } | |
119 Klass* as_klass() const { return non_null_obj()->klass_part(); } | |
120 | |
121 public: | |
122 // Constructors | |
123 KlassHandle () : Handle() {} | |
124 KlassHandle (oop obj) : Handle(obj) { | |
125 assert(SharedSkipVerify || is_null() || obj->is_klass(), "not a klassOop"); | |
126 } | |
127 KlassHandle (Klass* kl) : Handle(kl ? kl->as_klassOop() : (klassOop)NULL) { | |
128 assert(SharedSkipVerify || is_null() || obj()->is_klass(), "not a klassOop"); | |
129 } | |
130 | |
131 // Faster versions passing Thread | |
132 KlassHandle (Thread* thread, oop obj) : Handle(thread, obj) { | |
133 assert(SharedSkipVerify || is_null() || obj->is_klass(), "not a klassOop"); | |
134 } | |
135 KlassHandle (Thread *thread, Klass* kl) | |
136 : Handle(thread, kl ? kl->as_klassOop() : (klassOop)NULL) { | |
137 assert(is_null() || obj()->is_klass(), "not a klassOop"); | |
138 } | |
139 | |
140 // General access | |
141 klassOop operator () () const { return obj(); } | |
142 Klass* operator -> () const { return as_klass(); } | |
143 }; | |
144 | |
145 | |
146 //------------------------------------------------------------------------------------------------------------------------ | |
147 // Specific Handles for different oop types | |
148 #define DEF_HANDLE(type, is_a) \ | |
149 class type##Handle; \ | |
150 class type##Handle: public Handle { \ | |
151 protected: \ | |
152 type##Oop obj() const { return (type##Oop)Handle::obj(); } \ | |
153 type##Oop non_null_obj() const { return (type##Oop)Handle::non_null_obj(); } \ | |
154 \ | |
155 public: \ | |
156 /* Constructors */ \ | |
157 type##Handle () : Handle() {} \ | |
158 type##Handle (type##Oop obj) : Handle((oop)obj) { \ | |
159 assert(SharedSkipVerify || is_null() || ((oop)obj)->is_a(), \ | |
160 "illegal type"); \ | |
161 } \ | |
162 type##Handle (Thread* thread, type##Oop obj) : Handle(thread, (oop)obj) { \ | |
163 assert(SharedSkipVerify || is_null() || ((oop)obj)->is_a(), "illegal type"); \ | |
164 } \ | |
165 \ | |
166 /* Special constructor, use sparingly */ \ | |
167 type##Handle (type##Oop *handle, bool dummy) : Handle((oop*)handle, dummy) {} \ | |
168 \ | |
169 /* Operators for ease of use */ \ | |
170 type##Oop operator () () const { return obj(); } \ | |
171 type##Oop operator -> () const { return non_null_obj(); } \ | |
172 }; | |
173 | |
174 | |
175 DEF_HANDLE(instance , is_instance ) | |
176 DEF_HANDLE(method , is_method ) | |
177 DEF_HANDLE(constMethod , is_constMethod ) | |
178 DEF_HANDLE(methodData , is_methodData ) | |
179 DEF_HANDLE(array , is_array ) | |
180 DEF_HANDLE(constantPool , is_constantPool ) | |
181 DEF_HANDLE(constantPoolCache, is_constantPoolCache) | |
182 DEF_HANDLE(objArray , is_objArray ) | |
183 DEF_HANDLE(typeArray , is_typeArray ) | |
184 DEF_HANDLE(symbol , is_symbol ) | |
185 | |
186 //------------------------------------------------------------------------------------------------------------------------ | |
187 // Specific KlassHandles for different Klass types | |
188 | |
189 #define DEF_KLASS_HANDLE(type, is_a) \ | |
190 class type##Handle : public KlassHandle { \ | |
191 public: \ | |
192 /* Constructors */ \ | |
193 type##Handle () : KlassHandle() {} \ | |
194 type##Handle (klassOop obj) : KlassHandle(obj) { \ | |
195 assert(SharedSkipVerify || is_null() || obj->klass_part()->is_a(), \ | |
196 "illegal type"); \ | |
197 } \ | |
198 type##Handle (Thread* thread, klassOop obj) : KlassHandle(thread, obj) { \ | |
199 assert(SharedSkipVerify || is_null() || obj->klass_part()->is_a(), \ | |
200 "illegal type"); \ | |
201 } \ | |
202 \ | |
203 /* Access to klass part */ \ | |
204 type* operator -> () const { return (type*)obj()->klass_part(); } \ | |
205 \ | |
206 static type##Handle cast(KlassHandle h) { return type##Handle(h()); } \ | |
207 \ | |
208 }; | |
209 | |
210 | |
211 DEF_KLASS_HANDLE(instanceKlass , oop_is_instance_slow ) | |
212 DEF_KLASS_HANDLE(methodKlass , oop_is_method ) | |
213 DEF_KLASS_HANDLE(constMethodKlass , oop_is_constMethod ) | |
214 DEF_KLASS_HANDLE(klassKlass , oop_is_klass ) | |
215 DEF_KLASS_HANDLE(arrayKlassKlass , oop_is_arrayKlass ) | |
216 DEF_KLASS_HANDLE(objArrayKlassKlass , oop_is_objArrayKlass ) | |
217 DEF_KLASS_HANDLE(typeArrayKlassKlass , oop_is_typeArrayKlass) | |
218 DEF_KLASS_HANDLE(arrayKlass , oop_is_array ) | |
219 DEF_KLASS_HANDLE(typeArrayKlass , oop_is_typeArray_slow) | |
220 DEF_KLASS_HANDLE(objArrayKlass , oop_is_objArray_slow ) | |
221 DEF_KLASS_HANDLE(symbolKlass , oop_is_symbol ) | |
222 DEF_KLASS_HANDLE(constantPoolKlass , oop_is_constantPool ) | |
223 DEF_KLASS_HANDLE(constantPoolCacheKlass, oop_is_constantPool ) | |
224 | |
225 | |
226 //------------------------------------------------------------------------------------------------------------------------ | |
227 // Thread local handle area | |
228 | |
229 class HandleArea: public Arena { | |
230 friend class HandleMark; | |
231 friend class NoHandleMark; | |
232 friend class ResetNoHandleMark; | |
233 #ifdef ASSERT | |
234 int _handle_mark_nesting; | |
235 int _no_handle_mark_nesting; | |
236 #endif | |
237 HandleArea* _prev; // link to outer (older) area | |
238 public: | |
239 // Constructor | |
240 HandleArea(HandleArea* prev) { | |
241 debug_only(_handle_mark_nesting = 0); | |
242 debug_only(_no_handle_mark_nesting = 0); | |
243 _prev = prev; | |
244 } | |
245 | |
246 // Handle allocation | |
247 private: | |
248 oop* real_allocate_handle(oop obj) { | |
249 #ifdef ASSERT | |
250 oop* handle = (oop*) (UseMallocOnly ? internal_malloc_4(oopSize) : Amalloc_4(oopSize)); | |
251 #else | |
252 oop* handle = (oop*) Amalloc_4(oopSize); | |
253 #endif | |
254 *handle = obj; | |
255 return handle; | |
256 } | |
257 public: | |
258 #ifdef ASSERT | |
259 oop* allocate_handle(oop obj); | |
260 #else | |
261 oop* allocate_handle(oop obj) { return real_allocate_handle(obj); } | |
262 #endif | |
263 | |
264 // Garbage collection support | |
265 void oops_do(OopClosure* f); | |
266 | |
267 // Number of handles in use | |
268 size_t used() const { return Arena::used() / oopSize; } | |
269 | |
270 debug_only(bool no_handle_mark_active() { return _no_handle_mark_nesting > 0; }) | |
271 }; | |
272 | |
273 | |
274 //------------------------------------------------------------------------------------------------------------------------ | |
275 // Handles are allocated in a (growable) thread local handle area. Deallocation | |
276 // is managed using a HandleMark. It should normally not be necessary to use | |
277 // HandleMarks manually. | |
278 // | |
279 // A HandleMark constructor will record the current handle area top, and the | |
280 // desctructor will reset the top, destroying all handles allocated in between. | |
281 // The following code will therefore NOT work: | |
282 // | |
283 // Handle h; | |
284 // { | |
285 // HandleMark hm; | |
286 // h = Handle(obj); | |
287 // } | |
288 // h()->print(); // WRONG, h destroyed by HandleMark destructor. | |
289 // | |
290 // If h has to be preserved, it can be converted to an oop or a local JNI handle | |
291 // across the HandleMark boundary. | |
292 | |
293 // The base class of HandleMark should have been StackObj but we also heap allocate | |
294 // a HandleMark when a thread is created. | |
295 | |
296 class HandleMark { | |
297 private: | |
298 Thread *_thread; // thread that owns this mark | |
299 HandleArea *_area; // saved handle area | |
300 Chunk *_chunk; // saved arena chunk | |
301 char *_hwm, *_max; // saved arena info | |
302 NOT_PRODUCT(size_t _size_in_bytes;) // size of handle area | |
303 // Link to previous active HandleMark in thread | |
304 HandleMark* _previous_handle_mark; | |
305 | |
306 void initialize(Thread* thread); // common code for constructors | |
307 void set_previous_handle_mark(HandleMark* mark) { _previous_handle_mark = mark; } | |
308 HandleMark* previous_handle_mark() const { return _previous_handle_mark; } | |
309 | |
310 public: | |
311 HandleMark(); // see handles_inline.hpp | |
312 HandleMark(Thread* thread) { initialize(thread); } | |
313 ~HandleMark(); | |
314 | |
315 // Functions used by HandleMarkCleaner | |
316 // called in the constructor of HandleMarkCleaner | |
317 void push(); | |
318 // called in the destructor of HandleMarkCleaner | |
319 void pop_and_restore(); | |
320 }; | |
321 | |
322 //------------------------------------------------------------------------------------------------------------------------ | |
323 // A NoHandleMark stack object will verify that no handles are allocated | |
324 // in its scope. Enabled in debug mode only. | |
325 | |
326 class NoHandleMark: public StackObj { | |
327 public: | |
328 #ifdef ASSERT | |
329 NoHandleMark(); | |
330 ~NoHandleMark(); | |
331 #else | |
332 NoHandleMark() {} | |
333 ~NoHandleMark() {} | |
334 #endif | |
335 }; | |
336 | |
337 | |
338 class ResetNoHandleMark: public StackObj { | |
339 int _no_handle_mark_nesting; | |
340 public: | |
341 #ifdef ASSERT | |
342 ResetNoHandleMark(); | |
343 ~ResetNoHandleMark(); | |
344 #else | |
345 ResetNoHandleMark() {} | |
346 ~ResetNoHandleMark() {} | |
347 #endif | |
348 }; |