727 // Generate pre-barrier for array stores |
727 // Generate pre-barrier for array stores |
728 // |
728 // |
729 // Input: |
729 // Input: |
730 // start - starting address |
730 // start - starting address |
731 // count - element count |
731 // count - element count |
732 void gen_write_ref_array_pre_barrier(Register start, Register count) { |
732 void gen_write_ref_array_pre_barrier(Register start, Register count, bool uninitialized_target) { |
733 assert_different_registers(start, count); |
733 assert_different_registers(start, count); |
734 BarrierSet* bs = Universe::heap()->barrier_set(); |
734 BarrierSet* bs = Universe::heap()->barrier_set(); |
735 switch (bs->kind()) { |
735 switch (bs->kind()) { |
736 case BarrierSet::G1SATBCT: |
736 case BarrierSet::G1SATBCT: |
737 case BarrierSet::G1SATBCTLogging: |
737 case BarrierSet::G1SATBCTLogging: |
738 { |
738 // With G1, don't generate the call if we statically know that the target in uninitialized |
739 __ pusha(); // push registers |
739 if (!uninitialized_target) { |
740 __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre), |
740 __ pusha(); // push registers |
741 start, count); |
741 __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre), |
742 __ popa(); |
742 start, count); |
743 } |
743 __ popa(); |
|
744 } |
744 break; |
745 break; |
745 case BarrierSet::CardTableModRef: |
746 case BarrierSet::CardTableModRef: |
746 case BarrierSet::CardTableExtension: |
747 case BarrierSet::CardTableExtension: |
747 case BarrierSet::ModRef: |
748 case BarrierSet::ModRef: |
748 break; |
749 break; |
917 __ emms(); |
918 __ emms(); |
918 } |
919 } |
919 |
920 |
920 address generate_disjoint_copy(BasicType t, bool aligned, |
921 address generate_disjoint_copy(BasicType t, bool aligned, |
921 Address::ScaleFactor sf, |
922 Address::ScaleFactor sf, |
922 address* entry, const char *name) { |
923 address* entry, const char *name, |
|
924 bool dest_uninitialized = false) { |
923 __ align(CodeEntryAlignment); |
925 __ align(CodeEntryAlignment); |
924 StubCodeMark mark(this, "StubRoutines", name); |
926 StubCodeMark mark(this, "StubRoutines", name); |
925 address start = __ pc(); |
927 address start = __ pc(); |
926 |
928 |
927 Label L_0_count, L_exit, L_skip_align1, L_skip_align2, L_copy_byte; |
929 Label L_0_count, L_exit, L_skip_align1, L_skip_align2, L_copy_byte; |
948 } |
950 } |
949 |
951 |
950 if (t == T_OBJECT) { |
952 if (t == T_OBJECT) { |
951 __ testl(count, count); |
953 __ testl(count, count); |
952 __ jcc(Assembler::zero, L_0_count); |
954 __ jcc(Assembler::zero, L_0_count); |
953 gen_write_ref_array_pre_barrier(to, count); |
955 gen_write_ref_array_pre_barrier(to, count, dest_uninitialized); |
954 __ mov(saved_to, to); // save 'to' |
956 __ mov(saved_to, to); // save 'to' |
955 } |
957 } |
956 |
958 |
957 __ subptr(to, from); // to --> to_from |
959 __ subptr(to, from); // to --> to_from |
958 __ cmpl(count, 2<<shift); // Short arrays (< 8 bytes) copy by element |
960 __ cmpl(count, 2<<shift); // Short arrays (< 8 bytes) copy by element |
1082 } |
1084 } |
1083 |
1085 |
1084 address generate_conjoint_copy(BasicType t, bool aligned, |
1086 address generate_conjoint_copy(BasicType t, bool aligned, |
1085 Address::ScaleFactor sf, |
1087 Address::ScaleFactor sf, |
1086 address nooverlap_target, |
1088 address nooverlap_target, |
1087 address* entry, const char *name) { |
1089 address* entry, const char *name, |
|
1090 bool dest_uninitialized = false) { |
1088 __ align(CodeEntryAlignment); |
1091 __ align(CodeEntryAlignment); |
1089 StubCodeMark mark(this, "StubRoutines", name); |
1092 StubCodeMark mark(this, "StubRoutines", name); |
1090 address start = __ pc(); |
1093 address start = __ pc(); |
1091 |
1094 |
1092 Label L_0_count, L_exit, L_skip_align1, L_skip_align2, L_copy_byte; |
1095 Label L_0_count, L_exit, L_skip_align1, L_skip_align2, L_copy_byte; |
1126 __ jump_cc(Assembler::aboveEqual, nooverlap); |
1129 __ jump_cc(Assembler::aboveEqual, nooverlap); |
1127 |
1130 |
1128 if (t == T_OBJECT) { |
1131 if (t == T_OBJECT) { |
1129 __ testl(count, count); |
1132 __ testl(count, count); |
1130 __ jcc(Assembler::zero, L_0_count); |
1133 __ jcc(Assembler::zero, L_0_count); |
1131 gen_write_ref_array_pre_barrier(dst, count); |
1134 gen_write_ref_array_pre_barrier(dst, count, dest_uninitialized); |
1132 } |
1135 } |
1133 |
1136 |
1134 // copy from high to low |
1137 // copy from high to low |
1135 __ cmpl(count, 2<<shift); // Short arrays (< 8 bytes) copy by element |
1138 __ cmpl(count, 2<<shift); // Short arrays (< 8 bytes) copy by element |
1136 __ jcc(Assembler::below, L_copy_4_bytes); // use unsigned cmp |
1139 __ jcc(Assembler::below, L_copy_4_bytes); // use unsigned cmp |
1413 // |
1416 // |
1414 // Output: |
1417 // Output: |
1415 // rax, == 0 - success |
1418 // rax, == 0 - success |
1416 // rax, == -1^K - failure, where K is partial transfer count |
1419 // rax, == -1^K - failure, where K is partial transfer count |
1417 // |
1420 // |
1418 address generate_checkcast_copy(const char *name, address* entry) { |
1421 address generate_checkcast_copy(const char *name, address* entry, bool dest_uninitialized = false) { |
1419 __ align(CodeEntryAlignment); |
1422 __ align(CodeEntryAlignment); |
1420 StubCodeMark mark(this, "StubRoutines", name); |
1423 StubCodeMark mark(this, "StubRoutines", name); |
1421 address start = __ pc(); |
1424 address start = __ pc(); |
1422 |
1425 |
1423 Label L_load_element, L_store_element, L_do_card_marks, L_done; |
1426 Label L_load_element, L_store_element, L_do_card_marks, L_done; |
1474 Address from_element_addr(end_from, count, Address::times_ptr, 0); |
1477 Address from_element_addr(end_from, count, Address::times_ptr, 0); |
1475 Address to_element_addr(end_to, count, Address::times_ptr, 0); |
1478 Address to_element_addr(end_to, count, Address::times_ptr, 0); |
1476 Address elem_klass_addr(elem, oopDesc::klass_offset_in_bytes()); |
1479 Address elem_klass_addr(elem, oopDesc::klass_offset_in_bytes()); |
1477 |
1480 |
1478 // Copy from low to high addresses, indexed from the end of each array. |
1481 // Copy from low to high addresses, indexed from the end of each array. |
1479 gen_write_ref_array_pre_barrier(to, count); |
1482 gen_write_ref_array_pre_barrier(to, count, dest_uninitialized); |
1480 __ lea(end_from, end_from_addr); |
1483 __ lea(end_from, end_from_addr); |
1481 __ lea(end_to, end_to_addr); |
1484 __ lea(end_to, end_to_addr); |
1482 assert(length == count, ""); // else fix next line: |
1485 assert(length == count, ""); // else fix next line: |
1483 __ negptr(count); // negate and test the length |
1486 __ negptr(count); // negate and test the length |
1484 __ jccb(Assembler::notZero, L_load_element); |
1487 __ jccb(Assembler::notZero, L_load_element); |
2037 "oop_disjoint_arraycopy"); |
2040 "oop_disjoint_arraycopy"); |
2038 StubRoutines::_oop_arraycopy = |
2041 StubRoutines::_oop_arraycopy = |
2039 generate_conjoint_copy(T_OBJECT, true, Address::times_ptr, entry, |
2042 generate_conjoint_copy(T_OBJECT, true, Address::times_ptr, entry, |
2040 &entry_oop_arraycopy, "oop_arraycopy"); |
2043 &entry_oop_arraycopy, "oop_arraycopy"); |
2041 |
2044 |
|
2045 StubRoutines::_oop_disjoint_arraycopy_uninit = |
|
2046 generate_disjoint_copy(T_OBJECT, true, Address::times_ptr, &entry, |
|
2047 "oop_disjoint_arraycopy_uninit", |
|
2048 /*dest_uninitialized*/true); |
|
2049 StubRoutines::_oop_arraycopy_uninit = |
|
2050 generate_conjoint_copy(T_OBJECT, true, Address::times_ptr, entry, |
|
2051 NULL, "oop_arraycopy_uninit", |
|
2052 /*dest_uninitialized*/true); |
|
2053 |
2042 StubRoutines::_jlong_disjoint_arraycopy = |
2054 StubRoutines::_jlong_disjoint_arraycopy = |
2043 generate_disjoint_long_copy(&entry, "jlong_disjoint_arraycopy"); |
2055 generate_disjoint_long_copy(&entry, "jlong_disjoint_arraycopy"); |
2044 StubRoutines::_jlong_arraycopy = |
2056 StubRoutines::_jlong_arraycopy = |
2045 generate_conjoint_long_copy(entry, &entry_jlong_arraycopy, |
2057 generate_conjoint_long_copy(entry, &entry_jlong_arraycopy, |
2046 "jlong_arraycopy"); |
2058 "jlong_arraycopy"); |
2050 StubRoutines::_jint_fill = generate_fill(T_INT, false, "jint_fill"); |
2062 StubRoutines::_jint_fill = generate_fill(T_INT, false, "jint_fill"); |
2051 StubRoutines::_arrayof_jbyte_fill = generate_fill(T_BYTE, true, "arrayof_jbyte_fill"); |
2063 StubRoutines::_arrayof_jbyte_fill = generate_fill(T_BYTE, true, "arrayof_jbyte_fill"); |
2052 StubRoutines::_arrayof_jshort_fill = generate_fill(T_SHORT, true, "arrayof_jshort_fill"); |
2064 StubRoutines::_arrayof_jshort_fill = generate_fill(T_SHORT, true, "arrayof_jshort_fill"); |
2053 StubRoutines::_arrayof_jint_fill = generate_fill(T_INT, true, "arrayof_jint_fill"); |
2065 StubRoutines::_arrayof_jint_fill = generate_fill(T_INT, true, "arrayof_jint_fill"); |
2054 |
2066 |
2055 StubRoutines::_arrayof_jint_disjoint_arraycopy = |
2067 StubRoutines::_arrayof_jint_disjoint_arraycopy = StubRoutines::_jint_disjoint_arraycopy; |
2056 StubRoutines::_jint_disjoint_arraycopy; |
2068 StubRoutines::_arrayof_oop_disjoint_arraycopy = StubRoutines::_oop_disjoint_arraycopy; |
2057 StubRoutines::_arrayof_oop_disjoint_arraycopy = |
2069 StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit = StubRoutines::_oop_disjoint_arraycopy_uninit; |
2058 StubRoutines::_oop_disjoint_arraycopy; |
2070 StubRoutines::_arrayof_jlong_disjoint_arraycopy = StubRoutines::_jlong_disjoint_arraycopy; |
2059 StubRoutines::_arrayof_jlong_disjoint_arraycopy = |
2071 |
2060 StubRoutines::_jlong_disjoint_arraycopy; |
2072 StubRoutines::_arrayof_jint_arraycopy = StubRoutines::_jint_arraycopy; |
2061 |
2073 StubRoutines::_arrayof_oop_arraycopy = StubRoutines::_oop_arraycopy; |
2062 StubRoutines::_arrayof_jint_arraycopy = StubRoutines::_jint_arraycopy; |
2074 StubRoutines::_arrayof_oop_arraycopy_uninit = StubRoutines::_oop_arraycopy_uninit; |
2063 StubRoutines::_arrayof_oop_arraycopy = StubRoutines::_oop_arraycopy; |
2075 StubRoutines::_arrayof_jlong_arraycopy = StubRoutines::_jlong_arraycopy; |
2064 StubRoutines::_arrayof_jlong_arraycopy = StubRoutines::_jlong_arraycopy; |
|
2065 |
2076 |
2066 StubRoutines::_checkcast_arraycopy = |
2077 StubRoutines::_checkcast_arraycopy = |
2067 generate_checkcast_copy("checkcast_arraycopy", |
2078 generate_checkcast_copy("checkcast_arraycopy", &entry_checkcast_arraycopy); |
2068 &entry_checkcast_arraycopy); |
2079 StubRoutines::_checkcast_arraycopy_uninit = |
|
2080 generate_checkcast_copy("checkcast_arraycopy_uninit", NULL, /*dest_uninitialized*/true); |
2069 |
2081 |
2070 StubRoutines::_unsafe_arraycopy = |
2082 StubRoutines::_unsafe_arraycopy = |
2071 generate_unsafe_copy("unsafe_arraycopy", |
2083 generate_unsafe_copy("unsafe_arraycopy", |
2072 entry_jbyte_arraycopy, |
2084 entry_jbyte_arraycopy, |
2073 entry_jshort_arraycopy, |
2085 entry_jshort_arraycopy, |