From 2bc5ea6cdab5a4788b69fd5edf5304d83fa4ba87 Mon Sep 17 00:00:00 2001 From: 0-v-0 Date: Sun, 21 Jun 2026 00:26:31 +0800 Subject: [PATCH 1/2] Fix #17121 - cache profiler symbol lookups --- druntime/src/rt/trace.d | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/druntime/src/rt/trace.d b/druntime/src/rt/trace.d index 18a37b7a1dfd..d4a0d38ca57a 100644 --- a/druntime/src/rt/trace.d +++ b/druntime/src/rt/trace.d @@ -122,6 +122,12 @@ struct Symbol enum ubyte SFvisited = 1; // visited +struct SymbolCacheEntry +{ + const(char)* ptr; + size_t length; + Symbol* sym; +} ////////////////////////////////// // Build a linked list of these. @@ -140,6 +146,7 @@ bool trace_inited; Stack* stack_freelist; Stack* trace_tos; // top of stack +SymbolCacheEntry[2048] trace_cache; __gshared { @@ -636,10 +643,27 @@ private void trace_sympair_add(SymPair** psp, Symbol* s, ulong count) sp.count += count; } +private Symbol* trace_findsym(const(char)[] id) +{ + enum cacheMask = trace_cache.length - 1; + static assert((trace_cache.length & cacheMask) == 0); + + const idx = (cast(size_t) id.ptr >> 4) & cacheMask; + auto entry = &trace_cache[idx]; + if (entry.ptr == id.ptr && entry.length == id.length) + return entry.sym; + + auto s = trace_addsym(&root, id); + entry.ptr = id.ptr; + entry.length = id.length; + entry.sym = s; + return s; +} + ////////////////////////////////////////////// // This one is called by DMD -private extern(C) void trace_pro(char[] id) +private extern(C) void trace_pro(const(char)[] id) { //printf("trace_pro(ptr = %p, length = %lld)\n", id.ptr, id.length); //printf("trace_pro(id = '%.*s')\n", id.length, id.ptr); @@ -655,7 +679,7 @@ private extern(C) void trace_pro(char[] id) if (id.length == 0) return; auto tos = stack_push(); - auto s = trace_addsym(&root, id); + auto s = trace_findsym(id); tos.sym = s; if (tos.prev) { @@ -677,8 +701,7 @@ private extern(C) void trace_pro(char[] id) // Called by some old versions of DMD extern(C) void _c_trace_pro(size_t idlen, char* idptr) { - char[] id = idptr[0 .. idlen]; - trace_pro(id); + trace_pro(idptr[0 .. idlen]); } ///////////////////////////////////////// From 37b36ba2177e3c529534b446af24c547a7212515 Mon Sep 17 00:00:00 2001 From: 0-v-0 Date: Sun, 21 Jun 2026 11:06:44 +0800 Subject: [PATCH 2/2] Pack pointers in SymbolCacheEntry on 64bit platform --- druntime/src/rt/trace.d | 79 +++++++++++++++++++++++++++++------------ 1 file changed, 57 insertions(+), 22 deletions(-) diff --git a/druntime/src/rt/trace.d b/druntime/src/rt/trace.d index d4a0d38ca57a..516e32babf36 100644 --- a/druntime/src/rt/trace.d +++ b/druntime/src/rt/trace.d @@ -122,11 +122,48 @@ struct Symbol enum ubyte SFvisited = 1; // visited -struct SymbolCacheEntry +version (D_LP64) { - const(char)* ptr; - size_t length; - Symbol* sym; + struct SymbolCacheEntry + { + private: + ulong _packed; + uint _rest; + public: + uint length; + + pragma(inline, true): + @property const(char)* ptr() const + { + return cast(const(char)*)(_packed & 0xFFFFFFFFFFFF); + } + + @property void ptr(const(char)* p) + { + _packed = (_packed & 0xFFFF000000000000) | (cast(ulong)p & 0xFFFFFFFFFFFF); + } + + @property Symbol* sym() const + { + return cast(Symbol*)(((_packed >> 48) & 0xFFFF) << 32 | _rest); + } + + @property void sym(Symbol* s) + { + auto v = cast(ulong)s; + _packed = (_packed & 0xFFFFFFFFFFFF) | ((v >> 32) & 0xFFFF) << 48; + _rest = cast(uint)(v & 0xFFFFFFFF); + } + } +} +else +{ + struct SymbolCacheEntry + { + const(char)* ptr; + uint length; + Symbol* sym; + } } ////////////////////////////////// @@ -643,23 +680,6 @@ private void trace_sympair_add(SymPair** psp, Symbol* s, ulong count) sp.count += count; } -private Symbol* trace_findsym(const(char)[] id) -{ - enum cacheMask = trace_cache.length - 1; - static assert((trace_cache.length & cacheMask) == 0); - - const idx = (cast(size_t) id.ptr >> 4) & cacheMask; - auto entry = &trace_cache[idx]; - if (entry.ptr == id.ptr && entry.length == id.length) - return entry.sym; - - auto s = trace_addsym(&root, id); - entry.ptr = id.ptr; - entry.length = id.length; - entry.sym = s; - return s; -} - ////////////////////////////////////////////// // This one is called by DMD @@ -679,7 +699,22 @@ private extern(C) void trace_pro(const(char)[] id) if (id.length == 0) return; auto tos = stack_push(); - auto s = trace_findsym(id); + + enum cacheMask = trace_cache.length - 1; + static assert((trace_cache.length & cacheMask) == 0); + const cacheIdx = (cast(size_t) id.ptr >> 4) & cacheMask; + auto centry = &trace_cache[cacheIdx]; + Symbol* s; + if (centry.ptr == id.ptr && centry.length == id.length) + s = centry.sym; + else + { + s = trace_addsym(&root, id); + centry.ptr = id.ptr; + centry.length = cast(uint)id.length; + centry.sym = s; + } + tos.sym = s; if (tos.prev) {