2915 assert(ConstantPoolCacheEntry::_indy_resolved_references_appendix_offset == 0, "appendix expected at index+0");
2916 __ load_resolved_reference_at_index(temp, index);
2917 __ verify_oop(temp);
2918 __ push_ptr(temp); // push appendix (MethodType, CallSite, etc.)
2919 __ bind(L_no_push);
2920 }
2921
2922 // load receiver if needed (after appendix is pushed so parameter size is correct)
2923 if (load_receiver) {
2924 __ and3(flags, ConstantPoolCacheEntry::parameter_size_mask, temp); // get parameter size
2925 __ load_receiver(temp, recv); // __ argument_address uses Gargs but we need Lesp
2926 __ verify_oop(recv);
2927 }
2928
2929 // compute return type
2930 __ srl(flags, ConstantPoolCacheEntry::tos_state_shift, ra);
2931 // Make sure we don't need to mask flags after the above shift
2932 ConstantPoolCacheEntry::verify_tos_state_shift();
2933 // load return address
2934 {
2935 const address table_addr = (is_invokeinterface || is_invokedynamic) ?
2936 (address)Interpreter::return_5_addrs_by_index_table() :
2937 (address)Interpreter::return_3_addrs_by_index_table();
2938 AddressLiteral table(table_addr);
2939 __ set(table, temp);
2940 __ sll(ra, LogBytesPerWord, ra);
2941 __ ld_ptr(Address(temp, ra), ra);
2942 }
2943 }
2944
2945
2946 void TemplateTable::generate_vtable_call(Register Rrecv, Register Rindex, Register Rret) {
2947 Register Rtemp = G4_scratch;
2948 Register Rcall = Rindex;
2949 assert_different_registers(Rcall, G5_method, Gargs, Rret);
2950
2951 // get target Method* & entry point
2952 __ lookup_virtual_method(Rrecv, Rindex, G5_method);
2953 __ call_from_interpreter(Rcall, Gargs, Rret);
2954 }
2955
2956 void TemplateTable::invokevirtual(int byte_no) {
2957 transition(vtos, vtos);
2967 __ mov(SP, O5_savedSP); // record SP that we wanted the callee to restore
2968
2969 // Check for vfinal
2970 __ set((1 << ConstantPoolCacheEntry::is_vfinal_shift), G4_scratch);
2971 __ btst(Rret, G4_scratch);
2972 __ br(Assembler::zero, false, Assembler::pt, notFinal);
2973 __ delayed()->and3(Rret, 0xFF, G4_scratch); // gets number of parameters
2974
2975 patch_bytecode(Bytecodes::_fast_invokevfinal, Rscratch, Rtemp);
2976
2977 invokevfinal_helper(Rscratch, Rret);
2978
2979 __ bind(notFinal);
2980
2981 __ mov(G5_method, Rscratch); // better scratch register
2982 __ load_receiver(G4_scratch, O0_recv); // gets receiverOop
2983 // receiver is in O0_recv
2984 __ verify_oop(O0_recv);
2985
2986 // get return address
2987 AddressLiteral table(Interpreter::return_3_addrs_by_index_table());
2988 __ set(table, Rtemp);
2989 __ srl(Rret, ConstantPoolCacheEntry::tos_state_shift, Rret); // get return type
2990 // Make sure we don't need to mask Rret after the above shift
2991 ConstantPoolCacheEntry::verify_tos_state_shift();
2992 __ sll(Rret, LogBytesPerWord, Rret);
2993 __ ld_ptr(Rtemp, Rret, Rret); // get return address
2994
2995 // get receiver klass
2996 __ null_check(O0_recv, oopDesc::klass_offset_in_bytes());
2997 __ load_klass(O0_recv, O0_recv);
2998 __ verify_klass_ptr(O0_recv);
2999
3000 __ profile_virtual_call(O0_recv, O4);
3001
3002 generate_vtable_call(O0_recv, Rscratch, Rret);
3003 }
3004
3005 void TemplateTable::fast_invokevfinal(int byte_no) {
3006 transition(vtos, vtos);
3007 assert(byte_no == f2_byte, "use this argument");
3009 load_invoke_cp_cache_entry(byte_no, G5_method, noreg, Lscratch, true,
3010 /*is_invokevfinal*/true, false);
3011 __ mov(SP, O5_savedSP); // record SP that we wanted the callee to restore
3012 invokevfinal_helper(G3_scratch, Lscratch);
3013 }
3014
3015 void TemplateTable::invokevfinal_helper(Register Rscratch, Register Rret) {
3016 Register Rtemp = G4_scratch;
3017
3018 // Load receiver from stack slot
3019 __ ld_ptr(G5_method, in_bytes(Method::const_offset()), G4_scratch);
3020 __ lduh(G4_scratch, in_bytes(ConstMethod::size_of_parameters_offset()), G4_scratch);
3021 __ load_receiver(G4_scratch, O0);
3022
3023 // receiver NULL check
3024 __ null_check(O0);
3025
3026 __ profile_final_call(O4);
3027
3028 // get return address
3029 AddressLiteral table(Interpreter::return_3_addrs_by_index_table());
3030 __ set(table, Rtemp);
3031 __ srl(Rret, ConstantPoolCacheEntry::tos_state_shift, Rret); // get return type
3032 // Make sure we don't need to mask Rret after the above shift
3033 ConstantPoolCacheEntry::verify_tos_state_shift();
3034 __ sll(Rret, LogBytesPerWord, Rret);
3035 __ ld_ptr(Rtemp, Rret, Rret); // get return address
3036
3037
3038 // do the call
3039 __ call_from_interpreter(Rscratch, Gargs, Rret);
3040 }
3041
3042
3043 void TemplateTable::invokespecial(int byte_no) {
3044 transition(vtos, vtos);
3045 assert(byte_no == f1_byte, "use this argument");
3046
3047 const Register Rret = Lscratch;
3048 const Register O0_recv = O0;
3049 const Register Rscratch = G3_scratch;
|
2915 assert(ConstantPoolCacheEntry::_indy_resolved_references_appendix_offset == 0, "appendix expected at index+0");
2916 __ load_resolved_reference_at_index(temp, index);
2917 __ verify_oop(temp);
2918 __ push_ptr(temp); // push appendix (MethodType, CallSite, etc.)
2919 __ bind(L_no_push);
2920 }
2921
2922 // load receiver if needed (after appendix is pushed so parameter size is correct)
2923 if (load_receiver) {
2924 __ and3(flags, ConstantPoolCacheEntry::parameter_size_mask, temp); // get parameter size
2925 __ load_receiver(temp, recv); // __ argument_address uses Gargs but we need Lesp
2926 __ verify_oop(recv);
2927 }
2928
2929 // compute return type
2930 __ srl(flags, ConstantPoolCacheEntry::tos_state_shift, ra);
2931 // Make sure we don't need to mask flags after the above shift
2932 ConstantPoolCacheEntry::verify_tos_state_shift();
2933 // load return address
2934 {
2935 const address table_addr = (address) Interpreter::invoke_return_entry_table_for(code);
2936 AddressLiteral table(table_addr);
2937 __ set(table, temp);
2938 __ sll(ra, LogBytesPerWord, ra);
2939 __ ld_ptr(Address(temp, ra), ra);
2940 }
2941 }
2942
2943
2944 void TemplateTable::generate_vtable_call(Register Rrecv, Register Rindex, Register Rret) {
2945 Register Rtemp = G4_scratch;
2946 Register Rcall = Rindex;
2947 assert_different_registers(Rcall, G5_method, Gargs, Rret);
2948
2949 // get target Method* & entry point
2950 __ lookup_virtual_method(Rrecv, Rindex, G5_method);
2951 __ call_from_interpreter(Rcall, Gargs, Rret);
2952 }
2953
2954 void TemplateTable::invokevirtual(int byte_no) {
2955 transition(vtos, vtos);
2965 __ mov(SP, O5_savedSP); // record SP that we wanted the callee to restore
2966
2967 // Check for vfinal
2968 __ set((1 << ConstantPoolCacheEntry::is_vfinal_shift), G4_scratch);
2969 __ btst(Rret, G4_scratch);
2970 __ br(Assembler::zero, false, Assembler::pt, notFinal);
2971 __ delayed()->and3(Rret, 0xFF, G4_scratch); // gets number of parameters
2972
2973 patch_bytecode(Bytecodes::_fast_invokevfinal, Rscratch, Rtemp);
2974
2975 invokevfinal_helper(Rscratch, Rret);
2976
2977 __ bind(notFinal);
2978
2979 __ mov(G5_method, Rscratch); // better scratch register
2980 __ load_receiver(G4_scratch, O0_recv); // gets receiverOop
2981 // receiver is in O0_recv
2982 __ verify_oop(O0_recv);
2983
2984 // get return address
2985 AddressLiteral table(Interpreter::invoke_return_entry_table());
2986 __ set(table, Rtemp);
2987 __ srl(Rret, ConstantPoolCacheEntry::tos_state_shift, Rret); // get return type
2988 // Make sure we don't need to mask Rret after the above shift
2989 ConstantPoolCacheEntry::verify_tos_state_shift();
2990 __ sll(Rret, LogBytesPerWord, Rret);
2991 __ ld_ptr(Rtemp, Rret, Rret); // get return address
2992
2993 // get receiver klass
2994 __ null_check(O0_recv, oopDesc::klass_offset_in_bytes());
2995 __ load_klass(O0_recv, O0_recv);
2996 __ verify_klass_ptr(O0_recv);
2997
2998 __ profile_virtual_call(O0_recv, O4);
2999
3000 generate_vtable_call(O0_recv, Rscratch, Rret);
3001 }
3002
3003 void TemplateTable::fast_invokevfinal(int byte_no) {
3004 transition(vtos, vtos);
3005 assert(byte_no == f2_byte, "use this argument");
3007 load_invoke_cp_cache_entry(byte_no, G5_method, noreg, Lscratch, true,
3008 /*is_invokevfinal*/true, false);
3009 __ mov(SP, O5_savedSP); // record SP that we wanted the callee to restore
3010 invokevfinal_helper(G3_scratch, Lscratch);
3011 }
3012
3013 void TemplateTable::invokevfinal_helper(Register Rscratch, Register Rret) {
3014 Register Rtemp = G4_scratch;
3015
3016 // Load receiver from stack slot
3017 __ ld_ptr(G5_method, in_bytes(Method::const_offset()), G4_scratch);
3018 __ lduh(G4_scratch, in_bytes(ConstMethod::size_of_parameters_offset()), G4_scratch);
3019 __ load_receiver(G4_scratch, O0);
3020
3021 // receiver NULL check
3022 __ null_check(O0);
3023
3024 __ profile_final_call(O4);
3025
3026 // get return address
3027 AddressLiteral table(Interpreter::invoke_return_entry_table());
3028 __ set(table, Rtemp);
3029 __ srl(Rret, ConstantPoolCacheEntry::tos_state_shift, Rret); // get return type
3030 // Make sure we don't need to mask Rret after the above shift
3031 ConstantPoolCacheEntry::verify_tos_state_shift();
3032 __ sll(Rret, LogBytesPerWord, Rret);
3033 __ ld_ptr(Rtemp, Rret, Rret); // get return address
3034
3035
3036 // do the call
3037 __ call_from_interpreter(Rscratch, Gargs, Rret);
3038 }
3039
3040
3041 void TemplateTable::invokespecial(int byte_no) {
3042 transition(vtos, vtos);
3043 assert(byte_no == f1_byte, "use this argument");
3044
3045 const Register Rret = Lscratch;
3046 const Register O0_recv = O0;
3047 const Register Rscratch = G3_scratch;
|