192 assert(is_signature_polymorphic(iid), "expected invoke iid");
193 if (iid == vmIntrinsics::_invokeGeneric ||
194 iid == vmIntrinsics::_compiledLambdaForm) {
195 // Perhaps surprisingly, the symbolic references visible to Java are not directly used.
196 // They are linked to Java-generated adapters via MethodHandleNatives.linkMethod.
197 // They all allow an appendix argument.
198 __ hlt(); // empty stubs make SG sick
199 return NULL;
200 }
201
202 // rsi/r13: sender SP (must preserve; see prepare_to_jump_from_interpreted)
203 // rbx: Method*
204 // rdx: argument locator (parameter slot count, added to rsp)
205 // rcx: used as temp to hold mh or receiver
206 // rax, rdi: garbage temps, blown away
207 Register rdx_argp = rdx; // argument list ptr, live on error paths
208 Register rax_temp = rax;
209 Register rcx_mh = rcx; // MH receiver; dies quickly and is recycled
210 Register rbx_method = rbx; // eventual target of this invocation
211
212 address code_start = __ pc();
213
214 // here's where control starts out:
215 __ align(CodeEntryAlignment);
216 address entry_point = __ pc();
217
218 if (VerifyMethodHandles) {
219 Label L;
220 BLOCK_COMMENT("verify_intrinsic_id {");
221 __ cmpb(Address(rbx_method, Method::intrinsic_id_offset_in_bytes()), (int) iid);
222 __ jcc(Assembler::equal, L);
223 if (iid == vmIntrinsics::_linkToVirtual ||
224 iid == vmIntrinsics::_linkToSpecial) {
225 // could do this for all kinds, but would explode assembly code size
226 trace_method_handle(_masm, "bad Method*::intrinsic_id");
227 }
228 __ STOP("bad Method*::intrinsic_id");
229 __ bind(L);
230 BLOCK_COMMENT("} verify_intrinsic_id");
231 }
232
233 // First task: Find out how big the argument list is.
234 Address rdx_first_arg_addr;
235 int ref_kind = signature_polymorphic_intrinsic_ref_kind(iid);
236 assert(ref_kind != 0 || iid == vmIntrinsics::_invokeBasic, "must be _invokeBasic or a linkTo intrinsic");
237 if (ref_kind == 0 || MethodHandles::ref_kind_has_receiver(ref_kind)) {
238 __ load_sized_value(rdx_argp,
239 Address(rbx_method, Method::size_of_parameters_offset()),
240 sizeof(u2), /*is_signed*/ false);
241 // assert(sizeof(u2) == sizeof(Method::_size_of_parameters), "");
242 rdx_first_arg_addr = __ argument_address(rdx_argp, -1);
243 } else {
244 DEBUG_ONLY(rdx_argp = noreg);
245 }
246
247 if (!is_signature_polymorphic_static(iid)) {
248 __ movptr(rcx_mh, rdx_first_arg_addr);
249 DEBUG_ONLY(rdx_argp = noreg);
250 }
251
252 // rdx_first_arg_addr is live!
253
254 if (TraceMethodHandles) {
255 const char* name = vmIntrinsics::name_at(iid);
256 if (*name == '_') name += 1;
257 const size_t len = strlen(name) + 50;
258 char* qname = NEW_C_HEAP_ARRAY(char, len, mtInternal);
259 const char* suffix = "";
260 if (vmIntrinsics::method_for(iid) == NULL ||
261 !vmIntrinsics::method_for(iid)->access_flags().is_public()) {
262 if (is_signature_polymorphic_static(iid))
263 suffix = "/static";
264 else
265 suffix = "/private";
266 }
267 jio_snprintf(qname, len, "MethodHandle::interpreter_entry::%s%s", name, suffix);
268 // note: stub look for mh in rcx
269 trace_method_handle(_masm, qname);
270 }
271
272 if (iid == vmIntrinsics::_invokeBasic) {
273 generate_method_handle_dispatch(_masm, iid, rcx_mh, noreg, not_for_compiler_entry);
274
275 } else {
276 // Adjust argument list by popping the trailing MemberName argument.
277 Register rcx_recv = noreg;
278 if (MethodHandles::ref_kind_has_receiver(ref_kind)) {
279 // Load the receiver (not the MH; the actual MemberName's receiver) up from the interpreter stack.
280 __ movptr(rcx_recv = rcx, rdx_first_arg_addr);
281 }
282 DEBUG_ONLY(rdx_argp = noreg);
283 Register rbx_member = rbx_method; // MemberName ptr; incoming method ptr is dead now
284 __ pop(rax_temp); // return address
285 __ pop(rbx_member); // extract last argument
286 __ push(rax_temp); // re-push return address
287 generate_method_handle_dispatch(_masm, iid, rcx_recv, rbx_member, not_for_compiler_entry);
288 }
289
290 if (PrintMethodHandleStubs) {
291 address code_end = __ pc();
292 tty->print_cr("--------");
293 tty->print_cr("method handle interpreter entry for %s", vmIntrinsics::name_at(iid));
294 Disassembler::decode(code_start, code_end);
295 tty->cr();
296 }
297
298 return entry_point;
299 }
300
301 void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm,
302 vmIntrinsics::ID iid,
303 Register receiver_reg,
304 Register member_reg,
305 bool for_compiler_entry) {
306 assert(is_signature_polymorphic(iid), "expected invoke iid");
307 Register rbx_method = rbx; // eventual target of this invocation
308 // temps used in this code are not used in *either* compiled or interpreted calling sequences
309 #ifdef _LP64
310 Register temp1 = rscratch1;
311 Register temp2 = rscratch2;
312 Register temp3 = rax;
313 if (for_compiler_entry) {
314 assert(receiver_reg == (iid == vmIntrinsics::_linkToStatic ? noreg : j_rarg0), "only valid assignment");
315 assert_different_registers(temp1, j_rarg0, j_rarg1, j_rarg2, j_rarg3, j_rarg4, j_rarg5);
316 assert_different_registers(temp2, j_rarg0, j_rarg1, j_rarg2, j_rarg3, j_rarg4, j_rarg5);
317 assert_different_registers(temp3, j_rarg0, j_rarg1, j_rarg2, j_rarg3, j_rarg4, j_rarg5);
|
192 assert(is_signature_polymorphic(iid), "expected invoke iid");
193 if (iid == vmIntrinsics::_invokeGeneric ||
194 iid == vmIntrinsics::_compiledLambdaForm) {
195 // Perhaps surprisingly, the symbolic references visible to Java are not directly used.
196 // They are linked to Java-generated adapters via MethodHandleNatives.linkMethod.
197 // They all allow an appendix argument.
198 __ hlt(); // empty stubs make SG sick
199 return NULL;
200 }
201
202 // rsi/r13: sender SP (must preserve; see prepare_to_jump_from_interpreted)
203 // rbx: Method*
204 // rdx: argument locator (parameter slot count, added to rsp)
205 // rcx: used as temp to hold mh or receiver
206 // rax, rdi: garbage temps, blown away
207 Register rdx_argp = rdx; // argument list ptr, live on error paths
208 Register rax_temp = rax;
209 Register rcx_mh = rcx; // MH receiver; dies quickly and is recycled
210 Register rbx_method = rbx; // eventual target of this invocation
211
212 // here's where control starts out:
213 __ align(CodeEntryAlignment);
214 address entry_point = __ pc();
215
216 if (VerifyMethodHandles) {
217 Label L;
218 BLOCK_COMMENT("verify_intrinsic_id {");
219 __ cmpb(Address(rbx_method, Method::intrinsic_id_offset_in_bytes()), (int) iid);
220 __ jcc(Assembler::equal, L);
221 if (iid == vmIntrinsics::_linkToVirtual ||
222 iid == vmIntrinsics::_linkToSpecial) {
223 // could do this for all kinds, but would explode assembly code size
224 trace_method_handle(_masm, "bad Method*::intrinsic_id");
225 }
226 __ STOP("bad Method*::intrinsic_id");
227 __ bind(L);
228 BLOCK_COMMENT("} verify_intrinsic_id");
229 }
230
231 // First task: Find out how big the argument list is.
232 Address rdx_first_arg_addr;
233 int ref_kind = signature_polymorphic_intrinsic_ref_kind(iid);
234 assert(ref_kind != 0 || iid == vmIntrinsics::_invokeBasic, "must be _invokeBasic or a linkTo intrinsic");
235 if (ref_kind == 0 || MethodHandles::ref_kind_has_receiver(ref_kind)) {
236 __ load_sized_value(rdx_argp,
237 Address(rbx_method, Method::size_of_parameters_offset()),
238 sizeof(u2), /*is_signed*/ false);
239 // assert(sizeof(u2) == sizeof(Method::_size_of_parameters), "");
240 rdx_first_arg_addr = __ argument_address(rdx_argp, -1);
241 } else {
242 DEBUG_ONLY(rdx_argp = noreg);
243 }
244
245 if (!is_signature_polymorphic_static(iid)) {
246 __ movptr(rcx_mh, rdx_first_arg_addr);
247 DEBUG_ONLY(rdx_argp = noreg);
248 }
249
250 // rdx_first_arg_addr is live!
251
252 trace_method_handle_interpreter_entry(_masm, iid);
253
254 if (iid == vmIntrinsics::_invokeBasic) {
255 generate_method_handle_dispatch(_masm, iid, rcx_mh, noreg, not_for_compiler_entry);
256
257 } else {
258 // Adjust argument list by popping the trailing MemberName argument.
259 Register rcx_recv = noreg;
260 if (MethodHandles::ref_kind_has_receiver(ref_kind)) {
261 // Load the receiver (not the MH; the actual MemberName's receiver) up from the interpreter stack.
262 __ movptr(rcx_recv = rcx, rdx_first_arg_addr);
263 }
264 DEBUG_ONLY(rdx_argp = noreg);
265 Register rbx_member = rbx_method; // MemberName ptr; incoming method ptr is dead now
266 __ pop(rax_temp); // return address
267 __ pop(rbx_member); // extract last argument
268 __ push(rax_temp); // re-push return address
269 generate_method_handle_dispatch(_masm, iid, rcx_recv, rbx_member, not_for_compiler_entry);
270 }
271
272 return entry_point;
273 }
274
275 void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm,
276 vmIntrinsics::ID iid,
277 Register receiver_reg,
278 Register member_reg,
279 bool for_compiler_entry) {
280 assert(is_signature_polymorphic(iid), "expected invoke iid");
281 Register rbx_method = rbx; // eventual target of this invocation
282 // temps used in this code are not used in *either* compiled or interpreted calling sequences
283 #ifdef _LP64
284 Register temp1 = rscratch1;
285 Register temp2 = rscratch2;
286 Register temp3 = rax;
287 if (for_compiler_entry) {
288 assert(receiver_reg == (iid == vmIntrinsics::_linkToStatic ? noreg : j_rarg0), "only valid assignment");
289 assert_different_registers(temp1, j_rarg0, j_rarg1, j_rarg2, j_rarg3, j_rarg4, j_rarg5);
290 assert_different_registers(temp2, j_rarg0, j_rarg1, j_rarg2, j_rarg3, j_rarg4, j_rarg5);
291 assert_different_registers(temp3, j_rarg0, j_rarg1, j_rarg2, j_rarg3, j_rarg4, j_rarg5);
|