Avoid to record execontext used for origin tracking when --trac-origins=no
All calls to VG_(unknown_SP_update) were recording an execontext
of one IP, useful only for track origin.
This patch implements splits VG_(unknown_SP_update) 
in two different functions VG_(unknown_SP_update_w_ECU)
(doing origin tracking) and VG_(unknown_SP_update)  (not doing origin tracking).




git-svn-id: svn://svn.valgrind.org/valgrind/trunk@13225 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/m_scheduler/scheduler.c b/coregrind/m_scheduler/scheduler.c
index b3941f2..248dc35 100644
--- a/coregrind/m_scheduler/scheduler.c
+++ b/coregrind/m_scheduler/scheduler.c
@@ -285,7 +285,10 @@
    VG_(running_tid) = tid;
 
    { Addr gsp = VG_(get_SP)(tid);
-     VG_(unknown_SP_update)(gsp, gsp, 0/*unknown origin*/);
+      if (NULL != VG_(tdict).track_new_mem_stack_w_ECU)
+         VG_(unknown_SP_update_w_ECU)(gsp, gsp, 0/*unknown origin*/);
+      else
+         VG_(unknown_SP_update)(gsp, gsp);
    }
 
    if (VG_(clo_trace_sched)) {
diff --git a/coregrind/m_stacks.c b/coregrind/m_stacks.c
index 000aaa9..60c31ac 100644
--- a/coregrind/m_stacks.c
+++ b/coregrind/m_stacks.c
@@ -268,59 +268,97 @@
    }
 }
 
-/* This function gets called if new_mem_stack and/or die_mem_stack are
+
+/* complaints_stack_switch reports that SP has changed by more than some
+   threshold amount (by default, 2MB).  We take this to mean that the
+   application is switching to a new stack, for whatever reason.
+   
+   JRS 20021001: following discussions with John Regehr, if a stack
+   switch happens, it seems best not to mess at all with memory
+   permissions.  Seems to work well with Netscape 4.X.  Really the
+   only remaining difficulty is knowing exactly when a stack switch is
+   happening. */
+__attribute__((noinline))
+static void complaints_stack_switch (Addr old_SP, Addr new_SP)
+{
+   static Int complaints = 3;
+   if (VG_(clo_verbosity) > 0 && complaints > 0 && !VG_(clo_xml)) {
+      Word delta  = (Word)new_SP - (Word)old_SP;
+      complaints--;
+      VG_(message)(Vg_UserMsg,
+                   "Warning: client switching stacks?  "
+                   "SP change: 0x%lx --> 0x%lx\n", old_SP, new_SP);
+      VG_(message)(Vg_UserMsg,
+                   "         to suppress, use: --max-stackframe=%ld "
+                   "or greater\n",
+                   (delta < 0 ? -delta : delta));
+      if (complaints == 0)
+         VG_(message)(Vg_UserMsg,
+                      "         further instances of this message "
+                      "will not be shown.\n");
+   }
+}
+
+/* The functions VG_(unknown_SP_update) and VG_(unknown_SP_update_w_ECU)
+   get called if new_mem_stack and/or die_mem_stack are
    tracked by the tool, and one of the specialised cases
    (eg. new_mem_stack_4) isn't used in preference.  
-*/
+
+   These functions are performance critical, so are built with macros. */
+
+// preamble + check if stack has switched.
+#define IF_STACK_SWITCH_SET_current_task_AND_RETURN                     \
+   Word delta  = (Word)new_SP - (Word)old_SP;                           \
+                                                                        \
+   /* Check if the stack pointer is still in the same stack as before. */ \
+   if (UNLIKELY(current_stack == NULL ||                                \
+      new_SP < current_stack->start || new_SP > current_stack->end)) {  \
+      Stack* new_stack = find_stack_by_addr(new_SP);                    \
+      if (new_stack                                                     \
+          && (current_stack == NULL || new_stack->id != current_stack->id)) { \
+         /* The stack pointer is now in another stack.  Update the current */ \
+         /* stack information and return without doing anything else. */ \
+         current_stack = new_stack;                                     \
+         return;                                                        \
+      }                                                                 \
+   }
+
+#define IF_BIG_DELTA_complaints_AND_RETURN                              \
+   if (UNLIKELY(delta < -VG_(clo_max_stackframe)                        \
+                || VG_(clo_max_stackframe) < delta)) {                  \
+      complaints_stack_switch(old_SP, new_SP);                          \
+      return;                                                           \
+   }
+
+#define IF_SMALLER_STACK_die_mem_stack_AND_RETURN                       \
+   if (delta > 0) {                                                     \
+      VG_TRACK( die_mem_stack, old_SP,  delta );                        \
+      return;                                                           \
+   }
+
+  
 VG_REGPARM(3)
