< prev index next >

src/share/vm/jfr/recorder/stacktrace/jfrStackTraceRepository.cpp

Print this page
rev 9055 : 8214542: JFR: Old Object Sample event slow on a deep heap in debug builds
Reviewed-by: egahlin, rwestberg


 147   const StackTrace* table_entry = _table[index];
 148 
 149   while (table_entry != NULL) {
 150     if (table_entry->equals(stacktrace)) {
 151       return table_entry->id();
 152     }
 153     table_entry = table_entry->next();
 154   }
 155 
 156   if (!stacktrace.have_lineno()) {
 157     return 0;
 158   }
 159 
 160   traceid id = ++_next_id;
 161   _table[index] = new StackTrace(id, stacktrace, _table[index]);
 162   ++_entries;
 163   return id;
 164 }
 165 
 166 traceid JfrStackTraceRepository::add(const JfrStackTrace& stacktrace) {
 167   return instance().add_trace(stacktrace);






 168 }
 169 
 170 traceid JfrStackTraceRepository::record(Thread* thread, int skip /* 0 */) {
 171   assert(thread == Thread::current(), "invariant");
 172   JfrThreadLocal* const tl = thread->jfr_thread_local();
 173   assert(tl != NULL, "invariant");
 174   if (tl->has_cached_stack_trace()) {
 175     return tl->cached_stack_trace_id();
 176   }
 177   if (!thread->is_Java_thread() || thread->is_hidden_from_external_view()) {
 178     return 0;
 179   }
 180   JfrStackFrame* frames = tl->stackframes();
 181   if (frames == NULL) {
 182     // pending oom
 183     return 0;
 184   }
 185   assert(frames != NULL, "invariant");
 186   assert(tl->stackframes() == frames, "invariant");
 187   return instance().record_for((JavaThread*)thread, skip,frames, tl->stackdepth());
 188 }
 189 
 190 traceid JfrStackTraceRepository::record(Thread* thread, int skip, unsigned int* hash) {
 191   assert(thread == Thread::current(), "invariant");
 192   JfrThreadLocal* const tl = thread->jfr_thread_local();
 193   assert(tl != NULL, "invariant");
 194 
 195   if (tl->has_cached_stack_trace()) {
 196     *hash = tl->cached_stack_trace_hash();
 197     return tl->cached_stack_trace_id();
 198   }
 199   if (!thread->is_Java_thread() || thread->is_hidden_from_external_view()) {
 200     return 0;
 201   }
 202   JfrStackFrame* frames = tl->stackframes();
 203   if (frames == NULL) {
 204     // pending oom
 205     return 0;
 206   }
 207   assert(frames != NULL, "invariant");
 208   assert(tl->stackframes() == frames, "invariant");
 209   return instance().record_for((JavaThread*)thread, skip, frames, tl->stackdepth(), hash);
 210 }
 211 
 212 traceid JfrStackTraceRepository::record_for(JavaThread* thread, int skip, JfrStackFrame *frames, u4 max_frames) {
 213   JfrStackTrace stacktrace(frames, max_frames);
 214   if (!stacktrace.record_safe(thread, skip)) {
 215     return 0;
 216   }
 217   traceid tid = add(stacktrace);
 218   if (tid == 0) {
 219     stacktrace.resolve_linenos();
 220     tid = add(stacktrace);
 221   }
 222   return tid;
 223 }
 224 
 225 traceid JfrStackTraceRepository::record_for(JavaThread* thread, int skip, JfrStackFrame *frames, u4 max_frames, unsigned int* hash) {
 226   assert(hash != NULL && *hash == 0, "invariant");
 227   JfrStackTrace stacktrace(frames, max_frames);
 228   if (!stacktrace.record_safe(thread, skip, true)) {
 229     return 0;
 230   }
 231   traceid tid = add(stacktrace);
 232   if (tid == 0) {
 233     stacktrace.resolve_linenos();
 234     tid = add(stacktrace);






 235   }
 236   *hash = stacktrace._hash;
 237   return tid;
 238 }
 239 
 240 size_t JfrStackTraceRepository::write_impl(JfrChunkWriter& sw, bool clear) {
 241   MutexLockerEx lock(JfrStacktrace_lock, Mutex::_no_safepoint_check_flag);
 242   assert(_entries > 0, "invariant");
 243   int count = 0;
 244   for (u4 i = 0; i < TABLE_SIZE; ++i) {
 245     JfrStackTraceRepository::StackTrace* stacktrace = _table[i];
 246     while (stacktrace != NULL) {
 247       JfrStackTraceRepository::StackTrace* next = stacktrace->next();
 248       if (stacktrace->should_write()) {
 249         stacktrace->write(sw);
 250         ++count;
 251       }
 252       if (clear) {
 253         delete stacktrace;
 254       }
 255       stacktrace = next;
 256     }
 257   }


 346   write_frame(cw, _methodid, _line, _bci, _type);
 347 }
 348 
 349 void JfrStackFrame::write(JfrCheckpointWriter& cpw) const {
 350   write_frame(cpw, _methodid, _line, _bci, _type);
 351 }
 352 
 353 // invariant is that the entry to be resolved actually exists in the table
 354 const JfrStackTraceRepository::StackTrace* JfrStackTraceRepository::resolve_entry(unsigned int hash, traceid id) const {
 355   const size_t index = (hash % TABLE_SIZE);
 356   const StackTrace* trace = _table[index];
 357   while (trace != NULL && trace->id() != id) {
 358     trace = trace->next();
 359   }
 360   assert(trace != NULL, "invariant");
 361   assert(trace->hash() == hash, "invariant");
 362   assert(trace->id() == id, "invariant");
 363   return trace;
 364 }
 365 
 366 void JfrStackFrame::resolve_lineno() {
 367   assert(_method, "no method pointer");
 368   assert(_line == 0, "already have linenumber");
 369   _line = _method->line_number_from_bci(_bci);
 370   _method = NULL;
 371 }
 372 
 373 void JfrStackTrace::set_frame(u4 frame_pos, JfrStackFrame& frame) {
 374   assert(frame_pos < _max_frames, "illegal frame_pos");
 375   _frames[frame_pos] = frame;
 376 }
 377 
 378 void JfrStackTrace::resolve_linenos() {
 379   for(unsigned int i = 0; i < _nr_of_frames; i++) {
 380     _frames[i].resolve_lineno();
 381   }
 382   _lineno = true;
 383 }
 384 
 385 bool JfrStackTrace::record_safe(JavaThread* thread, int skip, bool leakp /* false */) {
 386   assert(SafepointSynchronize::safepoint_safe(thread, thread->thread_state())
 387          || thread == Thread::current(), "Thread stack needs to be walkable");
 388   vframeStream vfs(thread);
 389   u4 count = 0;
 390   _reached_root = true;
 391   for(int i = 0; i < skip; i++) {
 392     if (vfs.at_end()) {
 393       break;
 394     }
 395     vfs.next();
 396   }
 397 
 398   while (!vfs.at_end()) {




 147   const StackTrace* table_entry = _table[index];
 148 
 149   while (table_entry != NULL) {
 150     if (table_entry->equals(stacktrace)) {
 151       return table_entry->id();
 152     }
 153     table_entry = table_entry->next();
 154   }
 155 
 156   if (!stacktrace.have_lineno()) {
 157     return 0;
 158   }
 159 
 160   traceid id = ++_next_id;
 161   _table[index] = new StackTrace(id, stacktrace, _table[index]);
 162   ++_entries;
 163   return id;
 164 }
 165 
 166 traceid JfrStackTraceRepository::add(const JfrStackTrace& stacktrace) {
 167   traceid tid = instance().add_trace(stacktrace);
 168   if (tid == 0) {
 169     stacktrace.resolve_linenos();
 170     tid = instance().add_trace(stacktrace);
 171   }
 172   assert(tid != 0, "invariant");
 173   return tid;
 174 }
 175 
 176 traceid JfrStackTraceRepository::record(Thread* thread, int skip /* 0 */) {
 177   assert(thread == Thread::current(), "invariant");
 178   JfrThreadLocal* const tl = thread->jfr_thread_local();
 179   assert(tl != NULL, "invariant");
 180   if (tl->has_cached_stack_trace()) {
 181     return tl->cached_stack_trace_id();
 182   }
 183   if (!thread->is_Java_thread() || thread->is_hidden_from_external_view()) {
 184     return 0;
 185   }
 186   JfrStackFrame* frames = tl->stackframes();
 187   if (frames == NULL) {
 188     // pending oom
 189     return 0;
 190   }
 191   assert(frames != NULL, "invariant");
 192   assert(tl->stackframes() == frames, "invariant");
 193   return instance().record_for((JavaThread*)thread, skip,frames, tl->stackdepth());
 194 }
 195 






















 196 traceid JfrStackTraceRepository::record_for(JavaThread* thread, int skip, JfrStackFrame *frames, u4 max_frames) {
 197   JfrStackTrace stacktrace(frames, max_frames);
 198   return stacktrace.record_safe(thread, skip) ? add(stacktrace) : 0;








 199 }
 200 
 201 traceid JfrStackTraceRepository::add(const JfrStackTrace* stacktrace, JavaThread* thread) {
 202   assert(stacktrace != NULL, "invariant");
 203   assert(thread != NULL, "invariant");
 204   assert(stacktrace->hash() != 0, "invariant");
 205   return add(*stacktrace);
 206 }
 207 
 208 bool JfrStackTraceRepository::fill_stacktrace_for(JavaThread* thread, JfrStackTrace* stacktrace, int skip) {
 209   assert(thread == Thread::current(), "invariant");
 210   assert(stacktrace != NULL, "invariant");
 211   JfrThreadLocal* const tl = thread->jfr_thread_local();
 212   assert(tl != NULL, "invariant");
 213   const unsigned int cached_stacktrace_hash = tl->cached_stack_trace_hash();
 214   if (cached_stacktrace_hash != 0) {
 215     stacktrace->set_hash(cached_stacktrace_hash);
 216     return true;
 217   }
 218   return stacktrace->record_safe(thread, skip, true);

 219 }
 220 
 221 size_t JfrStackTraceRepository::write_impl(JfrChunkWriter& sw, bool clear) {
 222   MutexLockerEx lock(JfrStacktrace_lock, Mutex::_no_safepoint_check_flag);
 223   assert(_entries > 0, "invariant");
 224   int count = 0;
 225   for (u4 i = 0; i < TABLE_SIZE; ++i) {
 226     JfrStackTraceRepository::StackTrace* stacktrace = _table[i];
 227     while (stacktrace != NULL) {
 228       JfrStackTraceRepository::StackTrace* next = stacktrace->next();
 229       if (stacktrace->should_write()) {
 230         stacktrace->write(sw);
 231         ++count;
 232       }
 233       if (clear) {
 234         delete stacktrace;
 235       }
 236       stacktrace = next;
 237     }
 238   }


 327   write_frame(cw, _methodid, _line, _bci, _type);
 328 }
 329 
 330 void JfrStackFrame::write(JfrCheckpointWriter& cpw) const {
 331   write_frame(cpw, _methodid, _line, _bci, _type);
 332 }
 333 
 334 // invariant is that the entry to be resolved actually exists in the table
 335 const JfrStackTraceRepository::StackTrace* JfrStackTraceRepository::resolve_entry(unsigned int hash, traceid id) const {
 336   const size_t index = (hash % TABLE_SIZE);
 337   const StackTrace* trace = _table[index];
 338   while (trace != NULL && trace->id() != id) {
 339     trace = trace->next();
 340   }
 341   assert(trace != NULL, "invariant");
 342   assert(trace->hash() == hash, "invariant");
 343   assert(trace->id() == id, "invariant");
 344   return trace;
 345 }
 346 
 347 void JfrStackFrame::resolve_lineno() const {
 348   assert(_method, "no method pointer");
 349   assert(_line == 0, "already have linenumber");
 350   _line = _method->line_number_from_bci(_bci);
 351   _method = NULL;
 352 }
 353 
 354 void JfrStackTrace::set_frame(u4 frame_pos, JfrStackFrame& frame) {
 355   assert(frame_pos < _max_frames, "illegal frame_pos");
 356   _frames[frame_pos] = frame;
 357 }
 358 
 359 void JfrStackTrace::resolve_linenos() const {
 360   for(unsigned int i = 0; i < _nr_of_frames; i++) {
 361     _frames[i].resolve_lineno();
 362   }
 363   _lineno = true;
 364 }
 365 
 366 bool JfrStackTrace::record_safe(JavaThread* thread, int skip, bool leakp /* false */) {
 367   assert(SafepointSynchronize::safepoint_safe(thread, thread->thread_state())
 368          || thread == Thread::current(), "Thread stack needs to be walkable");
 369   vframeStream vfs(thread);
 370   u4 count = 0;
 371   _reached_root = true;
 372   for(int i = 0; i < skip; i++) {
 373     if (vfs.at_end()) {
 374       break;
 375     }
 376     vfs.next();
 377   }
 378 
 379   while (!vfs.at_end()) {


< prev index next >