4848#include " runtime/mutexLocker.hpp"
4949#include " runtime/safepoint.hpp"
5050
51- const unsigned int initial_size = 431 ;
52-
53- static JfrCHeapTraceIdSet* c_heap_allocate_set (int size = initial_size) {
54- return new JfrCHeapTraceIdSet (size);
55- }
56-
57- static JfrCHeapTraceIdSet* unloaded_thread_id_set = nullptr ;
58-
5951class ThreadIdExclusiveAccess : public StackObj {
6052 private:
6153 static Semaphore _mutex_semaphore;
@@ -66,19 +58,13 @@ class ThreadIdExclusiveAccess : public StackObj {
6658
6759Semaphore ThreadIdExclusiveAccess::_mutex_semaphore (1 );
6860
69- static bool has_thread_exited (traceid tid) {
70- assert (tid != 0 , " invariant" );
71- if (unloaded_thread_id_set == nullptr ) {
72- return false ;
73- }
74- ThreadIdExclusiveAccess lock;
75- return unloaded_thread_id_set->contains (tid);
76- }
61+ static const unsigned initial_set_size = 512 ;
62+ static JfrCHeapTraceIdSet* unloaded_thread_id_set = nullptr ;
7763
7864static void add_to_unloaded_thread_set (traceid tid) {
7965 ThreadIdExclusiveAccess lock;
8066 if (unloaded_thread_id_set == nullptr ) {
81- unloaded_thread_id_set = c_heap_allocate_set ( );
67+ unloaded_thread_id_set = new (mtTracing) JfrCHeapTraceIdSet (initial_set_size );
8268 }
8369 unloaded_thread_id_set->add (tid);
8470}
@@ -193,12 +179,6 @@ inline void BlobCache::on_unlink(BlobEntry* entry) const {
193179 assert (entry != nullptr , " invariant" );
194180}
195181
196- static JfrResourceAreaTraceIdSet* id_set = nullptr ;
197-
198- static void prepare_for_resolution () {
199- id_set = new JfrResourceAreaTraceIdSet (initial_size);
200- }
201-
202182static bool stack_trace_precondition (const ObjectSample* sample) {
203183 assert (sample != nullptr , " invariant" );
204184 return sample->has_stack_trace_id () && !sample->is_dead ();
@@ -213,15 +193,18 @@ static void add_to_leakp_set(const ObjectSample* sample) {
213193 JfrTraceId::load_leakp (object->klass ());
214194}
215195
196+ static JfrResourceAreaTraceIdSet* resolution_set = nullptr ;
197+
216198class StackTraceBlobInstaller {
217199 private:
218200 BlobCache _cache;
219201 void install (ObjectSample* sample);
220202 const JfrStackTrace* resolve (const ObjectSample* sample) const ;
221203 public:
222204 StackTraceBlobInstaller () : _cache(JfrOptionSet::old_object_queue_size()) {
223- prepare_for_resolution ( );
205+ resolution_set = new JfrResourceAreaTraceIdSet (initial_set_size );
224206 }
207+
225208 void sample_do (ObjectSample* sample) {
226209 if (stack_trace_precondition (sample)) {
227210 add_to_leakp_set (sample);
@@ -314,8 +297,8 @@ static bool is_klass_unloaded(traceid klass_id) {
314297
315298static bool is_processed (traceid method_id) {
316299 assert (method_id != 0 , " invariant" );
317- assert (id_set != nullptr , " invariant" );
318- return !id_set ->add (method_id);
300+ assert (resolution_set != nullptr , " invariant" );
301+ return !resolution_set ->add (method_id);
319302}
320303
321304void ObjectSampleCheckpoint::add_to_leakp_set (const InstanceKlass* ik, traceid method_id) {
@@ -356,7 +339,7 @@ static void write_type_set_blob(const ObjectSample* sample, JfrCheckpointWriter&
356339
357340static void write_thread_blob (const ObjectSample* sample, JfrCheckpointWriter& writer) {
358341 assert (sample->has_thread (), " invariant" );
359- if (sample->is_virtual_thread () || has_thread_exited ( sample->thread_id () )) {
342+ if (sample->is_virtual_thread () || sample->thread_exited ( )) {
360343 write_blob (sample->thread (), writer);
361344 }
362345}
@@ -372,13 +355,13 @@ static inline bool should_write(const JfrStackTrace* stacktrace) {
372355class LeakProfilerStackTraceWriter {
373356 private:
374357 JfrCheckpointWriter& _writer;
375- int _count;
358+ unsigned _count;
376359 public:
377360 LeakProfilerStackTraceWriter (JfrCheckpointWriter& writer) : _writer(writer), _count(0 ) {
378361 assert (_stacktrace_id_set != nullptr , " invariant" );
379362 }
380363
381- int count () const { return _count; }
364+ unsigned count () const { return _count; }
382365
383366 void operator ()(const JfrStackTrace* stacktrace) {
384367 if (should_write (stacktrace)) {
@@ -394,12 +377,10 @@ void ObjectSampleCheckpoint::write_stacktraces(Thread* thread) {
394377
395378 JfrCheckpointWriter writer (thread);
396379 writer.write_type (TYPE_STACKTRACE);
397- const int64_t count_offset = writer.reserve (sizeof (u4)); // Don't know how many yet
398-
380+ writer.write_count (_stacktrace_id_set->size ());
399381 LeakProfilerStackTraceWriter lpstw (writer);
400382 JfrStackTraceRepository::iterate_leakprofiler (lpstw);
401383 assert (lpstw.count () == _stacktrace_id_set->size (), " invariant" );
402- writer.write_count (lpstw.count (), count_offset);
403384}
404385
405386static void write_stacktrace_blob (const ObjectSample* sample, JfrCheckpointWriter& writer) {
@@ -422,6 +403,16 @@ static void write_blobs(const ObjectSample* sample, JfrCheckpointWriter& writer)
422403 write_type_set_blob (sample, writer);
423404}
424405
406+ static void check_if_thread_exited (const ObjectSample* sample) {
407+ assert (sample != nullptr , " invariant" );
408+ if (sample->thread_exited () || unloaded_thread_id_set == nullptr ) {
409+ return ;
410+ }
411+ if (unloaded_thread_id_set->contains (sample->thread_id ())) {
412+ sample->set_thread_exited ();
413+ }
414+ }
415+
425416class BlobWriter {
426417 private:
427418 const ObjectSampler* _sampler;
@@ -431,23 +422,36 @@ class BlobWriter {
431422 BlobWriter (const ObjectSampler* sampler, JfrCheckpointWriter& writer, jlong last_sweep) :
432423 _sampler (sampler), _writer(writer), _last_sweep(last_sweep) {}
433424 void sample_do (ObjectSample* sample) {
425+ check_if_thread_exited (sample);
434426 if (sample->is_alive_and_older_than (_last_sweep)) {
435427 write_blobs (sample, _writer);
436428 }
437429 }
438430};
439431
432+ static void delete_unloaded_thread_id_set () {
433+ if (unloaded_thread_id_set != nullptr ) {
434+ delete unloaded_thread_id_set;
435+ unloaded_thread_id_set = nullptr ;
436+ }
437+ }
438+
440439static void write_sample_blobs (const ObjectSampler* sampler, bool emit_all, Thread* thread) {
441440 // sample set is predicated on time of last sweep
442441 const jlong last_sweep = emit_all ? max_jlong : ObjectSampler::last_sweep ();
443442 JfrCheckpointWriter writer (thread, false );
444443 BlobWriter cbw (sampler, writer, last_sweep);
444+ ThreadIdExclusiveAccess lock;
445445 iterate_samples (cbw, true );
446+ delete_unloaded_thread_id_set ();
446447}
447448
448- static inline unsigned int set_size () {
449- const unsigned int queue_size = static_cast <unsigned int >(JfrOptionSet::old_object_queue_size ());
450- return queue_size > initial_size ? queue_size : initial_size;
449+ static inline unsigned stacktrace_id_set_size () {
450+ unsigned queue_size = static_cast <unsigned >(JfrOptionSet::old_object_queue_size ());
451+ if (!is_power_of_2 (queue_size)) {
452+ queue_size = next_power_of_2 (queue_size);
453+ }
454+ return queue_size > initial_set_size ? queue_size : initial_set_size;
451455}
452456
453457void ObjectSampleCheckpoint::write (const ObjectSampler* sampler, EdgeStore* edge_store, bool emit_all, Thread* thread) {
@@ -456,7 +460,9 @@ void ObjectSampleCheckpoint::write(const ObjectSampler* sampler, EdgeStore* edge
456460 assert (thread != nullptr , " invariant" );
457461 {
458462 ResourceMark rm (thread);
459- _stacktrace_id_set = new JfrResourceAreaTraceIdSet (set_size ());
463+ const unsigned stacktrace_set_size = stacktrace_id_set_size ();
464+ assert (is_power_of_2 (stacktrace_set_size), " invariant" );
465+ _stacktrace_id_set = new JfrResourceAreaTraceIdSet (stacktrace_set_size);
460466 write_sample_blobs (sampler, emit_all, thread);
461467 if (_stacktrace_id_set->is_nonempty ()) {
462468 write_stacktraces (thread);
0 commit comments