-void VG_(unknown_SP_update)( Addr old_SP, Addr new_SP, UInt ecu )
-{
-   static Int moans = 3;
-   Word delta  = (Word)new_SP - (Word)old_SP;
-
-   /* Check if the stack pointer is still in the same stack as before. */
-   if (current_stack == NULL ||
-       new_SP < current_stack->start || new_SP > current_stack->end) {
-      Stack* new_stack = find_stack_by_addr(new_SP);
-      if (new_stack 
-          && (current_stack == NULL || new_stack->id != current_stack->id)) { 
-         /* The stack pointer is now in another stack.  Update the current
-            stack information and return without doing anything else. */
-         current_stack = new_stack;
-         return;
-      }
-   }
-
-   if (delta < -VG_(clo_max_stackframe) || VG_(clo_max_stackframe) < delta) {
-      /* SP has changed by more than some threshold amount (by
-         default, 2MB).  We take this to mean that the application is
-         switching to a new stack, for whatever reason.
-       
-         JRS 20021001: following discussions with John Regehr, if a stack
-         switch happens, it seems best not to mess at all with memory
-         permissions.  Seems to work well with Netscape 4.X.  Really the
-         only remaining difficulty is knowing exactly when a stack switch is
-         happening. */
-      if (VG_(clo_verbosity) > 0 && moans > 0 && !VG_(clo_xml)) {
-         moans--;
-         VG_(message)(Vg_UserMsg,
-            "Warning: client switching stacks?  "
-            "SP change: 0x%lx --> 0x%lx\n", old_SP, new_SP);
-         VG_(message)(Vg_UserMsg,
-            "         to suppress, use: --max-stackframe=%ld or greater\n",
-            (delta < 0 ? -delta : delta));
-         if (moans == 0)
-            VG_(message)(Vg_UserMsg,
-                "         further instances of this message "
-                "will not be shown.\n");
-      }
-   } else if (delta < 0) {
+void VG_(unknown_SP_update_w_ECU)( Addr old_SP, Addr new_SP, UInt ecu ) {
+   IF_STACK_SWITCH_SET_current_task_AND_RETURN;
+   IF_BIG_DELTA_complaints_AND_RETURN;
+   IF_SMALLER_STACK_die_mem_stack_AND_RETURN;
+   if (delta < 0) { // IF_BIGGER_STACK
       VG_TRACK( new_mem_stack_w_ECU, new_SP, -delta, ecu );
-      VG_TRACK( new_mem_stack,       new_SP, -delta );
-
-   } else if (delta > 0) {
-      VG_TRACK( die_mem_stack, old_SP,  delta );
+      return;
    }
+   // SAME_STACK. nothing to do.
+}
+
+VG_REGPARM(2)
+void VG_(unknown_SP_update)( Addr old_SP, Addr new_SP ) {
+   IF_STACK_SWITCH_SET_current_task_AND_RETURN;
+   IF_BIG_DELTA_complaints_AND_RETURN;
+   IF_SMALLER_STACK_die_mem_stack_AND_RETURN;
+   if (delta < 0) { // IF_BIGGER_STACK
+      VG_TRACK( new_mem_stack,      new_SP, -delta );
+      return;
+   }
+   // SAME_STACK. nothing to do.
 }
 
 /*--------------------------------------------------------------------*/
diff --git a/coregrind/m_translate.c b/coregrind/m_translate.c
index fbc5c8c..6f8eeef 100644
--- a/coregrind/m_translate.c
+++ b/coregrind/m_translate.c
@@ -45,7 +45,7 @@
 #include "pub_core_redir.h"      // VG_(redir_do_lookup)
 
 #include "pub_core_signals.h"    // VG_(synth_fault_{perms,mapping}
-#include "pub_core_stacks.h"     // VG_(unknown_SP_update)()
+#include "pub_core_stacks.h"     // VG_(unknown_SP_update*)()
 #include "pub_core_tooliface.h"  // VG_(tdict)
 
 #include "pub_core_translate.h"
@@ -524,16 +524,25 @@
          /* Now we know what the old value of SP is.  But knowing the new
             value is a bit tricky if there is a partial write. */
          if (first_Put == first_SP && last_Put == last_SP) {
-           /* The common case, an exact write to SP.  So st->Ist.Put.data
-              does hold the new value; simple. */
+            /* The common case, an exact write to SP.  So st->Ist.Put.data
+               does hold the new value; simple. */
             vg_assert(curr_IP_known);
-            dcall = unsafeIRDirty_0_N( 
-                       3/*regparms*/, 
-                       "VG_(unknown_SP_update)", 
-                       VG_(fnptr_to_fnentry)( &VG_(unknown_SP_update) ),
-                       mkIRExprVec_3( IRExpr_RdTmp(old_SP), st->Ist.Put.data,
-                                      mk_ecu_Expr(curr_IP) ) 
-                    );
+            if (NULL != VG_(tdict).track_new_mem_stack_w_ECU)
+               dcall = unsafeIRDirty_0_N( 
+                          3/*regparms*/, 
+                          "VG_(unknown_SP_update_w_ECU)", 
+                          VG_(fnptr_to_fnentry)( &VG_(unknown_SP_update_w_ECU) ),
+                          mkIRExprVec_3( IRExpr_RdTmp(old_SP), st->Ist.Put.data,
+                                         mk_ecu_Expr(curr_IP) ) 
+                       );
+            else
+               dcall = unsafeIRDirty_0_N( 
+                          2/*regparms*/, 
+                          "VG_(unknown_SP_update)", 
+                          VG_(fnptr_to_fnentry)( &VG_(unknown_SP_update) ),
+                          mkIRExprVec_2( IRExpr_RdTmp(old_SP), st->Ist.Put.data )
+                       );
+
             addStmtToIRSB( bb, IRStmt_Dirty(dcall) );
             /* don't forget the original assignment */
             addStmtToIRSB( bb, st );
@@ -562,14 +571,23 @@
             addStmtToIRSB( bb, IRStmt_Put(offset_SP, IRExpr_RdTmp(old_SP) ));
             /* 4 */
             vg_assert(curr_IP_known);
-            dcall = unsafeIRDirty_0_N( 
-                       3/*regparms*/, 
-                       "VG_(unknown_SP_update)", 
-                       VG_(fnptr_to_fnentry)( &VG_(unknown_SP_update) ),
-                       mkIRExprVec_3( IRExpr_RdTmp(old_SP),
-                                      IRExpr_RdTmp(new_SP), 
-                                      mk_ecu_Expr(curr_IP) )
-                    );
+            if (NULL != VG_(tdict).track_new_mem_stack_w_ECU)
+               dcall = unsafeIRDirty_0_N( 
+                          3/*regparms*/, 
+                          "VG_(unknown_SP_update_w_ECU)", 
+                          VG_(fnptr_to_fnentry)( &VG_(unknown_SP_update_w_ECU) ),
+                          mkIRExprVec_3( IRExpr_RdTmp(old_SP),
+                                         IRExpr_RdTmp(new_SP), 
+                                         mk_ecu_Expr(curr_IP) )
+                       );
+            else
+               dcall = unsafeIRDirty_0_N( 
+                          2/*regparms*/, 
+                          "VG_(unknown_SP_update)", 
+                          VG_(fnptr_to_fnentry)( &VG_(unknown_SP_update) ),
+                          mkIRExprVec_2( IRExpr_RdTmp(old_SP),
+                                         IRExpr_RdTmp(new_SP) )
+                       );
             addStmtToIRSB( bb, IRStmt_Dirty(dcall) );
             /* 5 */
             addStmtToIRSB( bb, IRStmt_Put(offset_SP, IRExpr_RdTmp(new_SP) ));
diff --git a/coregrind/pub_core_stacks.h b/coregrind/pub_core_stacks.h
index eefd8a5..0a05b50 100644
--- a/coregrind/pub_core_stacks.h
+++ b/coregrind/pub_core_stacks.h
@@ -42,7 +42,10 @@
 extern void  VG_(stack_limits)     ( Addr SP, Addr *start, Addr *end );
 
 extern VG_REGPARM(3)
-       void VG_(unknown_SP_update) ( Addr old_SP, Addr new_SP, UInt otag );
+       void VG_(unknown_SP_update_w_ECU)
+                                   ( Addr old_SP, Addr new_SP, UInt ecu );
+extern VG_REGPARM(2)
+       void VG_(unknown_SP_update) ( Addr old_SP, Addr new_SP );
 
 #endif   // __PUB_CORE_STACKS_H