# HG changeset patch # User sjohanss # Date 1392282303 -3600 # Node ID 9c3dc501b5eb715288139495ce843321f5524ad7 # Parent cb1b723cbca8f953bfdd2c78387191d11d0cbaed 8028498: runtime/SharedArchiveFile/CdsDifferentObjectAlignment.java asserts in RT_Baseline Summary: Preventing GCs to occur before VM is completely initialized. This was previously partly done by one part of the GC locker which not was removed. Reviewed-by: coleenp, pliden diff -r cb1b723cbca8 -r 9c3dc501b5eb src/share/vm/gc_implementation/shared/vmGCOperations.cpp --- a/src/share/vm/gc_implementation/shared/vmGCOperations.cpp Mon Apr 14 20:56:48 2014 -0400 +++ b/src/share/vm/gc_implementation/shared/vmGCOperations.cpp Thu Feb 13 10:05:03 2014 +0100 @@ -103,6 +103,15 @@ assert(((_gc_cause != GCCause::_no_gc) && (_gc_cause != GCCause::_no_cause_specified)), "Illegal GCCause"); + // To be able to handle a GC the VM initialization needs to be completed. + if (!is_init_completed()) { + vm_exit_during_initialization( + err_msg("GC triggered before VM initialization completed. Try increasing " + "NewSize, current value " UINTX_FORMAT "%s.", + byte_size_in_proper_unit(NewSize), + proper_unit_for_byte_size(NewSize))); + } + acquire_pending_list_lock(); // If the GC count has changed someone beat us to the collection // Get the Heap_lock after the pending_list_lock. diff -r cb1b723cbca8 -r 9c3dc501b5eb src/share/vm/memory/gcLocker.cpp --- a/src/share/vm/memory/gcLocker.cpp Mon Apr 14 20:56:48 2014 -0400 +++ b/src/share/vm/memory/gcLocker.cpp Thu Feb 13 10:05:03 2014 +0100 @@ -28,7 +28,6 @@ #include "memory/sharedHeap.hpp" volatile jint GC_locker::_jni_lock_count = 0; -volatile jint GC_locker::_lock_count = 0; volatile bool GC_locker::_needs_gc = false; volatile bool GC_locker::_doing_gc = false; @@ -102,7 +101,7 @@ // We check that at least one thread is in a critical region before // blocking because blocked threads are woken up by a thread exiting // a JNI critical region. - while ((needs_gc() && is_jni_active()) || _doing_gc) { + while (is_active_and_needs_gc() || _doing_gc) { JNICritical_lock->wait(); } thread->enter_critical(); @@ -116,27 +115,20 @@ _jni_lock_count--; decrement_debug_jni_lock_count(); thread->exit_critical(); - if (needs_gc() && !is_jni_active()) { + if (needs_gc() && !is_active_internal()) { // We're the last thread out. Cause a GC to occur. - // GC will also check is_active, so this check is not - // strictly needed. It's added here to make it clear that - // the GC will NOT be performed if any other caller - // of GC_locker::lock() still needs GC locked. - if (!is_active_internal()) { - _doing_gc = true; - { - // Must give up the lock while at a safepoint - MutexUnlocker munlock(JNICritical_lock); - if (PrintJNIGCStalls && PrintGCDetails) { - ResourceMark rm; // JavaThread::name() allocates to convert to UTF8 - gclog_or_tty->print_cr("%.3f: Thread \"%s\" is performing GC after exiting critical section, %d locked", - gclog_or_tty->time_stamp().seconds(), Thread::current()->name(), _jni_lock_count); - } - Universe::heap()->collect(GCCause::_gc_locker); + _doing_gc = true; + { + // Must give up the lock while at a safepoint + MutexUnlocker munlock(JNICritical_lock); + if (PrintJNIGCStalls && PrintGCDetails) { + ResourceMark rm; // JavaThread::name() allocates to convert to UTF8 + gclog_or_tty->print_cr("%.3f: Thread \"%s\" is performing GC after exiting critical section, %d locked", + gclog_or_tty->time_stamp().seconds(), Thread::current()->name(), _jni_lock_count); } - _doing_gc = false; + Universe::heap()->collect(GCCause::_gc_locker); } - + _doing_gc = false; _needs_gc = false; JNICritical_lock->notify_all(); } diff -r cb1b723cbca8 -r 9c3dc501b5eb src/share/vm/memory/gcLocker.hpp --- a/src/share/vm/memory/gcLocker.hpp Mon Apr 14 20:56:48 2014 -0400 +++ b/src/share/vm/memory/gcLocker.hpp Thu Feb 13 10:05:03 2014 +0100 @@ -54,8 +54,6 @@ // safepointing and decremented during the slow path of GC_locker // unlocking. static volatile jint _jni_lock_count; // number of jni active instances. - - static volatile jint _lock_count; // number of other active instances static volatile bool _needs_gc; // heap is filling, we need a GC // note: bool is typedef'd as jint static volatile bool _doing_gc; // unlock_critical() is doing a GC @@ -66,12 +64,6 @@ static volatile jint _debug_jni_lock_count; #endif - // Accessors - static bool is_jni_active() { - assert(_needs_gc, "only valid when _needs_gc is set"); - return _jni_lock_count > 0; - } - // At a safepoint, visit all threads and count the number of active // critical sections. This is used to ensure that all active // critical sections are exited before a new one is started. @@ -82,7 +74,7 @@ static bool is_active_internal() { verify_critical_count(); - return _lock_count > 0 || _jni_lock_count > 0; + return _jni_lock_count > 0; } public: @@ -132,10 +124,6 @@ // not a stable predicate. static void stall_until_clear(); - // Non-structured GC locking: currently needed for JNI. Use with care! - static void lock(); - static void unlock(); - // The following two methods are used for JNI critical regions. // If we find that we failed to perform a GC because the GC_locker // was active, arrange for one as soon as possible by allowing diff -r cb1b723cbca8 -r 9c3dc501b5eb src/share/vm/memory/gcLocker.inline.hpp --- a/src/share/vm/memory/gcLocker.inline.hpp Mon Apr 14 20:56:48 2014 -0400 +++ b/src/share/vm/memory/gcLocker.inline.hpp Thu Feb 13 10:05:03 2014 +0100 @@ -27,22 +27,6 @@ #include "memory/gcLocker.hpp" -inline void GC_locker::lock() { - // cast away volatile - Atomic::inc(&_lock_count); - CHECK_UNHANDLED_OOPS_ONLY( - if (CheckUnhandledOops) { Thread::current()->_gc_locked_out_count++; }) - assert(Universe::heap() == NULL || - !Universe::heap()->is_gc_active(), "locking failed"); -} - -inline void GC_locker::unlock() { - // cast away volatile - Atomic::dec(&_lock_count); - CHECK_UNHANDLED_OOPS_ONLY( - if (CheckUnhandledOops) { Thread::current()->_gc_locked_out_count--; }) -} - inline void GC_locker::lock_critical(JavaThread* thread) { if (!thread->in_critical()) { if (needs_gc()) { diff -r cb1b723cbca8 -r 9c3dc501b5eb src/share/vm/memory/metaspaceShared.cpp --- a/src/share/vm/memory/metaspaceShared.cpp Mon Apr 14 20:56:48 2014 -0400 +++ b/src/share/vm/memory/metaspaceShared.cpp Thu Feb 13 10:05:03 2014 +0100 @@ -645,9 +645,6 @@ TraceTime timer("Dump Shared Spaces", TraceStartupTime); ResourceMark rm; - // Lock out GC - is it necessary? I don't think we care. - No_GC_Verifier no_gc; - // Preload classes to be shared. // Should use some os:: method rather than fopen() here. aB. // Construct the path to the class list (in jre/lib) diff -r cb1b723cbca8 -r 9c3dc501b5eb src/share/vm/memory/universe.cpp --- a/src/share/vm/memory/universe.cpp Mon Apr 14 20:56:48 2014 -0400 +++ b/src/share/vm/memory/universe.cpp Thu Feb 13 10:05:03 2014 +0100 @@ -632,7 +632,6 @@ guarantee(sizeof(oop) % sizeof(HeapWord) == 0, "oop size is not not a multiple of HeapWord size"); TraceTime timer("Genesis", TraceStartupTime); - GC_locker::lock(); // do not allow gc during bootstrapping JavaClasses::compute_hard_coded_offsets(); jint status = Universe::initialize_heap(); @@ -1164,8 +1163,6 @@ MemoryService::add_metaspace_memory_pools(); - GC_locker::unlock(); // allow gc after bootstrapping - MemoryService::set_universe_heap(Universe::_collectedHeap); return true; } diff -r cb1b723cbca8 -r 9c3dc501b5eb src/share/vm/runtime/thread.cpp --- a/src/share/vm/runtime/thread.cpp Mon Apr 14 20:56:48 2014 -0400 +++ b/src/share/vm/runtime/thread.cpp Thu Feb 13 10:05:03 2014 +0100 @@ -239,7 +239,6 @@ debug_only(_allow_allocation_count = 0;) NOT_PRODUCT(_allow_safepoint_count = 0;) NOT_PRODUCT(_skip_gcalot = false;) - CHECK_UNHANDLED_OOPS_ONLY(_gc_locked_out_count = 0;) _jvmti_env_iteration_count = 0; set_allocated_bytes(0); _vm_operation_started_count = 0; diff -r cb1b723cbca8 -r 9c3dc501b5eb src/share/vm/runtime/thread.hpp --- a/src/share/vm/runtime/thread.hpp Mon Apr 14 20:56:48 2014 -0400 +++ b/src/share/vm/runtime/thread.hpp Thu Feb 13 10:05:03 2014 +0100 @@ -249,9 +249,6 @@ // Used by SkipGCALot class. NOT_PRODUCT(bool _skip_gcalot;) // Should we elide gc-a-lot? - // Record when GC is locked out via the GC_locker mechanism - CHECK_UNHANDLED_OOPS_ONLY(int _gc_locked_out_count;) - friend class No_Alloc_Verifier; friend class No_Safepoint_Verifier; friend class Pause_No_Safepoint_Verifier; @@ -397,7 +394,6 @@ void clear_unhandled_oops() { if (CheckUnhandledOops) unhandled_oops()->clear_unhandled_oops(); } - bool is_gc_locked_out() { return _gc_locked_out_count > 0; } #endif // CHECK_UNHANDLED_OOPS #ifndef PRODUCT diff -r cb1b723cbca8 -r 9c3dc501b5eb src/share/vm/runtime/unhandledOops.cpp --- a/src/share/vm/runtime/unhandledOops.cpp Mon Apr 14 20:56:48 2014 -0400 +++ b/src/share/vm/runtime/unhandledOops.cpp Thu Feb 13 10:05:03 2014 +0100 @@ -113,9 +113,7 @@ void UnhandledOops::clear_unhandled_oops() { assert (CheckUnhandledOops, "should only be called with checking option"); - if (_thread->is_gc_locked_out()) { - return; - } + for (int k = 0; k < _oop_list->length(); k++) { UnhandledOopEntry entry = _oop_list->at(k); // If an entry is on the unhandled oop list but isn't on the stack