]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Simplify the mem3.c memory allocator. Have it call sqlite3_release_memory()
authordrh <drh@noemail.net>
Sat, 20 Oct 2007 15:41:57 +0000 (15:41 +0000)
committerdrh <drh@noemail.net>
Sat, 20 Oct 2007 15:41:57 +0000 (15:41 +0000)
automatically, without having to specify the soft heap limit. (CVS 4496)

FossilOrigin-Name: ca51b2f54076fcf73a8857aecf4b45d66ef0c7b6

manifest
manifest.uuid
src/mem3.c
src/vdbeaux.c
test/func.test
test/tester.tcl

index 0028f206072252f24552920f357e0297b65b7eb3..22508c9aa456f50baf01657988ebd2b2ab5253d4 100644 (file)
--- a/manifest
+++ b/manifest
@@ -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
index 2d2a7eeaddc42b0e29998df447f392dcbb870d54..b800c593cee4473b12a357ddda12fd513bd435c0 100644 (file)
@@ -1 +1 @@
-f56c9884be796dee3f267aca6021eb1846d8527c
\ No newline at end of file
+ca51b2f54076fcf73a8857aecf4b45d66ef0c7b6
\ No newline at end of file
index 3b9b4028e9eb2bd9fdd3e8e1cbd9e3fb14ce626c..52663e5748f5213619db14dc05b386ea306b20cd 100644 (file)
@@ -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);
index 8a6187214a5dbbdfc16decbfc5cce4b77304a4b7..df79d8bf4a6d414a7e1eed1a600e34604462d044 100644 (file)
@@ -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;
   }
index 3149c54276ca914bab3a9795107b400c1376d172..8af5a88d2f729deb6533e33587d215c0bf799552 100644 (file)
@@ -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.
index 2b24f3b6e90abbfcfff5b9772f0040fa7b428672..5b1939b212b1ce57774478ce21f9e3c2a95d092e 100644 (file)
@@ -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
     }