src/share/vm/opto/macro.cpp

changeset 1286
fc4be448891f
parent 1215
c96bf21b756f
child 1515
7c57aead6d3e
     1.1 --- a/src/share/vm/opto/macro.cpp	Wed Jul 15 13:37:35 2009 -0700
     1.2 +++ b/src/share/vm/opto/macro.cpp	Thu Jul 16 14:10:42 2009 -0700
     1.3 @@ -198,14 +198,79 @@
     1.4  }
     1.5  
     1.6  // Eliminate a card mark sequence.  p2x is a ConvP2XNode
     1.7 -void PhaseMacroExpand::eliminate_card_mark(Node *p2x) {
     1.8 +void PhaseMacroExpand::eliminate_card_mark(Node* p2x) {
     1.9    assert(p2x->Opcode() == Op_CastP2X, "ConvP2XNode required");
    1.10 -  Node *shift = p2x->unique_out();
    1.11 -  Node *addp = shift->unique_out();
    1.12 -  for (DUIterator_Last jmin, j = addp->last_outs(jmin); j >= jmin; --j) {
    1.13 -    Node *st = addp->last_out(j);
    1.14 -    assert(st->is_Store(), "store required");
    1.15 -    _igvn.replace_node(st, st->in(MemNode::Memory));
    1.16 +  if (!UseG1GC) {
    1.17 +    // vanilla/CMS post barrier
    1.18 +    Node *shift = p2x->unique_out();
    1.19 +    Node *addp = shift->unique_out();
    1.20 +    for (DUIterator_Last jmin, j = addp->last_outs(jmin); j >= jmin; --j) {
    1.21 +      Node *st = addp->last_out(j);
    1.22 +      assert(st->is_Store(), "store required");
    1.23 +      _igvn.replace_node(st, st->in(MemNode::Memory));
    1.24 +    }
    1.25 +  } else {
    1.26 +    // G1 pre/post barriers
    1.27 +    assert(p2x->outcnt() == 2, "expects 2 users: Xor and URShift nodes");
    1.28 +    // It could be only one user, URShift node, in Object.clone() instrinsic
    1.29 +    // but the new allocation is passed to arraycopy stub and it could not
    1.30 +    // be scalar replaced. So we don't check the case.
    1.31 +
    1.32 +    // Remove G1 post barrier.
    1.33 +
    1.34 +    // Search for CastP2X->Xor->URShift->Cmp path which
    1.35 +    // checks if the store done to a different from the value's region.
    1.36 +    // And replace Cmp with #0 (false) to collapse G1 post barrier.
    1.37 +    Node* xorx = NULL;
    1.38 +    for (DUIterator_Fast imax, i = p2x->fast_outs(imax); i < imax; i++) {
    1.39 +      Node* u = p2x->fast_out(i);
    1.40 +      if (u->Opcode() == Op_XorX) {
    1.41 +        xorx = u;
    1.42 +        break;
    1.43 +      }
    1.44 +    }
    1.45 +    assert(xorx != NULL, "missing G1 post barrier");
    1.46 +    Node* shift = xorx->unique_out();
    1.47 +    Node* cmpx = shift->unique_out();
    1.48 +    assert(cmpx->is_Cmp() && cmpx->unique_out()->is_Bool() &&
    1.49 +    cmpx->unique_out()->as_Bool()->_test._test == BoolTest::ne,
    1.50 +    "missing region check in G1 post barrier");
    1.51 +    _igvn.replace_node(cmpx, makecon(TypeInt::CC_EQ));
    1.52 +
    1.53 +    // Remove G1 pre barrier.
    1.54 +
    1.55 +    // Search "if (marking != 0)" check and set it to "false".
    1.56 +    Node* this_region = p2x->in(0);
    1.57 +    assert(this_region != NULL, "");
    1.58 +    // There is no G1 pre barrier if previous stored value is NULL
    1.59 +    // (for example, after initialization).
    1.60 +    if (this_region->is_Region() && this_region->req() == 3) {
    1.61 +      int ind = 1;
    1.62 +      if (!this_region->in(ind)->is_IfFalse()) {
    1.63 +        ind = 2;
    1.64 +      }
    1.65 +      if (this_region->in(ind)->is_IfFalse()) {
    1.66 +        Node* bol = this_region->in(ind)->in(0)->in(1);
    1.67 +        assert(bol->is_Bool(), "");
    1.68 +        cmpx = bol->in(1);
    1.69 +        if (bol->as_Bool()->_test._test == BoolTest::ne &&
    1.70 +            cmpx->is_Cmp() && cmpx->in(2) == intcon(0) &&
    1.71 +            cmpx->in(1)->is_Load()) {
    1.72 +          Node* adr = cmpx->in(1)->as_Load()->in(MemNode::Address);
    1.73 +          const int marking_offset = in_bytes(JavaThread::satb_mark_queue_offset() +
    1.74 +                                              PtrQueue::byte_offset_of_active());
    1.75 +          if (adr->is_AddP() && adr->in(AddPNode::Base) == top() &&
    1.76 +              adr->in(AddPNode::Address)->Opcode() == Op_ThreadLocal &&
    1.77 +              adr->in(AddPNode::Offset) == MakeConX(marking_offset)) {
    1.78 +            _igvn.replace_node(cmpx, makecon(TypeInt::CC_EQ));
    1.79 +          }
    1.80 +        }
    1.81 +      }
    1.82 +    }
    1.83 +    // Now CastP2X can be removed since it is used only on dead path
    1.84 +    // which currently still alive until igvn optimize it.
    1.85 +    assert(p2x->unique_out()->Opcode() == Op_URShiftX, "");
    1.86 +    _igvn.replace_node(p2x, top());
    1.87    }
    1.88  }
    1.89  
    1.90 @@ -760,14 +825,11 @@
    1.91            if (n->is_Store()) {
    1.92              _igvn.replace_node(n, n->in(MemNode::Memory));
    1.93            } else {
    1.94 -            assert( n->Opcode() == Op_CastP2X, "CastP2X required");
    1.95              eliminate_card_mark(n);
    1.96            }
    1.97            k -= (oc2 - use->outcnt());
    1.98          }
    1.99        } else {
   1.100 -        assert( !use->is_SafePoint(), "safepoint uses must have been already elimiated");
   1.101 -        assert( use->Opcode() == Op_CastP2X, "CastP2X required");
   1.102          eliminate_card_mark(use);
   1.103        }
   1.104        j -= (oc1 - res->outcnt());

mercurial