Mercurial > hg > truffle
comparison src/cpu/x86/vm/templateTable_x86_64.cpp @ 1108:85f13cdfbc1d
6829192: JSR 292 needs to support 64-bit x86
Summary: changes for method handles and invokedynamic
Reviewed-by: kvn
author | twisti |
---|---|
date | Wed, 16 Dec 2009 12:48:04 +0100 |
parents | beb8f45ee9f0 |
children | 455df1b81409 |
comparison
equal
deleted
inserted
replaced
1102:6dc5471e0f66 | 1108:85f13cdfbc1d |
---|---|
201 __ movzbl(scratch, at_bcp(0)); | 201 __ movzbl(scratch, at_bcp(0)); |
202 __ cmpl(scratch, Bytecodes::_breakpoint); | 202 __ cmpl(scratch, Bytecodes::_breakpoint); |
203 __ jcc(Assembler::notEqual, fast_patch); | 203 __ jcc(Assembler::notEqual, fast_patch); |
204 __ get_method(scratch); | 204 __ get_method(scratch); |
205 // Let breakpoint table handling rewrite to quicker bytecode | 205 // Let breakpoint table handling rewrite to quicker bytecode |
206 __ call_VM(noreg, | 206 __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::set_original_bytecode_at), scratch, r13, bc); |
207 CAST_FROM_FN_PTR(address, | |
208 InterpreterRuntime::set_original_bytecode_at), | |
209 scratch, r13, bc); | |
210 #ifndef ASSERT | 207 #ifndef ASSERT |
211 __ jmpb(patch_done); | 208 __ jmpb(patch_done); |
212 __ bind(fast_patch); | |
213 } | |
214 #else | 209 #else |
215 __ jmp(patch_done); | 210 __ jmp(patch_done); |
211 #endif | |
216 __ bind(fast_patch); | 212 __ bind(fast_patch); |
217 } | 213 } |
214 #ifdef ASSERT | |
218 Label okay; | 215 Label okay; |
219 __ load_unsigned_byte(scratch, at_bcp(0)); | 216 __ load_unsigned_byte(scratch, at_bcp(0)); |
220 __ cmpl(scratch, (int) Bytecodes::java_code(bytecode)); | 217 __ cmpl(scratch, (int) Bytecodes::java_code(bytecode)); |
221 __ jcc(Assembler::equal, okay); | 218 __ jcc(Assembler::equal, okay); |
222 __ cmpl(scratch, bc); | 219 __ cmpl(scratch, bc); |
2052 if (os::is_MP()) { // Not needed on single CPU | 2049 if (os::is_MP()) { // Not needed on single CPU |
2053 __ membar(order_constraint); | 2050 __ membar(order_constraint); |
2054 } | 2051 } |
2055 } | 2052 } |
2056 | 2053 |
2057 void TemplateTable::resolve_cache_and_index(int byte_no, | 2054 void TemplateTable::resolve_cache_and_index(int byte_no, Register Rcache, Register index) { |
2058 Register Rcache, | |
2059 Register index) { | |
2060 assert(byte_no == 1 || byte_no == 2, "byte_no out of range"); | 2055 assert(byte_no == 1 || byte_no == 2, "byte_no out of range"); |
2056 bool is_invokedynamic = (bytecode() == Bytecodes::_invokedynamic); | |
2061 | 2057 |
2062 const Register temp = rbx; | 2058 const Register temp = rbx; |
2063 assert_different_registers(Rcache, index, temp); | 2059 assert_different_registers(Rcache, index, temp); |
2064 | 2060 |
2065 const int shift_count = (1 + byte_no) * BitsPerByte; | 2061 const int shift_count = (1 + byte_no) * BitsPerByte; |
2066 Label resolved; | 2062 Label resolved; |
2067 __ get_cache_and_index_at_bcp(Rcache, index, 1); | 2063 __ get_cache_and_index_at_bcp(Rcache, index, 1, is_invokedynamic); |
2068 __ movl(temp, Address(Rcache, | 2064 if (is_invokedynamic) { |
2069 index, Address::times_8, | 2065 // we are resolved if the f1 field contains a non-null CallSite object |
2070 constantPoolCacheOopDesc::base_offset() + | 2066 __ cmpptr(Address(Rcache, index, Address::times_ptr, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::f1_offset()), (int32_t) NULL_WORD); |
2071 ConstantPoolCacheEntry::indices_offset())); | 2067 __ jcc(Assembler::notEqual, resolved); |
2072 __ shrl(temp, shift_count); | 2068 } else { |
2073 // have we resolved this bytecode? | 2069 __ movl(temp, Address(Rcache, index, Address::times_ptr, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::indices_offset())); |
2074 __ andl(temp, 0xFF); | 2070 __ shrl(temp, shift_count); |
2075 __ cmpl(temp, (int) bytecode()); | 2071 // have we resolved this bytecode? |
2076 __ jcc(Assembler::equal, resolved); | 2072 __ andl(temp, 0xFF); |
2073 __ cmpl(temp, (int) bytecode()); | |
2074 __ jcc(Assembler::equal, resolved); | |
2075 } | |
2077 | 2076 |
2078 // resolve first time through | 2077 // resolve first time through |
2079 address entry; | 2078 address entry; |
2080 switch (bytecode()) { | 2079 switch (bytecode()) { |
2081 case Bytecodes::_getstatic: | 2080 case Bytecodes::_getstatic: |
2088 case Bytecodes::_invokespecial: | 2087 case Bytecodes::_invokespecial: |
2089 case Bytecodes::_invokestatic: | 2088 case Bytecodes::_invokestatic: |
2090 case Bytecodes::_invokeinterface: | 2089 case Bytecodes::_invokeinterface: |
2091 entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke); | 2090 entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke); |
2092 break; | 2091 break; |
2092 case Bytecodes::_invokedynamic: | |
2093 entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic); | |
2094 break; | |
2093 default: | 2095 default: |
2094 ShouldNotReachHere(); | 2096 ShouldNotReachHere(); |
2095 break; | 2097 break; |
2096 } | 2098 } |
2097 __ movl(temp, (int) bytecode()); | 2099 __ movl(temp, (int) bytecode()); |
2098 __ call_VM(noreg, entry, temp); | 2100 __ call_VM(noreg, entry, temp); |
2099 | 2101 |
2100 // Update registers with resolved info | 2102 // Update registers with resolved info |
2101 __ get_cache_and_index_at_bcp(Rcache, index, 1); | 2103 __ get_cache_and_index_at_bcp(Rcache, index, 1, is_invokedynamic); |
2102 __ bind(resolved); | 2104 __ bind(resolved); |
2103 } | 2105 } |
2104 | 2106 |
2105 // The Rcache and index registers must be set before call | 2107 // The Rcache and index registers must be set before call |
2106 void TemplateTable::load_field_cp_cache_entry(Register obj, | 2108 void TemplateTable::load_field_cp_cache_entry(Register obj, |
2830 void TemplateTable::count_calls(Register method, Register temp) { | 2832 void TemplateTable::count_calls(Register method, Register temp) { |
2831 // implemented elsewhere | 2833 // implemented elsewhere |
2832 ShouldNotReachHere(); | 2834 ShouldNotReachHere(); |
2833 } | 2835 } |
2834 | 2836 |
2835 void TemplateTable::prepare_invoke(Register method, | 2837 void TemplateTable::prepare_invoke(Register method, Register index, int byte_no) { |
2836 Register index, | |
2837 int byte_no, | |
2838 Bytecodes::Code code) { | |
2839 // determine flags | 2838 // determine flags |
2839 Bytecodes::Code code = bytecode(); | |
2840 const bool is_invokeinterface = code == Bytecodes::_invokeinterface; | 2840 const bool is_invokeinterface = code == Bytecodes::_invokeinterface; |
2841 const bool is_invokedynamic = code == Bytecodes::_invokedynamic; | |
2841 const bool is_invokevirtual = code == Bytecodes::_invokevirtual; | 2842 const bool is_invokevirtual = code == Bytecodes::_invokevirtual; |
2842 const bool is_invokespecial = code == Bytecodes::_invokespecial; | 2843 const bool is_invokespecial = code == Bytecodes::_invokespecial; |
2843 const bool load_receiver = code != Bytecodes::_invokestatic; | 2844 const bool load_receiver = (code != Bytecodes::_invokestatic && code != Bytecodes::_invokedynamic); |
2844 const bool receiver_null_check = is_invokespecial; | 2845 const bool receiver_null_check = is_invokespecial; |
2845 const bool save_flags = is_invokeinterface || is_invokevirtual; | 2846 const bool save_flags = is_invokeinterface || is_invokevirtual; |
2846 // setup registers & access constant pool cache | 2847 // setup registers & access constant pool cache |
2847 const Register recv = rcx; | 2848 const Register recv = rcx; |
2848 const Register flags = rdx; | 2849 const Register flags = rdx; |
2856 // load receiver if needed (note: no return address pushed yet) | 2857 // load receiver if needed (note: no return address pushed yet) |
2857 if (load_receiver) { | 2858 if (load_receiver) { |
2858 __ movl(recv, flags); | 2859 __ movl(recv, flags); |
2859 __ andl(recv, 0xFF); | 2860 __ andl(recv, 0xFF); |
2860 if (TaggedStackInterpreter) __ shll(recv, 1); // index*2 | 2861 if (TaggedStackInterpreter) __ shll(recv, 1); // index*2 |
2861 __ movptr(recv, Address(rsp, recv, Address::times_8, | 2862 Address recv_addr(rsp, recv, Address::times_8, -Interpreter::expr_offset_in_bytes(1)); |
2862 -Interpreter::expr_offset_in_bytes(1))); | 2863 if (is_invokedynamic) { |
2863 __ verify_oop(recv); | 2864 __ lea(recv, recv_addr); |
2865 } else { | |
2866 __ movptr(recv, recv_addr); | |
2867 __ verify_oop(recv); | |
2868 } | |
2864 } | 2869 } |
2865 | 2870 |
2866 // do null check if needed | 2871 // do null check if needed |
2867 if (receiver_null_check) { | 2872 if (receiver_null_check) { |
2868 __ null_check(recv); | 2873 __ null_check(recv); |
2876 __ shrl(flags, ConstantPoolCacheEntry::tosBits); | 2881 __ shrl(flags, ConstantPoolCacheEntry::tosBits); |
2877 // Make sure we don't need to mask flags for tosBits after the above shift | 2882 // Make sure we don't need to mask flags for tosBits after the above shift |
2878 ConstantPoolCacheEntry::verify_tosBits(); | 2883 ConstantPoolCacheEntry::verify_tosBits(); |
2879 // load return address | 2884 // load return address |
2880 { | 2885 { |
2881 ExternalAddress return_5((address)Interpreter::return_5_addrs_by_index_table()); | 2886 address table_addr; |
2882 ExternalAddress return_3((address)Interpreter::return_3_addrs_by_index_table()); | 2887 if (is_invokeinterface || is_invokedynamic) |
2883 __ lea(rscratch1, (is_invokeinterface ? return_5 : return_3)); | 2888 table_addr = (address)Interpreter::return_5_addrs_by_index_table(); |
2884 __ movptr(flags, Address(rscratch1, flags, Address::times_8)); | 2889 else |
2890 table_addr = (address)Interpreter::return_3_addrs_by_index_table(); | |
2891 ExternalAddress table(table_addr); | |
2892 __ lea(rscratch1, table); | |
2893 __ movptr(flags, Address(rscratch1, flags, Address::times_ptr)); | |
2885 } | 2894 } |
2886 | 2895 |
2887 // push return address | 2896 // push return address |
2888 __ push(flags); | 2897 __ push(flags); |
2889 | 2898 |
2945 } | 2954 } |
2946 | 2955 |
2947 | 2956 |
2948 void TemplateTable::invokevirtual(int byte_no) { | 2957 void TemplateTable::invokevirtual(int byte_no) { |
2949 transition(vtos, vtos); | 2958 transition(vtos, vtos); |
2950 prepare_invoke(rbx, noreg, byte_no, bytecode()); | 2959 prepare_invoke(rbx, noreg, byte_no); |
2951 | 2960 |
2952 // rbx: index | 2961 // rbx: index |
2953 // rcx: receiver | 2962 // rcx: receiver |
2954 // rdx: flags | 2963 // rdx: flags |
2955 | 2964 |
2957 } | 2966 } |
2958 | 2967 |
2959 | 2968 |
2960 void TemplateTable::invokespecial(int byte_no) { | 2969 void TemplateTable::invokespecial(int byte_no) { |
2961 transition(vtos, vtos); | 2970 transition(vtos, vtos); |
2962 prepare_invoke(rbx, noreg, byte_no, bytecode()); | 2971 prepare_invoke(rbx, noreg, byte_no); |
2963 // do the call | 2972 // do the call |
2964 __ verify_oop(rbx); | 2973 __ verify_oop(rbx); |
2965 __ profile_call(rax); | 2974 __ profile_call(rax); |
2966 __ jump_from_interpreted(rbx, rax); | 2975 __ jump_from_interpreted(rbx, rax); |
2967 } | 2976 } |
2968 | 2977 |
2969 | 2978 |
2970 void TemplateTable::invokestatic(int byte_no) { | 2979 void TemplateTable::invokestatic(int byte_no) { |
2971 transition(vtos, vtos); | 2980 transition(vtos, vtos); |
2972 prepare_invoke(rbx, noreg, byte_no, bytecode()); | 2981 prepare_invoke(rbx, noreg, byte_no); |
2973 // do the call | 2982 // do the call |
2974 __ verify_oop(rbx); | 2983 __ verify_oop(rbx); |
2975 __ profile_call(rax); | 2984 __ profile_call(rax); |
2976 __ jump_from_interpreted(rbx, rax); | 2985 __ jump_from_interpreted(rbx, rax); |
2977 } | 2986 } |
2981 __ stop("fast_invokevfinal not used on amd64"); | 2990 __ stop("fast_invokevfinal not used on amd64"); |
2982 } | 2991 } |
2983 | 2992 |
2984 void TemplateTable::invokeinterface(int byte_no) { | 2993 void TemplateTable::invokeinterface(int byte_no) { |
2985 transition(vtos, vtos); | 2994 transition(vtos, vtos); |
2986 prepare_invoke(rax, rbx, byte_no, bytecode()); | 2995 prepare_invoke(rax, rbx, byte_no); |
2987 | 2996 |
2988 // rax: Interface | 2997 // rax: Interface |
2989 // rbx: index | 2998 // rbx: index |
2990 // rcx: receiver | 2999 // rcx: receiver |
2991 // rdx: flags | 3000 // rdx: flags |
3070 // the call_VM checks for exception, so we should never return here. | 3079 // the call_VM checks for exception, so we should never return here. |
3071 __ should_not_reach_here(); | 3080 __ should_not_reach_here(); |
3072 return; | 3081 return; |
3073 } | 3082 } |
3074 | 3083 |
3075 __ stop("invokedynamic NYI");//6815692// | 3084 prepare_invoke(rax, rbx, byte_no); |
3085 | |
3086 // rax: CallSite object (f1) | |
3087 // rbx: unused (f2) | |
3088 // rcx: receiver address | |
3089 // rdx: flags (unused) | |
3090 | |
3091 if (ProfileInterpreter) { | |
3092 Label L; | |
3093 // %%% should make a type profile for any invokedynamic that takes a ref argument | |
3094 // profile this call | |
3095 __ profile_call(r13); | |
3096 } | |
3097 | |
3098 __ movptr(rcx, Address(rax, __ delayed_value(java_dyn_CallSite::target_offset_in_bytes, rcx))); | |
3099 __ null_check(rcx); | |
3100 __ prepare_to_jump_from_interpreted(); | |
3101 __ jump_to_method_handle_entry(rcx, rdx); | |
3076 } | 3102 } |
3077 | 3103 |
3078 | 3104 |
3079 //----------------------------------------------------------------------------- | 3105 //----------------------------------------------------------------------------- |
3080 // Allocation | 3106 // Allocation |