3333#include " gc/shared/spaceDecorator.hpp"
3434#include " logging/log.hpp"
3535#include " oops/oop.inline.hpp"
36+ #include " runtime/init.hpp"
3637#include " runtime/java.hpp"
3738#include " utilities/align.hpp"
3839
@@ -118,13 +119,22 @@ void PSOldGen::initialize_performance_counters() {
118119}
119120
120121HeapWord* PSOldGen::expand_and_allocate (size_t word_size) {
122+ #ifdef ASSERT
121123 assert (Heap_lock->is_locked (), " precondition" );
124+ if (is_init_completed ()) {
125+ assert (SafepointSynchronize::is_at_safepoint (), " precondition" );
126+ assert (Thread::current ()->is_VM_thread (), " precondition" );
127+ } else {
128+ assert (Thread::current ()->is_Java_thread (), " precondition" );
129+ assert (Heap_lock->owned_by_self (), " precondition" );
130+ }
131+ #endif
122132
123- if (object_space ()->needs_expand (word_size) ) {
133+ if (pointer_delta ( object_space ()->end (), object_space ()-> top ()) < word_size ) {
124134 expand (word_size*HeapWordSize);
125135 }
126136
127- // Reuse the CAS API even though this is VM thread in safepoint . This method
137+ // Reuse the CAS API even though this is in a critical section . This method
128138 // is not invoked repeatedly, so the CAS overhead should be negligible.
129139 return cas_allocate_noexpand (word_size);
130140}
@@ -168,7 +178,7 @@ bool PSOldGen::expand_for_allocate(size_t word_size) {
168178 // true until we expand, since we have the lock. Other threads may take
169179 // the space we need before we can allocate it, regardless of whether we
170180 // expand. That's okay, we'll just try expanding again.
171- if (object_space ()->needs_expand (word_size) ) {
181+ if (pointer_delta ( object_space ()->end (), object_space ()-> top ()) < word_size ) {
172182 result = expand (word_size*HeapWordSize);
173183 }
174184 }
@@ -192,10 +202,21 @@ void PSOldGen::try_expand_till_size(size_t target_capacity_bytes) {
192202
193203bool PSOldGen::expand (size_t bytes) {
194204#ifdef ASSERT
195- if (!Thread::current ()->is_VM_thread ()) {
196- assert_lock_strong (PSOldGenExpand_lock);
205+ // During startup (is_init_completed() == false), expansion can occur for
206+ // 1. java-threads invoking heap-allocation (using Heap_lock)
207+ // 2. CDS construction by a single thread (using PSOldGenExpand_lock but not needed)
208+ //
209+ // After startup (is_init_completed() == true), expansion can occur for
210+ // 1. GC workers for promoting to old-gen (using PSOldGenExpand_lock)
211+ // 2. VM thread to satisfy the pending allocation
212+ // Both cases are inside safepoint pause, but are never overlapping.
213+ //
214+ if (is_init_completed ()) {
215+ assert (SafepointSynchronize::is_at_safepoint (), " precondition" );
216+ assert (Thread::current ()->is_VM_thread () || PSOldGenExpand_lock->owned_by_self (), " precondition" );
217+ } else {
218+ assert (Heap_lock->owned_by_self () || PSOldGenExpand_lock->owned_by_self (), " precondition" );
197219 }
198- assert_locked_or_safepoint (Heap_lock);
199220 assert (bytes > 0 , " precondition" );
200221#endif
201222 const size_t remaining_bytes = virtual_space ()->uncommitted_size ();
0 commit comments