30 #include "opto/callnode.hpp" |
30 #include "opto/callnode.hpp" |
31 #include "opto/castnode.hpp" |
31 #include "opto/castnode.hpp" |
32 #include "opto/cfgnode.hpp" |
32 #include "opto/cfgnode.hpp" |
33 #include "opto/compile.hpp" |
33 #include "opto/compile.hpp" |
34 #include "opto/convertnode.hpp" |
34 #include "opto/convertnode.hpp" |
|
35 #include "opto/graphKit.hpp" |
35 #include "opto/locknode.hpp" |
36 #include "opto/locknode.hpp" |
36 #include "opto/loopnode.hpp" |
37 #include "opto/loopnode.hpp" |
37 #include "opto/macro.hpp" |
38 #include "opto/macro.hpp" |
38 #include "opto/memnode.hpp" |
39 #include "opto/memnode.hpp" |
39 #include "opto/narrowptrnode.hpp" |
40 #include "opto/narrowptrnode.hpp" |
261 |
262 |
262 // Search for CastP2X->Xor->URShift->Cmp path which |
263 // Search for CastP2X->Xor->URShift->Cmp path which |
263 // checks if the store done to a different from the value's region. |
264 // checks if the store done to a different from the value's region. |
264 // And replace Cmp with #0 (false) to collapse G1 post barrier. |
265 // And replace Cmp with #0 (false) to collapse G1 post barrier. |
265 Node* xorx = p2x->find_out_with(Op_XorX); |
266 Node* xorx = p2x->find_out_with(Op_XorX); |
266 assert(xorx != NULL, "missing G1 post barrier"); |
267 if (xorx != NULL) { |
267 Node* shift = xorx->unique_out(); |
268 Node* shift = xorx->unique_out(); |
268 Node* cmpx = shift->unique_out(); |
269 Node* cmpx = shift->unique_out(); |
269 assert(cmpx->is_Cmp() && cmpx->unique_out()->is_Bool() && |
270 assert(cmpx->is_Cmp() && cmpx->unique_out()->is_Bool() && |
270 cmpx->unique_out()->as_Bool()->_test._test == BoolTest::ne, |
271 cmpx->unique_out()->as_Bool()->_test._test == BoolTest::ne, |
271 "missing region check in G1 post barrier"); |
272 "missing region check in G1 post barrier"); |
272 _igvn.replace_node(cmpx, makecon(TypeInt::CC_EQ)); |
273 _igvn.replace_node(cmpx, makecon(TypeInt::CC_EQ)); |
273 |
274 |
274 // Remove G1 pre barrier. |
275 // Remove G1 pre barrier. |
275 |
276 |
276 // Search "if (marking != 0)" check and set it to "false". |
277 // Search "if (marking != 0)" check and set it to "false". |
277 // There is no G1 pre barrier if previous stored value is NULL |
278 // There is no G1 pre barrier if previous stored value is NULL |
278 // (for example, after initialization). |
279 // (for example, after initialization). |
279 if (this_region->is_Region() && this_region->req() == 3) { |
280 if (this_region->is_Region() && this_region->req() == 3) { |
280 int ind = 1; |
281 int ind = 1; |
281 if (!this_region->in(ind)->is_IfFalse()) { |
282 if (!this_region->in(ind)->is_IfFalse()) { |
282 ind = 2; |
283 ind = 2; |
283 } |
284 } |
284 if (this_region->in(ind)->is_IfFalse()) { |
285 if (this_region->in(ind)->is_IfFalse()) { |
285 Node* bol = this_region->in(ind)->in(0)->in(1); |
286 Node* bol = this_region->in(ind)->in(0)->in(1); |
286 assert(bol->is_Bool(), ""); |
287 assert(bol->is_Bool(), ""); |
287 cmpx = bol->in(1); |
288 cmpx = bol->in(1); |
288 if (bol->as_Bool()->_test._test == BoolTest::ne && |
289 if (bol->as_Bool()->_test._test == BoolTest::ne && |
289 cmpx->is_Cmp() && cmpx->in(2) == intcon(0) && |
290 cmpx->is_Cmp() && cmpx->in(2) == intcon(0) && |
290 cmpx->in(1)->is_Load()) { |
291 cmpx->in(1)->is_Load()) { |
291 Node* adr = cmpx->in(1)->as_Load()->in(MemNode::Address); |
292 Node* adr = cmpx->in(1)->as_Load()->in(MemNode::Address); |
292 const int marking_offset = in_bytes(JavaThread::satb_mark_queue_offset() + |
293 const int marking_offset = in_bytes(JavaThread::satb_mark_queue_offset() + |
293 SATBMarkQueue::byte_offset_of_active()); |
294 SATBMarkQueue::byte_offset_of_active()); |
294 if (adr->is_AddP() && adr->in(AddPNode::Base) == top() && |
295 if (adr->is_AddP() && adr->in(AddPNode::Base) == top() && |
295 adr->in(AddPNode::Address)->Opcode() == Op_ThreadLocal && |
296 adr->in(AddPNode::Address)->Opcode() == Op_ThreadLocal && |
296 adr->in(AddPNode::Offset) == MakeConX(marking_offset)) { |
297 adr->in(AddPNode::Offset) == MakeConX(marking_offset)) { |
297 _igvn.replace_node(cmpx, makecon(TypeInt::CC_EQ)); |
298 _igvn.replace_node(cmpx, makecon(TypeInt::CC_EQ)); |
|
299 } |
298 } |
300 } |
299 } |
301 } |
300 } |
302 } |
|
303 } else { |
|
304 assert(!GraphKit::use_ReduceInitialCardMarks(), "can only happen with card marking"); |
|
305 // This is a G1 post barrier emitted by the Object.clone() intrinsic. |
|
306 // Search for the CastP2X->URShiftX->AddP->LoadB->Cmp path which checks if the card |
|
307 // is marked as young_gen and replace the Cmp with 0 (false) to collapse the barrier. |
|
308 Node* shift = p2x->find_out_with(Op_URShiftX); |
|
309 assert(shift != NULL, "missing G1 post barrier"); |
|
310 Node* addp = shift->unique_out(); |
|
311 Node* load = addp->find_out_with(Op_LoadB); |
|
312 assert(load != NULL, "missing G1 post barrier"); |
|
313 Node* cmpx = load->unique_out(); |
|
314 assert(cmpx->is_Cmp() && cmpx->unique_out()->is_Bool() && |
|
315 cmpx->unique_out()->as_Bool()->_test._test == BoolTest::ne, |
|
316 "missing card value check in G1 post barrier"); |
|
317 _igvn.replace_node(cmpx, makecon(TypeInt::CC_EQ)); |
|
318 // There is no G1 pre barrier in this case |
301 } |
319 } |
302 // Now CastP2X can be removed since it is used only on dead path |
320 // Now CastP2X can be removed since it is used only on dead path |
303 // which currently still alive until igvn optimize it. |
321 // which currently still alive until igvn optimize it. |
304 assert(p2x->outcnt() == 0 || p2x->unique_out()->Opcode() == Op_URShiftX, ""); |
322 assert(p2x->outcnt() == 0 || p2x->unique_out()->Opcode() == Op_URShiftX, ""); |
305 _igvn.replace_node(p2x, top()); |
323 _igvn.replace_node(p2x, top()); |
324 return in; |
342 return in; |
325 } else if (in->is_Call()) { |
343 } else if (in->is_Call()) { |
326 CallNode *call = in->as_Call(); |
344 CallNode *call = in->as_Call(); |
327 if (call->may_modify(tinst, phase)) { |
345 if (call->may_modify(tinst, phase)) { |
328 assert(call->is_ArrayCopy(), "ArrayCopy is the only call node that doesn't make allocation escape"); |
346 assert(call->is_ArrayCopy(), "ArrayCopy is the only call node that doesn't make allocation escape"); |
329 |
|
330 if (call->as_ArrayCopy()->modifies(offset, offset, phase, false)) { |
347 if (call->as_ArrayCopy()->modifies(offset, offset, phase, false)) { |
331 return in; |
348 return in; |
332 } |
349 } |
333 } |
350 } |
334 mem = in->in(TypeFunc::Memory); |
351 mem = in->in(TypeFunc::Memory); |
335 } else if (in->is_MemBar()) { |
352 } else if (in->is_MemBar()) { |
336 if (ArrayCopyNode::may_modify(tinst, in->as_MemBar(), phase)) { |
353 ArrayCopyNode* ac = NULL; |
337 assert(in->in(0)->is_Proj() && in->in(0)->in(0)->is_ArrayCopy(), "should be arraycopy"); |
354 if (ArrayCopyNode::may_modify(tinst, in->as_MemBar(), phase, ac)) { |
338 ArrayCopyNode* ac = in->in(0)->in(0)->as_ArrayCopy(); |
355 assert(ac != NULL && ac->is_clonebasic(), "Only basic clone is a non escaping clone"); |
339 assert(ac->is_clonebasic(), "Only basic clone is a non escaping clone"); |
|
340 return ac; |
356 return ac; |
341 } |
357 } |
342 mem = in->in(TypeFunc::Memory); |
358 mem = in->in(TypeFunc::Memory); |
343 } else { |
359 } else { |
344 assert(false, "unexpected projection"); |
360 assert(false, "unexpected projection"); |