Mercurial > hg > truffle
annotate src/share/vm/opto/runtime.cpp @ 9126:bc26f978b0ce
HotSpotResolvedObjectType: implement hasFinalizeSubclass() correctly
don't use the (wrong) cached value, but ask the runtime on each request.
Fixes regression on xml.* benchmarks @ specjvm2008. The problem was:
After the constructor of Object was deoptimized due to an assumption violation,
it was recompiled again after some time. However, on recompilation, the value
of hasFinalizeSubclass for the class was not updated and it was compiled again
with a, now wrong, assumption, which then triggers deoptimization again.
This was repeated until it hit the recompilation limit (defined by
PerMethodRecompilationCutoff), and therefore only executed by the interpreter
from now on, causing the performance regression.
author | Bernhard Urban <bernhard.urban@jku.at> |
---|---|
date | Mon, 15 Apr 2013 19:54:58 +0200 |
parents | 4fc2763e670e |
children | f2aebc22372a |
rev | line source |
---|---|
0 | 1 /* |
6006
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4063
diff
changeset
|
2 * Copyright (c) 1998, 2012, 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; | |
3961
a92cdbac8b9e
7081933: Use zeroing elimination optimization for large array
kvn
parents:
3899
diff
changeset
|
105 address OptoRuntime::_new_array_nozero_Java = NULL; |
0 | 106 address OptoRuntime::_multianewarray2_Java = NULL; |
107 address OptoRuntime::_multianewarray3_Java = NULL; | |
108 address OptoRuntime::_multianewarray4_Java = NULL; | |
109 address OptoRuntime::_multianewarray5_Java = NULL; | |
3805
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
3442
diff
changeset
|
110 address OptoRuntime::_multianewarrayN_Java = NULL; |
342 | 111 address OptoRuntime::_g1_wb_pre_Java = NULL; |
112 address OptoRuntime::_g1_wb_post_Java = NULL; | |
0 | 113 address OptoRuntime::_vtable_must_compile_Java = NULL; |
114 address OptoRuntime::_complete_monitor_locking_Java = NULL; | |
115 address OptoRuntime::_rethrow_Java = NULL; | |
116 | |
117 address OptoRuntime::_slow_arraycopy_Java = NULL; | |
118 address OptoRuntime::_register_finalizer_Java = NULL; | |
119 | |
120 # ifdef ENABLE_ZAP_DEAD_LOCALS | |
121 address OptoRuntime::_zap_dead_Java_locals_Java = NULL; | |
122 address OptoRuntime::_zap_dead_native_locals_Java = NULL; | |
123 # endif | |
124 | |
3442
f7d55ea6ee56
7045514: SPARC assembly code for JSR 292 ricochet frames
never
parents:
2426
diff
changeset
|
125 ExceptionBlob* OptoRuntime::_exception_blob; |
0 | 126 |
127 // This should be called in an assertion at the start of OptoRuntime routines | |
128 // which are entered from compiled code (all of them) | |
129 #ifndef PRODUCT | |
130 static bool check_compiled_frame(JavaThread* thread) { | |
131 assert(thread->last_frame().is_runtime_frame(), "cannot call runtime directly from compiled code"); | |
132 #ifdef ASSERT | |
133 RegisterMap map(thread, false); | |
134 frame caller = thread->last_frame().sender(&map); | |
135 assert(caller.is_compiled_frame(), "not being called from compiled like code"); | |
136 #endif /* ASSERT */ | |
137 return true; | |
138 } | |
139 #endif | |
140 | |
141 | |
142 #define gen(env, var, type_func_gen, c_func, fancy_jump, pass_tls, save_arg_regs, return_pc) \ | |
143 var = generate_stub(env, type_func_gen, CAST_FROM_FN_PTR(address, c_func), #var, fancy_jump, pass_tls, save_arg_regs, return_pc) | |
144 | |
145 void OptoRuntime::generate(ciEnv* env) { | |
146 | |
147 generate_exception_blob(); | |
148 | |
149 // Note: tls: Means fetching the return oop out of the thread-local storage | |
150 // | |
151 // variable/name type-function-gen , runtime method ,fncy_jp, tls,save_args,retpc | |
152 // ------------------------------------------------------------------------------------------------------------------------------- | |
153 gen(env, _new_instance_Java , new_instance_Type , new_instance_C , 0 , true , false, false); | |
154 gen(env, _new_array_Java , new_array_Type , new_array_C , 0 , true , false, false); | |
3961
a92cdbac8b9e
7081933: Use zeroing elimination optimization for large array
kvn
parents:
3899
diff
changeset
|
155 gen(env, _new_array_nozero_Java , new_array_Type , new_array_nozero_C , 0 , true , false, false); |
0 | 156 gen(env, _multianewarray2_Java , multianewarray2_Type , multianewarray2_C , 0 , true , false, false); |
157 gen(env, _multianewarray3_Java , multianewarray3_Type , multianewarray3_C , 0 , true , false, false); | |
158 gen(env, _multianewarray4_Java , multianewarray4_Type , multianewarray4_C , 0 , true , false, false); | |
159 gen(env, _multianewarray5_Java , multianewarray5_Type , multianewarray5_C , 0 , true , false, false); | |
3805
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
3442
diff
changeset
|
160 gen(env, _multianewarrayN_Java , multianewarrayN_Type , multianewarrayN_C , 0 , true , false, false); |
342 | 161 gen(env, _g1_wb_pre_Java , g1_wb_pre_Type , SharedRuntime::g1_wb_pre , 0 , false, false, false); |
162 gen(env, _g1_wb_post_Java , g1_wb_post_Type , SharedRuntime::g1_wb_post , 0 , false, false, false); | |
0 | 163 gen(env, _complete_monitor_locking_Java , complete_monitor_enter_Type , SharedRuntime::complete_monitor_locking_C , 0 , false, false, false); |
164 gen(env, _rethrow_Java , rethrow_Type , rethrow_C , 2 , true , false, true ); | |
165 | |
166 gen(env, _slow_arraycopy_Java , slow_arraycopy_Type , SharedRuntime::slow_arraycopy_C , 0 , false, false, false); | |
167 gen(env, _register_finalizer_Java , register_finalizer_Type , register_finalizer , 0 , false, false, false); | |
168 | |
169 # ifdef ENABLE_ZAP_DEAD_LOCALS | |
170 gen(env, _zap_dead_Java_locals_Java , zap_dead_locals_Type , zap_dead_Java_locals_C , 0 , false, true , false ); | |
171 gen(env, _zap_dead_native_locals_Java , zap_dead_locals_Type , zap_dead_native_locals_C , 0 , false, true , false ); | |
172 # endif | |
173 | |
174 } | |
175 | |
176 #undef gen | |
177 | |
178 | |
179 // Helper method to do generation of RunTimeStub's | |
180 address OptoRuntime::generate_stub( ciEnv* env, | |
181 TypeFunc_generator gen, address C_function, | |
182 const char *name, int is_fancy_jump, | |
183 bool pass_tls, | |
184 bool save_argument_registers, | |
185 bool return_pc ) { | |
186 ResourceMark rm; | |
187 Compile C( env, gen, C_function, name, is_fancy_jump, pass_tls, save_argument_registers, return_pc ); | |
188 return C.stub_entry_point(); | |
189 } | |
190 | |
191 const char* OptoRuntime::stub_name(address entry) { | |
192 #ifndef PRODUCT | |
193 CodeBlob* cb = CodeCache::find_blob(entry); | |
194 RuntimeStub* rs =(RuntimeStub *)cb; | |
195 assert(rs != NULL && rs->is_runtime_stub(), "not a runtime stub"); | |
196 return rs->name(); | |
197 #else | |
198 // Fast implementation for product mode (maybe it should be inlined too) | |
199 return "runtime stub"; | |
200 #endif | |
201 } | |
202 | |
203 | |
204 //============================================================================= | |
205 // Opto compiler runtime routines | |
206 //============================================================================= | |
207 | |
208 | |
209 //=============================allocation====================================== | |
210 // We failed the fast-path allocation. Now we need to do a scavenge or GC | |
211 // and try allocation again. | |
212 | |
1166 | 213 void OptoRuntime::new_store_pre_barrier(JavaThread* thread) { |
0 | 214 // 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
|
215 // 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
|
216 // 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
|
217 // GC may take any compensating steps. |
39b01ab7035a
6888898: CMS: ReduceInitialCardMarks unsafe in the presence of cms precleaning
ysr
parents:
605
diff
changeset
|
218 // NOTE: Keep this code consistent with GraphKit::store_barrier. |
0 | 219 |
220 oop new_obj = thread->vm_result(); | |
221 if (new_obj == NULL) return; | |
222 | |
223 assert(Universe::heap()->can_elide_tlab_store_barriers(), | |
224 "compiler must check this first"); | |
1027
39b01ab7035a
6888898: CMS: ReduceInitialCardMarks unsafe in the presence of cms precleaning
ysr
parents:
605
diff
changeset
|
225 // GC may decide to give back a safer copy of new_obj. |
1166 | 226 new_obj = Universe::heap()->new_store_pre_barrier(thread, new_obj); |
0 | 227 thread->set_vm_result(new_obj); |
228 } | |
229 | |
230 // object allocation | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6633
diff
changeset
|
231 JRT_BLOCK_ENTRY(void, OptoRuntime::new_instance_C(Klass* klass, JavaThread* thread)) |
0 | 232 JRT_BLOCK; |
233 #ifndef PRODUCT | |
234 SharedRuntime::_new_instance_ctr++; // new instance requires GC | |
235 #endif | |
236 assert(check_compiled_frame(thread), "incorrect caller"); | |
237 | |
238 // These checks are cheap to make and support reflective allocation. | |
6983 | 239 int lh = klass->layout_helper(); |
0 | 240 if (Klass::layout_helper_needs_slow_path(lh) |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6633
diff
changeset
|
241 || !InstanceKlass::cast(klass)->is_initialized()) { |
0 | 242 KlassHandle kh(THREAD, klass); |
243 kh->check_valid_for_instantiation(false, THREAD); | |
244 if (!HAS_PENDING_EXCEPTION) { | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6633
diff
changeset
|
245 InstanceKlass::cast(kh())->initialize(THREAD); |
0 | 246 } |
247 if (!HAS_PENDING_EXCEPTION) { | |
248 klass = kh(); | |
249 } else { | |
250 klass = NULL; | |
251 } | |
252 } | |
253 | |
254 if (klass != NULL) { | |
255 // Scavenge and allocate an instance. | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6633
diff
changeset
|
256 oop result = InstanceKlass::cast(klass)->allocate_instance(THREAD); |
0 | 257 thread->set_vm_result(result); |
258 | |
259 // Pass oops back through thread local storage. Our apparent type to Java | |
260 // is that we return an oop, but we can block on exit from this routine and | |
261 // a GC can trash the oop in C's return register. The generated stub will | |
262 // fetch the oop from TLS after any possible GC. | |
263 } | |
264 | |
265 deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION); | |
266 JRT_BLOCK_END; | |
267 | |
268 if (GraphKit::use_ReduceInitialCardMarks()) { | |
1027
39b01ab7035a
6888898: CMS: ReduceInitialCardMarks unsafe in the presence of cms precleaning
ysr
parents:
605
diff
changeset
|
269 // inform GC that we won't do card marks for initializing writes. |
1166 | 270 new_store_pre_barrier(thread); |
0 | 271 } |
272 JRT_END | |
273 | |
274 | |
275 // array allocation | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6633
diff
changeset
|
276 JRT_BLOCK_ENTRY(void, OptoRuntime::new_array_C(Klass* array_type, int len, JavaThread *thread)) |
0 | 277 JRT_BLOCK; |
278 #ifndef PRODUCT | |
279 SharedRuntime::_new_array_ctr++; // new array requires GC | |
280 #endif | |
281 assert(check_compiled_frame(thread), "incorrect caller"); | |
282 | |
283 // Scavenge and allocate an instance. | |
284 oop result; | |
285 | |
6983 | 286 if (array_type->oop_is_typeArray()) { |
0 | 287 // The oopFactory likes to work with the element type. |
288 // (We could bypass the oopFactory, since it doesn't add much value.) | |
6831
d8ce2825b193
8000213: NPG: Should have renamed arrayKlass and typeArrayKlass
coleenp
parents:
6739
diff
changeset
|
289 BasicType elem_type = TypeArrayKlass::cast(array_type)->element_type(); |
0 | 290 result = oopFactory::new_typeArray(elem_type, len, THREAD); |
291 } else { | |
292 // Although the oopFactory likes to work with the elem_type, | |
293 // the compiler prefers the array_type, since it must already have | |
294 // that latter value in hand for the fast path. | |
6831
d8ce2825b193
8000213: NPG: Should have renamed arrayKlass and typeArrayKlass
coleenp
parents:
6739
diff
changeset
|
295 Klass* elem_type = ObjArrayKlass::cast(array_type)->element_klass(); |
0 | 296 result = oopFactory::new_objArray(elem_type, len, THREAD); |
297 } | |
298 | |
299 // Pass oops back through thread local storage. Our apparent type to Java | |
300 // is that we return an oop, but we can block on exit from this routine and | |
301 // a GC can trash the oop in C's return register. The generated stub will | |
302 // fetch the oop from TLS after any possible GC. | |
303 deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION); | |
304 thread->set_vm_result(result); | |
305 JRT_BLOCK_END; | |
306 | |
307 if (GraphKit::use_ReduceInitialCardMarks()) { | |
1027
39b01ab7035a
6888898: CMS: ReduceInitialCardMarks unsafe in the presence of cms precleaning
ysr
parents:
605
diff
changeset
|
308 // inform GC that we won't do card marks for initializing writes. |
1166 | 309 new_store_pre_barrier(thread); |
0 | 310 } |
311 JRT_END | |
312 | |
3961
a92cdbac8b9e
7081933: Use zeroing elimination optimization for large array
kvn
parents:
3899
diff
changeset
|
313 // array allocation without zeroing |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6633
diff
changeset
|
314 JRT_BLOCK_ENTRY(void, OptoRuntime::new_array_nozero_C(Klass* array_type, int len, JavaThread *thread)) |
3961
a92cdbac8b9e
7081933: Use zeroing elimination optimization for large array
kvn
parents:
3899
diff
changeset
|
315 JRT_BLOCK; |
a92cdbac8b9e
7081933: Use zeroing elimination optimization for large array
kvn
parents:
3899
diff
changeset
|
316 #ifndef PRODUCT |
a92cdbac8b9e
7081933: Use zeroing elimination optimization for large array
kvn
parents:
3899
diff
changeset
|
317 SharedRuntime::_new_array_ctr++; // new array requires GC |
a92cdbac8b9e
7081933: Use zeroing elimination optimization for large array
kvn
parents:
3899
diff
changeset
|
318 #endif |
a92cdbac8b9e
7081933: Use zeroing elimination optimization for large array
kvn
parents:
3899
diff
changeset
|
319 assert(check_compiled_frame(thread), "incorrect caller"); |
a92cdbac8b9e
7081933: Use zeroing elimination optimization for large array
kvn
parents:
3899
diff
changeset
|
320 |
a92cdbac8b9e
7081933: Use zeroing elimination optimization for large array
kvn
parents:
3899
diff
changeset
|
321 // Scavenge and allocate an instance. |
a92cdbac8b9e
7081933: Use zeroing elimination optimization for large array
kvn
parents:
3899
diff
changeset
|
322 oop result; |
a92cdbac8b9e
7081933: Use zeroing elimination optimization for large array
kvn
parents:
3899
diff
changeset
|
323 |
6983 | 324 assert(array_type->oop_is_typeArray(), "should be called only for type array"); |
3961
a92cdbac8b9e
7081933: Use zeroing elimination optimization for large array
kvn
parents:
3899
diff
changeset
|
325 // The oopFactory likes to work with the element type. |
6831
d8ce2825b193
8000213: NPG: Should have renamed arrayKlass and typeArrayKlass
coleenp
parents:
6739
diff
changeset
|
326 BasicType elem_type = TypeArrayKlass::cast(array_type)->element_type(); |
3961
a92cdbac8b9e
7081933: Use zeroing elimination optimization for large array
kvn
parents:
3899
diff
changeset
|
327 result = oopFactory::new_typeArray_nozero(elem_type, len, THREAD); |
a92cdbac8b9e
7081933: Use zeroing elimination optimization for large array
kvn
parents:
3899
diff
changeset
|
328 |
a92cdbac8b9e
7081933: Use zeroing elimination optimization for large array
kvn
parents:
3899
diff
changeset
|
329 // Pass oops back through thread local storage. Our apparent type to Java |
a92cdbac8b9e
7081933: Use zeroing elimination optimization for large array
kvn
parents:
3899
diff
changeset
|
330 // is that we return an oop, but we can block on exit from this routine and |
a92cdbac8b9e
7081933: Use zeroing elimination optimization for large array
kvn
parents:
3899
diff
changeset
|
331 // a GC can trash the oop in C's return register. The generated stub will |
a92cdbac8b9e
7081933: Use zeroing elimination optimization for large array
kvn
parents:
3899
diff
changeset
|
332 // fetch the oop from TLS after any possible GC. |
a92cdbac8b9e
7081933: Use zeroing elimination optimization for large array
kvn
parents:
3899
diff
changeset
|
333 deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION); |
a92cdbac8b9e
7081933: Use zeroing elimination optimization for large array
kvn
parents:
3899
diff
changeset
|
334 thread->set_vm_result(result); |
a92cdbac8b9e
7081933: Use zeroing elimination optimization for large array
kvn
parents:
3899
diff
changeset
|
335 JRT_BLOCK_END; |
a92cdbac8b9e
7081933: Use zeroing elimination optimization for large array
kvn
parents:
3899
diff
changeset
|
336 |
a92cdbac8b9e
7081933: Use zeroing elimination optimization for large array
kvn
parents:
3899
diff
changeset
|
337 if (GraphKit::use_ReduceInitialCardMarks()) { |
a92cdbac8b9e
7081933: Use zeroing elimination optimization for large array
kvn
parents:
3899
diff
changeset
|
338 // inform GC that we won't do card marks for initializing writes. |
a92cdbac8b9e
7081933: Use zeroing elimination optimization for large array
kvn
parents:
3899
diff
changeset
|
339 new_store_pre_barrier(thread); |
a92cdbac8b9e
7081933: Use zeroing elimination optimization for large array
kvn
parents:
3899
diff
changeset
|
340 } |
4063
7e0e43cf86d6
7109887: java/util/Arrays/CopyMethods.java fails with -XX:+DeoptimizeALot
kvn
parents:
4048
diff
changeset
|
341 |
7e0e43cf86d6
7109887: java/util/Arrays/CopyMethods.java fails with -XX:+DeoptimizeALot
kvn
parents:
4048
diff
changeset
|
342 oop result = thread->vm_result(); |
7e0e43cf86d6
7109887: java/util/Arrays/CopyMethods.java fails with -XX:+DeoptimizeALot
kvn
parents:
4048
diff
changeset
|
343 if ((len > 0) && (result != NULL) && |
7e0e43cf86d6
7109887: java/util/Arrays/CopyMethods.java fails with -XX:+DeoptimizeALot
kvn
parents:
4048
diff
changeset
|
344 is_deoptimized_caller_frame(thread)) { |
7e0e43cf86d6
7109887: java/util/Arrays/CopyMethods.java fails with -XX:+DeoptimizeALot
kvn
parents:
4048
diff
changeset
|
345 // Zero array here if the caller is deoptimized. |
7e0e43cf86d6
7109887: java/util/Arrays/CopyMethods.java fails with -XX:+DeoptimizeALot
kvn
parents:
4048
diff
changeset
|
346 int size = ((typeArrayOop)result)->object_size(); |
6831
d8ce2825b193
8000213: NPG: Should have renamed arrayKlass and typeArrayKlass
coleenp
parents:
6739
diff
changeset
|
347 BasicType elem_type = TypeArrayKlass::cast(array_type)->element_type(); |
4063
7e0e43cf86d6
7109887: java/util/Arrays/CopyMethods.java fails with -XX:+DeoptimizeALot
kvn
parents:
4048
diff
changeset
|
348 const size_t hs = arrayOopDesc::header_size(elem_type); |
7e0e43cf86d6
7109887: java/util/Arrays/CopyMethods.java fails with -XX:+DeoptimizeALot
kvn
parents:
4048
diff
changeset
|
349 // Align to next 8 bytes to avoid trashing arrays's length. |
7e0e43cf86d6
7109887: java/util/Arrays/CopyMethods.java fails with -XX:+DeoptimizeALot
kvn
parents:
4048
diff
changeset
|
350 const size_t aligned_hs = align_object_offset(hs); |
7e0e43cf86d6
7109887: java/util/Arrays/CopyMethods.java fails with -XX:+DeoptimizeALot
kvn
parents:
4048
diff
changeset
|
351 HeapWord* obj = (HeapWord*)result; |
7e0e43cf86d6
7109887: java/util/Arrays/CopyMethods.java fails with -XX:+DeoptimizeALot
kvn
parents:
4048
diff
changeset
|
352 if (aligned_hs > hs) { |
7e0e43cf86d6
7109887: java/util/Arrays/CopyMethods.java fails with -XX:+DeoptimizeALot
kvn
parents:
4048
diff
changeset
|
353 Copy::zero_to_words(obj+hs, aligned_hs-hs); |
7e0e43cf86d6
7109887: java/util/Arrays/CopyMethods.java fails with -XX:+DeoptimizeALot
kvn
parents:
4048
diff
changeset
|
354 } |
7e0e43cf86d6
7109887: java/util/Arrays/CopyMethods.java fails with -XX:+DeoptimizeALot
kvn
parents:
4048
diff
changeset
|
355 // Optimized zeroing. |
7e0e43cf86d6
7109887: java/util/Arrays/CopyMethods.java fails with -XX:+DeoptimizeALot
kvn
parents:
4048
diff
changeset
|
356 Copy::fill_to_aligned_words(obj+aligned_hs, size-aligned_hs); |
7e0e43cf86d6
7109887: java/util/Arrays/CopyMethods.java fails with -XX:+DeoptimizeALot
kvn
parents:
4048
diff
changeset
|
357 } |
7e0e43cf86d6
7109887: java/util/Arrays/CopyMethods.java fails with -XX:+DeoptimizeALot
kvn
parents:
4048
diff
changeset
|
358 |
3961
a92cdbac8b9e
7081933: Use zeroing elimination optimization for large array
kvn
parents:
3899
diff
changeset
|
359 JRT_END |
a92cdbac8b9e
7081933: Use zeroing elimination optimization for large array
kvn
parents:
3899
diff
changeset
|
360 |
0 | 361 // Note: multianewarray for one dimension is handled inline by GraphKit::new_array. |
362 | |
363 // multianewarray for 2 dimensions | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6633
diff
changeset
|
364 JRT_ENTRY(void, OptoRuntime::multianewarray2_C(Klass* elem_type, int len1, int len2, JavaThread *thread)) |
0 | 365 #ifndef PRODUCT |
366 SharedRuntime::_multi2_ctr++; // multianewarray for 1 dimension | |
367 #endif | |
368 assert(check_compiled_frame(thread), "incorrect caller"); | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6633
diff
changeset
|
369 assert(elem_type->is_klass(), "not a class"); |
0 | 370 jint dims[2]; |
371 dims[0] = len1; | |
372 dims[1] = len2; | |
6831
d8ce2825b193
8000213: NPG: Should have renamed arrayKlass and typeArrayKlass
coleenp
parents:
6739
diff
changeset
|
373 oop obj = ArrayKlass::cast(elem_type)->multi_allocate(2, dims, THREAD); |
0 | 374 deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION); |
375 thread->set_vm_result(obj); | |
376 JRT_END | |
377 | |
378 // multianewarray for 3 dimensions | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6633
diff
changeset
|
379 JRT_ENTRY(void, OptoRuntime::multianewarray3_C(Klass* elem_type, int len1, int len2, int len3, JavaThread *thread)) |
0 | 380 #ifndef PRODUCT |
381 SharedRuntime::_multi3_ctr++; // multianewarray for 1 dimension | |
382 #endif | |
383 assert(check_compiled_frame(thread), "incorrect caller"); | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6633
diff
changeset
|
384 assert(elem_type->is_klass(), "not a class"); |
0 | 385 jint dims[3]; |
386 dims[0] = len1; | |
387 dims[1] = len2; | |
388 dims[2] = len3; | |
6831
d8ce2825b193
8000213: NPG: Should have renamed arrayKlass and typeArrayKlass
coleenp
parents:
6739
diff
changeset
|
389 oop obj = ArrayKlass::cast(elem_type)->multi_allocate(3, dims, THREAD); |
0 | 390 deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION); |
391 thread->set_vm_result(obj); | |
392 JRT_END | |
393 | |
394 // multianewarray for 4 dimensions | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6633
diff
changeset
|
395 JRT_ENTRY(void, OptoRuntime::multianewarray4_C(Klass* elem_type, int len1, int len2, int len3, int len4, JavaThread *thread)) |
0 | 396 #ifndef PRODUCT |
397 SharedRuntime::_multi4_ctr++; // multianewarray for 1 dimension | |
398 #endif | |
399 assert(check_compiled_frame(thread), "incorrect caller"); | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6633
diff
changeset
|
400 assert(elem_type->is_klass(), "not a class"); |
0 | 401 jint dims[4]; |
402 dims[0] = len1; | |
403 dims[1] = len2; | |
404 dims[2] = len3; | |
405 dims[3] = len4; | |
6831
d8ce2825b193
8000213: NPG: Should have renamed arrayKlass and typeArrayKlass
coleenp
parents:
6739
diff
changeset
|
406 oop obj = ArrayKlass::cast(elem_type)->multi_allocate(4, dims, THREAD); |
0 | 407 deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION); |
408 thread->set_vm_result(obj); | |
409 JRT_END | |
410 | |
411 // multianewarray for 5 dimensions | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6633
diff
changeset
|
412 JRT_ENTRY(void, OptoRuntime::multianewarray5_C(Klass* elem_type, int len1, int len2, int len3, int len4, int len5, JavaThread *thread)) |
0 | 413 #ifndef PRODUCT |
414 SharedRuntime::_multi5_ctr++; // multianewarray for 1 dimension | |
415 #endif | |
416 assert(check_compiled_frame(thread), "incorrect caller"); | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6633
diff
changeset
|
417 assert(elem_type->is_klass(), "not a class"); |
0 | 418 jint dims[5]; |
419 dims[0] = len1; | |
420 dims[1] = len2; | |
421 dims[2] = len3; | |
422 dims[3] = len4; | |
423 dims[4] = len5; | |
6831
d8ce2825b193
8000213: NPG: Should have renamed arrayKlass and typeArrayKlass
coleenp
parents:
6739
diff
changeset
|
424 oop obj = ArrayKlass::cast(elem_type)->multi_allocate(5, dims, THREAD); |
0 | 425 deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION); |
426 thread->set_vm_result(obj); | |
427 JRT_END | |
428 | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6633
diff
changeset
|
429 JRT_ENTRY(void, OptoRuntime::multianewarrayN_C(Klass* elem_type, arrayOopDesc* dims, JavaThread *thread)) |
3805
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
3442
diff
changeset
|
430 assert(check_compiled_frame(thread), "incorrect caller"); |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6633
diff
changeset
|
431 assert(elem_type->is_klass(), "not a class"); |
3805
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
3442
diff
changeset
|
432 assert(oop(dims)->is_typeArray(), "not an array"); |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
3442
diff
changeset
|
433 |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
3442
diff
changeset
|
434 ResourceMark rm; |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
3442
diff
changeset
|
435 jint len = dims->length(); |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
3442
diff
changeset
|
436 assert(len > 0, "Dimensions array should contain data"); |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
3442
diff
changeset
|
437 jint *j_dims = typeArrayOop(dims)->int_at_addr(0); |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
3442
diff
changeset
|
438 jint *c_dims = NEW_RESOURCE_ARRAY(jint, len); |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
3442
diff
changeset
|
439 Copy::conjoint_jints_atomic(j_dims, c_dims, len); |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
3442
diff
changeset
|
440 |
6831
d8ce2825b193
8000213: NPG: Should have renamed arrayKlass and typeArrayKlass
coleenp
parents:
6739
diff
changeset
|
441 oop obj = ArrayKlass::cast(elem_type)->multi_allocate(len, c_dims, THREAD); |
3805
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
3442
diff
changeset
|
442 deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION); |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
3442
diff
changeset
|
443 thread->set_vm_result(obj); |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
3442
diff
changeset
|
444 JRT_END |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
3442
diff
changeset
|
445 |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
3442
diff
changeset
|
446 |
0 | 447 const TypeFunc *OptoRuntime::new_instance_Type() { |
448 // create input type (domain) | |
449 const Type **fields = TypeTuple::fields(1); | |
450 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // Klass to be allocated | |
451 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+1, fields); | |
452 | |
453 // create result type (range) | |
454 fields = TypeTuple::fields(1); | |
455 fields[TypeFunc::Parms+0] = TypeRawPtr::NOTNULL; // Returned oop | |
456 | |
457 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+1, fields); | |
458 | |
459 return TypeFunc::make(domain, range); | |
460 } | |
461 | |
462 | |
463 const TypeFunc *OptoRuntime::athrow_Type() { | |
464 // create input type (domain) | |
465 const Type **fields = TypeTuple::fields(1); | |
466 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // Klass to be allocated | |
467 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+1, fields); | |
468 | |
469 // create result type (range) | |
470 fields = TypeTuple::fields(0); | |
471 | |
472 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0, fields); | |
473 | |
474 return TypeFunc::make(domain, range); | |
475 } | |
476 | |
477 | |
478 const TypeFunc *OptoRuntime::new_array_Type() { | |
479 // create input type (domain) | |
480 const Type **fields = TypeTuple::fields(2); | |
481 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // element klass | |
482 fields[TypeFunc::Parms+1] = TypeInt::INT; // array size | |
483 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2, fields); | |
484 | |
485 // create result type (range) | |
486 fields = TypeTuple::fields(1); | |
487 fields[TypeFunc::Parms+0] = TypeRawPtr::NOTNULL; // Returned oop | |
488 | |
489 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+1, fields); | |
490 | |
491 return TypeFunc::make(domain, range); | |
492 } | |
493 | |
494 const TypeFunc *OptoRuntime::multianewarray_Type(int ndim) { | |
495 // create input type (domain) | |
496 const int nargs = ndim + 1; | |
497 const Type **fields = TypeTuple::fields(nargs); | |
498 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // element klass | |
499 for( int i = 1; i < nargs; i++ ) | |
500 fields[TypeFunc::Parms + i] = TypeInt::INT; // array size | |
501 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+nargs, fields); | |
502 | |
503 // create result type (range) | |
504 fields = TypeTuple::fields(1); | |
505 fields[TypeFunc::Parms+0] = TypeRawPtr::NOTNULL; // Returned oop | |
506 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+1, fields); | |
507 | |
508 return TypeFunc::make(domain, range); | |
509 } | |
510 | |
511 const TypeFunc *OptoRuntime::multianewarray2_Type() { | |
512 return multianewarray_Type(2); | |
513 } | |
514 | |
515 const TypeFunc *OptoRuntime::multianewarray3_Type() { | |
516 return multianewarray_Type(3); | |
517 } | |
518 | |
519 const TypeFunc *OptoRuntime::multianewarray4_Type() { | |
520 return multianewarray_Type(4); | |
521 } | |
522 | |
523 const TypeFunc *OptoRuntime::multianewarray5_Type() { | |
524 return multianewarray_Type(5); | |
525 } | |
526 | |
3805
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
3442
diff
changeset
|
527 const TypeFunc *OptoRuntime::multianewarrayN_Type() { |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
3442
diff
changeset
|
528 // create input type (domain) |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
3442
diff
changeset
|
529 const Type **fields = TypeTuple::fields(2); |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
3442
diff
changeset
|
530 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // element klass |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
3442
diff
changeset
|
531 fields[TypeFunc::Parms+1] = TypeInstPtr::NOTNULL; // array of dim sizes |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
3442
diff
changeset
|
532 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2, fields); |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
3442
diff
changeset
|
533 |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
3442
diff
changeset
|
534 // create result type (range) |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
3442
diff
changeset
|
535 fields = TypeTuple::fields(1); |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
3442
diff
changeset
|
536 fields[TypeFunc::Parms+0] = TypeRawPtr::NOTNULL; // Returned oop |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
3442
diff
changeset
|
537 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+1, fields); |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
3442
diff
changeset
|
538 |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
3442
diff
changeset
|
539 return TypeFunc::make(domain, range); |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
3442
diff
changeset
|
540 } |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
3442
diff
changeset
|
541 |
342 | 542 const TypeFunc *OptoRuntime::g1_wb_pre_Type() { |
543 const Type **fields = TypeTuple::fields(2); | |
544 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // original field value | |
545 fields[TypeFunc::Parms+1] = TypeRawPtr::NOTNULL; // thread | |
546 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2, fields); | |
547 | |
548 // create result type (range) | |
549 fields = TypeTuple::fields(0); | |
550 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0, fields); | |
551 | |
552 return TypeFunc::make(domain, range); | |
553 } | |
554 | |
555 const TypeFunc *OptoRuntime::g1_wb_post_Type() { | |
556 | |
557 const Type **fields = TypeTuple::fields(2); | |
558 fields[TypeFunc::Parms+0] = TypeRawPtr::NOTNULL; // Card addr | |
559 fields[TypeFunc::Parms+1] = TypeRawPtr::NOTNULL; // thread | |
560 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2, fields); | |
561 | |
562 // create result type (range) | |
563 fields = TypeTuple::fields(0); | |
564 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms, fields); | |
565 | |
566 return TypeFunc::make(domain, range); | |
567 } | |
568 | |
0 | 569 const TypeFunc *OptoRuntime::uncommon_trap_Type() { |
570 // create input type (domain) | |
571 const Type **fields = TypeTuple::fields(1); | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1972
diff
changeset
|
572 // Symbol* name of class to be loaded |
0 | 573 fields[TypeFunc::Parms+0] = TypeInt::INT; |
574 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+1, fields); | |
575 | |
576 // create result type (range) | |
577 fields = TypeTuple::fields(0); | |
578 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0, fields); | |
579 | |
580 return TypeFunc::make(domain, range); | |
581 } | |
582 | |
583 # ifdef ENABLE_ZAP_DEAD_LOCALS | |
584 // Type used for stub generation for zap_dead_locals. | |
585 // No inputs or outputs | |
586 const TypeFunc *OptoRuntime::zap_dead_locals_Type() { | |
587 // create input type (domain) | |
588 const Type **fields = TypeTuple::fields(0); | |
589 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms,fields); | |
590 | |
591 // create result type (range) | |
592 fields = TypeTuple::fields(0); | |
593 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms,fields); | |
594 | |
595 return TypeFunc::make(domain,range); | |
596 } | |
597 # endif | |
598 | |
599 | |
600 //----------------------------------------------------------------------------- | |
601 // Monitor Handling | |
602 const TypeFunc *OptoRuntime::complete_monitor_enter_Type() { | |
603 // create input type (domain) | |
604 const Type **fields = TypeTuple::fields(2); | |
605 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // Object to be Locked | |
606 fields[TypeFunc::Parms+1] = TypeRawPtr::BOTTOM; // Address of stack location for lock | |
607 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2,fields); | |
608 | |
609 // create result type (range) | |
610 fields = TypeTuple::fields(0); | |
611 | |
612 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0,fields); | |
613 | |
614 return TypeFunc::make(domain,range); | |
615 } | |
616 | |
617 | |
618 //----------------------------------------------------------------------------- | |
619 const TypeFunc *OptoRuntime::complete_monitor_exit_Type() { | |
620 // create input type (domain) | |
621 const Type **fields = TypeTuple::fields(2); | |
622 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // Object to be Locked | |
623 fields[TypeFunc::Parms+1] = TypeRawPtr::BOTTOM; // Address of stack location for lock | |
624 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2,fields); | |
625 | |
626 // create result type (range) | |
627 fields = TypeTuple::fields(0); | |
628 | |
629 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0,fields); | |
630 | |
631 return TypeFunc::make(domain,range); | |
632 } | |
633 | |
634 const TypeFunc* OptoRuntime::flush_windows_Type() { | |
635 // create input type (domain) | |
636 const Type** fields = TypeTuple::fields(1); | |
637 fields[TypeFunc::Parms+0] = NULL; // void | |
638 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms, fields); | |
639 | |
640 // create result type | |
641 fields = TypeTuple::fields(1); | |
642 fields[TypeFunc::Parms+0] = NULL; // void | |
643 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms, fields); | |
644 | |
645 return TypeFunc::make(domain, range); | |
646 } | |
647 | |
648 const TypeFunc* OptoRuntime::l2f_Type() { | |
649 // create input type (domain) | |
650 const Type **fields = TypeTuple::fields(2); | |
651 fields[TypeFunc::Parms+0] = TypeLong::LONG; | |
652 fields[TypeFunc::Parms+1] = Type::HALF; | |
653 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2, fields); | |
654 | |
655 // create result type (range) | |
656 fields = TypeTuple::fields(1); | |
657 fields[TypeFunc::Parms+0] = Type::FLOAT; | |
658 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+1, fields); | |
659 | |
660 return TypeFunc::make(domain, range); | |
661 } | |
662 | |
663 const TypeFunc* OptoRuntime::modf_Type() { | |
664 const Type **fields = TypeTuple::fields(2); | |
665 fields[TypeFunc::Parms+0] = Type::FLOAT; | |
666 fields[TypeFunc::Parms+1] = Type::FLOAT; | |
667 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2, fields); | |
668 | |
669 // create result type (range) | |
670 fields = TypeTuple::fields(1); | |
671 fields[TypeFunc::Parms+0] = Type::FLOAT; | |
672 | |
673 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+1, fields); | |
674 | |
675 return TypeFunc::make(domain, range); | |
676 } | |
677 | |
678 const TypeFunc *OptoRuntime::Math_D_D_Type() { | |
679 // create input type (domain) | |
680 const Type **fields = TypeTuple::fields(2); | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1972
diff
changeset
|
681 // Symbol* name of class to be loaded |
0 | 682 fields[TypeFunc::Parms+0] = Type::DOUBLE; |
683 fields[TypeFunc::Parms+1] = Type::HALF; | |
684 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2, fields); | |
685 | |
686 // create result type (range) | |
687 fields = TypeTuple::fields(2); | |
688 fields[TypeFunc::Parms+0] = Type::DOUBLE; | |
689 fields[TypeFunc::Parms+1] = Type::HALF; | |
690 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+2, fields); | |
691 | |
692 return TypeFunc::make(domain, range); | |
693 } | |
694 | |
695 const TypeFunc* OptoRuntime::Math_DD_D_Type() { | |
696 const Type **fields = TypeTuple::fields(4); | |
697 fields[TypeFunc::Parms+0] = Type::DOUBLE; | |
698 fields[TypeFunc::Parms+1] = Type::HALF; | |
699 fields[TypeFunc::Parms+2] = Type::DOUBLE; | |
700 fields[TypeFunc::Parms+3] = Type::HALF; | |
701 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+4, fields); | |
702 | |
703 // create result type (range) | |
704 fields = TypeTuple::fields(2); | |
705 fields[TypeFunc::Parms+0] = Type::DOUBLE; | |
706 fields[TypeFunc::Parms+1] = Type::HALF; | |
707 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+2, fields); | |
708 | |
709 return TypeFunc::make(domain, range); | |
710 } | |
711 | |
6006
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4063
diff
changeset
|
712 //-------------- currentTimeMillis, currentTimeNanos, etc |
0 | 713 |
6006
0105f367a14c
7160570: Intrinsification support for tracing framework
rbackman
parents:
4063
diff
changeset
|
714 const TypeFunc* OptoRuntime::void_long_Type() { |
0 | 715 // create input type (domain) |
716 const Type **fields = TypeTuple::fields(0); | |
717 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+0, fields); | |
718 | |
719 // create result type (range) | |
720 fields = TypeTuple::fields(2); | |
721 fields[TypeFunc::Parms+0] = TypeLong::LONG; | |
722 fields[TypeFunc::Parms+1] = Type::HALF; | |
723 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+2, fields); | |
724 | |
725 return TypeFunc::make(domain, range); | |
726 } | |
727 | |
728 // arraycopy stub variations: | |
729 enum ArrayCopyType { | |
730 ac_fast, // void(ptr, ptr, size_t) | |
731 ac_checkcast, // int(ptr, ptr, size_t, size_t, ptr) | |
732 ac_slow, // void(ptr, int, ptr, int, int) | |
733 ac_generic // int(ptr, int, ptr, int, int) | |
734 }; | |
735 | |
736 static const TypeFunc* make_arraycopy_Type(ArrayCopyType act) { | |
737 // create input type (domain) | |
738 int num_args = (act == ac_fast ? 3 : 5); | |
739 int num_size_args = (act == ac_fast ? 1 : act == ac_checkcast ? 2 : 0); | |
740 int argcnt = num_args; | |
741 LP64_ONLY(argcnt += num_size_args); // halfwords for lengths | |
742 const Type** fields = TypeTuple::fields(argcnt); | |
743 int argp = TypeFunc::Parms; | |
744 fields[argp++] = TypePtr::NOTNULL; // src | |
745 if (num_size_args == 0) { | |
746 fields[argp++] = TypeInt::INT; // src_pos | |
747 } | |
748 fields[argp++] = TypePtr::NOTNULL; // dest | |
749 if (num_size_args == 0) { | |
750 fields[argp++] = TypeInt::INT; // dest_pos | |
751 fields[argp++] = TypeInt::INT; // length | |
752 } | |
753 while (num_size_args-- > 0) { | |
754 fields[argp++] = TypeX_X; // size in whatevers (size_t) | |
755 LP64_ONLY(fields[argp++] = Type::HALF); // other half of long length | |
756 } | |
757 if (act == ac_checkcast) { | |
758 fields[argp++] = TypePtr::NOTNULL; // super_klass | |
759 } | |
760 assert(argp == TypeFunc::Parms+argcnt, "correct decoding of act"); | |
761 const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+argcnt, fields); | |
762 | |
763 // create result type if needed | |
764 int retcnt = (act == ac_checkcast || act == ac_generic ? 1 : 0); | |
765 fields = TypeTuple::fields(1); | |
766 if (retcnt == 0) | |
767 fields[TypeFunc::Parms+0] = NULL; // void | |
768 else | |
769 fields[TypeFunc::Parms+0] = TypeInt::INT; // status result, if needed | |
770 const TypeTuple* range = TypeTuple::make(TypeFunc::Parms+retcnt, fields); | |
771 return TypeFunc::make(domain, range); | |
772 } | |
773 | |
774 const TypeFunc* OptoRuntime::fast_arraycopy_Type() { | |
775 // This signature is simple: Two base pointers and a size_t. | |
776 return make_arraycopy_Type(ac_fast); | |
777 } | |
778 | |
779 const TypeFunc* OptoRuntime::checkcast_arraycopy_Type() { | |
780 // An extension of fast_arraycopy_Type which adds type checking. | |
781 return make_arraycopy_Type(ac_checkcast); | |
782 } | |
783 | |
784 const TypeFunc* OptoRuntime::slow_arraycopy_Type() { | |
785 // This signature is exactly the same as System.arraycopy. | |
786 // There are no intptr_t (int/long) arguments. | |
787 return make_arraycopy_Type(ac_slow); | |
788 } | |
789 | |
790 const TypeFunc* OptoRuntime::generic_arraycopy_Type() { | |
791 // This signature is like System.arraycopy, except that it returns status. | |
792 return make_arraycopy_Type(ac_generic); | |
793 } | |
794 | |
795 | |
1763 | 796 const TypeFunc* OptoRuntime::array_fill_Type() { |
1844
75588558f1bf
6980792: Crash "exception happened outside interpreter, nmethods and vtable stubs (1)"
never
parents:
1763
diff
changeset
|
797 // 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
|
798 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
|
799 int argp = TypeFunc::Parms; |
75588558f1bf
6980792: Crash "exception happened outside interpreter, nmethods and vtable stubs (1)"
never
parents:
1763
diff
changeset
|
800 fields[argp++] = TypePtr::NOTNULL; |
75588558f1bf
6980792: Crash "exception happened outside interpreter, nmethods and vtable stubs (1)"
never
parents:
1763
diff
changeset
|
801 fields[argp++] = TypeInt::INT; |
75588558f1bf
6980792: Crash "exception happened outside interpreter, nmethods and vtable stubs (1)"
never
parents:
1763
diff
changeset
|
802 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
|
803 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
|
804 const TypeTuple *domain = TypeTuple::make(argp, fields); |
1763 | 805 |
806 // create result type | |
807 fields = TypeTuple::fields(1); | |
808 fields[TypeFunc::Parms+0] = NULL; // void | |
809 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms, fields); | |
810 | |
811 return TypeFunc::make(domain, range); | |
812 } | |
813 | |
6894 | 814 // for aescrypt encrypt/decrypt operations, just three pointers returning void (length is constant) |
815 const TypeFunc* OptoRuntime::aescrypt_block_Type() { | |
816 // create input type (domain) | |
817 int num_args = 3; | |
818 int argcnt = num_args; | |
819 const Type** fields = TypeTuple::fields(argcnt); | |
820 int argp = TypeFunc::Parms; | |
821 fields[argp++] = TypePtr::NOTNULL; // src | |
822 fields[argp++] = TypePtr::NOTNULL; // dest | |
823 fields[argp++] = TypePtr::NOTNULL; // k array | |
824 assert(argp == TypeFunc::Parms+argcnt, "correct decoding"); | |
825 const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+argcnt, fields); | |
826 | |
827 // no result type needed | |
828 fields = TypeTuple::fields(1); | |
829 fields[TypeFunc::Parms+0] = NULL; // void | |
830 const TypeTuple* range = TypeTuple::make(TypeFunc::Parms, fields); | |
831 return TypeFunc::make(domain, range); | |
832 } | |
833 | |
834 // for cipherBlockChaining calls of aescrypt encrypt/decrypt, four pointers and a length, returning void | |
835 const TypeFunc* OptoRuntime::cipherBlockChaining_aescrypt_Type() { | |
836 // create input type (domain) | |
837 int num_args = 5; | |
838 int argcnt = num_args; | |
839 const Type** fields = TypeTuple::fields(argcnt); | |
840 int argp = TypeFunc::Parms; | |
841 fields[argp++] = TypePtr::NOTNULL; // src | |
842 fields[argp++] = TypePtr::NOTNULL; // dest | |
843 fields[argp++] = TypePtr::NOTNULL; // k array | |
844 fields[argp++] = TypePtr::NOTNULL; // r array | |
845 fields[argp++] = TypeInt::INT; // src len | |
846 assert(argp == TypeFunc::Parms+argcnt, "correct decoding"); | |
847 const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+argcnt, fields); | |
848 | |
849 // no result type needed | |
850 fields = TypeTuple::fields(1); | |
851 fields[TypeFunc::Parms+0] = NULL; // void | |
852 const TypeTuple* range = TypeTuple::make(TypeFunc::Parms, fields); | |
853 return TypeFunc::make(domain, range); | |
854 } | |
855 | |
0 | 856 //------------- Interpreter state access for on stack replacement |
857 const TypeFunc* OptoRuntime::osr_end_Type() { | |
858 // create input type (domain) | |
859 const Type **fields = TypeTuple::fields(1); | |
860 fields[TypeFunc::Parms+0] = TypeRawPtr::BOTTOM; // OSR temp buf | |
861 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+1, fields); | |
862 | |
863 // create result type | |
864 fields = TypeTuple::fields(1); | |
865 // fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // locked oop | |
866 fields[TypeFunc::Parms+0] = NULL; // void | |
867 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms, fields); | |
868 return TypeFunc::make(domain, range); | |
869 } | |
870 | |
871 //-------------- methodData update helpers | |
872 | |
873 const TypeFunc* OptoRuntime::profile_receiver_type_Type() { | |
874 // create input type (domain) | |
875 const Type **fields = TypeTuple::fields(2); | |
876 fields[TypeFunc::Parms+0] = TypeAryPtr::NOTNULL; // methodData pointer | |
877 fields[TypeFunc::Parms+1] = TypeInstPtr::BOTTOM; // receiver oop | |
878 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2, fields); | |
879 | |
880 // create result type | |
881 fields = TypeTuple::fields(1); | |
882 fields[TypeFunc::Parms+0] = NULL; // void | |
883 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms, fields); | |
884 return TypeFunc::make(domain,range); | |
885 } | |
886 | |
887 JRT_LEAF(void, OptoRuntime::profile_receiver_type_C(DataLayout* data, oopDesc* receiver)) | |
888 if (receiver == NULL) return; | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6633
diff
changeset
|
889 Klass* receiver_klass = receiver->klass(); |
0 | 890 |
891 intptr_t* mdp = ((intptr_t*)(data)) + DataLayout::header_size_in_cells(); | |
892 int empty_row = -1; // free row, if any is encountered | |
893 | |
894 // ReceiverTypeData* vc = new ReceiverTypeData(mdp); | |
895 for (uint row = 0; row < ReceiverTypeData::row_limit(); row++) { | |
896 // if (vc->receiver(row) == receiver_klass) | |
897 int receiver_off = ReceiverTypeData::receiver_cell_index(row); | |
898 intptr_t row_recv = *(mdp + receiver_off); | |
899 if (row_recv == (intptr_t) receiver_klass) { | |
900 // vc->set_receiver_count(row, vc->receiver_count(row) + DataLayout::counter_increment); | |
901 int count_off = ReceiverTypeData::receiver_count_cell_index(row); | |
902 *(mdp + count_off) += DataLayout::counter_increment; | |
903 return; | |
904 } else if (row_recv == 0) { | |
905 // else if (vc->receiver(row) == NULL) | |
906 empty_row = (int) row; | |
907 } | |
908 } | |
909 | |
910 if (empty_row != -1) { | |
911 int receiver_off = ReceiverTypeData::receiver_cell_index(empty_row); | |
912 // vc->set_receiver(empty_row, receiver_klass); | |
913 *(mdp + receiver_off) = (intptr_t) receiver_klass; | |
914 // vc->set_receiver_count(empty_row, DataLayout::counter_increment); | |
915 int count_off = ReceiverTypeData::receiver_count_cell_index(empty_row); | |
916 *(mdp + count_off) = DataLayout::counter_increment; | |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1166
diff
changeset
|
917 } else { |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1166
diff
changeset
|
918 // 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
|
919 // Increment total counter to indicate polymorphic case. |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1166
diff
changeset
|
920 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
|
921 *count_p += DataLayout::counter_increment; |
0 | 922 } |
923 JRT_END | |
924 | |
925 //------------------------------------------------------------------------------------- | |
926 // register policy | |
927 | |
928 bool OptoRuntime::is_callee_saved_register(MachRegisterNumbers reg) { | |
929 assert(reg >= 0 && reg < _last_Mach_Reg, "must be a machine register"); | |
930 switch (register_save_policy[reg]) { | |
931 case 'C': return false; //SOC | |
932 case 'E': return true ; //SOE | |
933 case 'N': return false; //NS | |
934 case 'A': return false; //AS | |
935 } | |
936 ShouldNotReachHere(); | |
937 return false; | |
938 } | |
939 | |
940 //----------------------------------------------------------------------- | |
941 // Exceptions | |
942 // | |
943 | |
944 static void trace_exception(oop exception_oop, address exception_pc, const char* msg) PRODUCT_RETURN; | |
945 | |
946 // The method is an entry that is always called by a C++ method not | |
947 // directly from compiled code. Compiled code will call the C++ method following. | |
948 // We can't allow async exception to be installed during exception processing. | |
949 JRT_ENTRY_NO_ASYNC(address, OptoRuntime::handle_exception_C_helper(JavaThread* thread, nmethod* &nm)) | |
950 | |
951 // Do not confuse exception_oop with pending_exception. The exception_oop | |
952 // is only used to pass arguments into the method. Not for general | |
953 // exception handling. DO NOT CHANGE IT to use pending_exception, since | |
954 // the runtime stubs checks this on exit. | |
955 assert(thread->exception_oop() != NULL, "exception oop is found"); | |
956 address handler_address = NULL; | |
957 | |
958 Handle exception(thread, thread->exception_oop()); | |
959 | |
960 if (TraceExceptions) { | |
961 trace_exception(exception(), thread->exception_pc(), ""); | |
962 } | |
963 // for AbortVMOnException flag | |
964 NOT_PRODUCT(Exceptions::debug_check_abort(exception)); | |
965 | |
966 #ifdef ASSERT | |
1142 | 967 if (!(exception->is_a(SystemDictionary::Throwable_klass()))) { |
0 | 968 // should throw an exception here |
969 ShouldNotReachHere(); | |
970 } | |
971 #endif | |
972 | |
973 | |
974 // new exception handling: this method is entered only from adapters | |
975 // exceptions from compiled java methods are handled in compiled code | |
976 // using rethrow node | |
977 | |
978 address pc = thread->exception_pc(); | |
979 nm = CodeCache::find_nmethod(pc); | |
980 assert(nm != NULL, "No NMethod found"); | |
981 if (nm->is_native_method()) { | |
982 fatal("Native mathod should not have path to exception handling"); | |
983 } else { | |
984 // we are switching to old paradigm: search for exception handler in caller_frame | |
985 // instead in exception handler of caller_frame.sender() | |
986 | |
1213
6deeaebad47a
6902182: 4/4 Starting with jdwp agent should not incur performance penalty
dcubed
parents:
1166
diff
changeset
|
987 if (JvmtiExport::can_post_on_exceptions()) { |
0 | 988 // "Full-speed catching" is not necessary here, |
989 // since we're notifying the VM on every catch. | |
990 // Force deoptimization and the rest of the lookup | |
991 // will be fine. | |
7428
2d6c433b1f38
8004741: Missing compiled exception handle table entry for multidimensional array allocation
kvn
parents:
6983
diff
changeset
|
992 deoptimize_caller_frame(thread); |
0 | 993 } |
994 | |
995 // Check the stack guard pages. If enabled, look for handler in this frame; | |
996 // otherwise, forcibly unwind the frame. | |
997 // | |
998 // 4826555: use default current sp for reguard_stack instead of &nm: it's more accurate. | |
999 bool force_unwind = !thread->reguard_stack(); | |
1000 bool deopting = false; | |
1001 if (nm->is_deopt_pc(pc)) { | |
1002 deopting = true; | |
1003 RegisterMap map(thread, false); | |
1004 frame deoptee = thread->last_frame().sender(&map); | |
1005 assert(deoptee.is_deoptimized_frame(), "must be deopted"); | |
1006 // Adjust the pc back to the original throwing pc | |
1007 pc = deoptee.pc(); | |
1008 } | |
1009 | |
1010 // If we are forcing an unwind because of stack overflow then deopt is | |
1011 // irrelevant sice we are throwing the frame away anyway. | |
1012 | |
1013 if (deopting && !force_unwind) { | |
1014 handler_address = SharedRuntime::deopt_blob()->unpack_with_exception(); | |
1015 } else { | |
1016 | |
1017 handler_address = | |
1018 force_unwind ? NULL : nm->handler_for_exception_and_pc(exception, pc); | |
1019 | |
1020 if (handler_address == NULL) { | |
3998
ec5ce9326985
6865265: JVM crashes with "missing exception handler" error
kvn
parents:
3961
diff
changeset
|
1021 Handle original_exception(thread, exception()); |
0 | 1022 handler_address = SharedRuntime::compute_compiled_exc_handler(nm, pc, exception, force_unwind, true); |
1023 assert (handler_address != NULL, "must have compiled handler"); | |
3998
ec5ce9326985
6865265: JVM crashes with "missing exception handler" error
kvn
parents:
3961
diff
changeset
|
1024 // Update the exception cache only when the unwind was not forced |
ec5ce9326985
6865265: JVM crashes with "missing exception handler" error
kvn
parents:
3961
diff
changeset
|
1025 // and there didn't happen another exception during the computation of the |
ec5ce9326985
6865265: JVM crashes with "missing exception handler" error
kvn
parents:
3961
diff
changeset
|
1026 // compiled exception handler. |
ec5ce9326985
6865265: JVM crashes with "missing exception handler" error
kvn
parents:
3961
diff
changeset
|
1027 if (!force_unwind && original_exception() == exception()) { |
0 | 1028 nm->add_handler_for_exception_and_pc(exception,pc,handler_address); |
1029 } | |
1030 } else { | |
1031 assert(handler_address == SharedRuntime::compute_compiled_exc_handler(nm, pc, exception, force_unwind, true), "Must be the same"); | |
1032 } | |
1033 } | |
1034 | |
1035 thread->set_exception_pc(pc); | |
1036 thread->set_exception_handler_pc(handler_address); | |
1135
e66fd840cb6b
6893081: method handle & invokedynamic code needs additional cleanup (post 6815692, 6858164)
twisti
parents:
1027
diff
changeset
|
1037 |
1295 | 1038 // 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
|
1039 thread->set_is_method_handle_return(nm->is_method_handle_return(pc)); |
0 | 1040 } |
1041 | |
1042 // Restore correct return pc. Was saved above. | |
1043 thread->set_exception_oop(exception()); | |
1044 return handler_address; | |
1045 | |
1046 JRT_END | |
1047 | |
1048 // We are entering here from exception_blob | |
1049 // If there is a compiled exception handler in this method, we will continue there; | |
1050 // otherwise we will unwind the stack and continue at the caller of top frame method | |
1051 // Note we enter without the usual JRT wrapper. We will call a helper routine that | |
1052 // will do the normal VM entry. We do it this way so that we can see if the nmethod | |
1053 // we looked up the handler for has been deoptimized in the meantime. If it has been | |
1054 // we must not use the handler and instread return the deopt blob. | |
1055 address OptoRuntime::handle_exception_C(JavaThread* thread) { | |
1056 // | |
1057 // We are in Java not VM and in debug mode we have a NoHandleMark | |
1058 // | |
1059 #ifndef PRODUCT | |
1060 SharedRuntime::_find_handler_ctr++; // find exception handler | |
1061 #endif | |
1062 debug_only(NoHandleMark __hm;) | |
1063 nmethod* nm = NULL; | |
1064 address handler_address = NULL; | |
1065 { | |
1066 // Enter the VM | |
1067 | |
1068 ResetNoHandleMark rnhm; | |
1069 handler_address = handle_exception_C_helper(thread, nm); | |
1070 } | |
1071 | |
1072 // Back in java: Use no oops, DON'T safepoint | |
1073 | |
1074 // Now check to see if the handler we are returning is in a now | |
1075 // deoptimized frame | |
1076 | |
1077 if (nm != NULL) { | |
1078 RegisterMap map(thread, false); | |
1079 frame caller = thread->last_frame().sender(&map); | |
1080 #ifdef ASSERT | |
1081 assert(caller.is_compiled_frame(), "must be"); | |
1082 #endif // ASSERT | |
1083 if (caller.is_deoptimized_frame()) { | |
1084 handler_address = SharedRuntime::deopt_blob()->unpack_with_exception(); | |
1085 } | |
1086 } | |
1087 return handler_address; | |
1088 } | |
1089 | |
1090 //------------------------------rethrow---------------------------------------- | |
1091 // We get here after compiled code has executed a 'RethrowNode'. The callee | |
1092 // is either throwing or rethrowing an exception. The callee-save registers | |
1093 // have been restored, synchronized objects have been unlocked and the callee | |
1094 // stack frame has been removed. The return address was passed in. | |
1095 // Exception oop is passed as the 1st argument. This routine is then called | |
1096 // from the stub. On exit, we know where to jump in the caller's code. | |
1097 // After this C code exits, the stub will pop his frame and end in a jump | |
1098 // (instead of a return). We enter the caller's default handler. | |
1099 // | |
1100 // This must be JRT_LEAF: | |
1101 // - caller will not change its state as we cannot block on exit, | |
1102 // therefore raw_exception_handler_for_return_address is all it takes | |
1103 // to handle deoptimized blobs | |
1104 // | |
1105 // However, there needs to be a safepoint check in the middle! So compiled | |
1106 // safepoints are completely watertight. | |
1107 // | |
1108 // Thus, it cannot be a leaf since it contains the No_GC_Verifier. | |
1109 // | |
1110 // *THIS IS NOT RECOMMENDED PROGRAMMING STYLE* | |
1111 // | |
1112 address OptoRuntime::rethrow_C(oopDesc* exception, JavaThread* thread, address ret_pc) { | |
1113 #ifndef PRODUCT | |
1114 SharedRuntime::_rethrow_ctr++; // count rethrows | |
1115 #endif | |
1116 assert (exception != NULL, "should have thrown a NULLPointerException"); | |
1117 #ifdef ASSERT | |
1142 | 1118 if (!(exception->is_a(SystemDictionary::Throwable_klass()))) { |
0 | 1119 // should throw an exception here |
1120 ShouldNotReachHere(); | |
1121 } | |
1122 #endif | |
1123 | |
1124 thread->set_vm_result(exception); | |
1125 // Frame not compiled (handles deoptimization blob) | |
1295 | 1126 return SharedRuntime::raw_exception_handler_for_return_address(thread, ret_pc); |
0 | 1127 } |
1128 | |
1129 | |
1130 const TypeFunc *OptoRuntime::rethrow_Type() { | |
1131 // create input type (domain) | |
1132 const Type **fields = TypeTuple::fields(1); | |
1133 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // Exception oop | |
1134 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+1,fields); | |
1135 | |
1136 // create result type (range) | |
1137 fields = TypeTuple::fields(1); | |
1138 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // Exception oop | |
1139 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+1, fields); | |
1140 | |
1141 return TypeFunc::make(domain, range); | |
1142 } | |
1143 | |
1144 | |
1145 void OptoRuntime::deoptimize_caller_frame(JavaThread *thread, bool doit) { | |
7428
2d6c433b1f38
8004741: Missing compiled exception handle table entry for multidimensional array allocation
kvn
parents:
6983
diff
changeset
|
1146 // Deoptimize the caller before continuing, as the compiled |
2d6c433b1f38
8004741: Missing compiled exception handle table entry for multidimensional array allocation
kvn
parents:
6983
diff
changeset
|
1147 // exception handler table may not be valid. |
2d6c433b1f38
8004741: Missing compiled exception handle table entry for multidimensional array allocation
kvn
parents:
6983
diff
changeset
|
1148 if (!StressCompiledExceptionHandlers && doit) { |
2d6c433b1f38
8004741: Missing compiled exception handle table entry for multidimensional array allocation
kvn
parents:
6983
diff
changeset
|
1149 deoptimize_caller_frame(thread); |
2d6c433b1f38
8004741: Missing compiled exception handle table entry for multidimensional array allocation
kvn
parents:
6983
diff
changeset
|
1150 } |
2d6c433b1f38
8004741: Missing compiled exception handle table entry for multidimensional array allocation
kvn
parents:
6983
diff
changeset
|
1151 } |
0 | 1152 |
7428
2d6c433b1f38
8004741: Missing compiled exception handle table entry for multidimensional array allocation
kvn
parents:
6983
diff
changeset
|
1153 void OptoRuntime::deoptimize_caller_frame(JavaThread *thread) { |
2d6c433b1f38
8004741: Missing compiled exception handle table entry for multidimensional array allocation
kvn
parents:
6983
diff
changeset
|
1154 // Called from within the owner thread, so no need for safepoint |
2d6c433b1f38
8004741: Missing compiled exception handle table entry for multidimensional array allocation
kvn
parents:
6983
diff
changeset
|
1155 RegisterMap reg_map(thread); |
2d6c433b1f38
8004741: Missing compiled exception handle table entry for multidimensional array allocation
kvn
parents:
6983
diff
changeset
|
1156 frame stub_frame = thread->last_frame(); |
2d6c433b1f38
8004741: Missing compiled exception handle table entry for multidimensional array allocation
kvn
parents:
6983
diff
changeset
|
1157 assert(stub_frame.is_runtime_frame() || exception_blob()->contains(stub_frame.pc()), "sanity check"); |
2d6c433b1f38
8004741: Missing compiled exception handle table entry for multidimensional array allocation
kvn
parents:
6983
diff
changeset
|
1158 frame caller_frame = stub_frame.sender(®_map); |
2d6c433b1f38
8004741: Missing compiled exception handle table entry for multidimensional array allocation
kvn
parents:
6983
diff
changeset
|
1159 |
2d6c433b1f38
8004741: Missing compiled exception handle table entry for multidimensional array allocation
kvn
parents:
6983
diff
changeset
|
1160 // Deoptimize the caller frame. |
7485
4fc2763e670e
Another merge fix.
Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
parents:
7482
diff
changeset
|
1161 Deoptimization::deoptimize_frame(thread, caller_frame.id(), Deoptimization::Reason_constraint); |
0 | 1162 } |
1163 | |
1164 | |
4063
7e0e43cf86d6
7109887: java/util/Arrays/CopyMethods.java fails with -XX:+DeoptimizeALot
kvn
parents:
4048
diff
changeset
|
1165 bool OptoRuntime::is_deoptimized_caller_frame(JavaThread *thread) { |
7e0e43cf86d6
7109887: java/util/Arrays/CopyMethods.java fails with -XX:+DeoptimizeALot
kvn
parents:
4048
diff
changeset
|
1166 // Called from within the owner thread, so no need for safepoint |
7e0e43cf86d6
7109887: java/util/Arrays/CopyMethods.java fails with -XX:+DeoptimizeALot
kvn
parents:
4048
diff
changeset
|
1167 RegisterMap reg_map(thread); |
7e0e43cf86d6
7109887: java/util/Arrays/CopyMethods.java fails with -XX:+DeoptimizeALot
kvn
parents:
4048
diff
changeset
|
1168 frame stub_frame = thread->last_frame(); |
7e0e43cf86d6
7109887: java/util/Arrays/CopyMethods.java fails with -XX:+DeoptimizeALot
kvn
parents:
4048
diff
changeset
|
1169 assert(stub_frame.is_runtime_frame() || exception_blob()->contains(stub_frame.pc()), "sanity check"); |
7e0e43cf86d6
7109887: java/util/Arrays/CopyMethods.java fails with -XX:+DeoptimizeALot
kvn
parents:
4048
diff
changeset
|
1170 frame caller_frame = stub_frame.sender(®_map); |
7e0e43cf86d6
7109887: java/util/Arrays/CopyMethods.java fails with -XX:+DeoptimizeALot
kvn
parents:
4048
diff
changeset
|
1171 return caller_frame.is_deoptimized_frame(); |
7e0e43cf86d6
7109887: java/util/Arrays/CopyMethods.java fails with -XX:+DeoptimizeALot
kvn
parents:
4048
diff
changeset
|
1172 } |
7e0e43cf86d6
7109887: java/util/Arrays/CopyMethods.java fails with -XX:+DeoptimizeALot
kvn
parents:
4048
diff
changeset
|
1173 |
7e0e43cf86d6
7109887: java/util/Arrays/CopyMethods.java fails with -XX:+DeoptimizeALot
kvn
parents:
4048
diff
changeset
|
1174 |
0 | 1175 const TypeFunc *OptoRuntime::register_finalizer_Type() { |
1176 // create input type (domain) | |
1177 const Type **fields = TypeTuple::fields(1); | |
1178 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // oop; Receiver | |
1179 // // The JavaThread* is passed to each routine as the last argument | |
1180 // fields[TypeFunc::Parms+1] = TypeRawPtr::NOTNULL; // JavaThread *; Executing thread | |
1181 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+1,fields); | |
1182 | |
1183 // create result type (range) | |
1184 fields = TypeTuple::fields(0); | |
1185 | |
1186 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0,fields); | |
1187 | |
1188 return TypeFunc::make(domain,range); | |
1189 } | |
1190 | |
1191 | |
1192 //----------------------------------------------------------------------------- | |
1193 // Dtrace support. entry and exit probes have the same signature | |
1194 const TypeFunc *OptoRuntime::dtrace_method_entry_exit_Type() { | |
1195 // create input type (domain) | |
1196 const Type **fields = TypeTuple::fields(2); | |
1197 fields[TypeFunc::Parms+0] = TypeRawPtr::BOTTOM; // Thread-local storage | |
6739
8a02ca5e5576
7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents:
6725
diff
changeset
|
1198 fields[TypeFunc::Parms+1] = TypeMetadataPtr::BOTTOM; // Method*; Method we are entering |
0 | 1199 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2,fields); |
1200 | |
1201 // create result type (range) | |
1202 fields = TypeTuple::fields(0); | |
1203 | |
1204 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0,fields); | |
1205 | |
1206 return TypeFunc::make(domain,range); | |
1207 } | |
1208 | |
1209 const TypeFunc *OptoRuntime::dtrace_object_alloc_Type() { | |
1210 // create input type (domain) | |
1211 const Type **fields = TypeTuple::fields(2); | |
1212 fields[TypeFunc::Parms+0] = TypeRawPtr::BOTTOM; // Thread-local storage | |
1213 fields[TypeFunc::Parms+1] = TypeInstPtr::NOTNULL; // oop; newly allocated object | |
1214 | |
1215 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2,fields); | |
1216 | |
1217 // create result type (range) | |
1218 fields = TypeTuple::fields(0); | |
1219 | |
1220 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0,fields); | |
1221 | |
1222 return TypeFunc::make(domain,range); | |
1223 } | |
1224 | |
1225 | |
1226 JRT_ENTRY_NO_ASYNC(void, OptoRuntime::register_finalizer(oopDesc* obj, JavaThread* thread)) | |
1227 assert(obj->is_oop(), "must be a valid oop"); | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6633
diff
changeset
|
1228 assert(obj->klass()->has_finalizer(), "shouldn't be here otherwise"); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6633
diff
changeset
|
1229 InstanceKlass::register_finalizer(instanceOop(obj), CHECK); |
0 | 1230 JRT_END |
1231 | |
1232 //----------------------------------------------------------------------------- | |
1233 | |
1234 NamedCounter * volatile OptoRuntime::_named_counters = NULL; | |
1235 | |
1236 // | |
1237 // dump the collected NamedCounters. | |
1238 // | |
1239 void OptoRuntime::print_named_counters() { | |
1240 int total_lock_count = 0; | |
1241 int eliminated_lock_count = 0; | |
1242 | |
1243 NamedCounter* c = _named_counters; | |
1244 while (c) { | |
1245 if (c->tag() == NamedCounter::LockCounter || c->tag() == NamedCounter::EliminatedLockCounter) { | |
1246 int count = c->count(); | |
1247 if (count > 0) { | |
1248 bool eliminated = c->tag() == NamedCounter::EliminatedLockCounter; | |
1249 if (Verbose) { | |
1250 tty->print_cr("%d %s%s", count, c->name(), eliminated ? " (eliminated)" : ""); | |
1251 } | |
1252 total_lock_count += count; | |
1253 if (eliminated) { | |
1254 eliminated_lock_count += count; | |
1255 } | |
1256 } | |
1257 } else if (c->tag() == NamedCounter::BiasedLockingCounter) { | |
1258 BiasedLockingCounters* blc = ((BiasedLockingNamedCounter*)c)->counters(); | |
1259 if (blc->nonzero()) { | |
1260 tty->print_cr("%s", c->name()); | |
1261 blc->print_on(tty); | |
1262 } | |
1263 } | |
1264 c = c->next(); | |
1265 } | |
1266 if (total_lock_count > 0) { | |
1267 tty->print_cr("dynamic locks: %d", total_lock_count); | |
1268 if (eliminated_lock_count) { | |
1269 tty->print_cr("eliminated locks: %d (%d%%)", eliminated_lock_count, | |
1270 (int)(eliminated_lock_count * 100.0 / total_lock_count)); | |
1271 } | |
1272 } | |
1273 } | |
1274 | |
1275 // | |
1276 // Allocate a new NamedCounter. The JVMState is used to generate the | |
1277 // name which consists of method@line for the inlining tree. | |
1278 // | |
1279 | |
1280 NamedCounter* OptoRuntime::new_named_counter(JVMState* youngest_jvms, NamedCounter::CounterTag tag) { | |
1281 int max_depth = youngest_jvms->depth(); | |
1282 | |
1283 // Visit scopes from youngest to oldest. | |
1284 bool first = true; | |
1285 stringStream st; | |
1286 for (int depth = max_depth; depth >= 1; depth--) { | |
1287 JVMState* jvms = youngest_jvms->of_depth(depth); | |
1288 ciMethod* m = jvms->has_method() ? jvms->method() : NULL; | |
1289 if (!first) { | |
1290 st.print(" "); | |
1291 } else { | |
1292 first = false; | |
1293 } | |
1294 int bci = jvms->bci(); | |
1295 if (bci < 0) bci = 0; | |
1296 st.print("%s.%s@%d", m->holder()->name()->as_utf8(), m->name()->as_utf8(), bci); | |
1297 // To print linenumbers instead of bci use: m->line_number_from_bci(bci) | |
1298 } | |
1299 NamedCounter* c; | |
1300 if (tag == NamedCounter::BiasedLockingCounter) { | |
1301 c = new BiasedLockingNamedCounter(strdup(st.as_string())); | |
1302 } else { | |
1303 c = new NamedCounter(strdup(st.as_string()), tag); | |
1304 } | |
1305 | |
1306 // atomically add the new counter to the head of the list. We only | |
1307 // add counters so this is safe. | |
1308 NamedCounter* head; | |
1309 do { | |
1310 head = _named_counters; | |
1311 c->set_next(head); | |
1312 } while (Atomic::cmpxchg_ptr(c, &_named_counters, head) != head); | |
1313 return c; | |
1314 } | |
1315 | |
1316 //----------------------------------------------------------------------------- | |
1317 // Non-product code | |
1318 #ifndef PRODUCT | |
1319 | |
1320 int trace_exception_counter = 0; | |
1321 static void trace_exception(oop exception_oop, address exception_pc, const char* msg) { | |
1322 ttyLocker ttyl; | |
1323 trace_exception_counter++; | |
1324 tty->print("%d [Exception (%s): ", trace_exception_counter, msg); | |
1325 exception_oop->print_value(); | |
1326 tty->print(" in "); | |
1327 CodeBlob* blob = CodeCache::find_blob(exception_pc); | |
1328 if (blob->is_nmethod()) { | |
1329 ((nmethod*)blob)->method()->print_value(); | |
1330 } else if (blob->is_runtime_stub()) { | |
1331 tty->print("<runtime-stub>"); | |
1332 } else { | |
1333 tty->print("<unknown>"); | |
1334 } | |
1335 tty->print(" at " INTPTR_FORMAT, exception_pc); | |
1336 tty->print_cr("]"); | |
1337 } | |
1338 | |
1339 #endif // PRODUCT | |
1340 | |
1341 | |
1342 # ifdef ENABLE_ZAP_DEAD_LOCALS | |
1343 // Called from call sites in compiled code with oop maps (actually safepoints) | |
1344 // Zaps dead locals in first java frame. | |
1345 // Is entry because may need to lock to generate oop maps | |
1346 // Currently, only used for compiler frames, but someday may be used | |
1347 // for interpreter frames, too. | |
1348 | |
1349 int OptoRuntime::ZapDeadCompiledLocals_count = 0; | |
1350 | |
1351 // avoid pointers to member funcs with these helpers | |
1352 static bool is_java_frame( frame* f) { return f->is_java_frame(); } | |
1353 static bool is_native_frame(frame* f) { return f->is_native_frame(); } | |
1354 | |
1355 | |
1356 void OptoRuntime::zap_dead_java_or_native_locals(JavaThread* thread, | |
1357 bool (*is_this_the_right_frame_to_zap)(frame*)) { | |
1358 assert(JavaThread::current() == thread, "is this needed?"); | |
1359 | |
1360 if ( !ZapDeadCompiledLocals ) return; | |
1361 | |
1362 bool skip = false; | |
1363 | |
1364 if ( ZapDeadCompiledLocalsFirst == 0 ) ; // nothing special | |
1365 else if ( ZapDeadCompiledLocalsFirst > ZapDeadCompiledLocals_count ) skip = true; | |
1366 else if ( ZapDeadCompiledLocalsFirst == ZapDeadCompiledLocals_count ) | |
1367 warning("starting zapping after skipping"); | |
1368 | |
1369 if ( ZapDeadCompiledLocalsLast == -1 ) ; // nothing special | |
1370 else if ( ZapDeadCompiledLocalsLast < ZapDeadCompiledLocals_count ) skip = true; | |
1371 else if ( ZapDeadCompiledLocalsLast == ZapDeadCompiledLocals_count ) | |
1372 warning("about to zap last zap"); | |
1373 | |
1374 ++ZapDeadCompiledLocals_count; // counts skipped zaps, too | |
1375 | |
1376 if ( skip ) return; | |
1377 | |
1378 // find java frame and zap it | |
1379 | |
1380 for (StackFrameStream sfs(thread); !sfs.is_done(); sfs.next()) { | |
1381 if (is_this_the_right_frame_to_zap(sfs.current()) ) { | |
1382 sfs.current()->zap_dead_locals(thread, sfs.register_map()); | |
1383 return; | |
1384 } | |
1385 } | |
1386 warning("no frame found to zap in zap_dead_Java_locals_C"); | |
1387 } | |
1388 | |
1389 JRT_LEAF(void, OptoRuntime::zap_dead_Java_locals_C(JavaThread* thread)) | |
1390 zap_dead_java_or_native_locals(thread, is_java_frame); | |
1391 JRT_END | |
1392 | |
1393 // The following does not work because for one thing, the | |
1394 // thread state is wrong; it expects java, but it is native. | |
605 | 1395 // Also, the invariants in a native stub are different and |
0 | 1396 // I'm not sure it is safe to have a MachCalRuntimeDirectNode |
1397 // in there. | |
1398 // So for now, we do not zap in native stubs. | |
1399 | |
1400 JRT_LEAF(void, OptoRuntime::zap_dead_native_locals_C(JavaThread* thread)) | |
1401 zap_dead_java_or_native_locals(thread, is_native_frame); | |
1402 JRT_END | |
1403 | |
1404 # endif |