hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp
changeset 13728 882756847a04
parent 13195 be27e1b6a4b9
child 15959 9a29e0e3a633
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp	Fri Aug 31 16:39:35 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp	Sat Sep 01 13:25:18 2012 -0400
@@ -45,26 +45,23 @@
 
 PSYoungGen*  ParallelScavengeHeap::_young_gen = NULL;
 PSOldGen*    ParallelScavengeHeap::_old_gen = NULL;
-PSPermGen*   ParallelScavengeHeap::_perm_gen = NULL;
 PSAdaptiveSizePolicy* ParallelScavengeHeap::_size_policy = NULL;
 PSGCAdaptivePolicyCounters* ParallelScavengeHeap::_gc_policy_counters = NULL;
 ParallelScavengeHeap* ParallelScavengeHeap::_psh = NULL;
 GCTaskManager* ParallelScavengeHeap::_gc_task_manager = NULL;
 
 static void trace_gen_sizes(const char* const str,
-                            size_t pg_min, size_t pg_max,
                             size_t og_min, size_t og_max,
                             size_t yg_min, size_t yg_max)
 {
   if (TracePageSizes) {
     tty->print_cr("%s:  " SIZE_FORMAT "," SIZE_FORMAT " "
                   SIZE_FORMAT "," SIZE_FORMAT " "
-                  SIZE_FORMAT "," SIZE_FORMAT " "
                   SIZE_FORMAT,
-                  str, pg_min / K, pg_max / K,
+                  str,
                   og_min / K, og_max / K,
                   yg_min / K, yg_max / K,
-                  (pg_max + og_max + yg_max) / K);
+                  (og_max + yg_max) / K);
   }
 }
 
@@ -79,25 +76,15 @@
   size_t yg_max_size = _collector_policy->max_young_gen_size();
   size_t og_min_size = _collector_policy->min_old_gen_size();
   size_t og_max_size = _collector_policy->max_old_gen_size();
-  // Why isn't there a min_perm_gen_size()?
-  size_t pg_min_size = _collector_policy->perm_gen_size();
-  size_t pg_max_size = _collector_policy->max_perm_gen_size();
 
   trace_gen_sizes("ps heap raw",
-                  pg_min_size, pg_max_size,
                   og_min_size, og_max_size,
                   yg_min_size, yg_max_size);
 
-  // The ReservedSpace ctor used below requires that the page size for the perm
-  // gen is <= the page size for the rest of the heap (young + old gens).
   const size_t og_page_sz = os::page_size_for_region(yg_min_size + og_min_size,
                                                      yg_max_size + og_max_size,
                                                      8);
-  const size_t pg_page_sz = MIN2(os::page_size_for_region(pg_min_size,
-                                                          pg_max_size, 16),
-                                 og_page_sz);
 
-  const size_t pg_align = set_alignment(_perm_gen_alignment,  pg_page_sz);
   const size_t og_align = set_alignment(_old_gen_alignment,   og_page_sz);
   const size_t yg_align = set_alignment(_young_gen_alignment, og_page_sz);
 
@@ -121,55 +108,20 @@
     align_size_down(_collector_policy->old_gen_size(), og_align);
   og_cur_size = MAX2(og_cur_size, og_min_size);
 
-  pg_min_size = align_size_up(pg_min_size, pg_align);
-  pg_max_size = align_size_up(pg_max_size, pg_align);
-  size_t pg_cur_size = pg_min_size;
-
   trace_gen_sizes("ps heap rnd",
-                  pg_min_size, pg_max_size,
                   og_min_size, og_max_size,
                   yg_min_size, yg_max_size);
 
-  const size_t total_reserved = pg_max_size + og_max_size + yg_max_size;
-  char* addr = Universe::preferred_heap_base(total_reserved, Universe::UnscaledNarrowOop);
-
-  // The main part of the heap (old gen + young gen) can often use a larger page
-  // size than is needed or wanted for the perm gen.  Use the "compound
-  // alignment" ReservedSpace ctor to avoid having to use the same page size for
-  // all gens.
-
-  ReservedHeapSpace heap_rs(pg_max_size, pg_align, og_max_size + yg_max_size,
-                            og_align, addr);
+  const size_t heap_size = og_max_size + yg_max_size;
 
