/ Check-in [06e7ff4c]
Login

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

Overview
Comment:A few more optimizations to the VDBE. (CVS 1204)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:06e7ff4cb8c73fd690c6d5b5f530a30d83f4f10c
User & Date: drh 2004-01-31 20:20:30
Context
2004-01-31
20:40
Fix a bug introduced by the previous check-in. (CVS 1205) check-in: 04cf2278 user: drh tags: trunk
20:20
A few more optimizations to the VDBE. (CVS 1204) check-in: 06e7ff4c user: drh tags: trunk
19:22
Rework internal data structures to make the VDBE about 15% smaller. (CVS 1203) check-in: 8273c74b user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Show Whitespace Changes Patch

Changes to src/vdbe.c.

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
...
142
143
144
145
146
147
148

149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
...
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
....
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
....
4272
4273
4274
4275
4276
4277
4278

4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
....
4462
4463
4464
4465
4466
4467
4468

4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482

4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503

4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** 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.253 2004/01/31 19:22:56 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
................................................................................
** has focus.
**
** Return 0 on success and 1 if memory is exhausted.
*/
static int AggInsert(Agg *p, char *zKey, int nKey){
  AggElem *pElem, *pOld;
  int i;

  pElem = sqliteMalloc( sizeof(AggElem) + nKey +
                        (p->nMem-1)*sizeof(pElem->aMem[0]) );
  if( pElem==0 ) return 1;
  pElem->zKey = (char*)&pElem->aMem[p->nMem];
  memcpy(pElem->zKey, zKey, nKey);
  pElem->nKey = nKey;
  pOld = sqliteHashInsert(&p->hash, pElem->zKey, pElem->nKey, pElem);
  if( pOld!=0 ){
    assert( pOld==pElem );  /* Malloc failed on insert */
    sqliteFree(pOld);
    return 0;
  }
  for(i=0; i<p->nMem; i++){
    pElem->aMem[i].flags = MEM_Null;
  }
  p->pCurrent = pElem;
  return 0;
}

/*
** Get the AggElem currently in focus
................................................................................
** See also the Dup instruction.
*/
case OP_Pull: {
  Mem *pFrom = &pTos[-pOp->p1];
  int i;
  Mem ts;

  /* Deephemeralize(pFrom); *** not needed */
  ts = *pFrom;
  Deephemeralize(pTos);
  for(i=0; i<pOp->p1; i++, pFrom++){
    Deephemeralize(&pFrom[1]);
    *pFrom = pFrom[1];
    assert( (pFrom->flags & MEM_Ephem)==0 );
    if( pFrom->flags & MEM_Short ){
      assert( pFrom->flags & MEM_Str );
      assert( pFrom->z==pFrom[1].zShort );
      assert( (pTos->flags & (MEM_Dyn|MEM_Static|MEM_Ephem))==0 );
      pFrom->z = pFrom->zShort;
    }
  }
  *pTos = ts;
  /* assert( (pTos->flags & MEM_Ephem)==0 ); *** not needed */
  if( pTos->flags & MEM_Short ){
    assert( pTos->flags & MEM_Str );
    assert( pTos->z==pTos[-pOp->p1].zShort );
    assert( (pTos->flags & (MEM_Dyn|MEM_Static|MEM_Ephem))==0 );
    pTos->z = pTos->zShort;
  }
  break;
}

/* Opcode: Push P1 * *
**
................................................................................
**
** After the data is stored in the memory location, the
** stack is popped once if P2 is 1.  If P2 is zero, then
** the original data remains on the stack.
*/
case OP_MemStore: {
  int i = pOp->p1;
  char *zOld;
  Mem *pMem;
  int flags;
  assert( pTos>=p->aStack );
  if( i>=p->nMem ){
    int nOld = p->nMem;
    Mem *aMem;
    p->nMem = i + 5;
    aMem = sqliteRealloc(p->aMem, p->nMem*sizeof(p->aMem[0]));
    if( aMem==0 ) goto no_mem;
................................................................................
      }
    }
    p->aMem = aMem;
    if( nOld<p->nMem ){
      memset(&p->aMem[nOld], 0, sizeof(p->aMem[0])*(p->nMem-nOld));
    }
  }

  pMem = &p->aMem[i];
  flags = pMem->flags;
  if( flags & MEM_Dyn ){
    zOld = pMem->z;
  }else{
    zOld = 0;
  }
  *pMem = *pTos;
  flags = pMem->flags;
  if( flags & MEM_Dyn ){
    if( pOp->p2 ){
      pTos->flags = MEM_Null;
    }else{
      /* OR: perhaps just make the stack ephermeral */
      pMem->z = sqliteMallocRaw( pMem->n );
      if( pMem->z==0 ) goto no_mem;
      memcpy(pMem->z, pTos->z, pMem->n);
    }
  }else if( flags & MEM_Short ){
    pMem->z = pMem->zShort;
  }
  if( zOld ) sqliteFree(zOld);
  if( pOp->p2 ){
    Release(pTos);
    pTos--;
  }
  break;
}

