Mercurial > hg > graal-jvmci-8
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"); |