mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-21 11:34:38 +02:00
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:
parent
36eee7c8c8
commit
5c58d27aac
853 changed files with 26124 additions and 82956 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2012, 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
|
||||
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "precompiled.hpp"
|
||||
#include "gc_implementation/shared/cSpaceCounters.hpp"
|
||||
#include "memory/metaspace.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
|
||||
CSpaceCounters::CSpaceCounters(const char* name, int ordinal, size_t max_size,
|
||||
|
@ -44,7 +45,7 @@ CSpaceCounters::CSpaceCounters(const char* name, int ordinal, size_t max_size,
|
|||
PerfDataManager::create_string_constant(SUN_GC, cname, name, CHECK);
|
||||
|
||||
cname = PerfDataManager::counter_name(_name_space, "maxCapacity");
|
||||
PerfDataManager::create_constant(SUN_GC, cname, PerfData::U_Bytes,
|
||||
_max_capacity = PerfDataManager::create_variable(SUN_GC, cname, PerfData::U_Bytes,
|
||||
(jlong)max_size, CHECK);
|
||||
|
||||
cname = PerfDataManager::counter_name(_name_space, "capacity");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2012, 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
|
||||
|
@ -38,6 +38,7 @@ class CSpaceCounters: public CHeapObj<mtGC> {
|
|||
private:
|
||||
PerfVariable* _capacity;
|
||||
PerfVariable* _used;
|
||||
PerfVariable* _max_capacity;
|
||||
|
||||
// Constant PerfData types don't need to retain a reference.
|
||||
// However, it's a good idea to document them here.
|
||||
|
@ -55,15 +56,15 @@ class CSpaceCounters: public CHeapObj<mtGC> {
|
|||
if (_name_space != NULL) FREE_C_HEAP_ARRAY(char, _name_space, mtInternal);
|
||||
}
|
||||
|
||||
inline void update_capacity() {
|
||||
virtual inline void update_capacity() {
|
||||
_capacity->set_value(_space->capacity());
|
||||
}
|
||||
|
||||
inline void update_used() {
|
||||
virtual inline void update_used() {
|
||||
_used->set_value(_space->used());
|
||||
}
|
||||
|
||||
inline void update_all() {
|
||||
virtual inline void update_all() {
|
||||
update_used();
|
||||
update_capacity();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2012, 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
|
||||
|
@ -175,7 +175,7 @@ SurrogateLockerThread::SurrogateLockerThread() :
|
|||
{}
|
||||
|
||||
SurrogateLockerThread* SurrogateLockerThread::make(TRAPS) {
|
||||
klassOop k =
|
||||
Klass* k =
|
||||
SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(),
|
||||
true, CHECK_NULL);
|
||||
instanceKlassHandle klass (THREAD, k);
|
||||
|
|
|
@ -40,7 +40,7 @@ void ImmutableSpace::initialize(MemRegion mr) {
|
|||
_end = end;
|
||||
}
|
||||
|
||||
void ImmutableSpace::oop_iterate(OopClosure* cl) {
|
||||
void ImmutableSpace::oop_iterate(ExtendedOopClosure* cl) {
|
||||
HeapWord* obj_addr = bottom();
|
||||
HeapWord* t = end();
|
||||
// Could call objects iterate, but this is easier.
|
||||
|
|
|
@ -59,7 +59,7 @@ class ImmutableSpace: public CHeapObj<mtGC> {
|
|||
virtual size_t capacity_in_words(Thread*) const { return capacity_in_words(); }
|
||||
|
||||
// Iteration.
|
||||
virtual void oop_iterate(OopClosure* cl);
|
||||
virtual void oop_iterate(ExtendedOopClosure* cl);
|
||||
virtual void object_iterate(ObjectClosure* cl);
|
||||
|
||||
// Debugging
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2012, 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
|
||||
|
@ -26,13 +26,13 @@
|
|||
#include "compiler/compileBroker.hpp"
|
||||
#include "gc_implementation/shared/markSweep.inline.hpp"
|
||||
#include "gc_interface/collectedHeap.inline.hpp"
|
||||
#include "oops/methodDataOop.hpp"
|
||||
#include "oops/methodData.hpp"
|
||||
#include "oops/objArrayKlass.inline.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
|
||||
unsigned int MarkSweep::_total_invocations = 0;
|
||||
|
||||
Stack<oop, mtGC> MarkSweep::_marking_stack;
|
||||
Stack<DataLayout*, mtGC> MarkSweep::_revisit_mdo_stack;
|
||||
Stack<Klass*, mtGC> MarkSweep::_revisit_klass_stack;
|
||||
Stack<ObjArrayTask, mtGC> MarkSweep::_objarray_stack;
|
||||
|
||||
Stack<oop, mtGC> MarkSweep::_preserved_oop_stack;
|
||||
|
@ -62,47 +62,6 @@ GrowableArray<HeapWord*>* MarkSweep::_last_gc_live_oops_moved_to = NULL;
|
|||
GrowableArray<size_t> * MarkSweep::_last_gc_live_oops_size = NULL;
|
||||
#endif
|
||||
|
||||
void MarkSweep::revisit_weak_klass_link(Klass* k) {
|
||||
_revisit_klass_stack.push(k);
|
||||
}
|
||||
|
||||
void MarkSweep::follow_weak_klass_links() {
|
||||
// All klasses on the revisit stack are marked at this point.
|
||||
// Update and follow all subklass, sibling and implementor links.
|
||||
if (PrintRevisitStats) {
|
||||
gclog_or_tty->print_cr("#classes in system dictionary = %d",
|
||||
SystemDictionary::number_of_classes());
|
||||
gclog_or_tty->print_cr("Revisit klass stack size = " SIZE_FORMAT,
|
||||
_revisit_klass_stack.size());
|
||||
}
|
||||
while (!_revisit_klass_stack.is_empty()) {
|
||||
Klass* const k = _revisit_klass_stack.pop();
|
||||
k->follow_weak_klass_links(&is_alive, &keep_alive);
|
||||
}
|
||||
follow_stack();
|
||||
}
|
||||
|
||||
void MarkSweep::revisit_mdo(DataLayout* p) {
|
||||
_revisit_mdo_stack.push(p);
|
||||
}
|
||||
|
||||
void MarkSweep::follow_mdo_weak_refs() {
|
||||
// All strongly reachable oops have been marked at this point;
|
||||
// we can visit and clear any weak references from MDO's which
|
||||
// we memoized during the strong marking phase.
|
||||
assert(_marking_stack.is_empty(), "Marking stack should be empty");
|
||||
if (PrintRevisitStats) {
|
||||
gclog_or_tty->print_cr("#classes in system dictionary = %d",
|
||||
SystemDictionary::number_of_classes());
|
||||
gclog_or_tty->print_cr("Revisit MDO stack size = " SIZE_FORMAT,
|
||||
_revisit_mdo_stack.size());
|
||||
}
|
||||
while (!_revisit_mdo_stack.is_empty()) {
|
||||
_revisit_mdo_stack.pop()->follow_weak_refs(&is_alive);
|
||||
}
|
||||
follow_stack();
|
||||
}
|
||||
|
||||
MarkSweep::FollowRootClosure MarkSweep::follow_root_closure;
|
||||
CodeBlobToOopClosure MarkSweep::follow_code_root_closure(&MarkSweep::follow_root_closure, /*do_marking=*/ true);
|
||||
|
||||
|
@ -110,10 +69,46 @@ void MarkSweep::FollowRootClosure::do_oop(oop* p) { follow_root(p); }
|
|||
void MarkSweep::FollowRootClosure::do_oop(narrowOop* p) { follow_root(p); }
|
||||
|
||||
MarkSweep::MarkAndPushClosure MarkSweep::mark_and_push_closure;
|
||||
MarkSweep::FollowKlassClosure MarkSweep::follow_klass_closure;
|
||||
MarkSweep::AdjustKlassClosure MarkSweep::adjust_klass_closure;
|
||||
|
||||
void MarkSweep::MarkAndPushClosure::do_oop(oop* p) { assert(*p == NULL || (*p)->is_oop(), ""); mark_and_push(p); }
|
||||
void MarkSweep::MarkAndPushClosure::do_oop(oop* p) { mark_and_push(p); }
|
||||
void MarkSweep::MarkAndPushClosure::do_oop(narrowOop* p) { mark_and_push(p); }
|
||||
|
||||
void MarkSweep::FollowKlassClosure::do_klass(Klass* klass) {
|
||||
klass->oops_do(&MarkSweep::mark_and_push_closure);
|
||||
}
|
||||
void MarkSweep::AdjustKlassClosure::do_klass(Klass* klass) {
|
||||
klass->oops_do(&MarkSweep::adjust_pointer_closure);
|
||||
}
|
||||
|
||||
void MarkSweep::follow_klass(Klass* klass) {
|
||||
ClassLoaderData* cld = klass->class_loader_data();
|
||||
assert(cld->has_defined(klass), "inconsistency!");
|
||||
|
||||
// The actual processing of the klass is done when we
|
||||
// traverse the list of Klasses in the class loader data.
|
||||
MarkSweep::follow_class_loader(cld);
|
||||
}
|
||||
|
||||
void MarkSweep::adjust_klass(Klass* klass) {
|
||||
ClassLoaderData* cld = klass->class_loader_data();
|
||||
assert(cld->has_defined(klass), "inconsistency!");
|
||||
|
||||
// The actual processing of the klass is done when we
|
||||
// traverse the list of Klasses in the class loader data.
|
||||
MarkSweep::adjust_class_loader(cld);
|
||||
}
|
||||
|
||||
void MarkSweep::follow_class_loader(ClassLoaderData* cld) {
|
||||
cld->oops_do(&MarkSweep::mark_and_push_closure, &MarkSweep::follow_klass_closure, true);
|
||||
}
|
||||
|
||||
void MarkSweep::adjust_class_loader(ClassLoaderData* cld) {
|
||||
cld->oops_do(&MarkSweep::adjust_root_pointer_closure, &MarkSweep::adjust_klass_closure, true);
|
||||
}
|
||||
|
||||
|
||||
void MarkSweep::follow_stack() {
|
||||
do {
|
||||
while (!_marking_stack.is_empty()) {
|
||||
|
@ -124,7 +119,7 @@ void MarkSweep::follow_stack() {
|
|||
// Process ObjArrays one at a time to avoid marking stack bloat.
|
||||
if (!_objarray_stack.is_empty()) {
|
||||
ObjArrayTask task = _objarray_stack.pop();
|
||||
objArrayKlass* const k = (objArrayKlass*)task.obj()->blueprint();
|
||||
objArrayKlass* const k = (objArrayKlass*)task.obj()->klass();
|
||||
k->oop_follow_contents(task.obj(), task.index());
|
||||
}
|
||||
} while (!_marking_stack.is_empty() || !_objarray_stack.is_empty());
|
||||
|
@ -237,7 +232,7 @@ void MarkSweep::track_interior_pointers(oop obj) {
|
|||
_pointer_tracking = true;
|
||||
|
||||
AdjusterTracker checker;
|
||||
obj->oop_iterate(&checker);
|
||||
obj->oop_iterate_no_header(&checker);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -248,10 +243,10 @@ void MarkSweep::check_interior_pointers() {
|
|||
}
|
||||
}
|
||||
|
||||
void MarkSweep::reset_live_oop_tracking(bool at_perm) {
|
||||
void MarkSweep::reset_live_oop_tracking() {
|
||||
if (ValidateMarkSweep) {
|
||||
guarantee((size_t)_live_oops->length() == _live_oops_index, "should be at end of live oops");
|
||||
_live_oops_index = at_perm ? _live_oops_index_at_perm : 0;
|
||||
_live_oops_index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2012, 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
|
||||
|
@ -76,8 +76,17 @@ class MarkSweep : AllStatic {
|
|||
public:
|
||||
virtual void do_oop(oop* p);
|
||||
virtual void do_oop(narrowOop* p);
|
||||
virtual const bool should_remember_mdo() const { return true; }
|
||||
virtual void remember_mdo(DataLayout* p) { MarkSweep::revisit_mdo(p); }
|
||||
};
|
||||
|
||||
// The one and only place to start following the classes.
|
||||
// Should only be applied to the ClassLoaderData klasses list.
|
||||
class FollowKlassClosure : public KlassClosure {
|
||||
public:
|
||||
void do_klass(Klass* klass);
|
||||
};
|
||||
class AdjustKlassClosure : public KlassClosure {
|
||||
public:
|
||||
void do_klass(Klass* klass);
|
||||
};
|
||||
|
||||
class FollowStackClosure: public VoidClosure {
|
||||
|
@ -121,13 +130,12 @@ class MarkSweep : AllStatic {
|
|||
// Vars
|
||||
//
|
||||
protected:
|
||||
// Total invocations of a MarkSweep collection
|
||||
static unsigned int _total_invocations;
|
||||
|
||||
// Traversal stacks used during phase1
|
||||
static Stack<oop, mtGC> _marking_stack;
|
||||
static Stack<ObjArrayTask, mtGC> _objarray_stack;
|
||||
// Stack for live klasses to revisit at end of marking phase
|
||||
static Stack<Klass*, mtGC> _revisit_klass_stack;
|
||||
// Set (stack) of MDO's to revisit at end of marking phase
|
||||
static Stack<DataLayout*, mtGC> _revisit_mdo_stack;
|
||||
|
||||
// Space for storing/restoring mark word
|
||||
static Stack<markOop, mtGC> _preserved_mark_stack;
|
||||
|
@ -167,27 +175,25 @@ class MarkSweep : AllStatic {
|
|||
#endif
|
||||
|
||||
// Non public closures
|
||||
static IsAliveClosure is_alive;
|
||||
static KeepAliveClosure keep_alive;
|
||||
|
||||
// Class unloading. Update subklass/sibling/implementor links at end of marking phase.
|
||||
static void follow_weak_klass_links();
|
||||
|
||||
// Class unloading. Clear weak refs in MDO's (ProfileData)
|
||||
// at the end of the marking phase.
|
||||
static void follow_mdo_weak_refs();
|
||||
|
||||
// Debugging
|
||||
static void trace(const char* msg) PRODUCT_RETURN;
|
||||
|
||||
public:
|
||||
// Public closures
|
||||
static IsAliveClosure is_alive;
|
||||
static FollowRootClosure follow_root_closure;
|
||||
static CodeBlobToOopClosure follow_code_root_closure; // => follow_root_closure
|
||||
static MarkAndPushClosure mark_and_push_closure;
|
||||
static FollowKlassClosure follow_klass_closure;
|
||||
static FollowStackClosure follow_stack_closure;
|
||||
static AdjustPointerClosure adjust_root_pointer_closure;
|
||||
static AdjustPointerClosure adjust_pointer_closure;
|
||||
static AdjustKlassClosure adjust_klass_closure;
|
||||
|
||||
// Accessors
|
||||
static unsigned int total_invocations() { return _total_invocations; }
|
||||
|
||||
// Reference Processing
|
||||
static ReferenceProcessor* const ref_processor() { return _ref_processor; }
|
||||
|
@ -196,12 +202,20 @@ class MarkSweep : AllStatic {
|
|||
static void mark_object(oop obj);
|
||||
// Mark pointer and follow contents. Empty marking stack afterwards.
|
||||
template <class T> static inline void follow_root(T* p);
|
||||
|
||||
// Check mark and maybe push on marking stack
|
||||
template <class T> static inline void mark_and_push(T* p);
|
||||
template <class T> static void mark_and_push(T* p);
|
||||
|
||||
static inline void push_objarray(oop obj, size_t index);
|
||||
|
||||
static void follow_stack(); // Empty marking stack.
|
||||
|
||||
static void follow_klass(Klass* klass);
|
||||
static void adjust_klass(Klass* klass);
|
||||
|
||||
static void follow_class_loader(ClassLoaderData* cld);
|
||||
static void adjust_class_loader(ClassLoaderData* cld);
|
||||
|
||||
static void preserve_mark(oop p, markOop mark);
|
||||
// Save the mark word so it can be restored later
|
||||
static void adjust_marks(); // Adjust the pointers in the preserved marks table
|
||||
|
@ -219,7 +233,7 @@ class MarkSweep : AllStatic {
|
|||
static void track_interior_pointers(oop obj);
|
||||
static void check_interior_pointers();
|
||||
|
||||
static void reset_live_oop_tracking(bool at_perm);
|
||||
static void reset_live_oop_tracking();
|
||||
static void register_live_oop(oop p, size_t size);
|
||||
static void validate_live_oop(oop p, size_t size);
|
||||
static void live_oop_moved_to(HeapWord* q, size_t size, HeapWord* compaction_top);
|
||||
|
@ -231,12 +245,6 @@ class MarkSweep : AllStatic {
|
|||
// tracking down heap stomps.
|
||||
static void print_new_location_of_heap_address(HeapWord* q);
|
||||
#endif
|
||||
|
||||
// Call backs for class unloading
|
||||
// Update subklass/sibling/implementor links at end of marking.
|
||||
static void revisit_weak_klass_link(Klass* k);
|
||||
// For weak refs clearing in MDO's
|
||||
static void revisit_mdo(DataLayout* p);
|
||||
};
|
||||
|
||||
class PreservedMark VALUE_OBJ_CLASS_SPEC {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2012, 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
|
||||
|
@ -88,9 +88,8 @@ template <class T> inline void MarkSweep::adjust_pointer(T* p, bool isroot) {
|
|||
oop new_obj = oop(obj->mark()->decode_pointer());
|
||||
assert(new_obj != NULL || // is forwarding ptr?
|
||||
obj->mark() == markOopDesc::prototype() || // not gc marked?
|
||||
(UseBiasedLocking && obj->mark()->has_bias_pattern()) ||
|
||||
(UseBiasedLocking && obj->mark()->has_bias_pattern()),
|
||||
// not gc marked?
|
||||
obj->is_shared(), // never forwarded?
|
||||
"should be forwarded");
|
||||
if (new_obj != NULL) {
|
||||
assert(Universe::heap()->is_in_reserved(new_obj),
|
||||
|
|
|
@ -216,7 +216,7 @@ bool MutableSpace::cas_deallocate(HeapWord *obj, size_t size) {
|
|||
return (HeapWord*)Atomic::cmpxchg_ptr(obj, top_addr(), expected_top) == expected_top;
|
||||
}
|
||||
|
||||
void MutableSpace::oop_iterate(OopClosure* cl) {
|
||||
void MutableSpace::oop_iterate(ExtendedOopClosure* cl) {
|
||||
HeapWord* obj_addr = bottom();
|
||||
HeapWord* t = top();
|
||||
// Could call objects iterate, but this is easier.
|
||||
|
@ -225,6 +225,15 @@ void MutableSpace::oop_iterate(OopClosure* cl) {
|
|||
}
|
||||
}
|
||||
|
||||
void MutableSpace::oop_iterate_no_header(OopClosure* cl) {
|
||||
HeapWord* obj_addr = bottom();
|
||||
HeapWord* t = top();
|
||||
// Could call objects iterate, but this is easier.
|
||||
while (obj_addr < t) {
|
||||
obj_addr += oop(obj_addr)->oop_iterate_no_header(cl);
|
||||
}
|
||||
}
|
||||
|
||||
void MutableSpace::object_iterate(ObjectClosure* cl) {
|
||||
HeapWord* p = bottom();
|
||||
while (p < top()) {
|
||||
|
|
|
@ -133,7 +133,8 @@ class MutableSpace: public ImmutableSpace {
|
|||
bool cas_deallocate(HeapWord *obj, size_t size);
|
||||
|
||||
// Iteration.
|
||||
void oop_iterate(OopClosure* cl);
|
||||
void oop_iterate(ExtendedOopClosure* cl);
|
||||
void oop_iterate_no_header(OopClosure* cl);
|
||||
void object_iterate(ObjectClosure* cl);
|
||||
|
||||
// Debugging
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2012, 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
|
||||
|
@ -192,31 +192,69 @@ void VM_GenCollectFull::doit() {
|
|||
gch->do_full_collection(gch->must_clear_all_soft_refs(), _max_level);
|
||||
}
|
||||
|
||||
void VM_GenCollectForPermanentAllocation::doit() {
|
||||
void VM_CollectForMetadataAllocation::doit() {
|
||||
SvcGCMarker sgcm(SvcGCMarker::FULL);
|
||||
|
||||
SharedHeap* heap = (SharedHeap*)Universe::heap();
|
||||
CollectedHeap* heap = Universe::heap();
|
||||
GCCauseSetter gccs(heap, _gc_cause);
|
||||
switch (heap->kind()) {
|
||||
case (CollectedHeap::GenCollectedHeap): {
|
||||
GenCollectedHeap* gch = (GenCollectedHeap*)heap;
|
||||
gch->do_full_collection(gch->must_clear_all_soft_refs(),
|
||||
gch->n_gens() - 1);
|
||||
break;
|
||||
|
||||
bool do_cms_concurrent = false;
|
||||
|
||||
// Check again if the space is available. Another thread
|
||||
// may have similarly failed a metadata allocation and induced
|
||||
// a GC that freed space for the allocation.
|
||||
if (!MetadataAllocationFailALot) {
|
||||
_result = _loader_data->metaspace_non_null()->allocate(_size, _mdtype);
|
||||
}
|
||||
#ifndef SERIALGC
|
||||
case (CollectedHeap::G1CollectedHeap): {
|
||||
G1CollectedHeap* g1h = (G1CollectedHeap*)heap;
|
||||
g1h->do_full_collection(_gc_cause == GCCause::_last_ditch_collection);
|
||||
break;
|
||||
|
||||
if (_result == NULL) {
|
||||
if (!UseConcMarkSweepGC) {
|
||||
// Don't clear the soft refs the first time.
|
||||
heap->collect_as_vm_thread(GCCause::_metadata_GC_threshold);
|
||||
_result = _loader_data->metaspace_non_null()->allocate(_size, _mdtype);
|
||||
// Don't do this for now
|
||||
// This seems too costly to do a second full GC
|
||||
// Let the metaspace grow instead
|
||||
// if (_result == NULL) {
|
||||
// // If allocation fails again, clear soft refs
|
||||
// heap->collect_as_vm_thread(GCCause::_last_ditch_collection);
|
||||
// _result = _loader_data->metaspace_non_null()->allocate(_size, _mdtype);
|
||||
// }
|
||||
} else {
|
||||
MetaspaceGC::set_should_concurrent_collect(true);
|
||||
do_cms_concurrent = true;
|
||||
}
|
||||
#endif // SERIALGC
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
if (_result == NULL) {
|
||||
// If still failing, allow the Metaspace to expand.
|
||||
// See delta_capacity_until_GC() for explanation of the
|
||||
// amount of the expansion.
|
||||
// This should work unless there really is no more space
|
||||
// or a MaxMetaspaceSize has been specified on the command line.
|
||||
MetaspaceGC::set_expand_after_GC(true);
|
||||
size_t before_inc = MetaspaceGC::capacity_until_GC();
|
||||
size_t delta_words = MetaspaceGC::delta_capacity_until_GC(_size);
|
||||
MetaspaceGC::inc_capacity_until_GC(delta_words);
|
||||
if (PrintGCDetails && Verbose) {
|
||||
gclog_or_tty->print_cr("Increase capacity to GC from " SIZE_FORMAT
|
||||
" to " SIZE_FORMAT, before_inc, MetaspaceGC::capacity_until_GC());
|
||||
}
|
||||
_res = heap->perm_gen()->allocate(_size, false);
|
||||
assert(heap->is_in_reserved_or_null(_res), "result not in heap");
|
||||
if (_res == NULL && GC_locker::is_active_and_needs_gc()) {
|
||||
_result = _loader_data->metaspace_non_null()->allocate(_size, _mdtype);
|
||||
if (do_cms_concurrent && _result == NULL) {
|
||||
// Rather than fail with a metaspace out-of-memory, do a full
|
||||
// GC for CMS.
|
||||
heap->collect_as_vm_thread(GCCause::_metadata_GC_threshold);
|
||||
_result = _loader_data->metaspace_non_null()->allocate(_size, _mdtype);
|
||||
}
|
||||
if (_result == NULL) {
|
||||
if (PrintGCDetails) {
|
||||
gclog_or_tty->print_cr("\nAfter Metaspace GC failed to allocate size "
|
||||
SIZE_FORMAT, _size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_result == NULL && GC_locker::is_active_and_needs_gc()) {
|
||||
set_gc_locked();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2012, 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
|
||||
|
@ -42,7 +42,6 @@
|
|||
// VM_GenCollectFull
|
||||
// VM_GenCollectFullConcurrent
|
||||
// VM_ParallelGCFailedAllocation
|
||||
// VM_ParallelGCFailedPermanentAllocation
|
||||
// VM_ParallelGCSystemGC
|
||||
// VM_GC_Operation
|
||||
// - implements methods common to all classes in the hierarchy:
|
||||
|
@ -53,9 +52,7 @@
|
|||
// is specified; and also the attach "inspectheap" operation
|
||||
//
|
||||
// VM_GenCollectForAllocation
|
||||
// VM_GenCollectForPermanentAllocation
|
||||
// VM_ParallelGCFailedAllocation
|
||||
// VM_ParallelGCFailedPermanentAllocation
|
||||
// - this operation is invoked when allocation is failed;
|
||||
// operation performs garbage collection and tries to
|
||||
// allocate afterwards;
|
||||
|
@ -191,24 +188,27 @@ class VM_GenCollectFull: public VM_GC_Operation {
|
|||
virtual void doit();
|
||||
};
|
||||
|
||||
class VM_GenCollectForPermanentAllocation: public VM_GC_Operation {
|
||||
class VM_CollectForMetadataAllocation: public VM_GC_Operation {
|
||||
private:
|
||||
HeapWord* _res;
|
||||
MetaWord* _result;
|
||||
size_t _size; // size of object to be allocated
|
||||
Metaspace::MetadataType _mdtype;
|
||||
ClassLoaderData* _loader_data;
|
||||
public:
|
||||
VM_GenCollectForPermanentAllocation(size_t size,
|
||||
VM_CollectForMetadataAllocation(ClassLoaderData* loader_data,
|
||||
size_t size, Metaspace::MetadataType mdtype,
|
||||
unsigned int gc_count_before,
|
||||
unsigned int full_gc_count_before,
|
||||
GCCause::Cause gc_cause)
|
||||
: VM_GC_Operation(gc_count_before, gc_cause, full_gc_count_before, true),
|
||||
_size(size) {
|
||||
_res = NULL;
|
||||
_gc_cause = gc_cause;
|
||||
_loader_data(loader_data), _size(size), _mdtype(mdtype), _result(NULL) {
|
||||
}
|
||||
~VM_GenCollectForPermanentAllocation() {}
|
||||
virtual VMOp_Type type() const { return VMOp_GenCollectForPermanentAllocation; }
|
||||
~VM_CollectForMetadataAllocation() {
|
||||
MetaspaceGC::set_expand_after_GC(false);
|
||||
}
|
||||
virtual VMOp_Type type() const { return VMOp_CollectForMetadataAllocation; }
|
||||
virtual void doit();
|
||||
HeapWord* result() const { return _res; }
|
||||
MetaWord* result() const { return _result; }
|
||||
};
|
||||
|
||||
class SvcGCMarker : public StackObj {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue