1.1 --- a/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Mon Jul 23 13:04:59 2012 -0700 1.2 +++ b/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Tue Jul 24 10:51:00 2012 -0700 1.3 @@ -643,6 +643,19 @@ 1.4 __ movdbl(r, Address(saved_sp, next_val_off)); 1.5 } 1.6 1.7 +static void range_check(MacroAssembler* masm, Register pc_reg, Register temp_reg, 1.8 + address code_start, address code_end, 1.9 + Label& L_ok) { 1.10 + Label L_fail; 1.11 + __ lea(temp_reg, ExternalAddress(code_start)); 1.12 + __ cmpptr(pc_reg, temp_reg); 1.13 + __ jcc(Assembler::belowEqual, L_fail); 1.14 + __ lea(temp_reg, ExternalAddress(code_end)); 1.15 + __ cmpptr(pc_reg, temp_reg); 1.16 + __ jcc(Assembler::below, L_ok); 1.17 + __ bind(L_fail); 1.18 +} 1.19 + 1.20 static void gen_i2c_adapter(MacroAssembler *masm, 1.21 int total_args_passed, 1.22 int comp_args_on_stack, 1.23 @@ -653,9 +666,53 @@ 1.24 // we may do a i2c -> c2i transition if we lose a race where compiled 1.25 // code goes non-entrant while we get args ready. 1.26 1.27 + // Adapters can be frameless because they do not require the caller 1.28 + // to perform additional cleanup work, such as correcting the stack pointer. 1.29 + // An i2c adapter is frameless because the *caller* frame, which is interpreted, 1.30 + // routinely repairs its own stack pointer (from interpreter_frame_last_sp), 1.31 + // even if a callee has modified the stack pointer. 1.32 + // A c2i adapter is frameless because the *callee* frame, which is interpreted, 1.33 + // routinely repairs its caller's stack pointer (from sender_sp, which is set 1.34 + // up via the senderSP register). 1.35 + // In other words, if *either* the caller or callee is interpreted, we can 1.36 + // get the stack pointer repaired after a call. 1.37 + // This is why c2i and i2c adapters cannot be indefinitely composed. 1.38 + // In particular, if a c2i adapter were to somehow call an i2c adapter, 1.39 + // both caller and callee would be compiled methods, and neither would 1.40 + // clean up the stack pointer changes performed by the two adapters. 1.41 + // If this happens, control eventually transfers back to the compiled 1.42 + // caller, but with an uncorrected stack, causing delayed havoc. 1.43 + 1.44 // Pick up the return address 1.45 __ movptr(rax, Address(rsp, 0)); 1.46 1.47 + if (VerifyAdapterCalls && 1.48 + (Interpreter::code() != NULL || StubRoutines::code1() != NULL)) { 1.49 + // So, let's test for cascading c2i/i2c adapters right now. 1.50 + // assert(Interpreter::contains($return_addr) || 1.51 + // StubRoutines::contains($return_addr), 1.52 + // "i2c adapter must return to an interpreter frame"); 1.53 + __ block_comment("verify_i2c { "); 1.54 + Label L_ok; 1.55 + if (Interpreter::code() != NULL) 1.56 + range_check(masm, rax, rdi, 1.57 + Interpreter::code()->code_start(), Interpreter::code()->code_end(), 1.58 + L_ok); 1.59 + if (StubRoutines::code1() != NULL) 1.60 + range_check(masm, rax, rdi, 1.61 + StubRoutines::code1()->code_begin(), StubRoutines::code1()->code_end(), 1.62 + L_ok); 1.63 + if (StubRoutines::code2() != NULL) 1.64 + range_check(masm, rax, rdi, 1.65 + StubRoutines::code2()->code_begin(), StubRoutines::code2()->code_end(), 1.66 + L_ok); 1.67 + const char* msg = "i2c adapter must return to an interpreter frame"; 1.68 + __ block_comment(msg); 1.69 + __ stop(msg); 1.70 + __ bind(L_ok); 1.71 + __ block_comment("} verify_i2ce "); 1.72 + } 1.73 + 1.74 // Must preserve original SP for loading incoming arguments because 1.75 // we need to align the outgoing SP for compiled code. 1.76 __ movptr(rdi, rsp); 1.77 @@ -1293,6 +1350,89 @@ 1.78 __ bind(done); 1.79 } 1.80 1.81 +static void verify_oop_args(MacroAssembler* masm, 1.82 + int total_args_passed, 1.83 + const BasicType* sig_bt, 1.84 + const VMRegPair* regs) { 1.85 + Register temp_reg = rbx; // not part of any compiled calling seq 1.86 + if (VerifyOops) { 1.87 + for (int i = 0; i < total_args_passed; i++) { 1.88 + if (sig_bt[i] == T_OBJECT || 1.89 + sig_bt[i] == T_ARRAY) { 1.90 + VMReg r = regs[i].first(); 1.91 + assert(r->is_valid(), "bad oop arg"); 1.92 + if (r->is_stack()) { 1.93 + __ movptr(temp_reg, Address(rsp, r->reg2stack() * VMRegImpl::stack_slot_size + wordSize)); 1.94 + __ verify_oop(temp_reg); 1.95 + } else { 1.96 + __ verify_oop(r->as_Register()); 1.97 + } 1.98 + } 1.99 + } 1.100 + } 1.101 +} 1.102 + 1.103 +static void gen_special_dispatch(MacroAssembler* masm, 1.104 + int total_args_passed, 1.105 + int comp_args_on_stack, 1.106 + vmIntrinsics::ID special_dispatch, 1.107 + const BasicType* sig_bt, 1.108 + const VMRegPair* regs) { 1.109 + verify_oop_args(masm, total_args_passed, sig_bt, regs); 1.110 + 1.111 + // Now write the args into the outgoing interpreter space 1.112 + bool has_receiver = false; 1.113 + Register receiver_reg = noreg; 1.114 + int member_arg_pos = -1; 1.115 + Register member_reg = noreg; 1.116 + int ref_kind = MethodHandles::signature_polymorphic_intrinsic_ref_kind(special_dispatch); 1.117 + if (ref_kind != 0) { 1.118 + member_arg_pos = total_args_passed - 1; // trailing MemberName argument 1.119 + member_reg = rbx; // known to be free at this point 1.120 + has_receiver = MethodHandles::ref_kind_has_receiver(ref_kind); 1.121 + } else if (special_dispatch == vmIntrinsics::_invokeBasic) { 1.122 + has_receiver = true; 1.123 + } else { 1.124 + guarantee(false, err_msg("special_dispatch=%d", special_dispatch)); 1.125 + } 1.126 + 1.127 + if (member_reg != noreg) { 1.128 + // Load the member_arg into register, if necessary. 1.129 + assert(member_arg_pos >= 0 && member_arg_pos < total_args_passed, "oob"); 1.130 + assert(sig_bt[member_arg_pos] == T_OBJECT, "dispatch argument must be an object"); 1.131 + VMReg r = regs[member_arg_pos].first(); 1.132 + assert(r->is_valid(), "bad member arg"); 1.133 + if (r->is_stack()) { 1.134 + __ movptr(member_reg, Address(rsp, r->reg2stack() * VMRegImpl::stack_slot_size + wordSize)); 1.135 + } else { 1.136 + // no data motion is needed 1.137 + member_reg = r->as_Register(); 1.138 + } 1.139 + } 1.140 + 1.141 + if (has_receiver) { 1.142 + // Make sure the receiver is loaded into a register. 1.143 + assert(total_args_passed > 0, "oob"); 1.144 + assert(sig_bt[0] == T_OBJECT, "receiver argument must be an object"); 1.145 + VMReg r = regs[0].first(); 1.146 + assert(r->is_valid(), "bad receiver arg"); 1.147 + if (r->is_stack()) { 1.148 + // Porting note: This assumes that compiled calling conventions always 1.149 + // pass the receiver oop in a register. If this is not true on some 1.150 + // platform, pick a temp and load the receiver from stack. 1.151 + assert(false, "receiver always in a register"); 1.152 + receiver_reg = rcx; // known to be free at this point 1.153 + __ movptr(receiver_reg, Address(rsp, r->reg2stack() * VMRegImpl::stack_slot_size + wordSize)); 1.154 + } else { 1.155 + // no data motion is needed 1.156 + receiver_reg = r->as_Register(); 1.157 + } 1.158 + } 1.159 + 1.160 + // Figure out which address we are really jumping to: 1.161 + MethodHandles::generate_method_handle_dispatch(masm, special_dispatch, 1.162 + receiver_reg, member_reg, /*for_compiler_entry:*/ true); 1.163 +} 1.164 1.165 // --------------------------------------------------------------------------- 1.166 // Generate a native wrapper for a given method. The method takes arguments 1.167 @@ -1323,14 +1463,37 @@ 1.168 // transition back to thread_in_Java 1.169 // return to caller 1.170 // 1.171 -nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, 1.172 +nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, 1.173 methodHandle method, 1.174 int compile_id, 1.175 int total_in_args, 1.176 int comp_args_on_stack, 1.177 - BasicType *in_sig_bt, 1.178 - VMRegPair *in_regs, 1.179 + BasicType* in_sig_bt, 1.180 + VMRegPair* in_regs, 1.181 BasicType ret_type) { 1.182 + if (method->is_method_handle_intrinsic()) { 1.183 + vmIntrinsics::ID iid = method->intrinsic_id(); 1.184 + intptr_t start = (intptr_t)__ pc(); 1.185 + int vep_offset = ((intptr_t)__ pc()) - start; 1.186 + gen_special_dispatch(masm, 1.187 + total_in_args, 1.188 + comp_args_on_stack, 1.189 + method->intrinsic_id(), 1.190 + in_sig_bt, 1.191 + in_regs); 1.192 + int frame_complete = ((intptr_t)__ pc()) - start; // not complete, period 1.193 + __ flush(); 1.194 + int stack_slots = SharedRuntime::out_preserve_stack_slots(); // no out slots at all, actually 1.195 + return nmethod::new_native_nmethod(method, 1.196 + compile_id, 1.197 + masm->code(), 1.198 + vep_offset, 1.199 + frame_complete, 1.200 + stack_slots / VMRegImpl::slots_per_word, 1.201 + in_ByteSize(-1), 1.202 + in_ByteSize(-1), 1.203 + (OopMapSet*)NULL); 1.204 + } 1.205 bool is_critical_native = true; 1.206 address native_func = method->critical_native_function(); 1.207 if (native_func == NULL) { 1.208 @@ -1436,7 +1599,7 @@ 1.209 if (in_regs[i].first()->is_Register()) { 1.210 const Register reg = in_regs[i].first()->as_Register(); 1.211 switch (in_sig_bt[i]) { 1.212 - case T_ARRAY: 1.213 + case T_ARRAY: // critical array (uses 2 slots on LP64) 1.214 case T_BOOLEAN: 1.215 case T_BYTE: 1.216 case T_SHORT: