Mercurial > hg > graal-jvmci-8
comparison src/cpu/x86/vm/templateTable_x86_32.cpp @ 342:37f87013dfd8
6711316: Open source the Garbage-First garbage collector
Summary: First mercurial integration of the code for the Garbage-First garbage collector.
Reviewed-by: apetrusenko, iveresov, jmasa, sgoldman, tonyp, ysr
author | ysr |
---|---|
date | Thu, 05 Jun 2008 15:57:56 -0700 |
parents | 93b6525e3b82 |
children | 1ee8caae33af |
comparison
equal
deleted
inserted
replaced
189:0b27f3512f9e | 342:37f87013dfd8 |
---|---|
104 } | 104 } |
105 | 105 |
106 | 106 |
107 //---------------------------------------------------------------------------------------------------- | 107 //---------------------------------------------------------------------------------------------------- |
108 // Miscelaneous helper routines | 108 // Miscelaneous helper routines |
109 | |
110 // Store an oop (or NULL) at the address described by obj. | |
111 // If val == noreg this means store a NULL | |
112 | |
113 static void do_oop_store(InterpreterMacroAssembler* _masm, | |
114 Address obj, | |
115 Register val, | |
116 BarrierSet::Name barrier, | |
117 bool precise) { | |
118 assert(val == noreg || val == rax, "parameter is just for looks"); | |
119 switch (barrier) { | |
120 #ifndef SERIALGC | |
121 case BarrierSet::G1SATBCT: | |
122 case BarrierSet::G1SATBCTLogging: | |
123 { | |
124 // flatten object address if needed | |
125 // We do it regardless of precise because we need the registers | |
126 if (obj.index() == noreg && obj.disp() == 0) { | |
127 if (obj.base() != rdx) { | |
128 __ movl(rdx, obj.base()); | |
129 } | |
130 } else { | |
131 __ leal(rdx, obj); | |
132 } | |
133 __ get_thread(rcx); | |
134 __ save_bcp(); | |
135 __ g1_write_barrier_pre(rdx, rcx, rsi, rbx, val != noreg); | |
136 | |
137 // Do the actual store | |
138 // noreg means NULL | |
139 if (val == noreg) { | |
140 __ movl(Address(rdx, 0), NULL_WORD); | |
141 // No post barrier for NULL | |
142 } else { | |
143 __ movl(Address(rdx, 0), val); | |
144 __ g1_write_barrier_post(rdx, rax, rcx, rbx, rsi); | |
145 } | |
146 __ restore_bcp(); | |
147 | |
148 } | |
149 break; | |
150 #endif // SERIALGC | |
151 case BarrierSet::CardTableModRef: | |
152 case BarrierSet::CardTableExtension: | |
153 { | |
154 if (val == noreg) { | |
155 __ movl(obj, NULL_WORD); | |
156 } else { | |
157 __ movl(obj, val); | |
158 // flatten object address if needed | |
159 if (!precise || (obj.index() == noreg && obj.disp() == 0)) { | |
160 __ store_check(obj.base()); | |
161 } else { | |
162 __ leal(rdx, obj); | |
163 __ store_check(rdx); | |
164 } | |
165 } | |
166 } | |
167 break; | |
168 case BarrierSet::ModRef: | |
169 case BarrierSet::Other: | |
170 if (val == noreg) { | |
171 __ movl(obj, NULL_WORD); | |
172 } else { | |
173 __ movl(obj, val); | |
174 } | |
175 break; | |
176 default : | |
177 ShouldNotReachHere(); | |
178 | |
179 } | |
180 } | |
109 | 181 |
110 Address TemplateTable::at_bcp(int offset) { | 182 Address TemplateTable::at_bcp(int offset) { |
111 assert(_desc->uses_bcp(), "inconsistent uses_bcp information"); | 183 assert(_desc->uses_bcp(), "inconsistent uses_bcp information"); |
112 return Address(rsi, offset); | 184 return Address(rsi, offset); |
113 } | 185 } |
870 transition(vtos, vtos); | 942 transition(vtos, vtos); |
871 // stack: ..., array, index, value | 943 // stack: ..., array, index, value |
872 __ movl(rax, at_tos()); // Value | 944 __ movl(rax, at_tos()); // Value |
873 __ movl(rcx, at_tos_p1()); // Index | 945 __ movl(rcx, at_tos_p1()); // Index |
874 __ movl(rdx, at_tos_p2()); // Array | 946 __ movl(rdx, at_tos_p2()); // Array |
947 | |
948 Address element_address(rdx, rcx, Address::times_4, arrayOopDesc::base_offset_in_bytes(T_OBJECT)); | |
875 index_check_without_pop(rdx, rcx); // kills rbx, | 949 index_check_without_pop(rdx, rcx); // kills rbx, |
876 // do array store check - check for NULL value first | 950 // do array store check - check for NULL value first |
877 __ testl(rax, rax); | 951 __ testl(rax, rax); |
878 __ jcc(Assembler::zero, is_null); | 952 __ jcc(Assembler::zero, is_null); |
879 | 953 |
881 __ movl(rbx, Address(rax, oopDesc::klass_offset_in_bytes())); | 955 __ movl(rbx, Address(rax, oopDesc::klass_offset_in_bytes())); |
882 // Move superklass into EAX | 956 // Move superklass into EAX |
883 __ movl(rax, Address(rdx, oopDesc::klass_offset_in_bytes())); | 957 __ movl(rax, Address(rdx, oopDesc::klass_offset_in_bytes())); |
884 __ movl(rax, Address(rax, sizeof(oopDesc) + objArrayKlass::element_klass_offset_in_bytes())); | 958 __ movl(rax, Address(rax, sizeof(oopDesc) + objArrayKlass::element_klass_offset_in_bytes())); |
885 // Compress array+index*4+12 into a single register. Frees ECX. | 959 // Compress array+index*4+12 into a single register. Frees ECX. |
886 __ leal(rdx, Address(rdx, rcx, Address::times_4, arrayOopDesc::base_offset_in_bytes(T_OBJECT))); | 960 __ leal(rdx, element_address); |
887 | 961 |
888 // Generate subtype check. Blows ECX. Resets EDI to locals. | 962 // Generate subtype check. Blows ECX. Resets EDI to locals. |
889 // Superklass in EAX. Subklass in EBX. | 963 // Superklass in EAX. Subklass in EBX. |
890 __ gen_subtype_check( rbx, ok_is_subtype ); | 964 __ gen_subtype_check( rbx, ok_is_subtype ); |
891 | 965 |
893 // object is at TOS | 967 // object is at TOS |
894 __ jump(ExternalAddress(Interpreter::_throw_ArrayStoreException_entry)); | 968 __ jump(ExternalAddress(Interpreter::_throw_ArrayStoreException_entry)); |
895 | 969 |
896 // Come here on success | 970 // Come here on success |
897 __ bind(ok_is_subtype); | 971 __ bind(ok_is_subtype); |
898 __ movl(rax, at_rsp()); // Value | 972 |
899 __ movl(Address(rdx, 0), rax); | 973 // Get the value to store |
900 __ store_check(rdx); | 974 __ movl(rax, at_rsp()); |
901 __ jmpb(done); | 975 // and store it with appropriate barrier |
976 do_oop_store(_masm, Address(rdx, 0), rax, _bs->kind(), true); | |
977 | |
978 __ jmp(done); | |
902 | 979 |
903 // Have a NULL in EAX, EDX=array, ECX=index. Store NULL at ary[idx] | 980 // Have a NULL in EAX, EDX=array, ECX=index. Store NULL at ary[idx] |
904 __ bind(is_null); | 981 __ bind(is_null); |
905 __ profile_null_seen(rbx); | 982 __ profile_null_seen(rbx); |
906 __ movl(Address(rdx, rcx, Address::times_4, arrayOopDesc::base_offset_in_bytes(T_OBJECT)), rax); | 983 |
984 // Store NULL, (noreg means NULL to do_oop_store) | |
985 do_oop_store(_masm, element_address, noreg, _bs->kind(), true); | |
907 | 986 |
908 // Pop stack arguments | 987 // Pop stack arguments |
909 __ bind(done); | 988 __ bind(done); |
910 __ addl(rsp, 3 * Interpreter::stackElementSize()); | 989 __ addl(rsp, 3 * Interpreter::stackElementSize()); |
911 } | 990 } |
1504 __ load_unsigned_byte(rbx, Address(rsi, rdx, Address::times_1, 0)); | 1583 __ load_unsigned_byte(rbx, Address(rsi, rdx, Address::times_1, 0)); |
1505 | 1584 |
1506 // compute return address as bci in rax, | 1585 // compute return address as bci in rax, |
1507 __ leal(rax, at_bcp((is_wide ? 5 : 3) - in_bytes(constMethodOopDesc::codes_offset()))); | 1586 __ leal(rax, at_bcp((is_wide ? 5 : 3) - in_bytes(constMethodOopDesc::codes_offset()))); |
1508 __ subl(rax, Address(rcx, methodOopDesc::const_offset())); | 1587 __ subl(rax, Address(rcx, methodOopDesc::const_offset())); |
1509 // Adjust the bcp in ESI by the displacement in EDX | 1588 // Adjust the bcp in rsi by the displacement in EDX |
1510 __ addl(rsi, rdx); | 1589 __ addl(rsi, rdx); |
1511 // Push return address | 1590 // Push return address |
1512 __ push_i(rax); | 1591 __ push_i(rax); |
1513 // jsr returns vtos | 1592 // jsr returns vtos |
1514 __ dispatch_only_noverify(vtos); | 1593 __ dispatch_only_noverify(vtos); |
1515 return; | 1594 return; |
1516 } | 1595 } |
1517 | 1596 |
1518 // Normal (non-jsr) branch handling | 1597 // Normal (non-jsr) branch handling |
1519 | 1598 |
1520 // Adjust the bcp in ESI by the displacement in EDX | 1599 // Adjust the bcp in rsi by the displacement in EDX |
1521 __ addl(rsi, rdx); | 1600 __ addl(rsi, rdx); |
1522 | 1601 |
1523 assert(UseLoopCounter || !UseOnStackReplacement, "on-stack-replacement requires loop counters"); | 1602 assert(UseLoopCounter || !UseOnStackReplacement, "on-stack-replacement requires loop counters"); |
1524 Label backedge_counter_overflow; | 1603 Label backedge_counter_overflow; |
1525 Label profile_method; | 1604 Label profile_method; |
2424 __ jcc(Assembler::notEqual, notObj); | 2503 __ jcc(Assembler::notEqual, notObj); |
2425 | 2504 |
2426 __ pop(atos); | 2505 __ pop(atos); |
2427 if (!is_static) pop_and_check_object(obj); | 2506 if (!is_static) pop_and_check_object(obj); |
2428 | 2507 |
2429 __ movl(lo, rax ); | 2508 do_oop_store(_masm, lo, rax, _bs->kind(), false); |
2430 __ store_check(obj, lo); // Need to mark card | 2509 |
2431 if (!is_static) { | 2510 if (!is_static) { |
2432 patch_bytecode(Bytecodes::_fast_aputfield, rcx, rbx); | 2511 patch_bytecode(Bytecodes::_fast_aputfield, rcx, rbx); |
2433 } | 2512 } |
2513 | |
2434 __ jmp(Done); | 2514 __ jmp(Done); |
2435 | 2515 |
2436 __ bind(notObj); | 2516 __ bind(notObj); |
2437 // ctos | 2517 // ctos |
2438 __ cmpl(flags, ctos ); | 2518 __ cmpl(flags, ctos ); |
2636 case Bytecodes::_fast_cputfield: __ movw(lo, rax); break; | 2716 case Bytecodes::_fast_cputfield: __ movw(lo, rax); break; |
2637 case Bytecodes::_fast_iputfield: __ movl(lo, rax); break; | 2717 case Bytecodes::_fast_iputfield: __ movl(lo, rax); break; |
2638 case Bytecodes::_fast_lputfield: __ movl(hi, rdx); __ movl(lo, rax); break; | 2718 case Bytecodes::_fast_lputfield: __ movl(hi, rdx); __ movl(lo, rax); break; |
2639 case Bytecodes::_fast_fputfield: __ fstp_s(lo); break; | 2719 case Bytecodes::_fast_fputfield: __ fstp_s(lo); break; |
2640 case Bytecodes::_fast_dputfield: __ fstp_d(lo); break; | 2720 case Bytecodes::_fast_dputfield: __ fstp_d(lo); break; |
2641 case Bytecodes::_fast_aputfield: __ movl(lo, rax); __ store_check(rcx, lo); break; | 2721 case Bytecodes::_fast_aputfield: { |
2722 do_oop_store(_masm, lo, rax, _bs->kind(), false); | |
2723 break; | |
2724 } | |
2642 default: | 2725 default: |
2643 ShouldNotReachHere(); | 2726 ShouldNotReachHere(); |
2644 } | 2727 } |
2645 | 2728 |
2646 Label done; | 2729 Label done; |
2647 volatile_barrier( ); | 2730 volatile_barrier( ); |
2648 __ jmpb(done); | 2731 // Barriers are so large that short branch doesn't reach! |
2732 __ jmp(done); | |
2649 | 2733 |
2650 // Same code as above, but don't need rdx to test for volatile. | 2734 // Same code as above, but don't need rdx to test for volatile. |
2651 __ bind(notVolatile); | 2735 __ bind(notVolatile); |
2652 | 2736 |
2653 if (bytecode() == Bytecodes::_fast_lputfield) __ popl(rdx); | 2737 if (bytecode() == Bytecodes::_fast_lputfield) __ popl(rdx); |
2662 case Bytecodes::_fast_cputfield: __ movw(lo, rax); break; | 2746 case Bytecodes::_fast_cputfield: __ movw(lo, rax); break; |
2663 case Bytecodes::_fast_iputfield: __ movl(lo, rax); break; | 2747 case Bytecodes::_fast_iputfield: __ movl(lo, rax); break; |
2664 case Bytecodes::_fast_lputfield: __ movl(hi, rdx); __ movl(lo, rax); break; | 2748 case Bytecodes::_fast_lputfield: __ movl(hi, rdx); __ movl(lo, rax); break; |
2665 case Bytecodes::_fast_fputfield: __ fstp_s(lo); break; | 2749 case Bytecodes::_fast_fputfield: __ fstp_s(lo); break; |
2666 case Bytecodes::_fast_dputfield: __ fstp_d(lo); break; | 2750 case Bytecodes::_fast_dputfield: __ fstp_d(lo); break; |
2667 case Bytecodes::_fast_aputfield: __ movl(lo, rax); __ store_check(rcx, lo); break; | 2751 case Bytecodes::_fast_aputfield: { |
2752 do_oop_store(_masm, lo, rax, _bs->kind(), false); | |
2753 break; | |
2754 } | |
2668 default: | 2755 default: |
2669 ShouldNotReachHere(); | 2756 ShouldNotReachHere(); |
2670 } | 2757 } |
2671 __ bind(done); | 2758 __ bind(done); |
2672 } | 2759 } |
3017 Label done; | 3104 Label done; |
3018 Label initialize_header; | 3105 Label initialize_header; |
3019 Label initialize_object; // including clearing the fields | 3106 Label initialize_object; // including clearing the fields |
3020 Label allocate_shared; | 3107 Label allocate_shared; |
3021 | 3108 |
3022 ExternalAddress heap_top((address)Universe::heap()->top_addr()); | |
3023 | |
3024 __ get_cpool_and_tags(rcx, rax); | 3109 __ get_cpool_and_tags(rcx, rax); |
3025 // get instanceKlass | 3110 // get instanceKlass |
3026 __ movl(rcx, Address(rcx, rdx, Address::times_4, sizeof(constantPoolOopDesc))); | 3111 __ movl(rcx, Address(rcx, rdx, Address::times_4, sizeof(constantPoolOopDesc))); |
3027 __ pushl(rcx); // save the contexts of klass for initializing the header | 3112 __ pushl(rcx); // save the contexts of klass for initializing the header |
3028 | 3113 |
3074 // Allocation in the shared Eden, if allowed. | 3159 // Allocation in the shared Eden, if allowed. |
3075 // | 3160 // |
3076 // rdx: instance size in bytes | 3161 // rdx: instance size in bytes |
3077 if (allow_shared_alloc) { | 3162 if (allow_shared_alloc) { |
3078 __ bind(allocate_shared); | 3163 __ bind(allocate_shared); |
3164 | |
3165 ExternalAddress heap_top((address)Universe::heap()->top_addr()); | |
3079 | 3166 |
3080 Label retry; | 3167 Label retry; |
3081 __ bind(retry); | 3168 __ bind(retry); |
3082 __ mov32(rax, heap_top); | 3169 __ mov32(rax, heap_top); |
3083 __ leal(rbx, Address(rax, rdx, Address::times_1)); | 3170 __ leal(rbx, Address(rax, rdx, Address::times_1)); |