File 1052-erts-Optimize-the-normal-case-where-ErtsTracer-is-a-.patch of Package erlang

From 41421193d7e3c9093368bab040a1a4ca1cf2f3dc Mon Sep 17 00:00:00 2001
From: Sverker Eriksson <sverker@erlang.org>
Date: Wed, 10 Jul 2024 19:53:26 +0200
Subject: [PATCH 2/6] erts: Optimize the normal case where ErtsTracer is a
 local pid

Instead of [erl_tracer | pid] just store the pid.
---
 erts/emulator/beam/erl_ptab.h  |  4 ++--
 erts/emulator/beam/erl_trace.c | 24 ++++++++++++++++++------
 erts/emulator/beam/erl_trace.h |  1 +
 erts/emulator/beam/sys.h       |  5 +++--
 4 files changed, 24 insertions(+), 10 deletions(-)

diff --git a/erts/emulator/beam/erl_ptab.h b/erts/emulator/beam/erl_ptab.h
index d5e5da8181..8753ae9365 100644
--- a/erts/emulator/beam/erl_ptab.h
+++ b/erts/emulator/beam/erl_ptab.h
@@ -49,8 +49,8 @@ typedef struct ErtsTracee_ {
     ErtsTracerRef *first_ref;
 } ErtsTracee;
 
-#define ERTS_TRACER_MODULE(T) 	(CAR(list_val(T)))
-#define ERTS_TRACER_STATE(T) 	(CDR(list_val(T)))
+#define ERTS_TRACER_MODULE(T) 	(is_internal_pid(T) ? am_erl_tracer : CAR(list_val(T)))
+#define ERTS_TRACER_STATE(T) 	(is_internal_pid(T) ? T : CDR(list_val(T)))
 
 #define ERTS_P_LINKS(P)		((P)->common.u.alive.links)
 #define ERTS_P_MONITORS(P)	((P)->common.u.alive.monitors)
diff --git a/erts/emulator/beam/erl_trace.c b/erts/emulator/beam/erl_trace.c
index 649fe15ffb..4680c5d516 100644
--- a/erts/emulator/beam/erl_trace.c
+++ b/erts/emulator/beam/erl_trace.c
@@ -2810,7 +2810,11 @@ erts_term_to_tracer(Eterm prefix, Eterm t)
 {
     ErtsTracer tracer = erts_tracer_nil;
     ASSERT(is_atom(prefix) || prefix == THE_NON_VALUE);
-    if (!is_nil(t)) {
+
+    if (is_internal_pid(t)) {
+        tracer = t;
+    }
+    else if (!is_nil(t)) {
         Eterm module = am_erl_tracer, state = THE_NON_VALUE;
         Eterm hp[2];
         if (is_tuple(t)) {
@@ -3152,7 +3156,7 @@ static void free_tracer(void *p)
 }
 
 /*
- * ErtsTracer is either NIL, 'true' or [Mod | State]
+ * ErtsTracer is either NIL, 'true', local pid or [Mod | State]
  *
  * - If State is immediate then the memory for
  *   the cons cell is just two words + sizeof(ErtsThrPrgrLaterOp) large.
@@ -3177,15 +3181,15 @@ static void free_tracer(void *p)
  * the refc when *tracer is NIL.
  */
 void
-erts_tracer_update_impl(ErtsTracer *tracer, const ErtsTracer new_tracer)
+erts_tracer_update_impl(ErtsTracer *tracer, ErtsTracer new_tracer)
 {
     ErlHeapFragment *hf;
 
-    if (is_not_nil(*tracer)) {
+    if (is_list(*tracer)) {
         Uint offs = 2;
         UWord size = 2 * sizeof(Eterm) + sizeof(ErtsThrPrgrLaterOp);
         ErtsThrPrgrLaterOp *lop;
-        ASSERT(is_list(*tracer));
+
         if (is_not_immed(ERTS_TRACER_STATE(*tracer))) {
             hf = ErtsContainerStruct_(ptr_val(*tracer), ErlHeapFragment, mem);
             offs = hf->used_size;
@@ -3212,7 +3216,15 @@ erts_tracer_update_impl(ErtsTracer *tracer, const ErtsTracer new_tracer)
             free_tracer, (void*)(*tracer), lop, size);
     }
 
-    if (is_nil(new_tracer)) {
+    if (is_list(new_tracer)) {
+        const Eterm module = ERTS_TRACER_MODULE(new_tracer);
+        const Eterm state = ERTS_TRACER_STATE(new_tracer);
+        if (module == am_erl_tracer && is_internal_pid(state)) {
+            new_tracer = state;
+        }
+    }
+    if (is_immed(new_tracer)) {
+        ASSERT(is_nil(new_tracer) || is_internal_pid(new_tracer));
         *tracer = new_tracer;
     } else if (is_immed(ERTS_TRACER_STATE(new_tracer))) {
         /* If tracer state is an immediate we only allocate a 2 Eterm heap.
diff --git a/erts/emulator/beam/erl_trace.h b/erts/emulator/beam/erl_trace.h
index 90a5d2b5e7..0d261b0013 100644
--- a/erts/emulator/beam/erl_trace.h
+++ b/erts/emulator/beam/erl_trace.h
@@ -293,6 +293,7 @@ ERTS_DECLARE_DUMMY(erts_tracer_nil) = NIL;
 #define IS_TRACER_VALID(tracer)                                         \
     (ERTS_TRACER_COMPARE(tracer,erts_tracer_true)                       \
      || ERTS_TRACER_IS_NIL(tracer)                                      \
+     || is_internal_pid(tracer)                                         \
      || (is_list(tracer) && is_atom(CAR(list_val(tracer)))))
 
 #define ERTS_TRACER_FROM_ETERM(termp) \
diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h
index f90b9bfe66..45aebd7e68 100644
--- a/erts/emulator/beam/sys.h
+++ b/erts/emulator/beam/sys.h
@@ -701,12 +701,13 @@ typedef struct preload {
 } Preload;
 
 /*
- * ErtsTracer is either NIL, 'true' or [Mod | State]
+ * ErtsTracer is either NIL, 'true', LocalPid or [Mod | State]
  *
  * If set to NIL, it means no tracer.
  * If set to 'true' it means the current process' tracer.
  * If set to [Mod | State], there is a tracer.
- *  See erts_tracer_update for more details
+ * LocalPid is the optimized form of the common case [erl_tracer | LocalPid].
+ *  See erts_tracer_update_impl for more details
  */
 typedef Eterm ErtsTracer;
 
-- 
2.43.0

openSUSE Build Service is sponsored by