src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp

Print this page

        

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.

@@ -68,13 +68,14 @@
 
 typedef int RegionIdx_t;   // needs to hold [ 0..max_regions() )
 typedef int CardIdx_t;     // needs to hold [ 0..CardsPerRegion )
 
 enum GCAllocPurpose {
-  GCAllocForTenured,
-  GCAllocForSurvived,
-  GCAllocPurposeCount
+  GCAllocPurposeStart = 0,
+  GCAllocForTenured = GCAllocPurposeStart,
+  GCAllocForSurvived = GCAllocPurposeStart + 1,
+  GCAllocPurposeCount = GCAllocPurposeStart + 2
 };
 
 class YoungList : public CHeapObj<mtGC> {
 private:
   G1CollectedHeap* _g1h;

@@ -592,15 +593,10 @@
   // allocation region, either by picking one or expanding the
   // heap, and then allocate a block of the given size. The block
   // may not be a humongous - it must fit into a single heap region.
   HeapWord* par_allocate_during_gc(GCAllocPurpose purpose, size_t word_size);
 
-  HeapWord* allocate_during_gc_slow(GCAllocPurpose purpose,
-                                    HeapRegion*    alloc_region,
-                                    bool           par,
-                                    size_t         word_size);
-
   // Ensure that no further allocations can happen in "r", bearing in mind
   // that parallel threads might be attempting allocations.
   void par_allocate_remaining_space(HeapRegion* r);
 
   // Allocation attempt during GC for a survivor object / PLAB.

@@ -1745,23 +1741,117 @@
     if (_retired)
       return;
     ParGCAllocBuffer::retire(end_of_gc, retain);
     _retired = true;
   }
+
+  bool is_retired() {
+    return _retired;
+  }
+};
+
+class G1MultiParGCAllocBuffer {
+protected:
+  enum GCAllocPriority {
+      GCAllocPriorityStart = 0,
+      GCAllocPriority1 = GCAllocPriorityStart,
+      GCAllocPriority2 = GCAllocPriorityStart + 1,
+      GCAllocPriorityCount = GCAllocPriorityStart + 2
+  };
+  G1ParGCAllocBuffer* _priority_buffer[GCAllocPriorityCount];
+
+public:
+  G1MultiParGCAllocBuffer(size_t gclab_word_size) {
+    for (int pr = GCAllocPriorityStart; pr < GCAllocPriorityCount; ++pr) {
+      _priority_buffer[pr] = new G1ParGCAllocBuffer(gclab_word_size);
+    }
+  }
+
+  ~G1MultiParGCAllocBuffer() {
+    for (int pr = GCAllocPriorityStart; pr < GCAllocPriorityCount; ++pr) {
+      assert(_priority_buffer[pr]->is_retired(), "alloc buffers should all retire at this point.");
+      delete _priority_buffer[pr];
+    }
+  }
+
+  HeapWord* allocate(size_t word_sz) {
+    HeapWord* obj;
+    for (int pr = GCAllocPriorityStart; pr < GCAllocPriorityCount; ++pr) {
+      obj = _priority_buffer[pr]->allocate(word_sz);
+      if (obj != NULL) return obj;
+    }
+    return obj;
+  }
+
+  bool contains(void* addr) {
+    for (int pr = GCAllocPriorityStart; pr < GCAllocPriorityCount; ++pr) {
+      if (_priority_buffer[pr]->contains(addr)) return true;
+    }
+    return false;
+  }
+
+  void undo_allocation(HeapWord* obj, size_t word_sz) {
+    bool finish_undo;
+    for (int pr = GCAllocPriorityStart; pr < GCAllocPriorityCount; ++pr) {
+      if (_priority_buffer[pr]->contains(obj)) {
+        _priority_buffer[pr]->undo_allocation(obj, word_sz);
+        finish_undo = true;
+      }
+    }
+    if (finish_undo != true) ShouldNotReachHere();
+  }
+
+  size_t words_remaining() {
+    size_t result=0;
+    for (int pr = GCAllocPriorityStart; pr < GCAllocPriorityCount; ++pr) {
+      result += _priority_buffer[pr]->words_remaining();
+    }
+    return result;
+  }
+
+  size_t words_remaining_in_retired() {
+    G1ParGCAllocBuffer* retired =  _priority_buffer[GCAllocPriority1];
+    return retired->words_remaining();
+  }
+
+  void flush_stats_and_retire(PLABStats* stats, bool end_of_gc, bool retain) {
+    for (int pr = GCAllocPriorityStart; pr < GCAllocPriorityCount; ++pr) {
+      _priority_buffer[pr]->flush_stats_and_retire(stats, end_of_gc, retain);
+    }
+  }
+
+  void retire_and_set_buf(bool end_of_gc, bool retain, HeapWord* buf, size_t word_sz) {
+    G1ParGCAllocBuffer* retired_and_set =  _priority_buffer[GCAllocPriority1];
+    retired_and_set->retire(end_of_gc, retain);
+    retired_and_set->set_buf(buf);
+    retired_and_set->set_word_size(word_sz);
+    adjust_priority_order();
+  }
+
+private:
+  void adjust_priority_order() {
+    G1ParGCAllocBuffer* retired_and_set =  _priority_buffer[GCAllocPriority1];
+
+    int last = GCAllocPriorityCount - 1;
+    for (int pr = GCAllocPriorityStart; pr < last; ++pr) {
+      _priority_buffer[pr] = _priority_buffer[pr + 1];
+    }
+    _priority_buffer[last] = retired_and_set;
+  }
 };
 
 class G1ParScanThreadState : public StackObj {
 protected:
   G1CollectedHeap* _g1h;
   RefToScanQueue*  _refs;
   DirtyCardQueue   _dcq;
   CardTableModRefBS* _ct_bs;
   G1RemSet* _g1_rem;
 
-  G1ParGCAllocBuffer  _surviving_alloc_buffer;
-  G1ParGCAllocBuffer  _tenured_alloc_buffer;
-  G1ParGCAllocBuffer* _alloc_buffers[GCAllocPurposeCount];
+  G1MultiParGCAllocBuffer  _surviving_alloc_buffer;
+  G1MultiParGCAllocBuffer  _tenured_alloc_buffer;
+  G1MultiParGCAllocBuffer* _alloc_buffers[GCAllocPurposeCount];
   ageTable            _age_table;
 
   size_t           _alloc_buffer_waste;
   size_t           _undo_waste;
 

@@ -1821,11 +1911,11 @@
   }
 
   RefToScanQueue*   refs()            { return _refs;             }
   ageTable*         age_table()       { return &_age_table;       }
 
