/ Check-in [62db5fd4]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Free up the MEM_Frame bit in Mem.flags object. Store VdbeFrame objects as MEM_Blob with a special Mem.xDel pointer instead.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 62db5fd47660bbc4fcf2c6d4a6c5a3077f12c6442a128d22b66b789a0409ef32
User & Date: drh 2018-08-29 18:47:22
Context
2018-08-29
20:24
Also free up the MEM_RowSet bit in the Mem.flags field and have RowSet objects be destroyed using Mem.xDel. This change results in faster code. check-in: f48e9feb user: drh tags: trunk
18:47
Free up the MEM_Frame bit in Mem.flags object. Store VdbeFrame objects as MEM_Blob with a special Mem.xDel pointer instead. check-in: 62db5fd4 user: drh tags: trunk
15:50
Add the geopoly_group_bbox() aggregate function to the Geopoly module. check-in: 2d4debcc user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/vdbe.c.

  6046   6046       goto abort_due_to_error;
  6047   6047     }
  6048   6048   
  6049   6049     /* Register pRt is used to store the memory required to save the state
  6050   6050     ** of the current program, and the memory required at runtime to execute
  6051   6051     ** the trigger program. If this trigger has been fired before, then pRt 
  6052   6052     ** is already allocated. Otherwise, it must be initialized.  */
  6053         -  if( (pRt->flags&MEM_Frame)==0 ){
         6053  +  if( (pRt->flags&MEM_Blob)==0 ){
  6054   6054       /* SubProgram.nMem is set to the number of memory cells used by the 
  6055   6055       ** program stored in SubProgram.aOp. As well as these, one memory
  6056   6056       ** cell is required for each cursor used by the program. Set local
  6057   6057       ** variable nMem (and later, VdbeFrame.nChildMem) to this value.
  6058   6058       */
  6059   6059       nMem = pProgram->nMem + pProgram->nCsr;
  6060   6060       assert( nMem>0 );
................................................................................
  6064   6064                 + pProgram->nCsr * sizeof(VdbeCursor*)
  6065   6065                 + (pProgram->nOp + 7)/8;
  6066   6066       pFrame = sqlite3DbMallocZero(db, nByte);
  6067   6067       if( !pFrame ){
  6068   6068         goto no_mem;
  6069   6069       }
  6070   6070       sqlite3VdbeMemRelease(pRt);
  6071         -    pRt->flags = MEM_Frame;
  6072         -    pRt->u.pFrame = pFrame;
         6071  +    pRt->flags = MEM_Blob|MEM_Dyn;
         6072  +    pRt->z = (char*)pFrame;
         6073  +    pRt->n = nByte;
         6074  +    pRt->xDel = sqlite3VdbeFrameMemDel;
  6073   6075   
  6074   6076       pFrame->v = p;
  6075   6077       pFrame->nChildMem = nMem;
  6076   6078       pFrame->nChildCsr = pProgram->nCsr;
  6077   6079       pFrame->pc = (int)(pOp - aOp);
  6078   6080       pFrame->aMem = p->aMem;
  6079   6081       pFrame->nMem = p->nMem;
................................................................................
  6081   6083       pFrame->nCursor = p->nCursor;
  6082   6084       pFrame->aOp = p->aOp;
  6083   6085       pFrame->nOp = p->nOp;
  6084   6086       pFrame->token = pProgram->token;
  6085   6087   #ifdef SQLITE_ENABLE_STMT_SCANSTATUS
  6086   6088       pFrame->anExec = p->anExec;
  6087   6089   #endif
         6090  +#ifdef SQLITE_DEBUG
         6091  +    pFrame->iFrameMagic = SQLITE_FRAME_MAGIC;
         6092  +#endif
  6088   6093   
  6089   6094       pEnd = &VdbeFrameMem(pFrame)[pFrame->nChildMem];
  6090   6095       for(pMem=VdbeFrameMem(pFrame); pMem!=pEnd; pMem++){
  6091   6096         pMem->flags = MEM_Undefined;
  6092   6097         pMem->db = db;
  6093   6098       }
  6094   6099     }else{
  6095         -    pFrame = pRt->u.pFrame;
         6100  +    pFrame = (VdbeFrame*)pRt->z;
         6101  +    assert( pRt->xDel==sqlite3VdbeFrameMemDel );
  6096   6102       assert( pProgram->nMem+pProgram->nCsr==pFrame->nChildMem 
  6097   6103           || (pProgram->nCsr==0 && pProgram->nMem+1==pFrame->nChildMem) );
  6098   6104       assert( pProgram->nCsr==pFrame->nChildCsr );
  6099   6105       assert( (int)(pOp - aOp)==pFrame->pc );
  6100   6106     }
  6101   6107   
  6102   6108     p->nFrame++;

Changes to src/vdbeInt.h.

   165    165     i64 *anExec;            /* Event counters from parent frame */
   166    166     Mem *aMem;              /* Array of memory cells for parent frame */
   167    167     VdbeCursor **apCsr;     /* Array of Vdbe cursors for parent frame */
   168    168     u8 *aOnce;              /* Bitmask used by OP_Once */
   169    169     void *token;            /* Copy of SubProgram.token */
   170    170     i64 lastRowid;          /* Last insert rowid (sqlite3.lastRowid) */
   171    171     AuxData *pAuxData;      /* Linked list of auxdata allocations */
          172  +#if SQLITE_DEBUG
          173  +  u32 iFrameMagic;        /* magic number for sanity checking */
          174  +#endif
   172    175     int nCursor;            /* Number of entries in apCsr */
   173    176     int pc;                 /* Program Counter in parent (calling) frame */
   174    177     int nOp;                /* Size of aOp array */
   175    178     int nMem;               /* Number of entries in aMem */
   176    179     int nChildMem;          /* Number of memory cells for child frame */
   177    180     int nChildCsr;          /* Number of cursors for child frame */
   178    181     int nChange;            /* Statement changes (Vdbe.nChange)     */
   179    182     int nDbChange;          /* Value of db->nChange */
   180    183   };
   181    184   
          185  +/* Magic number for sanity checking on VdbeFrame objects */
          186  +#define SQLITE_FRAME_MAGIC 0x879fb71e
          187  +
          188  +/*
          189  +** Return a pointer to the array of registers allocated for use
          190  +** by a VdbeFrame.
          191  +*/
   182    192   #define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))])
   183    193   
   184    194   /*
   185    195   ** Internally, the vdbe manipulates nearly all SQL values as Mem
   186    196   ** structures. Each Mem struct may cache multiple representations (string,
   187    197   ** integer etc.) of the same value.
   188    198   */
