723 void MacroAssembler::jump(const AddressLiteral& addrlit, Register temp, int offset, const char* file, int line) { |
723 void MacroAssembler::jump(const AddressLiteral& addrlit, Register temp, int offset, const char* file, int line) { |
724 jumpl(addrlit, temp, G0, offset, file, line); |
724 jumpl(addrlit, temp, G0, offset, file, line); |
725 } |
725 } |
726 |
726 |
727 |
727 |
728 // Convert to C varargs format |
|
729 void MacroAssembler::set_varargs( Argument inArg, Register d ) { |
|
730 // spill register-resident args to their memory slots |
|
731 // (SPARC calling convention requires callers to have already preallocated these) |
|
732 // Note that the inArg might in fact be an outgoing argument, |
|
733 // if a leaf routine or stub does some tricky argument shuffling. |
|
734 // This routine must work even though one of the saved arguments |
|
735 // is in the d register (e.g., set_varargs(Argument(0, false), O0)). |
|
736 for (Argument savePtr = inArg; |
|
737 savePtr.is_register(); |
|
738 savePtr = savePtr.successor()) { |
|
739 st_ptr(savePtr.as_register(), savePtr.address_in_frame()); |
|
740 } |
|
741 // return the address of the first memory slot |
|
742 Address a = inArg.address_in_frame(); |
|
743 add(a.base(), a.disp(), d); |
|
744 } |
|
745 |
|
746 // Conditional breakpoint (for assertion checks in assembly code) |
728 // Conditional breakpoint (for assertion checks in assembly code) |
747 void MacroAssembler::breakpoint_trap(Condition c, CC cc) { |
729 void MacroAssembler::breakpoint_trap(Condition c, CC cc) { |
748 trap(c, cc, G0, ST_RESERVED_FOR_USER_0); |
730 trap(c, cc, G0, ST_RESERVED_FOR_USER_0); |
749 } |
731 } |
750 |
732 |
2941 Label& L_no_such_interface) { |
2923 Label& L_no_such_interface) { |
2942 assert_different_registers(recv_klass, intf_klass, method_result, scan_temp); |
2924 assert_different_registers(recv_klass, intf_klass, method_result, scan_temp); |
2943 assert(itable_index.is_constant() || itable_index.as_register() == method_result, |
2925 assert(itable_index.is_constant() || itable_index.as_register() == method_result, |
2944 "caller must use same register for non-constant itable index as for method"); |
2926 "caller must use same register for non-constant itable index as for method"); |
2945 |
2927 |
|
2928 Label L_no_such_interface_restore; |
|
2929 bool did_save = false; |
|
2930 if (scan_temp == noreg || sethi_temp == noreg) { |
|
2931 Register recv_2 = recv_klass->is_global() ? recv_klass : L0; |
|
2932 Register intf_2 = intf_klass->is_global() ? intf_klass : L1; |
|
2933 assert(method_result->is_global(), "must be able to return value"); |
|
2934 scan_temp = L2; |
|
2935 sethi_temp = L3; |
|
2936 save_frame_and_mov(0, recv_klass, recv_2, intf_klass, intf_2); |
|
2937 recv_klass = recv_2; |
|
2938 intf_klass = intf_2; |
|
2939 did_save = true; |
|
2940 } |
|
2941 |
2946 // Compute start of first itableOffsetEntry (which is at the end of the vtable) |
2942 // Compute start of first itableOffsetEntry (which is at the end of the vtable) |
2947 int vtable_base = InstanceKlass::vtable_start_offset() * wordSize; |
2943 int vtable_base = InstanceKlass::vtable_start_offset() * wordSize; |
2948 int scan_step = itableOffsetEntry::size() * wordSize; |
2944 int scan_step = itableOffsetEntry::size() * wordSize; |
2949 int vte_size = vtableEntry::size() * wordSize; |
2945 int vte_size = vtableEntry::size() * wordSize; |
2950 |
2946 |
2979 // for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) { |
2975 // for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) { |
2980 // if (scan->interface() == intf) { |
2976 // if (scan->interface() == intf) { |
2981 // result = (klass + scan->offset() + itable_index); |
2977 // result = (klass + scan->offset() + itable_index); |
2982 // } |
2978 // } |
2983 // } |
2979 // } |
2984 Label search, found_method; |
2980 Label L_search, L_found_method; |
2985 |
2981 |
2986 for (int peel = 1; peel >= 0; peel--) { |
2982 for (int peel = 1; peel >= 0; peel--) { |
2987 // %%%% Could load both offset and interface in one ldx, if they were |
2983 // %%%% Could load both offset and interface in one ldx, if they were |
2988 // in the opposite order. This would save a load. |
2984 // in the opposite order. This would save a load. |
2989 ld_ptr(scan_temp, itableOffsetEntry::interface_offset_in_bytes(), method_result); |
2985 ld_ptr(scan_temp, itableOffsetEntry::interface_offset_in_bytes(), method_result); |
2990 |
2986 |
2991 // Check that this entry is non-null. A null entry means that |
2987 // Check that this entry is non-null. A null entry means that |
2992 // the receiver class doesn't implement the interface, and wasn't the |
2988 // the receiver class doesn't implement the interface, and wasn't the |
2993 // same as when the caller was compiled. |
2989 // same as when the caller was compiled. |
2994 bpr(Assembler::rc_z, false, Assembler::pn, method_result, L_no_such_interface); |
2990 bpr(Assembler::rc_z, false, Assembler::pn, method_result, did_save ? L_no_such_interface_restore : L_no_such_interface); |
2995 delayed()->cmp(method_result, intf_klass); |
2991 delayed()->cmp(method_result, intf_klass); |
2996 |
2992 |
2997 if (peel) { |
2993 if (peel) { |
2998 brx(Assembler::equal, false, Assembler::pt, found_method); |
2994 brx(Assembler::equal, false, Assembler::pt, L_found_method); |
2999 } else { |
2995 } else { |
3000 brx(Assembler::notEqual, false, Assembler::pn, search); |
2996 brx(Assembler::notEqual, false, Assembler::pn, L_search); |
3001 // (invert the test to fall through to found_method...) |
2997 // (invert the test to fall through to found_method...) |
3002 } |
2998 } |
3003 delayed()->add(scan_temp, scan_step, scan_temp); |
2999 delayed()->add(scan_temp, scan_step, scan_temp); |
3004 |
3000 |
3005 if (!peel) break; |
3001 if (!peel) break; |
3006 |
3002 |
3007 bind(search); |
3003 bind(L_search); |
3008 } |
3004 } |
3009 |
3005 |
3010 bind(found_method); |
3006 bind(L_found_method); |
3011 |
3007 |
3012 // Got a hit. |
3008 // Got a hit. |
3013 int ito_offset = itableOffsetEntry::offset_offset_in_bytes(); |
3009 int ito_offset = itableOffsetEntry::offset_offset_in_bytes(); |
3014 // scan_temp[-scan_step] points to the vtable offset we need |
3010 // scan_temp[-scan_step] points to the vtable offset we need |
3015 ito_offset -= scan_step; |
3011 ito_offset -= scan_step; |
3016 lduw(scan_temp, ito_offset, scan_temp); |
3012 lduw(scan_temp, ito_offset, scan_temp); |
3017 ld_ptr(recv_klass, scan_temp, method_result); |
3013 ld_ptr(recv_klass, scan_temp, method_result); |
|
3014 |
|
3015 if (did_save) { |
|
3016 Label L_done; |
|
3017 ba(L_done); |
|
3018 delayed()->restore(); |
|
3019 |
|
3020 bind(L_no_such_interface_restore); |
|
3021 ba(L_no_such_interface); |
|
3022 delayed()->restore(); |
|
3023 |
|
3024 bind(L_done); |
|
3025 } |
3018 } |
3026 } |
3019 |
3027 |
3020 |
3028 |
3021 // virtual method calling |
3029 // virtual method calling |
3022 void MacroAssembler::lookup_virtual_method(Register recv_klass, |
3030 void MacroAssembler::lookup_virtual_method(Register recv_klass, |