6964458: Reimplement class meta-data storage to use native memory

Remove PermGen, allocate meta-data in metaspace linked to class loaders, rewrite GC walking, rewrite and rename metadata to be C++ classes

Co-authored-by: Stefan Karlsson <stefan.karlsson@oracle.com>
Co-authored-by: Mikael Gerdin <mikael.gerdin@oracle.com>
Co-authored-by: Tom Rodriguez <tom.rodriguez@oracle.com>
Reviewed-by: jmasa, stefank, never, coleenp, kvn, brutisso, mgerdin, dholmes, jrose, twisti, roland
This commit is contained in:
Jon Masamitsu 2012-09-01 13:25:18 -04:00 committed by Coleen Phillimore
parent 36eee7c8c8
commit 5c58d27aac
853 changed files with 26124 additions and 82956 deletions

View file

@ -32,10 +32,10 @@
#include "gc_implementation/parallelScavenge/psMarkSweep.hpp"
#include "gc_implementation/parallelScavenge/psMarkSweepDecorator.hpp"
#include "gc_implementation/parallelScavenge/psOldGen.hpp"
#include "gc_implementation/parallelScavenge/psPermGen.hpp"
#include "gc_implementation/parallelScavenge/psScavenge.hpp"
#include "gc_implementation/parallelScavenge/psYoungGen.hpp"
#include "gc_implementation/shared/isGCActiveMark.hpp"
#include "gc_implementation/shared/markSweep.hpp"
#include "gc_implementation/shared/spaceDecorator.hpp"
#include "gc_interface/gcCause.hpp"
#include "memory/gcLocker.inline.hpp"
@ -52,7 +52,6 @@
#include "utilities/stack.inline.hpp"
elapsedTimer PSMarkSweep::_accumulated_time;
unsigned int PSMarkSweep::_total_invocations = 0;
jlong PSMarkSweep::_time_of_last_gc = 0;
CollectorCounters* PSMarkSweep::_counters = NULL;
@ -119,7 +118,6 @@ bool PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) {
PSYoungGen* young_gen = heap->young_gen();
PSOldGen* old_gen = heap->old_gen();
PSPermGen* perm_gen = heap->perm_gen();
// Increment the invocation count
heap->increment_total_collections(true /* full */);
@ -148,7 +146,6 @@ bool PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) {
if (VerifyObjectStartArray &&
VerifyBeforeGC) {
old_gen->verify_object_start_array();
perm_gen->verify_object_start_array();
}
heap->pre_full_gc_dump();
@ -172,8 +169,6 @@ bool PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) {
// Let the size policy know we're starting
size_policy->major_collection_begin();
// When collecting the permanent generation methodOops may be moving,
// so we either have to flush all bcp data or convert it into bci.
CodeCache::gc_prologue();
Threads::gc_prologue();
BiasedLocking::preserve_marks();
@ -181,8 +176,8 @@ bool PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) {
// Capture heap size before collection for printing.
size_t prev_used = heap->used();
// Capture perm gen size before collection for sizing.
size_t perm_gen_prev_used = perm_gen->used_in_bytes();
// Capture metadata size before collection for sizing.
size_t metadata_prev_used = MetaspaceAux::used_in_bytes();
// For PrintGCDetails
size_t old_gen_prev_used = old_gen->used_in_bytes();
@ -234,16 +229,16 @@ bool PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) {
if (bs->is_a(BarrierSet::ModRef)) {
ModRefBarrierSet* modBS = (ModRefBarrierSet*)bs;
MemRegion old_mr = heap->old_gen()->reserved();
MemRegion perm_mr = heap->perm_gen()->reserved();
assert(perm_mr.end() <= old_mr.start(), "Generations out of order");
if (young_gen_empty) {
modBS->clear(MemRegion(perm_mr.start(), old_mr.end()));
modBS->clear(MemRegion(old_mr.start(), old_mr.end()));
} else {
modBS->invalidate(MemRegion(perm_mr.start(), old_mr.end()));
modBS->invalidate(MemRegion(old_mr.start(), old_mr.end()));
}
}
// Delete metaspaces for unloaded class loaders and clean up loader_data graph
ClassLoaderDataGraph::purge();
BiasedLocking::restore_marks();
Threads::gc_epilogue();
CodeCache::gc_epilogue();
@ -267,10 +262,8 @@ bool PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) {
gclog_or_tty->print_cr(" collection: %d ",
heap->total_collections());
if (Verbose) {
gclog_or_tty->print("old_gen_capacity: %d young_gen_capacity: %d"
" perm_gen_capacity: %d ",
old_gen->capacity_in_bytes(), young_gen->capacity_in_bytes(),
perm_gen->capacity_in_bytes());
gclog_or_tty->print("old_gen_capacity: %d young_gen_capacity: %d",
old_gen->capacity_in_bytes(), young_gen->capacity_in_bytes());
}
}
@ -290,7 +283,6 @@ bool PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) {
size_policy->compute_generation_free_space(young_gen->used_in_bytes(),
young_gen->eden_space()->used_in_bytes(),
old_gen->used_in_bytes(),
perm_gen->used_in_bytes(),
young_gen->eden_space()->capacity_in_bytes(),
old_gen->max_gen_size(),
max_eden_size,
@ -323,8 +315,8 @@ bool PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) {
heap->resize_all_tlabs();
// We collected the perm gen, so we'll resize it here.
perm_gen->compute_new_size(perm_gen_prev_used);
// We collected the heap, recalculate the metaspace capacity
MetaspaceGC::compute_new_size();
if (TraceGen1Time) accumulated_time()->stop();
@ -336,11 +328,8 @@ bool PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) {
old_gen->print_used_change(old_gen_prev_used);
}
heap->print_heap_change(prev_used);
// Do perm gen after heap becase prev_used does
// not include the perm gen (done this way in the other
// collectors).
if (PrintGCDetails) {
perm_gen->print_used_change(perm_gen_prev_used);
MetaspaceAux::print_metaspace_change(metadata_prev_used);
}
}
@ -359,12 +348,10 @@ bool PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) {
if (VerifyObjectStartArray &&
VerifyAfterGC) {
old_gen->verify_object_start_array();
perm_gen->verify_object_start_array();
}
if (ZapUnusedHeapArea) {
old_gen->object_space()->check_mangled_unused_area_complete();
perm_gen->object_space()->check_mangled_unused_area_complete();
}
NOT_PRODUCT(ref_processor()->verify_no_references_recorded());
@ -490,8 +477,6 @@ void PSMarkSweep::deallocate_stacks() {
_preserved_oop_stack.clear(true);
_marking_stack.clear();
_objarray_stack.clear(true);
_revisit_klass_stack.clear(true);
_revisit_mdo_stack.clear(true);
}
void PSMarkSweep::mark_sweep_phase1(bool clear_all_softrefs) {
@ -502,6 +487,9 @@ void PSMarkSweep::mark_sweep_phase1(bool clear_all_softrefs) {
ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity");
// Need to clear claim bits before the tracing starts.
ClassLoaderDataGraph::clear_claimed_marks();
// General strong roots.
{
ParallelScavengeHeap::ParStrongRootsScope psrs;
@ -514,6 +502,7 @@ void PSMarkSweep::mark_sweep_phase1(bool clear_all_softrefs) {
Management::oops_do(mark_and_push_closure());
JvmtiExport::oops_do(mark_and_push_closure());
SystemDictionary::always_strong_oops_do(mark_and_push_closure());
ClassLoaderDataGraph::always_strong_oops_do(mark_and_push_closure(), follow_klass_closure(), true);
// Do not treat nmethods as strong roots for mark/sweep, since we can unload them.
//CodeCache::scavenge_root_nmethods_do(CodeBlobToOopClosure(mark_and_push_closure()));
}
@ -537,11 +526,7 @@ void PSMarkSweep::mark_sweep_phase1(bool clear_all_softrefs) {
follow_stack(); // Flush marking stack
// Update subklass/sibling/implementor links of live klasses
follow_weak_klass_links();
assert(_marking_stack.is_empty(), "just drained");
// Visit memoized mdo's and clear unmarked weak refs
follow_mdo_weak_refs();
Klass::clean_weak_klass_links(&is_alive);
assert(_marking_stack.is_empty(), "just drained");
// Visit interned string tables and delete unmarked oops
@ -559,13 +544,6 @@ void PSMarkSweep::mark_sweep_phase2() {
// Now all live objects are marked, compute the new object addresses.
// It is imperative that we traverse perm_gen LAST. If dead space is
// allowed a range of dead object may get overwritten by a dead int
// array. If perm_gen is not traversed last a klassOop may get
// overwritten. This is fine since it is dead, but if the class has dead
// instances we have to skip them, and in order to find their size we
// need the klassOop!
//
// It is not required that we traverse spaces in the same order in
// phase2, phase3 and phase4, but the ValidateMarkSweep live oops
// tracking expects us to do so. See comment under phase4.
@ -574,18 +552,12 @@ void PSMarkSweep::mark_sweep_phase2() {
assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity");
PSOldGen* old_gen = heap->old_gen();
PSPermGen* perm_gen = heap->perm_gen();
// Begin compacting into the old gen
PSMarkSweepDecorator::set_destination_decorator_tenured();
// This will also compact the young gen spaces.
old_gen->precompact();
// Compact the perm gen into the perm gen
PSMarkSweepDecorator::set_destination_decorator_perm_gen();
perm_gen->precompact();
}
// This should be moved to the shared markSweep code!
@ -606,7 +578,9 @@ void PSMarkSweep::mark_sweep_phase3() {
PSYoungGen* young_gen = heap->young_gen();
PSOldGen* old_gen = heap->old_gen();
PSPermGen* perm_gen = heap->perm_gen();
// Need to clear claim bits before the tracing starts.
ClassLoaderDataGraph::clear_claimed_marks();
// General strong roots.
Universe::oops_do(adjust_root_pointer_closure());
@ -618,6 +592,7 @@ void PSMarkSweep::mark_sweep_phase3() {
JvmtiExport::oops_do(adjust_root_pointer_closure());
// SO_AllClasses
SystemDictionary::oops_do(adjust_root_pointer_closure());
ClassLoaderDataGraph::oops_do(adjust_root_pointer_closure(), adjust_klass_closure(), true);
//CodeCache::scavenge_root_nmethods_oops_do(adjust_root_pointer_closure());
// Now adjust pointers in remaining weak roots. (All of which should
@ -634,7 +609,6 @@ void PSMarkSweep::mark_sweep_phase3() {
young_gen->adjust_pointers();
old_gen->adjust_pointers();
perm_gen->adjust_pointers();
}
void PSMarkSweep::mark_sweep_phase4() {
@ -644,18 +618,12 @@ void PSMarkSweep::mark_sweep_phase4() {
// All pointers are now adjusted, move objects accordingly
// It is imperative that we traverse perm_gen first in phase4. All
// classes must be allocated earlier than their instances, and traversing
// perm_gen first makes sure that all klassOops have moved to their new
// location before any instance does a dispatch through it's klass!
ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity");
PSYoungGen* young_gen = heap->young_gen();
PSOldGen* old_gen = heap->old_gen();
PSPermGen* perm_gen = heap->perm_gen();
perm_gen->compact();
old_gen->compact();
young_gen->compact();
}