Author: sewardj
Date: 2008-03-05 12:39:15 +0000 (Wed, 05 Mar 2008)
New Revision: 7570

Log:
Split memory_state_machine() into msm_handle_read() and
msm_handle_write(), as it's pointless to keep interpreting "is_w".
This folds out quite a few branches and improves performance of
sequential code fragments by up to 15-20%.




Modified:
   branches/HGDEV/helgrind/hg_main.c


Modified: branches/HGDEV/helgrind/hg_main.c
===================================================================
--- branches/HGDEV/helgrind/hg_main.c   2008-03-05 10:54:45 UTC (rev 7569)
+++ branches/HGDEV/helgrind/hg_main.c   2008-03-05 12:39:15 UTC (rev 7570)
@@ -3039,9 +3039,201 @@
 // TODO: handle state with one segment in segment set separately 
 // for better performance. 
 static 
-SVal memory_state_machine(Bool is_w, Thread* thr, Addr a, SVal sv_old, Int sz)
+SVal msm_handle_write(Thread* thr, Addr a, SVal sv_old, Int sz)
 {
    UWord      i;
+   Bool       was_w;
+   SegmentSet oldSS;
+   LockSet    oldLS;
+   Bool       hb_all     = False;
+   UWord      oldSS_size = 0;
+   Bool       is_race    = False;
+   SVal       sv_new     = SHVAL_Invalid;
+   Bool       do_trace   = clo_trace_level > 0 
+                           && a >= clo_trace_addr 
+                           && a < (clo_trace_addr+sz);
+   SegmentID  currS = thr->csegid;
+   SegmentSet newSS = 0;
+   LockSet    newLS = 0;
+
+   // current locks. 
+   LockSet    currLS = thr->locksetW;
+
+   if (UNLIKELY(is_SHVAL_Race(sv_old))) {
+      // we already reported a race, don't bother again. 
+      stats__msm_Race++;
+      sv_new = sv_old;
+      goto done;
+   }
+
+   if (UNLIKELY(__bus_lock_Lock->heldBy)
+       && (is_SHVAL_New(sv_old) || is_SHVAL_R(sv_old))) {
+      stats__msm_BHL_hack++;
+      // BHL is held and we are in 'Read' or 'New' state. 
+      // User is doing something very smart with LOCK prefix.
+      // Just ignore this memory location. 
+      sv_new = SHVAL_Race;
+
+      // VG_(printf)("Ignoring memory %p accessed with LOCK prefix at\n", a);
+      // VG_(get_and_pp_StackTrace)(map_threads_reverse_lookup_SLOW(thr), 5);
+
+      goto done; 
+      // TODO: a better scheme might be: 
+      // When we see a first write with BHL held we do: 
+      // - If we are in state 'Read' or 'New', change the state to 'BHL'. 
+      // - If we are in state 'Write', report a race.
+      //
+      // When we are in state BHL: 
+      // - Any read keeps us in state 'BHL'. 
+      // - Any write with BHL held keeps us in state 'BHL'. 
+      // - Any other write is a race.
+   }
+
+   tl_assert(is_sane_Thread(thr));
+
+   // Read or Write
+   if (LIKELY(is_SHVAL_RW(sv_old))) {
+      was_w = is_SHVAL_W(sv_old);
+      oldSS = get_SHVAL_SS(sv_old);
+      oldLS = get_SHVAL_LS(sv_old);
+
+      oldSS_size = SS_get_size(oldSS);
+      if (oldSS_size == 1) {
+         stats__msm_oldSS_single++;
+      } else {
+         tl_assert(oldSS_size > 1);
+         stats__msm_oldSS_multi++;
+      }
+
+      // update the segment set and compute hb_all
+      hb_all = True;
+      newSS = SS_mk_singleton(currS);
+      for (i = 0; i < oldSS_size; i++) {
+         SegmentID S = SS_get_element(oldSS, i);
+         Bool hb = False;
+         if (S == currS  // Same segment. 
+             || SEG_get(S)->thr == thr // Same thread. 
+             || happens_before(S, currS)) {
+                // different thread, but happens-before
+            hb = True;
+         }
+         if (do_trace) {
+            VG_(printf)("HB(S%d/T%d,cur)=%d\n",
+                        S, SEG_get(S)->thr->errmsg_index, hb);
+         }
+
+         if (!hb) {
+            hb_all = False;
+            // Not happened-before. Leave this segment in SS.
+            if (SS_is_singleton(newSS)) {
+               tl_assert(currS != S);
+               newSS = HG_(doubletonWS)(univ_ssets, currS, S);
+            } else {
+               newSS = HG_(addToWS)(univ_ssets, newSS, S);
+            }
+         }
+      } 
+
+      // update lock set. 
+      if (hb_all) {
+         newLS = currLS;
+      } else {
+         newLS = HG_(intersectWS)(univ_lsets, oldLS, currLS);
+      }
+
+      // update the state 
+
+      // generate new SVal
+      sv_new = mk_SHVAL_W(newSS, newLS);
+
+      is_race = !SS_is_singleton(newSS)
+                && HG_(isEmptyWS)(univ_lsets, newLS);
+
+      if (oldLS != newLS) { 
+         // if the lockset changed, remember when it happened
+         if (0) // FIXME.  Do we want this functionality?  If so,
+            // it can be very slow.
+            record_last_lock_lossage(a, oldLS, newLS);
+      }
+
+      if      ( (!was_w) ) stats__msm_R_to_W++;
+      else if ( (was_w)  ) stats__msm_W_to_W++;
+
+      goto done;
+   }
+
+   // New
+   if (is_SHVAL_New(sv_old)) {
+      stats__msm_New_to_W++; 
+      newSS = SS_mk_singleton(currS);
+      sv_new = mk_SHVAL_W(newSS, currLS);
+      goto done;
+   }
+
+   // NoAccess
+   if (is_SHVAL_NoAccess(sv_old)) {
+      // TODO: complain
+      stats__msm_wr_NoAccess++; 
+      sv_new = sv_old;
+      goto done;
+   }
+
+   /*NOTREACHED*/
+   tl_assert(0);
+
+  done:
+
+   if (do_trace) {
+      HChar buf[200];
+
+      VG_(printf)("RW-Locks held: ");
+      show_lockset(thr->locksetA);
+      VG_(printf)("\n");
+      if (thr->locksetA != thr->locksetW) {
+         VG_(printf)(" W-Locks held: ");
+         show_lockset(thr->locksetW);
+         VG_(printf)("\n");
+      }
+
+      if (__bus_lock_Lock->heldBy) {
+         VG_(printf)("BHL is held\n");
+      }
+
+      show_sval(buf, sizeof(buf), sv_new);
+      VG_(message)(Vg_UserMsg, "TRACE: %p S%d/T%d %c %llx %s", a, 
+                   (int)currS, thr->errmsg_index, 
+                   'w' , sv_new, buf);
+      if (clo_trace_level >= 2) {
+         ThreadId tid = map_threads_maybe_reverse_lookup_SLOW(thr);
+         if (tid != VG_INVALID_THREADID) {
+            VG_(get_and_pp_StackTrace)( tid, 15);
+         }
+      }
+   }
+
+   if (clo_trace_level > 0 && !do_trace) {
+      // if we are tracing something, don't report a race on anything else.
+      is_race = False;
+   }
+
+   // report the race if needed
+   if (is_race) {
+      // ok, now record the race. 
+      record_error_Race( thr, 
+                         a, True, sz, sv_old, sv_new,
+                         maybe_get_lastlock_initpoint(a) );
+      // put this in Race state
+      sv_new = SHVAL_Race;
+   }
+
+   return sv_new; 
+}
+
+
+static 
+SVal msm_handle_read(Thread* thr, Addr a, SVal sv_old, Int sz)
+{
+   UWord      i;
    Bool       was_w, now_w;
    SegmentSet oldSS;
    LockSet    oldLS;
@@ -3057,8 +3249,7 @@
    LockSet    newLS = 0;
 
    // current locks. 
-   LockSet    currLS = is_w ? thr->locksetW
-                            : thr->locksetA;
+   LockSet    currLS = thr->locksetA;
 
    if (UNLIKELY(is_SHVAL_Race(sv_old))) {
       // we already reported a race, don't bother again. 
@@ -3143,7 +3334,7 @@
       }
 
       // update the state 
-      now_w = is_w || (was_w && !hb_all);
+      now_w = was_w && !hb_all;
 
       // generate new SVal
       sv_new = mk_SHVAL_RW(now_w, newSS, newLS);
@@ -3168,18 +3359,16 @@
 
    // New
    if (is_SHVAL_New(sv_old)) {
-      if (is_w) stats__msm_New_to_W++; 
-           else stats__msm_New_to_R++;
+      stats__msm_New_to_R++;
       newSS = SS_mk_singleton(currS);
-      sv_new = mk_SHVAL_RW(is_w, newSS, currLS);
+      sv_new = mk_SHVAL_R(newSS, currLS);
       goto done;
    }
 
    // NoAccess
    if (is_SHVAL_NoAccess(sv_old)) {
       // TODO: complain
-      if (is_w) stats__msm_wr_NoAccess++; 
-           else stats__msm_rd_NoAccess++;
+      stats__msm_rd_NoAccess++;
       sv_new = sv_old;
       goto done;
    }
@@ -3208,7 +3397,7 @@
       show_sval(buf, sizeof(buf), sv_new);
       VG_(message)(Vg_UserMsg, "TRACE: %p S%d/T%d %c %llx %s", a, 
                    (int)currS, thr->errmsg_index, 
-                   is_w ? 'w' : 'r', sv_new, buf);
+                   'r', sv_new, buf);
       if (clo_trace_level >= 2) {
          ThreadId tid = map_threads_maybe_reverse_lookup_SLOW(thr);
          if (tid != VG_INVALID_THREADID) {
@@ -3226,7 +3415,7 @@
    if (is_race) {
       // ok, now record the race. 
       record_error_Race( thr, 
-                         a, is_w, sz, sv_old, sv_new,
+                         a, False, sz, sv_old, sv_new,
                          maybe_get_lastlock_initpoint(a) );
       // put this in Race state
       sv_new = SHVAL_Race;
@@ -3236,8 +3425,6 @@
 }
 
 
-
-
 /*----------------------------------------------------------------*/
 /*--- Shadow value and address range handlers                  ---*/
 /*----------------------------------------------------------------*/
@@ -4201,7 +4388,7 @@
          tl_assert(is_sane_CacheLine(cl)); /* EXPENSIVE */
    }
    svOld = cl->svals[cloff];
-   svNew = memory_state_machine( False /*!is_w*/, thr_acc, a, svOld, 1 );
+   svNew = msm_handle_read( thr_acc, a, svOld, 1 );
    cl->svals[cloff] = svNew;
 }
 static void shadow_mem_read16 ( Thread* thr_acc, Addr a, SVal uuOpaque ) {
@@ -4227,7 +4414,7 @@
          tl_assert(is_sane_CacheLine(cl)); /* EXPENSIVE */
    }
    svOld = cl->svals[cloff];
