Ticket #7923: 0001-Optimization-for-takeMVar-putMVar-when-MVar-left-emp.patch

File 0001-Optimization-for-takeMVar-putMVar-when-MVar-left-emp.patch, 4.8 KB (added by ezyang, 2 years ago)

Patch

  • rts/PrimOps.cmm

    From e3e629456e1c320a05e541b1c4144ccafde3c2ca Mon Sep 17 00:00:00 2001
    From: "Edward Z. Yang" <[email protected]>
    Date: Mon, 20 May 2013 08:47:27 -0700
    Subject: [PATCH] Optimization for takeMVar/putMVar when MVar left empty.
    
    We only need to apply the write barrier to an MVar when it acquires
    a reference to live data; when the MVar is left empty in the case
    of a takeMVar/putMVar, we can save a memory reference.
    
    Signed-off-by: Edward Z. Yang <[email protected]>
    ---
     rts/PrimOps.cmm |   52 ++++++++++++++++++++++++++++++++--------------------
     1 file changed, 32 insertions(+), 20 deletions(-)
    
    diff --git a/rts/PrimOps.cmm b/rts/PrimOps.cmm
    index f4e80e9..6ff5868 100644
    a b stg_takeMVarzh ( P_ mvar /* :: MVar a */ ) 
    11961196#else
    11971197    info = GET_INFO(mvar);
    11981198#endif
    1199        
    1200     if (info == stg_MVAR_CLEAN_info) {
    1201         ccall dirty_MVAR(BaseReg "ptr", mvar "ptr");
    1202     }
     1199
     1200    /* we can avoid dirtying the MVar in the case that there are
     1201     * no pending putMVars; so we delay doing the operation.
     1202     */
    12031203
    12041204    /* If the MVar is empty, put ourselves on its blocking queue,
    12051205     * and wait until we're woken up.
    12061206     */
    12071207    if (StgMVar_value(mvar) == stg_END_TSO_QUEUE_closure) {
     1208
     1209        if (info == stg_MVAR_CLEAN_info) {
     1210            ccall dirty_MVAR(BaseReg "ptr", mvar "ptr");
     1211        }
    12081212       
    12091213        // We want to put the heap check down here in the slow path,
    12101214        // but be careful to unlock the closure before returning to
    loop: 
    12431247    if (q == stg_END_TSO_QUEUE_closure) {
    12441248        /* No further putMVars, MVar is now empty */
    12451249        StgMVar_value(mvar) = stg_END_TSO_QUEUE_closure;
    1246         unlockClosure(mvar, stg_MVAR_DIRTY_info);
     1250        unlockClosure(mvar, info);
     1251        // escape without dirty_MVar!
    12471252        return (val);
    12481253    }
    12491254    if (StgHeader_info(q) == stg_IND_info ||
    loop: 
    12531258    }
    12541259 
    12551260    // There are putMVar(s) waiting... wake up the first thread on the queue
     1261
     1262    if (info == stg_MVAR_CLEAN_info) {
     1263        ccall dirty_MVAR(BaseReg "ptr", mvar "ptr");
     1264    }
    12561265   
    12571266    tso = StgMVarTSOQueue_tso(q);
    12581267    StgMVar_head(mvar) = StgMVarTSOQueue_link(q);
    stg_tryTakeMVarzh ( P_ mvar /* :: MVar a */ ) 
    13011310         */
    13021311        return (0, stg_NO_FINALIZER_closure);
    13031312    }
    1304    
    1305     if (info == stg_MVAR_CLEAN_info) {
    1306         ccall dirty_MVAR(BaseReg "ptr", mvar "ptr");
    1307     }
    13081313
    13091314    /* we got the value... */
    13101315    val = StgMVar_value(mvar);
    loop: 
    13141319    if (q == stg_END_TSO_QUEUE_closure) {
    13151320        /* No further putMVars, MVar is now empty */
    13161321        StgMVar_value(mvar) = stg_END_TSO_QUEUE_closure;
    1317         unlockClosure(mvar, stg_MVAR_DIRTY_info);
     1322        unlockClosure(mvar, info);
    13181323        return (1, val);
    13191324    }
     1325
     1326    if (info == stg_MVAR_CLEAN_info) {
     1327        ccall dirty_MVAR(BaseReg "ptr", mvar "ptr");
     1328    }
     1329
    13201330    if (StgHeader_info(q) == stg_IND_info ||
    13211331        StgHeader_info(q) == stg_MSG_NULL_info) {
    13221332        q = StgInd_indirectee(q);
    stg_putMVarzh ( P_ mvar, /* :: MVar a */ 
    13611371    info = GET_INFO(mvar);
    13621372#endif
    13631373
    1364     if (info == stg_MVAR_CLEAN_info) {
    1365         ccall dirty_MVAR(BaseReg "ptr", mvar "ptr");
    1366     }
    1367 
    13681374    if (StgMVar_value(mvar) != stg_END_TSO_QUEUE_closure) {
    13691375
     1376        if (info == stg_MVAR_CLEAN_info) {
     1377            ccall dirty_MVAR(BaseReg "ptr", mvar "ptr");
     1378        }
     1379
    13701380        // We want to put the heap check down here in the slow path,
    13711381        // but be careful to unlock the closure before returning to
    13721382        // the RTS if the check fails.
    stg_putMVarzh ( P_ mvar, /* :: MVar a */ 
    14001410loop:
    14011411    if (q == stg_END_TSO_QUEUE_closure) {
    14021412        /* No further takes, the MVar is now full. */
     1413        if (info == stg_MVAR_CLEAN_info) {
     1414            ccall dirty_MVAR(BaseReg "ptr", mvar "ptr");
     1415        }
    14031416        StgMVar_value(mvar) = val;
    14041417        unlockClosure(mvar, stg_MVAR_DIRTY_info);
    14051418        return ();
    loop: 
    14351448   
    14361449    ccall tryWakeupThread(MyCapability() "ptr", tso);
    14371450
    1438     unlockClosure(mvar, stg_MVAR_DIRTY_info);
     1451    unlockClosure(mvar, info);
    14391452    return ();
    14401453}
    14411454
    stg_tryPutMVarzh ( P_ mvar, /* :: MVar a */ 
    14571470#endif
    14581471        return (0);
    14591472    }
    1460  
    1461     if (info == stg_MVAR_CLEAN_info) {
    1462         ccall dirty_MVAR(BaseReg "ptr", mvar "ptr");
    1463     }
    14641473
    14651474    q = StgMVar_head(mvar);
    14661475loop:
    14671476    if (q == stg_END_TSO_QUEUE_closure) {
    14681477        /* No further takes, the MVar is now full. */
     1478        if (info == stg_MVAR_CLEAN_info) {
     1479            ccall dirty_MVAR(BaseReg "ptr", mvar "ptr");
     1480        }
    14691481        StgMVar_value(mvar) = val;
    14701482        unlockClosure(mvar, stg_MVAR_DIRTY_info);
    14711483        return (1);
    loop: 
    15011513   
    15021514    ccall tryWakeupThread(MyCapability() "ptr", tso);
    15031515
    1504     unlockClosure(mvar, stg_MVAR_DIRTY_info);
     1516    unlockClosure(mvar, info);
    15051517    return (1);
    15061518}
    15071519