................................................................................
/* Opcode: AggSet * P2 *
**
** Move the top of the stack into the P2-th field of the current
** aggregate.  String values are duplicated into new memory.
*/
case OP_AggSet: {
  AggElem *pFocus = AggInFocus(p->agg);

  int i = pOp->p2;
  assert( pTos>=p->aStack );
  if( pFocus==0 ) goto no_mem;
  assert( i>=0 );
  assert( i<p->agg.nMem );
  if( i<p->agg.nMem ){
    Mem *pMem = &pFocus->aMem[i];
    char *zOld;
    if( pMem->flags & MEM_Dyn ){
      zOld = pMem->z;
    }else{
      zOld = 0;
    }
    Deephemeralize(pTos);

    *pMem = *pTos;
    if( pMem->flags & MEM_Dyn ){
      pTos->flags = MEM_Null;
    }else if( pMem->flags & MEM_Short ){
      pMem->z = pMem->zShort;
    }
    if( zOld ) sqliteFree(zOld);
  }
  Release(pTos);
  pTos--;
  break;
}

/* Opcode: AggGet * P2 *
**
** Push a new entry onto the stack which is a copy of the P2-th field
** of the current aggregate.  Strings are not duplicated so
** string values will be ephemeral.
*/
case OP_AggGet: {
  AggElem *pFocus = AggInFocus(p->agg);

  int i = pOp->p2;
  if( pFocus==0 ) goto no_mem;
  assert( i>=0 );
  pTos++;
  assert( i<p->agg.nMem );
  if( i<p->agg.nMem ){
    Mem *pMem = &pFocus->aMem[i];
    *pTos = *pMem;
    pTos->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short);
    pTos->flags |= MEM_Ephem;
  }
  break;
}

/* Opcode: AggNext * P2 *
**
** Make the next aggregate value the current aggregate.  The prior
** aggregate is deleted.  If all aggregate values have been consumed,







|







 







>












|
|







 







<









<




<



<







 







<

<







 







>

<
|
<
<
<
<

<
|



<




|


<







 







>



|
|
<
|
<
<
<
<
<
<
<
>






<
<













>


|

<
<
|



<







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
...
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
...
765
766
767
768
769
770
771

772
773
774
775
776
777
778
779
780

781
782
783
784

785
786
787

788
789
790
791
792
793
794
....
4246
4247
4248
4249
4250
4251
4252

4253

4254
4255
4256
4257
4258
4259
4260
....
4267
4268
4269
4270
4271
4272
4273
4274
4275

4276




4277

4278
4279
4280
4281

4282
4283
4284
4285
4286
4287
4288

4289
4290
4291
4292
4293
4294
4295
....
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462

4463







4464
4465
4466
4467
4468
4469
4470


4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488


4489
4490
4491
4492

4493
4494
4495
4496
4497
4498
4499
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** 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.254 2004/01/31 20:20:30 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
................................................................................
** has focus.
**
** Return 0 on success and 1 if memory is exhausted.
*/
static int AggInsert(Agg *p, char *zKey, int nKey){
  AggElem *pElem, *pOld;
  int i;
  Mem *pMem;
  pElem = sqliteMalloc( sizeof(AggElem) + nKey +
                        (p->nMem-1)*sizeof(pElem->aMem[0]) );
  if( pElem==0 ) return 1;
  pElem->zKey = (char*)&pElem->aMem[p->nMem];
  memcpy(pElem->zKey, zKey, nKey);
  pElem->nKey = nKey;
  pOld = sqliteHashInsert(&p->hash, pElem->zKey, pElem->nKey, pElem);
  if( pOld!=0 ){
    assert( pOld==pElem );  /* Malloc failed on insert */
    sqliteFree(pOld);
    return 0;
  }
  for(i=0, pMem=pElem->aMem; i<p->nMem; i++, pMem++){
    pMem->flags = MEM_Null;
  }
  p->pCurrent = pElem;
  return 0;
}

