1.1 --- a/src/cpu/x86/vm/templateTable_x86_32.cpp Mon Jul 23 13:04:59 2012 -0700 1.2 +++ b/src/cpu/x86/vm/templateTable_x86_32.cpp Tue Jul 24 10:51:00 2012 -0700 1.3 @@ -446,13 +446,13 @@ 1.4 const Register cache = rcx; 1.5 const Register index = rdx; 1.6 1.7 - resolve_cache_and_index(f1_oop, rax, cache, index, wide ? sizeof(u2) : sizeof(u1)); 1.8 + resolve_cache_and_index(f12_oop, rax, cache, index, wide ? sizeof(u2) : sizeof(u1)); 1.9 if (VerifyOops) { 1.10 __ verify_oop(rax); 1.11 } 1.12 1.13 Label L_done, L_throw_exception; 1.14 - const Register con_klass_temp = rcx; // same as Rcache 1.15 + const Register con_klass_temp = rcx; // same as cache 1.16 __ load_klass(con_klass_temp, rax); 1.17 __ cmpptr(con_klass_temp, ExternalAddress((address)Universe::systemObjArrayKlassObj_addr())); 1.18 __ jcc(Assembler::notEqual, L_done); 1.19 @@ -2084,15 +2084,15 @@ 1.20 Register Rcache, 1.21 Register index, 1.22 size_t index_size) { 1.23 - Register temp = rbx; 1.24 - 1.25 + const Register temp = rbx; 1.26 assert_different_registers(result, Rcache, index, temp); 1.27 1.28 Label resolved; 1.29 - if (byte_no == f1_oop) { 1.30 - // We are resolved if the f1 field contains a non-null object (CallSite, etc.) 1.31 - // This kind of CP cache entry does not need to match the flags byte, because 1.32 + if (byte_no == f12_oop) { 1.33 + // We are resolved if the f1 field contains a non-null object (CallSite, MethodType, etc.) 1.34 + // This kind of CP cache entry does not need to match bytecode_1 or bytecode_2, because 1.35 // there is a 1-1 relation between bytecode type and CP entry type. 1.36 + // The caller will also load a methodOop from f2. 1.37 assert(result != noreg, ""); //else do cmpptr(Address(...), (int32_t) NULL_WORD) 1.38 __ get_cache_and_index_at_bcp(Rcache, index, 1, index_size); 1.39 __ movptr(result, Address(Rcache, index, Address::times_ptr, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::f1_offset())); 1.40 @@ -2112,15 +2112,18 @@ 1.41 case Bytecodes::_getstatic : // fall through 1.42 case Bytecodes::_putstatic : // fall through 1.43 case Bytecodes::_getfield : // fall through 1.44 - case Bytecodes::_putfield : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_get_put); break; 1.45 + case Bytecodes::_putfield : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_get_put); break; 1.46 case Bytecodes::_invokevirtual : // fall through 1.47 case Bytecodes::_invokespecial : // fall through 1.48 case Bytecodes::_invokestatic : // fall through 1.49 - case Bytecodes::_invokeinterface: entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke); break; 1.50 - case Bytecodes::_invokedynamic : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic); break; 1.51 - case Bytecodes::_fast_aldc : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc); break; 1.52 - case Bytecodes::_fast_aldc_w : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc); break; 1.53 - default : ShouldNotReachHere(); break; 1.54 + case Bytecodes::_invokeinterface: entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke); break; 1.55 + case Bytecodes::_invokehandle : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokehandle); break; 1.56 + case Bytecodes::_invokedynamic : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic); break; 1.57 + case Bytecodes::_fast_aldc : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc); break; 1.58 + case Bytecodes::_fast_aldc_w : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc); break; 1.59 + default: 1.60 + fatal(err_msg("unexpected bytecode: %s", Bytecodes::name(bytecode()))); 1.61 + break; 1.62 } 1.63 __ movl(temp, (int)bytecode()); 1.64 __ call_VM(noreg, entry, temp); 1.65 @@ -2149,7 +2152,7 @@ 1.66 __ movl(flags, Address(cache, index, Address::times_ptr, 1.67 in_bytes(cp_base_offset + ConstantPoolCacheEntry::flags_offset()))); 1.68 1.69 - // klass overwrite register 1.70 + // klass overwrite register 1.71 if (is_static) { 1.72 __ movptr(obj, Address(cache, index, Address::times_ptr, 1.73 in_bytes(cp_base_offset + ConstantPoolCacheEntry::f1_offset()))); 1.74 @@ -2161,7 +2164,7 @@ 1.75 Register itable_index, 1.76 Register flags, 1.77 bool is_invokevirtual, 1.78 - bool is_invokevfinal /*unused*/, 1.79 + bool is_invokevfinal, /*unused*/ 1.80 bool is_invokedynamic) { 1.81 // setup registers 1.82 const Register cache = rcx; 1.83 @@ -2171,28 +2174,33 @@ 1.84 assert_different_registers(itable_index, flags); 1.85 assert_different_registers(itable_index, cache, index); 1.86 // determine constant pool cache field offsets 1.87 + assert(is_invokevirtual == (byte_no == f2_byte), "is_invokevirtual flag redundant"); 1.88 const int method_offset = in_bytes( 1.89 constantPoolCacheOopDesc::base_offset() + 1.90 - (is_invokevirtual 1.91 + ((byte_no == f2_byte) 1.92 ? ConstantPoolCacheEntry::f2_offset() 1.93 - : ConstantPoolCacheEntry::f1_offset() 1.94 - ) 1.95 - ); 1.96 + : ConstantPoolCacheEntry::f1_offset())); 1.97 const int flags_offset = in_bytes(constantPoolCacheOopDesc::base_offset() + 1.98 ConstantPoolCacheEntry::flags_offset()); 1.99 // access constant pool cache fields 1.100 const int index_offset = in_bytes(constantPoolCacheOopDesc::base_offset() + 1.101 ConstantPoolCacheEntry::f2_offset()); 1.102 1.103 - if (byte_no == f1_oop) { 1.104 - // Resolved f1_oop goes directly into 'method' register. 1.105 - assert(is_invokedynamic, ""); 1.106 - resolve_cache_and_index(byte_no, method, cache, index, sizeof(u4)); 1.107 + if (byte_no == f12_oop) { 1.108 + // Resolved f1_oop (CallSite, MethodType, etc.) goes into 'itable_index'. 1.109 + // Resolved f2_oop (methodOop invoker) will go into 'method' (at index_offset). 1.110 + // See ConstantPoolCacheEntry::set_dynamic_call and set_method_handle. 1.111 + size_t index_size = (is_invokedynamic ? sizeof(u4) : sizeof(u2)); 1.112 + resolve_cache_and_index(byte_no, itable_index, cache, index, index_size); 1.113 + __ movptr(method, Address(cache, index, Address::times_ptr, index_offset)); 1.114 + itable_index = noreg; // hack to disable load below 1.115 } else { 1.116 resolve_cache_and_index(byte_no, noreg, cache, index, sizeof(u2)); 1.117 __ movptr(method, Address(cache, index, Address::times_ptr, method_offset)); 1.118 } 1.119 if (itable_index != noreg) { 1.120 + // pick up itable index from f2 also: 1.121 + assert(byte_no == f1_byte, "already picked up f1"); 1.122 __ movptr(itable_index, Address(cache, index, Address::times_ptr, index_offset)); 1.123 } 1.124 __ movl(flags, Address(cache, index, Address::times_ptr, flags_offset)); 1.125 @@ -2260,10 +2268,10 @@ 1.126 1.127 Label Done, notByte, notInt, notShort, notChar, notLong, notFloat, notObj, notDouble; 1.128 1.129 - __ shrl(flags, ConstantPoolCacheEntry::tosBits); 1.130 + __ shrl(flags, ConstantPoolCacheEntry::tos_state_shift); 1.131 assert(btos == 0, "change code, btos != 0"); 1.132 // btos 1.133 - __ andptr(flags, 0x0f); 1.134 + __ andptr(flags, ConstantPoolCacheEntry::tos_state_mask); 1.135 __ jcc(Assembler::notZero, notByte); 1.136 1.137 __ load_signed_byte(rax, lo ); 1.138 @@ -2415,9 +2423,9 @@ 1.139 __ movl(rcx, Address(rax, rdx, Address::times_ptr, in_bytes(cp_base_offset + 1.140 ConstantPoolCacheEntry::flags_offset()))); 1.141 __ mov(rbx, rsp); 1.142 - __ shrl(rcx, ConstantPoolCacheEntry::tosBits); 1.143 - // Make sure we don't need to mask rcx for tosBits after the above shift 1.144 - ConstantPoolCacheEntry::verify_tosBits(); 1.145 + __ shrl(rcx, ConstantPoolCacheEntry::tos_state_shift); 1.146 + // Make sure we don't need to mask rcx after the above shift 1.147 + ConstantPoolCacheEntry::verify_tos_state_shift(); 1.148 __ cmpl(rcx, ltos); 1.149 __ jccb(Assembler::equal, two_word); 1.150 __ cmpl(rcx, dtos); 1.151 @@ -2467,7 +2475,7 @@ 1.152 1.153 Label notVolatile, Done; 1.154 __ movl(rdx, flags); 1.155 - __ shrl(rdx, ConstantPoolCacheEntry::volatileField); 1.156 + __ shrl(rdx, ConstantPoolCacheEntry::is_volatile_shift); 1.157 __ andl(rdx, 0x1); 1.158 1.159 // field addresses 1.160 @@ -2476,9 +2484,9 @@ 1.161 1.162 Label notByte, notInt, notShort, notChar, notLong, notFloat, notObj, notDouble; 1.163 1.164 - __ shrl(flags, ConstantPoolCacheEntry::tosBits); 1.165 + __ shrl(flags, ConstantPoolCacheEntry::tos_state_shift); 1.166 assert(btos == 0, "change code, btos != 0"); 1.167 - __ andl(flags, 0x0f); 1.168 + __ andl(flags, ConstantPoolCacheEntry::tos_state_mask); 1.169 __ jcc(Assembler::notZero, notByte); 1.170 1.171 // btos 1.172 @@ -2719,7 +2727,7 @@ 1.173 // volatile_barrier( ); 1.174 1.175 Label notVolatile, Done; 1.176 - __ shrl(rdx, ConstantPoolCacheEntry::volatileField); 1.177 + __ shrl(rdx, ConstantPoolCacheEntry::is_volatile_shift); 1.178 __ andl(rdx, 0x1); 1.179 // Check for volatile store 1.180 __ testl(rdx, rdx); 1.181 @@ -2885,19 +2893,29 @@ 1.182 } 1.183 1.184 1.185 -void TemplateTable::prepare_invoke(Register method, Register index, int byte_no) { 1.186 +void TemplateTable::prepare_invoke(int byte_no, 1.187 + Register method, // linked method (or i-klass) 1.188 + Register index, // itable index, MethodType, etc. 1.189 + Register recv, // if caller wants to see it 1.190 + Register flags // if caller wants to test it 1.191 + ) { 1.192 // determine flags 1.193 - Bytecodes::Code code = bytecode(); 1.194 + const Bytecodes::Code code = bytecode(); 1.195 const bool is_invokeinterface = code == Bytecodes::_invokeinterface; 1.196 const bool is_invokedynamic = code == Bytecodes::_invokedynamic; 1.197 + const bool is_invokehandle = code == Bytecodes::_invokehandle; 1.198 const bool is_invokevirtual = code == Bytecodes::_invokevirtual; 1.199 const bool is_invokespecial = code == Bytecodes::_invokespecial; 1.200 - const bool load_receiver = (code != Bytecodes::_invokestatic && code != Bytecodes::_invokedynamic); 1.201 - const bool receiver_null_check = is_invokespecial; 1.202 - const bool save_flags = is_invokeinterface || is_invokevirtual; 1.203 + const bool load_receiver = (recv != noreg); 1.204 + const bool save_flags = (flags != noreg); 1.205 + assert(load_receiver == (code != Bytecodes::_invokestatic && code != Bytecodes::_invokedynamic), ""); 1.206 + assert(save_flags == (is_invokeinterface || is_invokevirtual), "need flags for vfinal"); 1.207 + assert(flags == noreg || flags == rdx, ""); 1.208 + assert(recv == noreg || recv == rcx, ""); 1.209 + 1.210 // setup registers & access constant pool cache 1.211 - const Register recv = rcx; 1.212 - const Register flags = rdx; 1.213 + if (recv == noreg) recv = rcx; 1.214 + if (flags == noreg) flags = rdx; 1.215 assert_different_registers(method, index, recv, flags); 1.216 1.217 // save 'interpreter return address' 1.218 @@ -2905,37 +2923,43 @@ 1.219 1.220 load_invoke_cp_cache_entry(byte_no, method, index, flags, is_invokevirtual, false, is_invokedynamic); 1.221 1.222 + // maybe push appendix to arguments (just before return address) 1.223 + if (is_invokedynamic || is_invokehandle) { 1.224 + Label L_no_push; 1.225 + __ verify_oop(index); 1.226 + __ testl(flags, (1 << ConstantPoolCacheEntry::has_appendix_shift)); 1.227 + __ jccb(Assembler::zero, L_no_push); 1.228 + // Push the appendix as a trailing parameter. 1.229 + // This must be done before we get the receiver, 1.230 + // since the parameter_size includes it. 1.231 + __ push(index); // push appendix (MethodType, CallSite, etc.) 1.232 + __ bind(L_no_push); 1.233 + } 1.234 + 1.235 // load receiver if needed (note: no return address pushed yet) 1.236 if (load_receiver) { 1.237 - assert(!is_invokedynamic, ""); 1.238 __ movl(recv, flags); 1.239 - __ andl(recv, 0xFF); 1.240 - // recv count is 0 based? 1.241 - Address recv_addr(rsp, recv, Interpreter::stackElementScale(), -Interpreter::expr_offset_in_bytes(1)); 1.242 + __ andl(recv, ConstantPoolCacheEntry::parameter_size_mask); 1.243 + const int no_return_pc_pushed_yet = -1; // argument slot correction before we push return address 1.244 + const int receiver_is_at_end = -1; // back off one slot to get receiver 1.245 + Address recv_addr = __ argument_address(recv, no_return_pc_pushed_yet + receiver_is_at_end); 1.246 __ movptr(recv, recv_addr); 1.247 __ verify_oop(recv); 1.248 } 1.249 1.250 - // do null check if needed 1.251 - if (receiver_null_check) { 1.252 - __ null_check(recv); 1.253 - } 1.254 - 1.255 if (save_flags) { 1.256 __ mov(rsi, flags); 1.257 } 1.258 1.259 // compute return type 1.260 - __ shrl(flags, ConstantPoolCacheEntry::tosBits); 1.261 - // Make sure we don't need to mask flags for tosBits after the above shift 1.262 - ConstantPoolCacheEntry::verify_tosBits(); 1.263 + __ shrl(flags, ConstantPoolCacheEntry::tos_state_shift); 1.264 + // Make sure we don't need to mask flags after the above shift 1.265 + ConstantPoolCacheEntry::verify_tos_state_shift(); 1.266 // load return address 1.267 { 1.268 - address table_addr; 1.269 - if (is_invokeinterface || is_invokedynamic) 1.270 - table_addr = (address)Interpreter::return_5_addrs_by_index_table(); 1.271 - else 1.272 - table_addr = (address)Interpreter::return_3_addrs_by_index_table(); 1.273 + const address table_addr = (is_invokeinterface || is_invokedynamic) ? 1.274 + (address)Interpreter::return_5_addrs_by_index_table() : 1.275 + (address)Interpreter::return_3_addrs_by_index_table(); 1.276 ExternalAddress table(table_addr); 1.277 __ movptr(flags, ArrayAddress(table, Address(noreg, flags, Address::times_ptr))); 1.278 } 1.279 @@ -2943,7 +2967,7 @@ 1.280 // push return address 1.281 __ push(flags); 1.282 1.283 - // Restore flag value from the constant pool cache, and restore rsi 1.284 + // Restore flags value from the constant pool cache, and restore rsi 1.285 // for later null checks. rsi is the bytecode pointer 1.286 if (save_flags) { 1.287 __ mov(flags, rsi); 1.288 @@ -2952,22 +2976,26 @@ 1.289 } 1.290 1.291 1.292 -void TemplateTable::invokevirtual_helper(Register index, Register recv, 1.293 - Register flags) { 1.294 - 1.295 +void TemplateTable::invokevirtual_helper(Register index, 1.296 + Register recv, 1.297 + Register flags) { 1.298 // Uses temporary registers rax, rdx 1.299 assert_different_registers(index, recv, rax, rdx); 1.300 + assert(index == rbx, ""); 1.301 + assert(recv == rcx, ""); 1.302 1.303 // Test for an invoke of a final method 1.304 Label notFinal; 1.305 __ movl(rax, flags); 1.306 - __ andl(rax, (1 << ConstantPoolCacheEntry::vfinalMethod)); 1.307 + __ andl(rax, (1 << ConstantPoolCacheEntry::is_vfinal_shift)); 1.308 __ jcc(Assembler::zero, notFinal); 1.309 1.310 - Register method = index; // method must be rbx, 1.311 - assert(method == rbx, "methodOop must be rbx, for interpreter calling convention"); 1.312 + const Register method = index; // method must be rbx 1.313 + assert(method == rbx, 1.314 + "methodOop must be rbx for interpreter calling convention"); 1.315 1.316 // do the call - the index is actually the method to call 1.317 + // that is, f2 is a vtable index if !is_vfinal, else f2 is a methodOop 1.318 __ verify_oop(method); 1.319 1.320 // It's final, need a null check here! 1.321 @@ -2982,7 +3010,6 @@ 1.322 1.323 // get receiver klass 1.324 __ null_check(recv, oopDesc::klass_offset_in_bytes()); 1.325 - // Keep recv in rcx for callee expects it there 1.326 __ load_klass(rax, recv); 1.327 __ verify_oop(rax); 1.328 1.329 @@ -2990,9 +3017,7 @@ 1.330 __ profile_virtual_call(rax, rdi, rdx); 1.331 1.332 // get target methodOop & entry point 1.333 - const int base = instanceKlass::vtable_start_offset() * wordSize; 1.334 - assert(vtableEntry::size() * wordSize == 4, "adjust the scaling in the code below"); 1.335 - __ movptr(method, Address(rax, index, Address::times_ptr, base + vtableEntry::method_offset_in_bytes())); 1.336 + __ lookup_virtual_method(rax, index, method); 1.337 __ jump_from_interpreted(method, rdx); 1.338 } 1.339 1.340 @@ -3000,9 +3025,12 @@ 1.341 void TemplateTable::invokevirtual(int byte_no) { 1.342 transition(vtos, vtos); 1.343 assert(byte_no == f2_byte, "use this argument"); 1.344 - prepare_invoke(rbx, noreg, byte_no); 1.345 - 1.346 - // rbx,: index 1.347 + prepare_invoke(byte_no, 1.348 + rbx, // method or vtable index 1.349 + noreg, // unused itable index 1.350 + rcx, rdx); // recv, flags 1.351 + 1.352 + // rbx: index 1.353 // rcx: receiver 1.354 // rdx: flags 1.355 1.356 @@ -3013,7 +3041,10 @@ 1.357 void TemplateTable::invokespecial(int byte_no) { 1.358 transition(vtos, vtos); 1.359 assert(byte_no == f1_byte, "use this argument"); 1.360 - prepare_invoke(rbx, noreg, byte_no); 1.361 + prepare_invoke(byte_no, rbx, noreg, // get f1 methodOop 1.362 + rcx); // get receiver also for null check 1.363 + __ verify_oop(rcx); 1.364 + __ null_check(rcx); 1.365 // do the call 1.366 __ verify_oop(rbx); 1.367 __ profile_call(rax); 1.368 @@ -3024,7 +3055,7 @@ 1.369 void TemplateTable::invokestatic(int byte_no) { 1.370 transition(vtos, vtos); 1.371 assert(byte_no == f1_byte, "use this argument"); 1.372 - prepare_invoke(rbx, noreg, byte_no); 1.373 + prepare_invoke(byte_no, rbx); // get f1 methodOop 1.374 // do the call 1.375 __ verify_oop(rbx); 1.376 __ profile_call(rax); 1.377 @@ -3042,10 +3073,11 @@ 1.378 void TemplateTable::invokeinterface(int byte_no) { 1.379 transition(vtos, vtos); 1.380 assert(byte_no == f1_byte, "use this argument"); 1.381 - prepare_invoke(rax, rbx, byte_no); 1.382 - 1.383 - // rax,: Interface 1.384 - // rbx,: index 1.385 + prepare_invoke(byte_no, rax, rbx, // get f1 klassOop, f2 itable index 1.386 + rcx, rdx); // recv, flags 1.387 + 1.388 + // rax: interface klass (from f1) 1.389 + // rbx: itable index (from f2) 1.390 // rcx: receiver 1.391 // rdx: flags 1.392 1.393 @@ -3055,7 +3087,7 @@ 1.394 // another compliant java compiler. 1.395 Label notMethod; 1.396 __ movl(rdi, rdx); 1.397 - __ andl(rdi, (1 << ConstantPoolCacheEntry::methodInterface)); 1.398 + __ andl(rdi, (1 << ConstantPoolCacheEntry::is_forced_virtual_shift)); 1.399 __ jcc(Assembler::zero, notMethod); 1.400 1.401 invokevirtual_helper(rbx, rcx, rdx); 1.402 @@ -3063,6 +3095,7 @@ 1.403 1.404 // Get receiver klass into rdx - also a null check 1.405 __ restore_locals(); // restore rdi 1.406 + __ null_check(rcx, oopDesc::klass_offset_in_bytes()); 1.407 __ load_klass(rdx, rcx); 1.408 __ verify_oop(rdx); 1.409 1.410 @@ -3077,7 +3110,7 @@ 1.411 rbx, rsi, 1.412 no_such_interface); 1.413 1.414 - // rbx,: methodOop to call 1.415 + // rbx: methodOop to call 1.416 // rcx: receiver 1.417 // Check for abstract method error 1.418 // Note: This should be done more efficiently via a throw_abstract_method_error 1.419 @@ -3116,9 +3149,39 @@ 1.420 __ should_not_reach_here(); 1.421 } 1.422 1.423 +void TemplateTable::invokehandle(int byte_no) { 1.424 + transition(vtos, vtos); 1.425 + assert(byte_no == f12_oop, "use this argument"); 1.426 + const Register rbx_method = rbx; // (from f2) 1.427 + const Register rax_mtype = rax; // (from f1) 1.428 + const Register rcx_recv = rcx; 1.429 + const Register rdx_flags = rdx; 1.430 + 1.431 + if (!EnableInvokeDynamic) { 1.432 + // rewriter does not generate this bytecode 1.433 + __ should_not_reach_here(); 1.434 + return; 1.435 + } 1.436 + 1.437 + prepare_invoke(byte_no, 1.438 + rbx_method, rax_mtype, // get f2 methodOop, f1 MethodType 1.439 + rcx_recv); 1.440 + __ verify_oop(rbx_method); 1.441 + __ verify_oop(rcx_recv); 1.442 + __ null_check(rcx_recv); 1.443 + 1.444 + // Note: rax_mtype is already pushed (if necessary) by prepare_invoke 1.445 + 1.446 + // FIXME: profile the LambdaForm also 1.447 + __ profile_final_call(rax); 1.448 + 1.449 + __ jump_from_interpreted(rbx_method, rdx); 1.450 +} 1.451 + 1.452 + 1.453 void TemplateTable::invokedynamic(int byte_no) { 1.454 transition(vtos, vtos); 1.455 - assert(byte_no == f1_oop, "use this argument"); 1.456 + assert(byte_no == f12_oop, "use this argument"); 1.457 1.458 if (!EnableInvokeDynamic) { 1.459 // We should not encounter this bytecode if !EnableInvokeDynamic. 1.460 @@ -3131,26 +3194,23 @@ 1.461 return; 1.462 } 1.463 1.464 - prepare_invoke(rax, rbx, byte_no); 1.465 - 1.466 - // rax: CallSite object (f1) 1.467 - // rbx: unused (f2) 1.468 - // rcx: receiver address 1.469 - // rdx: flags (unused) 1.470 - 1.471 - Register rax_callsite = rax; 1.472 - Register rcx_method_handle = rcx; 1.473 + const Register rbx_method = rbx; 1.474 + const Register rax_callsite = rax; 1.475 + 1.476 + prepare_invoke(byte_no, rbx_method, rax_callsite); 1.477 + 1.478 + // rax: CallSite object (from f1) 1.479 + // rbx: MH.linkToCallSite method (from f2) 1.480 + 1.481 + // Note: rax_callsite is already pushed by prepare_invoke 1.482 1.483 // %%% should make a type profile for any invokedynamic that takes a ref argument 1.484 // profile this call 1.485 __ profile_call(rsi); 1.486 1.487 __ verify_oop(rax_callsite); 1.488 - __ load_heap_oop(rcx_method_handle, Address(rax_callsite, __ delayed_value(java_lang_invoke_CallSite::target_offset_in_bytes, rdx))); 1.489 - __ null_check(rcx_method_handle); 1.490 - __ verify_oop(rcx_method_handle); 1.491 - __ prepare_to_jump_from_interpreted(); 1.492 - __ jump_to_method_handle_entry(rcx_method_handle, rdx); 1.493 + 1.494 + __ jump_from_interpreted(rbx_method, rdx); 1.495 } 1.496 1.497 //----------------------------------------------------------------------------------------------------