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