Mercurial > hg > graal-jvmci-8
comparison src/cpu/x86/vm/templateTable_x86_64.cpp @ 1565:ab102d5d923e
6939207: refactor constant pool index processing
Summary: Factored cleanup of instruction decode which prepares for enhanced ldc semantics.
Reviewed-by: twisti
author | jrose |
---|---|
date | Sun, 23 May 2010 01:38:26 -0700 |
parents | 2338d41fbd81 |
children | e9ff18c4ace7 |
comparison
equal
deleted
inserted
replaced
1564:61b2245abf36 | 1565:ab102d5d923e |
---|---|
2013 if (os::is_MP()) { // Not needed on single CPU | 2013 if (os::is_MP()) { // Not needed on single CPU |
2014 __ membar(order_constraint); | 2014 __ membar(order_constraint); |
2015 } | 2015 } |
2016 } | 2016 } |
2017 | 2017 |
2018 void TemplateTable::resolve_cache_and_index(int byte_no, Register Rcache, Register index) { | 2018 void TemplateTable::resolve_cache_and_index(int byte_no, |
2019 assert(byte_no == 1 || byte_no == 2, "byte_no out of range"); | 2019 Register result, |
2020 bool is_invokedynamic = (bytecode() == Bytecodes::_invokedynamic); | 2020 Register Rcache, |
2021 | 2021 Register index, |
2022 size_t index_size) { | |
2022 const Register temp = rbx; | 2023 const Register temp = rbx; |
2023 assert_different_registers(Rcache, index, temp); | 2024 assert_different_registers(result, Rcache, index, temp); |
2024 | 2025 |
2025 const int shift_count = (1 + byte_no) * BitsPerByte; | |
2026 Label resolved; | 2026 Label resolved; |
2027 __ get_cache_and_index_at_bcp(Rcache, index, 1, is_invokedynamic); | 2027 __ get_cache_and_index_at_bcp(Rcache, index, 1, index_size); |
2028 if (is_invokedynamic) { | 2028 if (byte_no == f1_oop) { |
2029 // we are resolved if the f1 field contains a non-null CallSite object | 2029 // We are resolved if the f1 field contains a non-null object (CallSite, etc.) |
2030 __ cmpptr(Address(Rcache, index, Address::times_ptr, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::f1_offset()), (int32_t) NULL_WORD); | 2030 // This kind of CP cache entry does not need to match the flags byte, because |
2031 // there is a 1-1 relation between bytecode type and CP entry type. | |
2032 assert(result != noreg, ""); //else do cmpptr(Address(...), (int32_t) NULL_WORD) | |
2033 __ movptr(result, Address(Rcache, index, Address::times_ptr, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::f1_offset())); | |
2034 __ testptr(result, result); | |
2031 __ jcc(Assembler::notEqual, resolved); | 2035 __ jcc(Assembler::notEqual, resolved); |
2032 } else { | 2036 } else { |
2037 assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range"); | |
2038 assert(result == noreg, ""); //else change code for setting result | |
2039 const int shift_count = (1 + byte_no) * BitsPerByte; | |
2033 __ movl(temp, Address(Rcache, index, Address::times_ptr, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::indices_offset())); | 2040 __ movl(temp, Address(Rcache, index, Address::times_ptr, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::indices_offset())); |
2034 __ shrl(temp, shift_count); | 2041 __ shrl(temp, shift_count); |
2035 // have we resolved this bytecode? | 2042 // have we resolved this bytecode? |
2036 __ andl(temp, 0xFF); | 2043 __ andl(temp, 0xFF); |
2037 __ cmpl(temp, (int) bytecode()); | 2044 __ cmpl(temp, (int) bytecode()); |
2062 } | 2069 } |
2063 __ movl(temp, (int) bytecode()); | 2070 __ movl(temp, (int) bytecode()); |
2064 __ call_VM(noreg, entry, temp); | 2071 __ call_VM(noreg, entry, temp); |
2065 | 2072 |
2066 // Update registers with resolved info | 2073 // Update registers with resolved info |
2067 __ get_cache_and_index_at_bcp(Rcache, index, 1, is_invokedynamic); | 2074 __ get_cache_and_index_at_bcp(Rcache, index, 1, index_size); |
2075 if (result != noreg) | |
2076 __ movptr(result, Address(Rcache, index, Address::times_ptr, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::f1_offset())); | |
2068 __ bind(resolved); | 2077 __ bind(resolved); |
2069 } | 2078 } |
2070 | 2079 |
2071 // The Rcache and index registers must be set before call | 2080 // The Rcache and index registers must be set before call |
2072 void TemplateTable::load_field_cp_cache_entry(Register obj, | 2081 void TemplateTable::load_field_cp_cache_entry(Register obj, |
2098 void TemplateTable::load_invoke_cp_cache_entry(int byte_no, | 2107 void TemplateTable::load_invoke_cp_cache_entry(int byte_no, |
2099 Register method, | 2108 Register method, |
2100 Register itable_index, | 2109 Register itable_index, |
2101 Register flags, | 2110 Register flags, |
2102 bool is_invokevirtual, | 2111 bool is_invokevirtual, |
2103 bool is_invokevfinal /*unused*/) { | 2112 bool is_invokevfinal, /*unused*/ |
2113 bool is_invokedynamic) { | |
2104 // setup registers | 2114 // setup registers |
2105 const Register cache = rcx; | 2115 const Register cache = rcx; |
2106 const Register index = rdx; | 2116 const Register index = rdx; |
2107 assert_different_registers(method, flags); | 2117 assert_different_registers(method, flags); |
2108 assert_different_registers(method, cache, index); | 2118 assert_different_registers(method, cache, index); |
2118 ConstantPoolCacheEntry::flags_offset()); | 2128 ConstantPoolCacheEntry::flags_offset()); |
2119 // access constant pool cache fields | 2129 // access constant pool cache fields |
2120 const int index_offset = in_bytes(constantPoolCacheOopDesc::base_offset() + | 2130 const int index_offset = in_bytes(constantPoolCacheOopDesc::base_offset() + |
2121 ConstantPoolCacheEntry::f2_offset()); | 2131 ConstantPoolCacheEntry::f2_offset()); |
2122 | 2132 |
2123 resolve_cache_and_index(byte_no, cache, index); | 2133 if (byte_no == f1_oop) { |
2124 | 2134 // Resolved f1_oop goes directly into 'method' register. |
2125 assert(wordSize == 8, "adjust code below"); | 2135 assert(is_invokedynamic, ""); |
2126 __ movptr(method, Address(cache, index, Address::times_8, method_offset)); | 2136 resolve_cache_and_index(byte_no, method, cache, index, sizeof(u4)); |
2137 } else { | |
2138 resolve_cache_and_index(byte_no, noreg, cache, index, sizeof(u2)); | |
2139 __ movptr(method, Address(cache, index, Address::times_ptr, method_offset)); | |
2140 } | |
2127 if (itable_index != noreg) { | 2141 if (itable_index != noreg) { |
2128 __ movptr(itable_index, | 2142 __ movptr(itable_index, Address(cache, index, Address::times_ptr, index_offset)); |
2129 Address(cache, index, Address::times_8, index_offset)); | 2143 } |
2130 } | 2144 __ movl(flags, Address(cache, index, Address::times_ptr, flags_offset)); |
2131 __ movl(flags , Address(cache, index, Address::times_8, flags_offset)); | |
2132 } | 2145 } |
2133 | 2146 |
2134 | 2147 |
2135 // The registers cache and index expected to be set before call. | 2148 // The registers cache and index expected to be set before call. |
2136 // Correct values of the cache and index registers are preserved. | 2149 // Correct values of the cache and index registers are preserved. |
2185 const Register obj = c_rarg3; | 2198 const Register obj = c_rarg3; |
2186 const Register off = rbx; | 2199 const Register off = rbx; |
2187 const Register flags = rax; | 2200 const Register flags = rax; |
2188 const Register bc = c_rarg3; // uses same reg as obj, so don't mix them | 2201 const Register bc = c_rarg3; // uses same reg as obj, so don't mix them |
2189 | 2202 |
2190 resolve_cache_and_index(byte_no, cache, index); | 2203 resolve_cache_and_index(byte_no, noreg, cache, index, sizeof(u2)); |
2191 jvmti_post_field_access(cache, index, is_static, false); | 2204 jvmti_post_field_access(cache, index, is_static, false); |
2192 load_field_cp_cache_entry(obj, cache, index, off, flags, is_static); | 2205 load_field_cp_cache_entry(obj, cache, index, off, flags, is_static); |
2193 | 2206 |
2194 if (!is_static) { | 2207 if (!is_static) { |
2195 // obj is on the stack | 2208 // obj is on the stack |
2388 const Register obj = rcx; | 2401 const Register obj = rcx; |
2389 const Register off = rbx; | 2402 const Register off = rbx; |
2390 const Register flags = rax; | 2403 const Register flags = rax; |
2391 const Register bc = c_rarg3; | 2404 const Register bc = c_rarg3; |
2392 | 2405 |
2393 resolve_cache_and_index(byte_no, cache, index); | 2406 resolve_cache_and_index(byte_no, noreg, cache, index, sizeof(u2)); |
2394 jvmti_post_field_mod(cache, index, is_static); | 2407 jvmti_post_field_mod(cache, index, is_static); |
2395 load_field_cp_cache_entry(obj, cache, index, off, flags, is_static); | 2408 load_field_cp_cache_entry(obj, cache, index, off, flags, is_static); |
2396 | 2409 |
2397 // [jk] not needed currently | 2410 // [jk] not needed currently |
2398 // volatile_barrier(Assembler::Membar_mask_bits(Assembler::LoadStore | | 2411 // volatile_barrier(Assembler::Membar_mask_bits(Assembler::LoadStore | |
2813 assert_different_registers(method, index, recv, flags); | 2826 assert_different_registers(method, index, recv, flags); |
2814 | 2827 |
2815 // save 'interpreter return address' | 2828 // save 'interpreter return address' |
2816 __ save_bcp(); | 2829 __ save_bcp(); |
2817 | 2830 |
2818 load_invoke_cp_cache_entry(byte_no, method, index, flags, is_invokevirtual); | 2831 load_invoke_cp_cache_entry(byte_no, method, index, flags, is_invokevirtual, false, is_invokedynamic); |
2819 | 2832 |
2820 // load receiver if needed (note: no return address pushed yet) | 2833 // load receiver if needed (note: no return address pushed yet) |
2821 if (load_receiver) { | 2834 if (load_receiver) { |
2835 assert(!is_invokedynamic, ""); | |
2822 __ movl(recv, flags); | 2836 __ movl(recv, flags); |
2823 __ andl(recv, 0xFF); | 2837 __ andl(recv, 0xFF); |
2824 Address recv_addr(rsp, recv, Address::times_8, -Interpreter::expr_offset_in_bytes(1)); | 2838 Address recv_addr(rsp, recv, Address::times_8, -Interpreter::expr_offset_in_bytes(1)); |
2825 __ movptr(recv, recv_addr); | 2839 __ movptr(recv, recv_addr); |
2826 __ verify_oop(recv); | 2840 __ verify_oop(recv); |
2912 } | 2926 } |
2913 | 2927 |
2914 | 2928 |
2915 void TemplateTable::invokevirtual(int byte_no) { | 2929 void TemplateTable::invokevirtual(int byte_no) { |
2916 transition(vtos, vtos); | 2930 transition(vtos, vtos); |
2931 assert(byte_no == f2_byte, "use this argument"); | |
2917 prepare_invoke(rbx, noreg, byte_no); | 2932 prepare_invoke(rbx, noreg, byte_no); |
2918 | 2933 |
2919 // rbx: index | 2934 // rbx: index |
2920 // rcx: receiver | 2935 // rcx: receiver |
2921 // rdx: flags | 2936 // rdx: flags |
2924 } | 2939 } |
2925 | 2940 |
2926 | 2941 |
2927 void TemplateTable::invokespecial(int byte_no) { | 2942 void TemplateTable::invokespecial(int byte_no) { |
2928 transition(vtos, vtos); | 2943 transition(vtos, vtos); |
2944 assert(byte_no == f1_byte, "use this argument"); | |
2929 prepare_invoke(rbx, noreg, byte_no); | 2945 prepare_invoke(rbx, noreg, byte_no); |
2930 // do the call | 2946 // do the call |
2931 __ verify_oop(rbx); | 2947 __ verify_oop(rbx); |
2932 __ profile_call(rax); | 2948 __ profile_call(rax); |
2933 __ jump_from_interpreted(rbx, rax); | 2949 __ jump_from_interpreted(rbx, rax); |
2934 } | 2950 } |
2935 | 2951 |
2936 | 2952 |
2937 void TemplateTable::invokestatic(int byte_no) { | 2953 void TemplateTable::invokestatic(int byte_no) { |
2938 transition(vtos, vtos); | 2954 transition(vtos, vtos); |
2955 assert(byte_no == f1_byte, "use this argument"); | |
2939 prepare_invoke(rbx, noreg, byte_no); | 2956 prepare_invoke(rbx, noreg, byte_no); |
2940 // do the call | 2957 // do the call |
2941 __ verify_oop(rbx); | 2958 __ verify_oop(rbx); |
2942 __ profile_call(rax); | 2959 __ profile_call(rax); |
2943 __ jump_from_interpreted(rbx, rax); | 2960 __ jump_from_interpreted(rbx, rax); |
2944 } | 2961 } |
2945 | 2962 |
2946 void TemplateTable::fast_invokevfinal(int byte_no) { | 2963 void TemplateTable::fast_invokevfinal(int byte_no) { |
2947 transition(vtos, vtos); | 2964 transition(vtos, vtos); |
2965 assert(byte_no == f2_byte, "use this argument"); | |
2948 __ stop("fast_invokevfinal not used on amd64"); | 2966 __ stop("fast_invokevfinal not used on amd64"); |
2949 } | 2967 } |
2950 | 2968 |
2951 void TemplateTable::invokeinterface(int byte_no) { | 2969 void TemplateTable::invokeinterface(int byte_no) { |
2952 transition(vtos, vtos); | 2970 transition(vtos, vtos); |
2971 assert(byte_no == f1_byte, "use this argument"); | |
2953 prepare_invoke(rax, rbx, byte_no); | 2972 prepare_invoke(rax, rbx, byte_no); |
2954 | 2973 |
2955 // rax: Interface | 2974 // rax: Interface |
2956 // rbx: index | 2975 // rbx: index |
2957 // rcx: receiver | 2976 // rcx: receiver |
3025 return; | 3044 return; |
3026 } | 3045 } |
3027 | 3046 |
3028 void TemplateTable::invokedynamic(int byte_no) { | 3047 void TemplateTable::invokedynamic(int byte_no) { |
3029 transition(vtos, vtos); | 3048 transition(vtos, vtos); |
3049 assert(byte_no == f1_oop, "use this argument"); | |
3030 | 3050 |
3031 if (!EnableInvokeDynamic) { | 3051 if (!EnableInvokeDynamic) { |
3032 // We should not encounter this bytecode if !EnableInvokeDynamic. | 3052 // We should not encounter this bytecode if !EnableInvokeDynamic. |
3033 // The verifier will stop it. However, if we get past the verifier, | 3053 // The verifier will stop it. However, if we get past the verifier, |
3034 // this will stop the thread in a reasonable way, without crashing the JVM. | 3054 // this will stop the thread in a reasonable way, without crashing the JVM. |
3037 // the call_VM checks for exception, so we should never return here. | 3057 // the call_VM checks for exception, so we should never return here. |
3038 __ should_not_reach_here(); | 3058 __ should_not_reach_here(); |
3039 return; | 3059 return; |
3040 } | 3060 } |
3041 | 3061 |
3062 assert(byte_no == f1_oop, "use this argument"); | |
3042 prepare_invoke(rax, rbx, byte_no); | 3063 prepare_invoke(rax, rbx, byte_no); |
3043 | 3064 |
3044 // rax: CallSite object (f1) | 3065 // rax: CallSite object (f1) |
3045 // rbx: unused (f2) | 3066 // rbx: unused (f2) |
3046 // rcx: receiver address | 3067 // rcx: receiver address |