Optimise the code generated at trace points
authorSimon Marlow <marlowsd@gmail.com>
Sat, 12 Sep 2009 21:35:04 +0000 (21:35 +0000)
committerSimon Marlow <marlowsd@gmail.com>
Sat, 12 Sep 2009 21:35:04 +0000 (21:35 +0000)
includes/Rts.h
rts/Trace.c
rts/Trace.h
rts/sm/GC.c

index 753a664..1bfb37a 100644 (file)
@@ -65,6 +65,12 @@ extern "C" {
 #define END_RTS_PRIVATE   /* disabled: END_RTS_PRIVATE */
 #endif
 
+#if __GNUC__ > 4
+#define RTS_UNLIKELY(p) __builtin_expect((p),0)
+#else
+#define RTS_UNLIKELY(p) p
+#endif
+
 /* Fix for mingw stat problem (done here so it's early enough) */
 #ifdef mingw32_HOST_OS
 #define __MSVCRT__ 1
index 7194651..20debdc 100644 (file)
 #include "Threads.h"
 #include "Printer.h"
 
-StgWord32 classes_enabled; // not static due to inline funcs
+// debugging flags, set with +RTS -D<something>
+int DEBUG_sched;
+int DEBUG_interp;
+int DEBUG_weak;
+int DEBUG_gccafs;
+int DEBUG_gc;
+int DEBUG_block_alloc;
+int DEBUG_sanity;
+int DEBUG_stable;
+int DEBUG_stm;
+int DEBUG_prof;
+int DEBUG_gran;
+int DEBUG_par;
+int DEBUG_linker;
+int DEBUG_squeeze;
+int DEBUG_hpc;
+int DEBUG_sparks;
+
+// events
+int TRACE_sched;
 
 #ifdef THREADED_RTS
 static Mutex trace_utx;
@@ -37,7 +56,7 @@ void initTracing (void)
 
 #ifdef DEBUG
 #define DEBUG_FLAG(name, class) \
-    if (RtsFlags.DebugFlags.name) classes_enabled |= class;
+    class = RtsFlags.DebugFlags.name ? 1 : 0;
 
     DEBUG_FLAG(scheduler,    DEBUG_sched);
     DEBUG_FLAG(scheduler,    TRACE_sched); // -Ds enabled all sched events
@@ -58,7 +77,7 @@ void initTracing (void)
 #endif
 
 #define TRACE_FLAG(name, class) \
-    if (RtsFlags.TraceFlags.name) classes_enabled |= class;
+    class = RtsFlags.TraceFlags.name ? 1 : 0;
 
     TRACE_FLAG(scheduler, TRACE_sched);
 
@@ -200,8 +219,11 @@ static void traceCap_stderr(Capability *cap, char *msg, va_list ap)
 }
 #endif
 
-void traceCap_(Capability *cap, char *msg, va_list ap)
+void traceCap_(Capability *cap, char *msg, ...)
 {
+    va_list ap;
+    va_start(ap,msg);
+    
 #ifdef DEBUG
     if (RtsFlags.TraceFlags.trace_stderr) {
         traceCap_stderr(cap, msg, ap);
@@ -210,6 +232,8 @@ void traceCap_(Capability *cap, char *msg, va_list ap)
     {
         postCapMsg(cap, msg, ap);
     }
+
+    va_end(ap);
 }
 
 #ifdef DEBUG
@@ -225,8 +249,11 @@ static void trace_stderr(char *msg, va_list ap)
 }
 #endif
 