-  if (UseCompressedOops) {
-    if (addr != NULL && !heap_rs.is_reserved()) {
-      // Failed to reserve at specified address - the requested memory
-      // region is taken already, for example, by 'java' launcher.
-      // Try again to reserver heap higher.
-      addr = Universe::preferred_heap_base(total_reserved, Universe::ZeroBasedNarrowOop);
-      ReservedHeapSpace heap_rs0(pg_max_size, pg_align, og_max_size + yg_max_size,
-                                 og_align, addr);
-      if (addr != NULL && !heap_rs0.is_reserved()) {
-        // Failed to reserve at specified address again - give up.
-        addr = Universe::preferred_heap_base(total_reserved, Universe::HeapBasedNarrowOop);
-        assert(addr == NULL, "");
-        ReservedHeapSpace heap_rs1(pg_max_size, pg_align, og_max_size + yg_max_size,
-                                   og_align, addr);
-        heap_rs = heap_rs1;
-      } else {
-        heap_rs = heap_rs0;
-      }
-    }
-  }
+  ReservedSpace heap_rs = Universe::reserve_heap(heap_size, og_align);
 
   MemTracker::record_virtual_memory_type((address)heap_rs.base(), mtJavaHeap);
 
-  os::trace_page_sizes("ps perm", pg_min_size, pg_max_size, pg_page_sz,
-                       heap_rs.base(), pg_max_size);
   os::trace_page_sizes("ps main", og_min_size + yg_min_size,
                        og_max_size + yg_max_size, og_page_sz,
-                       heap_rs.base() + pg_max_size,
-                       heap_rs.size() - pg_max_size);
+                       heap_rs.base(),
+                       heap_rs.size());
   if (!heap_rs.is_reserved()) {
     vm_shutdown_during_initialization(
       "Could not reserve enough space for object heap");
@@ -194,11 +146,6 @@
   const size_t init_young_size = align_size_up(4 * M, yg_align);
   yg_cur_size = MAX2(MIN2(init_young_size, yg_max_size), yg_cur_size);
 
-  // Split the reserved space into perm gen and the main heap (everything else).
-  // The main heap uses a different alignment.
-  ReservedSpace perm_rs = heap_rs.first_part(pg_max_size);
-  ReservedSpace main_rs = heap_rs.last_part(pg_max_size, og_align);
-
   // Make up the generations
   // Calculate the maximum size that a generation can grow.  This
   // includes growth into the other generation.  Note that the
@@ -208,7 +155,7 @@
   double max_gc_pause_sec = ((double) MaxGCPauseMillis)/1000.0;
   double max_gc_minor_pause_sec = ((double) MaxGCMinorPauseMillis)/1000.0;
 
-  _gens = new AdjoiningGenerations(main_rs,
+  _gens = new AdjoiningGenerations(heap_rs,
                                    og_cur_size,
                                    og_min_size,
                                    og_max_size,
@@ -233,13 +180,6 @@
                              GCTimeRatio
                              );
 
-  _perm_gen = new PSPermGen(perm_rs,
-                            pg_align,
-                            pg_cur_size,
-                            pg_cur_size,
-                            pg_max_size,
-                            "perm", 2);
-
   assert(!UseAdaptiveGCBoundary ||
     (old_gen()->virtual_space()->high_boundary() ==
      young_gen()->virtual_space()->low_boundary()),
@@ -273,7 +213,7 @@
 void ParallelScavengeHeap::update_counters() {
   young_gen()->update_counters();
   old_gen()->update_counters();
-  perm_gen()->update_counters();
+  MetaspaceCounters::update_performance_counters();
 }
 
 size_t ParallelScavengeHeap::capacity() const {
@@ -291,17 +231,8 @@
 }
 
 
-size_t ParallelScavengeHeap::permanent_capacity() const {
-  return perm_gen()->capacity_in_bytes();
-}
-
-size_t ParallelScavengeHeap::permanent_used() const {
-  return perm_gen()->used_in_bytes();
-}
-
 size_t ParallelScavengeHeap::max_capacity() const {
   size_t estimated = reserved_region().byte_size();
-  estimated -= perm_gen()->reserved().byte_size();
   if (UseAdaptiveSizePolicy) {
     estimated -= _size_policy->max_survivor_size(young_gen()->max_size());
   } else {
@@ -319,10 +250,6 @@
     return true;
   }
 
-  if (perm_gen()->is_in(p)) {
-    return true;
-  }
-
   return false;
 }
 
@@ -335,10 +262,6 @@
     return true;
   }
 
-  if (perm_gen()->is_in_reserved(p)) {
-    return true;
-  }
-
   return false;
 }
 
@@ -352,7 +275,7 @@
 bool ParallelScavengeHeap::is_in_partial_collection(const void *p) {
   assert(is_in_reserved(p) || p == NULL,
     "Does not work if address is non-null and outside of the heap");
-  // The order of the generations is perm (low addr), old, young (high addr)
+  // The order of the generations is old (low addr), young (high addr)
   return p >= old_gen()->reserved().end();
 }
 #endif
@@ -553,6 +476,18 @@
   return NULL;
 }
 
