diff options
-rw-r--r-- | manifest | 18 | ||||
-rw-r--r-- | manifest.uuid | 2 | ||||
-rw-r--r-- | src/mem3.c | 195 | ||||
-rw-r--r-- | src/vdbeaux.c | 31 | ||||
-rw-r--r-- | test/func.test | 3 | ||||
-rw-r--r-- | test/tester.tcl | 4 |
6 files changed, 110 insertions, 143 deletions
@@ -1,5 +1,5 @@ -C Go\sback\sto\sallocating\seach\spage\sand\sits\sheader\swith\sa\ssingle\smemory\nallocation.\s\sThis\sundoes\sthe\schange\sof\s(4409).\s(CVS\s4495) -D 2007-10-20T13:17:55 +C Simplify\sthe\smem3.c\smemory\sallocator.\s\sHave\sit\scall\ssqlite3_release_memory()\nautomatically,\swithout\shaving\sto\sspecify\sthe\ssoft\sheap\slimit.\s(CVS\s4496) +D 2007-10-20T15:41:58 F Makefile.in 30c7e3ba426ddb253b8ef037d1873425da6009a8 F Makefile.linux-gcc 65241babba6faf1152bf86574477baab19190499 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -104,7 +104,7 @@ F src/malloc.c de4e77fe70a9a0ac47a1c3a874422b107231bf31 F src/md5.c c5fdfa5c2593eaee2e32a5ce6c6927c986eaf217 F src/mem1.c cacb202bc379da10d69aa66d497c0ea7bd9cd8a5 F src/mem2.c 3f669b5e20975a5a2ca392aca891cd686e22b097 -F src/mem3.c 6a9329f368d9a6f3f1937c870e63f25db4921cef +F src/mem3.c 0a86f5a93f8adf8604c0f346e2e99d7f01494cae F src/mutex.c 3259f62c2429967aee6dc112117a6d2f499ef061 F src/mutex.h 079fa6fe9da18ceb89e79012c010594c6672addb F src/mutex_os2.c 7fe4773e98ed74a63b2e54fc557929eb155f6269 @@ -169,7 +169,7 @@ F src/vdbe.c 57e37b55c4dcdc9ed71c57180cee514c33d0e8f9 F src/vdbe.h 03a0fa17f6753a24d6cb585d7a362944a2c115aa F src/vdbeInt.h 630145b9bfaa19190ab491f52658a7db550f2247 F src/vdbeapi.c 21b69e71ab39d8e694c9cdb556a74dbefba9ebda -F src/vdbeaux.c 5f1e5e98a13235cbc446501fe040eb31423fface +F src/vdbeaux.c 99534543766eec8eb3727e6f9dc8ed64d95f1f2d F src/vdbeblob.c 82f51cdf9b0c0af729732fde48c824e498c0a1ca F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6 F src/vdbemem.c 123994fcd344993d2fb050a83b91b341bbbd08b4 @@ -307,7 +307,7 @@ F test/fts3an.test 2da4df52fe8ea8389f6fa7a01e4c1a0f091118d6 F test/fts3ao.test 0aa29dd4fc1c8d46b1f7cfe5926f7ac97551bea9 F test/fts3atoken.test 25c2070e1e8755d414bf9c8200427b277a9f99fa F test/fts3b.test b3a25180a633873d37d86e1ccd00ed690d37237a -F test/func.test 590fe3e1d28256d98dd73efb671de0823043e82a +F test/func.test fd05232dffa77492c473f5a71d2cde6cb0ccfb1a F test/fuzz.test 62fc19dd36a427777fd671b569df07166548628a F test/fuzz2.test ea38692ce2da99ad79fe0be5eb1a452c1c4d37bb F test/fuzz_common.tcl ff4bc2dfc465f6878f8e2d819620914365382731 @@ -428,7 +428,7 @@ F test/table.test 13b1c2e2fb4727b35ee1fb7641fc469214fd2455 F test/tableapi.test 92651a95c23cf955e92407928e640536402fa3cc F test/tclsqlite.test c7feea1985c3e8a1ed134ba342347d47fa762e43 F test/temptable.test 19b851b9e3e64d91e9867619b2a3f5fffee6e125 -F test/tester.tcl 0fea2ceef69678ee8b15d3dd64d29f659449a081 +F test/tester.tcl 58a86ba2f93f76c728e7a338f8b7724c566ce708 F test/thread001.test 8fbd9559da0bbdc273e00318c7fd66c162020af7 F test/thread002.test 2c4ad2c386f60f6fe268cd91c769ee35b3c1fd0b F test/thread1.test 776c9e459b75ba905193b351926ac4019b049f35 @@ -582,7 +582,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5 -P 30f014d3d0231a668c40508ff4a6b90ce622c857 -R 353b5c52c9c15c7259d8c65cac3000a2 +P f56c9884be796dee3f267aca6021eb1846d8527c +R 99add766d4a1a5f07507dd355d51b89c U drh -Z 00b4c63daba6680a8c5aa4fee0ee068a +Z 2b02a1a666d477f557917b5280cb451c diff --git a/manifest.uuid b/manifest.uuid index 2d2a7eead..b800c593c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f56c9884be796dee3f267aca6021eb1846d8527c
\ No newline at end of file +ca51b2f54076fcf73a8857aecf4b45d66ef0c7b6
\ No newline at end of file diff --git a/src/mem3.c b/src/mem3.c index 3b9b4028e..52663e574 100644 --- a/src/mem3.c +++ b/src/mem3.c @@ -20,7 +20,7 @@ ** This version of the memory allocation subsystem is used if ** and only if SQLITE_MEMORY_SIZE is defined. ** -** $Id: mem3.c,v 1.2 2007/10/20 12:34:01 drh Exp $ +** $Id: mem3.c,v 1.3 2007/10/20 15:41:58 drh Exp $ */ /* @@ -89,15 +89,8 @@ struct Mem3Block { */ static struct { /* - ** The alarm callback and its arguments. The mem.mutex lock will - ** be held while the callback is running. Recursive calls into - ** the memory subsystem are allowed, but no new callbacks will be - ** issued. The alarmBusy variable is set to prevent recursive - ** callbacks. + ** True if we are evaluating an out-of-memory callback. */ - sqlite3_int64 alarmThreshold; - void (*alarmCallback)(void*, sqlite3_int64,int); - void *alarmArg; int alarmBusy; /* @@ -106,10 +99,9 @@ static struct { sqlite3_mutex *mutex; /* - ** Current allocation and high-water mark. + ** The minimum amount of free space that we have seen. */ - sqlite3_int64 nowUsed; - sqlite3_int64 mxUsed; + int mnMaster; /* ** iMaster is the index of the master chunk. Most new allocations @@ -138,7 +130,7 @@ static struct { ** Unlink the chunk at mem.aPool[i] from list it is currently ** on. *pRoot is the list that i is a member of. */ -static void unlinkChunkFromList(int i, int *pRoot){ +static void memsys3UnlinkFromList(int i, int *pRoot){ int next = mem.aPool[i].u.list.next; int prev = mem.aPool[i].u.list.prev; if( prev==0 ){ @@ -157,16 +149,16 @@ static void unlinkChunkFromList(int i, int *pRoot){ ** Unlink the chunk at index i from ** whatever list is currently a member of. */ -static void unlinkChunk(int i){ +static void memsys3Unlink(int i){ int size, hash; size = mem.aPool[i-1].u.hdr.size; assert( size==mem.aPool[i+size-1].u.hdr.prevSize ); assert( size>=2 ); if( size <= MX_SMALL ){ - unlinkChunkFromList(i, &mem.aiSmall[size-2]); + memsys3UnlinkFromList(i, &mem.aiSmall[size-2]); }else{ hash = size % N_HASH; - unlinkChunkFromList(i, &mem.aiHash[hash]); + memsys3UnlinkFromList(i, &mem.aiHash[hash]); } } @@ -174,7 +166,7 @@ static void unlinkChunk(int i){ ** Link the chunk at mem.aPool[i] so that is on the list rooted ** at *pRoot. */ -static void linkChunkIntoList(int i, int *pRoot){ +static void memsys3LinkIntoList(int i, int *pRoot){ mem.aPool[i].u.list.next = *pRoot; mem.aPool[i].u.list.prev = 0; if( *pRoot ){ @@ -187,16 +179,16 @@ static void linkChunkIntoList(int i, int *pRoot){ ** Link the chunk at index i into either the appropriate ** small chunk list, or into the large chunk hash table. */ -static void linkChunk(int i){ +static void memsys3Link(int i){ int size, hash; size = mem.aPool[i-1].u.hdr.size; assert( size==mem.aPool[i+size-1].u.hdr.prevSize ); assert( size>=2 ); if( size <= MX_SMALL ){ - linkChunkIntoList(i, &mem.aiSmall[size-2]); + memsys3LinkIntoList(i, &mem.aiSmall[size-2]); }else{ hash = size % N_HASH; - linkChunkIntoList(i, &mem.aiHash[hash]); + memsys3LinkIntoList(i, &mem.aiHash[hash]); } } @@ -206,13 +198,14 @@ static void linkChunk(int i){ ** Also: Initialize the memory allocation subsystem the first time ** this routine is called. */ -static void enterMem(void){ +static void memsys3Enter(void){ if( mem.mutex==0 ){ mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); mem.aPool[0].u.hdr.size = SQLITE_MEMORY_SIZE/8; mem.aPool[SQLITE_MEMORY_SIZE/8].u.hdr.prevSize = SQLITE_MEMORY_SIZE/8; mem.iMaster = 1; mem.szMaster = SQLITE_MEMORY_SIZE/8; + mem.mnMaster = mem.szMaster; } sqlite3_mutex_enter(mem.mutex); } @@ -222,8 +215,8 @@ static void enterMem(void){ */ sqlite3_int64 sqlite3_memory_used(void){ sqlite3_int64 n; - enterMem(); - n = mem.nowUsed; + memsys3Enter(); + n = SQLITE_MEMORY_SIZE - mem.szMaster*8; sqlite3_mutex_leave(mem.mutex); return n; } @@ -235,58 +228,53 @@ sqlite3_int64 sqlite3_memory_used(void){ */ sqlite3_int64 sqlite3_memory_highwater(int resetFlag){ sqlite3_int64 n; - enterMem(); - n = mem.mxUsed; + memsys3Enter(); + n = SQLITE_MEMORY_SIZE - mem.mnMaster*8; if( resetFlag ){ - mem.mxUsed = mem.nowUsed; + mem.mnMaster = mem.szMaster; } sqlite3_mutex_leave(mem.mutex); return n; } /* -** Change the alarm callback +** Change the alarm callback. +** +** This is a no-op for the static memory allocator. The purpose +** of the memory alarm is to support sqlite3_soft_heap_limit(). +** But with this memory allocator, the soft_heap_limit is really +** a hard limit that is fixed at SQLITE_MEMORY_SIZE. */ int sqlite3_memory_alarm( void(*xCallback)(void *pArg, sqlite3_int64 used,int N), void *pArg, sqlite3_int64 iThreshold ){ - enterMem(); - mem.alarmCallback = xCallback; - mem.alarmArg = pArg; - mem.alarmThreshold = iThreshold; - sqlite3_mutex_leave(mem.mutex); return SQLITE_OK; } /* -** Trigger the alarm +** Called when we are unable to satisfy an allocation of nBytes. */ -static void sqlite3MemsysAlarm(int nByte){ - void (*xCallback)(void*,sqlite3_int64,int); - sqlite3_int64 nowUsed; - void *pArg; - if( mem.alarmCallback==0 || mem.alarmBusy ) return; - mem.alarmBusy = 1; - xCallback = mem.alarmCallback; - nowUsed = mem.nowUsed; - pArg = mem.alarmArg; - sqlite3_mutex_leave(mem.mutex); - xCallback(pArg, nowUsed, nByte); - sqlite3_mutex_enter(mem.mutex); - mem.alarmBusy = 0; +static void memsys3OutOfMemory(int nByte){ + if( !mem.alarmBusy ){ + mem.alarmBusy = 1; + sqlite3_mutex_leave(mem.mutex); + sqlite3_release_memory(nByte); + sqlite3_mutex_enter(mem.mutex); + mem.alarmBusy = 0; + } } /* ** Return the size of an outstanding allocation, in bytes. The -** size returned includes the 8-byte header overhead. This only +** size returned omits the 8-byte header overhead. This only ** works for chunks that are currently checked out. */ -static int internal_size(void *p){ +static int memsys3Size(void *p){ Mem3Block *pBlock = (Mem3Block*)p; assert( pBlock[-1].u.hdr.size<0 ); - return -pBlock[-1].u.hdr.size*8; + return (1-pBlock[-1].u.hdr.size)*8; } /* @@ -294,7 +282,7 @@ static int internal_size(void *p){ ** size parameters for check-out and return a pointer to the ** user portion of the chunk. */ -static void *checkOutChunk(int i, int nBlock){ +static void *memsys3Checkout(int i, int nBlock){ assert( mem.aPool[i-1].u.hdr.size==nBlock ); assert( mem.aPool[i+nBlock-1].u.hdr.prevSize==nBlock ); mem.aPool[i-1].u.hdr.size = -nBlock; @@ -307,13 +295,14 @@ static void *checkOutChunk(int i, int nBlock){ ** Return a pointer to the new allocation. Or, if the master chunk ** is not large enough, return 0. */ -static void *internal_from_master(int nBlock){ +static void *memsys3FromMaster(int nBlock){ assert( mem.szMaster>=nBlock ); if( nBlock>=mem.szMaster-1 ){ /* Use the entire master */ - void *p = checkOutChunk(mem.iMaster, mem.szMaster); + void *p = memsys3Checkout(mem.iMaster, mem.szMaster); mem.iMaster = 0; mem.szMaster = 0; + mem.mnMaster = 0; return p; }else{ /* Split the master block. Return the tail. */ @@ -325,6 +314,9 @@ static void *internal_from_master(int nBlock){ mem.szMaster -= nBlock; mem.aPool[newi-1].u.hdr.prevSize = mem.szMaster; mem.aPool[mem.iMaster-1].u.hdr.size = mem.szMaster; + if( mem.szMaster < mem.mnMaster ){ + mem.mnMaster = mem.szMaster; + } return (void*)&mem.aPool[newi]; } } @@ -345,7 +337,7 @@ static void *internal_from_master(int nBlock){ ** chunk before invoking this routine, then must unlink the (possibly ** changed) master chunk once this routine has finished. */ -static void mergeChunks(int *pRoot){ +static void memsys3Merge(int *pRoot){ int iNext, prev, size, i; for(i=*pRoot; i>0; i=iNext){ @@ -353,17 +345,17 @@ static void mergeChunks(int *pRoot){ size = mem.aPool[i-1].u.hdr.size; assert( size>0 ); if( mem.aPool[i-1].u.hdr.prevSize>0 ){ - unlinkChunkFromList(i, pRoot); + memsys3UnlinkFromList(i, pRoot); prev = i - mem.aPool[i-1].u.hdr.prevSize; assert( prev>=0 ); if( prev==iNext ){ iNext = mem.aPool[prev].u.list.next; } - unlinkChunk(prev); + memsys3Unlink(prev); size = i + size - prev; mem.aPool[prev-1].u.hdr.size = size; mem.aPool[prev+size-1].u.hdr.prevSize = size; - linkChunk(prev); + memsys3Link(prev); i = prev; } if( size>mem.szMaster ){ @@ -377,7 +369,7 @@ static void mergeChunks(int *pRoot){ ** Return a block of memory of at least nBytes in size. ** Return NULL if unable. */ -static void *internal_malloc(int nByte){ +static void *memsys3Malloc(int nByte){ int i; int nBlock; @@ -397,15 +389,15 @@ static void *internal_malloc(int nByte){ if( nBlock <= MX_SMALL ){ i = mem.aiSmall[nBlock-2]; if( i>0 ){ - unlinkChunkFromList(i, &mem.aiSmall[nBlock-2]); - return checkOutChunk(i, nBlock); + memsys3UnlinkFromList(i, &mem.aiSmall[nBlock-2]); + return memsys3Checkout(i, nBlock); } }else{ int hash = nBlock % N_HASH; for(i=mem.aiHash[hash]; i>0; i=mem.aPool[i].u.list.next){ if( mem.aPool[i-1].u.hdr.size==nBlock ){ - unlinkChunkFromList(i, &mem.aiHash[hash]); - return checkOutChunk(i, nBlock); + memsys3UnlinkFromList(i, &mem.aiHash[hash]); + return memsys3Checkout(i, nBlock); } } } @@ -415,7 +407,7 @@ static void *internal_malloc(int nByte){ ** of the master chunk. This step usually works if step 1 fails. */ if( mem.szMaster>=nBlock ){ - return internal_from_master(nBlock); + return memsys3FromMaster(nBlock); } @@ -426,21 +418,22 @@ static void *internal_malloc(int nByte){ ** of the end of the master chunk. This step happens very ** rarely (we hope!) */ + memsys3OutOfMemory(nBlock*16); if( mem.iMaster ){ - linkChunk(mem.iMaster); + memsys3Link(mem.iMaster); mem.iMaster = 0; mem.szMaster = 0; } for(i=0; i<N_HASH; i++){ - mergeChunks(&mem.aiHash[i]); + memsys3Merge(&mem.aiHash[i]); } for(i=0; i<MX_SMALL-1; i++){ - mergeChunks(&mem.aiSmall[i]); + memsys3Merge(&mem.aiSmall[i]); } if( mem.szMaster ){ - unlinkChunk(mem.iMaster); + memsys3Unlink(mem.iMaster); if( mem.szMaster>=nBlock ){ - return internal_from_master(nBlock); + return memsys3FromMaster(nBlock); } } @@ -451,7 +444,7 @@ static void *internal_malloc(int nByte){ /* ** Free an outstanding memory allocation. */ -void internal_free(void *pOld){ +void memsys3Free(void *pOld){ Mem3Block *p = (Mem3Block*)pOld; int i; int size; @@ -462,7 +455,7 @@ void internal_free(void *pOld){ assert( mem.aPool[i+size-1].u.hdr.prevSize==-size ); mem.aPool[i-1].u.hdr.size = size; mem.aPool[i+size-1].u.hdr.prevSize = size; - linkChunk(i); + memsys3Link(i); /* Try to expand the master using the newly freed chunk */ if( mem.iMaster ){ @@ -470,12 +463,12 @@ void internal_free(void *pOld){ size = mem.aPool[mem.iMaster-1].u.hdr.prevSize; mem.iMaster -= size; mem.szMaster += size; - unlinkChunk(mem.iMaster); + memsys3Unlink(mem.iMaster); mem.aPool[mem.iMaster-1].u.hdr.size = mem.szMaster; mem.aPool[mem.iMaster+mem.szMaster-1].u.hdr.prevSize = mem.szMaster; } while( mem.aPool[mem.iMaster+mem.szMaster-1].u.hdr.size>0 ){ - unlinkChunk(mem.iMaster+mem.szMaster); + memsys3Unlink(mem.iMaster+mem.szMaster); mem.szMaster += mem.aPool[mem.iMaster+mem.szMaster-1].u.hdr.size; mem.aPool[mem.iMaster-1].u.hdr.size = mem.szMaster; mem.aPool[mem.iMaster+mem.szMaster-1].u.hdr.prevSize = mem.szMaster; @@ -489,21 +482,8 @@ void internal_free(void *pOld){ void *sqlite3_malloc(int nBytes){ sqlite3_int64 *p = 0; if( nBytes>0 ){ - enterMem(); - if( mem.alarmCallback!=0 && mem.nowUsed+nBytes>=mem.alarmThreshold ){ - sqlite3MemsysAlarm(nBytes); - } - p = internal_malloc(nBytes); - if( p==0 ){ - sqlite3MemsysAlarm(nBytes); - p = internal_malloc(nBytes); - } - if( p ){ - mem.nowUsed += internal_size(p); - if( mem.nowUsed>mem.mxUsed ){ - mem.mxUsed = mem.nowUsed; - } - } + memsys3Enter(); + p = memsys3Malloc(nBytes); sqlite3_mutex_leave(mem.mutex); } return (void*)p; @@ -518,8 +498,7 @@ void sqlite3_free(void *pPrior){ } assert( mem.mutex!=0 ); sqlite3_mutex_enter(mem.mutex); - mem.nowUsed -= internal_size(pPrior); - internal_free(pPrior); + memsys3Free(pPrior); sqlite3_mutex_leave(mem.mutex); } @@ -537,29 +516,21 @@ void *sqlite3_realloc(void *pPrior, int nBytes){ return 0; } assert( mem.mutex!=0 ); - sqlite3_mutex_enter(mem.mutex); - nOld = internal_size(pPrior); - if( mem.alarmCallback!=0 && mem.nowUsed+nBytes-nOld>=mem.alarmThreshold ){ - sqlite3MemsysAlarm(nBytes-nOld); + nOld = memsys3Size(pPrior); +#if 0 + if( nBytes<=nOld && nBytes>=nOld-128 ){ + return pPrior; } - p = internal_malloc(nBytes); - if( p==0 ){ - sqlite3MemsysAlarm(nBytes); - p = internal_malloc(nBytes); - if( p==0 ){ - sqlite3_mutex_leave(mem.mutex); - return 0; +#endif + sqlite3_mutex_enter(mem.mutex); + p = memsys3Malloc(nBytes); + if( p ){ + if( nOld<nBytes ){ + memcpy(p, pPrior, nOld); + }else{ + memcpy(p, pPrior, nBytes); } - } - if( nOld<nBytes ){ - memcpy(p, pPrior, nOld); - }else{ - memcpy(p, pPrior, nBytes); - } - internal_free(pPrior); - mem.nowUsed += internal_size(p)-nOld; - if( mem.nowUsed>mem.mxUsed ){ - mem.mxUsed = mem.nowUsed; + memsys3Free(pPrior); } sqlite3_mutex_leave(mem.mutex); return p; @@ -583,7 +554,7 @@ void sqlite3_memdebug_dump(const char *zFilename){ return; } } - enterMem(); + memsys3Enter(); fprintf(out, "CHUNKS:\n"); for(i=1; i<=SQLITE_MEMORY_SIZE/8; i+=size){ size = mem.aPool[i-1].u.hdr.size; @@ -622,8 +593,8 @@ void sqlite3_memdebug_dump(const char *zFilename){ fprintf(out, "\n"); } fprintf(out, "master=%d\n", mem.iMaster); - fprintf(out, "nowUsed=%lld\n", mem.nowUsed); - fprintf(out, "mxUsed=%lld\n", mem.mxUsed); + fprintf(out, "nowUsed=%d\n", SQLITE_MEMORY_SIZE - mem.szMaster*8); + fprintf(out, "mxUsed=%d\n", SQLITE_MEMORY_SIZE - mem.mnMaster*8); sqlite3_mutex_leave(mem.mutex); if( out==stdout ){ fflush(stdout); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 8a6187214..df79d8bf4 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -99,10 +99,7 @@ void sqlite3VdbeTrace(Vdbe *p, FILE *trace){ /* ** Resize the Vdbe.aOp array so that it contains at least N -** elements. If the Vdbe is in VDBE_MAGIC_RUN state, then -** the Vdbe.aOp array will be sized to contain exactly N -** elements. Vdbe.nOpAlloc is set to reflect the new size of -** the array. +** elements. ** ** If an out-of-memory error occurs while resizing the array, ** Vdbe.aOp and Vdbe.nOpAlloc remain unchanged (this is so that @@ -110,18 +107,14 @@ void sqlite3VdbeTrace(Vdbe *p, FILE *trace){ ** along with the rest of the Vdbe). */ static void resizeOpArray(Vdbe *p, int N){ - int runMode = p->magic==VDBE_MAGIC_RUN; - if( runMode || p->nOpAlloc<N ){ - VdbeOp *pNew; - int nNew = N + 100*(!runMode); - int oldSize = p->nOpAlloc; - pNew = sqlite3DbRealloc(p->db, p->aOp, nNew*sizeof(Op)); - if( pNew ){ - p->nOpAlloc = nNew; - p->aOp = pNew; - if( nNew>oldSize ){ - memset(&p->aOp[oldSize], 0, (nNew-oldSize)*sizeof(Op)); - } + VdbeOp *pNew; + int oldSize = p->nOpAlloc; + pNew = sqlite3DbRealloc(p->db, p->aOp, N*sizeof(Op)); + if( pNew ){ + p->nOpAlloc = N; + p->aOp = pNew; + if( N>oldSize ){ + memset(&p->aOp[oldSize], 0, (N-oldSize)*sizeof(Op)); } } } @@ -149,7 +142,7 @@ int sqlite3VdbeAddOp(Vdbe *p, int op, int p1, int p2){ i = p->nOp; assert( p->magic==VDBE_MAGIC_INIT ); if( p->nOpAlloc<=i ){ - resizeOpArray(p, i+1); + resizeOpArray(p, p->nOpAlloc*2 + 100); if( p->db->mallocFailed ){ return 0; } @@ -360,7 +353,9 @@ int sqlite3VdbeCurrentAddr(Vdbe *p){ int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp){ int addr; assert( p->magic==VDBE_MAGIC_INIT ); - resizeOpArray(p, p->nOp + nOp); + if( p->nOp + nOp > p->nOpAlloc ){ + resizeOpArray(p, p->nOp*2 + nOp); + } if( p->db->mallocFailed ){ return 0; } diff --git a/test/func.test b/test/func.test index 3149c5427..8af5a88d2 100644 --- a/test/func.test +++ b/test/func.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. The # focus of this file is testing built-in functions. # -# $Id: func.test,v 1.69 2007/09/12 17:01:45 danielk1977 Exp $ +# $Id: func.test,v 1.70 2007/10/20 15:41:58 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -465,6 +465,7 @@ do_test func-12.7 { } } {} + # Test that the auxdata API for scalar functions works. This test uses # a special user-defined function only available in test builds, # test_auxdata(). Function test_auxdata() takes any number of arguments. diff --git a/test/tester.tcl b/test/tester.tcl index 2b24f3b6e..5b1939b21 100644 --- a/test/tester.tcl +++ b/test/tester.tcl @@ -11,7 +11,7 @@ # This file implements some common TCL routines used for regression # testing the SQLite library # -# $Id: tester.tcl,v 1.92 2007/10/15 19:34:32 drh Exp $ +# $Id: tester.tcl,v 1.93 2007/10/20 15:41:58 drh Exp $ set tcl_precision 15 @@ -197,7 +197,7 @@ proc finalize_testing {} { if {[sqlite3_memory_used]>0} { puts "Unfreed memory: [sqlite3_memory_used] bytes" incr nErr - ifcapable memdebug { + ifcapable memdebug||(mem3&&debug) { puts "Writing unfreed memory log to \"./memleak.txt\"" sqlite3_memdebug_dump ./memleak.txt } |