Mercurial > hg > graal-compiler
annotate src/share/vm/opto/runtime.cpp @ 1941:79d04223b8a5
Added caching for resolved types and resolved fields.
This is crucial, because the local load elimination will lead to wrong results, if field equality (of two RiField objects with the same object and the same RiType) is not given. The caching makes sure that the default equals implementation is sufficient.
author | Thomas Wuerthinger <wuerthinger@ssw.jku.at> |
---|---|
date | Tue, 28 Dec 2010 18:33:26 +0100 |
parents | 75588558f1bf |
children | f95d63e2154a |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1368
diff
changeset
|
2 * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1368
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1368
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1368
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 #include "incls/_precompiled.incl" | |
26 #include "incls/_runtime.cpp.incl" | |
27 | |
28 | |
29 // For debugging purposes: | |
30 // To force FullGCALot inside a runtime function, add the following two lines | |
31 // | |
32 // Universe::release_fullgc_alot_dummy(); | |
33 // MarkSweep::invoke(0, "Debugging"); | |
34 // | |
35 // At command line specify the parameters: -XX:+FullGCALot -XX:FullGCALotStart=100000000 | |
36 | |
37 | |
38 | |
39 | |
40 // Compiled code entry points | |
41 address OptoRuntime::_new_instance_Java = NULL; | |
42 address OptoRuntime::_new_array_Java = NULL; | |
43 address OptoRuntime::_multianewarray2_Java = NULL; | |
44 address OptoRuntime::_multianewarray3_Java = NULL; | |
45 address OptoRuntime::_multianewarray4_Java = NULL; | |
46 address OptoRuntime::_multianewarray5_Java = NULL; | |
342 | 47 address OptoRuntime::_g1_wb_pre_Java = NULL; |
48 address OptoRuntime::_g1_wb_post_Java = NULL; | |
0 | 49 address OptoRuntime::_vtable_must_compile_Java = NULL; |
50 address OptoRuntime::_complete_monitor_locking_Java = NULL; | |
51 address OptoRuntime::_rethrow_Java = NULL; | |
52 | |
53 address OptoRuntime::_slow_arraycopy_Java = NULL; | |
54 address OptoRuntime::_register_finalizer_Java = NULL; | |
55 | |
56 # ifdef ENABLE_ZAP_DEAD_LOCALS | |
57 address OptoRuntime::_zap_dead_Java_locals_Java = NULL; | |
58 address OptoRuntime::_zap_dead_native_locals_Java = NULL; | |
59 # endif | |
60 | |
61 | |
62 // This should be called in an assertion at the start of OptoRuntime routines | |
63 // which are entered from compiled code (all of them) | |
64 #ifndef PRODUCT | |
65 static bool check_compiled_frame(JavaThread* thread) { | |
66 assert(thread->last_frame().is_runtime_frame(), "cannot call runtime directly from compiled code"); | |
67 #ifdef ASSERT | |
68 RegisterMap map(thread, false); | |
69 frame caller = thread->last_frame().sender(&map); | |
70 assert(caller.is_compiled_frame(), "not being called from compiled like code"); | |
71 #endif /* ASSERT */ | |
72 return true; | |
73 } | |
74 #endif | |
75 | |
76 | |
77 #define gen(env, var, type_func_gen, c_func, fancy_jump, pass_tls, save_arg_regs, return_pc) \ | |
78 var = generate_stub(env, type_func_gen, CAST_FROM_FN_PTR(address, c_func), #var, fancy_jump, pass_tls, save_arg_regs, return_pc) | |
79 | |
80 void OptoRuntime::generate(ciEnv* env) { | |
81 | |
82 generate_exception_blob(); | |
83 | |
84 // Note: tls: Means fetching the return oop out of the thread-local storage | |
85 // | |
86 // variable/name type-function-gen , runtime method ,fncy_jp, tls,save_args,retpc | |
87 // ------------------------------------------------------------------------------------------------------------------------------- | |
88 gen(env, _new_instance_Java , new_instance_Type , new_instance_C , 0 , true , false, false); | |
89 gen(env, _new_array_Java , new_array_Type , new_array_C , 0 , true , false, false); | |
90 gen(env, _multianewarray2_Java , multianewarray2_Type , multianewarray2_C , 0 , true , false, false); | |
91 gen(env, _multianewarray3_Java , multianewarray3_Type , multianewarray3_C , 0 , true , false, false); | |
92 gen(env, _multianewarray4_Java , multianewarray4_Type , multianewarray4_C , 0 , true , false, false); | |
93 gen(env, _multianewarray5_Java , multianewarray5_Type , multianewarray5_C , 0 , true , false, false); | |
342 | 94 gen(env, _g1_wb_pre_Java , g1_wb_pre_Type , SharedRuntime::g1_wb_pre , 0 , false, false, false); |
95 gen(env, _g1_wb_post_Java , g1_wb_post_Type , SharedRuntime::g1_wb_post , 0 , false, false, false); | |
0 | 96 gen(env, _complete_monitor_locking_Java , complete_monitor_enter_Type , SharedRuntime::complete_monitor_locking_C , 0 , false, false, false); |
97 gen(env, _rethrow_Java , rethrow_Type , rethrow_C , 2 , true , false, true ); | |
98 | |
99 gen(env, _slow_arraycopy_Java , slow_arraycopy_Type , SharedRuntime::slow_arraycopy_C , 0 , false, false, false); | |
100 gen(env, _register_finalizer_Java , register_finalizer_Type , register_finalizer , 0 , false, false, false); | |
101 | |
102 # ifdef ENABLE_ZAP_DEAD_LOCALS | |
103 gen(env, _zap_dead_Java_locals_Java , zap_dead_locals_Type , zap_dead_Java_locals_C , 0 , false, true , false ); | |
104 gen(env, _zap_dead_native_locals_Java , zap_dead_locals_Type , zap_dead_native_locals_C , 0 , false, true , false ); | |
105 # endif | |
106 | |
107 } | |
108 | |
109 #undef gen | |
110 | |
111 | |
112 // Helper method to do generation of RunTimeStub's | |
113 address OptoRuntime::generate_stub( ciEnv* env, | |
114 TypeFunc_generator gen, address C_function, | |
115 const char *name, int is_fancy_jump, | |
116 bool pass_tls, | |
117 bool save_argument_registers, | |
118 bool return_pc ) { | |
119 ResourceMark rm; | |
120 Compile C( env, gen, C_function, name, is_fancy_jump, pass_tls, save_argument_registers, return_pc ); | |
121 return C.stub_entry_point(); | |
122 } | |
123 | |
124 const char* OptoRuntime::stub_name(address entry) { | |
125 #ifndef PRODUCT | |
126 CodeBlob* cb = CodeCache::find_blob(entry); | |
127 RuntimeStub* rs =(RuntimeStub *)cb; | |
128 assert(rs != NULL && rs->is_runtime_stub(), "not a runtime stub"); | |
129 return rs->name(); | |
130 #else | |
131 // Fast implementation for product mode (maybe it should be inlined too) | |
132 return "runtime stub"; | |
133 #endif | |
134 } | |
135 | |
136 | |
137 //============================================================================= | |
138 // Opto compiler runtime routines | |
139 //============================================================================= | |
140 | |
141 | |
142 //=============================allocation====================================== | |
143 // We failed the fast-path allocation. Now we need to do a scavenge or GC | |
144 // and try allocation again. | |
145 | |
1166 | 146 void OptoRuntime::new_store_pre_barrier(JavaThread* thread) { |
0 | 147 // After any safepoint, just before going back to compiled code, |
1027
39b01ab7035a
6888898: CMS: ReduceInitialCardMarks unsafe in the presence of cms precleaning
ysr
parents:
605
diff
changeset
|
148 // we inform the GC that we will be doing initializing writes to |
39b01ab7035a
6888898: CMS: ReduceInitialCardMarks unsafe in the presence of cms precleaning
ysr
parents:
605
diff
changeset
|
149 // this object in the future without emitting card-marks, so |
39b01ab7035a
6888898: CMS: ReduceInitialCardMarks unsafe in the presence of cms precleaning
ysr
parents:
605
diff
changeset
|
150 // GC may take any compensating steps. |
39b01ab7035a
6888898: CMS: ReduceInitialCardMarks unsafe in the presence of cms precleaning
ysr
parents:
605
diff
changeset
|
151 // NOTE: Keep this code consistent with GraphKit::store_barrier. |
0 | 152 |
153 oop new_obj = thread->vm_result(); | |
154 if (new_obj == NULL) return; | |
155 | |
156 assert(Universe::heap()->can_elide_tlab_store_barriers(), | |
157 "compiler must check this first"); | |
1027
39b01ab7035a
6888898: CMS: ReduceInitialCardMarks unsafe in the presence of cms precleaning
ysr
parents:
605
diff
changeset
|
158 // GC may decide to give back a safer copy of new_obj. |
1166 | 159 new_obj = Universe::heap()->new_store_pre_barrier(thread, new_obj); |
0 | 160 thread->set_vm_result(new_obj); |
161 } | |
162 | |
163 // object allocation | |
164 JRT_BLOCK_ENTRY(void, OptoRuntime::new_instance_C(klassOopDesc* klass, JavaThread* thread)) | |
165 JRT_BLOCK; | |
166 #ifndef PRODUCT | |
167 SharedRuntime::_new_instance_ctr++; // new instance requires GC | |
168 #endif | |
169 assert(check_compiled_frame(thread), "incorrect caller"); | |
170 | |
171 // These checks are cheap to make and support reflective allocation. | |
172 int lh = Klass::cast(klass)->layout_helper(); | |
173 if (Klass::layout_helper_needs_slow_path(lh) | |
174 || !instanceKlass::cast(klass)->is_initialized()) { | |
175 KlassHandle kh(THREAD, klass); | |
176 kh->check_valid_for_instantiation(false, THREAD); | |
177 if (!HAS_PENDING_EXCEPTION) { | |
178 instanceKlass::cast(kh())->initialize(THREAD); | |
179 } | |
180 if (!HAS_PENDING_EXCEPTION) { | |
181 klass = kh(); | |
182 } else { | |
183 klass = NULL; | |
184 } | |
185 } | |
186 | |
187 if (klass != NULL) { | |
188 // Scavenge and allocate an instance. | |
189 oop result = instanceKlass::cast(klass)->allocate_instance(THREAD); | |
190 thread->set_vm_result(result); | |
191 | |
192 // Pass oops back through thread local storage. Our apparent type to Java | |
193 // is that we return an oop, but we can block on exit from this routine and | |
194 // a GC can trash the oop in C's return register. The generated stub will | |
195 // fetch the oop from TLS after any possible GC. | |
196 } | |
197 | |
198 deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION); | |
199 JRT_BLOCK_END; | |
200 | |
201 if (GraphKit::use_ReduceInitialCardMarks()) { | |
1027
39b01ab7035a
6888898: CMS: ReduceInitialCardMarks unsafe in the presence of cms precleaning
ysr
parents:
605
diff
changeset
|
202 // inform GC that we won't do card marks for initializing writes. |
1166 | 203 new_store_pre_barrier(thread); |
0 | 204 } |
205 JRT_END | |
206 | |
207 | |
208 // array allocation | |
209 JRT_BLOCK_ENTRY(void, OptoRuntime::new_array_C(klassOopDesc* array_type, int len, JavaThread *thread)) | |
210 JRT_BLOCK; | |
211 #ifndef PRODUCT | |
212 SharedRuntime::_new_array_ctr++; // new array requires GC | |
213 #endif | |
214 assert(check_compiled_frame(thread), "incorrect caller"); | |
215 | |
216 // Scavenge and allocate an instance. | |
217 oop result; | |
218 | |
219 if (Klass::cast(array_type)->oop_is_typeArray()) { | |
220 // The oopFactory likes to work with the element type. | |
221 // (We could bypass the oopFactory, since it doesn't add much value.) | |
222 BasicType elem_type = typeArrayKlass::cast(array_type)->element_type(); | |
223 result = oopFactory::new_typeArray(elem_type, len, THREAD); | |
224 } else { | |
225 // Although the oopFactory likes to work with the elem_type, | |
226 // the compiler prefers the array_type, since it must already have | |
227 // that latter value in hand for the fast path. | |
228 klassOopDesc* elem_type = objArrayKlass::cast(array_type)->element_klass(); | |
229 result = oopFactory::new_objArray(elem_type, len, THREAD); | |
230 } | |
231 | |
232 // Pass oops back through thread local storage. Our apparent type to Java | |
233 // is that we return an oop, but we can block on exit from this routine and | |
234 // a GC can trash the oop in C's return register. The generated stub will | |
235 // fetch the oop from TLS after any possible GC. | |
236 deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION); | |
237 thread->set_vm_result(result); | |
238 JRT_BLOCK_END; | |
239 | |
240 if (GraphKit::use_ReduceInitialCardMarks()) { | |
1027
39b01ab7035a
6888898: CMS: ReduceInitialCardMarks unsafe in the presence of cms precleaning
ysr
parents:
605
diff
changeset
|
241 // inform GC that we won't do card marks for initializing writes. |
1166 | 242 new_store_pre_barrier(thread); |
0 | 243 } |
244 JRT_END | |
245 | |
246 // Note: multianewarray for one dimension is handled inline by GraphKit::new_array. | |
247 | |
248 // multianewarray for 2 dimensions | |
249 JRT_ENTRY(void, OptoRuntime::multianewarray2_C(klassOopDesc* elem_type, int len1, int len2, JavaThread *thread)) | |
250 #ifndef PRODUCT | |
251 SharedRuntime::_multi2_ctr++; // multianewarray for 1 dimension | |
252 #endif | |
253 assert(check_compiled_frame(thread), "incorrect caller"); | |
254 assert(oop(elem_type)->is_klass(), "not a class"); | |
255 jint dims[2]; | |
256 dims[0] = len1; | |
257 dims[1] = len2; | |
258 oop obj = arrayKlass::cast(elem_type)->multi_allocate(2, dims, THREAD); | |
259 deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION); | |
260 thread->set_vm_result(obj); | |
261 JRT_END | |
262 | |
263 // multianewarray for 3 dimensions | |
264 JRT_ENTRY(void, OptoRuntime::multianewarray3_C(klassOopDesc* elem_type, int len1, int len2, int len3, JavaThread *thread)) | |
265 #ifndef PRODUCT | |
266 SharedRuntime::_multi3_ctr++; // multianewarray for 1 dimension | |
267 #endif | |
268 assert(check_compiled_frame(thread), "incorrect caller"); | |
269 assert(oop(elem_type)->is_klass(), "not a class"); | |
270 jint dims[3]; | |
271 dims[0] = len1; | |
272 dims[1] = len2; | |
273 dims[2] = len3; | |
274 oop obj = arrayKlass::cast(elem_type)->multi_allocate(3, dims, THREAD); | |
275 deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION); | |
276 thread->set_vm_result(obj); | |
277 JRT_END | |
278 | |
279 // multianewarray for 4 dimensions | |
280 JRT_ENTRY(void, OptoRuntime::multianewarray4_C(klassOopDesc* elem_type, int len1, int len2, int len3, int len4, JavaThread *thread)) | |
281 #ifndef PRODUCT | |
282 SharedRuntime::_multi4_ctr++; // multianewarray for 1 dimension | |
283 #endif | |
284 assert(check_compiled_frame(thread), "incorrect caller"); | |
285 assert(oop(elem_type)->is_klass(), "not a class"); | |
286 jint dims[4]; | |
287 dims[0] = len1; | |
288 dims[1] = len2; | |
289 dims[2] = len3; | |
290 dims[3] = len4; | |
291 oop obj = arrayKlass::cast(elem_type)->multi_allocate(4, dims, THREAD); | |
292 deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION); | |
293 thread->set_vm_result(obj); | |
294 JRT_END | |
295 | |
296 // multianewarray for 5 dimensions | |
297 JRT_ENTRY(void, OptoRuntime::multianewarray5_C(klassOopDesc* elem_type, int len1, int len2, int len3, int len4, int len5, JavaThread *thread)) | |
298 #ifndef PRODUCT | |
299 SharedRuntime::_multi5_ctr++; // multianewarray for 1 dimension | |
300 #endif | |
301 assert(check_compiled_frame(thread), "incorrect caller"); | |
302 assert(oop(elem_type)->is_klass(), "not a class"); | |
303 jint dims[5]; | |
304 dims[0] = len1; | |
305 dims[1] = len2; | |
306 dims[2] = len3; | |
307 dims[3] = len4; | |
308 dims[4] = len5; | |
309 oop obj = arrayKlass::cast(elem_type)->multi_allocate(5, dims, THREAD); | |
310 deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION); | |
311 thread->set_vm_result(obj); | |
312 JRT_END | |
313 | |
314 const TypeFunc *OptoRuntime::new_instance_Type() { | |
315 // create input type (domain) | |
316 const Type **fields = TypeTuple::fields(1); | |
317 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // Klass to be allocated | |
318 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+1, fields); | |
319 | |
320 // create result type (range) | |
321 fields = TypeTuple::fields(1); | |
322 fields[TypeFunc::Parms+0] = TypeRawPtr::NOTNULL; // Returned oop | |
323 | |
324 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+1, fields); | |
325 | |
326 return TypeFunc::make(domain, range); | |
327 } | |
328 | |
329 | |
330 const TypeFunc *OptoRuntime::athrow_Type() { | |
331 // create input type (domain) | |
332 const Type **fields = TypeTuple::fields(1); | |
333 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // Klass to be allocated | |
334 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+1, fields); | |
335 | |
336 // create result type (range) | |
337 fields = TypeTuple::fields(0); | |
338 | |
339 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0, fields); | |
340 | |
341 return TypeFunc::make(domain, range); | |
342 } | |
343 | |
344 | |
345 const TypeFunc *OptoRuntime::new_array_Type() { | |
346 // create input type (domain) | |
347 const Type **fields = TypeTuple::fields(2); | |
348 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // element klass | |
349 fields[TypeFunc::Parms+1] = TypeInt::INT; // array size | |
350 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2, fields); | |
351 | |
352 // create result type (range) | |
353 fields = TypeTuple::fields(1); | |
354 fields[TypeFunc::Parms+0] = TypeRawPtr::NOTNULL; // Returned oop | |
355 | |
356 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+1, fields); | |
357 | |
358 return TypeFunc::make(domain, range); | |
359 } | |
360 | |
361 const TypeFunc *OptoRuntime::multianewarray_Type(int ndim) { | |
362 // create input type (domain) | |
363 const int nargs = ndim + 1; | |
364 const Type **fields = TypeTuple::fields(nargs); | |
365 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // element klass | |
366 for( int i = 1; i < nargs; i++ ) | |
367 fields[TypeFunc::Parms + i] = TypeInt::INT; // array size | |
368 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+nargs, fields); | |
369 | |
370 // create result type (range) | |
371 fields = TypeTuple::fields(1); | |
372 fields[TypeFunc::Parms+0] = TypeRawPtr::NOTNULL; // Returned oop | |
373 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+1, fields); | |
374 | |
375 return TypeFunc::make(domain, range); | |
376 } | |
377 | |
378 const TypeFunc *OptoRuntime::multianewarray2_Type() { | |
379 return multianewarray_Type(2); | |
380 } | |
381 | |
382 const TypeFunc *OptoRuntime::multianewarray3_Type() { | |
383 return multianewarray_Type(3); | |
384 } | |
385 | |
386 const TypeFunc *OptoRuntime::multianewarray4_Type() { | |
387 return multianewarray_Type(4); | |
388 } | |
389 | |
390 const TypeFunc *OptoRuntime::multianewarray5_Type() { | |
391 return multianewarray_Type(5); | |
392 } | |
393 | |
342 | 394 const TypeFunc *OptoRuntime::g1_wb_pre_Type() { |
395 const Type **fields = TypeTuple::fields(2); | |
396 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // original field value | |
397 fields[TypeFunc::Parms+1] = TypeRawPtr::NOTNULL; // thread | |
398 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2, fields); | |
399 | |
400 // create result type (range) | |
401 fields = TypeTuple::fields(0); | |
402 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0, fields); | |
403 | |
404 return TypeFunc::make(domain, range); | |
405 } | |
406 | |
407 const TypeFunc *OptoRuntime::g1_wb_post_Type() { | |
408 | |
409 const Type **fields = TypeTuple::fields(2); | |
410 fields[TypeFunc::Parms+0] = TypeRawPtr::NOTNULL; // Card addr | |
411 fields[TypeFunc::Parms+1] = TypeRawPtr::NOTNULL; // thread | |
412 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2, fields); | |
413 | |
414 // create result type (range) | |
415 fields = TypeTuple::fields(0); | |
416 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms, fields); | |
417 | |
418 return TypeFunc::make(domain, range); | |
419 } | |
420 | |
0 | 421 const TypeFunc *OptoRuntime::uncommon_trap_Type() { |
422 // create input type (domain) | |
423 const Type **fields = TypeTuple::fields(1); | |
424 // symbolOop name of class to be loaded | |
425 fields[TypeFunc::Parms+0] = TypeInt::INT; | |
426 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+1, fields); | |
427 | |
428 // create result type (range) | |
429 fields = TypeTuple::fields(0); | |
430 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0, fields); | |
431 | |
432 return TypeFunc::make(domain, range); | |
433 } | |
434 | |
435 # ifdef ENABLE_ZAP_DEAD_LOCALS | |
436 // Type used for stub generation for zap_dead_locals. | |
437 // No inputs or outputs | |
438 const TypeFunc *OptoRuntime::zap_dead_locals_Type() { | |
439 // create input type (domain) | |
440 const Type **fields = TypeTuple::fields(0); | |
441 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms,fields); | |
442 | |
443 // create result type (range) | |
444 fields = TypeTuple::fields(0); | |
445 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms,fields); | |
446 | |
447 return TypeFunc::make(domain,range); | |
448 } | |
449 # endif | |
450 | |
451 | |
452 //----------------------------------------------------------------------------- | |
453 // Monitor Handling | |
454 const TypeFunc *OptoRuntime::complete_monitor_enter_Type() { | |
455 // create input type (domain) | |
456 const Type **fields = TypeTuple::fields(2); | |
457 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // Object to be Locked | |
458 fields[TypeFunc::Parms+1] = TypeRawPtr::BOTTOM; // Address of stack location for lock | |
459 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2,fields); | |
460 | |
461 // create result type (range) | |
462 fields = TypeTuple::fields(0); | |
463 | |
464 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0,fields); | |
465 | |
466 return TypeFunc::make(domain,range); | |
467 } | |
468 | |
469 | |
470 //----------------------------------------------------------------------------- | |
471 const TypeFunc *OptoRuntime::complete_monitor_exit_Type() { | |
472 // create input type (domain) | |
473 const Type **fields = TypeTuple::fields(2); | |
474 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // Object to be Locked | |
475 fields[TypeFunc::Parms+1] = TypeRawPtr::BOTTOM; // Address of stack location for lock | |
476 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2,fields); | |
477 | |
478 // create result type (range) | |
479 fields = TypeTuple::fields(0); | |
480 | |
481 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0,fields); | |
482 | |
483 return TypeFunc::make(domain,range); | |
484 } | |
485 | |
486 const TypeFunc* OptoRuntime::flush_windows_Type() { | |
487 // create input type (domain) | |
488 const Type** fields = TypeTuple::fields(1); | |
489 fields[TypeFunc::Parms+0] = NULL; // void | |
490 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms, fields); | |
491 | |
492 // create result type | |
493 fields = TypeTuple::fields(1); | |
494 fields[TypeFunc::Parms+0] = NULL; // void | |
495 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms, fields); | |
496 | |
497 return TypeFunc::make(domain, range); | |
498 } | |
499 | |
500 const TypeFunc* OptoRuntime::l2f_Type() { | |
501 // create input type (domain) | |
502 const Type **fields = TypeTuple::fields(2); | |
503 fields[TypeFunc::Parms+0] = TypeLong::LONG; | |
504 fields[TypeFunc::Parms+1] = Type::HALF; | |
505 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2, fields); | |
506 | |
507 // create result type (range) | |
508 fields = TypeTuple::fields(1); | |
509 fields[TypeFunc::Parms+0] = Type::FLOAT; | |
510 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+1, fields); | |
511 | |
512 return TypeFunc::make(domain, range); | |
513 } | |
514 | |
515 const TypeFunc* OptoRuntime::modf_Type() { | |
516 const Type **fields = TypeTuple::fields(2); | |
517 fields[TypeFunc::Parms+0] = Type::FLOAT; | |
518 fields[TypeFunc::Parms+1] = Type::FLOAT; | |
519 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2, fields); | |
520 | |
521 // create result type (range) | |
522 fields = TypeTuple::fields(1); | |
523 fields[TypeFunc::Parms+0] = Type::FLOAT; | |
524 | |
525 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+1, fields); | |
526 | |
527 return TypeFunc::make(domain, range); | |
528 } | |
529 | |
530 const TypeFunc *OptoRuntime::Math_D_D_Type() { | |
531 // create input type (domain) | |
532 const Type **fields = TypeTuple::fields(2); | |
533 // symbolOop name of class to be loaded | |
534 fields[TypeFunc::Parms+0] = Type::DOUBLE; | |
535 fields[TypeFunc::Parms+1] = Type::HALF; | |
536 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2, fields); | |
537 | |
538 // create result type (range) | |
539 fields = TypeTuple::fields(2); | |
540 fields[TypeFunc::Parms+0] = Type::DOUBLE; | |
541 fields[TypeFunc::Parms+1] = Type::HALF; | |
542 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+2, fields); | |
543 | |
544 return TypeFunc::make(domain, range); | |
545 } | |
546 | |
547 const TypeFunc* OptoRuntime::Math_DD_D_Type() { | |
548 const Type **fields = TypeTuple::fields(4); | |
549 fields[TypeFunc::Parms+0] = Type::DOUBLE; | |
550 fields[TypeFunc::Parms+1] = Type::HALF; | |
551 fields[TypeFunc::Parms+2] = Type::DOUBLE; | |
552 fields[TypeFunc::Parms+3] = Type::HALF; | |
553 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+4, fields); | |
554 | |
555 // create result type (range) | |
556 fields = TypeTuple::fields(2); | |
557 fields[TypeFunc::Parms+0] = Type::DOUBLE; | |
558 fields[TypeFunc::Parms+1] = Type::HALF; | |
559 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+2, fields); | |
560 | |
561 return TypeFunc::make(domain, range); | |
562 } | |
563 | |
564 //-------------- currentTimeMillis | |
565 | |
566 const TypeFunc* OptoRuntime::current_time_millis_Type() { | |
567 // create input type (domain) | |
568 const Type **fields = TypeTuple::fields(0); | |
569 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+0, fields); | |
570 | |
571 // create result type (range) | |
572 fields = TypeTuple::fields(2); | |
573 fields[TypeFunc::Parms+0] = TypeLong::LONG; | |
574 fields[TypeFunc::Parms+1] = Type::HALF; | |
575 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+2, fields); | |
576 | |
577 return TypeFunc::make(domain, range); | |
578 } | |
579 | |
580 // arraycopy stub variations: | |
581 enum ArrayCopyType { | |
582 ac_fast, // void(ptr, ptr, size_t) | |
583 ac_checkcast, // int(ptr, ptr, size_t, size_t, ptr) | |
584 ac_slow, // void(ptr, int, ptr, int, int) | |
585 ac_generic // int(ptr, int, ptr, int, int) | |
586 }; | |
587 | |
588 static const TypeFunc* make_arraycopy_Type(ArrayCopyType act) { | |
589 // create input type (domain) | |
590 int num_args = (act == ac_fast ? 3 : 5); | |
591 int num_size_args = (act == ac_fast ? 1 : act == ac_checkcast ? 2 : 0); | |
592 int argcnt = num_args; | |
593 LP64_ONLY(argcnt += num_size_args); // halfwords for lengths | |
594 const Type** fields = TypeTuple::fields(argcnt); | |
595 int argp = TypeFunc::Parms; | |
596 fields[argp++] = TypePtr::NOTNULL; // src | |
597 if (num_size_args == 0) { | |
598 fields[argp++] = TypeInt::INT; // src_pos | |
599 } | |
600 fields[argp++] = TypePtr::NOTNULL; // dest | |
601 if (num_size_args == 0) { | |
602 fields[argp++] = TypeInt::INT; // dest_pos | |
603 fields[argp++] = TypeInt::INT; // length | |
604 } | |
605 while (num_size_args-- > 0) { | |
606 fields[argp++] = TypeX_X; // size in whatevers (size_t) | |
607 LP64_ONLY(fields[argp++] = Type::HALF); // other half of long length | |
608 } | |
609 if (act == ac_checkcast) { | |
610 fields[argp++] = TypePtr::NOTNULL; // super_klass | |
611 } | |
612 assert(argp == TypeFunc::Parms+argcnt, "correct decoding of act"); | |
613 const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+argcnt, fields); | |
614 | |
615 // create result type if needed | |
616 int retcnt = (act == ac_checkcast || act == ac_generic ? 1 : 0); | |
617 fields = TypeTuple::fields(1); | |
618 if (retcnt == 0) | |
619 fields[TypeFunc::Parms+0] = NULL; // void | |
620 else | |
621 fields[TypeFunc::Parms+0] = TypeInt::INT; // status result, if needed | |
622 const TypeTuple* range = TypeTuple::make(TypeFunc::Parms+retcnt, fields); | |
623 return TypeFunc::make(domain, range); | |
624 } | |
625 | |
626 const TypeFunc* OptoRuntime::fast_arraycopy_Type() { | |
627 // This signature is simple: Two base pointers and a size_t. | |
628 return make_arraycopy_Type(ac_fast); | |
629 } | |
630 | |
631 const TypeFunc* OptoRuntime::checkcast_arraycopy_Type() { | |
632 // An extension of fast_arraycopy_Type which adds type checking. | |
633 return make_arraycopy_Type(ac_checkcast); | |
634 } | |
635 | |
636 const TypeFunc* OptoRuntime::slow_arraycopy_Type() { | |
637 // This signature is exactly the same as System.arraycopy. | |
638 // There are no intptr_t (int/long) arguments. | |
639 return make_arraycopy_Type(ac_slow); | |
640 } | |
641 | |
642 const TypeFunc* OptoRuntime::generic_arraycopy_Type() { | |
643 // This signature is like System.arraycopy, except that it returns status. | |
644 return make_arraycopy_Type(ac_generic); | |
645 } | |
646 | |
647 | |
1763 | 648 const TypeFunc* OptoRuntime::array_fill_Type() { |
1844
75588558f1bf
6980792: Crash "exception happened outside interpreter, nmethods and vtable stubs (1)"
never
parents:
1763
diff
changeset
|
649 // create input type (domain): pointer, int, size_t |
75588558f1bf
6980792: Crash "exception happened outside interpreter, nmethods and vtable stubs (1)"
never
parents:
1763
diff
changeset
|
650 const Type** fields = TypeTuple::fields(3 LP64_ONLY( + 1)); |
75588558f1bf
6980792: Crash "exception happened outside interpreter, nmethods and vtable stubs (1)"
never
parents:
1763
diff
changeset
|
651 int argp = TypeFunc::Parms; |
75588558f1bf
6980792: Crash "exception happened outside interpreter, nmethods and vtable stubs (1)"
never
parents:
1763
diff
changeset
|
652 fields[argp++] = TypePtr::NOTNULL; |
75588558f1bf
6980792: Crash "exception happened outside interpreter, nmethods and vtable stubs (1)"
never
parents:
1763
diff
changeset
|
653 fields[argp++] = TypeInt::INT; |
75588558f1bf
6980792: Crash "exception happened outside interpreter, nmethods and vtable stubs (1)"
never
parents:
1763
diff
changeset
|
654 fields[argp++] = TypeX_X; // size in whatevers (size_t) |
75588558f1bf
6980792: Crash "exception happened outside interpreter, nmethods and vtable stubs (1)"
never
parents:
1763
diff
changeset
|
655 LP64_ONLY(fields[argp++] = Type::HALF); // other half of long length |
75588558f1bf
6980792: Crash "exception happened outside interpreter, nmethods and vtable stubs (1)"
never
parents:
1763
diff
changeset
|
656 const TypeTuple *domain = TypeTuple::make(argp, fields); |
1763 | 657 |
658 // create result type | |
659 fields = TypeTuple::fields(1); | |
660 fields[TypeFunc::Parms+0] = NULL; // void | |
661 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms, fields); | |
662 | |
663 return TypeFunc::make(domain, range); | |
664 } | |
665 | |
0 | 666 //------------- Interpreter state access for on stack replacement |
667 const TypeFunc* OptoRuntime::osr_end_Type() { | |
668 // create input type (domain) | |
669 const Type **fields = TypeTuple::fields(1); | |
670 fields[TypeFunc::Parms+0] = TypeRawPtr::BOTTOM; // OSR temp buf | |
671 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+1, fields); | |
672 | |
673 // create result type | |
674 fields = TypeTuple::fields(1); | |
675 // fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // locked oop | |
676 fields[TypeFunc::Parms+0] = NULL; // void | |
677 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms, fields); | |
678 return TypeFunc::make(domain, range); | |
679 } | |
680 | |
681 //-------------- methodData update helpers | |
682 | |
683 const TypeFunc* OptoRuntime::profile_receiver_type_Type() { | |
684 // create input type (domain) | |
685 const Type **fields = TypeTuple::fields(2); | |
686 fields[TypeFunc::Parms+0] = TypeAryPtr::NOTNULL; // methodData pointer | |
687 fields[TypeFunc::Parms+1] = TypeInstPtr::BOTTOM; // receiver oop | |
688 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2, fields); | |
689 | |
690 // create result type | |
691 fields = TypeTuple::fields(1); | |
692 fields[TypeFunc::Parms+0] = NULL; // void | |
693 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms, fields); | |
694 return TypeFunc::make(domain,range); | |
695 } | |
696 | |
697 JRT_LEAF(void, OptoRuntime::profile_receiver_type_C(DataLayout* data, oopDesc* receiver)) | |
698 if (receiver == NULL) return; | |
699 klassOop receiver_klass = receiver->klass(); | |
700 | |
701 intptr_t* mdp = ((intptr_t*)(data)) + DataLayout::header_size_in_cells(); | |
702 int empty_row = -1; // free row, if any is encountered | |
703 | |
704 // ReceiverTypeData* vc = new ReceiverTypeData(mdp); | |
705 for (uint row = 0; row < ReceiverTypeData::row_limit(); row++) { | |
706 // if (vc->receiver(row) == receiver_klass) | |
707 int receiver_off = ReceiverTypeData::receiver_cell_index(row); | |
708 intptr_t row_recv = *(mdp + receiver_off); | |
709 if (row_recv == (intptr_t) receiver_klass) { | |
710 // vc->set_receiver_count(row, vc->receiver_count(row) + DataLayout::counter_increment); | |
711 int count_off = ReceiverTypeData::receiver_count_cell_index(row); | |
712 *(mdp + count_off) += DataLayout::counter_increment; | |
713 return; | |
714 } else if (row_recv == 0) { | |
715 // else if (vc->receiver(row) == NULL) | |
716 empty_row = (int) row; | |
717 } | |
718 } | |
719 | |
720 if (empty_row != -1) { | |
721 int receiver_off = ReceiverTypeData::receiver_cell_index(empty_row); | |
722 // vc->set_receiver(empty_row, receiver_klass); | |
723 *(mdp + receiver_off) = (intptr_t) receiver_klass; | |
724 // vc->set_receiver_count(empty_row, DataLayout::counter_increment); | |
725 int count_off = ReceiverTypeData::receiver_count_cell_index(empty_row); | |
726 *(mdp + count_off) = DataLayout::counter_increment; | |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1166
diff
changeset
|
727 } else { |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1166
diff
changeset
|
728 // Receiver did not match any saved receiver and there is no empty row for it. |
1251
576e77447e3c
6923002: assert(false,"this call site should not be polymorphic")
kvn
parents:
1206
diff
changeset
|
729 // Increment total counter to indicate polymorphic case. |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1166
diff
changeset
|
730 intptr_t* count_p = (intptr_t*)(((byte*)(data)) + in_bytes(CounterData::count_offset())); |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1166
diff
changeset
|
731 *count_p += DataLayout::counter_increment; |
0 | 732 } |
733 JRT_END | |
734 | |
735 //----------------------------------------------------------------------------- | |
736 // implicit exception support. | |
737 | |
738 static void report_null_exception_in_code_cache(address exception_pc) { | |
739 ResourceMark rm; | |
740 CodeBlob* n = CodeCache::find_blob(exception_pc); | |
741 if (n != NULL) { | |
742 tty->print_cr("#"); | |
743 tty->print_cr("# HotSpot Runtime Error, null exception in generated code"); | |
744 tty->print_cr("#"); | |
745 tty->print_cr("# pc where exception happened = " INTPTR_FORMAT, exception_pc); | |
746 | |
747 if (n->is_nmethod()) { | |
748 methodOop method = ((nmethod*)n)->method(); | |
749 tty->print_cr("# Method where it happened %s.%s ", Klass::cast(method->method_holder())->name()->as_C_string(), method->name()->as_C_string()); | |
750 tty->print_cr("#"); | |
751 if (ShowMessageBoxOnError && UpdateHotSpotCompilerFileOnError) { | |
752 const char* title = "HotSpot Runtime Error"; | |
753 const char* question = "Do you want to exclude compilation of this method in future runs?"; | |
754 if (os::message_box(title, question)) { | |
755 CompilerOracle::append_comment_to_file(""); | |
756 CompilerOracle::append_comment_to_file("Null exception in compiled code resulted in the following exclude"); | |
757 CompilerOracle::append_comment_to_file(""); | |
758 CompilerOracle::append_exclude_to_file(method); | |
759 tty->print_cr("#"); | |
760 tty->print_cr("# %s has been updated to exclude the specified method", CompileCommandFile); | |
761 tty->print_cr("#"); | |
762 } | |
763 } | |
764 fatal("Implicit null exception happened in compiled method"); | |
765 } else { | |
766 n->print(); | |
767 fatal("Implicit null exception happened in generated stub"); | |
768 } | |
769 } | |
770 fatal("Implicit null exception at wrong place"); | |
771 } | |
772 | |
773 | |
774 //------------------------------------------------------------------------------------- | |
775 // register policy | |
776 | |
777 bool OptoRuntime::is_callee_saved_register(MachRegisterNumbers reg) { | |
778 assert(reg >= 0 && reg < _last_Mach_Reg, "must be a machine register"); | |
779 switch (register_save_policy[reg]) { | |
780 case 'C': return false; //SOC | |
781 case 'E': return true ; //SOE | |
782 case 'N': return false; //NS | |
783 case 'A': return false; //AS | |
784 } | |
785 ShouldNotReachHere(); | |
786 return false; | |
787 } | |
788 | |
789 //----------------------------------------------------------------------- | |
790 // Exceptions | |
791 // | |
792 | |
793 static void trace_exception(oop exception_oop, address exception_pc, const char* msg) PRODUCT_RETURN; | |
794 | |
795 // The method is an entry that is always called by a C++ method not | |
796 // directly from compiled code. Compiled code will call the C++ method following. | |
797 // We can't allow async exception to be installed during exception processing. | |
798 JRT_ENTRY_NO_ASYNC(address, OptoRuntime::handle_exception_C_helper(JavaThread* thread, nmethod* &nm)) | |
799 | |
800 // Do not confuse exception_oop with pending_exception. The exception_oop | |
801 // is only used to pass arguments into the method. Not for general | |
802 // exception handling. DO NOT CHANGE IT to use pending_exception, since | |
803 // the runtime stubs checks this on exit. | |
804 assert(thread->exception_oop() != NULL, "exception oop is found"); | |
805 address handler_address = NULL; | |
806 | |
807 Handle exception(thread, thread->exception_oop()); | |
808 | |
809 if (TraceExceptions) { | |
810 trace_exception(exception(), thread->exception_pc(), ""); | |
811 } | |
812 // for AbortVMOnException flag | |
813 NOT_PRODUCT(Exceptions::debug_check_abort(exception)); | |
814 | |
815 #ifdef ASSERT | |
1142 | 816 if (!(exception->is_a(SystemDictionary::Throwable_klass()))) { |
0 | 817 // should throw an exception here |
818 ShouldNotReachHere(); | |
819 } | |
820 #endif | |
821 | |
822 | |
823 // new exception handling: this method is entered only from adapters | |
824 // exceptions from compiled java methods are handled in compiled code | |
825 // using rethrow node | |
826 | |
827 address pc = thread->exception_pc(); | |
828 nm = CodeCache::find_nmethod(pc); | |
829 assert(nm != NULL, "No NMethod found"); | |
830 if (nm->is_native_method()) { | |
831 fatal("Native mathod should not have path to exception handling"); | |
832 } else { | |
833 // we are switching to old paradigm: search for exception handler in caller_frame | |
834 // instead in exception handler of caller_frame.sender() | |
835 | |
1213
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
1166
diff
changeset
|
836 if (JvmtiExport::can_post_on_exceptions()) { |
0 | 837 // "Full-speed catching" is not necessary here, |
838 // since we're notifying the VM on every catch. | |
839 // Force deoptimization and the rest of the lookup | |
840 // will be fine. | |
841 deoptimize_caller_frame(thread, true); | |
842 } | |
843 | |
844 // Check the stack guard pages. If enabled, look for handler in this frame; | |
845 // otherwise, forcibly unwind the frame. | |
846 // | |
847 // 4826555: use default current sp for reguard_stack instead of &nm: it's more accurate. | |
848 bool force_unwind = !thread->reguard_stack(); | |
849 bool deopting = false; | |
850 if (nm->is_deopt_pc(pc)) { | |
851 deopting = true; | |
852 RegisterMap map(thread, false); | |
853 frame deoptee = thread->last_frame().sender(&map); | |
854 assert(deoptee.is_deoptimized_frame(), "must be deopted"); | |
855 // Adjust the pc back to the original throwing pc | |
856 pc = deoptee.pc(); | |
857 } | |
858 | |
859 // If we are forcing an unwind because of stack overflow then deopt is | |
860 // irrelevant sice we are throwing the frame away anyway. | |
861 | |
862 if (deopting && !force_unwind) { | |
863 handler_address = SharedRuntime::deopt_blob()->unpack_with_exception(); | |
864 } else { | |
865 | |
866 handler_address = | |
867 force_unwind ? NULL : nm->handler_for_exception_and_pc(exception, pc); | |
868 | |
869 if (handler_address == NULL) { | |
870 handler_address = SharedRuntime::compute_compiled_exc_handler(nm, pc, exception, force_unwind, true); | |
871 assert (handler_address != NULL, "must have compiled handler"); | |
872 // Update the exception cache only when the unwind was not forced. | |
873 if (!force_unwind) { | |
874 nm->add_handler_for_exception_and_pc(exception,pc,handler_address); | |
875 } | |
876 } else { | |
877 assert(handler_address == SharedRuntime::compute_compiled_exc_handler(nm, pc, exception, force_unwind, true), "Must be the same"); | |
878 } | |
879 } | |
880 | |
881 thread->set_exception_pc(pc); | |
882 thread->set_exception_handler_pc(handler_address); | |
883 thread->set_exception_stack_size(0); | |
1135
e66fd840cb6b
6893081: method handle & invokedynamic code needs additional cleanup (post 6815692, 6858164)
twisti
parents:
1027
diff
changeset
|
884 |
1295 | 885 // Check if the exception PC is a MethodHandle call site. |
1368
93767e6a2dfd
6941529: SharedRuntime::raw_exception_handler_for_return_address must reset thread MethodHandle flag
twisti
parents:
1295
diff
changeset
|
886 thread->set_is_method_handle_return(nm->is_method_handle_return(pc)); |
0 | 887 } |
888 | |
889 // Restore correct return pc. Was saved above. | |
890 thread->set_exception_oop(exception()); | |
891 return handler_address; | |
892 | |
893 JRT_END | |
894 | |
895 // We are entering here from exception_blob | |
896 // If there is a compiled exception handler in this method, we will continue there; | |
897 // otherwise we will unwind the stack and continue at the caller of top frame method | |
898 // Note we enter without the usual JRT wrapper. We will call a helper routine that | |
899 // will do the normal VM entry. We do it this way so that we can see if the nmethod | |
900 // we looked up the handler for has been deoptimized in the meantime. If it has been | |
901 // we must not use the handler and instread return the deopt blob. | |
902 address OptoRuntime::handle_exception_C(JavaThread* thread) { | |
903 // | |
904 // We are in Java not VM and in debug mode we have a NoHandleMark | |
905 // | |
906 #ifndef PRODUCT | |
907 SharedRuntime::_find_handler_ctr++; // find exception handler | |
908 #endif | |
909 debug_only(NoHandleMark __hm;) | |
910 nmethod* nm = NULL; | |
911 address handler_address = NULL; | |
912 { | |
913 // Enter the VM | |
914 | |
915 ResetNoHandleMark rnhm; | |
916 handler_address = handle_exception_C_helper(thread, nm); | |
917 } | |
918 | |
919 // Back in java: Use no oops, DON'T safepoint | |
920 | |
921 // Now check to see if the handler we are returning is in a now | |
922 // deoptimized frame | |
923 | |
924 if (nm != NULL) { | |
925 RegisterMap map(thread, false); | |
926 frame caller = thread->last_frame().sender(&map); | |
927 #ifdef ASSERT | |
928 assert(caller.is_compiled_frame(), "must be"); | |
929 #endif // ASSERT | |
930 if (caller.is_deoptimized_frame()) { | |
931 handler_address = SharedRuntime::deopt_blob()->unpack_with_exception(); | |
932 } | |
933 } | |
934 return handler_address; | |
935 } | |
936 | |
937 //------------------------------rethrow---------------------------------------- | |
938 // We get here after compiled code has executed a 'RethrowNode'. The callee | |
939 // is either throwing or rethrowing an exception. The callee-save registers | |
940 // have been restored, synchronized objects have been unlocked and the callee | |
941 // stack frame has been removed. The return address was passed in. | |
942 // Exception oop is passed as the 1st argument. This routine is then called | |
943 // from the stub. On exit, we know where to jump in the caller's code. | |
944 // After this C code exits, the stub will pop his frame and end in a jump | |
945 // (instead of a return). We enter the caller's default handler. | |
946 // | |
947 // This must be JRT_LEAF: | |
948 // - caller will not change its state as we cannot block on exit, | |
949 // therefore raw_exception_handler_for_return_address is all it takes | |
950 // to handle deoptimized blobs | |
951 // | |
952 // However, there needs to be a safepoint check in the middle! So compiled | |
953 // safepoints are completely watertight. | |
954 // | |
955 // Thus, it cannot be a leaf since it contains the No_GC_Verifier. | |
956 // | |
957 // *THIS IS NOT RECOMMENDED PROGRAMMING STYLE* | |
958 // | |
959 address OptoRuntime::rethrow_C(oopDesc* exception, JavaThread* thread, address ret_pc) { | |
960 #ifndef PRODUCT | |
961 SharedRuntime::_rethrow_ctr++; // count rethrows | |
962 #endif | |
963 assert (exception != NULL, "should have thrown a NULLPointerException"); | |
964 #ifdef ASSERT | |
1142 | 965 if (!(exception->is_a(SystemDictionary::Throwable_klass()))) { |
0 | 966 // should throw an exception here |
967 ShouldNotReachHere(); | |
968 } | |
969 #endif | |
970 | |
971 thread->set_vm_result(exception); | |
972 // Frame not compiled (handles deoptimization blob) | |
1295 | 973 return SharedRuntime::raw_exception_handler_for_return_address(thread, ret_pc); |
0 | 974 } |
975 | |
976 | |
977 const TypeFunc *OptoRuntime::rethrow_Type() { | |
978 // create input type (domain) | |
979 const Type **fields = TypeTuple::fields(1); | |
980 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // Exception oop | |
981 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+1,fields); | |
982 | |
983 // create result type (range) | |
984 fields = TypeTuple::fields(1); | |
985 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // Exception oop | |
986 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+1, fields); | |
987 | |
988 return TypeFunc::make(domain, range); | |
989 } | |
990 | |
991 | |
992 void OptoRuntime::deoptimize_caller_frame(JavaThread *thread, bool doit) { | |
993 // Deoptimize frame | |
994 if (doit) { | |
995 // Called from within the owner thread, so no need for safepoint | |
996 RegisterMap reg_map(thread); | |
997 frame stub_frame = thread->last_frame(); | |
998 assert(stub_frame.is_runtime_frame() || exception_blob()->contains(stub_frame.pc()), "sanity check"); | |
999 frame caller_frame = stub_frame.sender(®_map); | |
1000 | |
1213
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
1166
diff
changeset
|
1001 // bypass VM_DeoptimizeFrame and deoptimize the frame directly |
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
1166
diff
changeset
|
1002 Deoptimization::deoptimize_frame(thread, caller_frame.id()); |
0 | 1003 } |
1004 } | |
1005 | |
1006 | |
1007 const TypeFunc *OptoRuntime::register_finalizer_Type() { | |
1008 // create input type (domain) | |
1009 const Type **fields = TypeTuple::fields(1); | |
1010 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // oop; Receiver | |
1011 // // The JavaThread* is passed to each routine as the last argument | |
1012 // fields[TypeFunc::Parms+1] = TypeRawPtr::NOTNULL; // JavaThread *; Executing thread | |
1013 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+1,fields); | |
1014 | |
1015 // create result type (range) | |
1016 fields = TypeTuple::fields(0); | |
1017 | |
1018 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0,fields); | |
1019 | |
1020 return TypeFunc::make(domain,range); | |
1021 } | |
1022 | |
1023 | |
1024 //----------------------------------------------------------------------------- | |
1025 // Dtrace support. entry and exit probes have the same signature | |
1026 const TypeFunc *OptoRuntime::dtrace_method_entry_exit_Type() { | |
1027 // create input type (domain) | |
1028 const Type **fields = TypeTuple::fields(2); | |
1029 fields[TypeFunc::Parms+0] = TypeRawPtr::BOTTOM; // Thread-local storage | |
1030 fields[TypeFunc::Parms+1] = TypeInstPtr::NOTNULL; // methodOop; Method we are entering | |
1031 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2,fields); | |
1032 | |
1033 // create result type (range) | |
1034 fields = TypeTuple::fields(0); | |
1035 | |
1036 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0,fields); | |
1037 | |
1038 return TypeFunc::make(domain,range); | |
1039 } | |
1040 | |
1041 const TypeFunc *OptoRuntime::dtrace_object_alloc_Type() { | |
1042 // create input type (domain) | |
1043 const Type **fields = TypeTuple::fields(2); | |
1044 fields[TypeFunc::Parms+0] = TypeRawPtr::BOTTOM; // Thread-local storage | |
1045 fields[TypeFunc::Parms+1] = TypeInstPtr::NOTNULL; // oop; newly allocated object | |
1046 | |
1047 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2,fields); | |
1048 | |
1049 // create result type (range) | |
1050 fields = TypeTuple::fields(0); | |
1051 | |
1052 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0,fields); | |
1053 | |
1054 return TypeFunc::make(domain,range); | |
1055 } | |
1056 | |
1057 | |
1058 JRT_ENTRY_NO_ASYNC(void, OptoRuntime::register_finalizer(oopDesc* obj, JavaThread* thread)) | |
1059 assert(obj->is_oop(), "must be a valid oop"); | |
1060 assert(obj->klass()->klass_part()->has_finalizer(), "shouldn't be here otherwise"); | |
1061 instanceKlass::register_finalizer(instanceOop(obj), CHECK); | |
1062 JRT_END | |
1063 | |
1064 //----------------------------------------------------------------------------- | |
1065 | |
1066 NamedCounter * volatile OptoRuntime::_named_counters = NULL; | |
1067 | |
1068 // | |
1069 // dump the collected NamedCounters. | |
1070 // | |
1071 void OptoRuntime::print_named_counters() { | |
1072 int total_lock_count = 0; | |
1073 int eliminated_lock_count = 0; | |
1074 | |
1075 NamedCounter* c = _named_counters; | |
1076 while (c) { | |
1077 if (c->tag() == NamedCounter::LockCounter || c->tag() == NamedCounter::EliminatedLockCounter) { | |
1078 int count = c->count(); | |
1079 if (count > 0) { | |
1080 bool eliminated = c->tag() == NamedCounter::EliminatedLockCounter; | |
1081 if (Verbose) { | |
1082 tty->print_cr("%d %s%s", count, c->name(), eliminated ? " (eliminated)" : ""); | |
1083 } | |
1084 total_lock_count += count; | |
1085 if (eliminated) { | |
1086 eliminated_lock_count += count; | |
1087 } | |
1088 } | |
1089 } else if (c->tag() == NamedCounter::BiasedLockingCounter) { | |
1090 BiasedLockingCounters* blc = ((BiasedLockingNamedCounter*)c)->counters(); | |
1091 if (blc->nonzero()) { | |
1092 tty->print_cr("%s", c->name()); | |
1093 blc->print_on(tty); | |
1094 } | |
1095 } | |
1096 c = c->next(); | |
1097 } | |
1098 if (total_lock_count > 0) { | |
1099 tty->print_cr("dynamic locks: %d", total_lock_count); | |
1100 if (eliminated_lock_count) { | |
1101 tty->print_cr("eliminated locks: %d (%d%%)", eliminated_lock_count, | |
1102 (int)(eliminated_lock_count * 100.0 / total_lock_count)); | |
1103 } | |
1104 } | |
1105 } | |
1106 | |
1107 // | |
1108 // Allocate a new NamedCounter. The JVMState is used to generate the | |
1109 // name which consists of method@line for the inlining tree. | |
1110 // | |
1111 | |
1112 NamedCounter* OptoRuntime::new_named_counter(JVMState* youngest_jvms, NamedCounter::CounterTag tag) { | |
1113 int max_depth = youngest_jvms->depth(); | |
1114 | |
1115 // Visit scopes from youngest to oldest. | |
1116 bool first = true; | |
1117 stringStream st; | |
1118 for (int depth = max_depth; depth >= 1; depth--) { | |
1119 JVMState* jvms = youngest_jvms->of_depth(depth); | |
1120 ciMethod* m = jvms->has_method() ? jvms->method() : NULL; | |
1121 if (!first) { | |
1122 st.print(" "); | |
1123 } else { | |
1124 first = false; | |
1125 } | |
1126 int bci = jvms->bci(); | |
1127 if (bci < 0) bci = 0; | |
1128 st.print("%s.%s@%d", m->holder()->name()->as_utf8(), m->name()->as_utf8(), bci); | |
1129 // To print linenumbers instead of bci use: m->line_number_from_bci(bci) | |
1130 } | |
1131 NamedCounter* c; | |
1132 if (tag == NamedCounter::BiasedLockingCounter) { | |
1133 c = new BiasedLockingNamedCounter(strdup(st.as_string())); | |
1134 } else { | |
1135 c = new NamedCounter(strdup(st.as_string()), tag); | |
1136 } | |
1137 | |
1138 // atomically add the new counter to the head of the list. We only | |
1139 // add counters so this is safe. | |
1140 NamedCounter* head; | |
1141 do { | |
1142 head = _named_counters; | |
1143 c->set_next(head); | |
1144 } while (Atomic::cmpxchg_ptr(c, &_named_counters, head) != head); | |
1145 return c; | |
1146 } | |
1147 | |
1148 //----------------------------------------------------------------------------- | |
1149 // Non-product code | |
1150 #ifndef PRODUCT | |
1151 | |
1152 int trace_exception_counter = 0; | |
1153 static void trace_exception(oop exception_oop, address exception_pc, const char* msg) { | |
1154 ttyLocker ttyl; | |
1155 trace_exception_counter++; | |
1156 tty->print("%d [Exception (%s): ", trace_exception_counter, msg); | |
1157 exception_oop->print_value(); | |
1158 tty->print(" in "); | |
1159 CodeBlob* blob = CodeCache::find_blob(exception_pc); | |
1160 if (blob->is_nmethod()) { | |
1161 ((nmethod*)blob)->method()->print_value(); | |
1162 } else if (blob->is_runtime_stub()) { | |
1163 tty->print("<runtime-stub>"); | |
1164 } else { | |
1165 tty->print("<unknown>"); | |
1166 } | |
1167 tty->print(" at " INTPTR_FORMAT, exception_pc); | |
1168 tty->print_cr("]"); | |
1169 } | |
1170 | |
1171 #endif // PRODUCT | |
1172 | |
1173 | |
1174 # ifdef ENABLE_ZAP_DEAD_LOCALS | |
1175 // Called from call sites in compiled code with oop maps (actually safepoints) | |
1176 // Zaps dead locals in first java frame. | |
1177 // Is entry because may need to lock to generate oop maps | |
1178 // Currently, only used for compiler frames, but someday may be used | |
1179 // for interpreter frames, too. | |
1180 | |
1181 int OptoRuntime::ZapDeadCompiledLocals_count = 0; | |
1182 | |
1183 // avoid pointers to member funcs with these helpers | |
1184 static bool is_java_frame( frame* f) { return f->is_java_frame(); } | |
1185 static bool is_native_frame(frame* f) { return f->is_native_frame(); } | |
1186 | |
1187 | |
1188 void OptoRuntime::zap_dead_java_or_native_locals(JavaThread* thread, | |
1189 bool (*is_this_the_right_frame_to_zap)(frame*)) { | |
1190 assert(JavaThread::current() == thread, "is this needed?"); | |
1191 | |
1192 if ( !ZapDeadCompiledLocals ) return; | |
1193 | |
1194 bool skip = false; | |
1195 | |
1196 if ( ZapDeadCompiledLocalsFirst == 0 ) ; // nothing special | |
1197 else if ( ZapDeadCompiledLocalsFirst > ZapDeadCompiledLocals_count ) skip = true; | |
1198 else if ( ZapDeadCompiledLocalsFirst == ZapDeadCompiledLocals_count ) | |
1199 warning("starting zapping after skipping"); | |
1200 | |
1201 if ( ZapDeadCompiledLocalsLast == -1 ) ; // nothing special | |
1202 else if ( ZapDeadCompiledLocalsLast < ZapDeadCompiledLocals_count ) skip = true; | |
1203 else if ( ZapDeadCompiledLocalsLast == ZapDeadCompiledLocals_count ) | |
1204 warning("about to zap last zap"); | |
1205 | |
1206 ++ZapDeadCompiledLocals_count; // counts skipped zaps, too | |
1207 | |
1208 if ( skip ) return; | |
1209 | |
1210 // find java frame and zap it | |
1211 | |
1212 for (StackFrameStream sfs(thread); !sfs.is_done(); sfs.next()) { | |
1213 if (is_this_the_right_frame_to_zap(sfs.current()) ) { | |
1214 sfs.current()->zap_dead_locals(thread, sfs.register_map()); | |
1215 return; | |
1216 } | |
1217 } | |
1218 warning("no frame found to zap in zap_dead_Java_locals_C"); | |
1219 } | |
1220 | |
1221 JRT_LEAF(void, OptoRuntime::zap_dead_Java_locals_C(JavaThread* thread)) | |
1222 zap_dead_java_or_native_locals(thread, is_java_frame); | |
1223 JRT_END | |
1224 | |
1225 // The following does not work because for one thing, the | |
1226 // thread state is wrong; it expects java, but it is native. | |
605 | 1227 // Also, the invariants in a native stub are different and |
0 | 1228 // I'm not sure it is safe to have a MachCalRuntimeDirectNode |
1229 // in there. | |
1230 // So for now, we do not zap in native stubs. | |
1231 | |
1232 JRT_LEAF(void, OptoRuntime::zap_dead_native_locals_C(JavaThread* thread)) | |
1233 zap_dead_java_or_native_locals(thread, is_native_frame); | |
1234 JRT_END | |
1235 | |
1236 # endif |