143 mov(arg2, O2); assert(arg2 != O1, "smashed argument"); |
138 mov(arg2, O2); assert(arg2 != O1, "smashed argument"); |
144 mov(arg3, O3); assert(arg3 != O1 && arg3 != O2, "smashed argument"); |
139 mov(arg3, O3); assert(arg3 != O1 && arg3 != O2, "smashed argument"); |
145 return call_RT(oop_result1, metadata_result, entry, 3); |
140 return call_RT(oop_result1, metadata_result, entry, 3); |
146 } |
141 } |
147 |
142 |
|
143 void StubAssembler::prologue(const char* name, bool must_gc_arguments) { |
|
144 set_info(name, must_gc_arguments); |
|
145 } |
|
146 |
|
147 void StubAssembler::epilogue() { |
|
148 delayed()->restore(); |
|
149 } |
148 |
150 |
149 // Implementation of Runtime1 |
151 // Implementation of Runtime1 |
150 |
152 |
151 #define __ sasm-> |
|
152 |
153 |
153 static int cpu_reg_save_offsets[FrameMap::nof_cpu_regs]; |
154 static int cpu_reg_save_offsets[FrameMap::nof_cpu_regs]; |
154 static int fpu_reg_save_offsets[FrameMap::nof_fpu_regs]; |
155 static int fpu_reg_save_offsets[FrameMap::nof_fpu_regs]; |
155 static int reg_save_size_in_words; |
156 static int reg_save_size_in_words; |
156 static int frame_size_in_bytes = -1; |
157 static int frame_size_in_bytes = -1; |
157 |
158 |
158 static OopMap* generate_oop_map(StubAssembler* sasm, bool save_fpu_registers) { |
159 static OopMap* generate_oop_map(StubAssembler* sasm, bool save_fpu_registers) { |
159 assert(frame_size_in_bytes == __ total_frame_size_in_bytes(reg_save_size_in_words), |
160 assert(frame_size_in_bytes == sasm->total_frame_size_in_bytes(reg_save_size_in_words), |
160 "mismatch in calculation"); |
161 "mismatch in calculation"); |
161 sasm->set_frame_size(frame_size_in_bytes / BytesPerWord); |
162 sasm->set_frame_size(frame_size_in_bytes / BytesPerWord); |
162 int frame_size_in_slots = frame_size_in_bytes / sizeof(jint); |
163 int frame_size_in_slots = frame_size_in_bytes / sizeof(jint); |
163 OopMap* oop_map = new OopMap(frame_size_in_slots, 0); |
164 OopMap* oop_map = new OopMap(frame_size_in_slots, 0); |
164 |
165 |
757 __ ret(); |
770 __ ret(); |
758 __ delayed()->restore(); |
771 __ delayed()->restore(); |
759 } |
772 } |
760 break; |
773 break; |
761 |
774 |
762 #if INCLUDE_ALL_GCS |
|
763 case g1_pre_barrier_slow_id: |
|
764 { // G4: previous value of memory |
|
765 BarrierSet* bs = BarrierSet::barrier_set(); |
|
766 if (bs->kind() != BarrierSet::G1BarrierSet) { |
|
767 __ save_frame(0); |
|
768 __ set((int)id, O1); |
|
769 __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, unimplemented_entry), I0); |
|
770 __ should_not_reach_here(); |
|
771 break; |
|
772 } |
|
773 |
|
774 __ set_info("g1_pre_barrier_slow_id", dont_gc_arguments); |
|
775 |
|
776 Register pre_val = G4; |
|
777 Register tmp = G1_scratch; |
|
778 Register tmp2 = G3_scratch; |
|
779 |
|
780 Label refill, restart; |
|
781 int satb_q_active_byte_offset = in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()); |
|
782 int satb_q_index_byte_offset = in_bytes(G1ThreadLocalData::satb_mark_queue_index_offset()); |
|
783 int satb_q_buf_byte_offset = in_bytes(G1ThreadLocalData::satb_mark_queue_buffer_offset()); |
|
784 |
|
785 // Is marking still active? |
|
786 if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) { |
|
787 __ ld(G2_thread, satb_q_active_byte_offset, tmp); |
|
788 } else { |
|
789 assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption"); |
|
790 __ ldsb(G2_thread, satb_q_active_byte_offset, tmp); |
|
791 } |
|
792 __ cmp_and_br_short(tmp, G0, Assembler::notEqual, Assembler::pt, restart); |
|
793 __ retl(); |
|
794 __ delayed()->nop(); |
|
795 |
|
796 __ bind(restart); |
|
797 // Load the index into the SATB buffer. SATBMarkQueue::_index is a |
|
798 // size_t so ld_ptr is appropriate |
|
799 __ ld_ptr(G2_thread, satb_q_index_byte_offset, tmp); |
|
800 |
|
801 // index == 0? |
|
802 __ cmp_and_brx_short(tmp, G0, Assembler::equal, Assembler::pn, refill); |
|
803 |
|
804 __ ld_ptr(G2_thread, satb_q_buf_byte_offset, tmp2); |
|
805 __ sub(tmp, oopSize, tmp); |
|
806 |
|
807 __ st_ptr(pre_val, tmp2, tmp); // [_buf + index] := <address_of_card> |
|
808 // Use return-from-leaf |
|
809 __ retl(); |
|
810 __ delayed()->st_ptr(tmp, G2_thread, satb_q_index_byte_offset); |
|
811 |
|
812 __ bind(refill); |
|
813 |
|
814 save_live_registers(sasm); |
|
815 |
|
816 __ call_VM_leaf(L7_thread_cache, |
|
817 CAST_FROM_FN_PTR(address, |
|
818 SATBMarkQueueSet::handle_zero_index_for_thread), |
|
819 G2_thread); |
|
820 |
|
821 restore_live_registers(sasm); |
|
822 |
|
823 __ br(Assembler::always, /*annul*/false, Assembler::pt, restart); |
|
824 __ delayed()->restore(); |
|
825 } |
|
826 break; |
|
827 |
|
828 case g1_post_barrier_slow_id: |
|
829 { |
|
830 BarrierSet* bs = BarrierSet::barrier_set(); |
|
831 if (bs->kind() != BarrierSet::G1BarrierSet) { |
|
832 __ save_frame(0); |
|
833 __ set((int)id, O1); |
|
834 __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, unimplemented_entry), I0); |
|
835 __ should_not_reach_here(); |
|
836 break; |
|
837 } |
|
838 |
|
839 __ set_info("g1_post_barrier_slow_id", dont_gc_arguments); |
|
840 |
|
841 Register addr = G4; |
|
842 Register cardtable = G5; |
|
843 Register tmp = G1_scratch; |
|
844 Register tmp2 = G3_scratch; |
|
845 jbyte* byte_map_base = ci_card_table_address(); |
|
846 |
|
847 Label not_already_dirty, restart, refill, young_card; |
|
848 |
|
849 __ srlx(addr, CardTable::card_shift, addr); |
|
850 |
|
851 AddressLiteral rs(byte_map_base); |
|
852 __ set(rs, cardtable); // cardtable := <card table base> |
|
853 __ ldub(addr, cardtable, tmp); // tmp := [addr + cardtable] |
|
854 |
|
855 __ cmp_and_br_short(tmp, G1CardTable::g1_young_card_val(), Assembler::equal, Assembler::pt, young_card); |
|
856 |
|
857 __ membar(Assembler::Membar_mask_bits(Assembler::StoreLoad)); |
|
858 __ ldub(addr, cardtable, tmp); // tmp := [addr + cardtable] |
|
859 |
|
860 assert(CardTable::dirty_card_val() == 0, "otherwise check this code"); |
|
861 __ cmp_and_br_short(tmp, G0, Assembler::notEqual, Assembler::pt, not_already_dirty); |
|
862 |
|
863 __ bind(young_card); |
|
864 // We didn't take the branch, so we're already dirty: return. |
|
865 // Use return-from-leaf |
|
866 __ retl(); |
|
867 __ delayed()->nop(); |
|
868 |
|
869 // Not dirty. |
|
870 __ bind(not_already_dirty); |
|
871 |
|
872 // Get cardtable + tmp into a reg by itself |
|
873 __ add(addr, cardtable, tmp2); |
|
874 |
|
875 // First, dirty it. |
|
876 __ stb(G0, tmp2, 0); // [cardPtr] := 0 (i.e., dirty). |
|
877 |
|
878 Register tmp3 = cardtable; |
|
879 Register tmp4 = tmp; |
|
880 |
|
881 // these registers are now dead |
|
882 addr = cardtable = tmp = noreg; |
|
883 |
|
884 int dirty_card_q_index_byte_offset = in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset()); |
|
885 int dirty_card_q_buf_byte_offset = in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset()); |
|
886 |
|
887 __ bind(restart); |
|
888 |
|
889 // Get the index into the update buffer. DirtyCardQueue::_index is |
|
890 // a size_t so ld_ptr is appropriate here. |
|
891 __ ld_ptr(G2_thread, dirty_card_q_index_byte_offset, tmp3); |
|
892 |
|
893 // index == 0? |
|
894 __ cmp_and_brx_short(tmp3, G0, Assembler::equal, Assembler::pn, refill); |
|
895 |
|
896 __ ld_ptr(G2_thread, dirty_card_q_buf_byte_offset, tmp4); |
|
897 __ sub(tmp3, oopSize, tmp3); |
|
898 |
|
899 __ st_ptr(tmp2, tmp4, tmp3); // [_buf + index] := <address_of_card> |
|
900 // Use return-from-leaf |
|
901 __ retl(); |
|
902 __ delayed()->st_ptr(tmp3, G2_thread, dirty_card_q_index_byte_offset); |
|
903 |
|
904 __ bind(refill); |
|
905 |
|
906 save_live_registers(sasm); |
|
907 |
|
908 __ call_VM_leaf(L7_thread_cache, |
|
909 CAST_FROM_FN_PTR(address, |
|
910 DirtyCardQueueSet::handle_zero_index_for_thread), |
|
911 G2_thread); |
|
912 |
|
913 restore_live_registers(sasm); |
|
914 |
|
915 __ br(Assembler::always, /*annul*/false, Assembler::pt, restart); |
|
916 __ delayed()->restore(); |
|
917 } |
|
918 break; |
|
919 #endif // INCLUDE_ALL_GCS |
|
920 |
|
921 case predicate_failed_trap_id: |
775 case predicate_failed_trap_id: |
922 { |
776 { |
923 __ set_info("predicate_failed_trap", dont_gc_arguments); |
777 __ set_info("predicate_failed_trap", dont_gc_arguments); |
924 OopMap* oop_map = save_live_registers(sasm); |
778 OopMap* oop_map = save_live_registers(sasm); |
925 |
779 |