Mercurial > hg > truffle
comparison src/cpu/x86/vm/stubGenerator_x86_32.cpp @ 2324:0ac769a57c64
6627983: G1: Bad oop deference during marking
Summary: Bulk zeroing reduction didn't work with G1, because arraycopy would call pre-barriers on uninitialized oops. The solution is to have version of arraycopy stubs that don't have pre-barriers. Also refactored arraycopy stubs generation on SPARC to be more readable and reduced the number of stubs necessary in some cases.
Reviewed-by: jrose, kvn, never
author | iveresov |
---|---|
date | Tue, 01 Mar 2011 14:56:48 -0800 |
parents | 1b4e6a5d98e0 |
children | 38fa55e5e792 |
comparison
equal
deleted
inserted
replaced
2323:bc6b27fb3568 | 2324:0ac769a57c64 |
---|---|
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, |