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:
16
manifest
16
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
|
||||
|
||||
@@ -1 +1 @@
|
||||
6db26a19ea7ac77be41a7416dedaef1b9dfd9e16
|
||||
5f8d246852c7cefd5941b8c7bb22177dfc7157c5
|
||||
122
src/vdbe.c
122
src/vdbe.c
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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*));
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user