1 /*
2 * Copyright (c) 1997, 2024, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #ifndef SHARE_RUNTIME_HANDLES_HPP
26 #define SHARE_RUNTIME_HANDLES_HPP
27
28 #include "memory/arena.hpp"
29 #include "oops/oop.hpp"
30 #include "oops/oopsHierarchy.hpp"
31
32 class InlineKlass;
33 class InstanceKlass;
34 class Klass;
35 class Thread;
36
37 //------------------------------------------------------------------------------------------------------------------------
38 // In order to preserve oops during garbage collection, they should be
39 // allocated and passed around via Handles within the VM. A handle is
40 // simply an extra indirection allocated in a thread local handle area.
41 //
42 // A handle is a value object, so it can be passed around as a value, can
43 // be used as a parameter w/o using &-passing, and can be returned as a
44 // return value.
45 //
46 // oop parameters and return types should be Handles whenever feasible.
47 //
48 // Handles are declared in a straight-forward manner, e.g.
49 //
50 // oop obj = ...;
51 // Handle h2(thread, obj); // allocate a new handle in thread
52 // Handle h3; // declare handle only, no allocation occurs
53 // ...
54 // h3 = h1; // make h3 refer to same indirection as h1
55 // oop obj2 = h2(); // get handle value
56 // h1->print(); // invoking operation on oop
57 //
58 // Handles are specialized for different oop types to provide extra type
59 // information and avoid unnecessary casting. For each oop type xxxOop
60 // there is a corresponding handle called xxxHandle.
61
62 //------------------------------------------------------------------------------------------------------------------------
63 // Base class for all handles. Provides overloading of frequently
64 // used operators for ease of use.
65
66 class Handle {
67 private:
68 oop* _handle;
69
70 protected:
71 oop obj() const { return _handle == nullptr ? (oop)nullptr : *_handle; }
72 oop non_null_obj() const { assert(_handle != nullptr, "resolving null handle"); return *_handle; }
73
74 public:
75 // Constructors
76 Handle() { _handle = nullptr; }
77 inline Handle(Thread* thread, oop obj);
78
79 // General access
80 oop operator () () const { return obj(); }
81 oop operator -> () const { return non_null_obj(); }
82
83 bool operator == (oop o) const { return obj() == o; }
84 bool operator != (oop o) const { return obj() != o; }
85 bool operator == (const Handle& h) const { return obj() == h.obj(); }
86 bool operator != (const Handle& h) const { return obj() != h.obj(); }
87
88 // Null checks
89 bool is_null() const { return _handle == nullptr; }
90 bool not_null() const { return _handle != nullptr; }
91
92 // Debugging
93 void print() { obj()->print(); }
94
95 // Direct interface, use very sparingly.
96 // Used by JavaCalls to quickly convert handles and to create handles static data structures.
97 // Constructor takes a dummy argument to prevent unintentional type conversion in C++.
98 Handle(oop *handle, bool dummy) { _handle = handle; }
99
100 // Raw handle access. Allows easy duplication of Handles. This can be very unsafe
101 // since duplicates is only valid as long as original handle is alive.
102 oop* raw_value() const { return _handle; }
103 static oop raw_resolve(oop *handle) { return handle == nullptr ? (oop)nullptr : *handle; }
104
105 inline void replace(oop obj);
106 };
107
108 // Specific Handles for different oop types
109 #define DEF_HANDLE(type, is_a) \
110 class type##Handle: public Handle { \
111 protected: \
112 type##Oop obj() const { return (type##Oop)Handle::obj(); } \
113 type##Oop non_null_obj() const { return (type##Oop)Handle::non_null_obj(); } \
114 \
115 public: \
116 /* Constructors */ \
117 type##Handle () : Handle() {} \
118 inline type##Handle (Thread* thread, type##Oop obj); \
119 type##Handle (oop *handle, bool dummy) : Handle(handle, dummy) {} \
120 \
121 /* Operators for ease of use */ \
122 type##Oop operator () () const { return obj(); } \
123 type##Oop operator -> () const { return non_null_obj(); } \
124 };
125
126
127 DEF_HANDLE(instance , is_instance_noinline )
128 DEF_HANDLE(stackChunk , is_stackChunk_noinline )
129 DEF_HANDLE(array , is_array_noinline )
130 DEF_HANDLE(objArray , is_objArray_noinline )
131 DEF_HANDLE(typeArray , is_typeArray_noinline )
132 DEF_HANDLE(flatArray , is_flatArray_noinline )
133 DEF_HANDLE(refArray , is_refArray_noinline )
134
135 //------------------------------------------------------------------------------------------------------------------------
136
137 // Metadata Handles. Unlike oop Handles these are needed to prevent metadata
138 // from being reclaimed by RedefineClasses.
139 // Metadata Handles should be passed around as const references to avoid copy construction
140 // and destruction for parameters.
141
142 // Specific Handles for different oop types
143 #define DEF_METADATA_HANDLE(name, type) \
144 class name##Handle; \
145 class name##Handle : public StackObj { \
146 type* _value; \
147 Thread* _thread; \
148 protected: \
149 type* obj() const { return _value; } \
150 type* non_null_obj() const { assert(_value != nullptr, "resolving null _value"); return _value; } \
151 \
152 public: \
153 /* Constructors */ \
154 name##Handle () : _value(nullptr), _thread(nullptr) {} \
155 name##Handle (Thread* thread, type* obj); \
156 \
157 name##Handle (const name##Handle &h); \
158 name##Handle& operator=(const name##Handle &s); \
159 \
160 /* Destructor */ \
161 ~name##Handle (); \
162 void remove(); \
163 \
164 /* Operators for ease of use */ \
165 type* operator () () const { return obj(); } \
166 type* operator -> () const { return non_null_obj(); } \
167 \
168 bool operator == (type* o) const { return obj() == o; } \
169 bool operator == (const name##Handle& h) const { return obj() == h.obj(); } \
170 \
171 /* Null checks */ \
172 bool is_null() const { return _value == nullptr; } \
173 bool not_null() const { return _value != nullptr; } \
174 };
175
176
177 DEF_METADATA_HANDLE(method, Method)
178 DEF_METADATA_HANDLE(constantPool, ConstantPool)
179
180 //------------------------------------------------------------------------------------------------------------------------
181 // Thread local handle area
182 class HandleArea: public Arena {
183 friend class HandleMark;
184 friend class NoHandleMark;
185 friend class ResetNoHandleMark;
186 #ifdef ASSERT
187 int _handle_mark_nesting;
188 int _no_handle_mark_nesting;
189 #endif
190 HandleArea* _prev; // link to outer (older) area
191 public:
192 // Constructor
193 HandleArea(MemTag mem_tag, HandleArea* prev) : Arena(mem_tag, Tag::tag_ha, Chunk::tiny_size) {
194 DEBUG_ONLY(_handle_mark_nesting = 0);
195 DEBUG_ONLY(_no_handle_mark_nesting = 0);
196 _prev = prev;
197 }
198
199 // Handle allocation
200 private:
201 oop* real_allocate_handle(oop obj) {
202 oop* handle = (oop*)internal_amalloc(oopSize);
203 *handle = obj;
204 return handle;
205 }
206 public:
207 #ifdef ASSERT
208 oop* allocate_handle(oop obj);
209 oop* allocate_null_handle();
210 #else
211 oop* allocate_handle(oop obj) { return real_allocate_handle(obj); }
212 oop* allocate_null_handle() { return allocate_handle(nullptr); }
213 #endif
214
215 // Garbage collection support
216 void oops_do(OopClosure* f);
217
218 DEBUG_ONLY(bool no_handle_mark_active() { return _no_handle_mark_nesting > 0; })
219 };
220
221
222 //------------------------------------------------------------------------------------------------------------------------
223 // Handles are allocated in a (growable) thread local handle area. Deallocation
224 // is managed using a HandleMark. It should normally not be necessary to use
225 // HandleMarks manually.
226 //
227 // A HandleMark constructor will record the current handle area top, and the
228 // destructor will reset the top, destroying all handles allocated in between.
229 // The following code will therefore NOT work:
230 //
231 // Handle h;
232 // {
233 // HandleMark hm(THREAD);
234 // h = Handle(THREAD, obj);
235 // }
236 // h()->print(); // WRONG, h destroyed by HandleMark destructor.
237 //
238 // If h has to be preserved, it can be converted to an oop or a local JNI handle
239 // across the HandleMark boundary.
240
241 // The base class of HandleMark should have been StackObj but we also heap allocate
242 // a HandleMark when a thread is created. The operator new is for this special case.
243
244 class HandleMark {
245 private:
246 Thread *_thread; // thread that owns this mark
247 HandleArea *_area; // saved handle area
248 Chunk *_chunk; // saved arena chunk
249 char *_hwm, *_max; // saved arena info
250 size_t _size_in_bytes; // size of handle area
251 // Link to previous active HandleMark in thread
252 HandleMark* _previous_handle_mark;
253
254 void initialize(Thread* thread); // common code for constructors
255 void set_previous_handle_mark(HandleMark* mark) { _previous_handle_mark = mark; }
256 HandleMark* previous_handle_mark() const { return _previous_handle_mark; }
257
258 size_t size_in_bytes() const { return _size_in_bytes; }
259 // remove all chunks beginning with the next
260 void chop_later_chunks();
261 public:
262 HandleMark(Thread* thread) { initialize(thread); }
263 ~HandleMark();
264
265 // Functions used by HandleMarkCleaner
266 // called in the constructor of HandleMarkCleaner
267 void push();
268 // called in the destructor of HandleMarkCleaner
269 void pop_and_restore();
270 // overloaded operators
271 void* operator new(size_t size) throw();
272 void* operator new [](size_t size) throw();
273 void operator delete(void* p);
274 void operator delete[](void* p);
275 };
276
277 //------------------------------------------------------------------------------------------------------------------------
278 // A NoHandleMark stack object will verify that no handles are allocated
279 // in its scope. Enabled in debug mode only.
280
281 class NoHandleMark: public StackObj {
282 public:
283 #ifdef ASSERT
284 NoHandleMark();
285 ~NoHandleMark();
286 #else
287 NoHandleMark() {}
288 ~NoHandleMark() {}
289 #endif
290 };
291
292
293 // ResetNoHandleMark is called in a context where there is an enclosing
294 // NoHandleMark. A thread in _thread_in_native must not create handles so
295 // this is used when transitioning via ThreadInVMfromNative.
296 class ResetNoHandleMark: public StackObj {
297 int _no_handle_mark_nesting;
298 public:
299 #ifdef ASSERT
300 ResetNoHandleMark();
301 ~ResetNoHandleMark();
302 #else
303 ResetNoHandleMark() {}
304 ~ResetNoHandleMark() {}
305 #endif
306 };
307
308 // The HandleMarkCleaner is a faster version of HandleMark.
309 // It relies on the fact that there is a HandleMark further
310 // down the stack (in JavaCalls::call_helper), and just resets
311 // to the saved values in that HandleMark.
312
313 class HandleMarkCleaner: public StackObj {
314 private:
315 Thread* _thread;
316 public:
317 inline HandleMarkCleaner(Thread* thread);
318 inline ~HandleMarkCleaner();
319 };
320
321 #endif // SHARE_RUNTIME_HANDLES_HPP