Print this page
rev 3122 : 7133038: G1: Some small profile based optimizations
Summary: Some minor profile based optimizations. Reduce the number of branches and branch mispredicts by removing some virtual calls, through closure specalization, and refactoring some conditional statements.
Reviewed-by: brutisso, tonyp

Split Split Close
Expand all
Collapse all
          --- old/src/share/vm/gc_implementation/g1/heapRegion.cpp
          +++ new/src/share/vm/gc_implementation/g1/heapRegion.cpp
↓ open down ↓ 651 lines elided ↑ open up ↑
 652  652    if (filter_young) {
 653  653      assert(card_ptr != NULL, "pre-condition");
 654  654    } else {
 655  655      assert(card_ptr == NULL, "pre-condition");
 656  656    }
 657  657    G1CollectedHeap* g1h = G1CollectedHeap::heap();
 658  658  
 659  659    // If we're within a stop-world GC, then we might look at a card in a
 660  660    // GC alloc region that extends onto a GC LAB, which may not be
 661  661    // parseable.  Stop such at the "saved_mark" of the region.
 662      -  if (G1CollectedHeap::heap()->is_gc_active()) {
      662 +  if (g1h->is_gc_active()) {
 663  663      mr = mr.intersection(used_region_at_save_marks());
 664  664    } else {
 665  665      mr = mr.intersection(used_region());
 666  666    }
 667  667    if (mr.is_empty()) return NULL;
 668  668    // Otherwise, find the obj that extends onto mr.start().
 669  669  
 670  670    // The intersection of the incoming mr (for the card) and the
 671  671    // allocated part of the region is non-empty. This implies that
 672  672    // we have actually allocated into this region. The code in
↓ open down ↓ 8 lines elided ↑ open up ↑
 681  681  
 682  682    // We can only clean the card here, after we make the decision that
 683  683    // the card is not young. And we only clean the card if we have been
 684  684    // asked to (i.e., card_ptr != NULL).
 685  685    if (card_ptr != NULL) {
 686  686      *card_ptr = CardTableModRefBS::clean_card_val();
 687  687      // We must complete this write before we do any of the reads below.
 688  688      OrderAccess::storeload();
 689  689    }
 690  690  
      691 +  // Cache the boundaries of the memory region in some const locals
      692 +  HeapWord* const start = mr.start();
      693 +  HeapWord* const end = mr.end();
      694 +
 691  695    // We used to use "block_start_careful" here.  But we're actually happy
 692  696    // to update the BOT while we do this...
 693      -  HeapWord* cur = block_start(mr.start());
 694      -  assert(cur <= mr.start(), "Postcondition");
      697 +  HeapWord* cur = block_start(start);
      698 +  assert(cur <= start, "Postcondition");
 695  699  
 696      -  while (cur <= mr.start()) {
 697      -    if (oop(cur)->klass_or_null() == NULL) {
      700 +  oop obj;
      701 +
      702 +  HeapWord* next = cur;
      703 +  while (next <= start) {
      704 +    cur = next;
      705 +    obj = oop(cur);
      706 +    if (obj->klass_or_null() == NULL) {
 698  707        // Ran into an unparseable point.
 699  708        return cur;
 700  709      }
 701  710      // Otherwise...
 702      -    int sz = oop(cur)->size();
 703      -    if (cur + sz > mr.start()) break;
 704      -    // Otherwise, go on.
 705      -    cur = cur + sz;
      711 +    next = (cur + obj->size());
 706  712    }
 707      -  oop obj;
 708      -  obj = oop(cur);
 709      -  // If we finish this loop...
 710      -  assert(cur <= mr.start()
 711      -         && obj->klass_or_null() != NULL
 712      -         && cur + obj->size() > mr.start(),
      713 +
      714 +  // If we finish the above loop...We have a parseable object that
      715 +  // begins on or before the start of the memory region, and ends
      716 +  // inside or spans the entire region.
      717 +
      718 +  assert(obj == oop(cur), "sanity");
      719 +  assert(cur <= start &&
      720 +         obj->klass_or_null() != NULL &&
      721 +         (cur + obj->size()) > start,
 713  722           "Loop postcondition");
      723 +
 714  724    if (!g1h->is_obj_dead(obj)) {
 715  725      obj->oop_iterate(cl, mr);
 716  726    }
 717  727  
 718      -  HeapWord* next;
 719      -  while (cur < mr.end()) {
      728 +  while (cur < end) {
 720  729      obj = oop(cur);
 721  730      if (obj->klass_or_null() == NULL) {
 722  731        // Ran into an unparseable point.
 723  732        return cur;
 724  733      };
      734 +
 725  735      // Otherwise:
 726  736      next = (cur + obj->size());
      737 +
 727  738      if (!g1h->is_obj_dead(obj)) {
 728      -      if (next < mr.end()) {
      739 +      if (next < end || !obj->is_objArray()) {
      740 +        // This object either does not span the MemRegion
      741 +        // boundary, or if it does it's not an array.
      742 +        // Apply closure to whole object.
 729  743          obj->oop_iterate(cl);
 730  744        } else {
 731      -        // this obj spans the boundary.  If it's an array, stop at the
 732      -        // boundary.
 733      -        if (obj->is_objArray()) {
 734      -          obj->oop_iterate(cl, mr);
 735      -        } else {
 736      -          obj->oop_iterate(cl);
 737      -        }
      745 +        // This obj is an array that spans the boundary.
      746 +        // Stop at the boundary.
      747 +        obj->oop_iterate(cl, mr);
 738  748        }
 739  749      }
 740  750      cur = next;
 741  751    }
 742  752    return NULL;
 743  753  }
 744  754  
 745  755  void HeapRegion::print() const { print_on(gclog_or_tty); }
 746  756  void HeapRegion::print_on(outputStream* st) const {
 747  757    if (isHumongous()) {
↓ open down ↓ 257 lines elided ↑ open up ↑