File: | jdk/src/hotspot/share/classfile/stackMapTable.hpp |
Warning: | line 100, column 33 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | |||
2 | * Copyright (c) 2003, 2020, 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 | #include "precompiled.hpp" | |||
26 | #include "classfile/stackMapTable.hpp" | |||
27 | #include "classfile/verifier.hpp" | |||
28 | #include "memory/resourceArea.hpp" | |||
29 | #include "oops/constantPool.hpp" | |||
30 | #include "oops/oop.inline.hpp" | |||
31 | #include "runtime/handles.inline.hpp" | |||
32 | ||||
33 | StackMapTable::StackMapTable(StackMapReader* reader, StackMapFrame* init_frame, | |||
34 | u2 max_locals, u2 max_stack, | |||
35 | char* code_data, int code_len, TRAPSJavaThread* __the_thread__) { | |||
36 | _code_length = code_len; | |||
37 | _frame_count = reader->get_frame_count(); | |||
38 | if (_frame_count > 0) { | |||
39 | _frame_array = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD,(StackMapFrame**) resource_allocate_bytes(__the_thread__, (_frame_count ) * sizeof(StackMapFrame*)) | |||
40 | StackMapFrame*, _frame_count)(StackMapFrame**) resource_allocate_bytes(__the_thread__, (_frame_count ) * sizeof(StackMapFrame*)); | |||
41 | StackMapFrame* pre_frame = init_frame; | |||
42 | for (int32_t i = 0; i < _frame_count; i++) { | |||
43 | StackMapFrame* frame = reader->next( | |||
44 | pre_frame, i == 0, max_locals, max_stack, | |||
45 | CHECK_VERIFY(pre_frame->verifier())__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); if ((pre_frame->verifier())->has_error ()) return; ((void)0); | |||
46 | _frame_array[i] = frame; | |||
47 | int offset = frame->offset(); | |||
48 | if (offset >= code_len || code_data[offset] == 0) { | |||
49 | frame->verifier()->verify_error( | |||
50 | ErrorContext::bad_stackmap(i, frame), | |||
51 | "StackMapTable error: bad offset"); | |||
52 | return; | |||
53 | } | |||
54 | pre_frame = frame; | |||
55 | } | |||
56 | } | |||
57 | reader->check_end(CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | |||
58 | } | |||
59 | ||||
60 | // This method is only called by method in StackMapTable. | |||
61 | int StackMapTable::get_index_from_offset(int32_t offset) const { | |||
62 | int i = 0; | |||
63 | for (; i < _frame_count; i++) { | |||
64 | if (_frame_array[i]->offset() == offset) { | |||
65 | return i; | |||
66 | } | |||
67 | } | |||
68 | return i; // frame with offset doesn't exist in the array | |||
69 | } | |||
70 | ||||
71 | bool StackMapTable::match_stackmap( | |||
72 | StackMapFrame* frame, int32_t target, | |||
73 | bool match, bool update, ErrorContext* ctx, TRAPSJavaThread* __the_thread__) const { | |||
74 | int index = get_index_from_offset(target); | |||
75 | return match_stackmap(frame, target, index, match, update, ctx, THREAD__the_thread__); | |||
76 | } | |||
77 | ||||
78 | // Match and/or update current_frame to the frame in stackmap table with | |||
79 | // specified offset and frame index. Return true if the two frames match. | |||
80 | // | |||
81 | // The values of match and update are: _match__update | |||
82 | // | |||
83 | // checking a branch target: true false | |||
84 | // checking an exception handler: true false | |||
85 | // linear bytecode verification following an | |||
86 | // unconditional branch: false true | |||
87 | // linear bytecode verification not following an | |||
88 | // unconditional branch: true true | |||
89 | bool StackMapTable::match_stackmap( | |||
90 | StackMapFrame* frame, int32_t target, int32_t frame_index, | |||
91 | bool match, bool update, ErrorContext* ctx, TRAPSJavaThread* __the_thread__) const { | |||
92 | if (frame_index < 0 || frame_index >= _frame_count) { | |||
93 | *ctx = ErrorContext::missing_stackmap(frame->offset()); | |||
94 | frame->verifier()->verify_error( | |||
95 | *ctx, "Expecting a stackmap frame at branch target %d", target); | |||
96 | return false; | |||
97 | } | |||
98 | ||||
99 | StackMapFrame *stackmap_frame = _frame_array[frame_index]; | |||
100 | bool result = true; | |||
101 | if (match) { | |||
102 | // Has direct control flow from last instruction, need to match the two | |||
103 | // frames. | |||
104 | result = frame->is_assignable_to(stackmap_frame, | |||
105 | ctx, CHECK_VERIFY_(frame->verifier(), result)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return result; (void)(0); if ((frame->verifier())-> has_error()) return (result); ((void)0); | |||
106 | } | |||
107 | if (update) { | |||
108 | // Use the frame in stackmap table as current frame | |||
109 | int lsize = stackmap_frame->locals_size(); | |||
110 | int ssize = stackmap_frame->stack_size(); | |||
111 | if (frame->locals_size() > lsize || frame->stack_size() > ssize) { | |||
112 | // Make sure unused type array items are all _bogus_type. | |||
113 | frame->reset(); | |||
114 | } | |||
115 | frame->set_locals_size(lsize); | |||
116 | frame->copy_locals(stackmap_frame); | |||
117 | frame->set_stack_size(ssize); | |||
118 | frame->copy_stack(stackmap_frame); | |||
119 | frame->set_flags(stackmap_frame->flags()); | |||
120 | } | |||
121 | return result; | |||
122 | } | |||
123 | ||||
124 | void StackMapTable::check_jump_target( | |||
125 | StackMapFrame* frame, int32_t target, TRAPSJavaThread* __the_thread__) const { | |||
126 | ErrorContext ctx; | |||
127 | bool match = match_stackmap( | |||
128 | frame, target, true, false, &ctx, CHECK_VERIFY(frame->verifier())__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); if ((frame->verifier())->has_error ()) return; ((void)0); | |||
129 | if (!match || (target < 0 || target >= _code_length)) { | |||
130 | frame->verifier()->verify_error(ctx, | |||
131 | "Inconsistent stackmap frames at branch target %d", target); | |||
132 | } | |||
133 | } | |||
134 | ||||
135 | void StackMapTable::print_on(outputStream* str) const { | |||
136 | str->indent().print_cr("StackMapTable: frame_count = %d", _frame_count); | |||
137 | str->indent().print_cr("table = { "); | |||
138 | { | |||
139 | streamIndentor si(str); | |||
140 | for (int32_t i = 0; i < _frame_count; ++i) { | |||
141 | _frame_array[i]->print_on(str); | |||
142 | } | |||
143 | } | |||
144 | str->print_cr(" }"); | |||
145 | } | |||
146 | ||||
147 | StackMapReader::StackMapReader(ClassVerifier* v, StackMapStream* stream, char* code_data, | |||
148 | int32_t code_len, TRAPSJavaThread* __the_thread__) : | |||
149 | _verifier(v), _stream(stream), | |||
150 | _code_data(code_data), _code_length(code_len) { | |||
151 | methodHandle m = v->method(); | |||
152 | if (m->has_stackmap_table()) { | |||
| ||||
153 | _cp = constantPoolHandle(THREAD__the_thread__, m->constants()); | |||
154 | _frame_count = _stream->get_u2(CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | |||
155 | } else { | |||
156 | // There's no stackmap table present. Frame count and size are 0. | |||
157 | _frame_count = 0; | |||
158 | } | |||
159 | } | |||
160 | ||||
161 | int32_t StackMapReader::chop( | |||
162 | VerificationType* locals, int32_t length, int32_t chops) { | |||
163 | if (locals == NULL__null) return -1; | |||
164 | int32_t pos = length - 1; | |||
165 | for (int32_t i=0; i<chops; i++) { | |||
166 | if (locals[pos].is_category2_2nd()) { | |||
167 | pos -= 2; | |||
168 | } else { | |||
169 | pos --; | |||
170 | } | |||
171 | if (pos<0 && i<(chops-1)) return -1; | |||
172 | } | |||
173 | return pos+1; | |||
174 | } | |||
175 | ||||
176 | VerificationType StackMapReader::parse_verification_type(u1* flags, TRAPSJavaThread* __the_thread__) { | |||
177 | u1 tag = _stream->get_u1(THREAD__the_thread__); | |||
178 | if (tag < (u1)ITEM_UninitializedThis) { | |||
179 | return VerificationType::from_tag(tag); | |||
180 | } | |||
181 | if (tag == ITEM_Object) { | |||
182 | u2 class_index = _stream->get_u2(THREAD__the_thread__); | |||
183 | int nconstants = _cp->length(); | |||
184 | if ((class_index <= 0 || class_index >= nconstants) || | |||
185 | (!_cp->tag_at(class_index).is_klass() && | |||
186 | !_cp->tag_at(class_index).is_unresolved_klass())) { | |||
187 | _stream->stackmap_format_error("bad class index", THREAD__the_thread__); | |||
188 | return VerificationType::bogus_type(); | |||
189 | } | |||
190 | return VerificationType::reference_type(_cp->klass_name_at(class_index)); | |||
191 | } | |||
192 | if (tag == ITEM_UninitializedThis) { | |||
193 | if (flags != NULL__null) { | |||
194 | *flags |= FLAG_THIS_UNINIT; | |||
195 | } | |||
196 | return VerificationType::uninitialized_this_type(); | |||
197 | } | |||
198 | if (tag == ITEM_Uninitialized) { | |||
199 | u2 offset = _stream->get_u2(THREAD__the_thread__); | |||
200 | if (offset >= _code_length || | |||
201 | _code_data[offset] != ClassVerifier::NEW_OFFSET) { | |||
202 | _verifier->class_format_error( | |||
203 | "StackMapTable format error: bad offset for Uninitialized"); | |||
204 | return VerificationType::bogus_type(); | |||
205 | } | |||
206 | return VerificationType::uninitialized_type(offset); | |||
207 | } | |||
208 | _stream->stackmap_format_error("bad verification type", THREAD__the_thread__); | |||
209 | return VerificationType::bogus_type(); | |||
210 | } | |||
211 | ||||
212 | StackMapFrame* StackMapReader::next( | |||
213 | StackMapFrame* pre_frame, bool first, u2 max_locals, u2 max_stack, TRAPSJavaThread* __the_thread__) { | |||
214 | StackMapFrame* frame; | |||
215 | int offset; | |||
216 | VerificationType* locals = NULL__null; | |||
217 | u1 frame_type = _stream->get_u1(THREAD__the_thread__); | |||
218 | if (frame_type < 64) { | |||
219 | // same_frame | |||
220 | if (first) { | |||
221 | offset = frame_type; | |||
222 | // Can't share the locals array since that is updated by the verifier. | |||
223 | if (pre_frame->locals_size() > 0) { | |||
224 | locals = NEW_RESOURCE_ARRAY_IN_THREAD((VerificationType*) resource_allocate_bytes(__the_thread__, ( pre_frame->locals_size()) * sizeof(VerificationType)) | |||
225 | THREAD, VerificationType, pre_frame->locals_size())(VerificationType*) resource_allocate_bytes(__the_thread__, ( pre_frame->locals_size()) * sizeof(VerificationType)); | |||
226 | } | |||
227 | } else { | |||
228 | offset = pre_frame->offset() + frame_type + 1; | |||
229 | locals = pre_frame->locals(); | |||
230 | } | |||
231 | frame = new StackMapFrame( | |||
232 | offset, pre_frame->flags(), pre_frame->locals_size(), 0, | |||
233 | max_locals, max_stack, locals, NULL__null, _verifier); | |||
234 | if (first && locals != NULL__null) { | |||
235 | frame->copy_locals(pre_frame); | |||
236 | } | |||
237 | return frame; | |||
238 | } | |||
239 | if (frame_type < 128) { | |||
240 | // same_locals_1_stack_item_frame | |||
241 | if (first) { | |||
242 | offset = frame_type - 64; | |||
243 | // Can't share the locals array since that is updated by the verifier. | |||
244 | if (pre_frame->locals_size() > 0) { | |||
245 | locals = NEW_RESOURCE_ARRAY_IN_THREAD((VerificationType*) resource_allocate_bytes(__the_thread__, ( pre_frame->locals_size()) * sizeof(VerificationType)) | |||
246 | THREAD, VerificationType, pre_frame->locals_size())(VerificationType*) resource_allocate_bytes(__the_thread__, ( pre_frame->locals_size()) * sizeof(VerificationType)); | |||
247 | } | |||
248 | } else { | |||
249 | offset = pre_frame->offset() + frame_type - 63; | |||
250 | locals = pre_frame->locals(); | |||
251 | } | |||
252 | VerificationType* stack = NEW_RESOURCE_ARRAY_IN_THREAD((VerificationType*) resource_allocate_bytes(__the_thread__, ( 2) * sizeof(VerificationType)) | |||
253 | THREAD, VerificationType, 2)(VerificationType*) resource_allocate_bytes(__the_thread__, ( 2) * sizeof(VerificationType)); | |||
254 | u2 stack_size = 1; | |||
255 | stack[0] = parse_verification_type(NULL__null, CHECK_VERIFY_(_verifier, NULL)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); if ((_verifier)->has_error( )) return (__null); ((void)0); | |||
256 | if (stack[0].is_category2()) { | |||
257 | stack[1] = stack[0].to_category2_2nd(); | |||
258 | stack_size = 2; | |||
259 | } | |||
260 | check_verification_type_array_size( | |||
261 | stack_size, max_stack, CHECK_VERIFY_(_verifier, NULL)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); if ((_verifier)->has_error( )) return (__null); ((void)0); | |||
262 | frame = new StackMapFrame( | |||
263 | offset, pre_frame->flags(), pre_frame->locals_size(), stack_size, | |||
264 | max_locals, max_stack, locals, stack, _verifier); | |||
265 | if (first && locals != NULL__null) { | |||
266 | frame->copy_locals(pre_frame); | |||
267 | } | |||
268 | return frame; | |||
269 | } | |||
270 | ||||
271 | u2 offset_delta = _stream->get_u2(THREAD__the_thread__); | |||
272 | ||||
273 | if (frame_type < SAME_LOCALS_1_STACK_ITEM_EXTENDED) { | |||
274 | // reserved frame types | |||
275 | _stream->stackmap_format_error( | |||
276 | "reserved frame type", CHECK_VERIFY_(_verifier, NULL)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); if ((_verifier)->has_error( )) return (__null); ((void)0); | |||
277 | } | |||
278 | ||||
279 | if (frame_type == SAME_LOCALS_1_STACK_ITEM_EXTENDED) { | |||
280 | // same_locals_1_stack_item_frame_extended | |||
281 | if (first) { | |||
282 | offset = offset_delta; | |||
283 | // Can't share the locals array since that is updated by the verifier. | |||
284 | if (pre_frame->locals_size() > 0) { | |||
285 | locals = NEW_RESOURCE_ARRAY_IN_THREAD((VerificationType*) resource_allocate_bytes(__the_thread__, ( pre_frame->locals_size()) * sizeof(VerificationType)) | |||
286 | THREAD, VerificationType, pre_frame->locals_size())(VerificationType*) resource_allocate_bytes(__the_thread__, ( pre_frame->locals_size()) * sizeof(VerificationType)); | |||
287 | } | |||
288 | } else { | |||
289 | offset = pre_frame->offset() + offset_delta + 1; | |||
290 | locals = pre_frame->locals(); | |||
291 | } | |||
292 | VerificationType* stack = NEW_RESOURCE_ARRAY_IN_THREAD((VerificationType*) resource_allocate_bytes(__the_thread__, ( 2) * sizeof(VerificationType)) | |||
293 | THREAD, VerificationType, 2)(VerificationType*) resource_allocate_bytes(__the_thread__, ( 2) * sizeof(VerificationType)); | |||
294 | u2 stack_size = 1; | |||
295 | stack[0] = parse_verification_type(NULL__null, CHECK_VERIFY_(_verifier, NULL)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); if ((_verifier)->has_error( )) return (__null); ((void)0); | |||
296 | if (stack[0].is_category2()) { | |||
297 | stack[1] = stack[0].to_category2_2nd(); | |||
298 | stack_size = 2; | |||
299 | } | |||
300 | check_verification_type_array_size( | |||
301 | stack_size, max_stack, CHECK_VERIFY_(_verifier, NULL)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); if ((_verifier)->has_error( )) return (__null); ((void)0); | |||
302 | frame = new StackMapFrame( | |||
303 | offset, pre_frame->flags(), pre_frame->locals_size(), stack_size, | |||
304 | max_locals, max_stack, locals, stack, _verifier); | |||
305 | if (first && locals != NULL__null) { | |||
306 | frame->copy_locals(pre_frame); | |||
307 | } | |||
308 | return frame; | |||
309 | } | |||
310 | ||||
311 | if (frame_type <= SAME_EXTENDED) { | |||
312 | // chop_frame or same_frame_extended | |||
313 | locals = pre_frame->locals(); | |||
314 | int length = pre_frame->locals_size(); | |||
315 | int chops = SAME_EXTENDED - frame_type; | |||
316 | int new_length = length; | |||
317 | u1 flags = pre_frame->flags(); | |||
318 | if (chops != 0) { | |||
319 | new_length = chop(locals, length, chops); | |||
320 | check_verification_type_array_size( | |||
321 | new_length, max_locals, CHECK_VERIFY_(_verifier, NULL)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); if ((_verifier)->has_error( )) return (__null); ((void)0); | |||
322 | // Recompute flags since uninitializedThis could have been chopped. | |||
323 | flags = 0; | |||
324 | for (int i=0; i<new_length; i++) { | |||
325 | if (locals[i].is_uninitialized_this()) { | |||
326 | flags |= FLAG_THIS_UNINIT; | |||
327 | break; | |||
328 | } | |||
329 | } | |||
330 | } | |||
331 | if (first) { | |||
332 | offset = offset_delta; | |||
333 | // Can't share the locals array since that is updated by the verifier. | |||
334 | if (new_length > 0) { | |||
335 | locals = NEW_RESOURCE_ARRAY_IN_THREAD((VerificationType*) resource_allocate_bytes(__the_thread__, ( new_length) * sizeof(VerificationType)) | |||
336 | THREAD, VerificationType, new_length)(VerificationType*) resource_allocate_bytes(__the_thread__, ( new_length) * sizeof(VerificationType)); | |||
337 | } else { | |||
338 | locals = NULL__null; | |||
339 | } | |||
340 | } else { | |||
341 | offset = pre_frame->offset() + offset_delta + 1; | |||
342 | } | |||
343 | frame = new StackMapFrame( | |||
344 | offset, flags, new_length, 0, max_locals, max_stack, | |||
345 | locals, NULL__null, _verifier); | |||
346 | if (first && locals != NULL__null) { | |||
347 | frame->copy_locals(pre_frame); | |||
348 | } | |||
349 | return frame; | |||
350 | } else if (frame_type < SAME_EXTENDED + 4) { | |||
351 | // append_frame | |||
352 | int appends = frame_type - SAME_EXTENDED; | |||
353 | int real_length = pre_frame->locals_size(); | |||
354 | int new_length = real_length + appends*2; | |||
355 | locals = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, VerificationType, new_length)(VerificationType*) resource_allocate_bytes(__the_thread__, ( new_length) * sizeof(VerificationType)); | |||
356 | VerificationType* pre_locals = pre_frame->locals(); | |||
357 | int i; | |||
358 | for (i=0; i<pre_frame->locals_size(); i++) { | |||
359 | locals[i] = pre_locals[i]; | |||
360 | } | |||
361 | u1 flags = pre_frame->flags(); | |||
362 | for (i=0; i<appends; i++) { | |||
363 | locals[real_length] = parse_verification_type(&flags, THREAD__the_thread__); | |||
364 | if (locals[real_length].is_category2()) { | |||
365 | locals[real_length + 1] = locals[real_length].to_category2_2nd(); | |||
366 | ++real_length; | |||
367 | } | |||
368 | ++real_length; | |||
369 | } | |||
370 | check_verification_type_array_size( | |||
371 | real_length, max_locals, CHECK_VERIFY_(_verifier, NULL)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); if ((_verifier)->has_error( )) return (__null); ((void)0); | |||
372 | if (first) { | |||
373 | offset = offset_delta; | |||
374 | } else { | |||
375 | offset = pre_frame->offset() + offset_delta + 1; | |||
376 | } | |||
377 | frame = new StackMapFrame( | |||
378 | offset, flags, real_length, 0, max_locals, | |||
379 | max_stack, locals, NULL__null, _verifier); | |||
380 | return frame; | |||
381 | } | |||
382 | if (frame_type == FULL) { | |||
383 | // full_frame | |||
384 | u1 flags = 0; | |||
385 | u2 locals_size = _stream->get_u2(THREAD__the_thread__); | |||
386 | int real_locals_size = 0; | |||
387 | if (locals_size > 0) { | |||
388 | locals = NEW_RESOURCE_ARRAY_IN_THREAD((VerificationType*) resource_allocate_bytes(__the_thread__, ( locals_size*2) * sizeof(VerificationType)) | |||
389 | THREAD, VerificationType, locals_size*2)(VerificationType*) resource_allocate_bytes(__the_thread__, ( locals_size*2) * sizeof(VerificationType)); | |||
390 | } | |||
391 | int i; | |||
392 | for (i=0; i<locals_size; i++) { | |||
393 | locals[real_locals_size] = parse_verification_type(&flags, THREAD__the_thread__); | |||
394 | if (locals[real_locals_size].is_category2()) { | |||
395 | locals[real_locals_size + 1] = | |||
396 | locals[real_locals_size].to_category2_2nd(); | |||
397 | ++real_locals_size; | |||
398 | } | |||
399 | ++real_locals_size; | |||
400 | } | |||
401 | check_verification_type_array_size( | |||
402 | real_locals_size, max_locals, CHECK_VERIFY_(_verifier, NULL)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); if ((_verifier)->has_error( )) return (__null); ((void)0); | |||
403 | u2 stack_size = _stream->get_u2(THREAD__the_thread__); | |||
404 | int real_stack_size = 0; | |||
405 | VerificationType* stack = NULL__null; | |||
406 | if (stack_size > 0) { | |||
407 | stack = NEW_RESOURCE_ARRAY_IN_THREAD((VerificationType*) resource_allocate_bytes(__the_thread__, ( stack_size*2) * sizeof(VerificationType)) | |||
408 | THREAD, VerificationType, stack_size*2)(VerificationType*) resource_allocate_bytes(__the_thread__, ( stack_size*2) * sizeof(VerificationType)); | |||
409 | } | |||
410 | for (i=0; i<stack_size; i++) { | |||
411 | stack[real_stack_size] = parse_verification_type(NULL__null, THREAD__the_thread__); | |||
412 | if (stack[real_stack_size].is_category2()) { | |||
413 | stack[real_stack_size + 1] = stack[real_stack_size].to_category2_2nd(); | |||
414 | ++real_stack_size; | |||
415 | } | |||
416 | ++real_stack_size; | |||
417 | } | |||
418 | check_verification_type_array_size( | |||
419 | real_stack_size, max_stack, CHECK_VERIFY_(_verifier, NULL)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); if ((_verifier)->has_error( )) return (__null); ((void)0); | |||
420 | if (first) { | |||
421 | offset = offset_delta; | |||
422 | } else { | |||
423 | offset = pre_frame->offset() + offset_delta + 1; | |||
424 | } | |||
425 | frame = new StackMapFrame( | |||
426 | offset, flags, real_locals_size, real_stack_size, | |||
427 | max_locals, max_stack, locals, stack, _verifier); | |||
428 | return frame; | |||
429 | } | |||
430 | ||||
431 | _stream->stackmap_format_error( | |||
432 | "reserved frame type", CHECK_VERIFY_(pre_frame->verifier(), NULL)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0); if ((pre_frame->verifier()) ->has_error()) return (__null); ((void)0); | |||
433 | return NULL__null; | |||
434 | } |
1 | /* | |||
2 | * Copyright (c) 2003, 2019, 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_CLASSFILE_STACKMAPTABLE_HPP | |||
26 | #define SHARE_CLASSFILE_STACKMAPTABLE_HPP | |||
27 | ||||
28 | #include "classfile/stackMapFrame.hpp" | |||
29 | #include "classfile/verifier.hpp" | |||
30 | #include "memory/allocation.hpp" | |||
31 | #include "oops/constantPool.hpp" | |||
32 | #include "oops/method.hpp" | |||
33 | #include "utilities/bytes.hpp" | |||
34 | #include "utilities/globalDefinitions.hpp" | |||
35 | ||||
36 | class StackMapReader; | |||
37 | ||||
38 | // StackMapTable class is the StackMap table used by type checker | |||
39 | class StackMapTable : public StackObj { | |||
40 | private: | |||
41 | // Logically, the _frame_count (as well as many fields in the StackFrame) | |||
42 | // should be a u2, but if we defined the variable as that type it will | |||
43 | // be difficult to detect/recover from overflow or underflow conditions. | |||
44 | // Widening the type and making it signed will help detect these. | |||
45 | int32_t _code_length; | |||
46 | int32_t _frame_count; // Stackmap frame count | |||
47 | StackMapFrame** _frame_array; | |||
48 | ||||
49 | public: | |||
50 | StackMapTable(StackMapReader* reader, StackMapFrame* init_frame, | |||
51 | u2 max_locals, u2 max_stack, | |||
52 | char* code_data, int code_len, TRAPSJavaThread* __the_thread__); | |||
53 | ||||
54 | inline int32_t get_frame_count() const { return _frame_count; } | |||
55 | inline int get_offset(int index) const { | |||
56 | return _frame_array[index]->offset(); | |||
57 | } | |||
58 | ||||
59 | // Match and/or update current_frame to the frame in stackmap table with | |||
60 | // specified offset. Return true if the two frames match. | |||
61 | bool match_stackmap( | |||
62 | StackMapFrame* current_frame, int32_t offset, | |||
63 | bool match, bool update, ErrorContext* ctx, TRAPSJavaThread* __the_thread__) const; | |||
64 | // Match and/or update current_frame to the frame in stackmap table with | |||
65 | // specified offset and frame index. Return true if the two frames match. | |||
66 | bool match_stackmap( | |||
67 | StackMapFrame* current_frame, int32_t offset, int32_t frame_index, | |||
68 | bool match, bool update, ErrorContext* ctx, TRAPSJavaThread* __the_thread__) const; | |||
69 | ||||
70 | // Check jump instructions. Make sure there are no uninitialized | |||
71 | // instances on backward branch. | |||
72 | void check_jump_target(StackMapFrame* frame, int32_t target, TRAPSJavaThread* __the_thread__) const; | |||
73 | ||||
74 | // The following methods are only used inside this class. | |||
75 | ||||
76 | // Returns the frame array index where the frame with offset is stored. | |||
77 | int get_index_from_offset(int32_t offset) const; | |||
78 | ||||
79 | void print_on(outputStream* str) const; | |||
80 | }; | |||
81 | ||||
82 | class StackMapStream : StackObj { | |||
83 | private: | |||
84 | Array<u1>* _data; | |||
85 | int _index; | |||
86 | public: | |||
87 | StackMapStream(Array<u1>* ah) | |||
88 | : _data(ah), _index(0) { | |||
89 | } | |||
90 | u1 get_u1(TRAPSJavaThread* __the_thread__) { | |||
91 | if (_data == NULL__null || _index >= _data->length()) { | |||
92 | stackmap_format_error("access beyond the end of attribute", CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); | |||
93 | } | |||
94 | return _data->at(_index++); | |||
95 | } | |||
96 | u2 get_u2(TRAPSJavaThread* __the_thread__) { | |||
97 | if (_data == NULL__null || _index >= _data->length() - 1) { | |||
98 | stackmap_format_error("access beyond the end of attribute", CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0); | |||
99 | } | |||
100 | u2 res = Bytes::get_Java_u2(_data->adr_at(_index)); | |||
| ||||
101 | _index += 2; | |||
102 | return res; | |||
103 | } | |||
104 | bool at_end() { | |||
105 | return (_data == NULL__null) || (_index == _data->length()); | |||
106 | } | |||
107 | static void stackmap_format_error(const char* msg, TRAPSJavaThread* __the_thread__); | |||
108 | }; | |||
109 | ||||
110 | class StackMapReader : StackObj { | |||
111 | private: | |||
112 | // information about the class and method | |||
113 | constantPoolHandle _cp; | |||
114 | ClassVerifier* _verifier; | |||
115 | StackMapStream* _stream; | |||
116 | char* _code_data; | |||
117 | int32_t _code_length; | |||
118 | ||||
119 | // information get from the attribute | |||
120 | int32_t _frame_count; // frame count | |||
121 | ||||
122 | int32_t chop(VerificationType* locals, int32_t length, int32_t chops); | |||
123 | VerificationType parse_verification_type(u1* flags, TRAPSJavaThread* __the_thread__); | |||
124 | void check_verification_type_array_size( | |||
125 | int32_t size, int32_t max_size, TRAPSJavaThread* __the_thread__) { | |||
126 | if (size < 0 || size > max_size) { | |||
127 | // Since this error could be caused someone rewriting the method | |||
128 | // but not knowing to update the stackmap data, we call the the | |||
129 | // verifier's error method, which may not throw an exception and | |||
130 | // failover to the old verifier instead. | |||
131 | _verifier->class_format_error( | |||
132 | "StackMapTable format error: bad type array size"); | |||
133 | } | |||
134 | } | |||
135 | ||||
136 | enum { | |||
137 | SAME_LOCALS_1_STACK_ITEM_EXTENDED = 247, | |||
138 | SAME_EXTENDED = 251, | |||
139 | FULL = 255 | |||
140 | }; | |||
141 | ||||
142 | public: | |||
143 | // Constructor | |||
144 | StackMapReader(ClassVerifier* v, StackMapStream* stream, char* code_data, | |||
145 | int32_t code_len, TRAPSJavaThread* __the_thread__); | |||
146 | ||||
147 | inline int32_t get_frame_count() const { return _frame_count; } | |||
148 | StackMapFrame* next(StackMapFrame* pre_frame, bool first, | |||
149 | u2 max_locals, u2 max_stack, TRAPSJavaThread* __the_thread__); | |||
150 | ||||
151 | void check_end(TRAPSJavaThread* __the_thread__) { | |||
152 | if (!_stream->at_end()) { | |||
153 | StackMapStream::stackmap_format_error("wrong attribute size", CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0); | |||
154 | } | |||
155 | } | |||
156 | }; | |||
157 | ||||
158 | #endif // SHARE_CLASSFILE_STACKMAPTABLE_HPP |
1 | /* |
2 | * Copyright (c) 1998, 2021, 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_UTILITIES_EXCEPTIONS_HPP |
26 | #define SHARE_UTILITIES_EXCEPTIONS_HPP |
27 | |
28 | #include "memory/allocation.hpp" |
29 | #include "oops/oopsHierarchy.hpp" |
30 | #include "utilities/ostream.hpp" |
31 | #include "utilities/sizes.hpp" |
32 | |
33 | // This file provides the basic support for exception handling in the VM. |
34 | // Note: We do not use C++ exceptions to avoid compiler dependencies and |
35 | // unpredictable performance. |
36 | // |
37 | // Scheme: Exceptions are stored with the thread. There is never more |
38 | // than one pending exception per thread. All functions that can throw |
39 | // an exception carry a THREAD argument (usually the last argument and |
40 | // declared with the TRAPS macro). Throwing an exception means setting |
41 | // a pending exception in the thread. Upon return from a function that |
42 | // can throw an exception, we must check if an exception is pending. |
43 | // The CHECK macros do this in a convenient way. Carrying around the |
44 | // thread provides also convenient access to it (e.g. for Handle |
45 | // creation, w/o the need for recomputation). |
46 | |
47 | |
48 | |
49 | // Forward declarations to be independent of the include structure. |
50 | |
51 | class JavaThread; |
52 | class Handle; |
53 | class Symbol; |
54 | class JavaCallArguments; |
55 | class methodHandle; |
56 | |
57 | // The ThreadShadow class is a helper class to access the _pending_exception |
58 | // field of the Thread class w/o having access to the Thread's interface (for |
59 | // include hierachy reasons). |
60 | |
61 | class ThreadShadow: public CHeapObj<mtThread> { |
62 | friend class VMStructs; |
63 | friend class JVMCIVMStructs; |
64 | |
65 | protected: |
66 | oop _pending_exception; // Thread has gc actions. |
67 | const char* _exception_file; // file information for exception (debugging only) |
68 | int _exception_line; // line information for exception (debugging only) |
69 | friend void check_ThreadShadow(); // checks _pending_exception offset |
70 | |
71 | // The following virtual exists only to force creation of a vtable. |
72 | // We need ThreadShadow to have a vtable, even in product builds, |
73 | // so that its layout will start at an offset of zero relative to Thread. |
74 | // Some C++ compilers are so "clever" that they put the ThreadShadow |
75 | // base class at offset 4 in Thread (after Thread's vtable), if they |
76 | // notice that Thread has a vtable but ThreadShadow does not. |
77 | virtual void unused_initial_virtual() { } |
78 | |
79 | public: |
80 | oop pending_exception() const { return _pending_exception; } |
81 | bool has_pending_exception() const { return _pending_exception != NULL__null; } |
82 | const char* exception_file() const { return _exception_file; } |
83 | int exception_line() const { return _exception_line; } |
84 | |
85 | // Code generation support |
86 | static ByteSize pending_exception_offset() { return byte_offset_of(ThreadShadow, _pending_exception)in_ByteSize((int)(size_t)((intx)&(((ThreadShadow*)16)-> _pending_exception) - 16)); } |
87 | |
88 | // use THROW whenever possible! |
89 | void set_pending_exception(oop exception, const char* file, int line); |
90 | |
91 | // use CLEAR_PENDING_EXCEPTION whenever possible! |
92 | void clear_pending_exception(); |
93 | |
94 | // use CLEAR_PENDING_NONASYNC_EXCEPTION to clear probable nonasync exception. |
95 | void clear_pending_nonasync_exception(); |
96 | |
97 | ThreadShadow() : _pending_exception(NULL__null), |
98 | _exception_file(NULL__null), _exception_line(0) {} |
99 | }; |
100 | |
101 | |
102 | // Exceptions is a helper class that encapsulates all operations |
103 | // that require access to the thread interface and which are |
104 | // relatively rare. The Exceptions operations should only be |
105 | // used directly if the macros below are insufficient. |
106 | |
107 | class Exceptions { |
108 | static bool special_exception(JavaThread* thread, const char* file, int line, Handle exception); |
109 | static bool special_exception(JavaThread* thread, const char* file, int line, Symbol* name, const char* message); |
110 | |
111 | // Count out of memory errors that are interesting in error diagnosis |
112 | static volatile int _out_of_memory_error_java_heap_errors; |
113 | static volatile int _out_of_memory_error_metaspace_errors; |
114 | static volatile int _out_of_memory_error_class_metaspace_errors; |
115 | |
116 | // Count linkage errors |
117 | static volatile int _linkage_errors; |
118 | public: |
119 | // this enum is defined to indicate whether it is safe to |
120 | // ignore the encoding scheme of the original message string. |
121 | typedef enum { |
122 | safe_to_utf8 = 0, |
123 | unsafe_to_utf8 = 1 |
124 | } ExceptionMsgToUtf8Mode; |
125 | // Throw exceptions: w/o message, w/ message & with formatted message. |
126 | static void _throw_oop(JavaThread* thread, const char* file, int line, oop exception); |
127 | static void _throw(JavaThread* thread, const char* file, int line, Handle exception, const char* msg = NULL__null); |
128 | |
129 | static void _throw_msg(JavaThread* thread, const char* file, int line, Symbol* name, const char* message); |
130 | static void _throw_msg(JavaThread* thread, const char* file, int line, Symbol* name, const char* message, |
131 | Handle loader, Handle protection_domain); |
132 | |
133 | static void _throw_msg_cause(JavaThread* thread, const char* file, int line, Symbol* name, const char* message, Handle h_cause); |
134 | static void _throw_msg_cause(JavaThread* thread, const char* file, int line, Symbol* name, const char* message, Handle h_cause, |
135 | Handle h_loader, Handle h_protection_domain); |
136 | |
137 | static void _throw_cause(JavaThread* thread, const char* file, int line, Symbol* name, Handle h_cause); |
138 | static void _throw_cause(JavaThread* thread, const char* file, int line, Symbol* name, Handle h_cause, |
139 | Handle h_loader, Handle h_protection_domain); |
140 | |
141 | static void _throw_args(JavaThread* thread, const char* file, int line, |
142 | Symbol* name, Symbol* signature, |
143 | JavaCallArguments* args); |
144 | |
145 | // There is no THROW... macro for this method. Caller should remember |
146 | // to do a return after calling it. |
147 | static void fthrow(JavaThread* thread, const char* file, int line, Symbol* name, |
148 | const char* format, ...) ATTRIBUTE_PRINTF(5, 6)__attribute__((format(printf, 5, 6))); |
149 | |
150 | // Create and initialize a new exception |
151 | static Handle new_exception(JavaThread* thread, Symbol* name, |
152 | Symbol* signature, JavaCallArguments* args, |
153 | Handle loader, Handle protection_domain); |
154 | |
155 | static Handle new_exception(JavaThread* thread, Symbol* name, |
156 | Symbol* signature, JavaCallArguments* args, |
157 | Handle cause, |
158 | Handle loader, Handle protection_domain); |
159 | |
160 | static Handle new_exception(JavaThread* thread, Symbol* name, |
161 | Handle cause, |
162 | Handle loader, Handle protection_domain, |
163 | ExceptionMsgToUtf8Mode to_utf8_safe = safe_to_utf8); |
164 | |
165 | static Handle new_exception(JavaThread* thread, Symbol* name, |
166 | const char* message, Handle cause, |
167 | Handle loader, Handle protection_domain, |
168 | ExceptionMsgToUtf8Mode to_utf8_safe = safe_to_utf8); |
169 | |
170 | static Handle new_exception(JavaThread* thread, Symbol* name, |
171 | const char* message, |
172 | ExceptionMsgToUtf8Mode to_utf8_safe = safe_to_utf8); |
173 | |
174 | static void throw_stack_overflow_exception(JavaThread* thread, const char* file, int line, const methodHandle& method); |
175 | |
176 | static void throw_unsafe_access_internal_error(JavaThread* thread, const char* file, int line, const char* message); |
177 | |
178 | static void wrap_dynamic_exception(bool is_indy, JavaThread* thread); |
179 | |
180 | // Exception counting for error files of interesting exceptions that may have |
181 | // caused a problem for the jvm |
182 | static volatile int _stack_overflow_errors; |
183 | |
184 | static bool has_exception_counts(); |
185 | static void count_out_of_memory_exceptions(Handle exception); |
186 | static void print_exception_counts_on_error(outputStream* st); |
187 | |
188 | // for AbortVMOnException flag |
189 | static void debug_check_abort(Handle exception, const char* message = NULL__null); |
190 | static void debug_check_abort_helper(Handle exception, const char* message = NULL__null); |
191 | static void debug_check_abort(const char *value_string, const char* message = NULL__null); |
192 | |
193 | // for logging exceptions |
194 | static void log_exception(Handle exception, const char* message); |
195 | }; |
196 | |
197 | |
198 | // The THREAD & TRAPS macros facilitate the declaration of functions that throw exceptions. |
199 | // Convention: Use the TRAPS macro as the last argument of such a function; e.g.: |
200 | // |
201 | // int this_function_may_trap(int x, float y, TRAPS) |
202 | |
203 | #define THREAD__the_thread__ __the_thread__ |
204 | #define TRAPSJavaThread* __the_thread__ JavaThread* THREAD__the_thread__ |
205 | |
206 | |
207 | // The CHECK... macros should be used to pass along a THREAD reference and to check for pending |
208 | // exceptions. In special situations it is necessary to handle pending exceptions explicitly, |
209 | // in these cases the PENDING_EXCEPTION helper macros should be used. |
210 | // |
211 | // Macro naming conventions: Macros that end with _ require a result value to be returned. They |
212 | // are for functions with non-void result type. The result value is usually ignored because of |
213 | // the exception and is only needed for syntactic correctness. The _0 ending is a shortcut for |
214 | // _(0) since this is a frequent case. Example: |
215 | // |
216 | // int result = this_function_may_trap(x_arg, y_arg, CHECK_0); |
217 | // |
218 | // CAUTION: make sure that the function call using a CHECK macro is not the only statement of a |
219 | // conditional branch w/o enclosing {} braces, since the CHECK macros expand into several state- |
220 | // ments! Also make sure it is not used on a function call that is part of a return statement! |
221 | |
222 | #define PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->pending_exception()) (((ThreadShadow*)THREAD__the_thread__)->pending_exception()) |
223 | #define HAS_PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->has_pending_exception()) (((ThreadShadow*)THREAD__the_thread__)->has_pending_exception()) |
224 | #define CLEAR_PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->clear_pending_exception( )) (((ThreadShadow*)THREAD__the_thread__)->clear_pending_exception()) |
225 | |
226 | #define CHECK__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return ; (void)(0 THREAD__the_thread__); if (HAS_PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->has_pending_exception())) return ; (void)(0 |
227 | #define CHECK_(result)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return result; (void)(0 THREAD__the_thread__); if (HAS_PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->has_pending_exception())) return result; (void)(0 |
228 | #define CHECK_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0 CHECK_(0)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return 0; (void)(0 |
229 | #define CHECK_NH__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return Handle(); (void)(0 CHECK_(Handle())__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return Handle(); (void)(0 |
230 | #define CHECK_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0 CHECK_(NULL)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return __null; (void)(0 |
231 | #define CHECK_false__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return false; (void)(0 CHECK_(false)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return false; (void)(0 |
232 | #define CHECK_JNI_ERR__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return (-1); (void)(0 CHECK_(JNI_ERR)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) return (-1); (void)(0 |
233 | |
234 | // CAUTION: These macros clears all exceptions including async exceptions, use it with caution. |
235 | #define CHECK_AND_CLEAR__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_exception ()); return; } (void)(0 THREAD__the_thread__); if (HAS_PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->has_pending_exception())) { CLEAR_PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->clear_pending_exception( )); return; } (void)(0 |
236 | #define CHECK_AND_CLEAR_(result)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_exception ()); return result; } (void)(0 THREAD__the_thread__); if (HAS_PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->has_pending_exception())) { CLEAR_PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->clear_pending_exception( )); return result; } (void)(0 |
237 | #define CHECK_AND_CLEAR_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_exception ()); return 0; } (void)(0 CHECK_AND_CLEAR_(0)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_exception ()); return 0; } (void)(0 |
238 | #define CHECK_AND_CLEAR_NH__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_exception ()); return Handle(); } (void)(0 CHECK_AND_CLEAR_(Handle())__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_exception ()); return Handle(); } (void)(0 |
239 | #define CHECK_AND_CLEAR_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_exception ()); return __null; } (void)(0 CHECK_AND_CLEAR_(NULL)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_exception ()); return __null; } (void)(0 |
240 | #define CHECK_AND_CLEAR_false__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_exception ()); return false; } (void)(0 CHECK_AND_CLEAR_(false)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_exception ()); return false; } (void)(0 |
241 | |
242 | // CAUTION: These macros clears all exceptions except probable async exceptions j.l.InternalError and j.l.ThreadDeath. |
243 | // So use it with caution. |
244 | #define CLEAR_PENDING_NONASYNC_EXCEPTION(((ThreadShadow*)__the_thread__)->clear_pending_nonasync_exception ()) (((ThreadShadow*)THREAD__the_thread__)->clear_pending_nonasync_exception()) |
245 | #define CHECK_AND_CLEAR_NONASYNC__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_nonasync_exception ()); return; } (void)(0 THREAD__the_thread__); if (HAS_PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->has_pending_exception())) { CLEAR_PENDING_NONASYNC_EXCEPTION(((ThreadShadow*)__the_thread__)->clear_pending_nonasync_exception ()); return; } (void)(0 |
246 | #define CHECK_AND_CLEAR_NONASYNC_(result)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_nonasync_exception ()); return result; } (void)(0 THREAD__the_thread__); if (HAS_PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->has_pending_exception())) { CLEAR_PENDING_NONASYNC_EXCEPTION(((ThreadShadow*)__the_thread__)->clear_pending_nonasync_exception ()); return result; } (void)(0 |
247 | #define CHECK_AND_CLEAR_NONASYNC_0__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_nonasync_exception ()); return 0; } (void)(0 CHECK_AND_CLEAR_NONASYNC_(0)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_nonasync_exception ()); return 0; } (void)(0 |
248 | #define CHECK_AND_CLEAR_NONASYNC_NH__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_nonasync_exception ()); return Handle(); } (void)(0 CHECK_AND_CLEAR_NONASYNC_(Handle())__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_nonasync_exception ()); return Handle(); } (void)(0 |
249 | #define CHECK_AND_CLEAR_NONASYNC_NULL__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_nonasync_exception ()); return __null; } (void)(0 CHECK_AND_CLEAR_NONASYNC_(NULL)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_nonasync_exception ()); return __null; } (void)(0 |
250 | #define CHECK_AND_CLEAR_NONASYNC_false__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_nonasync_exception ()); return false; } (void)(0 CHECK_AND_CLEAR_NONASYNC_(false)__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { (((ThreadShadow*)__the_thread__)->clear_pending_nonasync_exception ()); return false; } (void)(0 |
251 | |
252 | // The THROW... macros should be used to throw an exception. They require a THREAD variable to be |
253 | // visible within the scope containing the THROW. Usually this is achieved by declaring the function |
254 | // with a TRAPS argument. |
255 | |
256 | #define THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 256 THREAD__the_thread__, __FILE__"/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp", __LINE__256 |
257 | |
258 | #define THROW_OOP(e){ Exceptions::_throw_oop(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 258, e); return; } \ |
259 | { Exceptions::_throw_oop(THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 259, e); return; } |
260 | |
261 | #define THROW_HANDLE(e){ Exceptions::_throw(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 261, e); return; } \ |
262 | { Exceptions::_throw(THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 262, e); return; } |
263 | |
264 | #define THROW(name){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 264, name, __null); return; } \ |
265 | { Exceptions::_throw_msg(THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 265, name, NULL__null); return; } |
266 | |
267 | #define THROW_MSG(name, message){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 267, name, message); return; } \ |
268 | { Exceptions::_throw_msg(THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 268, name, message); return; } |
269 | |
270 | #define THROW_CAUSE(name, cause){ Exceptions::_throw_cause(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 270, name, cause); return; } \ |
271 | { Exceptions::_throw_cause(THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 271, name, cause); return; } |
272 | |
273 | #define THROW_MSG_LOADER(name, message, loader, protection_domain){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 273, name, message, loader, protection_domain); return; } \ |
274 | { Exceptions::_throw_msg(THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 274, name, message, loader, protection_domain); return; } |
275 | |
276 | #define THROW_ARG(name, signature, args){ Exceptions::_throw_args(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 276, name, signature, args); return; } \ |
277 | { Exceptions::_throw_args(THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 277, name, signature, args); return; } |
278 | |
279 | #define THROW_OOP_(e, result){ Exceptions::_throw_oop(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 279, e); return result; } \ |
280 | { Exceptions::_throw_oop(THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 280, e); return result; } |
281 | |
282 | #define THROW_HANDLE_(e, result){ Exceptions::_throw(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 282, e); return result; } \ |
283 | { Exceptions::_throw(THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 283, e); return result; } |
284 | |
285 | #define THROW_(name, result){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 285, name, __null); return result; } \ |
286 | { Exceptions::_throw_msg(THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 286, name, NULL__null); return result; } |
287 | |
288 | #define THROW_MSG_(name, message, result){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 288, name, message); return result; } \ |
289 | { Exceptions::_throw_msg(THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 289, name, message); return result; } |
290 | |
291 | #define THROW_MSG_LOADER_(name, message, loader, protection_domain, result){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 291, name, message, loader, protection_domain); return result ; } \ |
292 | { Exceptions::_throw_msg(THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 292, name, message, loader, protection_domain); return result; } |
293 | |
294 | #define THROW_ARG_(name, signature, args, result){ Exceptions::_throw_args(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 294, name, signature, args); return result; } \ |
295 | { Exceptions::_throw_args(THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 295, name, signature, args); return result; } |
296 | |
297 | #define THROW_MSG_CAUSE(name, message, cause){ Exceptions::_throw_msg_cause(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 297, name, message, cause); return; } \ |
298 | { Exceptions::_throw_msg_cause(THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 298, name, message, cause); return; } |
299 | |
300 | #define THROW_MSG_CAUSE_(name, message, cause, result){ Exceptions::_throw_msg_cause(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 300, name, message, cause); return result; } \ |
301 | { Exceptions::_throw_msg_cause(THREAD_AND_LOCATION__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 301, name, message, cause); return result; } |
302 | |
303 | |
304 | #define THROW_OOP_0(e){ Exceptions::_throw_oop(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 304, e); return 0; } THROW_OOP_(e, 0){ Exceptions::_throw_oop(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 304, e); return 0; } |
305 | #define THROW_HANDLE_0(e){ Exceptions::_throw(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 305, e); return 0; } THROW_HANDLE_(e, 0){ Exceptions::_throw(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 305, e); return 0; } |
306 | #define THROW_0(name){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 306, name, __null); return 0; } THROW_(name, 0){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 306, name, __null); return 0; } |
307 | #define THROW_MSG_0(name, message){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 307, name, message); return 0; } THROW_MSG_(name, message, 0){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 307, name, message); return 0; } |
308 | #define THROW_WRAPPED_0(name, oop_to_wrap)THROW_WRAPPED_(name, oop_to_wrap, 0) THROW_WRAPPED_(name, oop_to_wrap, 0) |
309 | #define THROW_ARG_0(name, signature, arg){ Exceptions::_throw_args(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 309, name, signature, arg); return 0; } THROW_ARG_(name, signature, arg, 0){ Exceptions::_throw_args(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 309, name, signature, arg); return 0; } |
310 | #define THROW_MSG_CAUSE_0(name, message, cause){ Exceptions::_throw_msg_cause(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 310, name, message, cause); return 0; } THROW_MSG_CAUSE_(name, message, cause, 0){ Exceptions::_throw_msg_cause(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 310, name, message, cause); return 0; } |
311 | #define THROW_MSG_CAUSE_NULL(name, message, cause){ Exceptions::_throw_msg_cause(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 311, name, message, cause); return __null; } THROW_MSG_CAUSE_(name, message, cause, NULL){ Exceptions::_throw_msg_cause(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 311, name, message, cause); return __null; } |
312 | |
313 | #define THROW_NULL(name){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 313, name, __null); return __null; } THROW_(name, NULL){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 313, name, __null); return __null; } |
314 | #define THROW_MSG_NULL(name, message){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 314, name, message); return __null; } THROW_MSG_(name, message, NULL){ Exceptions::_throw_msg(__the_thread__, "/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 314, name, message); return __null; } |
315 | |
316 | // The CATCH macro checks that no exception has been thrown by a function; it is used at |
317 | // call sites about which is statically known that the callee cannot throw an exception |
318 | // even though it is declared with TRAPS. |
319 | |
320 | #define CATCH__the_thread__); if ((((ThreadShadow*)__the_thread__)->has_pending_exception ())) { oop ex = (((ThreadShadow*)__the_thread__)->pending_exception ()); (((ThreadShadow*)__the_thread__)->clear_pending_exception ()); ex->print(); do { if (!(false)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 320, "assert(" "false" ") failed", "CATCH"); ::breakpoint() ; } } while (0); } (void)(0 \ |
321 | THREAD__the_thread__); if (HAS_PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->has_pending_exception())) { \ |
322 | oop ex = PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->pending_exception()); \ |
323 | CLEAR_PENDING_EXCEPTION(((ThreadShadow*)__the_thread__)->clear_pending_exception( )); \ |
324 | DEBUG_ONLY(ex->print();)ex->print(); \ |
325 | assert(false, "CATCH")do { if (!(false)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/utilities/exceptions.hpp" , 325, "assert(" "false" ") failed", "CATCH"); ::breakpoint() ; } } while (0); \ |
326 | } (void)(0 |
327 | |
328 | // ExceptionMark is a stack-allocated helper class for local exception handling. |
329 | // It is used with the EXCEPTION_MARK macro. |
330 | |
331 | class ExceptionMark { |
332 | private: |
333 | JavaThread* _thread; |
334 | inline void check_no_pending_exception(); |
335 | |
336 | public: |
337 | ExceptionMark(); |
338 | ExceptionMark(JavaThread* thread); |
339 | ~ExceptionMark(); |
340 | |
341 | JavaThread* thread() { |
342 | return _thread; |
343 | } |
344 | }; |
345 | |
346 | // Use an EXCEPTION_MARK for 'local' exceptions. EXCEPTION_MARK makes sure that no |
347 | // pending exception exists upon entering its scope and tests that no pending exception |
348 | // exists when leaving the scope. |
349 | |
350 | // See also preserveException.hpp for PreserveExceptionMark |
351 | // which preserves pre-existing exceptions and does not allow new |
352 | // exceptions. |
353 | |
354 | #define EXCEPTION_MARKExceptionMark __em; JavaThread* __the_thread__ = __em.thread( ); ExceptionMark __em; JavaThread* THREAD__the_thread__ = __em.thread(); |
355 | |
356 | #endif // SHARE_UTILITIES_EXCEPTIONS_HPP |
1 | /* |
2 | * Copyright (c) 1997, 2020, 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_OOPS_OOPSHIERARCHY_HPP |
26 | #define SHARE_OOPS_OOPSHIERARCHY_HPP |
27 | |
28 | #include "metaprogramming/integralConstant.hpp" |
29 | #include "metaprogramming/primitiveConversions.hpp" |
30 | #include "utilities/globalDefinitions.hpp" |
31 | |
32 | // OBJECT hierarchy |
33 | // This hierarchy is a representation hierarchy, i.e. if A is a superclass |
34 | // of B, A's representation is a prefix of B's representation. |
35 | |
36 | // Global offset instead of address for an oop within a java object. |
37 | enum class narrowOop : uint32_t { null = 0 }; |
38 | |
39 | // If compressed klass pointers then use narrowKlass. |
40 | typedef juint narrowKlass; |
41 | |
42 | typedef void* OopOrNarrowOopStar; |
43 | |
44 | #ifndef CHECK_UNHANDLED_OOPS1 |
45 | |
46 | typedef class oopDesc* oop; |
47 | typedef class instanceOopDesc* instanceOop; |
48 | typedef class arrayOopDesc* arrayOop; |
49 | typedef class objArrayOopDesc* objArrayOop; |
50 | typedef class typeArrayOopDesc* typeArrayOop; |
51 | |
52 | #else |
53 | |
54 | // When CHECK_UNHANDLED_OOPS is defined, an "oop" is a class with a |
55 | // carefully chosen set of constructors and conversion operators to go |
56 | // to and from the underlying oopDesc pointer type. |
57 | // |
58 | // Because oop and its subclasses <type>Oop are class types, arbitrary |
59 | // conversions are not accepted by the compiler. Applying a cast to |
60 | // an oop will cause the best matched conversion operator to be |
61 | // invoked returning the underlying oopDesc* type if appropriate. |
62 | // No copy constructors, explicit user conversions or operators of |
63 | // numerical type should be defined within the oop class. Most C++ |
64 | // compilers will issue a compile time error concerning the overloading |
65 | // ambiguity between operators of numerical and pointer types. If |
66 | // a conversion to or from an oop to a numerical type is needed, |
67 | // use the inline template methods, cast_*_oop, defined below. |
68 | // |
69 | // Converting NULL to oop to Handle implicit is no longer accepted by the |
70 | // compiler because there are too many steps in the conversion. Use Handle() |
71 | // instead, which generates less code anyway. |
72 | |
73 | class Thread; |
74 | class oopDesc; |
75 | |
76 | extern "C" bool CheckUnhandledOops; |
77 | |
78 | class oop { |
79 | oopDesc* _o; |
80 | |
81 | void register_oop(); |
82 | void unregister_oop(); |
83 | |
84 | void register_if_checking() { |
85 | if (CheckUnhandledOops) register_oop(); |
86 | } |
87 | |
88 | public: |
89 | oop() : _o(nullptr) { register_if_checking(); } |
90 | oop(const oop& o) : _o(o._o) { register_if_checking(); } |
91 | oop(oopDesc* o) : _o(o) { register_if_checking(); } |
92 | ~oop() { |
93 | if (CheckUnhandledOops) unregister_oop(); |
94 | } |
95 | |
96 | oopDesc* obj() const { return _o; } |
97 | oopDesc* operator->() const { return _o; } |
98 | operator oopDesc* () const { return _o; } |
99 | |
100 | bool operator==(const oop& o) const { return _o == o._o; } |
101 | bool operator!=(const oop& o) const { return _o != o._o; } |
102 | |
103 | bool operator==(std::nullptr_t) const { return _o == nullptr; } |
104 | bool operator!=(std::nullptr_t) const { return _o != nullptr; } |
105 | |
106 | oop& operator=(const oop& o) { _o = o._o; return *this; } |
107 | }; |
108 | |
109 | template<> |
110 | struct PrimitiveConversions::Translate<oop> : public TrueType { |
111 | typedef oop Value; |
112 | typedef oopDesc* Decayed; |
113 | |
114 | static Decayed decay(Value x) { return x.obj(); } |
115 | static Value recover(Decayed x) { return oop(x); } |
116 | }; |
117 | |
118 | #define DEF_OOP(type)class typeOopDesc; class typeOop : public oop { public: typeOop () : oop() {} typeOop(const typeOop& o) : oop(o) {} typeOop (const oop& o) : oop(o) {} typeOop(typeOopDesc* o) : oop( (oopDesc*)o) {} operator typeOopDesc* () const { return (typeOopDesc *)obj(); } typeOopDesc* operator->() const { return (typeOopDesc *)obj(); } typeOop& operator=(const typeOop& o) { oop ::operator=(o); return *this; } }; template<> struct PrimitiveConversions ::Translate<typeOop> : public TrueType { typedef typeOop Value; typedef typeOopDesc* Decayed; static Decayed decay(Value x) { return (typeOopDesc*)x.obj(); } static Value recover(Decayed x) { return typeOop(x); } }; \ |
119 | class type##OopDesc; \ |
120 | class type##Oop : public oop { \ |
121 | public: \ |
122 | type##Oop() : oop() {} \ |
123 | type##Oop(const type##Oop& o) : oop(o) {} \ |
124 | type##Oop(const oop& o) : oop(o) {} \ |
125 | type##Oop(type##OopDesc* o) : oop((oopDesc*)o) {} \ |
126 | operator type##OopDesc* () const { return (type##OopDesc*)obj(); } \ |
127 | type##OopDesc* operator->() const { \ |
128 | return (type##OopDesc*)obj(); \ |
129 | } \ |
130 | type##Oop& operator=(const type##Oop& o) { \ |
131 | oop::operator=(o); \ |
132 | return *this; \ |
133 | } \ |
134 | }; \ |
135 | \ |
136 | template<> \ |
137 | struct PrimitiveConversions::Translate<type##Oop> : public TrueType { \ |
138 | typedef type##Oop Value; \ |
139 | typedef type##OopDesc* Decayed; \ |
140 | \ |
141 | static Decayed decay(Value x) { return (type##OopDesc*)x.obj(); } \ |
142 | static Value recover(Decayed x) { return type##Oop(x); } \ |
143 | }; |
144 | |
145 | DEF_OOP(instance)class instanceOopDesc; class instanceOop : public oop { public : instanceOop() : oop() {} instanceOop(const instanceOop& o) : oop(o) {} instanceOop(const oop& o) : oop(o) {} instanceOop (instanceOopDesc* o) : oop((oopDesc*)o) {} operator instanceOopDesc * () const { return (instanceOopDesc*)obj(); } instanceOopDesc * operator->() const { return (instanceOopDesc*)obj(); } instanceOop & operator=(const instanceOop& o) { oop::operator=(o) ; return *this; } }; template<> struct PrimitiveConversions ::Translate<instanceOop> : public TrueType { typedef instanceOop Value; typedef instanceOopDesc* Decayed; static Decayed decay (Value x) { return (instanceOopDesc*)x.obj(); } static Value recover (Decayed x) { return instanceOop(x); } };; |
146 | DEF_OOP(array)class arrayOopDesc; class arrayOop : public oop { public: arrayOop () : oop() {} arrayOop(const arrayOop& o) : oop(o) {} arrayOop (const oop& o) : oop(o) {} arrayOop(arrayOopDesc* o) : oop ((oopDesc*)o) {} operator arrayOopDesc* () const { return (arrayOopDesc *)obj(); } arrayOopDesc* operator->() const { return (arrayOopDesc *)obj(); } arrayOop& operator=(const arrayOop& o) { oop ::operator=(o); return *this; } }; template<> struct PrimitiveConversions ::Translate<arrayOop> : public TrueType { typedef arrayOop Value; typedef arrayOopDesc* Decayed; static Decayed decay(Value x) { return (arrayOopDesc*)x.obj(); } static Value recover(Decayed x) { return arrayOop(x); } };; |
147 | DEF_OOP(objArray)class objArrayOopDesc; class objArrayOop : public oop { public : objArrayOop() : oop() {} objArrayOop(const objArrayOop& o) : oop(o) {} objArrayOop(const oop& o) : oop(o) {} objArrayOop (objArrayOopDesc* o) : oop((oopDesc*)o) {} operator objArrayOopDesc * () const { return (objArrayOopDesc*)obj(); } objArrayOopDesc * operator->() const { return (objArrayOopDesc*)obj(); } objArrayOop & operator=(const objArrayOop& o) { oop::operator=(o) ; return *this; } }; template<> struct PrimitiveConversions ::Translate<objArrayOop> : public TrueType { typedef objArrayOop Value; typedef objArrayOopDesc* Decayed; static Decayed decay (Value x) { return (objArrayOopDesc*)x.obj(); } static Value recover (Decayed x) { return objArrayOop(x); } };; |
148 | DEF_OOP(typeArray)class typeArrayOopDesc; class typeArrayOop : public oop { public : typeArrayOop() : oop() {} typeArrayOop(const typeArrayOop& o) : oop(o) {} typeArrayOop(const oop& o) : oop(o) {} typeArrayOop (typeArrayOopDesc* o) : oop((oopDesc*)o) {} operator typeArrayOopDesc * () const { return (typeArrayOopDesc*)obj(); } typeArrayOopDesc * operator->() const { return (typeArrayOopDesc*)obj(); } typeArrayOop & operator=(const typeArrayOop& o) { oop::operator=(o ); return *this; } }; template<> struct PrimitiveConversions ::Translate<typeArrayOop> : public TrueType { typedef typeArrayOop Value; typedef typeArrayOopDesc* Decayed; static Decayed decay (Value x) { return (typeArrayOopDesc*)x.obj(); } static Value recover(Decayed x) { return typeArrayOop(x); } };; |
149 | |
150 | #endif // CHECK_UNHANDLED_OOPS |
151 | |
152 | // Cast functions to convert to and from oops. |
153 | template <typename T> inline oop cast_to_oop(T value) { |
154 | return (oopDesc*)value; |
155 | } |
156 | template <typename T> inline T cast_from_oop(oop o) { |
157 | return (T)(CHECK_UNHANDLED_OOPS_ONLY((oopDesc*))(oopDesc*)o); |
158 | } |
159 | |
160 | // The metadata hierarchy is separate from the oop hierarchy |
161 | |
162 | // class MetaspaceObj |
163 | class ConstMethod; |
164 | class ConstantPoolCache; |
165 | class MethodData; |
166 | // class Metadata |
167 | class Method; |
168 | class ConstantPool; |
169 | // class CHeapObj |
170 | class CompiledICHolder; |
171 | |
172 | |
173 | // The klass hierarchy is separate from the oop hierarchy. |
174 | |
175 | class Klass; |
176 | class InstanceKlass; |
177 | class InstanceMirrorKlass; |
178 | class InstanceClassLoaderKlass; |
179 | class InstanceRefKlass; |
180 | class ArrayKlass; |
181 | class ObjArrayKlass; |
182 | class TypeArrayKlass; |
183 | |
184 | #endif // SHARE_OOPS_OOPSHIERARCHY_HPP |