-  G1ParGCAllocBuffer* alloc_buffer(GCAllocPurpose purpose) {
+  G1MultiParGCAllocBuffer* alloc_buffer(GCAllocPurpose purpose) {
     return _alloc_buffers[purpose];
   }
 
   size_t alloc_buffer_waste() const              { return _alloc_buffer_waste; }
   size_t undo_waste() const                      { return _undo_waste; }

@@ -1851,19 +1941,18 @@
 
   HeapWord* allocate_slow(GCAllocPurpose purpose, size_t word_sz) {
     HeapWord* obj = NULL;
     size_t gclab_word_size = _g1h->desired_plab_sz(purpose);
     if (word_sz * 100 < gclab_word_size * ParallelGCBufferWastePct) {
-      G1ParGCAllocBuffer* alloc_buf = alloc_buffer(purpose);
-      add_to_alloc_buffer_waste(alloc_buf->words_remaining());
-      alloc_buf->retire(false /* end_of_gc */, false /* retain */);
+      G1MultiParGCAllocBuffer* alloc_buf = alloc_buffer(purpose);
 
       HeapWord* buf = _g1h->par_allocate_during_gc(purpose, gclab_word_size);
       if (buf == NULL) return NULL; // Let caller handle allocation failure.
-      // Otherwise.
-      alloc_buf->set_word_size(gclab_word_size);
-      alloc_buf->set_buf(buf);
+
+      add_to_alloc_buffer_waste(alloc_buf->words_remaining_in_retired());
+      alloc_buf->retire_and_set_buf(false /* end_of_gc */, false /* retain */,
+                                    buf, gclab_word_size);
 
       obj = alloc_buf->allocate(word_sz);
       assert(obj != NULL, "buffer was definitely big enough...");
     } else {
       obj = _g1h->par_allocate_during_gc(purpose, word_sz);

@@ -1971,10 +2060,9 @@
     } else {
       deal_with_reference((oop*)ref);
     }
   }
 
-public:
   void trim_queue();
 };
 
 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1COLLECTEDHEAP_HPP