1 | /* |
2 | * Copyright (c) 1998, 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 | #include "precompiled.hpp" |
26 | #include "jvm.h" |
27 | #include "code/codeBlob.hpp" |
28 | #include "code/codeCache.hpp" |
29 | #include "code/icBuffer.hpp" |
30 | #include "code/relocInfo.hpp" |
31 | #include "code/vtableStubs.hpp" |
32 | #include "compiler/disassembler.hpp" |
33 | #include "interpreter/bytecode.hpp" |
34 | #include "interpreter/interpreter.hpp" |
35 | #include "memory/allocation.inline.hpp" |
36 | #include "memory/heap.hpp" |
37 | #include "memory/resourceArea.hpp" |
38 | #include "oops/oop.inline.hpp" |
39 | #include "prims/forte.hpp" |
40 | #include "runtime/handles.inline.hpp" |
41 | #include "runtime/interfaceSupport.inline.hpp" |
42 | #include "runtime/mutexLocker.hpp" |
43 | #include "runtime/safepoint.hpp" |
44 | #include "runtime/sharedRuntime.hpp" |
45 | #include "runtime/vframe.hpp" |
46 | #include "services/memoryService.hpp" |
47 | #include "utilities/align.hpp" |
48 | #ifdef COMPILER1 |
49 | #include "c1/c1_Runtime1.hpp" |
50 | #endif |
51 | |
52 | const char* CodeBlob::compiler_name() const { |
53 | return compilertype2name(_type); |
54 | } |
55 | |
56 | unsigned int CodeBlob::align_code_offset(int offset) { |
57 | // align the size to CodeEntryAlignment |
58 | return |
59 | ((offset + (int)CodeHeap::header_size() + (CodeEntryAlignment-1)) & ~(CodeEntryAlignment-1)) |
60 | - (int)CodeHeap::header_size(); |
61 | } |
62 | |
63 | |
64 | // This must be consistent with the CodeBlob constructor's layout actions. |
65 | unsigned int CodeBlob::allocation_size(CodeBuffer* cb, int ) { |
66 | unsigned int size = header_size; |
67 | size += align_up(cb->total_relocation_size(), oopSize); |
68 | // align the size to CodeEntryAlignment |
69 | size = align_code_offset(size); |
70 | size += align_up(cb->total_content_size(), oopSize); |
71 | size += align_up(cb->total_oop_size(), oopSize); |
72 | size += align_up(cb->total_metadata_size(), oopSize); |
73 | return size; |
74 | } |
75 | |
76 | CodeBlob::CodeBlob(const char* name, CompilerType type, const CodeBlobLayout& layout, int frame_complete_offset, int frame_size, ImmutableOopMapSet* oop_maps, bool caller_must_gc_arguments) : |
77 | _type(type), |
78 | _size(layout.size()), |
79 | _header_size(layout.header_size()), |
80 | _frame_complete_offset(frame_complete_offset), |
81 | _data_offset(layout.data_offset()), |
82 | _frame_size(frame_size), |
83 | _code_begin(layout.code_begin()), |
84 | _code_end(layout.code_end()), |
85 | _content_begin(layout.content_begin()), |
86 | _data_end(layout.data_end()), |
87 | _relocation_begin(layout.relocation_begin()), |
88 | _relocation_end(layout.relocation_end()), |
89 | _oop_maps(oop_maps), |
90 | _caller_must_gc_arguments(caller_must_gc_arguments), |
91 | _strings(CodeStrings()), |
92 | _name(name) |
93 | { |
94 | assert(is_aligned(layout.size(), oopSize), "unaligned size" ); |
95 | assert(is_aligned(layout.header_size(), oopSize), "unaligned size" ); |
96 | assert(is_aligned(layout.relocation_size(), oopSize), "unaligned size" ); |
97 | assert(layout.code_end() == layout.content_end(), "must be the same - see code_end()" ); |
98 | #ifdef COMPILER1 |
99 | // probably wrong for tiered |
100 | assert(_frame_size >= -1, "must use frame size or -1 for runtime stubs" ); |
101 | #endif // COMPILER1 |
102 | } |
103 | |
104 | CodeBlob::CodeBlob(const char* name, CompilerType type, const CodeBlobLayout& layout, CodeBuffer* cb, int frame_complete_offset, int frame_size, OopMapSet* oop_maps, bool caller_must_gc_arguments) : |
105 | _type(type), |
106 | _size(layout.size()), |
107 | _header_size(layout.header_size()), |
108 | _frame_complete_offset(frame_complete_offset), |
109 | _data_offset(layout.data_offset()), |
110 | _frame_size(frame_size), |
111 | _code_begin(layout.code_begin()), |
112 | _code_end(layout.code_end()), |
113 | _content_begin(layout.content_begin()), |
114 | _data_end(layout.data_end()), |
115 | _relocation_begin(layout.relocation_begin()), |
116 | _relocation_end(layout.relocation_end()), |
117 | _caller_must_gc_arguments(caller_must_gc_arguments), |
118 | _strings(CodeStrings()), |
119 | _name(name) |
120 | { |
121 | assert(is_aligned(_size, oopSize), "unaligned size" ); |
122 | assert(is_aligned(_header_size, oopSize), "unaligned size" ); |
123 | assert(_data_offset <= _size, "codeBlob is too small" ); |
124 | assert(layout.code_end() == layout.content_end(), "must be the same - see code_end()" ); |
125 | |
126 | set_oop_maps(oop_maps); |
127 | #ifdef COMPILER1 |
128 | // probably wrong for tiered |
129 | assert(_frame_size >= -1, "must use frame size or -1 for runtime stubs" ); |
130 | #endif // COMPILER1 |
131 | } |
132 | |
133 | |
134 | // Creates a simple CodeBlob. Sets up the size of the different regions. |
135 | RuntimeBlob::RuntimeBlob(const char* name, int , int size, int frame_complete, int locs_size) |
136 | : CodeBlob(name, compiler_none, CodeBlobLayout((address) this, size, header_size, locs_size, size), frame_complete, 0, NULL, false /* caller_must_gc_arguments */) |
137 | { |
138 | assert(is_aligned(locs_size, oopSize), "unaligned size" ); |
139 | } |
140 | |
141 | |
142 | // Creates a RuntimeBlob from a CodeBuffer |
143 | // and copy code and relocation info. |
144 | RuntimeBlob::RuntimeBlob( |
145 | const char* name, |
146 | CodeBuffer* cb, |
147 | int , |
148 | int size, |
149 | int frame_complete, |
150 | int frame_size, |
151 | OopMapSet* oop_maps, |
152 | bool caller_must_gc_arguments |
153 | ) : CodeBlob(name, compiler_none, CodeBlobLayout((address) this, size, header_size, cb), cb, frame_complete, frame_size, oop_maps, caller_must_gc_arguments) { |
154 | cb->copy_code_and_locs_to(this); |
155 | } |
156 | |
157 | void CodeBlob::flush() { |
158 | if (_oop_maps) { |
159 | FREE_C_HEAP_ARRAY(unsigned char, _oop_maps); |
160 | _oop_maps = NULL; |
161 | } |
162 | _strings.free(); |
163 | } |
164 | |
165 | void CodeBlob::set_oop_maps(OopMapSet* p) { |
166 | // Danger Will Robinson! This method allocates a big |
167 | // chunk of memory, its your job to free it. |
168 | if (p != NULL) { |
169 | _oop_maps = ImmutableOopMapSet::build_from(p); |
170 | } else { |
171 | _oop_maps = NULL; |
172 | } |
173 | } |
174 | |
175 | |
176 | void RuntimeBlob::trace_new_stub(RuntimeBlob* stub, const char* name1, const char* name2) { |
177 | // Do not hold the CodeCache lock during name formatting. |
178 | assert(!CodeCache_lock->owned_by_self(), "release CodeCache before registering the stub" ); |
179 | |
180 | if (stub != NULL) { |
181 | char stub_id[256]; |
182 | assert(strlen(name1) + strlen(name2) < sizeof(stub_id), "" ); |
183 | jio_snprintf(stub_id, sizeof(stub_id), "%s%s" , name1, name2); |
184 | if (PrintStubCode) { |
185 | ttyLocker ttyl; |
186 | tty->print_cr("- - - [BEGIN] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -" ); |
187 | tty->print_cr("Decoding %s " INTPTR_FORMAT, stub_id, (intptr_t) stub); |
188 | Disassembler::decode(stub->code_begin(), stub->code_end(), tty); |
189 | if ((stub->oop_maps() != NULL) && AbstractDisassembler::show_structs()) { |
190 | tty->print_cr("- - - [OOP MAPS]- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -" ); |
191 | stub->oop_maps()->print(); |
192 | } |
193 | tty->print_cr("- - - [END] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -" ); |
194 | tty->cr(); |
195 | } |
196 | Forte::register_stub(stub_id, stub->code_begin(), stub->code_end()); |
197 | |
198 | if (JvmtiExport::should_post_dynamic_code_generated()) { |
199 | const char* stub_name = name2; |
200 | if (name2[0] == '\0') stub_name = name1; |
201 | JvmtiExport::post_dynamic_code_generated(stub_name, stub->code_begin(), stub->code_end()); |
202 | } |
203 | } |
204 | |
205 | // Track memory usage statistic after releasing CodeCache_lock |
206 | MemoryService::track_code_cache_memory_usage(); |
207 | } |
208 | |
209 | const ImmutableOopMap* CodeBlob::oop_map_for_return_address(address return_address) { |
210 | assert(_oop_maps != NULL, "nope" ); |
211 | return _oop_maps->find_map_at_offset((intptr_t) return_address - (intptr_t) code_begin()); |
212 | } |
213 | |
214 | void CodeBlob::print_code() { |
215 | ResourceMark m; |
216 | Disassembler::decode(this, tty); |
217 | } |
218 | |
219 | //---------------------------------------------------------------------------------------------------- |
220 | // Implementation of BufferBlob |
221 | |
222 | |
223 | BufferBlob::BufferBlob(const char* name, int size) |
224 | : RuntimeBlob(name, sizeof(BufferBlob), size, CodeOffsets::frame_never_safe, /*locs_size:*/ 0) |
225 | {} |
226 | |
227 | BufferBlob* BufferBlob::create(const char* name, int buffer_size) { |
228 | ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock |
229 | |
230 | BufferBlob* blob = NULL; |
231 | unsigned int size = sizeof(BufferBlob); |
232 | // align the size to CodeEntryAlignment |
233 | size = CodeBlob::align_code_offset(size); |
234 | size += align_up(buffer_size, oopSize); |
235 | assert(name != NULL, "must provide a name" ); |
236 | { |
237 | MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); |
238 | blob = new (size) BufferBlob(name, size); |
239 | } |
240 | // Track memory usage statistic after releasing CodeCache_lock |
241 | MemoryService::track_code_cache_memory_usage(); |
242 | |
243 | return blob; |
244 | } |
245 | |
246 | |
247 | BufferBlob::BufferBlob(const char* name, int size, CodeBuffer* cb) |
248 | : RuntimeBlob(name, cb, sizeof(BufferBlob), size, CodeOffsets::frame_never_safe, 0, NULL) |
249 | {} |
250 | |
251 | BufferBlob* BufferBlob::create(const char* name, CodeBuffer* cb) { |
252 | ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock |
253 | |
254 | BufferBlob* blob = NULL; |
255 | unsigned int size = CodeBlob::allocation_size(cb, sizeof(BufferBlob)); |
256 | assert(name != NULL, "must provide a name" ); |
257 | { |
258 | MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); |
259 | blob = new (size) BufferBlob(name, size, cb); |
260 | } |
261 | // Track memory usage statistic after releasing CodeCache_lock |
262 | MemoryService::track_code_cache_memory_usage(); |
263 | |
264 | return blob; |
265 | } |
266 | |
267 | void* BufferBlob::operator new(size_t s, unsigned size) throw() { |
268 | return CodeCache::allocate(size, CodeBlobType::NonNMethod); |
269 | } |
270 | |
271 | void BufferBlob::free(BufferBlob *blob) { |
272 | assert(blob != NULL, "caller must check for NULL" ); |
273 | ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock |
274 | blob->flush(); |
275 | { |
276 | MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); |
277 | CodeCache::free((RuntimeBlob*)blob); |
278 | } |
279 | // Track memory usage statistic after releasing CodeCache_lock |
280 | MemoryService::track_code_cache_memory_usage(); |
281 | } |
282 | |
283 | |
284 | //---------------------------------------------------------------------------------------------------- |
285 | // Implementation of AdapterBlob |
286 | |
287 | AdapterBlob::AdapterBlob(int size, CodeBuffer* cb) : |
288 | BufferBlob("I2C/C2I adapters" , size, cb) { |
289 | CodeCache::commit(this); |
290 | } |
291 | |
292 | AdapterBlob* AdapterBlob::create(CodeBuffer* cb) { |
293 | ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock |
294 | |
295 | AdapterBlob* blob = NULL; |
296 | unsigned int size = CodeBlob::allocation_size(cb, sizeof(AdapterBlob)); |
297 | { |
298 | MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); |
299 | blob = new (size) AdapterBlob(size, cb); |
300 | } |
301 | // Track memory usage statistic after releasing CodeCache_lock |
302 | MemoryService::track_code_cache_memory_usage(); |
303 | |
304 | return blob; |
305 | } |
306 | |
307 | VtableBlob::VtableBlob(const char* name, int size) : |
308 | BufferBlob(name, size) { |
309 | } |
310 | |
311 | VtableBlob* VtableBlob::create(const char* name, int buffer_size) { |
312 | ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock |
313 | |
314 | VtableBlob* blob = NULL; |
315 | unsigned int size = sizeof(VtableBlob); |
316 | // align the size to CodeEntryAlignment |
317 | size = align_code_offset(size); |
318 | size += align_up(buffer_size, oopSize); |
319 | assert(name != NULL, "must provide a name" ); |
320 | { |
321 | MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); |
322 | blob = new (size) VtableBlob(name, size); |
323 | } |
324 | // Track memory usage statistic after releasing CodeCache_lock |
325 | MemoryService::track_code_cache_memory_usage(); |
326 | |
327 | return blob; |
328 | } |
329 | |
330 | //---------------------------------------------------------------------------------------------------- |
331 | // Implementation of MethodHandlesAdapterBlob |
332 | |
333 | MethodHandlesAdapterBlob* MethodHandlesAdapterBlob::create(int buffer_size) { |
334 | ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock |
335 | |
336 | MethodHandlesAdapterBlob* blob = NULL; |
337 | unsigned int size = sizeof(MethodHandlesAdapterBlob); |
338 | // align the size to CodeEntryAlignment |
339 | size = CodeBlob::align_code_offset(size); |
340 | size += align_up(buffer_size, oopSize); |
341 | { |
342 | MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); |
343 | blob = new (size) MethodHandlesAdapterBlob(size); |
344 | if (blob == NULL) { |
345 | vm_exit_out_of_memory(size, OOM_MALLOC_ERROR, "CodeCache: no room for method handle adapter blob" ); |
346 | } |
347 | } |
348 | // Track memory usage statistic after releasing CodeCache_lock |
349 | MemoryService::track_code_cache_memory_usage(); |
350 | |
351 | return blob; |
352 | } |
353 | |
354 | //---------------------------------------------------------------------------------------------------- |
355 | // Implementation of RuntimeStub |
356 | |
357 | RuntimeStub::RuntimeStub( |
358 | const char* name, |
359 | CodeBuffer* cb, |
360 | int size, |
361 | int frame_complete, |
362 | int frame_size, |
363 | OopMapSet* oop_maps, |
364 | bool caller_must_gc_arguments |
365 | ) |
366 | : RuntimeBlob(name, cb, sizeof(RuntimeStub), size, frame_complete, frame_size, oop_maps, caller_must_gc_arguments) |
367 | { |
368 | } |
369 | |
370 | RuntimeStub* RuntimeStub::new_runtime_stub(const char* stub_name, |
371 | CodeBuffer* cb, |
372 | int frame_complete, |
373 | int frame_size, |
374 | OopMapSet* oop_maps, |
375 | bool caller_must_gc_arguments) |
376 | { |
377 | RuntimeStub* stub = NULL; |
378 | ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock |
379 | { |
380 | MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); |
381 | unsigned int size = CodeBlob::allocation_size(cb, sizeof(RuntimeStub)); |
382 | stub = new (size) RuntimeStub(stub_name, cb, size, frame_complete, frame_size, oop_maps, caller_must_gc_arguments); |
383 | } |
384 | |
385 | trace_new_stub(stub, "RuntimeStub - " , stub_name); |
386 | |
387 | return stub; |
388 | } |
389 | |
390 | |
391 | void* RuntimeStub::operator new(size_t s, unsigned size) throw() { |
392 | void* p = CodeCache::allocate(size, CodeBlobType::NonNMethod); |
393 | if (!p) fatal("Initial size of CodeCache is too small" ); |
394 | return p; |
395 | } |
396 | |
397 | // operator new shared by all singletons: |
398 | void* SingletonBlob::operator new(size_t s, unsigned size) throw() { |
399 | void* p = CodeCache::allocate(size, CodeBlobType::NonNMethod); |
400 | if (!p) fatal("Initial size of CodeCache is too small" ); |
401 | return p; |
402 | } |
403 | |
404 | |
405 | //---------------------------------------------------------------------------------------------------- |
406 | // Implementation of DeoptimizationBlob |
407 | |
408 | DeoptimizationBlob::DeoptimizationBlob( |
409 | CodeBuffer* cb, |
410 | int size, |
411 | OopMapSet* oop_maps, |
412 | int unpack_offset, |
413 | int unpack_with_exception_offset, |
414 | int unpack_with_reexecution_offset, |
415 | int frame_size |
416 | ) |
417 | : SingletonBlob("DeoptimizationBlob" , cb, sizeof(DeoptimizationBlob), size, frame_size, oop_maps) |
418 | { |
419 | _unpack_offset = unpack_offset; |
420 | _unpack_with_exception = unpack_with_exception_offset; |
421 | _unpack_with_reexecution = unpack_with_reexecution_offset; |
422 | #ifdef COMPILER1 |
423 | _unpack_with_exception_in_tls = -1; |
424 | #endif |
425 | } |
426 | |
427 | |
428 | DeoptimizationBlob* DeoptimizationBlob::create( |
429 | CodeBuffer* cb, |
430 | OopMapSet* oop_maps, |
431 | int unpack_offset, |
432 | int unpack_with_exception_offset, |
433 | int unpack_with_reexecution_offset, |
434 | int frame_size) |
435 | { |
436 | DeoptimizationBlob* blob = NULL; |
437 | ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock |
438 | { |
439 | MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); |
440 | unsigned int size = CodeBlob::allocation_size(cb, sizeof(DeoptimizationBlob)); |
441 | blob = new (size) DeoptimizationBlob(cb, |
442 | size, |
443 | oop_maps, |
444 | unpack_offset, |
445 | unpack_with_exception_offset, |
446 | unpack_with_reexecution_offset, |
447 | frame_size); |
448 | } |
449 | |
450 | trace_new_stub(blob, "DeoptimizationBlob" ); |
451 | |
452 | return blob; |
453 | } |
454 | |
455 | |
456 | //---------------------------------------------------------------------------------------------------- |
457 | // Implementation of UncommonTrapBlob |
458 | |
459 | #ifdef COMPILER2 |
460 | UncommonTrapBlob::UncommonTrapBlob( |
461 | CodeBuffer* cb, |
462 | int size, |
463 | OopMapSet* oop_maps, |
464 | int frame_size |
465 | ) |
466 | : SingletonBlob("UncommonTrapBlob" , cb, sizeof(UncommonTrapBlob), size, frame_size, oop_maps) |
467 | {} |
468 | |
469 | |
470 | UncommonTrapBlob* UncommonTrapBlob::create( |
471 | CodeBuffer* cb, |
472 | OopMapSet* oop_maps, |
473 | int frame_size) |
474 | { |
475 | UncommonTrapBlob* blob = NULL; |
476 | ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock |
477 | { |
478 | MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); |
479 | unsigned int size = CodeBlob::allocation_size(cb, sizeof(UncommonTrapBlob)); |
480 | blob = new (size) UncommonTrapBlob(cb, size, oop_maps, frame_size); |
481 | } |
482 | |
483 | trace_new_stub(blob, "UncommonTrapBlob" ); |
484 | |
485 | return blob; |
486 | } |
487 | |
488 | |
489 | #endif // COMPILER2 |
490 | |
491 | |
492 | //---------------------------------------------------------------------------------------------------- |
493 | // Implementation of ExceptionBlob |
494 | |
495 | #ifdef COMPILER2 |
496 | ExceptionBlob::ExceptionBlob( |
497 | CodeBuffer* cb, |
498 | int size, |
499 | OopMapSet* oop_maps, |
500 | int frame_size |
501 | ) |
502 | : SingletonBlob("ExceptionBlob" , cb, sizeof(ExceptionBlob), size, frame_size, oop_maps) |
503 | {} |
504 | |
505 | |
506 | ExceptionBlob* ExceptionBlob::create( |
507 | CodeBuffer* cb, |
508 | OopMapSet* oop_maps, |
509 | int frame_size) |
510 | { |
511 | ExceptionBlob* blob = NULL; |
512 | ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock |
513 | { |
514 | MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); |
515 | unsigned int size = CodeBlob::allocation_size(cb, sizeof(ExceptionBlob)); |
516 | blob = new (size) ExceptionBlob(cb, size, oop_maps, frame_size); |
517 | } |
518 | |
519 | trace_new_stub(blob, "ExceptionBlob" ); |
520 | |
521 | return blob; |
522 | } |
523 | |
524 | |
525 | #endif // COMPILER2 |
526 | |
527 | |
528 | //---------------------------------------------------------------------------------------------------- |
529 | // Implementation of SafepointBlob |
530 | |
531 | SafepointBlob::SafepointBlob( |
532 | CodeBuffer* cb, |
533 | int size, |
534 | OopMapSet* oop_maps, |
535 | int frame_size |
536 | ) |
537 | : SingletonBlob("SafepointBlob" , cb, sizeof(SafepointBlob), size, frame_size, oop_maps) |
538 | {} |
539 | |
540 | |
541 | SafepointBlob* SafepointBlob::create( |
542 | CodeBuffer* cb, |
543 | OopMapSet* oop_maps, |
544 | int frame_size) |
545 | { |
546 | SafepointBlob* blob = NULL; |
547 | ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock |
548 | { |
549 | MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); |
550 | unsigned int size = CodeBlob::allocation_size(cb, sizeof(SafepointBlob)); |
551 | blob = new (size) SafepointBlob(cb, size, oop_maps, frame_size); |
552 | } |
553 | |
554 | trace_new_stub(blob, "SafepointBlob" ); |
555 | |
556 | return blob; |
557 | } |
558 | |
559 | |
560 | //---------------------------------------------------------------------------------------------------- |
561 | // Verification and printing |
562 | |
563 | void CodeBlob::print_on(outputStream* st) const { |
564 | st->print_cr("[CodeBlob (" INTPTR_FORMAT ")]" , p2i(this)); |
565 | st->print_cr("Framesize: %d" , _frame_size); |
566 | } |
567 | |
568 | void CodeBlob::print() const { print_on(tty); } |
569 | |
570 | void CodeBlob::print_value_on(outputStream* st) const { |
571 | st->print_cr("[CodeBlob]" ); |
572 | } |
573 | |
574 | void CodeBlob::dump_for_addr(address addr, outputStream* st, bool verbose) const { |
575 | if (is_buffer_blob()) { |
576 | // the interpreter is generated into a buffer blob |
577 | InterpreterCodelet* i = Interpreter::codelet_containing(addr); |
578 | if (i != NULL) { |
579 | st->print_cr(INTPTR_FORMAT " is at code_begin+%d in an Interpreter codelet" , p2i(addr), (int)(addr - i->code_begin())); |
580 | i->print_on(st); |
581 | return; |
582 | } |
583 | if (Interpreter::contains(addr)) { |
584 | st->print_cr(INTPTR_FORMAT " is pointing into interpreter code" |
585 | " (not bytecode specific)" , p2i(addr)); |
586 | return; |
587 | } |
588 | // |
589 | if (AdapterHandlerLibrary::contains(this)) { |
590 | st->print_cr(INTPTR_FORMAT " is at code_begin+%d in an AdapterHandler" , p2i(addr), (int)(addr - code_begin())); |
591 | AdapterHandlerLibrary::print_handler_on(st, this); |
592 | } |
593 | // the stubroutines are generated into a buffer blob |
594 | StubCodeDesc* d = StubCodeDesc::desc_for(addr); |
595 | if (d != NULL) { |
596 | st->print_cr(INTPTR_FORMAT " is at begin+%d in a stub" , p2i(addr), (int)(addr - d->begin())); |
597 | d->print_on(st); |
598 | st->cr(); |
599 | return; |
600 | } |
601 | if (StubRoutines::contains(addr)) { |
602 | st->print_cr(INTPTR_FORMAT " is pointing to an (unnamed) stub routine" , p2i(addr)); |
603 | return; |
604 | } |
605 | // the InlineCacheBuffer is using stubs generated into a buffer blob |
606 | if (InlineCacheBuffer::contains(addr)) { |
607 | st->print_cr(INTPTR_FORMAT " is pointing into InlineCacheBuffer" , p2i(addr)); |
608 | return; |
609 | } |
610 | VtableStub* v = VtableStubs::stub_containing(addr); |
611 | if (v != NULL) { |
612 | st->print_cr(INTPTR_FORMAT " is at entry_point+%d in a vtable stub" , p2i(addr), (int)(addr - v->entry_point())); |
613 | v->print_on(st); |
614 | st->cr(); |
615 | return; |
616 | } |
617 | } |
618 | if (is_nmethod()) { |
619 | nmethod* nm = (nmethod*)this; |
620 | ResourceMark rm; |
621 | st->print(INTPTR_FORMAT " is at entry_point+%d in (nmethod*)" INTPTR_FORMAT, |
622 | p2i(addr), (int)(addr - nm->entry_point()), p2i(nm)); |
623 | if (verbose) { |
624 | st->print(" for " ); |
625 | nm->method()->print_value_on(st); |
626 | } |
627 | st->cr(); |
628 | nm->print_nmethod(verbose); |
629 | return; |
630 | } |
631 | st->print_cr(INTPTR_FORMAT " is at code_begin+%d in " , p2i(addr), (int)(addr - code_begin())); |
632 | print_on(st); |
633 | } |
634 | |
635 | void RuntimeBlob::verify() { |
636 | ShouldNotReachHere(); |
637 | } |
638 | |
639 | void BufferBlob::verify() { |
640 | // unimplemented |
641 | } |
642 | |
643 | void BufferBlob::print_on(outputStream* st) const { |
644 | RuntimeBlob::print_on(st); |
645 | print_value_on(st); |
646 | } |
647 | |
648 | void BufferBlob::print_value_on(outputStream* st) const { |
649 | st->print_cr("BufferBlob (" INTPTR_FORMAT ") used for %s" , p2i(this), name()); |
650 | } |
651 | |
652 | void RuntimeStub::verify() { |
653 | // unimplemented |
654 | } |
655 | |
656 | void RuntimeStub::print_on(outputStream* st) const { |
657 | ttyLocker ttyl; |
658 | RuntimeBlob::print_on(st); |
659 | st->print("Runtime Stub (" INTPTR_FORMAT "): " , p2i(this)); |
660 | st->print_cr("%s" , name()); |
661 | Disassembler::decode((RuntimeBlob*)this, st); |
662 | } |
663 | |
664 | void RuntimeStub::print_value_on(outputStream* st) const { |
665 | st->print("RuntimeStub (" INTPTR_FORMAT "): " , p2i(this)); st->print("%s" , name()); |
666 | } |
667 | |
668 | void SingletonBlob::verify() { |
669 | // unimplemented |
670 | } |
671 | |
672 | void SingletonBlob::print_on(outputStream* st) const { |
673 | ttyLocker ttyl; |
674 | RuntimeBlob::print_on(st); |
675 | st->print_cr("%s" , name()); |
676 | Disassembler::decode((RuntimeBlob*)this, st); |
677 | } |
678 | |
679 | void SingletonBlob::print_value_on(outputStream* st) const { |
680 | st->print_cr("%s" , name()); |
681 | } |
682 | |
683 | void DeoptimizationBlob::print_value_on(outputStream* st) const { |
684 | st->print_cr("Deoptimization (frame not available)" ); |
685 | } |
686 | |