Mercurial > hg > truffle
annotate src/share/vm/opto/runtime.cpp @ 1721:413ad0331a0c
6977924: Changes for 6975078 produce build error with certain gcc versions
Summary: The changes introduced for 6975078 assign badHeapOopVal to the _allocation field in the ResourceObj class. In 32 bit linux builds with certain versions of gcc this assignment will be flagged as an error while compiling allocation.cpp. In 32 bit builds the constant value badHeapOopVal (which is cast to an intptr_t) is negative. The _allocation field is typed as an unsigned intptr_t and gcc catches this as an error.
Reviewed-by: jcoomes, ysr, phh
author | johnc |
---|---|
date | Wed, 18 Aug 2010 10:59:06 -0700 |
parents | c18cbe5936b8 |
children | d6f45b55c972 |
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 | |
648 //------------- Interpreter state access for on stack replacement | |
649 const TypeFunc* OptoRuntime::osr_end_Type() { | |
650 // create input type (domain) | |
651 const Type **fields = TypeTuple::fields(1); | |
652 fields[TypeFunc::Parms+0] = TypeRawPtr::BOTTOM; // OSR temp buf | |
653 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+1, fields); | |
654 | |
655 // create result type | |
656 fields = TypeTuple::fields(1); | |
657 // fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // locked oop | |
658 fields[TypeFunc::Parms+0] = NULL; // void | |
659 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms, fields); | |
660 return TypeFunc::make(domain, range); | |
661 } | |
662 | |
663 //-------------- methodData update helpers | |
664 | |
665 const TypeFunc* OptoRuntime::profile_receiver_type_Type() { | |
666 // create input type (domain) | |
667 const Type **fields = TypeTuple::fields(2); | |
668 fields[TypeFunc::Parms+0] = TypeAryPtr::NOTNULL; // methodData pointer | |
669 fields[TypeFunc::Parms+1] = TypeInstPtr::BOTTOM; // receiver oop | |
670 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2, fields); | |
671 | |
672 // create result type | |
673 fields = TypeTuple::fields(1); | |
674 fields[TypeFunc::Parms+0] = NULL; // void | |
675 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms, fields); | |
676 return TypeFunc::make(domain,range); | |
677 } | |
678 | |
679 JRT_LEAF(void, OptoRuntime::profile_receiver_type_C(DataLayout* data, oopDesc* receiver)) | |
680 if (receiver == NULL) return; | |
681 klassOop receiver_klass = receiver->klass(); | |
682 | |
683 intptr_t* mdp = ((intptr_t*)(data)) + DataLayout::header_size_in_cells(); | |
684 int empty_row = -1; // free row, if any is encountered | |
685 | |
686 // ReceiverTypeData* vc = new ReceiverTypeData(mdp); | |
687 for (uint row = 0; row < ReceiverTypeData::row_limit(); row++) { | |
688 // if (vc->receiver(row) == receiver_klass) | |
689 int receiver_off = ReceiverTypeData::receiver_cell_index(row); | |
690 intptr_t row_recv = *(mdp + receiver_off); | |
691 if (row_recv == (intptr_t) receiver_klass) { | |
692 // vc->set_receiver_count(row, vc->receiver_count(row) + DataLayout::counter_increment); | |
693 int count_off = ReceiverTypeData::receiver_count_cell_index(row); | |
694 *(mdp + count_off) += DataLayout::counter_increment; | |
695 return; | |
696 } else if (row_recv == 0) { | |
697 // else if (vc->receiver(row) == NULL) | |
698 empty_row = (int) row; | |
699 } | |
700 } | |
701 | |
702 if (empty_row != -1) { | |
703 int receiver_off = ReceiverTypeData::receiver_cell_index(empty_row); | |
704 // vc->set_receiver(empty_row, receiver_klass); | |
705 *(mdp + receiver_off) = (intptr_t) receiver_klass; | |
706 // vc->set_receiver_count(empty_row, DataLayout::counter_increment); | |
707 int count_off = ReceiverTypeData::receiver_count_cell_index(empty_row); | |
708 *(mdp + count_off) = DataLayout::counter_increment; | |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1166
diff
changeset
|
709 } else { |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1166
diff
changeset
|
710 // 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
|
711 // Increment total counter to indicate polymorphic case. |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1166
diff
changeset
|
712 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
|
713 *count_p += DataLayout::counter_increment; |
0 | 714 } |
715 JRT_END | |
716 | |
717 //----------------------------------------------------------------------------- | |
718 // implicit exception support. | |
719 | |
720 static void report_null_exception_in_code_cache(address exception_pc) { | |
721 ResourceMark rm; | |
722 CodeBlob* n = CodeCache::find_blob(exception_pc); | |
723 if (n != NULL) { | |
724 tty->print_cr("#"); | |
725 tty->print_cr("# HotSpot Runtime Error, null exception in generated code"); | |
726 tty->print_cr("#"); | |
727 tty->print_cr("# pc where exception happened = " INTPTR_FORMAT, exception_pc); | |
728 | |
729 if (n->is_nmethod()) { | |
730 methodOop method = ((nmethod*)n)->method(); | |
731 tty->print_cr("# Method where it happened %s.%s ", Klass::cast(method->method_holder())->name()->as_C_string(), method->name()->as_C_string()); | |
732 tty->print_cr("#"); | |
733 if (ShowMessageBoxOnError && UpdateHotSpotCompilerFileOnError) { | |
734 const char* title = "HotSpot Runtime Error"; | |
735 const char* question = "Do you want to exclude compilation of this method in future runs?"; | |
736 if (os::message_box(title, question)) { | |
737 CompilerOracle::append_comment_to_file(""); | |
738 CompilerOracle::append_comment_to_file("Null exception in compiled code resulted in the following exclude"); | |
739 CompilerOracle::append_comment_to_file(""); | |
740 CompilerOracle::append_exclude_to_file(method); | |
741 tty->print_cr("#"); | |
742 tty->print_cr("# %s has been updated to exclude the specified method", CompileCommandFile); | |
743 tty->print_cr("#"); | |
744 } | |
745 } | |
746 fatal("Implicit null exception happened in compiled method"); | |
747 } else { | |
748 n->print(); | |
749 fatal("Implicit null exception happened in generated stub"); | |
750 } | |
751 } | |
752 fatal("Implicit null exception at wrong place"); | |
753 } | |
754 | |
755 | |
756 //------------------------------------------------------------------------------------- | |
757 // register policy | |
758 | |
759 bool OptoRuntime::is_callee_saved_register(MachRegisterNumbers reg) { | |
760 assert(reg >= 0 && reg < _last_Mach_Reg, "must be a machine register"); | |
761 switch (register_save_policy[reg]) { | |
762 case 'C': return false; //SOC | |
763 case 'E': return true ; //SOE | |
764 case 'N': return false; //NS | |
765 case 'A': return false; //AS | |
766 } | |
767 ShouldNotReachHere(); | |
768 return false; | |
769 } | |
770 | |
771 //----------------------------------------------------------------------- | |
772 // Exceptions | |
773 // | |
774 | |
775 static void trace_exception(oop exception_oop, address exception_pc, const char* msg) PRODUCT_RETURN; | |
776 | |
777 // The method is an entry that is always called by a C++ method not | |
778 // directly from compiled code. Compiled code will call the C++ method following. | |
779 // We can't allow async exception to be installed during exception processing. | |
780 JRT_ENTRY_NO_ASYNC(address, OptoRuntime::handle_exception_C_helper(JavaThread* thread, nmethod* &nm)) | |
781 | |
782 // Do not confuse exception_oop with pending_exception. The exception_oop | |
783 // is only used to pass arguments into the method. Not for general | |
784 // exception handling. DO NOT CHANGE IT to use pending_exception, since | |
785 // the runtime stubs checks this on exit. | |
786 assert(thread->exception_oop() != NULL, "exception oop is found"); | |
787 address handler_address = NULL; | |
788 | |
789 Handle exception(thread, thread->exception_oop()); | |
790 | |
791 if (TraceExceptions) { | |
792 trace_exception(exception(), thread->exception_pc(), ""); | |
793 } | |
794 // for AbortVMOnException flag | |
795 NOT_PRODUCT(Exceptions::debug_check_abort(exception)); | |
796 | |
797 #ifdef ASSERT | |
1142 | 798 if (!(exception->is_a(SystemDictionary::Throwable_klass()))) { |
0 | 799 // should throw an exception here |
800 ShouldNotReachHere(); | |
801 } | |
802 #endif | |
803 | |
804 | |
805 // new exception handling: this method is entered only from adapters | |
806 // exceptions from compiled java methods are handled in compiled code | |
807 // using rethrow node | |
808 | |
809 address pc = thread->exception_pc(); | |
810 nm = CodeCache::find_nmethod(pc); | |
811 assert(nm != NULL, "No NMethod found"); | |
812 if (nm->is_native_method()) { | |
813 fatal("Native mathod should not have path to exception handling"); | |
814 } else { | |
815 // we are switching to old paradigm: search for exception handler in caller_frame | |
816 // instead in exception handler of caller_frame.sender() | |
817 | |
1213
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
1166
diff
changeset
|
818 if (JvmtiExport::can_post_on_exceptions()) { |
0 | 819 // "Full-speed catching" is not necessary here, |
820 // since we're notifying the VM on every catch. | |
821 // Force deoptimization and the rest of the lookup | |
822 // will be fine. | |
823 deoptimize_caller_frame(thread, true); | |
824 } | |
825 | |
826 // Check the stack guard pages. If enabled, look for handler in this frame; | |
827 // otherwise, forcibly unwind the frame. | |
828 // | |
829 // 4826555: use default current sp for reguard_stack instead of &nm: it's more accurate. | |
830 bool force_unwind = !thread->reguard_stack(); | |
831 bool deopting = false; | |
832 if (nm->is_deopt_pc(pc)) { | |
833 deopting = true; | |
834 RegisterMap map(thread, false); | |
835 frame deoptee = thread->last_frame().sender(&map); | |
836 assert(deoptee.is_deoptimized_frame(), "must be deopted"); | |
837 // Adjust the pc back to the original throwing pc | |
838 pc = deoptee.pc(); | |
839 } | |
840 | |
841 // If we are forcing an unwind because of stack overflow then deopt is | |
842 // irrelevant sice we are throwing the frame away anyway. | |
843 | |
844 if (deopting && !force_unwind) { | |
845 handler_address = SharedRuntime::deopt_blob()->unpack_with_exception(); | |
846 } else { | |
847 | |
848 handler_address = | |
849 force_unwind ? NULL : nm->handler_for_exception_and_pc(exception, pc); | |
850 | |
851 if (handler_address == NULL) { | |
852 handler_address = SharedRuntime::compute_compiled_exc_handler(nm, pc, exception, force_unwind, true); | |
853 assert (handler_address != NULL, "must have compiled handler"); | |
854 // Update the exception cache only when the unwind was not forced. | |
855 if (!force_unwind) { | |
856 nm->add_handler_for_exception_and_pc(exception,pc,handler_address); | |
857 } | |
858 } else { | |
859 assert(handler_address == SharedRuntime::compute_compiled_exc_handler(nm, pc, exception, force_unwind, true), "Must be the same"); | |
860 } | |
861 } | |
862 | |
863 thread->set_exception_pc(pc); | |
864 thread->set_exception_handler_pc(handler_address); | |
865 thread->set_exception_stack_size(0); | |
1135
e66fd840cb6b
6893081: method handle & invokedynamic code needs additional cleanup (post 6815692, 6858164)
twisti
parents:
1027
diff
changeset
|
866 |
1295 | 867 // 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
|
868 thread->set_is_method_handle_return(nm->is_method_handle_return(pc)); |
0 | 869 } |
870 | |
871 // Restore correct return pc. Was saved above. | |
872 thread->set_exception_oop(exception()); | |
873 return handler_address; | |
874 | |
875 JRT_END | |
876 | |
877 // We are entering here from exception_blob | |
878 // If there is a compiled exception handler in this method, we will continue there; | |
879 // otherwise we will unwind the stack and continue at the caller of top frame method | |
880 // Note we enter without the usual JRT wrapper. We will call a helper routine that | |
881 // will do the normal VM entry. We do it this way so that we can see if the nmethod | |
882 // we looked up the handler for has been deoptimized in the meantime. If it has been | |
883 // we must not use the handler and instread return the deopt blob. | |
884 address OptoRuntime::handle_exception_C(JavaThread* thread) { | |
885 // | |
886 // We are in Java not VM and in debug mode we have a NoHandleMark | |
887 // | |
888 #ifndef PRODUCT | |
889 SharedRuntime::_find_handler_ctr++; // find exception handler | |
890 #endif | |
891 debug_only(NoHandleMark __hm;) | |
892 nmethod* nm = NULL; | |
893 address handler_address = NULL; | |
894 { | |
895 // Enter the VM | |
896 | |
897 ResetNoHandleMark rnhm; | |
898 handler_address = handle_exception_C_helper(thread, nm); | |
899 } | |
900 | |
901 // Back in java: Use no oops, DON'T safepoint | |
902 | |
903 // Now check to see if the handler we are returning is in a now | |
904 // deoptimized frame | |
905 | |
906 if (nm != NULL) { | |
907 RegisterMap map(thread, false); | |
908 frame caller = thread->last_frame().sender(&map); | |
909 #ifdef ASSERT | |
910 assert(caller.is_compiled_frame(), "must be"); | |
911 #endif // ASSERT | |
912 if (caller.is_deoptimized_frame()) { | |
913 handler_address = SharedRuntime::deopt_blob()->unpack_with_exception(); | |
914 } | |
915 } | |
916 return handler_address; | |
917 } | |
918 | |
919 //------------------------------rethrow---------------------------------------- | |
920 // We get here after compiled code has executed a 'RethrowNode'. The callee | |
921 // is either throwing or rethrowing an exception. The callee-save registers | |
922 // have been restored, synchronized objects have been unlocked and the callee | |
923 // stack frame has been removed. The return address was passed in. | |
924 // Exception oop is passed as the 1st argument. This routine is then called | |
925 // from the stub. On exit, we know where to jump in the caller's code. | |
926 // After this C code exits, the stub will pop his frame and end in a jump | |
927 // (instead of a return). We enter the caller's default handler. | |
928 // | |
929 // This must be JRT_LEAF: | |
930 // - caller will not change its state as we cannot block on exit, | |
931 // therefore raw_exception_handler_for_return_address is all it takes | |
932 // to handle deoptimized blobs | |
933 // | |
934 // However, there needs to be a safepoint check in the middle! So compiled | |
935 // safepoints are completely watertight. | |
936 // | |
937 // Thus, it cannot be a leaf since it contains the No_GC_Verifier. | |
938 // | |
939 // *THIS IS NOT RECOMMENDED PROGRAMMING STYLE* | |
940 // | |
941 address OptoRuntime::rethrow_C(oopDesc* exception, JavaThread* thread, address ret_pc) { | |
942 #ifndef PRODUCT | |
943 SharedRuntime::_rethrow_ctr++; // count rethrows | |
944 #endif | |
945 assert (exception != NULL, "should have thrown a NULLPointerException"); | |
946 #ifdef ASSERT | |
1142 | 947 if (!(exception->is_a(SystemDictionary::Throwable_klass()))) { |
0 | 948 // should throw an exception here |
949 ShouldNotReachHere(); | |
950 } | |
951 #endif | |
952 | |
953 thread->set_vm_result(exception); | |
954 // Frame not compiled (handles deoptimization blob) | |
1295 | 955 return SharedRuntime::raw_exception_handler_for_return_address(thread, ret_pc); |
0 | 956 } |
957 | |
958 | |
959 const TypeFunc *OptoRuntime::rethrow_Type() { | |
960 // create input type (domain) | |
961 const Type **fields = TypeTuple::fields(1); | |
962 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // Exception oop | |
963 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+1,fields); | |
964 | |
965 // create result type (range) | |
966 fields = TypeTuple::fields(1); | |
967 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // Exception oop | |
968 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+1, fields); | |
969 | |
970 return TypeFunc::make(domain, range); | |
971 } | |
972 | |
973 | |
974 void OptoRuntime::deoptimize_caller_frame(JavaThread *thread, bool doit) { | |
975 // Deoptimize frame | |
976 if (doit) { | |
977 // Called from within the owner thread, so no need for safepoint | |
978 RegisterMap reg_map(thread); | |
979 frame stub_frame = thread->last_frame(); | |
980 assert(stub_frame.is_runtime_frame() || exception_blob()->contains(stub_frame.pc()), "sanity check"); | |
981 frame caller_frame = stub_frame.sender(®_map); | |
982 | |
1213
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
1166
diff
changeset
|
983 // 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
|
984 Deoptimization::deoptimize_frame(thread, caller_frame.id()); |
0 | 985 } |
986 } | |
987 | |
988 | |
989 const TypeFunc *OptoRuntime::register_finalizer_Type() { | |
990 // create input type (domain) | |
991 const Type **fields = TypeTuple::fields(1); | |
992 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // oop; Receiver | |
993 // // The JavaThread* is passed to each routine as the last argument | |
994 // fields[TypeFunc::Parms+1] = TypeRawPtr::NOTNULL; // JavaThread *; Executing thread | |
995 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+1,fields); | |
996 | |
997 // create result type (range) | |
998 fields = TypeTuple::fields(0); | |
999 | |
1000 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0,fields); | |
1001 | |
1002 return TypeFunc::make(domain,range); | |
1003 } | |
1004 | |
1005 | |
1006 //----------------------------------------------------------------------------- | |
1007 // Dtrace support. entry and exit probes have the same signature | |
1008 const TypeFunc *OptoRuntime::dtrace_method_entry_exit_Type() { | |
1009 // create input type (domain) | |
1010 const Type **fields = TypeTuple::fields(2); | |
1011 fields[TypeFunc::Parms+0] = TypeRawPtr::BOTTOM; // Thread-local storage | |
1012 fields[TypeFunc::Parms+1] = TypeInstPtr::NOTNULL; // methodOop; Method we are entering | |
1013 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2,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 const TypeFunc *OptoRuntime::dtrace_object_alloc_Type() { | |
1024 // create input type (domain) | |
1025 const Type **fields = TypeTuple::fields(2); | |
1026 fields[TypeFunc::Parms+0] = TypeRawPtr::BOTTOM; // Thread-local storage | |
1027 fields[TypeFunc::Parms+1] = TypeInstPtr::NOTNULL; // oop; newly allocated object | |
1028 | |
1029 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2,fields); | |
1030 | |
1031 // create result type (range) | |
1032 fields = TypeTuple::fields(0); | |
1033 | |
1034 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0,fields); | |
1035 | |
1036 return TypeFunc::make(domain,range); | |
1037 } | |
1038 | |
1039 | |
1040 JRT_ENTRY_NO_ASYNC(void, OptoRuntime::register_finalizer(oopDesc* obj, JavaThread* thread)) | |
1041 assert(obj->is_oop(), "must be a valid oop"); | |
1042 assert(obj->klass()->klass_part()->has_finalizer(), "shouldn't be here otherwise"); | |
1043 instanceKlass::register_finalizer(instanceOop(obj), CHECK); | |
1044 JRT_END | |
1045 | |
1046 //----------------------------------------------------------------------------- | |
1047 | |
1048 NamedCounter * volatile OptoRuntime::_named_counters = NULL; | |
1049 | |
1050 // | |
1051 // dump the collected NamedCounters. | |
1052 // | |
1053 void OptoRuntime::print_named_counters() { | |
1054 int total_lock_count = 0; | |
1055 int eliminated_lock_count = 0; | |
1056 | |
1057 NamedCounter* c = _named_counters; | |
1058 while (c) { | |
1059 if (c->tag() == NamedCounter::LockCounter || c->tag() == NamedCounter::EliminatedLockCounter) { | |
1060 int count = c->count(); | |
1061 if (count > 0) { | |
1062 bool eliminated = c->tag() == NamedCounter::EliminatedLockCounter; | |
1063 if (Verbose) { | |
1064 tty->print_cr("%d %s%s", count, c->name(), eliminated ? " (eliminated)" : ""); | |
1065 } | |
1066 total_lock_count += count; | |
1067 if (eliminated) { | |
1068 eliminated_lock_count += count; | |
1069 } | |
1070 } | |
1071 } else if (c->tag() == NamedCounter::BiasedLockingCounter) { | |
1072 BiasedLockingCounters* blc = ((BiasedLockingNamedCounter*)c)->counters(); | |
1073 if (blc->nonzero()) { | |
1074 tty->print_cr("%s", c->name()); | |
1075 blc->print_on(tty); | |
1076 } | |
1077 } | |
1078 c = c->next(); | |
1079 } | |
1080 if (total_lock_count > 0) { | |
1081 tty->print_cr("dynamic locks: %d", total_lock_count); | |
1082 if (eliminated_lock_count) { | |
1083 tty->print_cr("eliminated locks: %d (%d%%)", eliminated_lock_count, | |
1084 (int)(eliminated_lock_count * 100.0 / total_lock_count)); | |
1085 } | |
1086 } | |
1087 } | |
1088 | |
1089 // | |
1090 // Allocate a new NamedCounter. The JVMState is used to generate the | |
1091 // name which consists of method@line for the inlining tree. | |
1092 // | |
1093 | |
1094 NamedCounter* OptoRuntime::new_named_counter(JVMState* youngest_jvms, NamedCounter::CounterTag tag) { | |
1095 int max_depth = youngest_jvms->depth(); | |
1096 | |
1097 // Visit scopes from youngest to oldest. | |
1098 bool first = true; | |
1099 stringStream st; | |
1100 for (int depth = max_depth; depth >= 1; depth--) { | |
1101 JVMState* jvms = youngest_jvms->of_depth(depth); | |
1102 ciMethod* m = jvms->has_method() ? jvms->method() : NULL; | |
1103 if (!first) { | |
1104 st.print(" "); | |
1105 } else { | |
1106 first = false; | |
1107 } | |
1108 int bci = jvms->bci(); | |
1109 if (bci < 0) bci = 0; | |
1110 st.print("%s.%s@%d", m->holder()->name()->as_utf8(), m->name()->as_utf8(), bci); | |
1111 // To print linenumbers instead of bci use: m->line_number_from_bci(bci) | |
1112 } | |
1113 NamedCounter* c; | |
1114 if (tag == NamedCounter::BiasedLockingCounter) { | |
1115 c = new BiasedLockingNamedCounter(strdup(st.as_string())); | |
1116 } else { | |
1117 c = new NamedCounter(strdup(st.as_string()), tag); | |
1118 } | |
1119 | |
1120 // atomically add the new counter to the head of the list. We only | |
1121 // add counters so this is safe. | |
1122 NamedCounter* head; | |
1123 do { | |
1124 head = _named_counters; | |
1125 c->set_next(head); | |
1126 } while (Atomic::cmpxchg_ptr(c, &_named_counters, head) != head); | |
1127 return c; | |
1128 } | |
1129 | |
1130 //----------------------------------------------------------------------------- | |
1131 // Non-product code | |
1132 #ifndef PRODUCT | |
1133 | |
1134 int trace_exception_counter = 0; | |
1135 static void trace_exception(oop exception_oop, address exception_pc, const char* msg) { | |
1136 ttyLocker ttyl; | |
1137 trace_exception_counter++; | |
1138 tty->print("%d [Exception (%s): ", trace_exception_counter, msg); | |
1139 exception_oop->print_value(); | |
1140 tty->print(" in "); | |
1141 CodeBlob* blob = CodeCache::find_blob(exception_pc); | |
1142 if (blob->is_nmethod()) { | |
1143 ((nmethod*)blob)->method()->print_value(); | |
1144 } else if (blob->is_runtime_stub()) { | |
1145 tty->print("<runtime-stub>"); | |
1146 } else { | |
1147 tty->print("<unknown>"); | |
1148 } | |
1149 tty->print(" at " INTPTR_FORMAT, exception_pc); | |
1150 tty->print_cr("]"); | |
1151 } | |
1152 | |
1153 #endif // PRODUCT | |
1154 | |
1155 | |
1156 # ifdef ENABLE_ZAP_DEAD_LOCALS | |
1157 // Called from call sites in compiled code with oop maps (actually safepoints) | |
1158 // Zaps dead locals in first java frame. | |
1159 // Is entry because may need to lock to generate oop maps | |
1160 // Currently, only used for compiler frames, but someday may be used | |
1161 // for interpreter frames, too. | |
1162 | |
1163 int OptoRuntime::ZapDeadCompiledLocals_count = 0; | |
1164 | |
1165 // avoid pointers to member funcs with these helpers | |
1166 static bool is_java_frame( frame* f) { return f->is_java_frame(); } | |
1167 static bool is_native_frame(frame* f) { return f->is_native_frame(); } | |
1168 | |
1169 | |
1170 void OptoRuntime::zap_dead_java_or_native_locals(JavaThread* thread, | |
1171 bool (*is_this_the_right_frame_to_zap)(frame*)) { | |
1172 assert(JavaThread::current() == thread, "is this needed?"); | |
1173 | |
1174 if ( !ZapDeadCompiledLocals ) return; | |
1175 | |
1176 bool skip = false; | |
1177 | |
1178 if ( ZapDeadCompiledLocalsFirst == 0 ) ; // nothing special | |
1179 else if ( ZapDeadCompiledLocalsFirst > ZapDeadCompiledLocals_count ) skip = true; | |
1180 else if ( ZapDeadCompiledLocalsFirst == ZapDeadCompiledLocals_count ) | |
1181 warning("starting zapping after skipping"); | |
1182 | |
1183 if ( ZapDeadCompiledLocalsLast == -1 ) ; // nothing special | |
1184 else if ( ZapDeadCompiledLocalsLast < ZapDeadCompiledLocals_count ) skip = true; | |
1185 else if ( ZapDeadCompiledLocalsLast == ZapDeadCompiledLocals_count ) | |
1186 warning("about to zap last zap"); | |
1187 | |
1188 ++ZapDeadCompiledLocals_count; // counts skipped zaps, too | |
1189 | |
1190 if ( skip ) return; | |
1191 | |
1192 // find java frame and zap it | |
1193 | |
1194 for (StackFrameStream sfs(thread); !sfs.is_done(); sfs.next()) { | |
1195 if (is_this_the_right_frame_to_zap(sfs.current()) ) { | |
1196 sfs.current()->zap_dead_locals(thread, sfs.register_map()); | |
1197 return; | |
1198 } | |
1199 } | |
1200 warning("no frame found to zap in zap_dead_Java_locals_C"); | |
1201 } | |
1202 | |
1203 JRT_LEAF(void, OptoRuntime::zap_dead_Java_locals_C(JavaThread* thread)) | |
1204 zap_dead_java_or_native_locals(thread, is_java_frame); | |
1205 JRT_END | |
1206 | |
1207 // The following does not work because for one thing, the | |
1208 // thread state is wrong; it expects java, but it is native. | |
605 | 1209 // Also, the invariants in a native stub are different and |
0 | 1210 // I'm not sure it is safe to have a MachCalRuntimeDirectNode |
1211 // in there. | |
1212 // So for now, we do not zap in native stubs. | |
1213 | |
1214 JRT_LEAF(void, OptoRuntime::zap_dead_native_locals_C(JavaThread* thread)) | |
1215 zap_dead_java_or_native_locals(thread, is_native_frame); | |
1216 JRT_END | |
1217 | |
1218 # endif |