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