Mercurial > hg > truffle
annotate src/share/vm/opto/generateOptoStub.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 | 9fae07c31641 |
children | 766fac3395d6 75ef1a499665 |
rev | line source |
---|---|
0 | 1 /* |
6842
b9a9ed0f8eeb
7197424: update copyright year to match last edit in jdk8 hotspot repository
mikael
parents:
6804
diff
changeset
|
2 * Copyright (c) 1999, 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:
0
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
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:
0
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "opto/addnode.hpp" | |
27 #include "opto/callnode.hpp" | |
28 #include "opto/cfgnode.hpp" | |
29 #include "opto/compile.hpp" | |
30 #include "opto/connode.hpp" | |
31 #include "opto/locknode.hpp" | |
32 #include "opto/memnode.hpp" | |
33 #include "opto/mulnode.hpp" | |
34 #include "opto/node.hpp" | |
35 #include "opto/parse.hpp" | |
36 #include "opto/phaseX.hpp" | |
37 #include "opto/rootnode.hpp" | |
38 #include "opto/runtime.hpp" | |
39 #include "opto/type.hpp" | |
0 | 40 |
41 //--------------------gen_stub------------------------------- | |
42 void GraphKit::gen_stub(address C_function, | |
43 const char *name, | |
44 int is_fancy_jump, | |
45 bool pass_tls, | |
46 bool return_pc) { | |
47 ResourceMark rm; | |
48 | |
49 const TypeTuple *jdomain = C->tf()->domain(); | |
50 const TypeTuple *jrange = C->tf()->range(); | |
51 | |
52 // The procedure start | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
53 StartNode* start = new (C) StartNode(root(), jdomain); |
0 | 54 _gvn.set_type_bottom(start); |
55 | |
56 // Make a map, with JVM state | |
57 uint parm_cnt = jdomain->cnt(); | |
58 uint max_map = MAX2(2*parm_cnt+1, jrange->cnt()); | |
59 // %%% SynchronizationEntryBCI is redundant; use InvocationEntryBci in interfaces | |
60 assert(SynchronizationEntryBCI == InvocationEntryBci, ""); | |
61 JVMState* jvms = new (C) JVMState(0); | |
62 jvms->set_bci(InvocationEntryBci); | |
63 jvms->set_monoff(max_map); | |
64 jvms->set_endoff(max_map); | |
65 { | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
66 SafePointNode *map = new (C) SafePointNode( max_map, jvms ); |
0 | 67 jvms->set_map(map); |
68 set_jvms(jvms); | |
69 assert(map == this->map(), "kit.map is set"); | |
70 } | |
71 | |
72 // Make up the parameters | |
73 uint i; | |
74 for( i = 0; i < parm_cnt; i++ ) | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
75 map()->init_req(i, _gvn.transform(new (C) ParmNode(start, i))); |
0 | 76 for( ; i<map()->req(); i++ ) |
77 map()->init_req(i, top()); // For nicer debugging | |
78 | |
79 // GraphKit requires memory to be a MergeMemNode: | |
80 set_all_memory(map()->memory()); | |
81 | |
82 // Get base of thread-local storage area | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
83 Node* thread = _gvn.transform( new (C) ThreadLocalNode() ); |
0 | 84 |
85 const int NoAlias = Compile::AliasIdxBot; | |
86 | |
87 Node* adr_last_Java_pc = basic_plus_adr(top(), | |
88 thread, | |
89 in_bytes(JavaThread::frame_anchor_offset()) + | |
90 in_bytes(JavaFrameAnchor::last_Java_pc_offset())); | |
7994 | 91 #if defined(SPARC) |
0 | 92 Node* adr_flags = basic_plus_adr(top(), |
93 thread, | |
94 in_bytes(JavaThread::frame_anchor_offset()) + | |
95 in_bytes(JavaFrameAnchor::flags_offset())); | |
7994 | 96 #endif /* defined(SPARC) */ |
0 | 97 |
98 | |
99 // Drop in the last_Java_sp. last_Java_fp is not touched. | |
100 // Always do this after the other "last_Java_frame" fields are set since | |
101 // as soon as last_Java_sp != NULL the has_last_Java_frame is true and | |
102 // users will look at the other fields. | |
103 // | |
104 Node *adr_sp = basic_plus_adr(top(), thread, in_bytes(JavaThread::last_Java_sp_offset())); | |
105 Node *last_sp = basic_plus_adr(top(), frameptr(), (intptr_t) STACK_BIAS); | |
106 store_to_memory(NULL, adr_sp, last_sp, T_ADDRESS, NoAlias); | |
107 | |
108 // Set _thread_in_native | |
109 // The order of stores into TLS is critical! Setting _thread_in_native MUST | |
110 // be last, because a GC is allowed at any time after setting it and the GC | |
111 // will require last_Java_pc and last_Java_sp. | |
112 Node* adr_state = basic_plus_adr(top(), thread, in_bytes(JavaThread::thread_state_offset())); | |
113 | |
114 //----------------------------- | |
115 // Compute signature for C call. Varies from the Java signature! | |
116 const Type **fields = TypeTuple::fields(2*parm_cnt+2); | |
117 uint cnt = TypeFunc::Parms; | |
118 // The C routines gets the base of thread-local storage passed in as an | |
119 // extra argument. Not all calls need it, but its cheap to add here. | |
120 for( ; cnt<parm_cnt; cnt++ ) | |
121 fields[cnt] = jdomain->field_at(cnt); | |
122 fields[cnt++] = TypeRawPtr::BOTTOM; // Thread-local storage | |
123 // Also pass in the caller's PC, if asked for. | |
124 if( return_pc ) | |
125 fields[cnt++] = TypeRawPtr::BOTTOM; // Return PC | |
126 | |
127 const TypeTuple* domain = TypeTuple::make(cnt,fields); | |
128 // The C routine we are about to call cannot return an oop; it can block on | |
129 // exit and a GC will trash the oop while it sits in C-land. Instead, we | |
130 // return the oop through TLS for runtime calls. | |
131 // Also, C routines returning integer subword values leave the high | |
132 // order bits dirty; these must be cleaned up by explicit sign extension. | |
133 const Type* retval = (jrange->cnt() == TypeFunc::Parms) ? Type::TOP : jrange->field_at(TypeFunc::Parms); | |
134 // Make a private copy of jrange->fields(); | |
135 const Type **rfields = TypeTuple::fields(jrange->cnt() - TypeFunc::Parms); | |
136 // Fixup oop returns | |
137 int retval_ptr = retval->isa_oop_ptr(); | |
138 if( retval_ptr ) { | |
139 assert( pass_tls, "Oop must be returned thru TLS" ); | |
140 // Fancy-jumps return address; others return void | |
141 rfields[TypeFunc::Parms] = is_fancy_jump ? TypeRawPtr::BOTTOM : Type::TOP; | |
142 | |
143 } else if( retval->isa_int() ) { // Returning any integer subtype? | |
144 // "Fatten" byte, char & short return types to 'int' to show that | |
145 // the native C code can return values with junk high order bits. | |
146 // We'll sign-extend it below later. | |
147 rfields[TypeFunc::Parms] = TypeInt::INT; // It's "dirty" and needs sign-ext | |
148 | |
149 } else if( jrange->cnt() >= TypeFunc::Parms+1 ) { // Else copy other types | |
150 rfields[TypeFunc::Parms] = jrange->field_at(TypeFunc::Parms); | |
151 if( jrange->cnt() == TypeFunc::Parms+2 ) | |
152 rfields[TypeFunc::Parms+1] = jrange->field_at(TypeFunc::Parms+1); | |
153 } | |
154 const TypeTuple* range = TypeTuple::make(jrange->cnt(),rfields); | |
155 | |
156 // Final C signature | |
157 const TypeFunc *c_sig = TypeFunc::make(domain,range); | |
158 | |
159 //----------------------------- | |
160 // Make the call node | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
161 CallRuntimeNode *call = new (C) |
0 | 162 CallRuntimeNode(c_sig, C_function, name, TypePtr::BOTTOM); |
163 //----------------------------- | |
164 | |
165 // Fix-up the debug info for the call | |
166 call->set_jvms( new (C) JVMState(0) ); | |
167 call->jvms()->set_bci(0); | |
168 call->jvms()->set_offsets(cnt); | |
169 | |
170 // Set fixed predefined input arguments | |
171 cnt = 0; | |
172 for( i=0; i<TypeFunc::Parms; i++ ) | |
173 call->init_req( cnt++, map()->in(i) ); | |
174 // A little too aggressive on the parm copy; return address is not an input | |
175 call->set_req(TypeFunc::ReturnAdr, top()); | |
176 for( ; i<parm_cnt; i++ ) // Regular input arguments | |
177 call->init_req( cnt++, map()->in(i) ); | |
178 | |
179 call->init_req( cnt++, thread ); | |
180 if( return_pc ) // Return PC, if asked for | |
181 call->init_req( cnt++, returnadr() ); | |
182 _gvn.transform_no_reclaim(call); | |
183 | |
184 | |
185 //----------------------------- | |
186 // Now set up the return results | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
187 set_control( _gvn.transform( new (C) ProjNode(call,TypeFunc::Control)) ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
188 set_i_o( _gvn.transform( new (C) ProjNode(call,TypeFunc::I_O )) ); |
0 | 189 set_all_memory_call(call); |
190 if (range->cnt() > TypeFunc::Parms) { | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
191 Node* retnode = _gvn.transform( new (C) ProjNode(call,TypeFunc::Parms) ); |
0 | 192 // C-land is allowed to return sub-word values. Convert to integer type. |
193 assert( retval != Type::TOP, "" ); | |
194 if (retval == TypeInt::BOOL) { | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
195 retnode = _gvn.transform( new (C) AndINode(retnode, intcon(0xFF)) ); |
0 | 196 } else if (retval == TypeInt::CHAR) { |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
197 retnode = _gvn.transform( new (C) AndINode(retnode, intcon(0xFFFF)) ); |
0 | 198 } else if (retval == TypeInt::BYTE) { |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
199 retnode = _gvn.transform( new (C) LShiftINode(retnode, intcon(24)) ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
200 retnode = _gvn.transform( new (C) RShiftINode(retnode, intcon(24)) ); |
0 | 201 } else if (retval == TypeInt::SHORT) { |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
202 retnode = _gvn.transform( new (C) LShiftINode(retnode, intcon(16)) ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
203 retnode = _gvn.transform( new (C) RShiftINode(retnode, intcon(16)) ); |
0 | 204 } |
205 map()->set_req( TypeFunc::Parms, retnode ); | |
206 } | |
207 | |
208 //----------------------------- | |
209 | |
210 // Clear last_Java_sp | |
211 store_to_memory(NULL, adr_sp, null(), T_ADDRESS, NoAlias); | |
212 // Clear last_Java_pc and (optionally)_flags | |
213 store_to_memory(NULL, adr_last_Java_pc, null(), T_ADDRESS, NoAlias); | |
7994 | 214 #if defined(SPARC) |
0 | 215 store_to_memory(NULL, adr_flags, intcon(0), T_INT, NoAlias); |
7994 | 216 #endif /* defined(SPARC) */ |
0 | 217 #ifdef IA64 |
218 Node* adr_last_Java_fp = basic_plus_adr(top(), thread, in_bytes(JavaThread::last_Java_fp_offset())); | |
219 if( os::is_MP() ) insert_mem_bar(Op_MemBarRelease); | |
220 store_to_memory(NULL, adr_last_Java_fp, null(), T_ADDRESS, NoAlias); | |
221 #endif | |
222 | |
223 // For is-fancy-jump, the C-return value is also the branch target | |
224 Node* target = map()->in(TypeFunc::Parms); | |
225 // Runtime call returning oop in TLS? Fetch it out | |
226 if( pass_tls ) { | |
227 Node* adr = basic_plus_adr(top(), thread, in_bytes(JavaThread::vm_result_offset())); | |
228 Node* vm_result = make_load(NULL, adr, TypeOopPtr::BOTTOM, T_OBJECT, NoAlias, false); | |
229 map()->set_req(TypeFunc::Parms, vm_result); // vm_result passed as result | |
230 // clear thread-local-storage(tls) | |
231 store_to_memory(NULL, adr, null(), T_ADDRESS, NoAlias); | |
232 } | |
233 | |
234 //----------------------------- | |
235 // check exception | |
236 Node* adr = basic_plus_adr(top(), thread, in_bytes(Thread::pending_exception_offset())); | |
237 Node* pending = make_load(NULL, adr, TypeOopPtr::BOTTOM, T_OBJECT, NoAlias, false); | |
238 | |
239 Node* exit_memory = reset_memory(); | |
240 | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
241 Node* cmp = _gvn.transform( new (C) CmpPNode(pending, null()) ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
242 Node* bo = _gvn.transform( new (C) BoolNode(cmp, BoolTest::ne) ); |
0 | 243 IfNode *iff = create_and_map_if(control(), bo, PROB_MIN, COUNT_UNKNOWN); |
244 | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
245 Node* if_null = _gvn.transform( new (C) IfFalseNode(iff) ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
246 Node* if_not_null = _gvn.transform( new (C) IfTrueNode(iff) ); |
0 | 247 |
248 assert (StubRoutines::forward_exception_entry() != NULL, "must be generated before"); | |
249 Node *exc_target = makecon(TypeRawPtr::make( StubRoutines::forward_exception_entry() )); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
250 Node *to_exc = new (C) TailCallNode(if_not_null, |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
251 i_o(), |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
252 exit_memory, |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
253 frameptr(), |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
254 returnadr(), |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
255 exc_target, null()); |
0 | 256 root()->add_req(_gvn.transform(to_exc)); // bind to root to keep live |
257 C->init_start(start); | |
258 | |
259 //----------------------------- | |
260 // If this is a normal subroutine return, issue the return and be done. | |
261 Node *ret; | |
262 switch( is_fancy_jump ) { | |
263 case 0: // Make a return instruction | |
264 // Return to caller, free any space for return address | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
265 ret = new (C) ReturnNode(TypeFunc::Parms, if_null, |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
266 i_o(), |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
267 exit_memory, |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
268 frameptr(), |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
269 returnadr()); |
0 | 270 if (C->tf()->range()->cnt() > TypeFunc::Parms) |
271 ret->add_req( map()->in(TypeFunc::Parms) ); | |
272 break; | |
273 case 1: // This is a fancy tail-call jump. Jump to computed address. | |
274 // Jump to new callee; leave old return address alone. | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
275 ret = new (C) TailCallNode(if_null, |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
276 i_o(), |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
277 exit_memory, |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
278 frameptr(), |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
279 returnadr(), |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
280 target, map()->in(TypeFunc::Parms)); |
0 | 281 break; |
282 case 2: // Pop return address & jump | |
283 // Throw away old return address; jump to new computed address | |
284 //assert(C_function == CAST_FROM_FN_PTR(address, OptoRuntime::rethrow_C), "fancy_jump==2 only for rethrow"); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
285 ret = new (C) TailJumpNode(if_null, |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
286 i_o(), |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
287 exit_memory, |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
288 frameptr(), |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
289 target, map()->in(TypeFunc::Parms)); |
0 | 290 break; |
291 default: | |
292 ShouldNotReachHere(); | |
293 } | |
294 root()->add_req(_gvn.transform(ret)); | |
295 } |