238 return _stack_trace_repo.lookup(sample->stack_trace_hash(), sample->stack_trace_id()); |
238 return _stack_trace_repo.lookup(sample->stack_trace_hash(), sample->stack_trace_id()); |
239 } |
239 } |
240 |
240 |
241 #ifdef ASSERT |
241 #ifdef ASSERT |
242 static void validate_stack_trace(const ObjectSample* sample, const JfrStackTrace* stack_trace) { |
242 static void validate_stack_trace(const ObjectSample* sample, const JfrStackTrace* stack_trace) { |
243 assert(sample != NULL, "invariant"); |
|
244 assert(!sample->is_dead(), "invariant"); |
|
245 assert(!sample->has_stacktrace(), "invariant"); |
243 assert(!sample->has_stacktrace(), "invariant"); |
246 assert(stack_trace != NULL, "invariant"); |
244 assert(stack_trace != NULL, "invariant"); |
247 assert(stack_trace->hash() == sample->stack_trace_hash(), "invariant"); |
245 assert(stack_trace->hash() == sample->stack_trace_hash(), "invariant"); |
248 assert(stack_trace->id() == sample->stack_trace_id(), "invariant"); |
246 assert(stack_trace->id() == sample->stack_trace_id(), "invariant"); |
249 } |
247 } |
253 JfrBlobHandle blob = _cache.get(sample); |
251 JfrBlobHandle blob = _cache.get(sample); |
254 if (blob.valid()) { |
252 if (blob.valid()) { |
255 sample->set_stacktrace(blob); |
253 sample->set_stacktrace(blob); |
256 return; |
254 return; |
257 } |
255 } |
258 const JfrStackTrace* stack_trace = resolve(sample); |
256 const JfrStackTrace* const stack_trace = resolve(sample); |
259 DEBUG_ONLY(validate_stack_trace(sample, stack_trace)); |
257 DEBUG_ONLY(validate_stack_trace(sample, stack_trace)); |
260 JfrCheckpointWriter writer; |
258 JfrCheckpointWriter writer; |
261 writer.write_type(TYPE_STACKTRACE); |
259 writer.write_type(TYPE_STACKTRACE); |
262 writer.write_count(1); |
260 writer.write_count(1); |
263 ObjectSampleCheckpoint::write_stacktrace(stack_trace, writer); |
261 ObjectSampleCheckpoint::write_stacktrace(stack_trace, writer); |
302 assert(id != 0, "invariant"); |
300 assert(id != 0, "invariant"); |
303 assert(id_set != NULL, "invariant"); |
301 assert(id_set != NULL, "invariant"); |
304 return mutable_predicate(id_set, id); |
302 return mutable_predicate(id_set, id); |
305 } |
303 } |
306 |
304 |
307 void ObjectSampleCheckpoint::tag(const JfrStackFrame& frame, traceid method_id) { |
305 void ObjectSampleCheckpoint::add_to_leakp_set(const Method* method, traceid method_id) { |
308 if (is_processed(method_id) || is_klass_unloaded(method_id)) { |
306 if (is_processed(method_id) || is_klass_unloaded(method_id)) { |
309 return; |
307 return; |
310 } |
308 } |
311 JfrTraceId::set_leakp(frame._method); |
309 JfrTraceId::set_leakp(method); |
312 } |
310 } |
313 |
311 |
314 void ObjectSampleCheckpoint::write_stacktrace(const JfrStackTrace* trace, JfrCheckpointWriter& writer) { |
312 void ObjectSampleCheckpoint::write_stacktrace(const JfrStackTrace* trace, JfrCheckpointWriter& writer) { |
315 assert(trace != NULL, "invariant"); |
313 assert(trace != NULL, "invariant"); |
316 // JfrStackTrace |
314 // JfrStackTrace |
317 writer.write(trace->id()); |
315 writer.write(trace->id()); |
318 writer.write((u1)!trace->_reached_root); |
316 writer.write((u1)!trace->_reached_root); |
319 writer.write(trace->_nr_of_frames); |
317 writer.write(trace->_nr_of_frames); |
320 traceid last_id = 0; |
|
321 // JfrStackFrames |
318 // JfrStackFrames |
322 for (u4 i = 0; i < trace->_nr_of_frames; ++i) { |
319 for (u4 i = 0; i < trace->_nr_of_frames; ++i) { |
323 trace->_frames[i].write(writer); |
320 const JfrStackFrame& frame = trace->_frames[i]; |
324 const traceid method_id = trace->_frames[i]._methodid; |
321 frame.write(writer); |
325 if (method_id != last_id) { |
322 add_to_leakp_set(frame._method, frame._methodid); |
326 tag(trace->_frames[i], method_id); |
|
327 last_id = method_id; |
|
328 } |
|
329 } |
323 } |
330 } |
324 } |
331 |
325 |
332 static void write_blob(const JfrBlobHandle& blob, JfrCheckpointWriter& writer, bool reset) { |
326 static void write_blob(const JfrBlobHandle& blob, JfrCheckpointWriter& writer, bool reset) { |
333 if (reset) { |
327 if (reset) { |