+void ParallelScavengeHeap::do_full_collection(bool clear_all_soft_refs) {
+  if (UseParallelOldGC) {
+    // The do_full_collection() parameter clear_all_soft_refs
+    // is interpreted here as maximum_compaction which will
+    // cause SoftRefs to be cleared.
+    bool maximum_compaction = clear_all_soft_refs;
+    PSParallelCompact::invoke(maximum_compaction);
+  } else {
+    PSMarkSweep::invoke(clear_all_soft_refs);
+  }
+}
+
 // Failed allocation policy. Must be called from the VM thread, and
 // only at a safepoint! Note that this method has policy for allocation
 // flow, and NOT collection policy. So we do not check for gc collection
@@ -575,7 +510,7 @@
   // Second level allocation failure.
   //   Mark sweep and allocate in young generation.
   if (result == NULL && !invoked_full_gc) {
-    invoke_full_gc(false);
+    do_full_collection(false);
     result = young_gen()->allocate(size);
   }
 
@@ -591,7 +526,7 @@
   // Fourth level allocation failure. We're running out of memory.
   //   More complete mark sweep and allocate in young generation.
   if (result == NULL) {
-    invoke_full_gc(true);
+    do_full_collection(true);
     result = young_gen()->allocate(size);
   }
 
@@ -604,160 +539,6 @@
   return result;
 }
 
