Free up the MEM_Frame bit in Mem.flags object. Store VdbeFrame objects
as MEM_Blob with a special Mem.xDel pointer instead. FossilOrigin-Name: 62db5fd47660bbc4fcf2c6d4a6c5a3077f12c6442a128d22b66b789a0409ef32
This commit is contained in:
parent
c0d2117f1c
commit
72f56ef95d
18
manifest
18
manifest
@ -1,5 +1,5 @@
|
||||
C Add\sthe\sgeopoly_group_bbox()\saggregate\sfunction\sto\sthe\sGeopoly\smodule.
|
||||
D 2018-08-29T15:50:47.314
|
||||
C Free\sup\sthe\sMEM_Frame\sbit\sin\sMem.flags\sobject.\s\sStore\sVdbeFrame\sobjects\nas\sMEM_Blob\swith\sa\sspecial\sMem.xDel\spointer\sinstead.
|
||||
D 2018-08-29T18:47:22.883
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F Makefile.in d06f463c5b623a61ac27f5cb8214fca9e53a6704d34d6b8f2124e2b1b293c88f
|
||||
@ -571,13 +571,13 @@ F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4
|
||||
F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5
|
||||
F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157
|
||||
F src/vacuum.c 36e7d21a20c0bf6ef4ef7c399d192b5239410b7c4d3c1070fba4e30810d0b855
|
||||
F src/vdbe.c b11baa48b293dc48fbd51c6a9029f88bdf4cd117c01225b2a2b5e90e5928a8a3
|
||||
F src/vdbe.c a44a1cd246f808d36ee0ce7dc031d9624a50242db96ac57f65ad93aea65ceaac
|
||||
F src/vdbe.h 5081dcc497777efe5e9ebe7330d283a044a005e4bdda2e2e984f03bf89a0d907
|
||||
F src/vdbeInt.h 8ea493d994c6697cf7bccc60583a80a0222560490410f60f1113e90d36643ce0
|
||||
F src/vdbeInt.h a660268d9e60dcd60abe8768c1582dd35f3d174ad12f742aee8c805af72dac03
|
||||
F src/vdbeapi.c 2ba821c5929a2769e4b217dd85843479c718b8989d414723ec8af0616a83d611
|
||||
F src/vdbeaux.c b64c699261611e3921de8bdf5a69d5559f0d1443dab8c4ba8e81a64d9219ac6a
|
||||
F src/vdbeaux.c 20da0273e9bdb3f49dafa71123d7bdd63b2656134ecd73123562c028847d0e07
|
||||
F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191
|
||||
F src/vdbemem.c 0dc99941388a867a4dc77a8bed5dfc6024ee9c3ef147a09de844a6629086ec0c
|
||||
F src/vdbemem.c 9a9aa4262f2c5620a552ad83902379d9b1dbb792eb4c1e8758ffffa7ab8a2e64
|
||||
F src/vdbesort.c 90aad5a92608f2dd771c96749beabdb562c9d881131a860a7a5bccf66dc3be7f
|
||||
F src/vdbetrace.c 79d6dbbc479267b255a7de8080eee6e729928a0ef93ed9b0bfa5618875b48392
|
||||
F src/vtab.c 678992ac8ec677a3f9b08126aaf891441083805e3b42574e3654d44538381c14
|
||||
@ -1758,7 +1758,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 43efdd8c7e468405c9d4956a8caa66548059499289cbcc091628de7b055268cd
|
||||
R 67d74f447410c9c096d1d977e8daccbd
|
||||
P 2d4debccbc027405a33aeb10f9d65f6fe4bfb5eb1be5a4d8b82158caba04643f
|
||||
R bd76e3ebc281873295239e9b6605a092
|
||||
U drh
|
||||
Z b43229d61c5d2506dfee2bf7cbf08d25
|
||||
Z 6a1519aefdfc6d3a0da507442f0a767b
|
||||
|
@ -1 +1 @@
|
||||
2d4debccbc027405a33aeb10f9d65f6fe4bfb5eb1be5a4d8b82158caba04643f
|
||||
62db5fd47660bbc4fcf2c6d4a6c5a3077f12c6442a128d22b66b789a0409ef32
|
14
src/vdbe.c
14
src/vdbe.c
@ -6050,7 +6050,7 @@ case OP_Program: { /* jump */
|
||||
** of the current program, and the memory required at runtime to execute
|
||||
** the trigger program. If this trigger has been fired before, then pRt
|
||||
** is already allocated. Otherwise, it must be initialized. */
|
||||
if( (pRt->flags&MEM_Frame)==0 ){
|
||||
if( (pRt->flags&MEM_Blob)==0 ){
|
||||
/* SubProgram.nMem is set to the number of memory cells used by the
|
||||
** program stored in SubProgram.aOp. As well as these, one memory
|
||||
** cell is required for each cursor used by the program. Set local
|
||||
@ -6068,8 +6068,10 @@ case OP_Program: { /* jump */
|
||||
goto no_mem;
|
||||
}
|
||||
sqlite3VdbeMemRelease(pRt);
|
||||
pRt->flags = MEM_Frame;
|
||||
pRt->u.pFrame = pFrame;
|
||||
pRt->flags = MEM_Blob|MEM_Dyn;
|
||||
pRt->z = (char*)pFrame;
|
||||
pRt->n = nByte;
|
||||
pRt->xDel = sqlite3VdbeFrameMemDel;
|
||||
|
||||
pFrame->v = p;
|
||||
pFrame->nChildMem = nMem;
|
||||
@ -6085,6 +6087,9 @@ case OP_Program: { /* jump */
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
pFrame->anExec = p->anExec;
|
||||
#endif
|
||||
#ifdef SQLITE_DEBUG
|
||||
pFrame->iFrameMagic = SQLITE_FRAME_MAGIC;
|
||||
#endif
|
||||
|
||||
pEnd = &VdbeFrameMem(pFrame)[pFrame->nChildMem];
|
||||
for(pMem=VdbeFrameMem(pFrame); pMem!=pEnd; pMem++){
|
||||
@ -6092,7 +6097,8 @@ case OP_Program: { /* jump */
|
||||
pMem->db = db;
|
||||
}
|
||||
}else{
|
||||
pFrame = pRt->u.pFrame;
|
||||
pFrame = (VdbeFrame*)pRt->z;
|
||||
assert( pRt->xDel==sqlite3VdbeFrameMemDel );
|
||||
assert( pProgram->nMem+pProgram->nCsr==pFrame->nChildMem
|
||||
|| (pProgram->nCsr==0 && pProgram->nMem+1==pFrame->nChildMem) );
|
||||
assert( pProgram->nCsr==pFrame->nChildCsr );
|
||||
|
@ -169,6 +169,9 @@ struct VdbeFrame {
|
||||
void *token; /* Copy of SubProgram.token */
|
||||
i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */
|
||||
AuxData *pAuxData; /* Linked list of auxdata allocations */
|
||||
#if SQLITE_DEBUG
|
||||
u32 iFrameMagic; /* magic number for sanity checking */
|
||||
#endif
|
||||
int nCursor; /* Number of entries in apCsr */
|
||||
int pc; /* Program Counter in parent (calling) frame */
|
||||
int nOp; /* Size of aOp array */
|
||||
@ -179,6 +182,13 @@ struct VdbeFrame {
|
||||
int nDbChange; /* Value of db->nChange */
|
||||
};
|
||||
|
||||
/* Magic number for sanity checking on VdbeFrame objects */
|
||||
#define SQLITE_FRAME_MAGIC 0x879fb71e
|
||||
|
||||
/*
|
||||
** Return a pointer to the array of registers allocated for use
|
||||
** by a VdbeFrame.
|
||||
*/
|
||||
#define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))])
|
||||
|
||||
/*
|
||||
@ -194,7 +204,6 @@ struct sqlite3_value {
|
||||
const char *zPType; /* Pointer type when MEM_Term|MEM_Subtype|MEM_Null */
|
||||
FuncDef *pDef; /* Used only when flags==MEM_Agg */
|
||||
RowSet *pRowSet; /* Used only when flags==MEM_RowSet */
|
||||
VdbeFrame *pFrame; /* Used when flags==MEM_Frame */
|
||||
} u;
|
||||
u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
|
||||
u8 enc; /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */
|
||||
@ -239,7 +248,7 @@ struct sqlite3_value {
|
||||
#define MEM_Blob 0x0010 /* Value is a BLOB */
|
||||
#define MEM_AffMask 0x001f /* Mask of affinity bits */
|
||||
#define MEM_RowSet 0x0020 /* Value is a RowSet object */
|
||||
#define MEM_Frame 0x0040 /* Value is a VdbeFrame object */
|
||||
/* Available 0x0040 */
|
||||
#define MEM_Undefined 0x0080 /* Value is undefined */
|
||||
#define MEM_Cleared 0x0100 /* NULL set by OP_Null, not from data */
|
||||
#define MEM_TypeMask 0xc1ff /* Mask of type bits */
|
||||
@ -266,7 +275,7 @@ struct sqlite3_value {
|
||||
** that needs to be deallocated to avoid a leak.
|
||||
*/
|
||||
#define VdbeMemDynamic(X) \
|
||||
(((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame))!=0)
|
||||
(((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet))!=0)
|
||||
|
||||
/*
|
||||
** Clear any existing type flags from a Mem and replace them with f
|
||||
@ -500,7 +509,11 @@ const char *sqlite3OpcodeName(int);
|
||||
int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
|
||||
int sqlite3VdbeMemClearAndResize(Mem *pMem, int n);
|
||||
int sqlite3VdbeCloseStatement(Vdbe *, int);
|
||||
void sqlite3VdbeFrameDelete(VdbeFrame*);
|
||||
#ifdef SQLITE_DEBUG
|
||||
int sqlite3VdbeFrameIsValid(VdbeFrame*);
|
||||
#endif
|
||||
void sqlite3VdbeFrameMemDel(void*); /* Destructor on Mem */
|
||||
void sqlite3VdbeFrameDelete(VdbeFrame*); /* Actually deletes the Frame */
|
||||
int sqlite3VdbeFrameRestore(VdbeFrame *);
|
||||
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
|
||||
void sqlite3VdbePreUpdateHook(Vdbe*,VdbeCursor*,int,const char*,Table*,i64,int);
|
||||
|
@ -1661,9 +1661,9 @@ static void releaseMemArray(Mem *p, int N){
|
||||
*/
|
||||
testcase( p->flags & MEM_Agg );
|
||||
testcase( p->flags & MEM_Dyn );
|
||||
testcase( p->flags & MEM_Frame );
|
||||
testcase( p->xDel==sqlite3VdbeFrameMemDel );
|
||||
testcase( p->flags & MEM_RowSet );
|
||||
if( p->flags&(MEM_Agg|MEM_Dyn|MEM_Frame|MEM_RowSet) ){
|
||||
if( p->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet) ){
|
||||
sqlite3VdbeMemRelease(p);
|
||||
}else if( p->szMalloc ){
|
||||
sqlite3DbFreeNN(db, p->zMalloc);
|
||||
@ -1675,6 +1675,35 @@ static void releaseMemArray(Mem *p, int N){
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/*
|
||||
** Verify that pFrame is a valid VdbeFrame pointer. Return true if it is
|
||||
** and false if something is wrong.
|
||||
**
|
||||
** This routine is intended for use inside of assert() statements only.
|
||||
*/
|
||||
int sqlite3VdbeFrameIsValid(VdbeFrame *pFrame){
|
||||
if( pFrame->iFrameMagic!=SQLITE_FRAME_MAGIC ) return 0;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** This is a destructor on a Mem object (which is really an sqlite3_value)
|
||||
** that deletes the Frame object that is attached to it as a blob.
|
||||
**
|
||||
** This routine does not delete the Frame right away. It merely adds the
|
||||
** frame to a list of frames to be deleted when the Vdbe halts.
|
||||
*/
|
||||
void sqlite3VdbeFrameMemDel(void *pArg){
|
||||
VdbeFrame *pFrame = (VdbeFrame*)pArg;
|
||||
assert( sqlite3VdbeFrameIsValid(pFrame) );
|
||||
pFrame->pParent = pFrame->v->pDelFrame;
|
||||
pFrame->v->pDelFrame = pFrame;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Delete a VdbeFrame object and its contents. VdbeFrame objects are
|
||||
** allocated by the OP_Program opcode in sqlite3VdbeExec().
|
||||
@ -1683,6 +1712,7 @@ void sqlite3VdbeFrameDelete(VdbeFrame *p){
|
||||
int i;
|
||||
Mem *aMem = VdbeFrameMem(p);
|
||||
VdbeCursor **apCsr = (VdbeCursor **)&aMem[p->nChildMem];
|
||||
assert( sqlite3VdbeFrameIsValid(p) );
|
||||
for(i=0; i<p->nChildCsr; i++){
|
||||
sqlite3VdbeFreeCursor(p->v, apCsr[i]);
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ int sqlite3VdbeCheckMemInvariants(Mem *p){
|
||||
if( p->flags & MEM_Null ){
|
||||
/* Cannot be both MEM_Null and some other type */
|
||||
assert( (p->flags & (MEM_Int|MEM_Real|MEM_Str|MEM_Blob
|
||||
|MEM_RowSet|MEM_Frame|MEM_Agg))==0 );
|
||||
|MEM_RowSet|MEM_Agg))==0 );
|
||||
|
||||
/* If MEM_Null is set, then either the value is a pure NULL (the usual
|
||||
** case) or it is a pointer set using sqlite3_bind_pointer() or
|
||||
@ -467,10 +467,6 @@ static SQLITE_NOINLINE void vdbeMemClearExternAndSetNull(Mem *p){
|
||||
p->xDel((void *)p->z);
|
||||
}else if( p->flags&MEM_RowSet ){
|
||||
sqlite3RowSetClear(p->u.pRowSet);
|
||||
}else if( p->flags&MEM_Frame ){
|
||||
VdbeFrame *pFrame = p->u.pFrame;
|
||||
pFrame->pParent = pFrame->v->pDelFrame;
|
||||
pFrame->v->pDelFrame = pFrame;
|
||||
}
|
||||
p->flags = MEM_Null;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user