1 | /* |
2 | * Copyright (c) 1999, 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 "asm/codeBuffer.hpp" |
27 | #include "c1/c1_CodeStubs.hpp" |
28 | #include "c1/c1_Defs.hpp" |
29 | #include "c1/c1_FrameMap.hpp" |
30 | #include "c1/c1_LIRAssembler.hpp" |
31 | #include "c1/c1_MacroAssembler.hpp" |
32 | #include "c1/c1_Runtime1.hpp" |
33 | #include "classfile/systemDictionary.hpp" |
34 | #include "classfile/vmSymbols.hpp" |
35 | #include "code/codeBlob.hpp" |
36 | #include "code/compiledIC.hpp" |
37 | #include "code/pcDesc.hpp" |
38 | #include "code/scopeDesc.hpp" |
39 | #include "code/vtableStubs.hpp" |
40 | #include "compiler/disassembler.hpp" |
41 | #include "gc/shared/barrierSet.hpp" |
42 | #include "gc/shared/c1/barrierSetC1.hpp" |
43 | #include "gc/shared/collectedHeap.hpp" |
44 | #include "interpreter/bytecode.hpp" |
45 | #include "interpreter/interpreter.hpp" |
46 | #include "jfr/support/jfrIntrinsics.hpp" |
47 | #include "logging/log.hpp" |
48 | #include "memory/allocation.inline.hpp" |
49 | #include "memory/oopFactory.hpp" |
50 | #include "memory/resourceArea.hpp" |
51 | #include "memory/universe.hpp" |
52 | #include "oops/access.inline.hpp" |
53 | #include "oops/objArrayOop.inline.hpp" |
54 | #include "oops/objArrayKlass.hpp" |
55 | #include "oops/oop.inline.hpp" |
56 | #include "runtime/atomic.hpp" |
57 | #include "runtime/biasedLocking.hpp" |
58 | #include "runtime/compilationPolicy.hpp" |
59 | #include "runtime/fieldDescriptor.inline.hpp" |
60 | #include "runtime/frame.inline.hpp" |
61 | #include "runtime/handles.inline.hpp" |
62 | #include "runtime/interfaceSupport.inline.hpp" |
63 | #include "runtime/javaCalls.hpp" |
64 | #include "runtime/sharedRuntime.hpp" |
65 | #include "runtime/threadCritical.hpp" |
66 | #include "runtime/vframe.inline.hpp" |
67 | #include "runtime/vframeArray.hpp" |
68 | #include "runtime/vm_version.hpp" |
69 | #include "utilities/copy.hpp" |
70 | #include "utilities/events.hpp" |
71 | |
72 | |
73 | // Implementation of StubAssembler |
74 | |
75 | StubAssembler::StubAssembler(CodeBuffer* code, const char * name, int stub_id) : C1_MacroAssembler(code) { |
76 | _name = name; |
77 | _must_gc_arguments = false; |
78 | _frame_size = no_frame_size; |
79 | _num_rt_args = 0; |
80 | _stub_id = stub_id; |
81 | } |
82 | |
83 | |
84 | void StubAssembler::set_info(const char* name, bool must_gc_arguments) { |
85 | _name = name; |
86 | _must_gc_arguments = must_gc_arguments; |
87 | } |
88 | |
89 | |
90 | void StubAssembler::set_frame_size(int size) { |
91 | if (_frame_size == no_frame_size) { |
92 | _frame_size = size; |
93 | } |
94 | assert(_frame_size == size, "can't change the frame size" ); |
95 | } |
96 | |
97 | |
98 | void StubAssembler::set_num_rt_args(int args) { |
99 | if (_num_rt_args == 0) { |
100 | _num_rt_args = args; |
101 | } |
102 | assert(_num_rt_args == args, "can't change the number of args" ); |
103 | } |
104 | |
105 | // Implementation of Runtime1 |
106 | |
107 | CodeBlob* Runtime1::_blobs[Runtime1::number_of_ids]; |
108 | const char *Runtime1::_blob_names[] = { |
109 | RUNTIME1_STUBS(STUB_NAME, LAST_STUB_NAME) |
110 | }; |
111 | |
112 | #ifndef PRODUCT |
113 | // statistics |
114 | int Runtime1::_generic_arraycopy_cnt = 0; |
115 | int Runtime1::_generic_arraycopystub_cnt = 0; |
116 | int Runtime1::_arraycopy_slowcase_cnt = 0; |
117 | int Runtime1::_arraycopy_checkcast_cnt = 0; |
118 | int Runtime1::_arraycopy_checkcast_attempt_cnt = 0; |
119 | int Runtime1::_new_type_array_slowcase_cnt = 0; |
120 | int Runtime1::_new_object_array_slowcase_cnt = 0; |
121 | int Runtime1::_new_instance_slowcase_cnt = 0; |
122 | int Runtime1::_new_multi_array_slowcase_cnt = 0; |
123 | int Runtime1::_monitorenter_slowcase_cnt = 0; |
124 | int Runtime1::_monitorexit_slowcase_cnt = 0; |
125 | int Runtime1::_patch_code_slowcase_cnt = 0; |
126 | int Runtime1::_throw_range_check_exception_count = 0; |
127 | int Runtime1::_throw_index_exception_count = 0; |
128 | int Runtime1::_throw_div0_exception_count = 0; |
129 | int Runtime1::_throw_null_pointer_exception_count = 0; |
130 | int Runtime1::_throw_class_cast_exception_count = 0; |
131 | int Runtime1::_throw_incompatible_class_change_error_count = 0; |
132 | int Runtime1::_throw_array_store_exception_count = 0; |
133 | int Runtime1::_throw_count = 0; |
134 | |
135 | static int _byte_arraycopy_stub_cnt = 0; |
136 | static int _short_arraycopy_stub_cnt = 0; |
137 | static int _int_arraycopy_stub_cnt = 0; |
138 | static int _long_arraycopy_stub_cnt = 0; |
139 | static int _oop_arraycopy_stub_cnt = 0; |
140 | |
141 | address Runtime1::arraycopy_count_address(BasicType type) { |
142 | switch (type) { |
143 | case T_BOOLEAN: |
144 | case T_BYTE: return (address)&_byte_arraycopy_stub_cnt; |
145 | case T_CHAR: |
146 | case T_SHORT: return (address)&_short_arraycopy_stub_cnt; |
147 | case T_FLOAT: |
148 | case T_INT: return (address)&_int_arraycopy_stub_cnt; |
149 | case T_DOUBLE: |
150 | case T_LONG: return (address)&_long_arraycopy_stub_cnt; |
151 | case T_ARRAY: |
152 | case T_OBJECT: return (address)&_oop_arraycopy_stub_cnt; |
153 | default: |
154 | ShouldNotReachHere(); |
155 | return NULL; |
156 | } |
157 | } |
158 | |
159 | |
160 | #endif |
161 | |
162 | // Simple helper to see if the caller of a runtime stub which |
163 | // entered the VM has been deoptimized |
164 | |
165 | static bool caller_is_deopted() { |
166 | JavaThread* thread = JavaThread::current(); |
167 | RegisterMap reg_map(thread, false); |
168 | frame runtime_frame = thread->last_frame(); |
169 | frame caller_frame = runtime_frame.sender(®_map); |
170 | assert(caller_frame.is_compiled_frame(), "must be compiled" ); |
171 | return caller_frame.is_deoptimized_frame(); |
172 | } |
173 | |
174 | // Stress deoptimization |
175 | static void deopt_caller() { |
176 | if ( !caller_is_deopted()) { |
177 | JavaThread* thread = JavaThread::current(); |
178 | RegisterMap reg_map(thread, false); |
179 | frame runtime_frame = thread->last_frame(); |
180 | frame caller_frame = runtime_frame.sender(®_map); |
181 | Deoptimization::deoptimize_frame(thread, caller_frame.id()); |
182 | assert(caller_is_deopted(), "Must be deoptimized" ); |
183 | } |
184 | } |
185 | |
186 | class StubIDStubAssemblerCodeGenClosure: public StubAssemblerCodeGenClosure { |
187 | private: |
188 | Runtime1::StubID _id; |
189 | public: |
190 | StubIDStubAssemblerCodeGenClosure(Runtime1::StubID id) : _id(id) {} |
191 | virtual OopMapSet* generate_code(StubAssembler* sasm) { |
192 | return Runtime1::generate_code_for(_id, sasm); |
193 | } |
194 | }; |
195 | |
196 | CodeBlob* Runtime1::generate_blob(BufferBlob* buffer_blob, int stub_id, const char* name, bool expect_oop_map, StubAssemblerCodeGenClosure* cl) { |
197 | ResourceMark rm; |
198 | // create code buffer for code storage |
199 | CodeBuffer code(buffer_blob); |
200 | |
201 | OopMapSet* oop_maps; |
202 | int frame_size; |
203 | bool must_gc_arguments; |
204 | |
205 | Compilation::setup_code_buffer(&code, 0); |
206 | |
207 | // create assembler for code generation |
208 | StubAssembler* sasm = new StubAssembler(&code, name, stub_id); |
209 | // generate code for runtime stub |
210 | oop_maps = cl->generate_code(sasm); |
211 | assert(oop_maps == NULL || sasm->frame_size() != no_frame_size, |
212 | "if stub has an oop map it must have a valid frame size" ); |
213 | assert(!expect_oop_map || oop_maps != NULL, "must have an oopmap" ); |
214 | |
215 | // align so printing shows nop's instead of random code at the end (SimpleStubs are aligned) |
216 | sasm->align(BytesPerWord); |
217 | // make sure all code is in code buffer |
218 | sasm->flush(); |
219 | |
220 | frame_size = sasm->frame_size(); |
221 | must_gc_arguments = sasm->must_gc_arguments(); |
222 | // create blob - distinguish a few special cases |
223 | CodeBlob* blob = RuntimeStub::new_runtime_stub(name, |
224 | &code, |
225 | CodeOffsets::frame_never_safe, |
226 | frame_size, |
227 | oop_maps, |
228 | must_gc_arguments); |
229 | assert(blob != NULL, "blob must exist" ); |
230 | return blob; |
231 | } |
232 | |
233 | void Runtime1::generate_blob_for(BufferBlob* buffer_blob, StubID id) { |
234 | assert(0 <= id && id < number_of_ids, "illegal stub id" ); |
235 | bool expect_oop_map = true; |
236 | #ifdef ASSERT |
237 | // Make sure that stubs that need oopmaps have them |
238 | switch (id) { |
239 | // These stubs don't need to have an oopmap |
240 | case dtrace_object_alloc_id: |
241 | case slow_subtype_check_id: |
242 | case fpu2long_stub_id: |
243 | case unwind_exception_id: |
244 | case counter_overflow_id: |
245 | #if defined(SPARC) || defined(PPC32) |
246 | case handle_exception_nofpu_id: // Unused on sparc |
247 | #endif |
248 | expect_oop_map = false; |
249 | break; |
250 | default: |
251 | break; |
252 | } |
253 | #endif |
254 | StubIDStubAssemblerCodeGenClosure cl(id); |
255 | CodeBlob* blob = generate_blob(buffer_blob, id, name_for(id), expect_oop_map, &cl); |
256 | // install blob |
257 | _blobs[id] = blob; |
258 | } |
259 | |
260 | void Runtime1::initialize(BufferBlob* blob) { |
261 | // platform-dependent initialization |
262 | initialize_pd(); |
263 | // generate stubs |
264 | for (int id = 0; id < number_of_ids; id++) generate_blob_for(blob, (StubID)id); |
265 | // printing |
266 | #ifndef PRODUCT |
267 | if (PrintSimpleStubs) { |
268 | ResourceMark rm; |
269 | for (int id = 0; id < number_of_ids; id++) { |
270 | _blobs[id]->print(); |
271 | if (_blobs[id]->oop_maps() != NULL) { |
272 | _blobs[id]->oop_maps()->print(); |
273 | } |
274 | } |
275 | } |
276 | #endif |
277 | BarrierSetC1* bs = BarrierSet::barrier_set()->barrier_set_c1(); |
278 | bs->generate_c1_runtime_stubs(blob); |
279 | } |
280 | |
281 | CodeBlob* Runtime1::blob_for(StubID id) { |
282 | assert(0 <= id && id < number_of_ids, "illegal stub id" ); |
283 | return _blobs[id]; |
284 | } |
285 | |
286 | |
287 | const char* Runtime1::name_for(StubID id) { |
288 | assert(0 <= id && id < number_of_ids, "illegal stub id" ); |
289 | return _blob_names[id]; |
290 | } |
291 | |
292 | const char* Runtime1::name_for_address(address entry) { |
293 | for (int id = 0; id < number_of_ids; id++) { |
294 | if (entry == entry_for((StubID)id)) return name_for((StubID)id); |
295 | } |
296 | |
297 | #define FUNCTION_CASE(a, f) \ |
298 | if ((intptr_t)a == CAST_FROM_FN_PTR(intptr_t, f)) return #f |
299 | |
300 | FUNCTION_CASE(entry, os::javaTimeMillis); |
301 | FUNCTION_CASE(entry, os::javaTimeNanos); |
302 | FUNCTION_CASE(entry, SharedRuntime::OSR_migration_end); |
303 | FUNCTION_CASE(entry, SharedRuntime::d2f); |
304 | FUNCTION_CASE(entry, SharedRuntime::d2i); |
305 | FUNCTION_CASE(entry, SharedRuntime::d2l); |
306 | FUNCTION_CASE(entry, SharedRuntime::dcos); |
307 | FUNCTION_CASE(entry, SharedRuntime::dexp); |
308 | FUNCTION_CASE(entry, SharedRuntime::dlog); |
309 | FUNCTION_CASE(entry, SharedRuntime::dlog10); |
310 | FUNCTION_CASE(entry, SharedRuntime::dpow); |
311 | FUNCTION_CASE(entry, SharedRuntime::drem); |
312 | FUNCTION_CASE(entry, SharedRuntime::dsin); |
313 | FUNCTION_CASE(entry, SharedRuntime::dtan); |
314 | FUNCTION_CASE(entry, SharedRuntime::f2i); |
315 | FUNCTION_CASE(entry, SharedRuntime::f2l); |
316 | FUNCTION_CASE(entry, SharedRuntime::frem); |
317 | FUNCTION_CASE(entry, SharedRuntime::l2d); |
318 | FUNCTION_CASE(entry, SharedRuntime::l2f); |
319 | FUNCTION_CASE(entry, SharedRuntime::ldiv); |
320 | FUNCTION_CASE(entry, SharedRuntime::lmul); |
321 | FUNCTION_CASE(entry, SharedRuntime::lrem); |
322 | FUNCTION_CASE(entry, SharedRuntime::lrem); |
323 | FUNCTION_CASE(entry, SharedRuntime::dtrace_method_entry); |
324 | FUNCTION_CASE(entry, SharedRuntime::dtrace_method_exit); |
325 | FUNCTION_CASE(entry, is_instance_of); |
326 | FUNCTION_CASE(entry, trace_block_entry); |
327 | #ifdef JFR_HAVE_INTRINSICS |
328 | FUNCTION_CASE(entry, JFR_TIME_FUNCTION); |
329 | #endif |
330 | FUNCTION_CASE(entry, StubRoutines::updateBytesCRC32()); |
331 | FUNCTION_CASE(entry, StubRoutines::updateBytesCRC32C()); |
332 | FUNCTION_CASE(entry, StubRoutines::vectorizedMismatch()); |
333 | FUNCTION_CASE(entry, StubRoutines::dexp()); |
334 | FUNCTION_CASE(entry, StubRoutines::dlog()); |
335 | FUNCTION_CASE(entry, StubRoutines::dlog10()); |
336 | FUNCTION_CASE(entry, StubRoutines::dpow()); |
337 | FUNCTION_CASE(entry, StubRoutines::dsin()); |
338 | FUNCTION_CASE(entry, StubRoutines::dcos()); |
339 | FUNCTION_CASE(entry, StubRoutines::dtan()); |
340 | |
341 | #undef FUNCTION_CASE |
342 | |
343 | // Soft float adds more runtime names. |
344 | return pd_name_for_address(entry); |
345 | } |
346 | |
347 | |
348 | JRT_ENTRY(void, Runtime1::new_instance(JavaThread* thread, Klass* klass)) |
349 | NOT_PRODUCT(_new_instance_slowcase_cnt++;) |
350 | |
351 | assert(klass->is_klass(), "not a class" ); |
352 | Handle holder(THREAD, klass->klass_holder()); // keep the klass alive |
353 | InstanceKlass* h = InstanceKlass::cast(klass); |
354 | h->check_valid_for_instantiation(true, CHECK); |
355 | // make sure klass is initialized |
356 | h->initialize(CHECK); |
357 | // allocate instance and return via TLS |
358 | oop obj = h->allocate_instance(CHECK); |
359 | thread->set_vm_result(obj); |
360 | JRT_END |
361 | |
362 | |
363 | JRT_ENTRY(void, Runtime1::new_type_array(JavaThread* thread, Klass* klass, jint length)) |
364 | NOT_PRODUCT(_new_type_array_slowcase_cnt++;) |
365 | // Note: no handle for klass needed since they are not used |
366 | // anymore after new_typeArray() and no GC can happen before. |
367 | // (This may have to change if this code changes!) |
368 | assert(klass->is_klass(), "not a class" ); |
369 | BasicType elt_type = TypeArrayKlass::cast(klass)->element_type(); |
370 | oop obj = oopFactory::new_typeArray(elt_type, length, CHECK); |
371 | thread->set_vm_result(obj); |
372 | // This is pretty rare but this runtime patch is stressful to deoptimization |
373 | // if we deoptimize here so force a deopt to stress the path. |
374 | if (DeoptimizeALot) { |
375 | deopt_caller(); |
376 | } |
377 | |
378 | JRT_END |
379 | |
380 | |
381 | JRT_ENTRY(void, Runtime1::new_object_array(JavaThread* thread, Klass* array_klass, jint length)) |
382 | NOT_PRODUCT(_new_object_array_slowcase_cnt++;) |
383 | |
384 | // Note: no handle for klass needed since they are not used |
385 | // anymore after new_objArray() and no GC can happen before. |
386 | // (This may have to change if this code changes!) |
387 | assert(array_klass->is_klass(), "not a class" ); |
388 | Handle holder(THREAD, array_klass->klass_holder()); // keep the klass alive |
389 | Klass* elem_klass = ObjArrayKlass::cast(array_klass)->element_klass(); |
390 | objArrayOop obj = oopFactory::new_objArray(elem_klass, length, CHECK); |
391 | thread->set_vm_result(obj); |
392 | // This is pretty rare but this runtime patch is stressful to deoptimization |
393 | // if we deoptimize here so force a deopt to stress the path. |
394 | if (DeoptimizeALot) { |
395 | deopt_caller(); |
396 | } |
397 | JRT_END |
398 | |
399 | |
400 | JRT_ENTRY(void, Runtime1::new_multi_array(JavaThread* thread, Klass* klass, int rank, jint* dims)) |
401 | NOT_PRODUCT(_new_multi_array_slowcase_cnt++;) |
402 | |
403 | assert(klass->is_klass(), "not a class" ); |
404 | assert(rank >= 1, "rank must be nonzero" ); |
405 | Handle holder(THREAD, klass->klass_holder()); // keep the klass alive |
406 | oop obj = ArrayKlass::cast(klass)->multi_allocate(rank, dims, CHECK); |
407 | thread->set_vm_result(obj); |
408 | JRT_END |
409 | |
410 | |
411 | JRT_ENTRY(void, Runtime1::unimplemented_entry(JavaThread* thread, StubID id)) |
412 | tty->print_cr("Runtime1::entry_for(%d) returned unimplemented entry point" , id); |
413 | JRT_END |
414 | |
415 | |
416 | JRT_ENTRY(void, Runtime1::throw_array_store_exception(JavaThread* thread, oopDesc* obj)) |
417 | ResourceMark rm(thread); |
418 | const char* klass_name = obj->klass()->external_name(); |
419 | SharedRuntime::throw_and_post_jvmti_exception(thread, vmSymbols::java_lang_ArrayStoreException(), klass_name); |
420 | JRT_END |
421 | |
422 | |
423 | // counter_overflow() is called from within C1-compiled methods. The enclosing method is the method |
424 | // associated with the top activation record. The inlinee (that is possibly included in the enclosing |
425 | // method) method oop is passed as an argument. In order to do that it is embedded in the code as |
426 | // a constant. |
427 | static nmethod* counter_overflow_helper(JavaThread* THREAD, int branch_bci, Method* m) { |
428 | nmethod* osr_nm = NULL; |
429 | methodHandle method(THREAD, m); |
430 | |
431 | RegisterMap map(THREAD, false); |
432 | frame fr = THREAD->last_frame().sender(&map); |
433 | nmethod* nm = (nmethod*) fr.cb(); |
434 | assert(nm!= NULL && nm->is_nmethod(), "Sanity check" ); |
435 | methodHandle enclosing_method(THREAD, nm->method()); |
436 | |
437 | CompLevel level = (CompLevel)nm->comp_level(); |
438 | int bci = InvocationEntryBci; |
439 | if (branch_bci != InvocationEntryBci) { |
440 | // Compute destination bci |
441 | address pc = method()->code_base() + branch_bci; |
442 | Bytecodes::Code branch = Bytecodes::code_at(method(), pc); |
443 | int offset = 0; |
444 | switch (branch) { |
445 | case Bytecodes::_if_icmplt: case Bytecodes::_iflt: |
446 | case Bytecodes::_if_icmpgt: case Bytecodes::_ifgt: |
447 | case Bytecodes::_if_icmple: case Bytecodes::_ifle: |
448 | case Bytecodes::_if_icmpge: case Bytecodes::_ifge: |
449 | case Bytecodes::_if_icmpeq: case Bytecodes::_if_acmpeq: case Bytecodes::_ifeq: |
450 | case Bytecodes::_if_icmpne: case Bytecodes::_if_acmpne: case Bytecodes::_ifne: |
451 | case Bytecodes::_ifnull: case Bytecodes::_ifnonnull: case Bytecodes::_goto: |
452 | offset = (int16_t)Bytes::get_Java_u2(pc + 1); |
453 | break; |
454 | case Bytecodes::_goto_w: |
455 | offset = Bytes::get_Java_u4(pc + 1); |
456 | break; |
457 | default: ; |
458 | } |
459 | bci = branch_bci + offset; |
460 | } |
461 | assert(!HAS_PENDING_EXCEPTION, "Should not have any exceptions pending" ); |
462 | osr_nm = CompilationPolicy::policy()->event(enclosing_method, method, branch_bci, bci, level, nm, THREAD); |
463 | assert(!HAS_PENDING_EXCEPTION, "Event handler should not throw any exceptions" ); |
464 | return osr_nm; |
465 | } |
466 | |
467 | JRT_BLOCK_ENTRY(address, Runtime1::counter_overflow(JavaThread* thread, int bci, Method* method)) |
468 | nmethod* osr_nm; |
469 | JRT_BLOCK |
470 | osr_nm = counter_overflow_helper(thread, bci, method); |
471 | if (osr_nm != NULL) { |
472 | RegisterMap map(thread, false); |
473 | frame fr = thread->last_frame().sender(&map); |
474 | Deoptimization::deoptimize_frame(thread, fr.id()); |
475 | } |
476 | JRT_BLOCK_END |
477 | return NULL; |
478 | JRT_END |
479 | |
480 | extern void vm_exit(int code); |
481 | |
482 | // Enter this method from compiled code handler below. This is where we transition |
483 | // to VM mode. This is done as a helper routine so that the method called directly |
484 | // from compiled code does not have to transition to VM. This allows the entry |
485 | // method to see if the nmethod that we have just looked up a handler for has |
486 | // been deoptimized while we were in the vm. This simplifies the assembly code |
487 | // cpu directories. |
488 | // |
489 | // We are entering here from exception stub (via the entry method below) |
490 | // If there is a compiled exception handler in this method, we will continue there; |
491 | // otherwise we will unwind the stack and continue at the caller of top frame method |
492 | // Note: we enter in Java using a special JRT wrapper. This wrapper allows us to |
493 | // control the area where we can allow a safepoint. After we exit the safepoint area we can |
494 | // check to see if the handler we are going to return is now in a nmethod that has |
495 | // been deoptimized. If that is the case we return the deopt blob |
496 | // unpack_with_exception entry instead. This makes life for the exception blob easier |
497 | // because making that same check and diverting is painful from assembly language. |
498 | JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* thread, oopDesc* ex, address pc, nmethod*& nm)) |
499 | // Reset method handle flag. |
500 | thread->set_is_method_handle_return(false); |
501 | |
502 | Handle exception(thread, ex); |
503 | nm = CodeCache::find_nmethod(pc); |
504 | assert(nm != NULL, "this is not an nmethod" ); |
505 | // Adjust the pc as needed/ |
506 | if (nm->is_deopt_pc(pc)) { |
507 | RegisterMap map(thread, false); |
508 | frame exception_frame = thread->last_frame().sender(&map); |
509 | // if the frame isn't deopted then pc must not correspond to the caller of last_frame |
510 | assert(exception_frame.is_deoptimized_frame(), "must be deopted" ); |
511 | pc = exception_frame.pc(); |
512 | } |
513 | #ifdef ASSERT |
514 | assert(exception.not_null(), "NULL exceptions should be handled by throw_exception" ); |
515 | // Check that exception is a subclass of Throwable, otherwise we have a VerifyError |
516 | if (!(exception->is_a(SystemDictionary::Throwable_klass()))) { |
517 | if (ExitVMOnVerifyError) vm_exit(-1); |
518 | ShouldNotReachHere(); |
519 | } |
520 | #endif |
521 | |
522 | // Check the stack guard pages and reenable them if necessary and there is |
523 | // enough space on the stack to do so. Use fast exceptions only if the guard |
524 | // pages are enabled. |
525 | bool guard_pages_enabled = thread->stack_guards_enabled(); |
526 | if (!guard_pages_enabled) guard_pages_enabled = thread->reguard_stack(); |
527 | |
528 | if (JvmtiExport::can_post_on_exceptions()) { |
529 | // To ensure correct notification of exception catches and throws |
530 | // we have to deoptimize here. If we attempted to notify the |
531 | // catches and throws during this exception lookup it's possible |
532 | // we could deoptimize on the way out of the VM and end back in |
533 | // the interpreter at the throw site. This would result in double |
534 | // notifications since the interpreter would also notify about |
535 | // these same catches and throws as it unwound the frame. |
536 | |
537 | RegisterMap reg_map(thread); |
538 | frame stub_frame = thread->last_frame(); |
539 | frame caller_frame = stub_frame.sender(®_map); |
540 | |
541 | // We don't really want to deoptimize the nmethod itself since we |
542 | // can actually continue in the exception handler ourselves but I |
543 | // don't see an easy way to have the desired effect. |
544 | Deoptimization::deoptimize_frame(thread, caller_frame.id()); |
545 | assert(caller_is_deopted(), "Must be deoptimized" ); |
546 | |
547 | return SharedRuntime::deopt_blob()->unpack_with_exception_in_tls(); |
548 | } |
549 | |
550 | // ExceptionCache is used only for exceptions at call sites and not for implicit exceptions |
551 | if (guard_pages_enabled) { |
552 | address fast_continuation = nm->handler_for_exception_and_pc(exception, pc); |
553 | if (fast_continuation != NULL) { |
554 | // Set flag if return address is a method handle call site. |
555 | thread->set_is_method_handle_return(nm->is_method_handle_return(pc)); |
556 | return fast_continuation; |
557 | } |
558 | } |
559 | |
560 | // If the stack guard pages are enabled, check whether there is a handler in |
561 | // the current method. Otherwise (guard pages disabled), force an unwind and |
562 | // skip the exception cache update (i.e., just leave continuation==NULL). |
563 | address continuation = NULL; |
564 | if (guard_pages_enabled) { |
565 | |
566 | // New exception handling mechanism can support inlined methods |
567 | // with exception handlers since the mappings are from PC to PC |
568 | |
569 | // debugging support |
570 | // tracing |
571 | if (log_is_enabled(Info, exceptions)) { |
572 | ResourceMark rm; |
573 | stringStream tempst; |
574 | assert(nm->method() != NULL, "Unexpected NULL method()" ); |
575 | tempst.print("compiled method <%s>\n" |
576 | " at PC" INTPTR_FORMAT " for thread " INTPTR_FORMAT, |
577 | nm->method()->print_value_string(), p2i(pc), p2i(thread)); |
578 | Exceptions::log_exception(exception, tempst.as_string()); |
579 | } |
580 | // for AbortVMOnException flag |
581 | Exceptions::debug_check_abort(exception); |
582 | |
583 | // Clear out the exception oop and pc since looking up an |
584 | // exception handler can cause class loading, which might throw an |
585 | // exception and those fields are expected to be clear during |
586 | // normal bytecode execution. |
587 | thread->clear_exception_oop_and_pc(); |
588 | |
589 | bool recursive_exception = false; |
590 | continuation = SharedRuntime::compute_compiled_exc_handler(nm, pc, exception, false, false, recursive_exception); |
591 | // If an exception was thrown during exception dispatch, the exception oop may have changed |
592 | thread->set_exception_oop(exception()); |
593 | thread->set_exception_pc(pc); |
594 | |
595 | // the exception cache is used only by non-implicit exceptions |
596 | // Update the exception cache only when there didn't happen |
597 | // another exception during the computation of the compiled |
598 | // exception handler. Checking for exception oop equality is not |
599 | // sufficient because some exceptions are pre-allocated and reused. |
600 | if (continuation != NULL && !recursive_exception) { |
601 | nm->add_handler_for_exception_and_pc(exception, pc, continuation); |
602 | } |
603 | } |
604 | |
605 | thread->set_vm_result(exception()); |
606 | // Set flag if return address is a method handle call site. |
607 | thread->set_is_method_handle_return(nm->is_method_handle_return(pc)); |
608 | |
609 | if (log_is_enabled(Info, exceptions)) { |
610 | ResourceMark rm; |
611 | log_info(exceptions)("Thread " PTR_FORMAT " continuing at PC " PTR_FORMAT |
612 | " for exception thrown at PC " PTR_FORMAT, |
613 | p2i(thread), p2i(continuation), p2i(pc)); |
614 | } |
615 | |
616 | return continuation; |
617 | JRT_END |
618 | |
619 | // Enter this method from compiled code only if there is a Java exception handler |
620 | // in the method handling the exception. |
621 | // We are entering here from exception stub. We don't do a normal VM transition here. |
622 | // We do it in a helper. This is so we can check to see if the nmethod we have just |
623 | // searched for an exception handler has been deoptimized in the meantime. |
624 | address Runtime1::exception_handler_for_pc(JavaThread* thread) { |
625 | oop exception = thread->exception_oop(); |
626 | address pc = thread->exception_pc(); |
627 | // Still in Java mode |
628 | DEBUG_ONLY(ResetNoHandleMark rnhm); |
629 | nmethod* nm = NULL; |
630 | address continuation = NULL; |
631 | { |
632 | // Enter VM mode by calling the helper |
633 | ResetNoHandleMark rnhm; |
634 | continuation = exception_handler_for_pc_helper(thread, exception, pc, nm); |
635 | } |
636 | // Back in JAVA, use no oops DON'T safepoint |
637 | |
638 | // Now check to see if the nmethod we were called from is now deoptimized. |
639 | // If so we must return to the deopt blob and deoptimize the nmethod |
640 | if (nm != NULL && caller_is_deopted()) { |
641 | continuation = SharedRuntime::deopt_blob()->unpack_with_exception_in_tls(); |
642 | } |
643 | |
644 | assert(continuation != NULL, "no handler found" ); |
645 | return continuation; |
646 | } |
647 | |
648 | |
649 | JRT_ENTRY(void, Runtime1::throw_range_check_exception(JavaThread* thread, int index, arrayOopDesc* a)) |
650 | NOT_PRODUCT(_throw_range_check_exception_count++;) |
651 | const int len = 35; |
652 | assert(len < strlen("Index %d out of bounds for length %d" ), "Must allocate more space for message." ); |
653 | char message[2 * jintAsStringSize + len]; |
654 | sprintf(message, "Index %d out of bounds for length %d" , index, a->length()); |
655 | SharedRuntime::throw_and_post_jvmti_exception(thread, vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), message); |
656 | JRT_END |
657 | |
658 | |
659 | JRT_ENTRY(void, Runtime1::throw_index_exception(JavaThread* thread, int index)) |
660 | NOT_PRODUCT(_throw_index_exception_count++;) |
661 | char message[16]; |
662 | sprintf(message, "%d" , index); |
663 | SharedRuntime::throw_and_post_jvmti_exception(thread, vmSymbols::java_lang_IndexOutOfBoundsException(), message); |
664 | JRT_END |
665 | |
666 | |
667 | JRT_ENTRY(void, Runtime1::throw_div0_exception(JavaThread* thread)) |
668 | NOT_PRODUCT(_throw_div0_exception_count++;) |
669 | SharedRuntime::throw_and_post_jvmti_exception(thread, vmSymbols::java_lang_ArithmeticException(), "/ by zero" ); |
670 | JRT_END |
671 | |
672 | |
673 | JRT_ENTRY(void, Runtime1::throw_null_pointer_exception(JavaThread* thread)) |
674 | NOT_PRODUCT(_throw_null_pointer_exception_count++;) |
675 | SharedRuntime::throw_and_post_jvmti_exception(thread, vmSymbols::java_lang_NullPointerException()); |
676 | JRT_END |
677 | |
678 | |
679 | JRT_ENTRY(void, Runtime1::throw_class_cast_exception(JavaThread* thread, oopDesc* object)) |
680 | NOT_PRODUCT(_throw_class_cast_exception_count++;) |
681 | ResourceMark rm(thread); |
682 | char* message = SharedRuntime::generate_class_cast_message( |
683 | thread, object->klass()); |
684 | SharedRuntime::throw_and_post_jvmti_exception( |
685 | thread, vmSymbols::java_lang_ClassCastException(), message); |
686 | JRT_END |
687 | |
688 | |
689 | JRT_ENTRY(void, Runtime1::throw_incompatible_class_change_error(JavaThread* thread)) |
690 | NOT_PRODUCT(_throw_incompatible_class_change_error_count++;) |
691 | ResourceMark rm(thread); |
692 | SharedRuntime::throw_and_post_jvmti_exception(thread, vmSymbols::java_lang_IncompatibleClassChangeError()); |
693 | JRT_END |
694 | |
695 | |
696 | JRT_ENTRY_NO_ASYNC(void, Runtime1::monitorenter(JavaThread* thread, oopDesc* obj, BasicObjectLock* lock)) |
697 | NOT_PRODUCT(_monitorenter_slowcase_cnt++;) |
698 | if (PrintBiasedLockingStatistics) { |
699 | Atomic::inc(BiasedLocking::slow_path_entry_count_addr()); |
700 | } |
701 | Handle h_obj(thread, obj); |
702 | if (UseBiasedLocking) { |
703 | // Retry fast entry if bias is revoked to avoid unnecessary inflation |
704 | ObjectSynchronizer::fast_enter(h_obj, lock->lock(), true, CHECK); |
705 | } else { |
706 | if (UseFastLocking) { |
707 | // When using fast locking, the compiled code has already tried the fast case |
708 | assert(obj == lock->obj(), "must match" ); |
709 | ObjectSynchronizer::slow_enter(h_obj, lock->lock(), THREAD); |
710 | } else { |
711 | lock->set_obj(obj); |
712 | ObjectSynchronizer::fast_enter(h_obj, lock->lock(), false, THREAD); |
713 | } |
714 | } |
715 | JRT_END |
716 | |
717 | |
718 | JRT_LEAF(void, Runtime1::monitorexit(JavaThread* thread, BasicObjectLock* lock)) |
719 | NOT_PRODUCT(_monitorexit_slowcase_cnt++;) |
720 | assert(thread == JavaThread::current(), "threads must correspond" ); |
721 | assert(thread->last_Java_sp(), "last_Java_sp must be set" ); |
722 | // monitorexit is non-blocking (leaf routine) => no exceptions can be thrown |
723 | EXCEPTION_MARK; |
724 | |
725 | oop obj = lock->obj(); |
726 | assert(oopDesc::is_oop(obj), "must be NULL or an object" ); |
727 | if (UseFastLocking) { |
728 | // When using fast locking, the compiled code has already tried the fast case |
729 | ObjectSynchronizer::slow_exit(obj, lock->lock(), THREAD); |
730 | } else { |
731 | ObjectSynchronizer::fast_exit(obj, lock->lock(), THREAD); |
732 | } |
733 | JRT_END |
734 | |
735 | // Cf. OptoRuntime::deoptimize_caller_frame |
736 | JRT_ENTRY(void, Runtime1::deoptimize(JavaThread* thread, jint trap_request)) |
737 | // Called from within the owner thread, so no need for safepoint |
738 | RegisterMap reg_map(thread, false); |
739 | frame stub_frame = thread->last_frame(); |
740 | assert(stub_frame.is_runtime_frame(), "Sanity check" ); |
741 | frame caller_frame = stub_frame.sender(®_map); |
742 | nmethod* nm = caller_frame.cb()->as_nmethod_or_null(); |
743 | assert(nm != NULL, "Sanity check" ); |
744 | methodHandle method(thread, nm->method()); |
745 | assert(nm == CodeCache::find_nmethod(caller_frame.pc()), "Should be the same" ); |
746 | Deoptimization::DeoptAction action = Deoptimization::trap_request_action(trap_request); |
747 | Deoptimization::DeoptReason reason = Deoptimization::trap_request_reason(trap_request); |
748 | |
749 | if (action == Deoptimization::Action_make_not_entrant) { |
750 | if (nm->make_not_entrant()) { |
751 | if (reason == Deoptimization::Reason_tenured) { |
752 | MethodData* trap_mdo = Deoptimization::get_method_data(thread, method, true /*create_if_missing*/); |
753 | if (trap_mdo != NULL) { |
754 | trap_mdo->inc_tenure_traps(); |
755 | } |
756 | } |
757 | } |
758 | } |
759 | |
760 | // Deoptimize the caller frame. |
761 | Deoptimization::deoptimize_frame(thread, caller_frame.id()); |
762 | // Return to the now deoptimized frame. |
763 | JRT_END |
764 | |
765 | |
766 | #ifndef DEOPTIMIZE_WHEN_PATCHING |
767 | |
768 | static Klass* resolve_field_return_klass(const methodHandle& caller, int bci, TRAPS) { |
769 | Bytecode_field field_access(caller, bci); |
770 | // This can be static or non-static field access |
771 | Bytecodes::Code code = field_access.code(); |
772 | |
773 | // We must load class, initialize class and resolve the field |
774 | fieldDescriptor result; // initialize class if needed |
775 | constantPoolHandle constants(THREAD, caller->constants()); |
776 | LinkResolver::resolve_field_access(result, constants, field_access.index(), caller, Bytecodes::java_code(code), CHECK_NULL); |
777 | return result.field_holder(); |
778 | } |
779 | |
780 | |
781 | // |
782 | // This routine patches sites where a class wasn't loaded or |
783 | // initialized at the time the code was generated. It handles |
784 | // references to classes, fields and forcing of initialization. Most |
785 | // of the cases are straightforward and involving simply forcing |
786 | // resolution of a class, rewriting the instruction stream with the |
787 | // needed constant and replacing the call in this function with the |
788 | // patched code. The case for static field is more complicated since |
789 | // the thread which is in the process of initializing a class can |
790 | // access it's static fields but other threads can't so the code |
791 | // either has to deoptimize when this case is detected or execute a |
792 | // check that the current thread is the initializing thread. The |
793 | // current |
794 | // |
795 | // Patches basically look like this: |
796 | // |
797 | // |
798 | // patch_site: jmp patch stub ;; will be patched |
799 | // continue: ... |
800 | // ... |
801 | // ... |
802 | // ... |
803 | // |
804 | // They have a stub which looks like this: |
805 | // |
806 | // ;; patch body |
807 | // movl <const>, reg (for class constants) |
808 | // <or> movl [reg1 + <const>], reg (for field offsets) |
809 | // <or> movl reg, [reg1 + <const>] (for field offsets) |
810 | // <being_init offset> <bytes to copy> <bytes to skip> |
811 | // patch_stub: call Runtime1::patch_code (through a runtime stub) |
812 | // jmp patch_site |
813 | // |
814 | // |
815 | // A normal patch is done by rewriting the patch body, usually a move, |
816 | // and then copying it into place over top of the jmp instruction |
817 | // being careful to flush caches and doing it in an MP-safe way. The |
818 | // constants following the patch body are used to find various pieces |
819 | // of the patch relative to the call site for Runtime1::patch_code. |
820 | // The case for getstatic and putstatic is more complicated because |
821 | // getstatic and putstatic have special semantics when executing while |
822 | // the class is being initialized. getstatic/putstatic on a class |
823 | // which is being_initialized may be executed by the initializing |
824 | // thread but other threads have to block when they execute it. This |
825 | // is accomplished in compiled code by executing a test of the current |
826 | // thread against the initializing thread of the class. It's emitted |
827 | // as boilerplate in their stub which allows the patched code to be |
828 | // executed before it's copied back into the main body of the nmethod. |
829 | // |
830 | // being_init: get_thread(<tmp reg> |
831 | // cmpl [reg1 + <init_thread_offset>], <tmp reg> |
832 | // jne patch_stub |
833 | // movl [reg1 + <const>], reg (for field offsets) <or> |
834 | // movl reg, [reg1 + <const>] (for field offsets) |
835 | // jmp continue |
836 | // <being_init offset> <bytes to copy> <bytes to skip> |
837 | // patch_stub: jmp Runtim1::patch_code (through a runtime stub) |
838 | // jmp patch_site |
839 | // |
840 | // If the class is being initialized the patch body is rewritten and |
841 | // the patch site is rewritten to jump to being_init, instead of |
842 | // patch_stub. Whenever this code is executed it checks the current |
843 | // thread against the intializing thread so other threads will enter |
844 | // the runtime and end up blocked waiting the class to finish |
845 | // initializing inside the calls to resolve_field below. The |
846 | // initializing class will continue on it's way. Once the class is |
847 | // fully_initialized, the intializing_thread of the class becomes |
848 | // NULL, so the next thread to execute this code will fail the test, |
849 | // call into patch_code and complete the patching process by copying |
850 | // the patch body back into the main part of the nmethod and resume |
851 | // executing. |
852 | |
853 | // NB: |
854 | // |
855 | // Patchable instruction sequences inherently exhibit race conditions, |
856 | // where thread A is patching an instruction at the same time thread B |
857 | // is executing it. The algorithms we use ensure that any observation |
858 | // that B can make on any intermediate states during A's patching will |
859 | // always end up with a correct outcome. This is easiest if there are |
860 | // few or no intermediate states. (Some inline caches have two |
861 | // related instructions that must be patched in tandem. For those, |
862 | // intermediate states seem to be unavoidable, but we will get the |
863 | // right answer from all possible observation orders.) |
864 | // |
865 | // When patching the entry instruction at the head of a method, or a |
866 | // linkable call instruction inside of a method, we try very hard to |
867 | // use a patch sequence which executes as a single memory transaction. |
868 | // This means, in practice, that when thread A patches an instruction, |
869 | // it should patch a 32-bit or 64-bit word that somehow overlaps the |
870 | // instruction or is contained in it. We believe that memory hardware |
871 | // will never break up such a word write, if it is naturally aligned |
872 | // for the word being written. We also know that some CPUs work very |
873 | // hard to create atomic updates even of naturally unaligned words, |
874 | // but we don't want to bet the farm on this always working. |
875 | // |
876 | // Therefore, if there is any chance of a race condition, we try to |
877 | // patch only naturally aligned words, as single, full-word writes. |
878 | |
879 | JRT_ENTRY(void, Runtime1::patch_code(JavaThread* thread, Runtime1::StubID stub_id )) |
880 | NOT_PRODUCT(_patch_code_slowcase_cnt++;) |
881 | |
882 | ResourceMark rm(thread); |
883 | RegisterMap reg_map(thread, false); |
884 | frame runtime_frame = thread->last_frame(); |
885 | frame caller_frame = runtime_frame.sender(®_map); |
886 | |
887 | // last java frame on stack |
888 | vframeStream vfst(thread, true); |
889 | assert(!vfst.at_end(), "Java frame must exist" ); |
890 | |
891 | methodHandle caller_method(THREAD, vfst.method()); |
892 | // Note that caller_method->code() may not be same as caller_code because of OSR's |
893 | // Note also that in the presence of inlining it is not guaranteed |
894 | // that caller_method() == caller_code->method() |
895 | |
896 | int bci = vfst.bci(); |
897 | Bytecodes::Code code = caller_method()->java_code_at(bci); |
898 | |
899 | // this is used by assertions in the access_field_patching_id |
900 | BasicType patch_field_type = T_ILLEGAL; |
901 | bool deoptimize_for_volatile = false; |
902 | bool deoptimize_for_atomic = false; |
903 | int patch_field_offset = -1; |
904 | Klass* init_klass = NULL; // klass needed by load_klass_patching code |
905 | Klass* load_klass = NULL; // klass needed by load_klass_patching code |
906 | Handle mirror(THREAD, NULL); // oop needed by load_mirror_patching code |
907 | Handle appendix(THREAD, NULL); // oop needed by appendix_patching code |
908 | bool load_klass_or_mirror_patch_id = |
909 | (stub_id == Runtime1::load_klass_patching_id || stub_id == Runtime1::load_mirror_patching_id); |
910 | |
911 | if (stub_id == Runtime1::access_field_patching_id) { |
912 | |
913 | Bytecode_field field_access(caller_method, bci); |
914 | fieldDescriptor result; // initialize class if needed |
915 | Bytecodes::Code code = field_access.code(); |
916 | constantPoolHandle constants(THREAD, caller_method->constants()); |
917 | LinkResolver::resolve_field_access(result, constants, field_access.index(), caller_method, Bytecodes::java_code(code), CHECK); |
918 | patch_field_offset = result.offset(); |
919 | |
920 | // If we're patching a field which is volatile then at compile it |
921 | // must not have been know to be volatile, so the generated code |
922 | // isn't correct for a volatile reference. The nmethod has to be |
923 | // deoptimized so that the code can be regenerated correctly. |
924 | // This check is only needed for access_field_patching since this |
925 | // is the path for patching field offsets. load_klass is only |
926 | // used for patching references to oops which don't need special |
927 | // handling in the volatile case. |
928 | |
929 | deoptimize_for_volatile = result.access_flags().is_volatile(); |
930 | |
931 | // If we are patching a field which should be atomic, then |
932 | // the generated code is not correct either, force deoptimizing. |
933 | // We need to only cover T_LONG and T_DOUBLE fields, as we can |
934 | // break access atomicity only for them. |
935 | |
936 | // Strictly speaking, the deoptimization on 64-bit platforms |
937 | // is unnecessary, and T_LONG stores on 32-bit platforms need |
938 | // to be handled by special patching code when AlwaysAtomicAccesses |
939 | // becomes product feature. At this point, we are still going |
940 | // for the deoptimization for consistency against volatile |
941 | // accesses. |
942 | |
943 | patch_field_type = result.field_type(); |
944 | deoptimize_for_atomic = (AlwaysAtomicAccesses && (patch_field_type == T_DOUBLE || patch_field_type == T_LONG)); |
945 | |
946 | } else if (load_klass_or_mirror_patch_id) { |
947 | Klass* k = NULL; |
948 | switch (code) { |
949 | case Bytecodes::_putstatic: |
950 | case Bytecodes::_getstatic: |
951 | { Klass* klass = resolve_field_return_klass(caller_method, bci, CHECK); |
952 | init_klass = klass; |
953 | mirror = Handle(THREAD, klass->java_mirror()); |
954 | } |
955 | break; |
956 | case Bytecodes::_new: |
957 | { Bytecode_new bnew(caller_method(), caller_method->bcp_from(bci)); |
958 | k = caller_method->constants()->klass_at(bnew.index(), CHECK); |
959 | } |
960 | break; |
961 | case Bytecodes::_multianewarray: |
962 | { Bytecode_multianewarray mna(caller_method(), caller_method->bcp_from(bci)); |
963 | k = caller_method->constants()->klass_at(mna.index(), CHECK); |
964 | } |
965 | break; |
966 | case Bytecodes::_instanceof: |
967 | { Bytecode_instanceof io(caller_method(), caller_method->bcp_from(bci)); |
968 | k = caller_method->constants()->klass_at(io.index(), CHECK); |
969 | } |
970 | break; |
971 | case Bytecodes::_checkcast: |
972 | { Bytecode_checkcast cc(caller_method(), caller_method->bcp_from(bci)); |
973 | k = caller_method->constants()->klass_at(cc.index(), CHECK); |
974 | } |
975 | break; |
976 | case Bytecodes::_anewarray: |
977 | { Bytecode_anewarray anew(caller_method(), caller_method->bcp_from(bci)); |
978 | Klass* ek = caller_method->constants()->klass_at(anew.index(), CHECK); |
979 | k = ek->array_klass(CHECK); |
980 | } |
981 | break; |
982 | case Bytecodes::_ldc: |
983 | case Bytecodes::_ldc_w: |
984 | { |
985 | Bytecode_loadconstant cc(caller_method, bci); |
986 | oop m = cc.resolve_constant(CHECK); |
987 | mirror = Handle(THREAD, m); |
988 | } |
989 | break; |
990 | default: fatal("unexpected bytecode for load_klass_or_mirror_patch_id" ); |
991 | } |
992 | load_klass = k; |
993 | } else if (stub_id == load_appendix_patching_id) { |
994 | Bytecode_invoke bytecode(caller_method, bci); |
995 | Bytecodes::Code bc = bytecode.invoke_code(); |
996 | |
997 | CallInfo info; |
998 | constantPoolHandle pool(thread, caller_method->constants()); |
999 | int index = bytecode.index(); |
1000 | LinkResolver::resolve_invoke(info, Handle(), pool, index, bc, CHECK); |
1001 | switch (bc) { |
1002 | case Bytecodes::_invokehandle: { |
1003 | int cache_index = ConstantPool::decode_cpcache_index(index, true); |
1004 | assert(cache_index >= 0 && cache_index < pool->cache()->length(), "unexpected cache index" ); |
1005 | ConstantPoolCacheEntry* cpce = pool->cache()->entry_at(cache_index); |
1006 | cpce->set_method_handle(pool, info); |
1007 | appendix = Handle(THREAD, cpce->appendix_if_resolved(pool)); // just in case somebody already resolved the entry |
1008 | break; |
1009 | } |
1010 | case Bytecodes::_invokedynamic: { |
1011 | ConstantPoolCacheEntry* cpce = pool->invokedynamic_cp_cache_entry_at(index); |
1012 | cpce->set_dynamic_call(pool, info); |
1013 | appendix = Handle(THREAD, cpce->appendix_if_resolved(pool)); // just in case somebody already resolved the entry |
1014 | break; |
1015 | } |
1016 | default: fatal("unexpected bytecode for load_appendix_patching_id" ); |
1017 | } |
1018 | } else { |
1019 | ShouldNotReachHere(); |
1020 | } |
1021 | |
1022 | if (deoptimize_for_volatile || deoptimize_for_atomic) { |
1023 | // At compile time we assumed the field wasn't volatile/atomic but after |
1024 | // loading it turns out it was volatile/atomic so we have to throw the |
1025 | // compiled code out and let it be regenerated. |
1026 | if (TracePatching) { |
1027 | if (deoptimize_for_volatile) { |
1028 | tty->print_cr("Deoptimizing for patching volatile field reference" ); |
1029 | } |
1030 | if (deoptimize_for_atomic) { |
1031 | tty->print_cr("Deoptimizing for patching atomic field reference" ); |
1032 | } |
1033 | } |
1034 | |
1035 | // It's possible the nmethod was invalidated in the last |
1036 | // safepoint, but if it's still alive then make it not_entrant. |
1037 | nmethod* nm = CodeCache::find_nmethod(caller_frame.pc()); |
1038 | if (nm != NULL) { |
1039 | nm->make_not_entrant(); |
1040 | } |
1041 | |
1042 | Deoptimization::deoptimize_frame(thread, caller_frame.id()); |
1043 | |
1044 | // Return to the now deoptimized frame. |
1045 | } |
1046 | |
1047 | // Now copy code back |
1048 | |
1049 | { |
1050 | MutexLocker ml_patch (Patching_lock, Mutex::_no_safepoint_check_flag); |
1051 | // |
1052 | // Deoptimization may have happened while we waited for the lock. |
1053 | // In that case we don't bother to do any patching we just return |
1054 | // and let the deopt happen |
1055 | if (!caller_is_deopted()) { |
1056 | NativeGeneralJump* jump = nativeGeneralJump_at(caller_frame.pc()); |
1057 | address instr_pc = jump->jump_destination(); |
1058 | NativeInstruction* ni = nativeInstruction_at(instr_pc); |
1059 | if (ni->is_jump() ) { |
1060 | // the jump has not been patched yet |
1061 | // The jump destination is slow case and therefore not part of the stubs |
1062 | // (stubs are only for StaticCalls) |
1063 | |
1064 | // format of buffer |
1065 | // .... |
1066 | // instr byte 0 <-- copy_buff |
1067 | // instr byte 1 |
1068 | // .. |
1069 | // instr byte n-1 |
1070 | // n |
1071 | // .... <-- call destination |
1072 | |
1073 | address stub_location = caller_frame.pc() + PatchingStub::patch_info_offset(); |
1074 | unsigned char* byte_count = (unsigned char*) (stub_location - 1); |
1075 | unsigned char* byte_skip = (unsigned char*) (stub_location - 2); |
1076 | unsigned char* being_initialized_entry_offset = (unsigned char*) (stub_location - 3); |
1077 | address copy_buff = stub_location - *byte_skip - *byte_count; |
1078 | address being_initialized_entry = stub_location - *being_initialized_entry_offset; |
1079 | if (TracePatching) { |
1080 | ttyLocker ttyl; |
1081 | tty->print_cr(" Patching %s at bci %d at address " INTPTR_FORMAT " (%s)" , Bytecodes::name(code), bci, |
1082 | p2i(instr_pc), (stub_id == Runtime1::access_field_patching_id) ? "field" : "klass" ); |
1083 | nmethod* caller_code = CodeCache::find_nmethod(caller_frame.pc()); |
1084 | assert(caller_code != NULL, "nmethod not found" ); |
1085 | |
1086 | // NOTE we use pc() not original_pc() because we already know they are |
1087 | // identical otherwise we'd have never entered this block of code |
1088 | |
1089 | const ImmutableOopMap* map = caller_code->oop_map_for_return_address(caller_frame.pc()); |
1090 | assert(map != NULL, "null check" ); |
1091 | map->print(); |
1092 | tty->cr(); |
1093 | |
1094 | Disassembler::decode(copy_buff, copy_buff + *byte_count, tty); |
1095 | } |
1096 | // depending on the code below, do_patch says whether to copy the patch body back into the nmethod |
1097 | bool do_patch = true; |
1098 | if (stub_id == Runtime1::access_field_patching_id) { |
1099 | // The offset may not be correct if the class was not loaded at code generation time. |
1100 | // Set it now. |
1101 | NativeMovRegMem* n_move = nativeMovRegMem_at(copy_buff); |
1102 | assert(n_move->offset() == 0 || (n_move->offset() == 4 && (patch_field_type == T_DOUBLE || patch_field_type == T_LONG)), "illegal offset for type" ); |
1103 | assert(patch_field_offset >= 0, "illegal offset" ); |
1104 | n_move->add_offset_in_bytes(patch_field_offset); |
1105 | } else if (load_klass_or_mirror_patch_id) { |
1106 | // If a getstatic or putstatic is referencing a klass which |
1107 | // isn't fully initialized, the patch body isn't copied into |
1108 | // place until initialization is complete. In this case the |
1109 | // patch site is setup so that any threads besides the |
1110 | // initializing thread are forced to come into the VM and |
1111 | // block. |
1112 | do_patch = (code != Bytecodes::_getstatic && code != Bytecodes::_putstatic) || |
1113 | InstanceKlass::cast(init_klass)->is_initialized(); |
1114 | NativeGeneralJump* jump = nativeGeneralJump_at(instr_pc); |
1115 | if (jump->jump_destination() == being_initialized_entry) { |
1116 | assert(do_patch == true, "initialization must be complete at this point" ); |
1117 | } else { |
1118 | // patch the instruction <move reg, klass> |
1119 | NativeMovConstReg* n_copy = nativeMovConstReg_at(copy_buff); |
1120 | |
1121 | assert(n_copy->data() == 0 || |
1122 | n_copy->data() == (intptr_t)Universe::non_oop_word(), |
1123 | "illegal init value" ); |
1124 | if (stub_id == Runtime1::load_klass_patching_id) { |
1125 | assert(load_klass != NULL, "klass not set" ); |
1126 | n_copy->set_data((intx) (load_klass)); |
1127 | } else { |
1128 | assert(mirror() != NULL, "klass not set" ); |
1129 | // Don't need a G1 pre-barrier here since we assert above that data isn't an oop. |
1130 | n_copy->set_data(cast_from_oop<intx>(mirror())); |
1131 | } |
1132 | |
1133 | if (TracePatching) { |
1134 | Disassembler::decode(copy_buff, copy_buff + *byte_count, tty); |
1135 | } |
1136 | } |
1137 | } else if (stub_id == Runtime1::load_appendix_patching_id) { |
1138 | NativeMovConstReg* n_copy = nativeMovConstReg_at(copy_buff); |
1139 | assert(n_copy->data() == 0 || |
1140 | n_copy->data() == (intptr_t)Universe::non_oop_word(), |
1141 | "illegal init value" ); |
1142 | n_copy->set_data(cast_from_oop<intx>(appendix())); |
1143 | |
1144 | if (TracePatching) { |
1145 | Disassembler::decode(copy_buff, copy_buff + *byte_count, tty); |
1146 | } |
1147 | } else { |
1148 | ShouldNotReachHere(); |
1149 | } |
1150 | |
1151 | #if defined(SPARC) || defined(PPC32) |
1152 | if (load_klass_or_mirror_patch_id || |
1153 | stub_id == Runtime1::load_appendix_patching_id) { |
1154 | // Update the location in the nmethod with the proper |
1155 | // metadata. When the code was generated, a NULL was stuffed |
1156 | // in the metadata table and that table needs to be update to |
1157 | // have the right value. On intel the value is kept |
1158 | // directly in the instruction instead of in the metadata |
1159 | // table, so set_data above effectively updated the value. |
1160 | nmethod* nm = CodeCache::find_nmethod(instr_pc); |
1161 | assert(nm != NULL, "invalid nmethod_pc" ); |
1162 | RelocIterator mds(nm, copy_buff, copy_buff + 1); |
1163 | bool found = false; |
1164 | while (mds.next() && !found) { |
1165 | if (mds.type() == relocInfo::oop_type) { |
1166 | assert(stub_id == Runtime1::load_mirror_patching_id || |
1167 | stub_id == Runtime1::load_appendix_patching_id, "wrong stub id" ); |
1168 | oop_Relocation* r = mds.oop_reloc(); |
1169 | oop* oop_adr = r->oop_addr(); |
1170 | *oop_adr = stub_id == Runtime1::load_mirror_patching_id ? mirror() : appendix(); |
1171 | r->fix_oop_relocation(); |
1172 | found = true; |
1173 | } else if (mds.type() == relocInfo::metadata_type) { |
1174 | assert(stub_id == Runtime1::load_klass_patching_id, "wrong stub id" ); |
1175 | metadata_Relocation* r = mds.metadata_reloc(); |
1176 | Metadata** metadata_adr = r->metadata_addr(); |
1177 | *metadata_adr = load_klass; |
1178 | r->fix_metadata_relocation(); |
1179 | found = true; |
1180 | } |
1181 | } |
1182 | assert(found, "the metadata must exist!" ); |
1183 | } |
1184 | #endif |
1185 | if (do_patch) { |
1186 | // replace instructions |
1187 | // first replace the tail, then the call |
1188 | #ifdef ARM |
1189 | if((load_klass_or_mirror_patch_id || |
1190 | stub_id == Runtime1::load_appendix_patching_id) && |
1191 | nativeMovConstReg_at(copy_buff)->is_pc_relative()) { |
1192 | nmethod* nm = CodeCache::find_nmethod(instr_pc); |
1193 | address addr = NULL; |
1194 | assert(nm != NULL, "invalid nmethod_pc" ); |
1195 | RelocIterator mds(nm, copy_buff, copy_buff + 1); |
1196 | while (mds.next()) { |
1197 | if (mds.type() == relocInfo::oop_type) { |
1198 | assert(stub_id == Runtime1::load_mirror_patching_id || |
1199 | stub_id == Runtime1::load_appendix_patching_id, "wrong stub id" ); |
1200 | oop_Relocation* r = mds.oop_reloc(); |
1201 | addr = (address)r->oop_addr(); |
1202 | break; |
1203 | } else if (mds.type() == relocInfo::metadata_type) { |
1204 | assert(stub_id == Runtime1::load_klass_patching_id, "wrong stub id" ); |
1205 | metadata_Relocation* r = mds.metadata_reloc(); |
1206 | addr = (address)r->metadata_addr(); |
1207 | break; |
1208 | } |
1209 | } |
1210 | assert(addr != NULL, "metadata relocation must exist" ); |
1211 | copy_buff -= *byte_count; |
1212 | NativeMovConstReg* n_copy2 = nativeMovConstReg_at(copy_buff); |
1213 | n_copy2->set_pc_relative_offset(addr, instr_pc); |
1214 | } |
1215 | #endif |
1216 | |
1217 | for (int i = NativeGeneralJump::instruction_size; i < *byte_count; i++) { |
1218 | address ptr = copy_buff + i; |
1219 | int a_byte = (*ptr) & 0xFF; |
1220 | address dst = instr_pc + i; |
1221 | *(unsigned char*)dst = (unsigned char) a_byte; |
1222 | } |
1223 | ICache::invalidate_range(instr_pc, *byte_count); |
1224 | NativeGeneralJump::replace_mt_safe(instr_pc, copy_buff); |
1225 | |
1226 | if (load_klass_or_mirror_patch_id || |
1227 | stub_id == Runtime1::load_appendix_patching_id) { |
1228 | relocInfo::relocType rtype = |
1229 | (stub_id == Runtime1::load_klass_patching_id) ? |
1230 | relocInfo::metadata_type : |
1231 | relocInfo::oop_type; |
1232 | // update relocInfo to metadata |
1233 | nmethod* nm = CodeCache::find_nmethod(instr_pc); |
1234 | assert(nm != NULL, "invalid nmethod_pc" ); |
1235 | |
1236 | // The old patch site is now a move instruction so update |
1237 | // the reloc info so that it will get updated during |
1238 | // future GCs. |
1239 | RelocIterator iter(nm, (address)instr_pc, (address)(instr_pc + 1)); |
1240 | relocInfo::change_reloc_info_for_address(&iter, (address) instr_pc, |
1241 | relocInfo::none, rtype); |
1242 | #ifdef SPARC |
1243 | // Sparc takes two relocations for an metadata so update the second one. |
1244 | address instr_pc2 = instr_pc + NativeMovConstReg::add_offset; |
1245 | RelocIterator iter2(nm, instr_pc2, instr_pc2 + 1); |
1246 | relocInfo::change_reloc_info_for_address(&iter2, (address) instr_pc2, |
1247 | relocInfo::none, rtype); |
1248 | #endif |
1249 | #ifdef PPC32 |
1250 | { address instr_pc2 = instr_pc + NativeMovConstReg::lo_offset; |
1251 | RelocIterator iter2(nm, instr_pc2, instr_pc2 + 1); |
1252 | relocInfo::change_reloc_info_for_address(&iter2, (address) instr_pc2, |
1253 | relocInfo::none, rtype); |
1254 | } |
1255 | #endif |
1256 | } |
1257 | |
1258 | } else { |
1259 | ICache::invalidate_range(copy_buff, *byte_count); |
1260 | NativeGeneralJump::insert_unconditional(instr_pc, being_initialized_entry); |
1261 | } |
1262 | } |
1263 | } |
1264 | } |
1265 | |
1266 | // If we are patching in a non-perm oop, make sure the nmethod |
1267 | // is on the right list. |
1268 | { |
1269 | MutexLocker ml_code (CodeCache_lock, Mutex::_no_safepoint_check_flag); |
1270 | nmethod* nm = CodeCache::find_nmethod(caller_frame.pc()); |
1271 | guarantee(nm != NULL, "only nmethods can contain non-perm oops" ); |
1272 | |
1273 | // Since we've patched some oops in the nmethod, |
1274 | // (re)register it with the heap. |
1275 | Universe::heap()->register_nmethod(nm); |
1276 | } |
1277 | JRT_END |
1278 | |
1279 | #else // DEOPTIMIZE_WHEN_PATCHING |
1280 | |
1281 | JRT_ENTRY(void, Runtime1::patch_code(JavaThread* thread, Runtime1::StubID stub_id )) |
1282 | RegisterMap reg_map(thread, false); |
1283 | |
1284 | NOT_PRODUCT(_patch_code_slowcase_cnt++;) |
1285 | if (TracePatching) { |
1286 | tty->print_cr("Deoptimizing because patch is needed" ); |
1287 | } |
1288 | |
1289 | frame runtime_frame = thread->last_frame(); |
1290 | frame caller_frame = runtime_frame.sender(®_map); |
1291 | |
1292 | // It's possible the nmethod was invalidated in the last |
1293 | // safepoint, but if it's still alive then make it not_entrant. |
1294 | nmethod* nm = CodeCache::find_nmethod(caller_frame.pc()); |
1295 | if (nm != NULL) { |
1296 | nm->make_not_entrant(); |
1297 | } |
1298 | |
1299 | Deoptimization::deoptimize_frame(thread, caller_frame.id()); |
1300 | |
1301 | // Return to the now deoptimized frame. |
1302 | JRT_END |
1303 | |
1304 | #endif // DEOPTIMIZE_WHEN_PATCHING |
1305 | |
1306 | // |
1307 | // Entry point for compiled code. We want to patch a nmethod. |
1308 | // We don't do a normal VM transition here because we want to |
1309 | // know after the patching is complete and any safepoint(s) are taken |
1310 | // if the calling nmethod was deoptimized. We do this by calling a |
1311 | // helper method which does the normal VM transition and when it |
1312 | // completes we can check for deoptimization. This simplifies the |
1313 | // assembly code in the cpu directories. |
1314 | // |
1315 | int Runtime1::move_klass_patching(JavaThread* thread) { |
1316 | // |
1317 | // NOTE: we are still in Java |
1318 | // |
1319 | Thread* THREAD = thread; |
1320 | debug_only(NoHandleMark nhm;) |
1321 | { |
1322 | // Enter VM mode |
1323 | |
1324 | ResetNoHandleMark rnhm; |
1325 | patch_code(thread, load_klass_patching_id); |
1326 | } |
1327 | // Back in JAVA, use no oops DON'T safepoint |
1328 | |
1329 | // Return true if calling code is deoptimized |
1330 | |
1331 | return caller_is_deopted(); |
1332 | } |
1333 | |
1334 | int Runtime1::move_mirror_patching(JavaThread* thread) { |
1335 | // |
1336 | // NOTE: we are still in Java |
1337 | // |
1338 | Thread* THREAD = thread; |
1339 | debug_only(NoHandleMark nhm;) |
1340 | { |
1341 | // Enter VM mode |
1342 | |
1343 | ResetNoHandleMark rnhm; |
1344 | patch_code(thread, load_mirror_patching_id); |
1345 | } |
1346 | // Back in JAVA, use no oops DON'T safepoint |
1347 | |
1348 | // Return true if calling code is deoptimized |
1349 | |
1350 | return caller_is_deopted(); |
1351 | } |
1352 | |
1353 | int Runtime1::move_appendix_patching(JavaThread* thread) { |
1354 | // |
1355 | // NOTE: we are still in Java |
1356 | // |
1357 | Thread* THREAD = thread; |
1358 | debug_only(NoHandleMark nhm;) |
1359 | { |
1360 | // Enter VM mode |
1361 | |
1362 | ResetNoHandleMark rnhm; |
1363 | patch_code(thread, load_appendix_patching_id); |
1364 | } |
1365 | // Back in JAVA, use no oops DON'T safepoint |
1366 | |
1367 | // Return true if calling code is deoptimized |
1368 | |
1369 | return caller_is_deopted(); |
1370 | } |
1371 | // |
1372 | // Entry point for compiled code. We want to patch a nmethod. |
1373 | // We don't do a normal VM transition here because we want to |
1374 | // know after the patching is complete and any safepoint(s) are taken |
1375 | // if the calling nmethod was deoptimized. We do this by calling a |
1376 | // helper method which does the normal VM transition and when it |
1377 | // completes we can check for deoptimization. This simplifies the |
1378 | // assembly code in the cpu directories. |
1379 | // |
1380 | |
1381 | int Runtime1::access_field_patching(JavaThread* thread) { |
1382 | // |
1383 | // NOTE: we are still in Java |
1384 | // |
1385 | Thread* THREAD = thread; |
1386 | debug_only(NoHandleMark nhm;) |
1387 | { |
1388 | // Enter VM mode |
1389 | |
1390 | ResetNoHandleMark rnhm; |
1391 | patch_code(thread, access_field_patching_id); |
1392 | } |
1393 | // Back in JAVA, use no oops DON'T safepoint |
1394 | |
1395 | // Return true if calling code is deoptimized |
1396 | |
1397 | return caller_is_deopted(); |
1398 | JRT_END |
1399 | |
1400 | |
1401 | JRT_LEAF(void, Runtime1::trace_block_entry(jint block_id)) |
1402 | // for now we just print out the block id |
1403 | tty->print("%d " , block_id); |
1404 | JRT_END |
1405 | |
1406 | |
1407 | JRT_LEAF(int, Runtime1::is_instance_of(oopDesc* mirror, oopDesc* obj)) |
1408 | // had to return int instead of bool, otherwise there may be a mismatch |
1409 | // between the C calling convention and the Java one. |
1410 | // e.g., on x86, GCC may clear only %al when returning a bool false, but |
1411 | // JVM takes the whole %eax as the return value, which may misinterpret |
1412 | // the return value as a boolean true. |
1413 | |
1414 | assert(mirror != NULL, "should null-check on mirror before calling" ); |
1415 | Klass* k = java_lang_Class::as_Klass(mirror); |
1416 | return (k != NULL && obj != NULL && obj->is_a(k)) ? 1 : 0; |
1417 | JRT_END |
1418 | |
1419 | JRT_ENTRY(void, Runtime1::predicate_failed_trap(JavaThread* thread)) |
1420 | ResourceMark rm; |
1421 | |
1422 | assert(!TieredCompilation, "incompatible with tiered compilation" ); |
1423 | |
1424 | RegisterMap reg_map(thread, false); |
1425 | frame runtime_frame = thread->last_frame(); |
1426 | frame caller_frame = runtime_frame.sender(®_map); |
1427 | |
1428 | nmethod* nm = CodeCache::find_nmethod(caller_frame.pc()); |
1429 | assert (nm != NULL, "no more nmethod?" ); |
1430 | nm->make_not_entrant(); |
1431 | |
1432 | methodHandle m(nm->method()); |
1433 | MethodData* mdo = m->method_data(); |
1434 | |
1435 | if (mdo == NULL && !HAS_PENDING_EXCEPTION) { |
1436 | // Build an MDO. Ignore errors like OutOfMemory; |
1437 | // that simply means we won't have an MDO to update. |
1438 | Method::build_interpreter_method_data(m, THREAD); |
1439 | if (HAS_PENDING_EXCEPTION) { |
1440 | assert((PENDING_EXCEPTION->is_a(SystemDictionary::OutOfMemoryError_klass())), "we expect only an OOM error here" ); |
1441 | CLEAR_PENDING_EXCEPTION; |
1442 | } |
1443 | mdo = m->method_data(); |
1444 | } |
1445 | |
1446 | if (mdo != NULL) { |
1447 | mdo->inc_trap_count(Deoptimization::Reason_none); |
1448 | } |
1449 | |
1450 | if (TracePredicateFailedTraps) { |
1451 | stringStream ss1, ss2; |
1452 | vframeStream vfst(thread); |
1453 | methodHandle inlinee = methodHandle(vfst.method()); |
1454 | inlinee->print_short_name(&ss1); |
1455 | m->print_short_name(&ss2); |
1456 | tty->print_cr("Predicate failed trap in method %s at bci %d inlined in %s at pc " INTPTR_FORMAT, ss1.as_string(), vfst.bci(), ss2.as_string(), p2i(caller_frame.pc())); |
1457 | } |
1458 | |
1459 | |
1460 | Deoptimization::deoptimize_frame(thread, caller_frame.id()); |
1461 | |
1462 | JRT_END |
1463 | |
1464 | #ifndef PRODUCT |
1465 | void Runtime1::print_statistics() { |
1466 | tty->print_cr("C1 Runtime statistics:" ); |
1467 | tty->print_cr(" _resolve_invoke_virtual_cnt: %d" , SharedRuntime::_resolve_virtual_ctr); |
1468 | tty->print_cr(" _resolve_invoke_opt_virtual_cnt: %d" , SharedRuntime::_resolve_opt_virtual_ctr); |
1469 | tty->print_cr(" _resolve_invoke_static_cnt: %d" , SharedRuntime::_resolve_static_ctr); |
1470 | tty->print_cr(" _handle_wrong_method_cnt: %d" , SharedRuntime::_wrong_method_ctr); |
1471 | tty->print_cr(" _ic_miss_cnt: %d" , SharedRuntime::_ic_miss_ctr); |
1472 | tty->print_cr(" _generic_arraycopy_cnt: %d" , _generic_arraycopy_cnt); |
1473 | tty->print_cr(" _generic_arraycopystub_cnt: %d" , _generic_arraycopystub_cnt); |
1474 | tty->print_cr(" _byte_arraycopy_cnt: %d" , _byte_arraycopy_stub_cnt); |
1475 | tty->print_cr(" _short_arraycopy_cnt: %d" , _short_arraycopy_stub_cnt); |
1476 | tty->print_cr(" _int_arraycopy_cnt: %d" , _int_arraycopy_stub_cnt); |
1477 | tty->print_cr(" _long_arraycopy_cnt: %d" , _long_arraycopy_stub_cnt); |
1478 | tty->print_cr(" _oop_arraycopy_cnt: %d" , _oop_arraycopy_stub_cnt); |
1479 | tty->print_cr(" _arraycopy_slowcase_cnt: %d" , _arraycopy_slowcase_cnt); |
1480 | tty->print_cr(" _arraycopy_checkcast_cnt: %d" , _arraycopy_checkcast_cnt); |
1481 | tty->print_cr(" _arraycopy_checkcast_attempt_cnt:%d" , _arraycopy_checkcast_attempt_cnt); |
1482 | |
1483 | tty->print_cr(" _new_type_array_slowcase_cnt: %d" , _new_type_array_slowcase_cnt); |
1484 | tty->print_cr(" _new_object_array_slowcase_cnt: %d" , _new_object_array_slowcase_cnt); |
1485 | tty->print_cr(" _new_instance_slowcase_cnt: %d" , _new_instance_slowcase_cnt); |
1486 | tty->print_cr(" _new_multi_array_slowcase_cnt: %d" , _new_multi_array_slowcase_cnt); |
1487 | tty->print_cr(" _monitorenter_slowcase_cnt: %d" , _monitorenter_slowcase_cnt); |
1488 | tty->print_cr(" _monitorexit_slowcase_cnt: %d" , _monitorexit_slowcase_cnt); |
1489 | tty->print_cr(" _patch_code_slowcase_cnt: %d" , _patch_code_slowcase_cnt); |
1490 | |
1491 | tty->print_cr(" _throw_range_check_exception_count: %d:" , _throw_range_check_exception_count); |
1492 | tty->print_cr(" _throw_index_exception_count: %d:" , _throw_index_exception_count); |
1493 | tty->print_cr(" _throw_div0_exception_count: %d:" , _throw_div0_exception_count); |
1494 | tty->print_cr(" _throw_null_pointer_exception_count: %d:" , _throw_null_pointer_exception_count); |
1495 | tty->print_cr(" _throw_class_cast_exception_count: %d:" , _throw_class_cast_exception_count); |
1496 | tty->print_cr(" _throw_incompatible_class_change_error_count: %d:" , _throw_incompatible_class_change_error_count); |
1497 | tty->print_cr(" _throw_array_store_exception_count: %d:" , _throw_array_store_exception_count); |
1498 | tty->print_cr(" _throw_count: %d:" , _throw_count); |
1499 | |
1500 | SharedRuntime::print_ic_miss_histogram(); |
1501 | tty->cr(); |
1502 | } |
1503 | #endif // PRODUCT |
1504 | |