1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-12 13:01:09 +03:00

Memory handling fixes and optimizations in the VDBE. Ticket #862. (CVS 1909)

FossilOrigin-Name: 5f8d246852c7cefd5941b8c7bb22177dfc7157c5
This commit is contained in:
drh
2004-08-28 18:17:48 +00:00
parent 4aec8b65c7
commit febe1060f9
5 changed files with 88 additions and 98 deletions

View File

@@ -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) C Memory\shandling\sfixes\sand\soptimizations\sin\sthe\sVDBE.\s\sTicket\s#862.\s(CVS\s1909)
D 2004-08-28T16:19:01 D 2004-08-28T18:17:48
F Makefile.in 65a7c43fcaf9a710d62f120b11b6e435eeb4a450 F Makefile.in 65a7c43fcaf9a710d62f120b11b6e435eeb4a450
F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457 F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@@ -75,12 +75,12 @@ F src/update.c 151f1869ce532ed883f1ce26306f0b0fa7b2589a
F src/utf.c 3d8f7bffcbefcced69a436c9e0a1c7eb9e0bb4fa F src/utf.c 3d8f7bffcbefcced69a436c9e0a1c7eb9e0bb4fa
F src/util.c e2c631849cc9e035f6fd387f507ad8886f77cedd F src/util.c e2c631849cc9e035f6fd387f507ad8886f77cedd
F src/vacuum.c 9978a5760c2c430bc5b5e66505a02dad76f25813 F src/vacuum.c 9978a5760c2c430bc5b5e66505a02dad76f25813
F src/vdbe.c ea662188cc489934a567d1eaa3fb6754d5b92b7d F src/vdbe.c 28a48fcee38d2601cb00adc02bdac475bd43e176
F src/vdbe.h e081c72cd0f7c19d49b1927460aeefcf0fbc85ac F src/vdbe.h e081c72cd0f7c19d49b1927460aeefcf0fbc85ac
F src/vdbeInt.h 16322cbfccf0b05631fcf0df68b115c46584d6c9 F src/vdbeInt.h aadadddc8cfad6aa5a5445c849f70d881276fe34
F src/vdbeapi.c 854732720c2cfc6ff76b28eef6253ac84a5408bc F src/vdbeapi.c 854732720c2cfc6ff76b28eef6253ac84a5408bc
F src/vdbeaux.c 022c484dba235d2dcbb1faca0f1943702f4232ed F src/vdbeaux.c 022c484dba235d2dcbb1faca0f1943702f4232ed
F src/vdbemem.c 68fefaf83adb48fe44135da01502c9327f6172b0 F src/vdbemem.c 8971ecc9e56f8b7dbde865906753dbd7812a4f8f
F src/where.c a84eee276cd072158224da6b5f30733df2d56027 F src/where.c a84eee276cd072158224da6b5f30733df2d56027
F test/all.test 3b692eb43583b52c99c344b2fa8934512d179016 F test/all.test 3b692eb43583b52c99c344b2fa8934512d179016
F test/attach.test feb2ce54e78688df4c84553416d5aec3b2a0112e F test/attach.test feb2ce54e78688df4c84553416d5aec3b2a0112e
@@ -244,7 +244,7 @@ F www/tclsqlite.tcl 560ecd6a916b320e59f2917317398f3d59b7cc25
F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9 F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9
F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0 F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
P 6ef1f662d71c75bdb7f61b2fff03f5b1b41e5586 P 6db26a19ea7ac77be41a7416dedaef1b9dfd9e16
R 5b251c944f99c3bf147bc10eb4f70f96 R 99e5b852a5fab1a5e5963194c447eb34
U drh U drh
Z 5c52cbb1dda1a18b82f5188a439efbf0 Z b40cbed2b276adf8c405b360bef48d5f

View File

@@ -1 +1 @@
6db26a19ea7ac77be41a7416dedaef1b9dfd9e16 5f8d246852c7cefd5941b8c7bb22177dfc7157c5

View File

