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"
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
53 StartNode* start = new (C) StartNode(root(), jdomain);
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 {
66 SafePointNode *map = new (C) SafePointNode( max_map, jvms );
67 jvms->set_map(map);
68 set_jvms(jvms);
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;
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
161 CallRuntimeNode *call = new (C)
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
187 set_control( _gvn.transform( new (C) ProjNode(call,TypeFunc::Control)) );
188 set_i_o( _gvn.transform( new (C) ProjNode(call,TypeFunc::I_O )) );
189 set_all_memory_call(call);
190 if (range->cnt() > TypeFunc::Parms) {
191 Node* retnode = _gvn.transform( new (C) ProjNode(call,TypeFunc::Parms) );
192 // C-land is allowed to return sub-word values. Convert to integer type.
193 assert( retval != Type::TOP, "" );
194 if (retval == TypeInt::BOOL) {
195 retnode = _gvn.transform( new (C) AndINode(retnode, intcon(0xFF)) );
196 } else if (retval == TypeInt::CHAR) {
197 retnode = _gvn.transform( new (C) AndINode(retnode, intcon(0xFFFF)) );
|
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"
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 // Do we need to convert ints to longs for c calls?
50 const bool convert_ints_to_longs =
51 SharedRuntime::c_calling_convention_requires_ints_as_longs();
52
53 const TypeTuple *jdomain = C->tf()->domain();
54 const TypeTuple *jrange = C->tf()->range();
55
56 // The procedure start
57 StartNode* start = new (C) StartNode(root(), jdomain);
58 _gvn.set_type_bottom(start);
59
60 // Make a map, with JVM state
61 uint parm_cnt = jdomain->cnt();
62 uint max_map = MAX2(2*parm_cnt+1, jrange->cnt());
63 // %%% SynchronizationEntryBCI is redundant; use InvocationEntryBci in interfaces
64 assert(SynchronizationEntryBCI == InvocationEntryBci, "");
65 JVMState* jvms = new (C) JVMState(0);
66 jvms->set_bci(InvocationEntryBci);
67 jvms->set_monoff(max_map);
68 jvms->set_endoff(max_map);
69 {
70 SafePointNode *map = new (C) SafePointNode( max_map, jvms );
71 jvms->set_map(map);
72 set_jvms(jvms);
104 // Always do this after the other "last_Java_frame" fields are set since
105 // as soon as last_Java_sp != NULL the has_last_Java_frame is true and
106 // users will look at the other fields.
107 //
108 Node *adr_sp = basic_plus_adr(top(), thread, in_bytes(JavaThread::last_Java_sp_offset()));
109 Node *last_sp = basic_plus_adr(top(), frameptr(), (intptr_t) STACK_BIAS);
110 store_to_memory(NULL, adr_sp, last_sp, T_ADDRESS, NoAlias);
111
112 // Set _thread_in_native
113 // The order of stores into TLS is critical! Setting _thread_in_native MUST
114 // be last, because a GC is allowed at any time after setting it and the GC
115 // will require last_Java_pc and last_Java_sp.
116 Node* adr_state = basic_plus_adr(top(), thread, in_bytes(JavaThread::thread_state_offset()));
117
118 //-----------------------------
119 // Compute signature for C call. Varies from the Java signature!
120 const Type **fields = TypeTuple::fields(2*parm_cnt+2);
121 uint cnt = TypeFunc::Parms;
122 // The C routines gets the base of thread-local storage passed in as an
123 // extra argument. Not all calls need it, but its cheap to add here.
124 for (uint pcnt = cnt; pcnt < parm_cnt; pcnt++, cnt++) {
125 // Convert ints to longs if required.
126 if (convert_ints_to_longs && jdomain->field_at(pcnt)->isa_int()) {
127 fields[cnt++] = TypeLong::LONG;
128 fields[cnt] = Type::HALF; // must add an additional half for a long
129 } else {
130 fields[cnt] = jdomain->field_at(pcnt);
131 }
132 }
133
134 fields[cnt++] = TypeRawPtr::BOTTOM; // Thread-local storage
135 // Also pass in the caller's PC, if asked for.
136 if( return_pc )
137 fields[cnt++] = TypeRawPtr::BOTTOM; // Return PC
138
139 const TypeTuple* domain = TypeTuple::make(cnt,fields);
140 // The C routine we are about to call cannot return an oop; it can block on
141 // exit and a GC will trash the oop while it sits in C-land. Instead, we
142 // return the oop through TLS for runtime calls.
143 // Also, C routines returning integer subword values leave the high
144 // order bits dirty; these must be cleaned up by explicit sign extension.
145 const Type* retval = (jrange->cnt() == TypeFunc::Parms) ? Type::TOP : jrange->field_at(TypeFunc::Parms);
146 // Make a private copy of jrange->fields();
147 const Type **rfields = TypeTuple::fields(jrange->cnt() - TypeFunc::Parms);
148 // Fixup oop returns
149 int retval_ptr = retval->isa_oop_ptr();
150 if( retval_ptr ) {
151 assert( pass_tls, "Oop must be returned thru TLS" );
152 // Fancy-jumps return address; others return void
153 rfields[TypeFunc::Parms] = is_fancy_jump ? TypeRawPtr::BOTTOM : Type::TOP;
164 rfields[TypeFunc::Parms+1] = jrange->field_at(TypeFunc::Parms+1);
165 }
166 const TypeTuple* range = TypeTuple::make(jrange->cnt(),rfields);
167
168 // Final C signature
169 const TypeFunc *c_sig = TypeFunc::make(domain,range);
170
171 //-----------------------------
172 // Make the call node
173 CallRuntimeNode *call = new (C)
174 CallRuntimeNode(c_sig, C_function, name, TypePtr::BOTTOM);
175 //-----------------------------
176
177 // Fix-up the debug info for the call
178 call->set_jvms( new (C) JVMState(0) );
179 call->jvms()->set_bci(0);
180 call->jvms()->set_offsets(cnt);
181
182 // Set fixed predefined input arguments
183 cnt = 0;
184 for (i = 0; i < TypeFunc::Parms; i++)
185 call->init_req(cnt++, map()->in(i));
186 // A little too aggressive on the parm copy; return address is not an input
187 call->set_req(TypeFunc::ReturnAdr, top());
188 for (; i < parm_cnt; i++) { // Regular input arguments
189 // Convert ints to longs if required.
190 if (convert_ints_to_longs && jdomain->field_at(i)->isa_int()) {
191 Node* int_as_long = _gvn.transform(new (C) ConvI2LNode(map()->in(i)));
192 call->init_req(cnt++, int_as_long); // long
193 call->init_req(cnt++, top()); // half
194 } else {
195 call->init_req(cnt++, map()->in(i));
196 }
197 }
198
199 call->init_req( cnt++, thread );
200 if( return_pc ) // Return PC, if asked for
201 call->init_req( cnt++, returnadr() );
202 _gvn.transform_no_reclaim(call);
203
204
205 //-----------------------------
206 // Now set up the return results
207 set_control( _gvn.transform( new (C) ProjNode(call,TypeFunc::Control)) );
208 set_i_o( _gvn.transform( new (C) ProjNode(call,TypeFunc::I_O )) );
209 set_all_memory_call(call);
210 if (range->cnt() > TypeFunc::Parms) {
211 Node* retnode = _gvn.transform( new (C) ProjNode(call,TypeFunc::Parms) );
212 // C-land is allowed to return sub-word values. Convert to integer type.
213 assert( retval != Type::TOP, "" );
214 if (retval == TypeInt::BOOL) {
215 retnode = _gvn.transform( new (C) AndINode(retnode, intcon(0xFF)) );
216 } else if (retval == TypeInt::CHAR) {
217 retnode = _gvn.transform( new (C) AndINode(retnode, intcon(0xFFFF)) );
|