-//
-// This is the policy loop for allocating in the permanent generation.
-// If the initial allocation fails, we create a vm operation which will
-// cause a collection.
-HeapWord* ParallelScavengeHeap::permanent_mem_allocate(size_t size) {
-  assert(!SafepointSynchronize::is_at_safepoint(), "should not be at safepoint");
-  assert(Thread::current() != (Thread*)VMThread::vm_thread(), "should not be in vm thread");
-  assert(!Heap_lock->owned_by_self(), "this thread should not own the Heap_lock");
-
-  HeapWord* result;
-
-  uint loop_count = 0;
-  uint gc_count = 0;
-  uint full_gc_count = 0;
-
-  do {
-    // We don't want to have multiple collections for a single filled generation.
-    // To prevent this, each thread tracks the total_collections() value, and if
-    // the count has changed, does not do a new collection.
-    //
-    // The collection count must be read only while holding the heap lock. VM
-    // operations also hold the heap lock during collections. There is a lock
-    // contention case where thread A blocks waiting on the Heap_lock, while
-    // thread B is holding it doing a collection. When thread A gets the lock,
-    // the collection count has already changed. To prevent duplicate collections,
-    // The policy MUST attempt allocations during the same period it reads the
-    // total_collections() value!
-    {
-      MutexLocker ml(Heap_lock);
-      gc_count      = Universe::heap()->total_collections();
-      full_gc_count = Universe::heap()->total_full_collections();
-
-      result = perm_gen()->allocate_permanent(size);
-
-      if (result != NULL) {
-        return result;
-      }
-
-      if (GC_locker::is_active_and_needs_gc()) {
-        // If this thread is not in a jni critical section, we stall
-        // the requestor until the critical section has cleared and
-        // GC allowed. When the critical section clears, a GC is
-        // initiated by the last thread exiting the critical section; so
-        // we retry the allocation sequence from the beginning of the loop,
-        // rather than causing more, now probably unnecessary, GC attempts.
-        JavaThread* jthr = JavaThread::current();
-        if (!jthr->in_critical()) {
-          MutexUnlocker mul(Heap_lock);
-          GC_locker::stall_until_clear();
-          continue;
-        } else {
-          if (CheckJNICalls) {
-            fatal("Possible deadlock due to allocating while"
-                  " in jni critical section");
-          }
-          return NULL;
-        }
-      }
-    }
-
-    if (result == NULL) {
-
-      // Exit the loop if the gc time limit has been exceeded.
-      // The allocation must have failed above (result must be NULL),
-      // and the most recent collection must have exceeded the
-      // gc time limit.  Exit the loop so that an out-of-memory
-      // will be thrown (returning a NULL will do that), but
-      // clear gc_overhead_limit_exceeded so that the next collection
-      // will succeeded if the applications decides to handle the
-      // out-of-memory and tries to go on.
-      const bool limit_exceeded = size_policy()->gc_overhead_limit_exceeded();
-      if (limit_exceeded) {
-        size_policy()->set_gc_overhead_limit_exceeded(false);
-        if (PrintGCDetails && Verbose) {
-          gclog_or_tty->print_cr("ParallelScavengeHeap::permanent_mem_allocate:"
-            " return NULL because gc_overhead_limit_exceeded is set");
-        }
-        assert(result == NULL, "Allocation did not fail");
-        return NULL;
-      }
-
-      // Generate a VM operation
-      VM_ParallelGCFailedPermanentAllocation op(size, gc_count, full_gc_count);
-      VMThread::execute(&op);
-
-      // Did the VM operation execute? If so, return the result directly.
-      // This prevents us from looping until time out on requests that can
-      // not be satisfied.
-      if (op.prologue_succeeded()) {
-        assert(Universe::heap()->is_in_permanent_or_null(op.result()),
-          "result not in heap");
-        // If GC was locked out during VM operation then retry allocation
-        // and/or stall as necessary.
-        if (op.gc_locked()) {
-          assert(op.result() == NULL, "must be NULL if gc_locked() is true");
-          continue;  // retry and/or stall as necessary
-        }
-        // If a NULL results is being returned, an out-of-memory
-        // will be thrown now.  Clear the gc_overhead_limit_exceeded
-        // flag to avoid the following situation.
-        //      gc_overhead_limit_exceeded is set during a collection
-        //      the collection fails to return enough space and an OOM is thrown
-        //      a subsequent GC prematurely throws an out-of-memory because
-        //        the gc_overhead_limit_exceeded counts did not start
-        //        again from 0.
-        if (op.result() == NULL) {
-          size_policy()->reset_gc_overhead_limit_count();
-        }
-        return op.result();
-      }
-    }
-
-    // The policy object will prevent us from looping forever. If the
-    // time spent in gc crosses a threshold, we will bail out.
-    loop_count++;
-    if ((QueuedAllocationWarningCount > 0) &&
-        (loop_count % QueuedAllocationWarningCount == 0)) {
-      warning("ParallelScavengeHeap::permanent_mem_allocate retries %d times \n\t"
-              " size=%d", loop_count, size);
-    }
-  } while (result == NULL);
-
-  return result;
-}
-
-//
-// This is the policy code for permanent allocations which have failed
-// and require a collection. Note that just as in failed_mem_allocate,
-// we do not set collection policy, only where & when to allocate and
-// collect.
-HeapWord* ParallelScavengeHeap::failed_permanent_mem_allocate(size_t size) {
-  assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint");
-  assert(Thread::current() == (Thread*)VMThread::vm_thread(), "should be in vm thread");
-  assert(!Universe::heap()->is_gc_active(), "not reentrant");
-  assert(!Heap_lock->owned_by_self(), "this thread should not own the Heap_lock");
-  assert(size > perm_gen()->free_in_words(), "Allocation should fail");
-
-  // We assume (and assert!) that an allocation at this point will fail
-  // unless we collect.
-
-  // First level allocation failure.  Mark-sweep and allocate in perm gen.
-  GCCauseSetter gccs(this, GCCause::_allocation_failure);
-  invoke_full_gc(false);
-  HeapWord* result = perm_gen()->allocate_permanent(size);
-
-  // Second level allocation failure. We're running out of memory.
-  if (result == NULL) {
-    invoke_full_gc(true);
-    result = perm_gen()->allocate_permanent(size);
-  }
-
-  return result;
-}
-
 void ParallelScavengeHeap::ensure_parsability(bool retire_tlabs) {
   CollectedHeap::ensure_parsability(retire_tlabs);
   young_gen()->eden_space()->ensure_parsability();
@@ -812,44 +593,15 @@
   VMThread::execute(&op);
 }
 
