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
--- a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp Fri Mar 28 14:15:03 2014 +0100
+++ b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp Thu Feb 13 10:05:03 2014 +0100
@@ -89,6 +89,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.
--- a/hotspot/src/share/vm/memory/gcLocker.cpp Fri Mar 28 14:15:03 2014 +0100
+++ b/hotspot/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();
}
--- a/hotspot/src/share/vm/memory/gcLocker.hpp Fri Mar 28 14:15:03 2014 +0100
+++ b/hotspot/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
--- a/hotspot/src/share/vm/memory/gcLocker.inline.hpp Fri Mar 28 14:15:03 2014 +0100
+++ b/hotspot/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()) {
--- a/hotspot/src/share/vm/memory/metaspaceShared.cpp Fri Mar 28 14:15:03 2014 +0100
+++ b/hotspot/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)
--- a/hotspot/src/share/vm/memory/universe.cpp Fri Mar 28 14:15:03 2014 +0100
+++ b/hotspot/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;
}
--- a/hotspot/src/share/vm/runtime/thread.cpp Fri Mar 28 14:15:03 2014 +0100
+++ b/hotspot/src/share/vm/runtime/thread.cpp Thu Feb 13 10:05:03 2014 +0100
@@ -211,7 +211,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;
--- a/hotspot/src/share/vm/runtime/thread.hpp Fri Mar 28 14:15:03 2014 +0100
+++ b/hotspot/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
--- a/hotspot/src/share/vm/runtime/unhandledOops.cpp Fri Mar 28 14:15:03 2014 +0100
+++ b/hotspot/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