................................................................................
   190    200     union MemValue {
   191    201       double r;           /* Real value used when MEM_Real is set in flags */
   192    202       i64 i;              /* Integer value used when MEM_Int is set in flags */
   193    203       int nZero;          /* Extra zero bytes when MEM_Zero and MEM_Blob set */
   194    204       const char *zPType; /* Pointer type when MEM_Term|MEM_Subtype|MEM_Null */
   195    205       FuncDef *pDef;      /* Used only when flags==MEM_Agg */
   196    206       RowSet *pRowSet;    /* Used only when flags==MEM_RowSet */
   197         -    VdbeFrame *pFrame;  /* Used when flags==MEM_Frame */
   198    207     } u;
   199    208     u16 flags;          /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
   200    209     u8  enc;            /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */
   201    210     u8  eSubtype;       /* Subtype for this value */
   202    211     int n;              /* Number of characters in string value, excluding '\0' */
   203    212     char *z;            /* String or BLOB value */
   204    213     /* ShallowCopy only needs to copy the information above */
................................................................................
   235    244   #define MEM_Null      0x0001   /* Value is NULL (or a pointer) */
   236    245   #define MEM_Str       0x0002   /* Value is a string */
   237    246   #define MEM_Int       0x0004   /* Value is an integer */
   238    247   #define MEM_Real      0x0008   /* Value is a real number */
   239    248   #define MEM_Blob      0x0010   /* Value is a BLOB */
   240    249   #define MEM_AffMask   0x001f   /* Mask of affinity bits */
   241    250   #define MEM_RowSet    0x0020   /* Value is a RowSet object */
   242         -#define MEM_Frame     0x0040   /* Value is a VdbeFrame object */
          251  +/* Available          0x0040   */
   243    252   #define MEM_Undefined 0x0080   /* Value is undefined */
   244    253   #define MEM_Cleared   0x0100   /* NULL set by OP_Null, not from data */
   245    254   #define MEM_TypeMask  0xc1ff   /* Mask of type bits */
   246    255   
   247    256   
   248    257   /* Whenever Mem contains a valid string or blob representation, one of
   249    258   ** the following flags must be set to determine the memory management
................................................................................
   262    271     #define MEM_Zero 0x0000
   263    272   #endif
   264    273   
   265    274   /* Return TRUE if Mem X contains dynamically allocated content - anything
   266    275   ** that needs to be deallocated to avoid a leak.
   267    276   */
   268    277   #define VdbeMemDynamic(X)  \
   269         -  (((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame))!=0)
          278  +  (((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet))!=0)
   270    279   
   271    280   /*
   272    281   ** Clear any existing type flags from a Mem and replace them with f
   273    282   */
   274    283   #define MemSetTypeFlag(p, f) \
   275    284      ((p)->flags = ((p)->flags&~(MEM_TypeMask|MEM_Zero))|f)
   276    285   