-void trace_(char *msg, va_list ap)
+void trace_(char *msg, ...)
 {
+    va_list ap;
+    va_start(ap,msg);
+
 #ifdef DEBUG
     if (RtsFlags.TraceFlags.trace_stderr) {
         trace_stderr(msg, ap);
@@ -235,6 +262,8 @@ void trace_(char *msg, va_list ap)
     {
         postMsg(msg, ap);
     }
+
+    va_end(ap);
 }
 
 void traceThreadStatus_ (StgTSO *tso USED_IF_DEBUG)
index 702a51e..775f235 100644 (file)
 BEGIN_RTS_PRIVATE
 
 // -----------------------------------------------------------------------------
-// Posting events
-// -----------------------------------------------------------------------------
-
-INLINE_HEADER void trace (StgWord32 class, char *msg, ...);
-
-#ifdef DEBUG
-INLINE_HEADER void debugTrace (StgWord32 class, char *msg, ...);
-#endif
-
-INLINE_HEADER void traceSchedEvent (Capability *cap, EventTypeNum tag, 
-                                    StgTSO *tso, StgWord64 other);
-
-INLINE_HEADER void traceCap (StgWord32 class, Capability *cap,
-                             char *msg, ...);
-
-INLINE_HEADER void traceThreadStatus (StgWord32 class, StgTSO *tso);
-
-INLINE_HEADER rtsBool traceClass (StgWord32 class);
-
-#ifdef DEBUG
-void traceBegin (const char *str, ...);
-void traceEnd (void);
-#endif
-
-// -----------------------------------------------------------------------------
 // EventLog API
 // -----------------------------------------------------------------------------
 
@@ -52,137 +27,111 @@ void freeTracing (void);
 #endif /* TRACING */
 
 // -----------------------------------------------------------------------------
-// Message classes, these may be OR-ed together
+// Message classes
 // -----------------------------------------------------------------------------
 
 // debugging flags, set with +RTS -D<something>
-#define DEBUG_sched               (1<<0)
-#define DEBUG_interp              (1<<1)
-#define DEBUG_weak                (1<<2)
-#define DEBUG_gccafs              (1<<3) 
-#define DEBUG_gc                  (1<<4) 
-#define DEBUG_block_alloc         (1<<5) 
-#define DEBUG_sanity              (1<<6) 
-#define DEBUG_stable              (1<<7) 
-#define DEBUG_stm                 (1<<8) 
-#define DEBUG_prof                (1<<9) 
-#define DEBUG_gran                (1<<10)
-#define DEBUG_par                 (1<<11)
-#define DEBUG_linker              (1<<12)
-#define DEBUG_squeeze              (1<<13)
-#define DEBUG_hpc                  (1<<14)
-#define DEBUG_sparks              (1<<15)
+extern int DEBUG_sched;
+extern int DEBUG_interp;
+extern int DEBUG_weak;
+extern int DEBUG_gccafs;
+extern int DEBUG_gc;
+extern int DEBUG_block_alloc;
+extern int DEBUG_sanity;
+extern int DEBUG_stable;
+extern int DEBUG_stm;
+extern int DEBUG_prof;
+extern int DEBUG_gran;
+extern int DEBUG_par;
+extern int DEBUG_linker;
+extern int DEBUG_squeeze;
+extern int DEBUG_hpc;
+extern int DEBUG_sparks;
 
 // events
-#define TRACE_sched                (1<<16)
+extern int TRACE_sched;
 
 // -----------------------------------------------------------------------------
-// PRIVATE below here
+// Posting events
+//
+// We use macros rather than inline functions deliberately.  We want
+// the not-taken case to be as efficient as possible, a simple
+// test-and-jump, and with inline functions gcc seemed to move some of
+// the instructions from the branch up before the test.
+// 
 // -----------------------------------------------------------------------------
 
-#ifdef TRACING
+#ifdef DEBUG
+void traceBegin (const char *str, ...);
+void traceEnd (void);
+#endif
 
-extern StgWord32 classes_enabled;
+#ifdef TRACING
 
-INLINE_HEADER rtsBool traceClass (StgWord32 class) 
-{ return (classes_enabled & class); }
+/* 
+ * Record a scheduler event
+ */
+#define traceSchedEvent(cap, tag, tso, other)   \
+    if (RTS_UNLIKELY(TRACE_sched)) {            \
+        traceSchedEvent_(cap, tag, tso, other); \
+    }
 
 void traceSchedEvent_ (Capability *cap, EventTypeNum tag, 
                        StgTSO *tso, StgWord64 other);
 
+// variadic macros are C99, and supported by gcc.  However, the
+// ##__VA_ARGS syntax is a gcc extension, which allows the variable
+// argument list to be empty (see gcc docs for details).
+
 /* 
- * Trace an event to the capability's event buffer.
+ * Emit a trace message on a particular Capability
  */
-INLINE_HEADER void traceSchedEvent(Capability *cap, EventTypeNum tag, 
-                                   StgTSO *tso, StgWord64 other)
-{
-    if (traceClass(TRACE_sched)) {
-        traceSchedEvent_(cap, tag, tso, other);
+#define traceCap(class, cap, msg, ...)          \
+    if (RTS_UNLIKELY(class)) {                  \
+        traceCap_(cap, msg, ##__VA_ARGS__);     \
     }
-}
 
-void traceCap_(Capability *cap, char *msg, va_list ap);
+void traceCap_(Capability *cap, char *msg, ...);
 
 /* 
- * Trace a log message
+ * Emit a trace message
  */
-INLINE_HEADER void traceCap (StgWord32 class, Capability *cap, char *msg, ...)
-{
-    va_list ap;
-    va_start(ap,msg);
-    if (traceClass(class)) {
-        traceCap_(cap, msg, ap);
+#define trace(class, msg, ...)                  \
+    if (RTS_UNLIKELY(class)) {                  \
+        trace_(msg, ##__VA_ARGS__);             \
     }
-    va_end(ap);
-}
 
-void trace_(char *msg, va_list ap);
+void trace_(char *msg, ...);
 
 /* 
- * Trace a log message
+ * Emit a debug message (only when DEBUG is defined)
  */
-INLINE_HEADER void trace (StgWord32 class, char *msg, ...)
-{
-    va_list ap;
-    va_start(ap,msg);
-    if (traceClass(class)) {
-        trace_(msg, ap);
-    }
-    va_end(ap);
-}
-
 #ifdef DEBUG
-INLINE_HEADER void debugTrace (StgWord32 class, char *msg, ...)
-{
-    va_list ap;
-    va_start(ap,msg);
-    if (traceClass(class)) {
-        trace_(msg, ap);
+#define debugTrace(class, msg, ...)             \
+    if (RTS_UNLIKELY(class)) {                  \
+        trace_(msg, ##__VA_ARGS__);             \
     }
-    va_end(ap);
-}
 #else
-
 #define debugTrace(class, str, ...) /* nothing */
-// variable arg macros are C99, and supported by gcc.
-
 #endif
 
-void traceThreadStatus_ (StgTSO *tso);
-
-INLINE_HEADER void traceThreadStatus (StgWord32 class, StgTSO *tso)
-{
-    if (traceClass(class)) {
-        traceThreadStatus_(tso);
+/* 
+ * Emit a message/event describing the state of a thread
+ */
+#define traceThreadStatus(class, tso)           \
+    if (RTS_UNLIKELY(class)) {                  \
+        traceThreadStatus_(tso);                \
     }
-}    
-
-#else /* !TRACING */
 
-INLINE_HEADER rtsBool traceClass (StgWord32 class STG_UNUSED) 
-{ return rtsFalse; }
-
-INLINE_HEADER void traceSchedEvent (Capability *cap STG_UNUSED,
-                                    EventTypeNum tag STG_UNUSED, 
-                                    StgTSO *tso STG_UNUSED,
-                                    StgWord64 other STG_UNUSED)
-{ /* nothing */ }
-
-INLINE_HEADER void traceCap (StgWord32 class STG_UNUSED,
-                             Capability *cap STG_UNUSED,
-                             char *msg STG_UNUSED, ...)
-{ /* nothing */ }
+void traceThreadStatus_ (StgTSO *tso);
 
-INLINE_HEADER void trace (StgWord32 class STG_UNUSED, 
-                          char *msg STG_UNUSED, ...)
-{ /* nothing */ }
+#else /* !TRACING */
 
+#define traceSchedEvent(cap, tag, tso, other) /* nothing */
+#define traceCap(class, cap, msg, ...) /* nothing */
+#define trace(class, msg, ...) /* nothing */
 #define debugTrace(class, str, ...) /* nothing */
-// variable arg macros are C99, and supported by gcc.
-
-INLINE_HEADER void traceThreadStatus (StgWord32 class STG_UNUSED, 
-                                      StgTSO *tso STG_UNUSED)
-{ /* nothing */ }
+#define traceThreadStatus(class, tso) /* nothing */
 
 #endif /* TRACING */
 
index 6f15a47..97acc38 100644 (file)
@@ -279,7 +279,7 @@ GarbageCollect (rtsBool force_major_gc,
 
 #ifdef DEBUG
   // check for memory leaks if DEBUG is on 
-  memInventory(traceClass(DEBUG_gc));
+  memInventory(DEBUG_gc);
 #endif
 
   // check stack sanity *before* GC
@@ -782,7 +782,7 @@ SET_GCT(gc_threads[0]);
 
 #ifdef DEBUG
   // check for memory leaks if DEBUG is on 
-  memInventory(traceClass(DEBUG_gc));
+  memInventory(DEBUG_gc);
 #endif
 
 #ifdef RTS_GTK_FRONTPANEL