@@ -43,7 +43,7 @@
** in this file for details. If in doubt, do not deviate from existing ** in this file for details. If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code. ** 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 "sqliteInt.h"
#include "os.h" #include "os.h"
@@ -792,12 +792,7 @@ case OP_Variable: {
assert( j>=0 && j<p->nVar ); assert( j>=0 && j<p->nVar );
pTos++; pTos++;
memcpy(pTos, &p->aVar[j], sizeof(*pTos)-NBFS); sqlite3VdbeMemShallowCopy(pTos, &p->aVar[j], MEM_Static);
pTos->xDel = 0;
if( pTos->flags&(MEM_Str|MEM_Blob) ){
pTos->flags &= ~(MEM_Dyn|MEM_Ephem|MEM_Short);
pTos->flags |= MEM_Static;
}
break; break;
} }
@@ -831,23 +826,9 @@ case OP_Dup: {
Mem *pFrom = &pTos[-pOp->p1]; Mem *pFrom = &pTos[-pOp->p1];
assert( pFrom<=pTos && pFrom>=p->aStack ); assert( pFrom<=pTos && pFrom>=p->aStack );
pTos++; pTos++;
memcpy(pTos, pFrom, sizeof(*pFrom)-NBFS); sqlite3VdbeMemShallowCopy(pTos, pFrom, MEM_Ephem);
pTos->xDel = 0; if( pOp->p2 ){
if( pTos->flags & (MEM_Str|MEM_Blob) ){ Deephemeralize(pTos);
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;
}
} }
break; break;
} }
@@ -898,13 +879,7 @@ case OP_Push: {
Mem *pTo = &pTos[-pOp->p1]; Mem *pTo = &pTos[-pOp->p1];
assert( pTo>=p->aStack ); assert( pTo>=p->aStack );
Deephemeralize(pTos); sqlite3VdbeMemMove(pTo, pTos);
Release(pTo);
*pTo = *pTos;
if( pTo->flags & MEM_Short ){
assert( pTo->z==pTos->zShort );
pTo->z = pTo->zShort;
}
pTos--; pTos--;
break; break;
} }
@@ -1240,12 +1215,11 @@ case OP_Function: {
} }
/* Copy the result of the function to the top of the stack */ /* Copy the result of the function to the top of the stack */
pTos++;
sqlite3VdbeChangeEncoding(&ctx.s, db->enc); sqlite3VdbeChangeEncoding(&ctx.s, db->enc);
*pTos = ctx.s; pTos++;
if( pTos->flags & MEM_Short ){ pTos->flags = 0;
pTos->z = pTos->zShort; sqlite3VdbeMemMove(pTos, &ctx.s);
}
/* If the function returned an error, throw an exception */ /* If the function returned an error, throw an exception */
if( ctx.isError ){ if( ctx.isError ){
if( !(pTos->flags&MEM_Str) ){ if( !(pTos->flags&MEM_Str) ){
@@ -1773,6 +1747,7 @@ case OP_Column: {
sMem.flags = 0; sMem.flags = 0;
assert( p1<p->nCursor ); assert( p1<p->nCursor );
pTos++; pTos++;
pTos->flags = MEM_Null;
/* This block sets the variable payloadSize to be the total number of /* This block sets the variable payloadSize to be the total number of
** bytes in the record. ** bytes in the record.
@@ -1937,6 +1912,9 @@ case OP_Column: {
/* Get the column information. /* Get the column information.
*/ */
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
if( zRec ){ if( zRec ){
zData = &zRec[aOffset[p2]]; zData = &zRec[aOffset[p2]];
}else{ }else{
@@ -1945,14 +1923,25 @@ case OP_Column: {
zData = sMem.z; zData = sMem.z;
} }
sqlite3VdbeSerialGet(zData, aType[p2], pTos); sqlite3VdbeSerialGet(zData, aType[p2], pTos);
if( sqlite3VdbeMemMakeWriteable(pTos)==SQLITE_NOMEM ){
goto no_mem;
}
pTos->enc = db->enc; 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 */ /* Release the aType[] memory if we are not dealing with cursor */
if( !pC ){ if( !pC ){
@@ -3250,6 +3239,7 @@ case OP_FullKey: {
assert( p->apCsr[i]->keyAsData ); assert( p->apCsr[i]->keyAsData );
assert( !p->apCsr[i]->pseudoTable ); assert( !p->apCsr[i]->pseudoTable );
pTos++; pTos++;
pTos->flags = MEM_Null;
if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
i64 amt; i64 amt;
char *z; char *z;
@@ -3506,6 +3496,7 @@ case OP_IdxRecno: {
assert( i>=0 && i<p->nCursor ); assert( i>=0 && i<p->nCursor );
assert( p->apCsr[i]!=0 ); assert( p->apCsr[i]!=0 );
pTos++; pTos++;
pTos->flags = MEM_Null;
if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
i64 rowid; i64 rowid;
@@ -3521,8 +3512,6 @@ case OP_IdxRecno: {
pTos->flags = MEM_Int; pTos->flags = MEM_Int;
pTos->i = rowid; pTos->i = rowid;
} }
}else{
pTos->flags = MEM_Null;
} }
break; break;
} }
@@ -4019,8 +4008,6 @@ case OP_SortPut: {
pSorter->zKey = pTos->z; pSorter->zKey = pTos->z;
pSorter->data.flags = MEM_Null; pSorter->data.flags = MEM_Null;
rc = sqlite3VdbeMemMove(&pSorter->data, pNos); rc = sqlite3VdbeMemMove(&pSorter->data, pNos);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
Deephemeralize(&pSorter->data);
pTos -= 2; pTos -= 2;
break; break;
} }
@@ -4080,7 +4067,6 @@ case OP_SortNext: {
pTos++; pTos++;
pTos->flags = MEM_Null; pTos->flags = MEM_Null;
rc = sqlite3VdbeMemMove(pTos, &pSorter->data); rc = sqlite3VdbeMemMove(pTos, &pSorter->data);
assert( rc==SQLITE_OK );
sqliteFree(pSorter->zKey); sqliteFree(pSorter->zKey);
sqliteFree(pSorter); sqliteFree(pSorter);
}else{ }else{
@@ -4109,18 +4095,9 @@ case OP_SortReset: {
** the original data remains on the stack. ** the original data remains on the stack.
*/ */
case OP_MemStore: { case OP_MemStore: {
int i = pOp->p1;
Mem *pMem;
assert( pTos>=p->aStack ); assert( pTos>=p->aStack );
assert( i<p->nMem ); assert( pOp->p1>=0 && pOp->p1<p->nMem );
Deephemeralize(pTos); rc = sqlite3VdbeMemMove(&p->aMem[pOp->p1], pTos);
pMem = &p->aMem[i];
Release(pMem);
*pMem = *pTos;
pTos->flags = MEM_Null;
if( pMem->flags & MEM_Short ){
pMem->z = pMem->zShort;
}
pTos--; pTos--;
/* If P2 is 0 then fall thru to the next opcode, OP_MemLoad, that will /* 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; int i = pOp->p1;
assert( i>=0 && i<p->nMem ); assert( i>=0 && i<p->nMem );
pTos++; pTos++;
memcpy(pTos, &p->aMem[i], sizeof(pTos[0])-NBFS);; sqlite3VdbeMemShallowCopy(pTos, &p->aMem[i], MEM_Ephem);
pTos->xDel = 0;
if( pTos->flags & (MEM_Str|MEM_Blob) ){
pTos->flags |= MEM_Ephem;
pTos->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short);
}
break; break;
} }
@@ -4322,20 +4294,12 @@ case OP_AggFocus: {
case OP_AggSet: { case OP_AggSet: {
AggElem *pFocus; AggElem *pFocus;
int i = pOp->p2; int i = pOp->p2;
Mem *pMem;
rc = AggInFocus(&p->agg, &pFocus); rc = AggInFocus(&p->agg, &pFocus);
if( rc!=SQLITE_OK ) goto abort_due_to_error; if( rc!=SQLITE_OK ) goto abort_due_to_error;
assert( pTos>=p->aStack ); assert( pTos>=p->aStack );
if( pFocus==0 ) goto no_mem; if( pFocus==0 ) goto no_mem;
assert( i>=0 && i<p->agg.nMem ); assert( i>=0 && i<p->agg.nMem );
Deephemeralize(pTos); rc = sqlite3VdbeMemMove(&pFocus->aMem[i], pTos);
pMem = &pFocus->aMem[i];
Release(pMem);
*pMem = *pTos;
pTos->flags = MEM_Null;
if( pMem->flags & MEM_Short ){
pMem->z = pMem->zShort;
}
pTos--; pTos--;
break; break;
} }
@@ -4348,23 +4312,19 @@ case OP_AggSet: {
*/ */
case OP_AggGet: { case OP_AggGet: {
AggElem *pFocus; AggElem *pFocus;
Mem *pMem;
int i = pOp->p2; int i = pOp->p2;
rc = AggInFocus(&p->agg, &pFocus); rc = AggInFocus(&p->agg, &pFocus);
if( rc!=SQLITE_OK ) goto abort_due_to_error; if( rc!=SQLITE_OK ) goto abort_due_to_error;
if( pFocus==0 ) goto no_mem; if( pFocus==0 ) goto no_mem;
assert( i>=0 && i<p->agg.nMem ); assert( i>=0 && i<p->agg.nMem );
pTos++; pTos++;
pMem = &pFocus->aMem[i]; sqlite3VdbeMemShallowCopy(pTos, &pFocus->aMem[i], MEM_Ephem);
*pTos = *pMem; assert( (pTos->flags & MEM_Str)==0 || pTos->enc==db->enc );
pTos->xDel = 0; #if 0
if( pTos->flags & (MEM_Str|MEM_Blob) ){
pTos->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short);
pTos->flags |= MEM_Ephem;
}
if( pTos->flags&MEM_Str ){ if( pTos->flags&MEM_Str ){
sqlite3VdbeChangeEncoding(pTos, db->enc); sqlite3VdbeChangeEncoding(pTos, db->enc);
} }
#endif
break; break;
} }

View File

@@ -381,6 +381,7 @@ int sqlite3VdbeExec(Vdbe*);
int sqlite3VdbeList(Vdbe*); int sqlite3VdbeList(Vdbe*);
int sqlite3VdbeChangeEncoding(Mem *, int); int sqlite3VdbeChangeEncoding(Mem *, int);
int sqlite3VdbeMemCopy(Mem*, const Mem*); int sqlite3VdbeMemCopy(Mem*, const Mem*);
void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int);
int sqlite3VdbeMemMove(Mem*, Mem*); int sqlite3VdbeMemMove(Mem*, Mem*);
int sqlite3VdbeMemNulTerminate(Mem*); int sqlite3VdbeMemNulTerminate(Mem*);
int sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, void(*)(void*)); int sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, void(*)(void*));

View 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){ void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){
int rc;
sqlite3VdbeMemRelease(pTo);
memcpy(pTo, pFrom, sizeof(*pFrom)-sizeof(pFrom->zShort)); memcpy(pTo, pFrom, sizeof(*pFrom)-sizeof(pFrom->zShort));
pTo->xDel = 0; pTo->xDel = 0;
if( pTo->flags & (MEM_Str|MEM_Blob) ){ if( pTo->flags & (MEM_Str|MEM_Blob) ){
pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short); pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short|MEM_Ephem);
pTo->flags |= 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); rc = sqlite3VdbeMemMakeWriteable(pTo);
}else{ }else{
rc = SQLITE_OK; 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 ** 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 sqlite3VdbeMemMove(Mem *pTo, Mem *pFrom){
int rc;
if( pTo->flags & MEM_Dyn ){
sqlite3VdbeMemRelease(pTo);
}
memcpy(pTo, pFrom, sizeof(Mem)); memcpy(pTo, pFrom, sizeof(Mem));
if( pFrom->flags & MEM_Short ){ if( pFrom->flags & MEM_Short ){
pTo->z = pTo->zShort; pTo->z = pTo->zShort;
} }
pFrom->flags = MEM_Null; pFrom->flags = MEM_Null;
pFrom->xDel = 0; pFrom->xDel = 0;
return SQLITE_OK; if( pTo->flags & MEM_Ephem ){
rc = sqlite3VdbeMemMakeWriteable(pTo);
}else{
rc = SQLITE_OK;
}
return rc;
} }
/* /*