-   svNew = memory_state_machine( False /*!is_w*/,  thr_acc, a, svOld, 2 );
+   svNew = msm_handle_read( thr_acc, a, svOld, 2 );
    cl->svals[cloff] = svNew;
    return;
   slowcase: /* misaligned, or must go further down the tree */
@@ -4259,7 +4446,7 @@
          tl_assert(is_sane_CacheLine(cl)); /* EXPENSIVE */
    }
    svOld = cl->svals[cloff];
-   svNew = memory_state_machine( False /*!is_w*/,  thr_acc, a, svOld, 4 );
+   svNew = msm_handle_read( thr_acc, a, svOld, 4 );
    cl->svals[cloff] = svNew;
    return;
   slowcase: /* misaligned, or must go further down the tree */
@@ -4281,7 +4468,7 @@
    descr = cl->descrs[tno];
    if (UNLIKELY( !(descr & (TREE_DESCR_32_0 << toff)) )) goto slowcase;
    { SVal* p = &cl->svals[cloff];
-     *p = memory_state_machine( False /*!is_w*/,  thr_acc, a, *p, 4 );
+     *p = msm_handle_read( thr_acc, a, *p, 4 );
    }
    return;
   slowcase: /* misaligned, or not at this level in the tree */
@@ -4305,7 +4492,7 @@
       goto slowcase;
    }
    svOld = cl->svals[cloff];
