From: dan Date: Wed, 18 Jul 2012 11:28:51 +0000 (+0000) Subject: Reorganize code to remove a few of the branches introduced into the critical sqlite3D... X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a785a59fb82e63779086937646ba636e6c51c55f;p=thirdparty%2Fsqlite.git Reorganize code to remove a few of the branches introduced into the critical sqlite3DbMallocXXX() path by the previous commit. FossilOrigin-Name: 75c095ee463c0c76e9637edccd33e807f837eb4e --- diff --git a/manifest b/manifest index 88f8ef4219..b5c5fc1968 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sthe\scustom\smemory\sallocation\sinterface\sto\sallow\sthe\suser\sto\sspecify\sa\scalloc()\sfunction. -D 2012-07-17T19:32:32.796 +C Reorganize\scode\sto\sremove\sa\sfew\sof\sthe\sbranches\sintroduced\sinto\sthe\scritical\ssqlite3DbMallocXXX()\spath\sby\sthe\sprevious\scommit. +D 2012-07-18T11:28:51.265 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 8f6d858bf3df9978ba43df19985146a1173025e4 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -146,9 +146,9 @@ F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f F src/lempar.c 0ee69fca0be54cd93939df98d2aca4ca46f44416 F src/loadext.c f20382fbaeec832438a1ba7797bee3d3c8a6d51d F src/main.c 0ce67958cf9cd68330c9c77d78dae275c867418e -F src/malloc.c e80dccc5d2be2fc0335fb6f430247460e4211388 +F src/malloc.c 1deb02c01b234aae858fc370138af9bf94d99112 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 -F src/mem1.c bc33172c15cbd3d15f0e962311da955c8aba1295 +F src/mem1.c 5ac4fb90adf0aa2beb912abafc67100a6ce126dc F src/mem2.c e307323e86b5da1853d7111b68fd6b84ad6f09cf F src/mem3.c 61c9d47b792908c532ca3a62b999cf21795c6534 F src/mem5.c c2c63b7067570b00bf33d751c39af24182316f7f @@ -1005,10 +1005,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P e4163596339c2166f9c4356ab824fff8bda8d0b0 -R 884dbf95b40a83feea70896cc9aa3953 -T *branch * calloc -T *sym-calloc * -T -sym-trunk * +P 8752237d123240b330baa461f855dbc01ffcab5b +R 83cf777410c006c6e09638632424df66 U dan -Z a86d2e070abe26c339e2a7663eba53d5 +Z 7172e94ea9d607acb82697b15b0d80b0 diff --git a/manifest.uuid b/manifest.uuid index 2db5f14677..3b93314bd0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8752237d123240b330baa461f855dbc01ffcab5b \ No newline at end of file +75c095ee463c0c76e9637edccd33e807f837eb4e \ No newline at end of file diff --git a/src/malloc.c b/src/malloc.c index e49b15b1f2..3894066cc5 100644 --- a/src/malloc.c +++ b/src/malloc.c @@ -259,10 +259,9 @@ static void sqlite3MallocAlarm(int nByte){ ** Do a memory allocation with statistics and alarms. Assume the ** lock is already held. */ -static int mallocWithAlarm( +static void *mallocWithAlarm( void *(*xAlloc)(int), /* Memory allocation function */ - int n, /* Bytes of memory to allocate */ - void **pp /* OUT: Pointer to allocation */ + int n /* Bytes of memory to allocate */ ){ int nFull; void *p; @@ -294,8 +293,8 @@ static int mallocWithAlarm( sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nFull); sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, 1); } - *pp = p; - return nFull; + + return p; } /* @@ -317,7 +316,7 @@ static void *memAllocate( p = 0; }else if( sqlite3GlobalConfig.bMemstat ){ sqlite3_mutex_enter(mem0.mutex); - mallocWithAlarm(xAlloc, n, &p); + p = mallocWithAlarm(xAlloc, n); sqlite3_mutex_leave(mem0.mutex); }else{ p = xAlloc(n); @@ -388,8 +387,11 @@ void *sqlite3ScratchMalloc(int n){ }else{ if( sqlite3GlobalConfig.bMemstat ){ sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n); - n = mallocWithAlarm(sqlite3GlobalConfig.m.xMalloc, n, &p); - if( p ) sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, n); + p = mallocWithAlarm(sqlite3GlobalConfig.m.xMalloc, n); + if( p ){ + n = sqlite3MallocSize(p); + sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, n); + } sqlite3_mutex_leave(mem0.mutex); }else{ sqlite3_mutex_leave(mem0.mutex); @@ -597,37 +599,18 @@ void *sqlite3_realloc(void *pOld, int n){ } /* -** Allocate and, if bZero is true, zero memory. If the allocation -** fails, set the mallocFailed flag in the connection pointer. -** -** If db!=0 and db->mallocFailed is true (indicating a prior malloc -** failure on the same database connection) then always return 0. -** Hence for a particular database connection, once malloc starts -** failing, it fails consistently until mallocFailed is reset. -** This is an important assumption. There are many places in the -** code that do things like this: -** -** int *a = (int*)sqlite3DbMallocRaw(db, 100); -** int *b = (int*)sqlite3DbMallocRaw(db, 200); -** if( b ) a[10] = 9; -** -** In other words, if a subsequent malloc (ex: "b") worked, it is assumed -** that all prior mallocs (ex: "a") worked too. +** Attempt to allocate an n byte block from the lookaside buffer of +** connection db. If successful, return a pointer to the new allocation. +** Otherwise, return a NULL pointer. */ -static void *dbMalloc(sqlite3 *db, int n, int bZero){ - void *p; - assert( db==0 || sqlite3_mutex_held(db->mutex) ); - assert( db==0 || db->pnBytesFreed==0 ); #ifndef SQLITE_OMIT_LOOKASIDE - if( db ){ - LookasideSlot *pBuf; - if( db->mallocFailed ){ - return 0; - } - if( db->lookaside.bEnabled ){ - if( n>db->lookaside.sz ){ - db->lookaside.anStat[1]++; - }else if( (pBuf = db->lookaside.pFree)==0 ){ +static void *lookasideAlloc(sqlite3 *db, int n){ + if( db->lookaside.bEnabled ){ + if( n>db->lookaside.sz ){ + db->lookaside.anStat[1]++; + }else{ + LookasideSlot *pBuf; + if( (pBuf = db->lookaside.pFree)==0 ){ db->lookaside.anStat[2]++; }else{ db->lookaside.pFree = pBuf->pNext; @@ -636,43 +619,79 @@ static void *dbMalloc(sqlite3 *db, int n, int bZero){ if( db->lookaside.nOut>db->lookaside.mxOut ){ db->lookaside.mxOut = db->lookaside.nOut; } - if( bZero ) memset(pBuf, 0, n); - return (void*)pBuf; } + return (void*)pBuf; } } + return 0; +} #else - if( db && db->mallocFailed ){ - return 0; - } +# define lookasideAlloc(x,y) 0 #endif - if( bZero ){ - p = sqlite3MallocZero(n); - }else{ - p = sqlite3Malloc(n); - } - if( !p && db ){ - db->mallocFailed = 1; - } - sqlite3MemdebugSetType(p, MEMTYPE_DB | - ((db && db->lookaside.bEnabled) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP)); - return p; -} /* ** Allocate and zero memory. If the allocation fails, set the ** mallocFailed flag in the connection pointer. +** +** If db!=0 and db->mallocFailed is true (indicating a prior malloc +** failure on the same database connection) then always return 0. +** Hence for a particular database connection, once malloc starts +** failing, it fails consistently until mallocFailed is reset. +** This is an important assumption. There are many places in the +** code that do things like this: +** +** int *a = (int*)sqlite3DbMallocRaw(db, 100); +** int *b = (int*)sqlite3DbMallocRaw(db, 200); +** if( b ) a[10] = 9; +** +** In other words, if a subsequent malloc (ex: "b") worked, it is assumed +** that all prior mallocs (ex: "a") worked too. */ void *sqlite3DbMallocZero(sqlite3 *db, int n){ - return dbMalloc(db, n, 1); + void *p; + if( db==0 ){ + p = memAllocate(sqlite3GlobalConfig.m.xCalloc, n); + }else if( db->mallocFailed ){ + p = 0; + }else{ + if( (p = lookasideAlloc(db, n)) ){ + memset(p, 0, n); + }else{ + p = memAllocate(sqlite3GlobalConfig.m.xCalloc, n); + if( !p ) db->mallocFailed = 1; + } + } + + sqlite3MemdebugSetType(p, MEMTYPE_DB | + ((db && db->lookaside.bEnabled) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP)); + return p; } /* ** Allocate memory. If the allocation fails, make the mallocFailed ** flag in the connection pointer. +** +** If db!=0 and db->mallocFailed is true (indicating a prior malloc +** failure on the same database connection) then always return 0. +** See also comments above sqlite3DbMallocZero() for details. */ void *sqlite3DbMallocRaw(sqlite3 *db, int n){ - return dbMalloc(db, n, 0); + void *p; + if( db==0 ){ + p = memAllocate(sqlite3GlobalConfig.m.xMalloc, n); + }else if( db->mallocFailed ){ + p = 0; + }else{ + p = lookasideAlloc(db, n); + if( !p ){ + p = memAllocate(sqlite3GlobalConfig.m.xMalloc, n); + if( !p ) db->mallocFailed = 1; + } + } + + sqlite3MemdebugSetType(p, MEMTYPE_DB | + ((db && db->lookaside.bEnabled) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP)); + return p; } /* diff --git a/src/mem1.c b/src/mem1.c index 50d724b195..8e4b66ec01 100644 --- a/src/mem1.c +++ b/src/mem1.c @@ -102,43 +102,60 @@ static malloc_zone_t* _sqliteZone_; #endif /* __APPLE__ or not __APPLE__ */ /* -** Like malloc() (if bZero==0) or calloc() (if bZero!=0), except remember -** the size of the allocation so that we can find it later using -** sqlite3MemSize(). +** A memory allocation of nByte bytes has failed. Log an error message +** using sqlite3_log(). +*/ +static void logAllocationError(int nByte){ + testcase( sqlite3GlobalConfig.xLog!=0 ); + sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte); +} + +/* +** Allocate nByte bytes of memory. ** ** For this low-level routine, we are guaranteed that nByte>0 because ** cases of nByte<=0 will be intercepted and dealt with by higher level ** routines. */ -static void *memMalloc(int nByte, int bZero){ +static void *sqlite3MemMalloc(int nByte){ + i64 *p; #ifdef SQLITE_MALLOCSIZE - void *p = (bZero ? SQLITE_CALLOC( nByte ) : SQLITE_MALLOC( nByte )); + p = SQLITE_MALLOC(nByte); if( p==0 ){ - testcase( sqlite3GlobalConfig.xLog!=0 ); - sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte); - } - return p; #else - sqlite3_int64 *p; - assert( nByte>0 ); nByte = ROUND8(nByte); - p = (bZero ? SQLITE_CALLOC( nByte+8 ) : SQLITE_MALLOC( nByte+8 )); + p = SQLITE_MALLOC(nByte+8); if( p ){ - p[0] = nByte; - p++; + *(p++) = (i64)nByte; }else{ - testcase( sqlite3GlobalConfig.xLog!=0 ); - sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte); +#endif + logAllocationError(nByte); } return (void *)p; -#endif } -static void *sqlite3MemMalloc(int nByte){ - return memMalloc(nByte, 0); -} +/* +** Allocate and zero nByte bytes of memory. +** +** For this low-level routine, we are guaranteed that nByte>0 because +** cases of nByte<=0 will be intercepted and dealt with by higher level +** routines. +*/ static void *sqlite3MemCalloc(int nByte){ - return memMalloc(nByte, 1); + i64 *p; +#ifdef SQLITE_MALLOCSIZE + p = SQLITE_CALLOC(nByte); + if( p==0 ){ +#else + nByte = ROUND8(nByte); + p = SQLITE_CALLOC(nByte+8); + if( p ){ + *(p++) = (i64)nByte; + }else{ +#endif + logAllocationError(nByte); + } + return (void *)p; } /*