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