-// This interface assumes that it's being called by the
-// vm thread. It collects the heap assuming that the
-// heap lock is already held and that we are executing in
-// the context of the vm thread.
-void ParallelScavengeHeap::collect_as_vm_thread(GCCause::Cause cause) {
-  assert(Thread::current()->is_VM_thread(), "Precondition#1");
-  assert(Heap_lock->is_locked(), "Precondition#2");
-  GCCauseSetter gcs(this, cause);
-  switch (cause) {
-    case GCCause::_heap_inspection:
-    case GCCause::_heap_dump: {
-      HandleMark hm;
-      invoke_full_gc(false);
-      break;
-    }
-    default: // XXX FIX ME
-      ShouldNotReachHere();
-  }
-}
-
-
-void ParallelScavengeHeap::oop_iterate(OopClosure* cl) {
+void ParallelScavengeHeap::oop_iterate(ExtendedOopClosure* cl) {
   Unimplemented();
 }
 
 void ParallelScavengeHeap::object_iterate(ObjectClosure* cl) {
   young_gen()->object_iterate(cl);
   old_gen()->object_iterate(cl);
-  perm_gen()->object_iterate(cl);
 }
 
-void ParallelScavengeHeap::permanent_oop_iterate(OopClosure* cl) {
-  Unimplemented();
-}
-
-void ParallelScavengeHeap::permanent_object_iterate(ObjectClosure* cl) {
-  perm_gen()->object_iterate(cl);
-}
 
 HeapWord* ParallelScavengeHeap::block_start(const void* addr) const {
   if (young_gen()->is_in_reserved(addr)) {
@@ -862,10 +614,6 @@
     assert(old_gen()->is_in(addr),
            "addr should be in allocated part of old gen");
     return old_gen()->start_array()->object_start((HeapWord*)addr);
-  } else if (perm_gen()->is_in_reserved(addr)) {
-    assert(perm_gen()->is_in(addr),
-           "addr should be in allocated part of perm gen");
-    return perm_gen()->start_array()->object_start((HeapWord*)addr);
   }
   return 0;
 }
@@ -891,7 +639,7 @@
 void ParallelScavengeHeap::print_on(outputStream* st) const {
   young_gen()->print_on(st);
   old_gen()->print_on(st);
-  perm_gen()->print_on(st);
+  MetaspaceAux::print_on(st);
 }
 
 void ParallelScavengeHeap::gc_threads_do(ThreadClosure* tc) const {
@@ -918,11 +666,6 @@
   // Why do we need the total_collections()-filter below?
   if (total_collections() > 0) {
     if (!silent) {
-      gclog_or_tty->print("permanent ");
-    }
-    perm_gen()->verify();
-
-    if (!silent) {
       gclog_or_tty->print("tenured ");
     }
     old_gen()->verify();
@@ -1000,7 +743,6 @@
   if (ZapUnusedHeapArea) {
     young_gen()->record_spaces_top();
     old_gen()->record_spaces_top();
-    perm_gen()->record_spaces_top();
   }
 }
 
@@ -1010,7 +752,6 @@
     young_gen()->to_space()->mangle_unused_area();
     young_gen()->from_space()->mangle_unused_area();
     old_gen()->object_space()->mangle_unused_area();
-    perm_gen()->object_space()->mangle_unused_area();
   }
 }
 #endif