................................................................................
   496    505   #ifndef SQLITE_OMIT_WINDOWFUNC
   497    506   int sqlite3VdbeMemAggValue(Mem*, Mem*, FuncDef*);
   498    507   #endif
   499    508   const char *sqlite3OpcodeName(int);
   500    509   int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
   501    510   int sqlite3VdbeMemClearAndResize(Mem *pMem, int n);
   502    511   int sqlite3VdbeCloseStatement(Vdbe *, int);
   503         -void sqlite3VdbeFrameDelete(VdbeFrame*);
          512  +#ifdef SQLITE_DEBUG
          513  +int sqlite3VdbeFrameIsValid(VdbeFrame*);
          514  +#endif
          515  +void sqlite3VdbeFrameMemDel(void*);      /* Destructor on Mem */
          516  +void sqlite3VdbeFrameDelete(VdbeFrame*); /* Actually deletes the Frame */
   504    517   int sqlite3VdbeFrameRestore(VdbeFrame *);
   505    518   #ifdef SQLITE_ENABLE_PREUPDATE_HOOK
   506    519   void sqlite3VdbePreUpdateHook(Vdbe*,VdbeCursor*,int,const char*,Table*,i64,int);
   507    520   #endif
   508    521   int sqlite3VdbeTransferError(Vdbe *p);
   509    522   
   510    523   int sqlite3VdbeSorterInit(sqlite3 *, int, VdbeCursor *);

