Index: third_party/sqlite/src/src/malloc.c |
diff --git a/third_party/sqlite/src/src/malloc.c b/third_party/sqlite/src/src/malloc.c |
index 6678d56596d085949e43e0f767c16744ee402426..50fdf524c5242f728c37cf782975204e3a881089 100644 |
--- a/third_party/sqlite/src/src/malloc.c |
+++ b/third_party/sqlite/src/src/malloc.c |
@@ -11,79 +11,39 @@ |
************************************************************************* |
** |
** Memory allocation functions used throughout sqlite. |
-** |
-** $Id: malloc.c,v 1.66 2009/07/17 11:44:07 drh Exp $ |
*/ |
#include "sqliteInt.h" |
#include <stdarg.h> |
/* |
-** This routine runs when the memory allocator sees that the |
-** total memory allocation is about to exceed the soft heap |
-** limit. |
-*/ |
-static void softHeapLimitEnforcer( |
- void *NotUsed, |
- sqlite3_int64 NotUsed2, |
- int allocSize |
-){ |
- UNUSED_PARAMETER2(NotUsed, NotUsed2); |
- sqlite3_release_memory(allocSize); |
-} |
- |
-/* |
-** Set the soft heap-size limit for the library. Passing a zero or |
-** negative value indicates no limit. |
-*/ |
-void sqlite3_soft_heap_limit(int n){ |
- sqlite3_uint64 iLimit; |
- int overage; |
- if( n<0 ){ |
- iLimit = 0; |
- }else{ |
- iLimit = n; |
- } |
-#ifndef SQLITE_OMIT_AUTOINIT |
- sqlite3_initialize(); |
-#endif |
- if( iLimit>0 ){ |
- sqlite3MemoryAlarm(softHeapLimitEnforcer, 0, iLimit); |
- }else{ |
- sqlite3MemoryAlarm(0, 0, 0); |
- } |
- overage = (int)(sqlite3_memory_used() - (i64)n); |
- if( overage>0 ){ |
- sqlite3_release_memory(overage); |
- } |
-} |
- |
-/* |
** Attempt to release up to n bytes of non-essential memory currently |
** held by SQLite. An example of non-essential memory is memory used to |
** cache database pages that are not currently in use. |
*/ |
int sqlite3_release_memory(int n){ |
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT |
- int nRet = 0; |
-#if 0 |
- nRet += sqlite3VdbeReleaseMemory(n); |
-#endif |
- nRet += sqlite3PcacheReleaseMemory(n-nRet); |
- return nRet; |
+ return sqlite3PcacheReleaseMemory(n); |
#else |
+ /* IMPLEMENTATION-OF: R-34391-24921 The sqlite3_release_memory() routine |
+ ** is a no-op returning zero if SQLite is not compiled with |
+ ** SQLITE_ENABLE_MEMORY_MANAGEMENT. */ |
UNUSED_PARAMETER(n); |
- return SQLITE_OK; |
+ return 0; |
#endif |
} |
/* |
+** An instance of the following object records the location of |
+** each unused scratch buffer. |
+*/ |
+typedef struct ScratchFreeslot { |
+ struct ScratchFreeslot *pNext; /* Next unused scratch buffer */ |
+} ScratchFreeslot; |
+ |
+/* |
** State information local to the memory allocation subsystem. |
*/ |
static SQLITE_WSD struct Mem0Global { |
- /* Number of free pages for scratch and page-cache memory */ |
- u32 nScratchFree; |
- u32 nPageFree; |
- |
sqlite3_mutex *mutex; /* Mutex to serialize access */ |
/* |
@@ -97,17 +57,100 @@ static SQLITE_WSD struct Mem0Global { |
void *alarmArg; |
/* |
- ** Pointers to the end of sqlite3GlobalConfig.pScratch and |
- ** sqlite3GlobalConfig.pPage to a block of memory that records |
- ** which pages are available. |
+ ** Pointers to the end of sqlite3GlobalConfig.pScratch memory |
+ ** (so that a range test can be used to determine if an allocation |
+ ** being freed came from pScratch) and a pointer to the list of |
+ ** unused scratch allocations. |
*/ |
- u32 *aScratchFree; |
- u32 *aPageFree; |
+ void *pScratchEnd; |
+ ScratchFreeslot *pScratchFree; |
+ u32 nScratchFree; |
+ |
+ /* |
+ ** True if heap is nearly "full" where "full" is defined by the |
+ ** sqlite3_soft_heap_limit() setting. |
+ */ |
+ int nearlyFull; |
} mem0 = { 0, 0, 0, 0, 0, 0, 0, 0 }; |
#define mem0 GLOBAL(struct Mem0Global, mem0) |
/* |
+** This routine runs when the memory allocator sees that the |
+** total memory allocation is about to exceed the soft heap |
+** limit. |
+*/ |
+static void softHeapLimitEnforcer( |
+ void *NotUsed, |
+ sqlite3_int64 NotUsed2, |
+ int allocSize |
+){ |
+ UNUSED_PARAMETER2(NotUsed, NotUsed2); |
+ sqlite3_release_memory(allocSize); |
+} |
+ |
+/* |
+** Change the alarm callback |
+*/ |
+static int sqlite3MemoryAlarm( |
+ void(*xCallback)(void *pArg, sqlite3_int64 used,int N), |
+ void *pArg, |
+ sqlite3_int64 iThreshold |
+){ |
+ int nUsed; |
+ sqlite3_mutex_enter(mem0.mutex); |
+ mem0.alarmCallback = xCallback; |
+ mem0.alarmArg = pArg; |
+ mem0.alarmThreshold = iThreshold; |
+ nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED); |
+ mem0.nearlyFull = (iThreshold>0 && iThreshold<=nUsed); |
+ sqlite3_mutex_leave(mem0.mutex); |
+ return SQLITE_OK; |
+} |
+ |
+#ifndef SQLITE_OMIT_DEPRECATED |
+/* |
+** Deprecated external interface. Internal/core SQLite code |
+** should call sqlite3MemoryAlarm. |
+*/ |
+int sqlite3_memory_alarm( |
+ void(*xCallback)(void *pArg, sqlite3_int64 used,int N), |
+ void *pArg, |
+ sqlite3_int64 iThreshold |
+){ |
+ return sqlite3MemoryAlarm(xCallback, pArg, iThreshold); |
+} |
+#endif |
+ |
+/* |
+** Set the soft heap-size limit for the library. Passing a zero or |
+** negative value indicates no limit. |
+*/ |
+sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 n){ |
+ sqlite3_int64 priorLimit; |
+ sqlite3_int64 excess; |
+#ifndef SQLITE_OMIT_AUTOINIT |
+ sqlite3_initialize(); |
+#endif |
+ sqlite3_mutex_enter(mem0.mutex); |
+ priorLimit = mem0.alarmThreshold; |
+ sqlite3_mutex_leave(mem0.mutex); |
+ if( n<0 ) return priorLimit; |
+ if( n>0 ){ |
+ sqlite3MemoryAlarm(softHeapLimitEnforcer, 0, n); |
+ }else{ |
+ sqlite3MemoryAlarm(0, 0, 0); |
+ } |
+ excess = sqlite3_memory_used() - n; |
+ if( excess>0 ) sqlite3_release_memory((int)(excess & 0x7fffffff)); |
+ return priorLimit; |
+} |
+void sqlite3_soft_heap_limit(int n){ |
+ if( n<0 ) n = 0; |
+ sqlite3_soft_heap_limit64(n); |
+} |
+ |
+/* |
** Initialize the memory allocation subsystem. |
*/ |
int sqlite3MallocInit(void){ |
@@ -119,37 +162,46 @@ int sqlite3MallocInit(void){ |
mem0.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); |
} |
if( sqlite3GlobalConfig.pScratch && sqlite3GlobalConfig.szScratch>=100 |
- && sqlite3GlobalConfig.nScratch>=0 ){ |
- int i; |
- sqlite3GlobalConfig.szScratch = ROUNDDOWN8(sqlite3GlobalConfig.szScratch-4); |
- mem0.aScratchFree = (u32*)&((char*)sqlite3GlobalConfig.pScratch) |
- [sqlite3GlobalConfig.szScratch*sqlite3GlobalConfig.nScratch]; |
- for(i=0; i<sqlite3GlobalConfig.nScratch; i++){ mem0.aScratchFree[i] = i; } |
- mem0.nScratchFree = sqlite3GlobalConfig.nScratch; |
+ && sqlite3GlobalConfig.nScratch>0 ){ |
+ int i, n, sz; |
+ ScratchFreeslot *pSlot; |
+ sz = ROUNDDOWN8(sqlite3GlobalConfig.szScratch); |
+ sqlite3GlobalConfig.szScratch = sz; |
+ pSlot = (ScratchFreeslot*)sqlite3GlobalConfig.pScratch; |
+ n = sqlite3GlobalConfig.nScratch; |
+ mem0.pScratchFree = pSlot; |
+ mem0.nScratchFree = n; |
+ for(i=0; i<n-1; i++){ |
+ pSlot->pNext = (ScratchFreeslot*)(sz+(char*)pSlot); |
+ pSlot = pSlot->pNext; |
+ } |
+ pSlot->pNext = 0; |
+ mem0.pScratchEnd = (void*)&pSlot[1]; |
}else{ |
+ mem0.pScratchEnd = 0; |
sqlite3GlobalConfig.pScratch = 0; |
sqlite3GlobalConfig.szScratch = 0; |
+ sqlite3GlobalConfig.nScratch = 0; |
} |
- if( sqlite3GlobalConfig.pPage && sqlite3GlobalConfig.szPage>=512 |
- && sqlite3GlobalConfig.nPage>=1 ){ |
- int i; |
- int overhead; |
- int sz = ROUNDDOWN8(sqlite3GlobalConfig.szPage); |
- int n = sqlite3GlobalConfig.nPage; |
- overhead = (4*n + sz - 1)/sz; |
- sqlite3GlobalConfig.nPage -= overhead; |
- mem0.aPageFree = (u32*)&((char*)sqlite3GlobalConfig.pPage) |
- [sqlite3GlobalConfig.szPage*sqlite3GlobalConfig.nPage]; |
- for(i=0; i<sqlite3GlobalConfig.nPage; i++){ mem0.aPageFree[i] = i; } |
- mem0.nPageFree = sqlite3GlobalConfig.nPage; |
- }else{ |
+ if( sqlite3GlobalConfig.pPage==0 || sqlite3GlobalConfig.szPage<512 |
+ || sqlite3GlobalConfig.nPage<1 ){ |
sqlite3GlobalConfig.pPage = 0; |
sqlite3GlobalConfig.szPage = 0; |
+ sqlite3GlobalConfig.nPage = 0; |
} |
return sqlite3GlobalConfig.m.xInit(sqlite3GlobalConfig.m.pAppData); |
} |
/* |
+** Return true if the heap is currently under memory pressure - in other |
+** words if the amount of heap used is close to the limit set by |
+** sqlite3_soft_heap_limit(). |
+*/ |
+int sqlite3HeapNearlyFull(void){ |
+ return mem0.nearlyFull; |
+} |
+ |
+/* |
** Deinitialize the memory allocation subsystem. |
*/ |
void sqlite3MallocEnd(void){ |
@@ -184,36 +236,6 @@ sqlite3_int64 sqlite3_memory_highwater(int resetFlag){ |
} |
/* |
-** Change the alarm callback |
-*/ |
-int sqlite3MemoryAlarm( |
- void(*xCallback)(void *pArg, sqlite3_int64 used,int N), |
- void *pArg, |
- sqlite3_int64 iThreshold |
-){ |
- sqlite3_mutex_enter(mem0.mutex); |
- mem0.alarmCallback = xCallback; |
- mem0.alarmArg = pArg; |
- mem0.alarmThreshold = iThreshold; |
- sqlite3_mutex_leave(mem0.mutex); |
- return SQLITE_OK; |
-} |
- |
-#ifndef SQLITE_OMIT_DEPRECATED |
-/* |
-** Deprecated external interface. Internal/core SQLite code |
-** should call sqlite3MemoryAlarm. |
-*/ |
-int sqlite3_memory_alarm( |
- void(*xCallback)(void *pArg, sqlite3_int64 used,int N), |
- void *pArg, |
- sqlite3_int64 iThreshold |
-){ |
- return sqlite3MemoryAlarm(xCallback, pArg, iThreshold); |
-} |
-#endif |
- |
-/* |
** Trigger the alarm |
*/ |
static void sqlite3MallocAlarm(int nByte){ |
@@ -245,17 +267,23 @@ static int mallocWithAlarm(int n, void **pp){ |
if( mem0.alarmCallback!=0 ){ |
int nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED); |
if( nUsed+nFull >= mem0.alarmThreshold ){ |
+ mem0.nearlyFull = 1; |
sqlite3MallocAlarm(nFull); |
+ }else{ |
+ mem0.nearlyFull = 0; |
} |
} |
p = sqlite3GlobalConfig.m.xMalloc(nFull); |
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT |
if( p==0 && mem0.alarmCallback ){ |
sqlite3MallocAlarm(nFull); |
p = sqlite3GlobalConfig.m.xMalloc(nFull); |
} |
+#endif |
if( p ){ |
nFull = sqlite3MallocSize(p); |
sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nFull); |
+ sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, 1); |
} |
*pp = p; |
return nFull; |
@@ -267,7 +295,9 @@ static int mallocWithAlarm(int n, void **pp){ |
*/ |
void *sqlite3Malloc(int n){ |
void *p; |
- if( n<=0 || n>=0x7fffff00 ){ |
+ if( n<=0 /* IMP: R-65312-04917 */ |
+ || n>=0x7fffff00 |
+ ){ |
/* A memory allocation of a number of bytes which is near the maximum |
** signed integer value might cause an integer overflow inside of the |
** xMalloc(). Hence we limit the maximum size to 0x7fffff00, giving |
@@ -281,6 +311,7 @@ void *sqlite3Malloc(int n){ |
}else{ |
p = sqlite3GlobalConfig.m.xMalloc(n); |
} |
+ assert( EIGHT_BYTE_ALIGNMENT(p) ); /* IMP: R-04675-44850 */ |
return p; |
} |
@@ -319,88 +350,79 @@ void *sqlite3ScratchMalloc(int n){ |
void *p; |
assert( n>0 ); |
-#if SQLITE_THREADSAFE==0 && !defined(NDEBUG) |
- /* Verify that no more than one scratch allocation per thread |
- ** is outstanding at one time. (This is only checked in the |
- ** single-threaded case since checking in the multi-threaded case |
- ** would be much more complicated.) */ |
- assert( scratchAllocOut==0 ); |
-#endif |
- |
- if( sqlite3GlobalConfig.szScratch<n ){ |
- goto scratch_overflow; |
- }else{ |
- sqlite3_mutex_enter(mem0.mutex); |
- if( mem0.nScratchFree==0 ){ |
+ sqlite3_mutex_enter(mem0.mutex); |
+ if( mem0.nScratchFree && sqlite3GlobalConfig.szScratch>=n ){ |
+ p = mem0.pScratchFree; |
+ mem0.pScratchFree = mem0.pScratchFree->pNext; |
+ mem0.nScratchFree--; |
+ sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, 1); |
+ sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n); |
+ sqlite3_mutex_leave(mem0.mutex); |
+ }else{ |
+ if( sqlite3GlobalConfig.bMemstat ){ |
+ sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n); |
+ n = mallocWithAlarm(n, &p); |
+ if( p ) sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, n); |
sqlite3_mutex_leave(mem0.mutex); |
- goto scratch_overflow; |
}else{ |
- int i; |
- i = mem0.aScratchFree[--mem0.nScratchFree]; |
- i *= sqlite3GlobalConfig.szScratch; |
- sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, 1); |
- sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n); |
sqlite3_mutex_leave(mem0.mutex); |
- p = (void*)&((char*)sqlite3GlobalConfig.pScratch)[i]; |
- assert( (((u8*)p - (u8*)0) & 7)==0 ); |
+ p = sqlite3GlobalConfig.m.xMalloc(n); |
} |
+ sqlite3MemdebugSetType(p, MEMTYPE_SCRATCH); |
} |
-#if SQLITE_THREADSAFE==0 && !defined(NDEBUG) |
- scratchAllocOut = p!=0; |
-#endif |
+ assert( sqlite3_mutex_notheld(mem0.mutex) ); |
- return p; |
-scratch_overflow: |
- if( sqlite3GlobalConfig.bMemstat ){ |
- sqlite3_mutex_enter(mem0.mutex); |
- sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n); |
- n = mallocWithAlarm(n, &p); |
- if( p ) sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, n); |
- sqlite3_mutex_leave(mem0.mutex); |
- }else{ |
- p = sqlite3GlobalConfig.m.xMalloc(n); |
- } |
#if SQLITE_THREADSAFE==0 && !defined(NDEBUG) |
- scratchAllocOut = p!=0; |
+ /* Verify that no more than two scratch allocations per thread |
+ ** are outstanding at one time. (This is only checked in the |
+ ** single-threaded case since checking in the multi-threaded case |
+ ** would be much more complicated.) */ |
+ assert( scratchAllocOut<=1 ); |
+ if( p ) scratchAllocOut++; |
#endif |
- return p; |
+ |
+ return p; |
} |
void sqlite3ScratchFree(void *p){ |
if( p ){ |
#if SQLITE_THREADSAFE==0 && !defined(NDEBUG) |
- /* Verify that no more than one scratch allocation per thread |
+ /* Verify that no more than two scratch allocation per thread |
** is outstanding at one time. (This is only checked in the |
** single-threaded case since checking in the multi-threaded case |
** would be much more complicated.) */ |
- assert( scratchAllocOut==1 ); |
- scratchAllocOut = 0; |
+ assert( scratchAllocOut>=1 && scratchAllocOut<=2 ); |
+ scratchAllocOut--; |
#endif |
- if( sqlite3GlobalConfig.pScratch==0 |
- || p<sqlite3GlobalConfig.pScratch |
- || p>=(void*)mem0.aScratchFree ){ |
+ if( p>=sqlite3GlobalConfig.pScratch && p<mem0.pScratchEnd ){ |
+ /* Release memory from the SQLITE_CONFIG_SCRATCH allocation */ |
+ ScratchFreeslot *pSlot; |
+ pSlot = (ScratchFreeslot*)p; |
+ sqlite3_mutex_enter(mem0.mutex); |
+ pSlot->pNext = mem0.pScratchFree; |
+ mem0.pScratchFree = pSlot; |
+ mem0.nScratchFree++; |
+ assert( mem0.nScratchFree <= (u32)sqlite3GlobalConfig.nScratch ); |
+ sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, -1); |
+ sqlite3_mutex_leave(mem0.mutex); |
+ }else{ |
+ /* Release memory back to the heap */ |
+ assert( sqlite3MemdebugHasType(p, MEMTYPE_SCRATCH) ); |
+ assert( sqlite3MemdebugNoType(p, ~MEMTYPE_SCRATCH) ); |
+ sqlite3MemdebugSetType(p, MEMTYPE_HEAP); |
if( sqlite3GlobalConfig.bMemstat ){ |
int iSize = sqlite3MallocSize(p); |
sqlite3_mutex_enter(mem0.mutex); |
sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, -iSize); |
sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -iSize); |
+ sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, -1); |
sqlite3GlobalConfig.m.xFree(p); |
sqlite3_mutex_leave(mem0.mutex); |
}else{ |
sqlite3GlobalConfig.m.xFree(p); |
} |
- }else{ |
- int i; |
- i = (int)((u8*)p - (u8*)sqlite3GlobalConfig.pScratch); |
- i /= sqlite3GlobalConfig.szScratch; |
- assert( i>=0 && i<sqlite3GlobalConfig.nScratch ); |
- sqlite3_mutex_enter(mem0.mutex); |
- assert( mem0.nScratchFree<(u32)sqlite3GlobalConfig.nScratch ); |
- mem0.aScratchFree[mem0.nScratchFree++] = i; |
- sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, -1); |
- sqlite3_mutex_leave(mem0.mutex); |
} |
} |
} |
@@ -410,7 +432,7 @@ void sqlite3ScratchFree(void *p){ |
*/ |
#ifndef SQLITE_OMIT_LOOKASIDE |
static int isLookaside(sqlite3 *db, void *p){ |
- return db && p && p>=db->lookaside.pStart && p<db->lookaside.pEnd; |
+ return p && p>=db->lookaside.pStart && p<db->lookaside.pEnd; |
} |
#else |
#define isLookaside(A,B) 0 |
@@ -421,13 +443,18 @@ static int isLookaside(sqlite3 *db, void *p){ |
** sqlite3Malloc() or sqlite3_malloc(). |
*/ |
int sqlite3MallocSize(void *p){ |
+ assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); |
+ assert( sqlite3MemdebugNoType(p, MEMTYPE_DB) ); |
return sqlite3GlobalConfig.m.xSize(p); |
} |
int sqlite3DbMallocSize(sqlite3 *db, void *p){ |
assert( db==0 || sqlite3_mutex_held(db->mutex) ); |
- if( isLookaside(db, p) ){ |
+ if( db && isLookaside(db, p) ){ |
return db->lookaside.sz; |
}else{ |
+ assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) ); |
+ assert( sqlite3MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) ); |
+ assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) ); |
return sqlite3GlobalConfig.m.xSize(p); |
} |
} |
@@ -436,10 +463,13 @@ int sqlite3DbMallocSize(sqlite3 *db, void *p){ |
** Free memory previously obtained from sqlite3Malloc(). |
*/ |
void sqlite3_free(void *p){ |
- if( p==0 ) return; |
+ if( p==0 ) return; /* IMP: R-49053-54554 */ |
+ assert( sqlite3MemdebugNoType(p, MEMTYPE_DB) ); |
+ assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) ); |
if( sqlite3GlobalConfig.bMemstat ){ |
sqlite3_mutex_enter(mem0.mutex); |
sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -sqlite3MallocSize(p)); |
+ sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, -1); |
sqlite3GlobalConfig.m.xFree(p); |
sqlite3_mutex_leave(mem0.mutex); |
}else{ |
@@ -453,14 +483,24 @@ void sqlite3_free(void *p){ |
*/ |
void sqlite3DbFree(sqlite3 *db, void *p){ |
assert( db==0 || sqlite3_mutex_held(db->mutex) ); |
- if( isLookaside(db, p) ){ |
- LookasideSlot *pBuf = (LookasideSlot*)p; |
- pBuf->pNext = db->lookaside.pFree; |
- db->lookaside.pFree = pBuf; |
- db->lookaside.nOut--; |
- }else{ |
- sqlite3_free(p); |
+ if( db ){ |
+ if( db->pnBytesFreed ){ |
+ *db->pnBytesFreed += sqlite3DbMallocSize(db, p); |
+ return; |
+ } |
+ if( isLookaside(db, p) ){ |
+ LookasideSlot *pBuf = (LookasideSlot*)p; |
+ pBuf->pNext = db->lookaside.pFree; |
+ db->lookaside.pFree = pBuf; |
+ db->lookaside.nOut--; |
+ return; |
+ } |
} |
+ assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) ); |
+ assert( sqlite3MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) ); |
+ assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) ); |
+ sqlite3MemdebugSetType(p, MEMTYPE_HEAP); |
+ sqlite3_free(p); |
} |
/* |
@@ -470,10 +510,10 @@ void *sqlite3Realloc(void *pOld, int nBytes){ |
int nOld, nNew; |
void *pNew; |
if( pOld==0 ){ |
- return sqlite3Malloc(nBytes); |
+ return sqlite3Malloc(nBytes); /* IMP: R-28354-25769 */ |
} |
if( nBytes<=0 ){ |
- sqlite3_free(pOld); |
+ sqlite3_free(pOld); /* IMP: R-31593-10574 */ |
return 0; |
} |
if( nBytes>=0x7fffff00 ){ |
@@ -481,6 +521,9 @@ void *sqlite3Realloc(void *pOld, int nBytes){ |
return 0; |
} |
nOld = sqlite3MallocSize(pOld); |
+ /* IMPLEMENTATION-OF: R-46199-30249 SQLite guarantees that the second |
+ ** argument to xRealloc is always a value returned by a prior call to |
+ ** xRoundup. */ |
nNew = sqlite3GlobalConfig.m.xRoundup(nBytes); |
if( nOld==nNew ){ |
pNew = pOld; |
@@ -491,6 +534,8 @@ void *sqlite3Realloc(void *pOld, int nBytes){ |
mem0.alarmThreshold ){ |
sqlite3MallocAlarm(nNew-nOld); |
} |
+ assert( sqlite3MemdebugHasType(pOld, MEMTYPE_HEAP) ); |
+ assert( sqlite3MemdebugNoType(pOld, ~MEMTYPE_HEAP) ); |
pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew); |
if( pNew==0 && mem0.alarmCallback ){ |
sqlite3MallocAlarm(nBytes); |
@@ -504,6 +549,7 @@ void *sqlite3Realloc(void *pOld, int nBytes){ |
}else{ |
pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew); |
} |
+ assert( EIGHT_BYTE_ALIGNMENT(pNew) ); /* IMP: R-04675-44850 */ |
return pNew; |
} |
@@ -563,20 +609,27 @@ void *sqlite3DbMallocZero(sqlite3 *db, int n){ |
void *sqlite3DbMallocRaw(sqlite3 *db, int n){ |
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 && n<=db->lookaside.sz |
- && (pBuf = db->lookaside.pFree)!=0 ){ |
- db->lookaside.pFree = pBuf->pNext; |
- db->lookaside.nOut++; |
- if( db->lookaside.nOut>db->lookaside.mxOut ){ |
- db->lookaside.mxOut = db->lookaside.nOut; |
+ if( db->lookaside.bEnabled ){ |
+ if( n>db->lookaside.sz ){ |
+ db->lookaside.anStat[1]++; |
+ }else if( (pBuf = db->lookaside.pFree)==0 ){ |
+ db->lookaside.anStat[2]++; |
+ }else{ |
+ db->lookaside.pFree = pBuf->pNext; |
+ db->lookaside.nOut++; |
+ db->lookaside.anStat[0]++; |
+ if( db->lookaside.nOut>db->lookaside.mxOut ){ |
+ db->lookaside.mxOut = db->lookaside.nOut; |
+ } |
+ return (void*)pBuf; |
} |
- return (void*)pBuf; |
} |
} |
#else |
@@ -588,6 +641,8 @@ void *sqlite3DbMallocRaw(sqlite3 *db, int n){ |
if( !p && db ){ |
db->mallocFailed = 1; |
} |
+ sqlite3MemdebugSetType(p, MEMTYPE_DB | |
+ ((db && db->lookaside.bEnabled) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP)); |
return p; |
} |
@@ -613,10 +668,16 @@ void *sqlite3DbRealloc(sqlite3 *db, void *p, int n){ |
sqlite3DbFree(db, p); |
} |
}else{ |
+ assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) ); |
+ assert( sqlite3MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) ); |
+ sqlite3MemdebugSetType(p, MEMTYPE_HEAP); |
pNew = sqlite3_realloc(p, n); |
if( !pNew ){ |
+ sqlite3MemdebugSetType(p, MEMTYPE_DB|MEMTYPE_HEAP); |
db->mallocFailed = 1; |
} |
+ sqlite3MemdebugSetType(pNew, MEMTYPE_DB | |
+ (db->lookaside.bEnabled ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP)); |
} |
} |
return pNew; |