/*
** Get the AggElem currently in focus
................................................................................
** See also the Dup instruction.
*/
case OP_Pull: {
  Mem *pFrom = &pTos[-pOp->p1];
  int i;
  Mem ts;


  ts = *pFrom;
  Deephemeralize(pTos);
  for(i=0; i<pOp->p1; i++, pFrom++){
    Deephemeralize(&pFrom[1]);
    *pFrom = pFrom[1];
    assert( (pFrom->flags & MEM_Ephem)==0 );
    if( pFrom->flags & MEM_Short ){
      assert( pFrom->flags & MEM_Str );
      assert( pFrom->z==pFrom[1].zShort );

      pFrom->z = pFrom->zShort;
    }
  }
  *pTos = ts;

  if( pTos->flags & MEM_Short ){
    assert( pTos->flags & MEM_Str );
    assert( pTos->z==pTos[-pOp->p1].zShort );

    pTos->z = pTos->zShort;
  }
  break;
}

/* Opcode: Push P1 * *
**
................................................................................
**
** After the data is stored in the memory location, the
** stack is popped once if P2 is 1.  If P2 is zero, then
** the original data remains on the stack.
*/
case OP_MemStore: {
  int i = pOp->p1;

  Mem *pMem;

  assert( pTos>=p->aStack );
  if( i>=p->nMem ){
    int nOld = p->nMem;
    Mem *aMem;
    p->nMem = i + 5;
    aMem = sqliteRealloc(p->aMem, p->nMem*sizeof(p->aMem[0]));
    if( aMem==0 ) goto no_mem;
................................................................................
      }
    }
    p->aMem = aMem;
    if( nOld<p->nMem ){
      memset(&p->aMem[nOld], 0, sizeof(p->aMem[0])*(p->nMem-nOld));
    }
  }
  Deephemeralize(pTos);
  pMem = &p->aMem[i];

  Release(pMem);




  *pMem = *pTos;

  if( pMem->flags & MEM_Dyn ){
    if( pOp->p2 ){
      pTos->flags = MEM_Null;
    }else{

      pMem->z = sqliteMallocRaw( pMem->n );
      if( pMem->z==0 ) goto no_mem;
      memcpy(pMem->z, pTos->z, pMem->n);
    }
  }else if( pMem->flags & MEM_Short ){
    pMem->z = pMem->zShort;
  }

  if( pOp->p2 ){
    Release(pTos);
    pTos--;
  }
  break;
}

................................................................................
/* Opcode: AggSet * P2 *
**
** Move the top of the stack into the P2-th field of the current
** aggregate.  String values are duplicated into new memory.
*/
case OP_AggSet: {
  AggElem *pFocus = AggInFocus(p->agg);
  Mem *pMem;
  int i = pOp->p2;
  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;
  if( pMem->flags & MEM_Dyn ){
    pTos->flags = MEM_Null;
  }else if( pMem->flags & MEM_Short ){
    pMem->z = pMem->zShort;
  }


  Release(pTos);
  pTos--;
  break;
}

/* Opcode: AggGet * P2 *
**
** Push a new entry onto the stack which is a copy of the P2-th field
** of the current aggregate.  Strings are not duplicated so
** string values will be ephemeral.
*/
case OP_AggGet: {
  AggElem *pFocus = AggInFocus(p->agg);
  Mem *pMem;
  int i = pOp->p2;
  if( pFocus==0 ) goto no_mem;
  assert( i>=0 && i<p->agg.nMem );
  pTos++;


  pMem = &pFocus->aMem[i];
  *pTos = *pMem;
  pTos->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short);
  pTos->flags |= MEM_Ephem;

  break;
}

/* Opcode: AggNext * P2 *
**
** Make the next aggregate value the current aggregate.  The prior
** aggregate is deleted.  If all aggregate values have been consumed,