From: drh Date: Fri, 30 Sep 2016 20:22:27 +0000 (+0000) Subject: Fix the Parse.aColCache column cache so that all of the valid entries are X-Git-Tag: version-3.15.0~38 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9b40d13f437429abae07b4e03fd18647696c98e4;p=thirdparty%2Fsqlite.git Fix the Parse.aColCache column cache so that all of the valid entries are in the first Parse.nColCache slots. FossilOrigin-Name: 6028502059ccbd3699637b7a70a6d8ce1b7c3dad --- diff --git a/manifest b/manifest index 5f89cfbd3e..5681d1db00 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Another\ssimplification\sto\sthe\sParse\sobject. -D 2016-09-30T19:14:32.049 +C Fix\sthe\sParse.aColCache\scolumn\scache\sso\sthat\sall\sof\sthe\svalid\sentries\sare\s\nin\sthe\sfirst\sParse.nColCache\sslots. +D 2016-09-30T20:22:27.729 F Makefile.in 6fd48ffcf7c2deea7499062d1f3747f986c19678 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 5151cc64c4c05f3455f4f692ad11410a810d937f @@ -339,7 +339,7 @@ F src/ctime.c e77f3dc297b4b65c96da78b4ae4272fdfae863d7 F src/date.c 95c9a8d00767e7221a8e9a31f4e913fc8029bf6b F src/dbstat.c 19ee7a4e89979d4df8e44cfac7a8f905ec89b77d F src/delete.c cb3f6300df24c26c609778b2731f82644b5532ec -F src/expr.c a27090ab1d9d9901c64974c43588a38a486d6a55 +F src/expr.c f0ea2e1a7af0047b71e40dfed6902249129710e5 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c b9ca262f6ad4d030a3cab737ebf9b0b3c8b4ac80 F src/func.c 29cc9acb170ec1387b9f63eb52cd85f8de96c771 @@ -457,7 +457,7 @@ F src/vdbe.c 51e754eec26d892abc6279f5e949545af68ec1b3 F src/vdbe.h c044be7050ac6bf596eecc6ab159f5dbc020a3b7 F src/vdbeInt.h 581b737c2f6e413c555469480efe31796a71bcad F src/vdbeapi.c 794f80669e9e3b9b3edc78d80c15968985c7bf21 -F src/vdbeaux.c 240fecf157b6a3deb3c68abe614ae30cb8e884cd +F src/vdbeaux.c 5f97a1aed18b5b064407652654f73f3cd4836a87 F src/vdbeblob.c 3e82a797b60c3b9fed7b8de8c539ca7607874937 F src/vdbemem.c 1c330522e6b6e4ddd2ff63c4c0dfafa20c3965a7 F src/vdbesort.c 91fda3909326860382b0ca8aa251e609c6a9d62c @@ -1525,7 +1525,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 814e41da3563eecf5514811bc8ab2df4f5cc0d4b -R 608d1a96b91ee96ffbbec71d9c1f3711 +P c1419727f5e4cb3ef63b5853b6ef3b1e53af0651 +R 1c5f450e057ea86e47df56b91a0fd28e U drh -Z 828299b9894d67f8570c817a01bf6c81 +Z 0c5e41f0df0638c8d6aea45323876192 diff --git a/manifest.uuid b/manifest.uuid index 585ee1fd87..423c99ffef 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c1419727f5e4cb3ef63b5853b6ef3b1e53af0651 \ No newline at end of file +6028502059ccbd3699637b7a70a6d8ce1b7c3dad \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index e8c245ec4d..0640029cb0 100644 --- a/src/expr.c +++ b/src/expr.c @@ -2964,32 +2964,19 @@ static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){ } } -#if defined(SQLITE_DEBUG) /* -** Verify the consistency of the column cache +** Erase column-cache entry number i */ -static int cacheIsValid(Parse *pParse){ - int i, n; - for(i=n=0; iaColCache[i].iReg>0 ) n++; - } - return n==pParse->nColCache; -} -#endif - -/* -** Clear a cache entry. -*/ -static void cacheEntryClear(Parse *pParse, struct yColCache *p){ - if( p->tempReg ){ +static void cacheEntryClear(Parse *pParse, int i){ + if( pParse->aColCache[i].tempReg ){ if( pParse->nTempRegaTempReg) ){ - pParse->aTempReg[pParse->nTempReg++] = p->iReg; + pParse->aTempReg[pParse->nTempReg++] = pParse->aColCache[i].iReg; } - p->tempReg = 0; } - p->iReg = 0; pParse->nColCache--; - assert( pParse->db->mallocFailed || cacheIsValid(pParse) ); + if( inColCache ){ + pParse->aColCache[i] = pParse->aColCache[pParse->nColCache]; + } } @@ -3019,46 +3006,33 @@ void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){ ** that the object will never already be in cache. Verify this guarantee. */ #ifndef NDEBUG - for(i=0, p=pParse->aColCache; iiReg==0 || p->iTable!=iTab || p->iColumn!=iCol ); + for(i=0, p=pParse->aColCache; inColCache; i++, p++){ + assert( p->iTable!=iTab || p->iColumn!=iCol ); } #endif - /* Find an empty slot and replace it */ - for(i=0, p=pParse->aColCache; iiReg==0 ){ - p->iLevel = pParse->iCacheLevel; - p->iTable = iTab; - p->iColumn = iCol; - p->iReg = iReg; - p->tempReg = 0; - p->lru = pParse->iCacheCnt++; - pParse->nColCache++; - assert( pParse->db->mallocFailed || cacheIsValid(pParse) ); - return; - } - } - - /* Replace the last recently used */ - minLru = 0x7fffffff; - idxLru = -1; - for(i=0, p=pParse->aColCache; ilrulru; + /* If the cache is already full, delete the least recently used entry */ + if( pParse->nColCache>=SQLITE_N_COLCACHE ){ + minLru = 0x7fffffff; + idxLru = -1; + for(i=0, p=pParse->aColCache; ilrulru; + } } - } - if( ALWAYS(idxLru>=0) ){ p = &pParse->aColCache[idxLru]; - p->iLevel = pParse->iCacheLevel; - p->iTable = iTab; - p->iColumn = iCol; - p->iReg = iReg; - p->tempReg = 0; - p->lru = pParse->iCacheCnt++; - assert( cacheIsValid(pParse) ); - return; + }else{ + p = &pParse->aColCache[pParse->nColCache++]; } + + /* Add the new entry to the end of the cache */ + p->iLevel = pParse->iCacheLevel; + p->iTable = iTab; + p->iColumn = iCol; + p->iReg = iReg; + p->tempReg = 0; + p->lru = pParse->iCacheCnt++; } /* @@ -3066,13 +3040,14 @@ void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){ ** Purge the range of registers from the column cache. */ void sqlite3ExprCacheRemove(Parse *pParse, int iReg, int nReg){ - struct yColCache *p; - if( iReg<=0 || pParse->nColCache==0 ) return; - p = &pParse->aColCache[SQLITE_N_COLCACHE-1]; - while(1){ - if( p->iReg >= iReg && p->iReg < iReg+nReg ) cacheEntryClear(pParse, p); - if( p==pParse->aColCache ) break; - p--; + int i = 0; + while( inColCache ){ + struct yColCache *p = &pParse->aColCache[i]; + if( p->iReg >= iReg && p->iReg < iReg+nReg ){ + cacheEntryClear(pParse, i); + }else{ + i++; + } } } @@ -3096,8 +3071,7 @@ void sqlite3ExprCachePush(Parse *pParse){ ** the cache to the state it was in prior the most recent Push. */ void sqlite3ExprCachePop(Parse *pParse){ - int i; - struct yColCache *p; + int i = 0; assert( pParse->iCacheLevel>=1 ); pParse->iCacheLevel--; #ifdef SQLITE_DEBUG @@ -3105,9 +3079,11 @@ void sqlite3ExprCachePop(Parse *pParse){ printf("POP to %d\n", pParse->iCacheLevel); } #endif - for(i=0, p=pParse->aColCache; iiReg && p->iLevel>pParse->iCacheLevel ){ - cacheEntryClear(pParse, p); + while( inColCache ){ + if( pParse->aColCache[i].iLevel>pParse->iCacheLevel ){ + cacheEntryClear(pParse, i); + }else{ + i++; } } } @@ -3121,7 +3097,7 @@ void sqlite3ExprCachePop(Parse *pParse){ static void sqlite3ExprCachePinRegister(Parse *pParse, int iReg){ int i; struct yColCache *p; - for(i=0, p=pParse->aColCache; iaColCache; inColCache; i++, p++){ if( p->iReg==iReg ){ p->tempReg = 0; } @@ -3199,7 +3175,7 @@ int sqlite3ExprCodeGetColumn( int i; struct yColCache *p; - for(i=0, p=pParse->aColCache; iaColCache; inColCache; i++, p++){ if( p->iReg>0 && p->iTable==iTable && p->iColumn==iColumn ){ p->lru = pParse->iCacheCnt++; sqlite3ExprCachePinRegister(pParse, p->iReg); @@ -3232,18 +3208,20 @@ void sqlite3ExprCodeGetColumnToReg( */ void sqlite3ExprCacheClear(Parse *pParse){ int i; - struct yColCache *p; #if SQLITE_DEBUG if( pParse->db->flags & SQLITE_VdbeAddopTrace ){ printf("CLEAR\n"); } #endif - for(i=0, p=pParse->aColCache; iiReg ){ - cacheEntryClear(pParse, p); + for(i=0; inColCache; i++){ + if( pParse->aColCache[i].tempReg + && pParse->nTempRegaTempReg) + ){ + pParse->aTempReg[pParse->nTempReg++] = pParse->aColCache[i].iReg; } } + pParse->nColCache = 0; } /* @@ -3275,7 +3253,7 @@ void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){ static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){ int i; struct yColCache *p; - for(i=0, p=pParse->aColCache; iaColCache; inColCache; i++, p++){ int r = p->iReg; if( r>=iFrom && r<=iTo ) return 1; /*NO_TEST*/ } @@ -4971,7 +4949,7 @@ void sqlite3ReleaseTempReg(Parse *pParse, int iReg){ if( iReg && pParse->nTempRegaTempReg) ){ int i; struct yColCache *p; - for(i=0, p=pParse->aColCache; iaColCache; inColCache; i++, p++){ if( p->iReg==iReg ){ p->tempReg = 1; return; diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 2e3a4eaaf1..86f5096a8b 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -184,9 +184,8 @@ int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){ if( p->db->flags & SQLITE_VdbeAddopTrace ){ int jj, kk; Parse *pParse = p->pParse; - for(jj=kk=0; jjnColCache; jj++){ struct yColCache *x = pParse->aColCache + jj; - if( x->iLevel>pParse->iCacheLevel || x->iReg==0 ) continue; printf(" r[%d]={%d:%d}", x->iReg, x->iTable, x->iColumn); kk++; }