Mercurial > hg > truffle
annotate src/share/vm/opto/generateOptoStub.cpp @ 17716:cdb71841f4bc
6498581: ThreadInterruptTest3 produces wrong output on Windows
Summary: There is race condition between os::interrupt and os::is_interrupted on Windows. In JVM_Sleep(Thread.sleep), check if thread gets interrupted, it may see interrupted but not really interrupted so cause spurious waking up (early return from sleep). Fix by checking if interrupt event really gets set thus prevent false return. For intrinsic of _isInterrupted, on Windows, go fastpath only on bit not set.
Reviewed-by: acorn, kvn
Contributed-by: david.holmes@oracle.com, yumin.qi@oracle.com
author | minqi |
---|---|
date | Wed, 26 Feb 2014 15:20:41 -0800 |
parents | 55fb97c4c58d |
children | abec000618bf |
rev | line source |
---|---|
0 | 1 /* |
17467
55fb97c4c58d
8029233: Update copyright year to match last edit in jdk8 hotspot repository for 2013
mikael
parents:
12158
diff
changeset
|
2 * Copyright (c) 1999, 2013, 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); | |
12158
766fac3395d6
8012972: Incremental Inlining should support scalar replaced object in debug info
kvn
parents:
7994
diff
changeset
|
64 jvms->set_scloff(max_map); |
0 | 65 jvms->set_endoff(max_map); |
66 { | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
67 SafePointNode *map = new (C) SafePointNode( max_map, jvms ); |
0 | 68 jvms->set_map(map); |
69 set_jvms(jvms); | |
70 assert(map == this->map(), "kit.map is set"); | |
71 } | |
72 | |
73 // Make up the parameters | |
74 uint i; | |
75 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
|
76 map()->init_req(i, _gvn.transform(new (C) ParmNode(start, i))); |
0 | 77 for( ; i<map()->req(); i++ ) |
78 map()->init_req(i, top()); // For nicer debugging | |
79 | |
80 // GraphKit requires memory to be a MergeMemNode: | |
81 set_all_memory(map()->memory()); | |
82 | |
83 // 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
|
84 Node* thread = _gvn.transform( new (C) ThreadLocalNode() ); |
0 | 85 |
86 const int NoAlias = Compile::AliasIdxBot; | |
87 | |
88 Node* adr_last_Java_pc = basic_plus_adr(top(), | |
89 thread, | |
90 in_bytes(JavaThread::frame_anchor_offset()) + | |
91 in_bytes(JavaFrameAnchor::last_Java_pc_offset())); | |
7994 | 92 #if defined(SPARC) |
0 | 93 Node* adr_flags = basic_plus_adr(top(), |
94 thread, | |
95 in_bytes(JavaThread::frame_anchor_offset()) + | |
96 in_bytes(JavaFrameAnchor::flags_offset())); | |
7994 | 97 #endif /* defined(SPARC) */ |
0 | 98 |
99 | |
100 // Drop in the last_Java_sp. last_Java_fp is not touched. | |
101 // Always do this after the other "last_Java_frame" fields are set since | |
102 // as soon as last_Java_sp != NULL the has_last_Java_frame is true and | |
103 // users will look at the other fields. | |
104 // | |
105 Node *adr_sp = basic_plus_adr(top(), thread, in_bytes(JavaThread::last_Java_sp_offset())); | |
106 Node *last_sp = basic_plus_adr(top(), frameptr(), (intptr_t) STACK_BIAS); | |
107 store_to_memory(NULL, adr_sp, last_sp, T_ADDRESS, NoAlias); | |
108 | |
109 // Set _thread_in_native | |
110 // The order of stores into TLS is critical! Setting _thread_in_native MUST | |
111 // be last, because a GC is allowed at any time after setting it and the GC | |
112 // will require last_Java_pc and last_Java_sp. | |
113 Node* adr_state = basic_plus_adr(top(), thread, in_bytes(JavaThread::thread_state_offset())); | |
114 | |
115 //----------------------------- | |
116 // Compute signature for C call. Varies from the Java signature! | |
117 const Type **fields = TypeTuple::fields(2*parm_cnt+2); | |
118 uint cnt = TypeFunc::Parms; | |
119 // The C routines gets the base of thread-local storage passed in as an | |
120 // extra argument. Not all calls need it, but its cheap to add here. | |
121 for( ; cnt<parm_cnt; cnt++ ) | |
122 fields[cnt] = jdomain->field_at(cnt); | |
123 fields[cnt++] = TypeRawPtr::BOTTOM; // Thread-local storage | |
124 // Also pass in the caller's PC, if asked for. | |
125 if( return_pc ) | |
126 fields[cnt++] = TypeRawPtr::BOTTOM; // Return PC | |
127 | |
128 const TypeTuple* domain = TypeTuple::make(cnt,fields); | |
129 // The C routine we are about to call cannot return an oop; it can block on | |
130 // exit and a GC will trash the oop while it sits in C-land. Instead, we | |
131 // return the oop through TLS for runtime calls. | |
132 // Also, C routines returning integer subword values leave the high | |
133 // order bits dirty; these must be cleaned up by explicit sign extension. | |
134 const Type* retval = (jrange->cnt() == TypeFunc::Parms) ? Type::TOP : jrange->field_at(TypeFunc::Parms); | |
135 // Make a private copy of jrange->fields(); | |
136 const Type **rfields = TypeTuple::fields(jrange->cnt() - TypeFunc::Parms); | |
137 // Fixup oop returns | |
138 int retval_ptr = retval->isa_oop_ptr(); | |
139 if( retval_ptr ) { | |
140 assert( pass_tls, "Oop must be returned thru TLS" ); | |
141 // Fancy-jumps return address; others return void | |
142 rfields[TypeFunc::Parms] = is_fancy_jump ? TypeRawPtr::BOTTOM : Type::TOP; | |
143 | |
144 } else if( retval->isa_int() ) { // Returning any integer subtype? | |
145 // "Fatten" byte, char & short return types to 'int' to show that | |
146 // the native C code can return values with junk high order bits. | |
147 // We'll sign-extend it below later. | |
148 rfields[TypeFunc::Parms] = TypeInt::INT; // It's "dirty" and needs sign-ext | |
149 | |
150 } else if( jrange->cnt() >= TypeFunc::Parms+1 ) { // Else copy other types | |
151 rfields[TypeFunc::Parms] = jrange->field_at(TypeFunc::Parms); | |
152 if( jrange->cnt() == TypeFunc::Parms+2 ) | |
153 rfields[TypeFunc::Parms+1] = jrange->field_at(TypeFunc::Parms+1); | |
154 } | |
155 const TypeTuple* range = TypeTuple::make(jrange->cnt(),rfields); | |
156 | |
157 // Final C signature | |
158 const TypeFunc *c_sig = TypeFunc::make(domain,range); | |
159 | |
160 //----------------------------- | |
161 // Make the call node | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
162 CallRuntimeNode *call = new (C) |
0 | 163 CallRuntimeNode(c_sig, C_function, name, TypePtr::BOTTOM); |
164 //----------------------------- | |
165 | |
166 // Fix-up the debug info for the call | |
167 call->set_jvms( new (C) JVMState(0) ); | |
168 call->jvms()->set_bci(0); | |
169 call->jvms()->set_offsets(cnt); | |
170 | |
171 // Set fixed predefined input arguments | |
172 cnt = 0; | |
173 for( i=0; i<TypeFunc::Parms; i++ ) | |
174 call->init_req( cnt++, map()->in(i) ); | |
175 // A little too aggressive on the parm copy; return address is not an input | |
176 call->set_req(TypeFunc::ReturnAdr, top()); | |
177 for( ; i<parm_cnt; i++ ) // Regular input arguments | |
178 call->init_req( cnt++, map()->in(i) ); | |
179 | |
180 call->init_req( cnt++, thread ); | |
181 if( return_pc ) // Return PC, if asked for | |
182 call->init_req( cnt++, returnadr() ); | |
183 _gvn.transform_no_reclaim(call); | |
184 | |
185 | |
186 //----------------------------- | |
187 // 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
|
188 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
|
189 set_i_o( _gvn.transform( new (C) ProjNode(call,TypeFunc::I_O )) ); |
0 | 190 set_all_memory_call(call); |
191 if (range->cnt() > TypeFunc::Parms) { | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
192 Node* retnode = _gvn.transform( new (C) ProjNode(call,TypeFunc::Parms) ); |
0 | 193 // C-land is allowed to return sub-word values. Convert to integer type. |
194 assert( retval != Type::TOP, "" ); | |
195 if (retval == TypeInt::BOOL) { | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
196 retnode = _gvn.transform( new (C) AndINode(retnode, intcon(0xFF)) ); |
0 | 197 } else if (retval == TypeInt::CHAR) { |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
198 retnode = _gvn.transform( new (C) AndINode(retnode, intcon(0xFFFF)) ); |
0 | 199 } else if (retval == TypeInt::BYTE) { |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
200 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
|
201 retnode = _gvn.transform( new (C) RShiftINode(retnode, intcon(24)) ); |
0 | 202 } else if (retval == TypeInt::SHORT) { |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
203 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
|
204 retnode = _gvn.transform( new (C) RShiftINode(retnode, intcon(16)) ); |
0 | 205 } |
206 map()->set_req( TypeFunc::Parms, retnode ); | |
207 } | |
208 | |
209 //----------------------------- | |
210 | |
211 // Clear last_Java_sp | |
212 store_to_memory(NULL, adr_sp, null(), T_ADDRESS, NoAlias); | |
213 // Clear last_Java_pc and (optionally)_flags | |
214 store_to_memory(NULL, adr_last_Java_pc, null(), T_ADDRESS, NoAlias); | |
7994 | 215 #if defined(SPARC) |
0 | 216 store_to_memory(NULL, adr_flags, intcon(0), T_INT, NoAlias); |
7994 | 217 #endif /* defined(SPARC) */ |
0 | 218 #ifdef IA64 |
219 Node* adr_last_Java_fp = basic_plus_adr(top(), thread, in_bytes(JavaThread::last_Java_fp_offset())); | |
220 if( os::is_MP() ) insert_mem_bar(Op_MemBarRelease); | |
221 store_to_memory(NULL, adr_last_Java_fp, null(), T_ADDRESS, NoAlias); | |
222 #endif | |
223 | |
224 // For is-fancy-jump, the C-return value is also the branch target | |
225 Node* target = map()->in(TypeFunc::Parms); | |
226 // Runtime call returning oop in TLS? Fetch it out | |
227 if( pass_tls ) { | |
228 Node* adr = basic_plus_adr(top(), thread, in_bytes(JavaThread::vm_result_offset())); | |
229 Node* vm_result = make_load(NULL, adr, TypeOopPtr::BOTTOM, T_OBJECT, NoAlias, false); | |
230 map()->set_req(TypeFunc::Parms, vm_result); // vm_result passed as result | |
231 // clear thread-local-storage(tls) | |
232 store_to_memory(NULL, adr, null(), T_ADDRESS, NoAlias); | |
233 } | |
234 | |
235 //----------------------------- | |
236 // check exception | |
237 Node* adr = basic_plus_adr(top(), thread, in_bytes(Thread::pending_exception_offset())); | |
238 Node* pending = make_load(NULL, adr, TypeOopPtr::BOTTOM, T_OBJECT, NoAlias, false); | |
239 | |
240 Node* exit_memory = reset_memory(); | |
241 | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
242 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
|
243 Node* bo = _gvn.transform( new (C) BoolNode(cmp, BoolTest::ne) ); |
0 | 244 IfNode *iff = create_and_map_if(control(), bo, PROB_MIN, COUNT_UNKNOWN); |
245 | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
246 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
|
247 Node* if_not_null = _gvn.transform( new (C) IfTrueNode(iff) ); |
0 | 248 |
249 assert (StubRoutines::forward_exception_entry() != NULL, "must be generated before"); | |
250 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
|
251 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
|
252 i_o(), |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
253 exit_memory, |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
254 frameptr(), |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
255 returnadr(), |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
256 exc_target, null()); |
0 | 257 root()->add_req(_gvn.transform(to_exc)); // bind to root to keep live |
258 C->init_start(start); | |
259 | |
260 //----------------------------- | |
261 // If this is a normal subroutine return, issue the return and be done. | |
262 Node *ret; | |
263 switch( is_fancy_jump ) { | |
264 case 0: // Make a return instruction | |
265 // 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
|
266 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
|
267 i_o(), |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
268 exit_memory, |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
269 frameptr(), |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
270 returnadr()); |
0 | 271 if (C->tf()->range()->cnt() > TypeFunc::Parms) |
272 ret->add_req( map()->in(TypeFunc::Parms) ); | |
273 break; | |
274 case 1: // This is a fancy tail-call jump. Jump to computed address. | |
275 // 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
|
276 ret = new (C) TailCallNode(if_null, |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
277 i_o(), |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
278 exit_memory, |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
279 frameptr(), |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
280 returnadr(), |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
281 target, map()->in(TypeFunc::Parms)); |
0 | 282 break; |
283 case 2: // Pop return address & jump | |
284 // Throw away old return address; jump to new computed address | |
285 //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
|
286 ret = new (C) TailJumpNode(if_null, |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
287 i_o(), |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
288 exit_memory, |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
289 frameptr(), |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
1972
diff
changeset
|
290 target, map()->in(TypeFunc::Parms)); |
0 | 291 break; |
292 default: | |
293 ShouldNotReachHere(); | |
294 } | |
295 root()->add_req(_gvn.transform(ret)); | |
296 } |