-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
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
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
** 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"
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;
}
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;
}
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;
}
}
/* 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) ){
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.
/* Get the column information.
*/
+ if( rc!=SQLITE_OK ){
+ goto abort_due_to_error;
+ }
if( zRec ){
zData = &zRec[aOffset[p2]];
}else{
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 ){
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;
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;
pTos->flags = MEM_Int;
pTos->i = rowid;
}
- }else{
- pTos->flags = MEM_Null;
}
break;
}
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;
}
pTos++;
pTos->flags = MEM_Null;
rc = sqlite3VdbeMemMove(pTos, &pSorter->data);
- assert( rc==SQLITE_OK );
sqliteFree(pSorter->zKey);
sqliteFree(pSorter);
}else{
** 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
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;
}
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;
}
*/
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;
}
}
/*
-** 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;
/*
** 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;
}
/*