@@ -246,22 +246,37 @@ ContextNode *getFlatProfile(FunctionData &Data, GUID Guid,
246
246
247
247
ContextNode *getUnhandledContext (FunctionData &Data, GUID Guid,
248
248
uint32_t NumCounters) {
249
- // 1) if we are under a root (regardless if this thread is collecting or not a
249
+
250
+ // 1) if we are currently collecting a contextual profile, fetch a ContextNode
251
+ // in the `Unhandled` set. We want to do this regardless of `ProfilingStarted`
252
+ // to (hopefully) offset the penalty of creating these contexts to before
253
+ // profiling.
254
+ //
255
+ // 2) if we are under a root (regardless if this thread is collecting or not a
250
256
// contextual profile for that root), do not collect a flat profile. We want
251
257
// to keep flat profiles only for activations that can't happen under a root,
252
258
// to avoid confusing profiles. We can, for example, combine flattened and
253
259
// flat profiles meaningfully, as we wouldn't double-count anything.
254
260
//
255
- // 2 ) to avoid lengthy startup, don't bother with flat profiles until the
261
+ // 3 ) to avoid lengthy startup, don't bother with flat profiles until the
256
262
// profiling started. We would reset them anyway when profiling starts.
257
263
// HOWEVER. This does lose profiling for message pumps: those functions are
258
264
// entered once and never exit. They should be assumed to be entered before
259
265
// profiling starts - because profiling should start after the server is up
260
266
// and running (which is equivalent to "message pumps are set up").
261
- if (IsUnderContext || !__sanitizer::atomic_load_relaxed (&ProfilingStarted))
262
- return TheScratchContext;
263
- return markAsScratch (
264
- onContextEnter (*getFlatProfile (Data, Guid, NumCounters)));
267
+ ContextRoot *R = __llvm_ctx_profile_current_context_root;
268
+ if (!R) {
269
+ if (IsUnderContext || !__sanitizer::atomic_load_relaxed (&ProfilingStarted))
270
+ return TheScratchContext;
271
+ else
272
+ return markAsScratch (
273
+ onContextEnter (*getFlatProfile (Data, Guid, NumCounters)));
274
+ }
275
+ auto It = R->Unhandled .insert ({Guid, nullptr });
276
+ if (It.second )
277
+ It.first ->second =
278
+ getCallsiteSlow (Guid, &R->FirstUnhandledCalleeNode , NumCounters, 0 );
279
+ return markAsScratch (onContextEnter (*It.first ->second ));
265
280
}
266
281
267
282
ContextNode *__llvm_ctx_profile_get_context (FunctionData *Data, void *Callee,
@@ -396,6 +411,8 @@ void __llvm_ctx_profile_start_collection() {
396
411
++NumMemUnits;
397
412
398
413
resetContextNode (*Root->FirstNode );
414
+ if (Root->FirstUnhandledCalleeNode )
415
+ resetContextNode (*Root->FirstUnhandledCalleeNode );
399
416
__sanitizer::atomic_store_relaxed (&Root->TotalEntries , 0 );
400
417
}
401
418
__sanitizer::atomic_store_relaxed (&ProfilingStarted, true );
0 commit comments