134 // And dump it back to the caller, decorated with any exceptions: |
134 // And dump it back to the caller, decorated with any exceptions: |
135 return kit.transfer_exceptions_into_jvms(); |
135 return kit.transfer_exceptions_into_jvms(); |
136 } |
136 } |
137 // Mark the call node as virtual, sort of: |
137 // Mark the call node as virtual, sort of: |
138 call->set_optimized_virtual(true); |
138 call->set_optimized_virtual(true); |
|
139 if (method()->is_method_handle_invoke()) |
|
140 call->set_method_handle_invoke(true); |
139 } |
141 } |
140 kit.set_arguments_for_java_call(call); |
142 kit.set_arguments_for_java_call(call); |
141 kit.set_edges_for_java_call(call, false, _separate_io_proj); |
143 kit.set_edges_for_java_call(call, false, _separate_io_proj); |
142 Node* ret = kit.set_results_for_java_call(call, _separate_io_proj); |
144 Node* ret = kit.set_results_for_java_call(call, _separate_io_proj); |
143 kit.push_node(method()->return_type()->basic_type(), ret); |
145 kit.push_node(method()->return_type()->basic_type(), ret); |
144 _call_node = call; // Save the call node in case we need it later |
146 _call_node = call; // Save the call node in case we need it later |
145 return kit.transfer_exceptions_into_jvms(); |
147 return kit.transfer_exceptions_into_jvms(); |
146 } |
148 } |
147 |
149 |
|
150 //---------------------------DynamicCallGenerator----------------------------- |
|
151 // Internal class which handles all out-of-line dynamic calls. |
|
152 class DynamicCallGenerator : public CallGenerator { |
|
153 public: |
|
154 DynamicCallGenerator(ciMethod* method) |
|
155 : CallGenerator(method) |
|
156 { |
|
157 } |
|
158 virtual JVMState* generate(JVMState* jvms); |
|
159 }; |
|
160 |
|
161 JVMState* DynamicCallGenerator::generate(JVMState* jvms) { |
|
162 GraphKit kit(jvms); |
|
163 |
|
164 if (kit.C->log() != NULL) { |
|
165 kit.C->log()->elem("dynamic_call bci='%d'", jvms->bci()); |
|
166 } |
|
167 |
|
168 // Get the constant pool cache from the caller class. |
|
169 ciMethod* caller_method = jvms->method(); |
|
170 ciBytecodeStream str(caller_method); |
|
171 str.force_bci(jvms->bci()); // Set the stream to the invokedynamic bci. |
|
172 assert(str.cur_bc() == Bytecodes::_invokedynamic, "wrong place to issue a dynamic call!"); |
|
173 ciCPCache* cpcache = str.get_cpcache(); |
|
174 |
|
175 // Get the offset of the CallSite from the constant pool cache |
|
176 // pointer. |
|
177 int index = str.get_method_index(); |
|
178 size_t call_site_offset = cpcache->get_f1_offset(index); |
|
179 |
|
180 // Load the CallSite object from the constant pool cache. |
|
181 const TypeOopPtr* cpcache_ptr = TypeOopPtr::make_from_constant(cpcache); |
|
182 Node* cpc = kit.makecon(cpcache_ptr); |
|
183 Node* adr = kit.basic_plus_adr(cpc, cpc, call_site_offset); |
|
184 Node* call_site = kit.make_load(kit.control(), adr, TypeInstPtr::BOTTOM, T_OBJECT, Compile::AliasIdxRaw); |
|
185 |
|
186 // Load the MethodHandle (target) from the CallSite object. |
|
187 Node* mh_adr = kit.basic_plus_adr(call_site, call_site, java_dyn_CallSite::target_offset_in_bytes()); |
|
188 Node* mh = kit.make_load(kit.control(), mh_adr, TypeInstPtr::BOTTOM, T_OBJECT); |
|
189 |
|
190 address stub = SharedRuntime::get_resolve_opt_virtual_call_stub(); |
|
191 |
|
192 CallStaticJavaNode *call = new (kit.C, tf()->domain()->cnt()) CallStaticJavaNode(tf(), stub, method(), kit.bci()); |
|
193 // invokedynamic is treated as an optimized invokevirtual. |
|
194 call->set_optimized_virtual(true); |
|
195 // Take extra care (in the presence of argument motion) not to trash the SP: |
|
196 call->set_method_handle_invoke(true); |
|
197 |
|
198 // Pass the MethodHandle as first argument and shift the other |
|
199 // arguments. |
|
200 call->init_req(0 + TypeFunc::Parms, mh); |
|
201 uint nargs = call->method()->arg_size(); |
|
202 for (uint i = 1; i < nargs; i++) { |
|
203 Node* arg = kit.argument(i - 1); |
|
204 call->init_req(i + TypeFunc::Parms, arg); |
|
205 } |
|
206 |
|
207 kit.set_edges_for_java_call(call); |
|
208 Node* ret = kit.set_results_for_java_call(call); |
|
209 kit.push_node(method()->return_type()->basic_type(), ret); |
|
210 return kit.transfer_exceptions_into_jvms(); |
|
211 } |
|
212 |
|
213 //--------------------------VirtualCallGenerator------------------------------ |
|
214 // Internal class which handles all out-of-line calls checking receiver type. |
148 class VirtualCallGenerator : public CallGenerator { |
215 class VirtualCallGenerator : public CallGenerator { |
149 private: |
216 private: |
150 int _vtable_index; |
217 int _vtable_index; |
151 public: |
218 public: |
152 VirtualCallGenerator(ciMethod* method, int vtable_index) |
219 VirtualCallGenerator(ciMethod* method, int vtable_index) |
251 CallGenerator* CallGenerator::for_direct_call(ciMethod* m, bool separate_io_proj) { |
316 CallGenerator* CallGenerator::for_direct_call(ciMethod* m, bool separate_io_proj) { |
252 assert(!m->is_abstract(), "for_direct_call mismatch"); |
317 assert(!m->is_abstract(), "for_direct_call mismatch"); |
253 return new DirectCallGenerator(m, separate_io_proj); |
318 return new DirectCallGenerator(m, separate_io_proj); |
254 } |
319 } |
255 |
320 |
|
321 CallGenerator* CallGenerator::for_dynamic_call(ciMethod* m) { |
|
322 assert(m->is_method_handle_invoke(), "for_dynamic_call mismatch"); |
|
323 return new DynamicCallGenerator(m); |
|
324 } |
|
325 |
256 CallGenerator* CallGenerator::for_virtual_call(ciMethod* m, int vtable_index) { |
326 CallGenerator* CallGenerator::for_virtual_call(ciMethod* m, int vtable_index) { |
257 assert(!m->is_static(), "for_virtual_call mismatch"); |
327 assert(!m->is_static(), "for_virtual_call mismatch"); |
|
328 assert(!m->is_method_handle_invoke(), "should be a direct call"); |
258 return new VirtualCallGenerator(m, vtable_index); |
329 return new VirtualCallGenerator(m, vtable_index); |
259 } |
330 } |
260 |
331 |
261 // Allow inlining decisions to be delayed |
332 // Allow inlining decisions to be delayed |
262 class LateInlineCallGenerator : public DirectCallGenerator { |
333 class LateInlineCallGenerator : public DirectCallGenerator { |