comparison src/share/vm/opto/macro.cpp @ 851:fc4be448891f

6851742: (EA) allocation elimination doesn't work with UseG1GC Summary: Fix eliminate_card_mark() to eliminate G1 pre/post barriers. Reviewed-by: never
author kvn
date Thu, 16 Jul 2009 14:10:42 -0700
parents c96bf21b756f
children 7c57aead6d3e
comparison
equal deleted inserted replaced
850:fd50a67f97d1 851:fc4be448891f
196 } 196 }
197 197
198 } 198 }
199 199
200 // Eliminate a card mark sequence. p2x is a ConvP2XNode 200 // Eliminate a card mark sequence. p2x is a ConvP2XNode
201 void PhaseMacroExpand::eliminate_card_mark(Node *p2x) { 201 void PhaseMacroExpand::eliminate_card_mark(Node* p2x) {
202 assert(p2x->Opcode() == Op_CastP2X, "ConvP2XNode required"); 202 assert(p2x->Opcode() == Op_CastP2X, "ConvP2XNode required");
203 Node *shift = p2x->unique_out(); 203 if (!UseG1GC) {
204 Node *addp = shift->unique_out(); 204 // vanilla/CMS post barrier
205 for (DUIterator_Last jmin, j = addp->last_outs(jmin); j >= jmin; --j) { 205 Node *shift = p2x->unique_out();
206 Node *st = addp->last_out(j); 206 Node *addp = shift->unique_out();
207 assert(st->is_Store(), "store required"); 207 for (DUIterator_Last jmin, j = addp->last_outs(jmin); j >= jmin; --j) {
208 _igvn.replace_node(st, st->in(MemNode::Memory)); 208 Node *st = addp->last_out(j);
209 assert(st->is_Store(), "store required");
210 _igvn.replace_node(st, st->in(MemNode::Memory));
211 }
212 } else {
213 // G1 pre/post barriers
214 assert(p2x->outcnt() == 2, "expects 2 users: Xor and URShift nodes");
215 // It could be only one user, URShift node, in Object.clone() instrinsic
216 // but the new allocation is passed to arraycopy stub and it could not
217 // be scalar replaced. So we don't check the case.
218
219 // Remove G1 post barrier.
220
221 // Search for CastP2X->Xor->URShift->Cmp path which
222 // checks if the store done to a different from the value's region.
223 // And replace Cmp with #0 (false) to collapse G1 post barrier.
224 Node* xorx = NULL;
225 for (DUIterator_Fast imax, i = p2x->fast_outs(imax); i < imax; i++) {
226 Node* u = p2x->fast_out(i);
227 if (u->Opcode() == Op_XorX) {
228 xorx = u;
229 break;
230 }
231 }
232 assert(xorx != NULL, "missing G1 post barrier");
233 Node* shift = xorx->unique_out();
234 Node* cmpx = shift->unique_out();
235 assert(cmpx->is_Cmp() && cmpx->unique_out()->is_Bool() &&
236 cmpx->unique_out()->as_Bool()->_test._test == BoolTest::ne,
237 "missing region check in G1 post barrier");
238 _igvn.replace_node(cmpx, makecon(TypeInt::CC_EQ));
239
240 // Remove G1 pre barrier.
241
242 // Search "if (marking != 0)" check and set it to "false".
243 Node* this_region = p2x->in(0);
244 assert(this_region != NULL, "");
245 // There is no G1 pre barrier if previous stored value is NULL
246 // (for example, after initialization).
247 if (this_region->is_Region() && this_region->req() == 3) {
248 int ind = 1;
249 if (!this_region->in(ind)->is_IfFalse()) {
250 ind = 2;
251 }
252 if (this_region->in(ind)->is_IfFalse()) {
253 Node* bol = this_region->in(ind)->in(0)->in(1);
254 assert(bol->is_Bool(), "");
255 cmpx = bol->in(1);
256 if (bol->as_Bool()->_test._test == BoolTest::ne &&
257 cmpx->is_Cmp() && cmpx->in(2) == intcon(0) &&
258 cmpx->in(1)->is_Load()) {
259 Node* adr = cmpx->in(1)->as_Load()->in(MemNode::Address);
260 const int marking_offset = in_bytes(JavaThread::satb_mark_queue_offset() +
261 PtrQueue::byte_offset_of_active());
262 if (adr->is_AddP() && adr->in(AddPNode::Base) == top() &&
263 adr->in(AddPNode::Address)->Opcode() == Op_ThreadLocal &&
264 adr->in(AddPNode::Offset) == MakeConX(marking_offset)) {
265 _igvn.replace_node(cmpx, makecon(TypeInt::CC_EQ));
266 }
267 }
268 }
269 }
270 // Now CastP2X can be removed since it is used only on dead path
271 // which currently still alive until igvn optimize it.
272 assert(p2x->unique_out()->Opcode() == Op_URShiftX, "");
273 _igvn.replace_node(p2x, top());
209 } 274 }
210 } 275 }
211 276
212 // Search for a memory operation for the specified memory slice. 277 // Search for a memory operation for the specified memory slice.
213 static Node *scan_mem_chain(Node *mem, int alias_idx, int offset, Node *start_mem, Node *alloc, PhaseGVN *phase) { 278 static Node *scan_mem_chain(Node *mem, int alias_idx, int offset, Node *start_mem, Node *alloc, PhaseGVN *phase) {
758 Node *n = use->last_out(k); 823 Node *n = use->last_out(k);
759 uint oc2 = use->outcnt(); 824 uint oc2 = use->outcnt();
760 if (n->is_Store()) { 825 if (n->is_Store()) {
761 _igvn.replace_node(n, n->in(MemNode::Memory)); 826 _igvn.replace_node(n, n->in(MemNode::Memory));
762 } else { 827 } else {
763 assert( n->Opcode() == Op_CastP2X, "CastP2X required");
764 eliminate_card_mark(n); 828 eliminate_card_mark(n);
765 } 829 }
766 k -= (oc2 - use->outcnt()); 830 k -= (oc2 - use->outcnt());
767 } 831 }
768 } else { 832 } else {
769 assert( !use->is_SafePoint(), "safepoint uses must have been already elimiated");
770 assert( use->Opcode() == Op_CastP2X, "CastP2X required");
771 eliminate_card_mark(use); 833 eliminate_card_mark(use);
772 } 834 }
773 j -= (oc1 - res->outcnt()); 835 j -= (oc1 - res->outcnt());
774 } 836 }
775 assert(res->outcnt() == 0, "all uses of allocated objects must be deleted"); 837 assert(res->outcnt() == 0, "all uses of allocated objects must be deleted");