179 int count() const { |
179 int count() const { |
180 return _count; |
180 return _count; |
181 } |
181 } |
182 }; |
182 }; |
183 |
183 |
184 void ObjectSampleCheckpoint::install(JfrCheckpointWriter& writer, bool class_unload, bool resume) { |
184 void ObjectSampleCheckpoint::install(JfrCheckpointWriter& writer, bool class_unload, bool type_set) { |
185 assert(class_unload ? SafepointSynchronize::is_at_safepoint() : LeakProfiler::is_suspended(), "invariant"); |
|
186 |
|
187 if (!writer.has_data()) { |
185 if (!writer.has_data()) { |
188 if (!class_unload) { |
|
189 LeakProfiler::resume(); |
|
190 } |
|
191 assert(LeakProfiler::is_running(), "invariant"); |
|
192 return; |
186 return; |
193 } |
187 } |
194 |
188 |
195 assert(writer.has_data(), "invariant"); |
189 assert(writer.has_data(), "invariant"); |
196 const JfrCheckpointBlobHandle h_cp = writer.checkpoint_blob(); |
190 const JfrCheckpointBlobHandle h_cp = writer.checkpoint_blob(); |
197 |
191 CheckpointInstall install(h_cp); |
198 const ObjectSampler* const object_sampler = LeakProfiler::object_sampler(); |
192 |
|
193 // Class unload implies a safepoint. |
|
194 // Not class unload implies the object sampler is locked, because it was claimed exclusively earlier. |
|
195 // Therefore: direct access the object sampler instance is safe. |
|
196 ObjectSampler* const object_sampler = ObjectSampler::sampler(); |
199 assert(object_sampler != NULL, "invariant"); |
197 assert(object_sampler != NULL, "invariant"); |
200 |
198 |
201 ObjectSample* const last = const_cast<ObjectSample*>(object_sampler->last()); |
199 ObjectSample* const last = const_cast<ObjectSample*>(object_sampler->last()); |
202 const ObjectSample* const last_resolved = object_sampler->last_resolved(); |
200 const ObjectSample* const last_resolved = object_sampler->last_resolved(); |
203 CheckpointInstall install(h_cp); |
201 |
204 |
202 // install only to new samples since last resolved checkpoint |
205 if (class_unload) { |
|
206 if (last != NULL) { |
|
207 // all samples need the class unload information |
|
208 do_samples(last, NULL, install); |
|
209 } |
|
210 assert(LeakProfiler::is_running(), "invariant"); |
|
211 return; |
|
212 } |
|
213 |
|
214 // only new samples since last resolved checkpoint |
|
215 if (last != last_resolved) { |
203 if (last != last_resolved) { |
216 do_samples(last, last_resolved, install); |
204 do_samples(last, last_resolved, install); |
217 if (resume) { |
205 if (class_unload) { |
218 const_cast<ObjectSampler*>(object_sampler)->set_last_resolved(last); |
206 return; |
219 } |
207 } |
220 } |
208 if (type_set) { |
221 assert(LeakProfiler::is_suspended(), "invariant"); |
209 object_sampler->set_last_resolved(last); |
222 if (resume) { |
210 } |
223 LeakProfiler::resume(); |
211 } |
224 assert(LeakProfiler::is_running(), "invariant"); |
212 } |
225 } |
213 |
226 } |
214 void ObjectSampleCheckpoint::write(ObjectSampler* sampler, EdgeStore* edge_store, bool emit_all, Thread* thread) { |
227 |
215 assert(sampler != NULL, "invariant"); |
228 void ObjectSampleCheckpoint::write(const EdgeStore* edge_store, bool emit_all, Thread* thread) { |
|
229 assert(edge_store != NULL, "invariant"); |
216 assert(edge_store != NULL, "invariant"); |
230 assert(thread != NULL, "invariant"); |
217 assert(thread != NULL, "invariant"); |
|
218 |
231 static bool types_registered = false; |
219 static bool types_registered = false; |
232 if (!types_registered) { |
220 if (!types_registered) { |
233 JfrSerializer::register_serializer(TYPE_OLDOBJECTROOTSYSTEM, false, true, new RootSystemType()); |
221 JfrSerializer::register_serializer(TYPE_OLDOBJECTROOTSYSTEM, false, true, new RootSystemType()); |
234 JfrSerializer::register_serializer(TYPE_OLDOBJECTROOTTYPE, false, true, new RootType()); |
222 JfrSerializer::register_serializer(TYPE_OLDOBJECTROOTTYPE, false, true, new RootType()); |
235 types_registered = true; |
223 types_registered = true; |
236 } |
224 } |
237 const ObjectSampler* const object_sampler = LeakProfiler::object_sampler(); |
225 |
238 assert(object_sampler != NULL, "invariant"); |
226 const jlong last_sweep = emit_all ? max_jlong : sampler->last_sweep().value(); |
239 const jlong last_sweep = emit_all ? max_jlong : object_sampler->last_sweep().value(); |
227 ObjectSample* const last = const_cast<ObjectSample*>(sampler->last()); |
240 ObjectSample* const last = const_cast<ObjectSample*>(object_sampler->last()); |
|
241 { |
228 { |
242 JfrCheckpointWriter writer(false, false, thread); |
229 JfrCheckpointWriter writer(false, false, thread); |
243 CheckpointWrite checkpoint_write(writer, last_sweep); |
230 CheckpointWrite checkpoint_write(writer, last_sweep); |
244 do_samples(last, NULL, checkpoint_write); |
231 do_samples(last, NULL, checkpoint_write); |
245 } |
232 } |
|
233 |
246 CheckpointStateReset state_reset(last_sweep); |
234 CheckpointStateReset state_reset(last_sweep); |
247 do_samples(last, NULL, state_reset); |
235 do_samples(last, NULL, state_reset); |
|
236 |
248 if (!edge_store->is_empty()) { |
237 if (!edge_store->is_empty()) { |
249 // java object and chain representations |
238 // java object and chain representations |
250 JfrCheckpointWriter writer(false, true, thread); |
239 JfrCheckpointWriter writer(false, true, thread); |
251 ObjectSampleWriter osw(writer, edge_store); |
240 ObjectSampleWriter osw(writer, edge_store); |
252 edge_store->iterate_edges(osw); |
241 edge_store->iterate(osw); |
253 } |
242 } |
254 } |
243 } |
255 |
244 |
256 WriteObjectSampleStacktrace::WriteObjectSampleStacktrace(JfrStackTraceRepository& repo) : |
245 int ObjectSampleCheckpoint::mark(ObjectSampler* object_sampler, ObjectSampleMarker& marker, bool emit_all) { |
257 _stack_trace_repo(repo) { |
246 assert(object_sampler != NULL, "invariant"); |
258 } |
247 ObjectSample* const last = const_cast<ObjectSample*>(object_sampler->last()); |
|
248 if (last == NULL) { |
|
249 return 0; |
|
250 } |
|
251 const jlong last_sweep = emit_all ? max_jlong : object_sampler->last_sweep().value(); |
|
252 SampleMark mark(marker, last_sweep); |
|
253 do_samples(last, NULL, mark); |
|
254 return mark.count(); |
|
255 } |
|
256 |
|
257 WriteObjectSampleStacktrace::WriteObjectSampleStacktrace(ObjectSampler* sampler, JfrStackTraceRepository& repo) : |
|
258 _sampler(sampler), _stack_trace_repo(repo) {} |
259 |
259 |
260 bool WriteObjectSampleStacktrace::process() { |
260 bool WriteObjectSampleStacktrace::process() { |
261 assert(SafepointSynchronize::is_at_safepoint(), "invariant"); |
261 assert(LeakProfiler::is_running(), "invariant"); |
262 if (!LeakProfiler::is_running()) { |
262 assert(_sampler != NULL, "invariant"); |
263 return true; |
263 |
264 } |
264 ObjectSample* const last = const_cast<ObjectSample*>(_sampler->last()); |
265 // Suspend the LeakProfiler subsystem |
265 const ObjectSample* const last_resolved = _sampler->last_resolved(); |
266 // to ensure stable samples even |
|
267 // after we return from the safepoint. |
|
268 LeakProfiler::suspend(); |
|
269 assert(!LeakProfiler::is_running(), "invariant"); |
|
270 assert(LeakProfiler::is_suspended(), "invariant"); |
|
271 |
|
272 const ObjectSampler* object_sampler = LeakProfiler::object_sampler(); |
|
273 assert(object_sampler != NULL, "invariant"); |
|
274 assert(LeakProfiler::is_suspended(), "invariant"); |
|
275 |
|
276 ObjectSample* const last = const_cast<ObjectSample*>(object_sampler->last()); |
|
277 const ObjectSample* const last_resolved = object_sampler->last_resolved(); |
|
278 if (last == last_resolved) { |
266 if (last == last_resolved) { |
279 assert(LeakProfiler::is_suspended(), "invariant"); |
|
280 return true; |
267 return true; |
281 } |
268 } |
282 |
269 |
283 JfrCheckpointWriter writer(false, true, Thread::current()); |
270 JfrCheckpointWriter writer(false, true, Thread::current()); |
284 const JfrCheckpointContext ctx = writer.context(); |
271 const JfrCheckpointContext ctx = writer.context(); |
292 do_samples(last, last_resolved, stack_trace_write); |
279 do_samples(last, last_resolved, stack_trace_write); |
293 count = stack_trace_write.count(); |
280 count = stack_trace_write.count(); |
294 } |
281 } |
295 if (count == 0) { |
282 if (count == 0) { |
296 writer.set_context(ctx); |
283 writer.set_context(ctx); |
297 assert(LeakProfiler::is_suspended(), "invariant"); |
|
298 return true; |
284 return true; |
299 } |
285 } |
300 assert(count > 0, "invariant"); |
286 assert(count > 0, "invariant"); |
301 writer.write_count((u4)count, count_offset); |
287 writer.write_count((u4)count, count_offset); |
302 JfrStackTraceRepository::write_metadata(writer); |
288 JfrStackTraceRepository::write_metadata(writer); |
303 |
289 |
|
290 // install the stacktrace checkpoint information to the candidates |
304 ObjectSampleCheckpoint::install(writer, false, false); |
291 ObjectSampleCheckpoint::install(writer, false, false); |
305 assert(LeakProfiler::is_suspended(), "invariant"); |
|
306 return true; |
292 return true; |
307 } |
293 } |
308 |
|
309 int ObjectSampleCheckpoint::mark(ObjectSampleMarker& marker, bool emit_all) { |
|
310 const ObjectSampler* object_sampler = LeakProfiler::object_sampler(); |
|
311 assert(object_sampler != NULL, "invariant"); |
|
312 ObjectSample* const last = const_cast<ObjectSample*>(object_sampler->last()); |
|
313 if (last == NULL) { |
|
314 return 0; |
|
315 } |
|
316 const jlong last_sweep = emit_all ? max_jlong : object_sampler->last_sweep().value(); |
|
317 SampleMark mark(marker, last_sweep); |
|
318 do_samples(last, NULL, mark); |
|
319 return mark.count(); |
|
320 } |
|