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