src/hotspot/share/jfr/leakprofiler/sampling/objectSampler.cpp
changeset 58132 caa25ab47aca
parent 55571 49102ba8cf14
child 58157 9dca61a7df19
child 58679 9c3209ff7550
child 58863 c16ac7a2eba4
equal deleted inserted replaced
58131:3054503bad7d 58132:caa25ab47aca
     1 /*
     1 /*
     2  * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     7  * published by the Free Software Foundation.
   108   if (thread->threadObj() == NULL) {
   108   if (thread->threadObj() == NULL) {
   109     return 0;
   109     return 0;
   110   }
   110   }
   111   const JfrThreadLocal* const tl = thread->jfr_thread_local();
   111   const JfrThreadLocal* const tl = thread->jfr_thread_local();
   112   assert(tl != NULL, "invariant");
   112   assert(tl != NULL, "invariant");
   113   if (!tl->has_thread_checkpoint()) {
   113   if (!tl->has_thread_blob()) {
   114     JfrCheckpointManager::create_thread_checkpoint(thread);
   114     JfrCheckpointManager::create_thread_blob(thread);
   115   }
   115   }
   116   assert(tl->has_thread_checkpoint(), "invariant");
   116   assert(tl->has_thread_blob(), "invariant");
   117   return tl->thread_id();
   117   return tl->thread_id();
   118 }
   118 }
   119 
   119 
   120 // Populates the thread local stack frames, but does not add them
   120 static void record_stacktrace(JavaThread* thread) {
   121 // to the stacktrace repository (...yet, see stacktrace_id() below)
       
   122 //
       
   123 void ObjectSampler::fill_stacktrace(JfrStackTrace* stacktrace, JavaThread* thread) {
       
   124   assert(stacktrace != NULL, "invariant");
       
   125   assert(thread != NULL, "invariant");
   121   assert(thread != NULL, "invariant");
   126   if (JfrEventSetting::has_stacktrace(EventOldObjectSample::eventId)) {
   122   if (JfrEventSetting::has_stacktrace(EventOldObjectSample::eventId)) {
   127     JfrStackTraceRepository::fill_stacktrace_for(thread, stacktrace, 0);
   123     JfrStackTraceRepository::record_and_cache(thread);
   128   }
   124   }
   129 }
       
   130 
       
   131 // We were successful in acquiring the try lock and have been selected for adding a sample.
       
   132 // Go ahead with installing our previously taken stacktrace into the stacktrace repository.
       
   133 //
       
   134 traceid ObjectSampler::stacktrace_id(const JfrStackTrace* stacktrace, JavaThread* thread) {
       
   135   assert(stacktrace != NULL, "invariant");
       
   136   assert(stacktrace->hash() != 0, "invariant");
       
   137   const traceid stacktrace_id = JfrStackTraceRepository::add(stacktrace, thread);
       
   138   thread->jfr_thread_local()->set_cached_stack_trace_id(stacktrace_id, stacktrace->hash());
       
   139   return stacktrace_id;
       
   140 }
   125 }
   141 
   126 
   142 void ObjectSampler::sample(HeapWord* obj, size_t allocated, JavaThread* thread) {
   127 void ObjectSampler::sample(HeapWord* obj, size_t allocated, JavaThread* thread) {
   143   assert(thread != NULL, "invariant");
   128   assert(thread != NULL, "invariant");
   144   assert(is_created(), "invariant");
   129   assert(is_created(), "invariant");
   145 
       
   146   const traceid thread_id = get_thread_id(thread);
   130   const traceid thread_id = get_thread_id(thread);
   147   if (thread_id == 0) {
   131   if (thread_id == 0) {
   148     return;
   132     return;
   149   }
   133   }
   150 
   134   record_stacktrace(thread);
   151   const JfrThreadLocal* const tl = thread->jfr_thread_local();
       
   152   JfrStackTrace stacktrace(tl->stackframes(), tl->stackdepth());
       
   153   fill_stacktrace(&stacktrace, thread);
       
   154 
       
   155   // try enter critical section
   135   // try enter critical section
   156   JfrTryLock tryLock(&_lock);
   136   JfrTryLock tryLock(&_lock);
   157   if (!tryLock.has_lock()) {
   137   if (!tryLock.has_lock()) {
   158     log_trace(jfr, oldobject, sampling)("Skipping old object sample due to lock contention");
   138     log_trace(jfr, oldobject, sampling)("Skipping old object sample due to lock contention");
   159     return;
   139     return;
   160   }
   140   }
   161 
   141   instance().add(obj, allocated, thread_id, thread);
   162   instance().add(obj, allocated, thread_id, &stacktrace, thread);
   142 }
   163 }
   143 
   164 
   144 void ObjectSampler::add(HeapWord* obj, size_t allocated, traceid thread_id, JavaThread* thread) {
   165 void ObjectSampler::add(HeapWord* obj, size_t allocated, traceid thread_id, JfrStackTrace* stacktrace, JavaThread* thread) {
   145   assert(obj != NULL, "invariant");
   166   assert(stacktrace != NULL, "invariant");
       
   167   assert(thread_id != 0, "invariant");
   146   assert(thread_id != 0, "invariant");
   168   assert(thread != NULL, "invariant");
   147   assert(thread != NULL, "invariant");
   169   assert(thread->jfr_thread_local()->has_thread_checkpoint(), "invariant");
   148   assert(thread->jfr_thread_local()->has_thread_blob(), "invariant");
   170 
   149 
   171   if (_dead_samples) {
   150   if (_dead_samples) {
   172     scavenge();
   151     scavenge();
   173     assert(!_dead_samples, "invariant");
   152     assert(!_dead_samples, "invariant");
   174   }
   153   }
   188     sample = _list->get();
   167     sample = _list->get();
   189   }
   168   }
   190 
   169 
   191   assert(sample != NULL, "invariant");
   170   assert(sample != NULL, "invariant");
   192   sample->set_thread_id(thread_id);
   171   sample->set_thread_id(thread_id);
   193   sample->set_thread_checkpoint(thread->jfr_thread_local()->thread_checkpoint());
   172 
   194 
   173   const JfrThreadLocal* const tl = thread->jfr_thread_local();
   195   const unsigned int stacktrace_hash = stacktrace->hash();
   174   sample->set_thread(tl->thread_blob());
       
   175 
       
   176   const unsigned int stacktrace_hash = tl->cached_stack_trace_hash();
   196   if (stacktrace_hash != 0) {
   177   if (stacktrace_hash != 0) {
   197     sample->set_stack_trace_id(stacktrace_id(stacktrace, thread));
   178     sample->set_stack_trace_id(tl->cached_stack_trace_id());
   198     sample->set_stack_trace_hash(stacktrace_hash);
   179     sample->set_stack_trace_hash(stacktrace_hash);
   199   }
   180   }
   200 
   181 
   201   sample->set_span(allocated);
   182   sample->set_span(allocated);
   202   sample->set_object((oop)obj);
   183   sample->set_object((oop)obj);
   251     current = next;
   232     current = next;
   252   }
   233   }
   253   sampler._last_sweep = JfrTicks::now();
   234   sampler._last_sweep = JfrTicks::now();
   254 }
   235 }
   255 
   236 
   256 const ObjectSample* ObjectSampler::last() const {
   237 ObjectSample* ObjectSampler::last() const {
   257   return _list->last();
   238   return _list->last();
   258 }
   239 }
   259 
   240 
   260 const ObjectSample* ObjectSampler::first() const {
   241 const ObjectSample* ObjectSampler::first() const {
   261   return _list->first();
   242   return _list->first();