Changes to src/vdbeaux.c.

  1657   1657         ** sqlite3MemRelease() were called from here. With -O2, this jumps
  1658   1658         ** to 6.6 percent. The test case is inserting 1000 rows into a table 
  1659   1659         ** with no indexes using a single prepared INSERT statement, bind() 
  1660   1660         ** and reset(). Inserts are grouped into a transaction.
  1661   1661         */
  1662   1662         testcase( p->flags & MEM_Agg );
  1663   1663         testcase( p->flags & MEM_Dyn );
  1664         -      testcase( p->flags & MEM_Frame );
         1664  +      testcase( p->xDel==sqlite3VdbeFrameMemDel );
  1665   1665         testcase( p->flags & MEM_RowSet );
  1666         -      if( p->flags&(MEM_Agg|MEM_Dyn|MEM_Frame|MEM_RowSet) ){
         1666  +      if( p->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet) ){
  1667   1667           sqlite3VdbeMemRelease(p);
  1668   1668         }else if( p->szMalloc ){
  1669   1669           sqlite3DbFreeNN(db, p->zMalloc);
  1670   1670           p->szMalloc = 0;
  1671   1671         }
  1672   1672   
  1673   1673         p->flags = MEM_Undefined;
  1674   1674       }while( (++p)<pEnd );
  1675   1675     }
  1676   1676   }
         1677  +
         1678  +#ifdef SQLITE_DEBUG
         1679  +/*
         1680  +** Verify that pFrame is a valid VdbeFrame pointer.  Return true if it is
         1681  +** and false if something is wrong.
         1682  +**
         1683  +** This routine is intended for use inside of assert() statements only.
         1684  +*/
         1685  +int sqlite3VdbeFrameIsValid(VdbeFrame *pFrame){
         1686  +  if( pFrame->iFrameMagic!=SQLITE_FRAME_MAGIC ) return 0;
         1687  +  return 1;
         1688  +}
         1689  +#endif
         1690  +
         1691  +
         1692  +/*
         1693  +** This is a destructor on a Mem object (which is really an sqlite3_value)
         1694  +** that deletes the Frame object that is attached to it as a blob.
         1695  +**
         1696  +** This routine does not delete the Frame right away.  It merely adds the
         1697  +** frame to a list of frames to be deleted when the Vdbe halts.
         1698  +*/
         1699  +void sqlite3VdbeFrameMemDel(void *pArg){
         1700  +  VdbeFrame *pFrame = (VdbeFrame*)pArg;
         1701  +  assert( sqlite3VdbeFrameIsValid(pFrame) );
         1702  +  pFrame->pParent = pFrame->v->pDelFrame;
         1703  +  pFrame->v->pDelFrame = pFrame;
         1704  +}
         1705  +
  1677   1706   
  1678   1707   /*
  1679   1708   ** Delete a VdbeFrame object and its contents. VdbeFrame objects are
  1680   1709   ** allocated by the OP_Program opcode in sqlite3VdbeExec().
  1681   1710   */
  1682   1711   void sqlite3VdbeFrameDelete(VdbeFrame *p){
  1683   1712     int i;
  1684   1713     Mem *aMem = VdbeFrameMem(p);
  1685   1714     VdbeCursor **apCsr = (VdbeCursor **)&aMem[p->nChildMem];
         1715  +  assert( sqlite3VdbeFrameIsValid(p) );
  1686   1716     for(i=0; i<p->nChildCsr; i++){
  1687   1717       sqlite3VdbeFreeCursor(p->v, apCsr[i]);
  1688   1718     }
  1689   1719     releaseMemArray(aMem, p->nChildMem);
  1690   1720     sqlite3VdbeDeleteAuxData(p->v->db, &p->pAuxData, -1, 0);
  1691   1721     sqlite3DbFree(p->v->db, p);
  1692   1722   }

Changes to src/vdbemem.c.

    39     39   
    40     40     /* Cannot be both MEM_Int and MEM_Real at the same time */
    41     41     assert( (p->flags & (MEM_Int|MEM_Real))!=(MEM_Int|MEM_Real) );
    42     42   
    43     43     if( p->flags & MEM_Null ){
    44     44       /* Cannot be both MEM_Null and some other type */
    45     45       assert( (p->flags & (MEM_Int|MEM_Real|MEM_Str|MEM_Blob
    46         -                         |MEM_RowSet|MEM_Frame|MEM_Agg))==0 );
           46  +                         |MEM_RowSet|MEM_Agg))==0 );
    47     47   
    48     48       /* If MEM_Null is set, then either the value is a pure NULL (the usual
    49     49       ** case) or it is a pointer set using sqlite3_bind_pointer() or
    50     50       ** sqlite3_result_pointer().  If a pointer, then MEM_Term must also be
    51     51       ** set.
    52     52       */
    53     53       if( (p->flags & (MEM_Term|MEM_Subtype))==(MEM_Term|MEM_Subtype) ){
................................................................................
   463    463     }
   464    464     if( p->flags&MEM_Dyn ){
   465    465       assert( (p->flags&MEM_RowSet)==0 );
   466    466       assert( p->xDel!=SQLITE_DYNAMIC && p->xDel!=0 );
   467    467       p->xDel((void *)p->z);
   468    468     }else if( p->flags&MEM_RowSet ){
   469    469       sqlite3RowSetClear(p->u.pRowSet);
   470         -  }else if( p->flags&MEM_Frame ){
   471         -    VdbeFrame *pFrame = p->u.pFrame;
   472         -    pFrame->pParent = pFrame->v->pDelFrame;
   473         -    pFrame->v->pDelFrame = pFrame;
   474    470     }
   475    471     p->flags = MEM_Null;
   476    472   }
   477    473   
   478    474   /*
   479    475   ** Release memory held by the Mem p, both external memory cleared
   480    476   ** by p->xDel and memory in p->zMalloc.