1014 |
1014 |
1015 ctrl = new IfFalseNode(in_cset_fast_test_iff); |
1015 ctrl = new IfFalseNode(in_cset_fast_test_iff); |
1016 phase->register_control(ctrl, loop, in_cset_fast_test_iff); |
1016 phase->register_control(ctrl, loop, in_cset_fast_test_iff); |
1017 } |
1017 } |
1018 |
1018 |
1019 void ShenandoahBarrierC2Support::call_lrb_stub(Node*& ctrl, Node*& val, Node*& result_mem, Node* raw_mem, bool is_native, PhaseIdealLoop* phase) { |
1019 void ShenandoahBarrierC2Support::call_lrb_stub(Node*& ctrl, Node*& val, Node* load_addr, Node*& result_mem, Node* raw_mem, bool is_native, PhaseIdealLoop* phase) { |
1020 IdealLoopTree*loop = phase->get_loop(ctrl); |
1020 IdealLoopTree*loop = phase->get_loop(ctrl); |
1021 const TypePtr* obj_type = phase->igvn().type(val)->is_oopptr()->cast_to_nonconst(); |
1021 const TypePtr* obj_type = phase->igvn().type(val)->is_oopptr()->cast_to_nonconst(); |
1022 |
1022 |
1023 // The slow path stub consumes and produces raw memory in addition |
1023 // The slow path stub consumes and produces raw memory in addition |
1024 // to the existing memory edges |
1024 // to the existing memory edges |
1025 Node* base = find_bottom_mem(ctrl, phase); |
1025 Node* base = find_bottom_mem(ctrl, phase); |
1026 MergeMemNode* mm = MergeMemNode::make(base); |
1026 MergeMemNode* mm = MergeMemNode::make(base); |
1027 mm->set_memory_at(Compile::AliasIdxRaw, raw_mem); |
1027 mm->set_memory_at(Compile::AliasIdxRaw, raw_mem); |
1028 phase->register_new_node(mm, ctrl); |
1028 phase->register_new_node(mm, ctrl); |
1029 |
1029 |
|
1030 address target = LP64_ONLY(UseCompressedOops) NOT_LP64(false) ? |
|
1031 CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_fixup_narrow) : |
|
1032 CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_fixup); |
|
1033 |
1030 address calladdr = is_native ? CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_native) |
1034 address calladdr = is_native ? CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_native) |
1031 : CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier); |
1035 : target; |
1032 const char* name = is_native ? "oop_load_from_native_barrier" : "load_reference_barrier"; |
1036 const char* name = is_native ? "oop_load_from_native_barrier" : "load_reference_barrier"; |
1033 Node* call = new CallLeafNode(ShenandoahBarrierSetC2::shenandoah_load_reference_barrier_Type(), calladdr, name, TypeRawPtr::BOTTOM); |
1037 Node* call = new CallLeafNode(ShenandoahBarrierSetC2::shenandoah_load_reference_barrier_Type(), calladdr, name, TypeRawPtr::BOTTOM); |
|
1038 |
1034 call->init_req(TypeFunc::Control, ctrl); |
1039 call->init_req(TypeFunc::Control, ctrl); |
1035 call->init_req(TypeFunc::I_O, phase->C->top()); |
1040 call->init_req(TypeFunc::I_O, phase->C->top()); |
1036 call->init_req(TypeFunc::Memory, mm); |
1041 call->init_req(TypeFunc::Memory, mm); |
1037 call->init_req(TypeFunc::FramePtr, phase->C->top()); |
1042 call->init_req(TypeFunc::FramePtr, phase->C->top()); |
1038 call->init_req(TypeFunc::ReturnAdr, phase->C->top()); |
1043 call->init_req(TypeFunc::ReturnAdr, phase->C->top()); |
1039 call->init_req(TypeFunc::Parms, val); |
1044 call->init_req(TypeFunc::Parms, val); |
|
1045 call->init_req(TypeFunc::Parms+1, load_addr); |
1040 phase->register_control(call, loop, ctrl); |
1046 phase->register_control(call, loop, ctrl); |
1041 ctrl = new ProjNode(call, TypeFunc::Control); |
1047 ctrl = new ProjNode(call, TypeFunc::Control); |
1042 phase->register_control(ctrl, loop, call); |
1048 phase->register_control(ctrl, loop, call); |
1043 result_mem = new ProjNode(call, TypeFunc::Memory); |
1049 result_mem = new ProjNode(call, TypeFunc::Memory); |
1044 phase->register_new_node(result_mem, call); |
1050 phase->register_new_node(result_mem, call); |
1399 Node* null_ctrl = NULL; |
1405 Node* null_ctrl = NULL; |
1400 |
1406 |
1401 assert(val->bottom_type()->make_oopptr(), "need oop"); |
1407 assert(val->bottom_type()->make_oopptr(), "need oop"); |
1402 assert(val->bottom_type()->make_oopptr()->const_oop() == NULL, "expect non-constant"); |
1408 assert(val->bottom_type()->make_oopptr()->const_oop() == NULL, "expect non-constant"); |
1403 |
1409 |
1404 enum { _heap_stable = 1, _not_cset, _fwded, _evac_path, _null_path, PATH_LIMIT }; |
1410 enum { _heap_stable = 1, _not_cset, _evac_path, _null_path, PATH_LIMIT }; |
1405 Node* region = new RegionNode(PATH_LIMIT); |
1411 Node* region = new RegionNode(PATH_LIMIT); |
1406 Node* val_phi = new PhiNode(region, uncasted_val->bottom_type()->is_oopptr()); |
1412 Node* val_phi = new PhiNode(region, uncasted_val->bottom_type()->is_oopptr()); |
1407 Node* raw_mem_phi = PhiNode::make(region, raw_mem, Type::MEMORY, TypeRawPtr::BOTTOM); |
1413 Node* raw_mem_phi = PhiNode::make(region, raw_mem, Type::MEMORY, TypeRawPtr::BOTTOM); |
1408 |
1414 |
1409 // Stable path. |
1415 // Stable path. |
1449 fix_null_check(unc, unc_ctrl, ctrl->in(0)->as_If()->proj_out(0), uses, phase); |
1455 fix_null_check(unc, unc_ctrl, ctrl->in(0)->as_If()->proj_out(0), uses, phase); |
1450 |
1456 |
1451 IfNode* iff = unc_ctrl->in(0)->as_If(); |
1457 IfNode* iff = unc_ctrl->in(0)->as_If(); |
1452 phase->igvn().replace_input_of(iff, 1, phase->igvn().intcon(1)); |
1458 phase->igvn().replace_input_of(iff, 1, phase->igvn().intcon(1)); |
1453 } |
1459 } |
1454 Node* addr = new AddPNode(new_val, uncasted_val, phase->igvn().MakeConX(oopDesc::mark_offset_in_bytes())); |
|
1455 phase->register_new_node(addr, ctrl); |
|
1456 assert(new_val->bottom_type()->isa_oopptr(), "what else?"); |
|
1457 Node* markword = new LoadXNode(ctrl, raw_mem, addr, TypeRawPtr::BOTTOM, TypeX_X, MemNode::unordered); |
|
1458 phase->register_new_node(markword, ctrl); |
|
1459 |
|
1460 // Test if object is forwarded. This is the case if lowest two bits are set. |
|
1461 Node* masked = new AndXNode(markword, phase->igvn().MakeConX(markWord::lock_mask_in_place)); |
|
1462 phase->register_new_node(masked, ctrl); |
|
1463 Node* cmp = new CmpXNode(masked, phase->igvn().MakeConX(markWord::marked_value)); |
|
1464 phase->register_new_node(cmp, ctrl); |
|
1465 |
|
1466 // Only branch to LRB stub if object is not forwarded; otherwise reply with fwd ptr |
|
1467 Node* bol = new BoolNode(cmp, BoolTest::eq); // Equals 3 means it's forwarded |
|
1468 phase->register_new_node(bol, ctrl); |
|
1469 |
|
1470 IfNode* iff = new IfNode(ctrl, bol, PROB_LIKELY(0.999), COUNT_UNKNOWN); |
|
1471 phase->register_control(iff, loop, ctrl); |
|
1472 Node* if_fwd = new IfTrueNode(iff); |
|
1473 phase->register_control(if_fwd, loop, iff); |
|
1474 Node* if_not_fwd = new IfFalseNode(iff); |
|
1475 phase->register_control(if_not_fwd, loop, iff); |
|
1476 |
|
1477 // Decode forward pointer: since we already have the lowest bits, we can just subtract them |
|
1478 // from the mark word without the need for large immediate mask. |
|
1479 Node* masked2 = new SubXNode(markword, masked); |
|
1480 phase->register_new_node(masked2, if_fwd); |
|
1481 Node* fwdraw = new CastX2PNode(masked2); |
|
1482 fwdraw->init_req(0, if_fwd); |
|
1483 phase->register_new_node(fwdraw, if_fwd); |
|
1484 Node* fwd = new CheckCastPPNode(NULL, fwdraw, val->bottom_type()); |
|
1485 phase->register_new_node(fwd, if_fwd); |
|
1486 |
|
1487 // Wire up not-equal-path in slots 3. |
|
1488 region->init_req(_fwded, if_fwd); |
|
1489 val_phi->init_req(_fwded, fwd); |
|
1490 raw_mem_phi->init_req(_fwded, raw_mem); |
|
1491 |
1460 |
1492 // Call lrb-stub and wire up that path in slots 4 |
1461 // Call lrb-stub and wire up that path in slots 4 |
1493 Node* result_mem = NULL; |
1462 Node* result_mem = NULL; |
1494 ctrl = if_not_fwd; |
1463 |
1495 fwd = new_val; |
1464 Node* fwd = new_val; |
1496 call_lrb_stub(ctrl, fwd, result_mem, raw_mem, lrb->is_native(), phase); |
1465 Node* addr; |
|
1466 if (ShenandoahSelfFixing) { |
|
1467 VectorSet visited(Thread::current()->resource_area()); |
|
1468 addr = get_load_addr(phase, visited, lrb); |
|
1469 } else { |
|
1470 addr = phase->igvn().zerocon(T_OBJECT); |
|
1471 } |
|
1472 if (addr->Opcode() == Op_AddP) { |
|
1473 Node* orig_base = addr->in(AddPNode::Base); |
|
1474 Node* base = new CheckCastPPNode(ctrl, orig_base, orig_base->bottom_type(), true); |
|
1475 phase->register_new_node(base, ctrl); |
|
1476 if (addr->in(AddPNode::Base) == addr->in((AddPNode::Address))) { |
|
1477 // Field access |
|
1478 addr = addr->clone(); |
|
1479 addr->set_req(AddPNode::Base, base); |
|
1480 addr->set_req(AddPNode::Address, base); |
|
1481 phase->register_new_node(addr, ctrl); |
|
1482 } else { |
|
1483 Node* addr2 = addr->in(AddPNode::Address); |
|
1484 if (addr2->Opcode() == Op_AddP && addr2->in(AddPNode::Base) == addr2->in(AddPNode::Address) && |
|
1485 addr2->in(AddPNode::Base) == orig_base) { |
|
1486 addr2 = addr2->clone(); |
|
1487 addr2->set_req(AddPNode::Base, base); |
|
1488 addr2->set_req(AddPNode::Address, base); |
|
1489 phase->register_new_node(addr2, ctrl); |
|
1490 addr = addr->clone(); |
|
1491 addr->set_req(AddPNode::Base, base); |
|
1492 addr->set_req(AddPNode::Address, addr2); |
|
1493 phase->register_new_node(addr, ctrl); |
|
1494 } |
|
1495 } |
|
1496 } |
|
1497 call_lrb_stub(ctrl, fwd, addr, result_mem, raw_mem, lrb->is_native(), phase); |
1497 region->init_req(_evac_path, ctrl); |
1498 region->init_req(_evac_path, ctrl); |
1498 val_phi->init_req(_evac_path, fwd); |
1499 val_phi->init_req(_evac_path, fwd); |
1499 raw_mem_phi->init_req(_evac_path, result_mem); |
1500 raw_mem_phi->init_req(_evac_path, result_mem); |
1500 |
1501 |
1501 phase->register_control(region, loop, heap_stable_iff); |
1502 phase->register_control(region, loop, heap_stable_iff); |
1691 fixer.fix_mem(init_ctrl, region, init_raw_mem, raw_mem_for_ctrl, phi, uses); |
1692 fixer.fix_mem(init_ctrl, region, init_raw_mem, raw_mem_for_ctrl, phi, uses); |
1692 |
1693 |
1693 phase->igvn().replace_node(barrier, pre_val); |
1694 phase->igvn().replace_node(barrier, pre_val); |
1694 } |
1695 } |
1695 assert(state->enqueue_barriers_count() == 0, "all enqueue barrier nodes should have been replaced"); |
1696 assert(state->enqueue_barriers_count() == 0, "all enqueue barrier nodes should have been replaced"); |
|
1697 |
|
1698 } |
|
1699 |
|
1700 Node* ShenandoahBarrierC2Support::get_load_addr(PhaseIdealLoop* phase, VectorSet& visited, Node* in) { |
|
1701 if (visited.test_set(in->_idx)) { |
|
1702 return NULL; |
|
1703 } |
|
1704 switch (in->Opcode()) { |
|
1705 case Op_Proj: |
|
1706 return get_load_addr(phase, visited, in->in(0)); |
|
1707 case Op_CastPP: |
|
1708 case Op_CheckCastPP: |
|
1709 case Op_DecodeN: |
|
1710 case Op_EncodeP: |
|
1711 return get_load_addr(phase, visited, in->in(1)); |
|
1712 case Op_LoadN: |
|
1713 case Op_LoadP: |
|
1714 return in->in(MemNode::Address); |
|
1715 case Op_CompareAndExchangeN: |
|
1716 case Op_CompareAndExchangeP: |
|
1717 case Op_GetAndSetN: |
|
1718 case Op_GetAndSetP: |
|
1719 case Op_ShenandoahCompareAndExchangeP: |
|
1720 case Op_ShenandoahCompareAndExchangeN: |
|
1721 // Those instructions would just have stored a different |
|
1722 // value into the field. No use to attempt to fix it at this point. |
|
1723 return phase->igvn().zerocon(T_OBJECT); |
|
1724 case Op_CMoveP: |
|
1725 case Op_CMoveN: { |
|
1726 Node* t = get_load_addr(phase, visited, in->in(CMoveNode::IfTrue)); |
|
1727 Node* f = get_load_addr(phase, visited, in->in(CMoveNode::IfFalse)); |
|
1728 // Handle unambiguous cases: single address reported on both branches. |
|
1729 if (t != NULL && f == NULL) return t; |
|
1730 if (t == NULL && f != NULL) return f; |
|
1731 if (t != NULL && t == f) return t; |
|
1732 // Ambiguity. |
|
1733 return phase->igvn().zerocon(T_OBJECT); |
|
1734 } |
|
1735 case Op_Phi: { |
|
1736 Node* addr = NULL; |
|
1737 for (uint i = 1; i < in->req(); i++) { |
|
1738 Node* addr1 = get_load_addr(phase, visited, in->in(i)); |
|
1739 if (addr == NULL) { |
|
1740 addr = addr1; |
|
1741 } |
|
1742 if (addr != addr1) { |
|
1743 return phase->igvn().zerocon(T_OBJECT); |
|
1744 } |
|
1745 } |
|
1746 return addr; |
|
1747 } |
|
1748 case Op_ShenandoahLoadReferenceBarrier: |
|
1749 return get_load_addr(phase, visited, in->in(ShenandoahLoadReferenceBarrierNode::ValueIn)); |
|
1750 case Op_ShenandoahEnqueueBarrier: |
|
1751 return get_load_addr(phase, visited, in->in(1)); |
|
1752 case Op_CallDynamicJava: |
|
1753 case Op_CallLeaf: |
|
1754 case Op_CallStaticJava: |
|
1755 case Op_ConN: |
|
1756 case Op_ConP: |
|
1757 case Op_Parm: |
|
1758 return phase->igvn().zerocon(T_OBJECT); |
|
1759 default: |
|
1760 #ifdef ASSERT |
|
1761 fatal("Unknown node in get_load_addr: %s", NodeClassNames[in->Opcode()]); |
|
1762 #endif |
|
1763 return phase->igvn().zerocon(T_OBJECT); |
|
1764 } |
1696 |
1765 |
1697 } |
1766 } |
1698 |
1767 |
1699 void ShenandoahBarrierC2Support::move_heap_stable_test_out_of_loop(IfNode* iff, PhaseIdealLoop* phase) { |
1768 void ShenandoahBarrierC2Support::move_heap_stable_test_out_of_loop(IfNode* iff, PhaseIdealLoop* phase) { |
1700 IdealLoopTree *loop = phase->get_loop(iff); |
1769 IdealLoopTree *loop = phase->get_loop(iff); |