-   svNew = memory_state_machine( False /*!is_w*/,  thr_acc, a, svOld, 8 );
+   svNew = msm_handle_read( thr_acc, a, svOld, 8 );
    cl->svals[cloff] = svNew;
    return;
   slowcase: /* misaligned, or must go further down the tree */
@@ -4332,7 +4519,7 @@
          tl_assert(is_sane_CacheLine(cl)); /* EXPENSIVE */
    }
    svOld = cl->svals[cloff];
-   svNew = memory_state_machine( True /*is_w*/,  thr_acc, a, svOld, 1 );
+   svNew = msm_handle_write( thr_acc, a, svOld, 1 );
    cl->svals[cloff] = svNew;
 }
 static void shadow_mem_write16 ( Thread* thr_acc, Addr a, SVal uuOpaque ) {
@@ -4358,7 +4545,7 @@
          tl_assert(is_sane_CacheLine(cl)); /* EXPENSIVE */
    }
    svOld = cl->svals[cloff];
-   svNew = memory_state_machine( True /*is_w*/,  thr_acc, a, svOld, 2 );
+   svNew = msm_handle_write( thr_acc, a, svOld, 2 );
    cl->svals[cloff] = svNew;
    return;
   slowcase: /* misaligned, or must go further down the tree */
@@ -4390,7 +4577,7 @@
          tl_assert(is_sane_CacheLine(cl)); /* EXPENSIVE */
    }
    svOld = cl->svals[cloff];
-   svNew = memory_state_machine( True /*is_w*/,  thr_acc, a, svOld, 4 );
+   svNew = msm_handle_write( thr_acc, a, svOld, 4 );
    cl->svals[cloff] = svNew;
    return;
   slowcase: /* misaligned, or must go further down the tree */
@@ -4412,7 +4599,7 @@
    descr = cl->descrs[tno];
    if (UNLIKELY( !(descr & (TREE_DESCR_32_0 << toff)) )) goto slowcase;
    { SVal* p = &cl->svals[cloff];
-     *p = memory_state_machine( True /*is_w*/,  thr_acc, a, *p, 4 );
+     *p = msm_handle_write( thr_acc, a, *p, 4 );
    }
    return;
   slowcase: /* misaligned, or must go further down the tree */
@@ -4436,7 +4623,7 @@
       goto slowcase;
    }
    svOld = cl->svals[cloff];
-   svNew = memory_state_machine( True /*is_w*/,  thr_acc, a, svOld, 8 );
+   svNew = msm_handle_write( thr_acc, a, svOld, 8 );
    cl->svals[cloff] = svNew;
    return;
   slowcase: /* misaligned, or must go further down the tree */


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Valgrind-developers mailing list
Valgrind-developers@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/valgrind-developers

Reply via email to