]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Memory handling fixes and optimizations in the VDBE. Ticket #862. (CVS 1909)
authordrh <drh@noemail.net>
Sat, 28 Aug 2004 18:17:48 +0000 (18:17 +0000)
committerdrh <drh@noemail.net>
Sat, 28 Aug 2004 18:17:48 +0000 (18:17 +0000)
FossilOrigin-Name: 5f8d246852c7cefd5941b8c7bb22177dfc7157c5

manifest
manifest.uuid
src/vdbe.c
src/vdbeInt.h
src/vdbemem.c

index 404c3299dde408afe69db8736a74d54c2adfd440..3f24c7ac6f7702fc6b4c1b9aab04aa82632f2411 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\sthe\ssqlite3_libversion()\sAPI\s(ticket\s#834).\s\sFix\sthe\sbuild\sscripts\sto\ncorrectly\sbuild\sthe\sshared\slibraries\swith\sversion\s8.4\sof\sTcl.\s(CVS\s1908)
-D 2004-08-28T16:19:01
+C Memory\shandling\sfixes\sand\soptimizations\sin\sthe\sVDBE.\s\sTicket\s#862.\s(CVS\s1909)
+D 2004-08-28T18:17:48
 F Makefile.in 65a7c43fcaf9a710d62f120b11b6e435eeb4a450
 F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@@ -75,12 +75,12 @@ F src/update.c 151f1869ce532ed883f1ce26306f0b0fa7b2589a
 F src/utf.c 3d8f7bffcbefcced69a436c9e0a1c7eb9e0bb4fa
 F src/util.c e2c631849cc9e035f6fd387f507ad8886f77cedd
 F src/vacuum.c 9978a5760c2c430bc5b5e66505a02dad76f25813
-F src/vdbe.c ea662188cc489934a567d1eaa3fb6754d5b92b7d
+F src/vdbe.c 28a48fcee38d2601cb00adc02bdac475bd43e176
 F src/vdbe.h e081c72cd0f7c19d49b1927460aeefcf0fbc85ac
-F src/vdbeInt.h 16322cbfccf0b05631fcf0df68b115c46584d6c9
+F src/vdbeInt.h aadadddc8cfad6aa5a5445c849f70d881276fe34
 F src/vdbeapi.c 854732720c2cfc6ff76b28eef6253ac84a5408bc
 F src/vdbeaux.c 022c484dba235d2dcbb1faca0f1943702f4232ed
-F src/vdbemem.c 68fefaf83adb48fe44135da01502c9327f6172b0
+F src/vdbemem.c 8971ecc9e56f8b7dbde865906753dbd7812a4f8f
 F src/where.c a84eee276cd072158224da6b5f30733df2d56027
 F test/all.test 3b692eb43583b52c99c344b2fa8934512d179016
 F test/attach.test feb2ce54e78688df4c84553416d5aec3b2a0112e
@@ -244,7 +244,7 @@ F www/tclsqlite.tcl 560ecd6a916b320e59f2917317398f3d59b7cc25
 F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9
 F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
-P 6ef1f662d71c75bdb7f61b2fff03f5b1b41e5586
-R 5b251c944f99c3bf147bc10eb4f70f96
+P 6db26a19ea7ac77be41a7416dedaef1b9dfd9e16
+R 99e5b852a5fab1a5e5963194c447eb34
 U drh
-Z 5c52cbb1dda1a18b82f5188a439efbf0
+Z b40cbed2b276adf8c405b360bef48d5f
index 78ab67cc41db97a00595d9577783ab948f267fc7..d1b0dcbf2e23c02d80cf56bc8a4d4bd80f01f3d6 100644 (file)
@@ -1 +1 @@
-6db26a19ea7ac77be41a7416dedaef1b9dfd9e16
\ No newline at end of file
+5f8d246852c7cefd5941b8c7bb22177dfc7157c5
\ No newline at end of file
index 5a92c9b07854e4c5419efdd1dbdbf14de617ccda..81e3b6ab6ee382ad14daed812ad2ab681d46a3c8 100644 (file)
@@ -43,7 +43,7 @@
 ** in this file for details.  If in doubt, do not deviate from existing
 ** commenting and indentation practices when changing or adding code.
 **
-** $Id: vdbe.c,v 1.409 2004/08/21 17:54:45 drh Exp $
+** $Id: vdbe.c,v 1.410 2004/08/28 18:17:48 drh Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -792,12 +792,7 @@ case OP_Variable: {
   assert( j>=0 && j<p->nVar );
 
   pTos++;
-  memcpy(pTos, &p->aVar[j], sizeof(*pTos)-NBFS);
-  pTos->xDel = 0;
-  if( pTos->flags&(MEM_Str|MEM_Blob) ){
-    pTos->flags &= ~(MEM_Dyn|MEM_Ephem|MEM_Short);
-    pTos->flags |= MEM_Static;
-  }
+  sqlite3VdbeMemShallowCopy(pTos, &p->aVar[j], MEM_Static);
   break;
 }
 
@@ -831,23 +826,9 @@ case OP_Dup: {
   Mem *pFrom = &pTos[-pOp->p1];
   assert( pFrom<=pTos && pFrom>=p->aStack );
   pTos++;
-  memcpy(pTos, pFrom, sizeof(*pFrom)-NBFS);
-  pTos->xDel = 0;
-  if( pTos->flags & (MEM_Str|MEM_Blob) ){
-    if( pOp->p2 && (pTos->flags & (MEM_Dyn|MEM_Ephem)) ){
-      pTos->flags &= ~MEM_Dyn;
-      pTos->flags |= MEM_Ephem;
-    }else if( pTos->flags & MEM_Short ){
-      memcpy(pTos->zShort, pFrom->zShort, pTos->n+2);
-      pTos->z = pTos->zShort;
-    }else if( (pTos->flags & MEM_Static)==0 ){
-      pTos->z = sqliteMallocRaw(pFrom->n+2);
-      if( sqlite3_malloc_failed ) goto no_mem;
-      memcpy(pTos->z, pFrom->z, pFrom->n);
-      memcpy(&pTos->z[pTos->n], "\0", 2);
-      pTos->flags &= ~(MEM_Static|MEM_Ephem|MEM_Short);
-      pTos->flags |= MEM_Dyn|MEM_Term;
-    }
+  sqlite3VdbeMemShallowCopy(pTos, pFrom, MEM_Ephem);
+  if( pOp->p2 ){
+    Deephemeralize(pTos);
   }
   break;
 }
@@ -898,13 +879,7 @@ case OP_Push: {
   Mem *pTo = &pTos[-pOp->p1];
 
   assert( pTo>=p->aStack );
-  Deephemeralize(pTos);
-  Release(pTo);
-  *pTo = *pTos;
-  if( pTo->flags & MEM_Short ){
-    assert( pTo->z==pTos->zShort );
-    pTo->z = pTo->zShort;
-  }
+  sqlite3VdbeMemMove(pTo, pTos);
   pTos--;
   break;
 }
@@ -1240,12 +1215,11 @@ case OP_Function: {
   }
 
   /* Copy the result of the function to the top of the stack */
-  pTos++;
   sqlite3VdbeChangeEncoding(&ctx.s, db->enc);
-  *pTos = ctx.s;
-  if( pTos->flags & MEM_Short ){
-    pTos->z = pTos->zShort;
-  }
+  pTos++;
+  pTos->flags = 0;
+  sqlite3VdbeMemMove(pTos, &ctx.s);
+
   /* If the function returned an error, throw an exception */
   if( ctx.isError ){
     if( !(pTos->flags&MEM_Str) ){
@@ -1773,6 +1747,7 @@ case OP_Column: {
   sMem.flags = 0;
   assert( p1<p->nCursor );
   pTos++;
+  pTos->flags = MEM_Null;
 
   /* This block sets the variable payloadSize to be the total number of
   ** bytes in the record.
@@ -1937,6 +1912,9 @@ case OP_Column: {
 
   /* Get the column information.
   */
+  if( rc!=SQLITE_OK ){
+    goto abort_due_to_error;
+  }
   if( zRec ){
     zData = &zRec[aOffset[p2]];
   }else{
@@ -1945,14 +1923,25 @@ case OP_Column: {
     zData = sMem.z;
   }
   sqlite3VdbeSerialGet(zData, aType[p2], pTos);
-  if( sqlite3VdbeMemMakeWriteable(pTos)==SQLITE_NOMEM ){
-    goto no_mem;
-  }
   pTos->enc = db->enc;
-  if( rc!=SQLITE_OK ){
-    goto abort_due_to_error;
+
+  /* If we dynamically allocated space to hold the data (in the
+  ** sqlite3VdbeMemFromBtree() call above) then transfer control of that
+  ** dynamically allocated space over to the pTos structure rather.
+  ** This prevents a memory copy.
+  */
+  if( (sMem.flags & MEM_Dyn)!=0 ){
+    assert( pTos->flags & MEM_Ephem );
+    assert( pTos->flags & (MEM_Str|MEM_Blob) );
+    assert( pTos->z==sMem.z );
+    assert( sMem.flags & MEM_Term );
+    pTos->flags &= ~MEM_Ephem;
+    pTos->flags |= MEM_Dyn|MEM_Term;
   }
-  Release(&sMem);
+
+  /* pTos->z might be pointing to sMem.zShort[].  Fix that so that we
+  ** can abandon sMem */
+  rc = sqlite3VdbeMemMakeWriteable(pTos);
 
   /* Release the aType[] memory if we are not dealing with cursor */
   if( !pC ){
@@ -3250,6 +3239,7 @@ case OP_FullKey: {
   assert( p->apCsr[i]->keyAsData );
   assert( !p->apCsr[i]->pseudoTable );
   pTos++;
+  pTos->flags = MEM_Null;
   if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
     i64 amt;
     char *z;
@@ -3506,6 +3496,7 @@ case OP_IdxRecno: {
   assert( i>=0 && i<p->nCursor );
   assert( p->apCsr[i]!=0 );
   pTos++;
+  pTos->flags = MEM_Null;
   if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
     i64 rowid;
 
@@ -3521,8 +3512,6 @@ case OP_IdxRecno: {
       pTos->flags = MEM_Int;
       pTos->i = rowid;
     }
-  }else{
-    pTos->flags = MEM_Null;
   }
   break;
 }
@@ -4019,8 +4008,6 @@ case OP_SortPut: {
   pSorter->zKey = pTos->z;
   pSorter->data.flags = MEM_Null;
   rc = sqlite3VdbeMemMove(&pSorter->data, pNos);
-  if( rc!=SQLITE_OK ) goto abort_due_to_error;
-  Deephemeralize(&pSorter->data);
   pTos -= 2;
   break;
 }
@@ -4080,7 +4067,6 @@ case OP_SortNext: {
     pTos++;
     pTos->flags = MEM_Null;
     rc = sqlite3VdbeMemMove(pTos, &pSorter->data);
-    assert( rc==SQLITE_OK );
     sqliteFree(pSorter->zKey);
     sqliteFree(pSorter);
   }else{
@@ -4109,18 +4095,9 @@ case OP_SortReset: {
 ** the original data remains on the stack.
 */
 case OP_MemStore: {
-  int i = pOp->p1;
-  Mem *pMem;
   assert( pTos>=p->aStack );
-  assert( i<p->nMem );
-  Deephemeralize(pTos);
-  pMem = &p->aMem[i];
-  Release(pMem);
-  *pMem = *pTos;
-  pTos->flags = MEM_Null;
-  if( pMem->flags & MEM_Short ){
-    pMem->z = pMem->zShort;
-  }
+  assert( pOp->p1>=0 && pOp->p1<p->nMem );
+  rc = sqlite3VdbeMemMove(&p->aMem[pOp->p1], pTos);
   pTos--;
 
   /* If P2 is 0 then fall thru to the next opcode, OP_MemLoad, that will
@@ -4143,12 +4120,7 @@ case OP_MemLoad: {
   int i = pOp->p1;
   assert( i>=0 && i<p->nMem );
   pTos++;
-  memcpy(pTos, &p->aMem[i], sizeof(pTos[0])-NBFS);;
-  pTos->xDel = 0;
-  if( pTos->flags & (MEM_Str|MEM_Blob) ){
-    pTos->flags |= MEM_Ephem;
-    pTos->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short);
-  }
+  sqlite3VdbeMemShallowCopy(pTos, &p->aMem[i], MEM_Ephem);
   break;
 }
 
@@ -4322,20 +4294,12 @@ case OP_AggFocus: {
 case OP_AggSet: {
   AggElem *pFocus;
   int i = pOp->p2;
-  Mem *pMem;
   rc = AggInFocus(&p->agg, &pFocus);
   if( rc!=SQLITE_OK ) goto abort_due_to_error;
   assert( pTos>=p->aStack );
   if( pFocus==0 ) goto no_mem;
   assert( i>=0 && i<p->agg.nMem );
-  Deephemeralize(pTos);
-  pMem = &pFocus->aMem[i];
-  Release(pMem);
-  *pMem = *pTos;
-  pTos->flags = MEM_Null;
-  if( pMem->flags & MEM_Short ){
-    pMem->z = pMem->zShort;
-  }
+  rc = sqlite3VdbeMemMove(&pFocus->aMem[i], pTos);
   pTos--;
   break;
 }
@@ -4348,23 +4312,19 @@ case OP_AggSet: {
 */
 case OP_AggGet: {
   AggElem *pFocus;
-  Mem *pMem;
   int i = pOp->p2;
   rc = AggInFocus(&p->agg, &pFocus);
   if( rc!=SQLITE_OK ) goto abort_due_to_error;
   if( pFocus==0 ) goto no_mem;
   assert( i>=0 && i<p->agg.nMem );
   pTos++;
-  pMem = &pFocus->aMem[i];
-  *pTos = *pMem;
-  pTos->xDel = 0;
-  if( pTos->flags & (MEM_Str|MEM_Blob) ){
-    pTos->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short);
-    pTos->flags |= MEM_Ephem;
-  }
+  sqlite3VdbeMemShallowCopy(pTos, &pFocus->aMem[i], MEM_Ephem);
+  assert( (pTos->flags & MEM_Str)==0 || pTos->enc==db->enc );
+#if 0
   if( pTos->flags&MEM_Str ){
     sqlite3VdbeChangeEncoding(pTos, db->enc);
   }
+#endif
   break;
 }
 
index af6667a9f1290d1631bc687f8e244966f2c094a0..c16c2613673a2518d5ff34a6f78eba7f0cb16e75 100644 (file)
@@ -381,6 +381,7 @@ int sqlite3VdbeExec(Vdbe*);
 int sqlite3VdbeList(Vdbe*);
 int sqlite3VdbeChangeEncoding(Mem *, int);
 int sqlite3VdbeMemCopy(Mem*, const Mem*);
+void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int);
 int sqlite3VdbeMemMove(Mem*, Mem*);
 int sqlite3VdbeMemNulTerminate(Mem*);
 int sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, void(*)(void*));
index b842fc775d8061c011bb11388596cf4097b36b53..434ec4daa1aa918a58c253e3b084a5fd4fbf683e 100644 (file)
@@ -299,16 +299,32 @@ void sqlite3VdbeMemSetDouble(Mem *pMem, double val){
 }
 
 /*
-** Copy the contents of memory cell pFrom into pTo.
+** Make an shallow copy of pFrom into pTo.  Prior contents of
+** pTo are overwritten.  The pFrom->z field is not duplicated.  If
+** pFrom->z is used, then pTo->z points to the same thing as pFrom->z
+** and flags gets srcType (either MEM_Ephem or MEM_Static).
 */
-int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){
-  int rc;
-  sqlite3VdbeMemRelease(pTo);
+void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){
   memcpy(pTo, pFrom, sizeof(*pFrom)-sizeof(pFrom->zShort));
   pTo->xDel = 0;
   if( pTo->flags & (MEM_Str|MEM_Blob) ){
-    pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short);
-    pTo->flags |= MEM_Ephem;
+    pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short|MEM_Ephem);
+    assert( srcType==MEM_Ephem || srcType==MEM_Static );
+    pTo->flags |= srcType;
+  }
+}
+
+/*
+** Make a full copy of pFrom into pTo.  Prior contents of pTo are
+** freed before the copy is made.
+*/
+int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){
+  int rc;
+  if( pTo->flags & MEM_Dyn ){
+    sqlite3VdbeMemRelease(pTo);
+  }
+  sqlite3VdbeMemShallowCopy(pTo, pFrom, MEM_Ephem);
+  if( pTo->flags & MEM_Ephem ){
     rc = sqlite3VdbeMemMakeWriteable(pTo);
   }else{
     rc = SQLITE_OK;
@@ -318,16 +334,29 @@ int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){
 
 /*
 ** Transfer the contents of pFrom to pTo. Any existing value in pTo is
-** deleted. pFrom contains an SQL NULL when this routine returns.
+** freed. If pFrom contains ephemeral data, a copy is made.
+**
+** pFrom contains an SQL NULL when this routine returns.  SQLITE_NOMEM
+** might be returned if pFrom held ephemeral data and we were unable
+** to allocate enough space to make a copy.
 */
 int sqlite3VdbeMemMove(Mem *pTo, Mem *pFrom){
+  int rc;
+  if( pTo->flags & MEM_Dyn ){
+    sqlite3VdbeMemRelease(pTo);
+  }
   memcpy(pTo, pFrom, sizeof(Mem));
   if( pFrom->flags & MEM_Short ){
     pTo->z = pTo->zShort;
   }
   pFrom->flags = MEM_Null;
   pFrom->xDel = 0;
-  return SQLITE_OK;
+  if( pTo->flags & MEM_Ephem ){
+    rc = sqlite3VdbeMemMakeWriteable(pTo);
+  }else{
+    rc = SQLITE_OK;
+  }
+  return rc;
 }
 
 /*