Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Replace the NOPUSH_MASKs with a bit-vector mechanism that can contain several different properties about each opcode. (CVS 4677) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
042dcb9621934d0318a7c6e9cd08b20a |
User & Date: | drh 2008-01-04 16:50:09.000 |
Context
2008-01-04
| ||
19:10 | Some modifications to insert.c to work without using the stack. (CVS 4678) (check-in: d9ac6beef5 user: danielk1977 tags: trunk) | |
16:50 | Replace the NOPUSH_MASKs with a bit-vector mechanism that can contain several different properties about each opcode. (CVS 4677) (check-in: 042dcb9621 user: drh tags: trunk) | |
13:57 | Modify FifoRead and FifoWrite to work exclusively with memory cells. (CVS 4676) (check-in: 2c913908a4 user: danielk1977 tags: trunk) | |
Changes
Changes to mkopcodeh.awk.
︙ | ︙ | |||
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | # Scan for "case OP_aaaa:" lines in the vdbe.c file /^case OP_/ { name = $2 sub(/:/,"",name) sub("\r","",name) op[name] = -1 for(i=3; i<NF; i++){ if($i=="same" && $(i+1)=="as"){ sym = $(i+2) sub(/,/,"",sym) op[name] = tk[sym] used[op[name]] = 1 sameas[op[name]] = sym } if($i=="no-push"){ nopush[name] = 1 } } } # Assign numbers to all opcodes and output the result. END { cnt = 0 | > > > > > > > > > > > > > > > > > > > > > > | 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | # Scan for "case OP_aaaa:" lines in the vdbe.c file /^case OP_/ { name = $2 sub(/:/,"",name) sub("\r","",name) op[name] = -1 out1[name] = 0 out2[name] = 0 out3[name] = 0 jump[name] = 0 in1[name] = 0 in2[name] = 0 in3[name] = 0 for(i=3; i<NF; i++){ if($i=="same" && $(i+1)=="as"){ sym = $(i+2) sub(/,/,"",sym) op[name] = tk[sym] used[op[name]] = 1 sameas[op[name]] = sym } sub(",","",$i) if($i=="no-push"){ nopush[name] = 1 }else if($i=="out1"){ out1[name] = 1 }else if($i=="out2"){ out2[name] = 2 }else if($i=="out3"){ out3[name] = 3 }else if($i=="in1"){ in1[name] = 1 }else if($i=="in2"){ in2[name] = 1 }else if($i=="in3"){ in3[name] = 1 }else if($i=="jump"){ jump[name] = 1 } } } # Assign numbers to all opcodes and output the result. END { cnt = 0 |
︙ | ︙ | |||
92 93 94 95 96 97 98 | printf "\n/* The following opcode values are never used */\n" seenUnused = 1 } printf "#define %-25s %15d\n", sprintf( "OP_NotUsed_%-3d", i ), i } } | | < | > | | | | | | | > | < < < | | > > | > > > | | < | | | > | > > > > > > > > > | | > > | 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 | printf "\n/* The following opcode values are never used */\n" seenUnused = 1 } printf "#define %-25s %15d\n", sprintf( "OP_NotUsed_%-3d", i ), i } } # Generate the bitvectors: # # bit 0: jump # bit 1: output on P1 # bit 2: output on P2 # bit 3: output on P3 # bit 4: input on P1 # bit 5: input on P2 # bit 6: input on P3 # bit 7: pushes a result onto stack # for(i=0; i<=max; i++) bv[i] = 0; for(name in op){ x = op[name] if( jump[name] ) bv[x] += 0x01; if( out1[name] ) bv[x] += 0x02; if( out2[name] ) bv[x] += 0x04; if( out3[name] ) bv[x] += 0x08; if( in1[name] ) bv[x] += 0x10; if( in2[name] ) bv[x] += 0x20; if( in3[name] ) bv[x] += 0x40; if( !nopush[name] ) bv[x] += 0x80; } print "\n" print "/* Properties such as \"out2\" or \"jump\" that are specified in" print "** comments following the "case" for each opcode in the vdbe.c" print "** are encoded into bitvectors as follows:" print "*/" print "#define OPFLG_JUMP 0x01 /* jump: P2 holds a jump target */" print "#define OPFLG_OUT1 0x02 /* out1: P1 specifies output reg */" print "#define OPFLG_OUT2 0x04 /* out2: P2 specifies output reg */" print "#define OPFLG_OUT3 0x08 /* out3: P3 specifies output reg */" print "#define OPFLG_IN1 0x10 /* in1: P1 is an input reg */" print "#define OPFLG_IN2 0x20 /* in2: P2 is an input reg */" print "#define OPFLG_IN3 0x40 /* in3: P3 is an input reg */" print "#define OPFLG_PUSH 0x80 /* omits no-push: Does not push */" print "#define OPFLG_INITIALIZER {\\" for(i=0; i<=max; i++){ printf " 0x%02x,", bv[i] if( i%10==9 ) printf("\\\n"); } print "}" } |
Changes to src/vdbe.c.
︙ | ︙ | |||
39 40 41 42 43 44 45 | ** ** 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. ** | | | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | ** ** 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.677 2008/01/04 16:50:09 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> #include "vdbeInt.h" /* ** The following global variable is incremented every time a cursor |
︙ | ︙ | |||
167 168 169 170 171 172 173 174 175 176 177 178 179 180 | } else if( flags & MEM_Str ){ pMem->type = SQLITE_TEXT; }else{ pMem->type = SQLITE_BLOB; } } /* ** Pop the stack N times. */ static void popStack(Mem **ppTos, int N){ Mem *pTos = *ppTos; while( N>0 ){ | > > > > > > > > > > > > > > > > > > > > > > > > > | 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 | } else if( flags & MEM_Str ){ pMem->type = SQLITE_TEXT; }else{ pMem->type = SQLITE_BLOB; } } /* ** Properties of opcodes. The OPFLG_INITIALIZER macro is ** created by mkopcodeh.awk during compilation. Data is obtained ** from the comments following the "case OP_xxxx:" statements in ** this file. ** ** jump: OPFLG_JUMP ** out1: OPFLG_OUT1 ** out2: OPFLG_OUT2 ** out3: OPFLG_OUT3 ** in1: OPFLG_IN1 ** in2: OPFLG_IN2 ** in3: OPFLG_IN3 */ static unsigned char opcodeProperty[] = OPFLG_INITIALIZER; /* ** Return true if an opcode has any of the OPFLG_xxx properties ** specified by mask. */ int sqlite3VdbeOpcodeHasProperty(int opcode, int mask){ assert( opcode>0 && opcode<sizeof(opcodeProperty) ); return (opcodeProperty[opcode]&mask)!=0; } /* ** Pop the stack N times. */ static void popStack(Mem **ppTos, int N){ Mem *pTos = *ppTos; while( N>0 ){ |
︙ | ︙ | |||
555 556 557 558 559 560 561 | nProgressOps = 0; } nProgressOps++; } #endif #ifndef NDEBUG | | < < < < < | < < | | 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 | nProgressOps = 0; } nProgressOps++; } #endif #ifndef NDEBUG /* This is to check to make sure that the OPFLG_PUSH property ** is set correctly on all opcodes. */ pStackLimit = pTos; if( sqlite3VdbeOpcodeHasProperty(pOp->opcode, OPFLG_PUSH) ){ pStackLimit++; } #endif switch( pOp->opcode ){ /***************************************************************************** |
︙ | ︙ | |||
615 616 617 618 619 620 621 | /* Opcode: Goto * P2 * ** ** An unconditional jump to address P2. ** The next instruction executed will be ** the one at index P2 from the beginning of ** the program. */ | | | | 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 | /* Opcode: Goto * P2 * ** ** An unconditional jump to address P2. ** The next instruction executed will be ** the one at index P2 from the beginning of ** the program. */ case OP_Goto: { /* no-push, jump */ CHECK_FOR_INTERRUPT; pc = pOp->p2 - 1; break; } /* Opcode: Gosub * P2 * ** ** Push the current address plus 1 onto the return address stack ** and then jump to address P2. ** ** The return address stack is of limited depth. If too many ** OP_Gosub operations occur without intervening OP_Returns, then ** the return address stack will fill up and processing will abort ** with a fatal error. */ case OP_Gosub: { /* no-push, jump */ assert( p->returnDepth<sizeof(p->returnStack)/sizeof(p->returnStack[0]) ); p->returnStack[p->returnDepth++] = pc+1; pc = pOp->p2 - 1; break; } /* Opcode: Return * * * |
︙ | ︙ | |||
1479 1480 1481 1482 1483 1484 1485 | ** the stack is not numeric (meaning that is is a NULL or a string that ** does not look like an integer or floating point number) then pop the ** stack and jump to P2. If the top of the stack is numeric then ** convert it into the least integer that is greater than or equal to its ** current value if P1==0, or to the least integer that is strictly ** greater than its current value if P1==1. */ | | | 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 | ** the stack is not numeric (meaning that is is a NULL or a string that ** does not look like an integer or floating point number) then pop the ** stack and jump to P2. If the top of the stack is numeric then ** convert it into the least integer that is greater than or equal to its ** current value if P1==0, or to the least integer that is strictly ** greater than its current value if P1==1. */ case OP_ForceInt: { /* no-push, jump */ i64 v; assert( pTos>=p->aStack ); applyAffinity(pTos, SQLITE_AFF_NUMERIC, encoding); if( (pTos->flags & (MEM_Int|MEM_Real))==0 ){ Release(pTos); pTos--; pc = pOp->p2 - 1; |
︙ | ︙ | |||
1515 1516 1517 1518 1519 1520 1521 | ** without data loss, then jump immediately to P2, or if P2==0 ** raise an SQLITE_MISMATCH exception. ** ** If the top of the stack is not an integer and P2 is not zero and ** P1 is 1, then the stack is popped. In all other cases, the depth ** of the stack is unchanged. */ | | | 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 | ** without data loss, then jump immediately to P2, or if P2==0 ** raise an SQLITE_MISMATCH exception. ** ** If the top of the stack is not an integer and P2 is not zero and ** P1 is 1, then the stack is popped. In all other cases, the depth ** of the stack is unchanged. */ case OP_MustBeInt: { /* no-push, jump */ assert( pTos>=p->aStack ); applyAffinity(pTos, SQLITE_AFF_NUMERIC, encoding); if( (pTos->flags & MEM_Int)==0 ){ if( pOp->p2==0 ){ rc = SQLITE_MISMATCH; goto abort_due_to_error; }else{ |
︙ | ︙ | |||
1720 1721 1722 1723 1724 1725 1726 | */ /* Opcode: Ge P1 P2 P4 ** ** This works just like the Eq opcode except that the jump is taken if ** the 2nd element down on the stack is greater than or equal to the ** top of the stack. See the Eq opcode for additional information. */ | | | | | | | | 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 | */ /* Opcode: Ge P1 P2 P4 ** ** This works just like the Eq opcode except that the jump is taken if ** the 2nd element down on the stack is greater than or equal to the ** top of the stack. See the Eq opcode for additional information. */ case OP_Eq: /* same as TK_EQ, no-push, jump */ case OP_Ne: /* same as TK_NE, no-push, jump */ case OP_Lt: /* same as TK_LT, no-push, jump */ case OP_Le: /* same as TK_LE, no-push, jump */ case OP_Gt: /* same as TK_GT, no-push, jump */ case OP_Ge: { /* same as TK_GE, no-push, jump */ Mem *pNos; int flags; int res; char affinity; pNos = &pTos[-1]; flags = pTos->flags|pNos->flags; |
︙ | ︙ | |||
1953 1954 1955 1956 1957 1958 1959 | ** false, then jump to p2. Otherwise continue to the next instruction. ** An integer is false if zero and true otherwise. A string is ** false if it has zero length and true otherwise. ** ** If the value popped of the stack is NULL, then take the jump if P1 ** is true and fall through if P1 is false. */ | | | | 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 | ** false, then jump to p2. Otherwise continue to the next instruction. ** An integer is false if zero and true otherwise. A string is ** false if it has zero length and true otherwise. ** ** If the value popped of the stack is NULL, then take the jump if P1 ** is true and fall through if P1 is false. */ case OP_If: /* no-push, jump */ case OP_IfNot: { /* no-push, jump */ int c; assert( pTos>=p->aStack ); if( pTos->flags & MEM_Null ){ c = pOp->p1; }else{ #ifdef SQLITE_OMIT_FLOATING_POINT c = sqlite3VdbeIntValue(pTos); |
︙ | ︙ | |||
1981 1982 1983 1984 1985 1986 1987 | ** ** Check the top of the stack and jump to P2 if the top of the stack ** is NULL. If P1 is positive, then pop P1 elements from the stack ** regardless of whether or not the jump is taken. If P1 is negative, ** pop -P1 elements from the stack only if the jump is taken and leave ** the stack unchanged if the jump is not taken. */ | | | | 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 | ** ** Check the top of the stack and jump to P2 if the top of the stack ** is NULL. If P1 is positive, then pop P1 elements from the stack ** regardless of whether or not the jump is taken. If P1 is negative, ** pop -P1 elements from the stack only if the jump is taken and leave ** the stack unchanged if the jump is not taken. */ case OP_IsNull: { /* same as TK_ISNULL, no-push, jump */ if( pTos->flags & MEM_Null ){ pc = pOp->p2-1; if( pOp->p1<0 ){ popStack(&pTos, -pOp->p1); } } if( pOp->p1>0 ){ popStack(&pTos, pOp->p1); } break; } /* Opcode: NotNull P1 P2 * ** ** Jump to P2 if the top abs(P1) values on the stack are all not NULL. ** Regardless of whether or not the jump is taken, pop the stack ** P1 times if P1 is greater than zero. But if P1 is negative, ** leave the stack unchanged. */ case OP_NotNull: { /* same as TK_NOTNULL, no-push, jump */ int i, cnt; cnt = pOp->p1; if( cnt<0 ) cnt = -cnt; assert( &pTos[1-cnt] >= p->aStack ); for(i=0; i<cnt && (pTos[1+i-cnt].flags & MEM_Null)==0; i++){} if( i>=cnt ) pc = pOp->p2-1; if( pOp->p1>0 ) popStack(&pTos, cnt); |
︙ | ︙ | |||
2342 2343 2344 2345 2346 2347 2348 | ** Works like OP_MakeIdxRec except data is taken from registers ** rather than from the stack. The P1 register is an integer which ** is the number of register to use in building the new record. ** Data is taken from P1+1, P1+2, ..., P1+mem[P1]. */ case OP_RegMakeRec: case OP_RegMakeIRec: | | | | 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 | ** Works like OP_MakeIdxRec except data is taken from registers ** rather than from the stack. The P1 register is an integer which ** is the number of register to use in building the new record. ** Data is taken from P1+1, P1+2, ..., P1+mem[P1]. */ case OP_RegMakeRec: case OP_RegMakeIRec: case OP_MakeIdxRec: /* jump */ case OP_MakeRecord: { /* jump */ /* Assuming the record contains N fields, the record format looks ** like this: ** ** ------------------------------------------------------------------------ ** | hdr-size | type 0 | type 1 | ... | type N-1 | data0 | ... | data N-1 | ** ------------------------------------------------------------------------ ** |
︙ | ︙ | |||
3064 3065 3066 3067 3068 3069 3070 | ** cursor P1 so that it points to the largest entry that is less than ** or equal to the key that was popped from the stack. ** If there are no records less than or eqal to the key and P2 is not zero, ** then jump to P2. ** ** See also: Found, NotFound, Distinct, MoveGt, MoveGe, MoveLt */ | | | | | | 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 | ** cursor P1 so that it points to the largest entry that is less than ** or equal to the key that was popped from the stack. ** If there are no records less than or eqal to the key and P2 is not zero, ** then jump to P2. ** ** See also: Found, NotFound, Distinct, MoveGt, MoveGe, MoveLt */ case OP_MoveLt: /* no-push, jump */ case OP_MoveLe: /* no-push, jump */ case OP_MoveGe: /* no-push, jump */ case OP_MoveGt: { /* no-push, jump */ int i = pOp->p1; Cursor *pC; assert( pTos>=p->aStack ); assert( i>=0 && i<p->nCursor ); pC = p->apCsr[i]; assert( pC!=0 ); |
︙ | ︙ | |||
3197 3198 3199 3200 3201 3202 3203 | ** pointing to the entry that matches. The blob is popped from the stack. ** ** The difference between this operation and Distinct is that ** Distinct does not pop the key from the stack. ** ** See also: Distinct, Found, MoveTo, NotExists, IsUnique */ | | | | | 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 | ** pointing to the entry that matches. The blob is popped from the stack. ** ** The difference between this operation and Distinct is that ** Distinct does not pop the key from the stack. ** ** See also: Distinct, Found, MoveTo, NotExists, IsUnique */ case OP_Distinct: /* no-push, jump */ case OP_NotFound: /* no-push, jump */ case OP_Found: { /* no-push, jump */ int i = pOp->p1; int alreadyExists = 0; Cursor *pC; assert( pTos>=p->aStack ); assert( i>=0 && i<p->nCursor ); assert( p->apCsr[i]!=0 ); if( (pC = p->apCsr[i])->pCursor!=0 ){ |
︙ | ︙ | |||
3256 3257 3258 3259 3260 3261 3262 | ** jump to P2. If any entry does exist where the index string ** matches K but the record number is not R, then the record ** number for that entry is pushed onto the stack and control ** falls through to the next instruction. ** ** See also: Distinct, NotFound, NotExists, Found */ | | | 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 | ** jump to P2. If any entry does exist where the index string ** matches K but the record number is not R, then the record ** number for that entry is pushed onto the stack and control ** falls through to the next instruction. ** ** See also: Distinct, NotFound, NotExists, Found */ case OP_IsUnique: { /* no-push, jump */ int i = pOp->p1; Mem *pNos = &pTos[-1]; Cursor *pCx; BtCursor *pCrsr; i64 R; /* Pop the value R off the top of the stack |
︙ | ︙ | |||
3356 3357 3358 3359 3360 3361 3362 | ** The difference between this operation and NotFound is that this ** operation assumes the key is an integer and that P1 is a table whereas ** NotFound assumes key is a blob constructed from MakeRecord and ** P1 is an index. ** ** See also: Distinct, Found, MoveTo, NotFound, IsUnique */ | | | 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 | ** The difference between this operation and NotFound is that this ** operation assumes the key is an integer and that P1 is a table whereas ** NotFound assumes key is a blob constructed from MakeRecord and ** P1 is an index. ** ** See also: Distinct, Found, MoveTo, NotFound, IsUnique */ case OP_NotExists: { /* no-push, jump */ int i = pOp->p1; Cursor *pC; BtCursor *pCrsr; Mem *pKey; if( pOp->p3 ){ assert( pOp->p3<=p->nMem ); pKey = &p->aMem[pOp->p3]; |
︙ | ︙ | |||
3891 3892 3893 3894 3895 3896 3897 | ** ** The next use of the Rowid or Column or Next instruction for P1 ** will refer to the last entry in the database table or index. ** If the table or index is empty and P2>0, then jump immediately to P2. ** If P2 is 0 or if the table or index is not empty, fall through ** to the following instruction. */ | | | 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 | ** ** The next use of the Rowid or Column or Next instruction for P1 ** will refer to the last entry in the database table or index. ** If the table or index is empty and P2>0, then jump immediately to P2. ** If P2 is 0 or if the table or index is not empty, fall through ** to the following instruction. */ case OP_Last: { /* no-push, jump */ int i = pOp->p1; Cursor *pC; BtCursor *pCrsr; assert( i>=0 && i<p->nCursor ); pC = p->apCsr[i]; assert( pC!=0 ); |
︙ | ︙ | |||
3927 3928 3929 3930 3931 3932 3933 | ** Sorting is accomplished by writing records into a sorting index, ** then rewinding that index and playing it back from beginning to ** end. We use the OP_Sort opcode instead of OP_Rewind to do the ** rewinding so that the global variable will be incremented and ** regression tests can determine whether or not the optimizer is ** correctly optimizing out sorts. */ | | | | 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 | ** Sorting is accomplished by writing records into a sorting index, ** then rewinding that index and playing it back from beginning to ** end. We use the OP_Sort opcode instead of OP_Rewind to do the ** rewinding so that the global variable will be incremented and ** regression tests can determine whether or not the optimizer is ** correctly optimizing out sorts. */ case OP_Sort: { /* no-push, jump */ #ifdef SQLITE_TEST sqlite3_sort_count++; sqlite3_search_count--; #endif /* Fall through into OP_Rewind */ } /* Opcode: Rewind P1 P2 * ** ** The next use of the Rowid or Column or Next instruction for P1 ** will refer to the first entry in the database table or index. ** If the table or index is empty and P2>0, then jump immediately to P2. ** If P2 is 0 or if the table or index is not empty, fall through ** to the following instruction. */ case OP_Rewind: { /* no-push, jump */ int i = pOp->p1; Cursor *pC; BtCursor *pCrsr; int res; assert( i>=0 && i<p->nCursor ); pC = p->apCsr[i]; |
︙ | ︙ | |||
3982 3983 3984 3985 3986 3987 3988 | /* Opcode: Prev P1 P2 * ** ** Back up cursor P1 so that it points to the previous key/data pair in its ** table or index. If there is no previous key/value pairs then fall through ** to the following instruction. But if the cursor backup was successful, ** jump immediately to P2. */ | | | | 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 | /* Opcode: Prev P1 P2 * ** ** Back up cursor P1 so that it points to the previous key/data pair in its ** table or index. If there is no previous key/value pairs then fall through ** to the following instruction. But if the cursor backup was successful, ** jump immediately to P2. */ case OP_Prev: /* no-push, jump */ case OP_Next: { /* no-push, jump */ Cursor *pC; BtCursor *pCrsr; CHECK_FOR_INTERRUPT; assert( pOp->p1>=0 && pOp->p1<p->nCursor ); pC = p->apCsr[pOp->p1]; if( pC==0 ){ |
︙ | ︙ | |||
4168 4169 4170 4171 4172 4173 4174 | ** In either case, the stack is popped once. ** ** If P4 is the "+" string (or any other non-NULL string) then the ** index taken from the top of the stack is temporarily increased by ** an epsilon prior to the comparison. This makes the opcode work ** like IdxLE. */ | | | | | 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 | ** In either case, the stack is popped once. ** ** If P4 is the "+" string (or any other non-NULL string) then the ** index taken from the top of the stack is temporarily increased by ** an epsilon prior to the comparison. This makes the opcode work ** like IdxLE. */ case OP_IdxLT: /* no-push, jump */ case OP_IdxGT: /* no-push, jump */ case OP_IdxGE: { /* no-push, jump */ int i= pOp->p1; Cursor *pC; assert( i>=0 && i<p->nCursor ); assert( p->apCsr[i]!=0 ); assert( pTos>=p->aStack ); if( (pC = p->apCsr[i])->pCursor!=0 ){ |
︙ | ︙ | |||
4542 4543 4544 4545 4546 4547 4548 | ** Attempt to read a single integer from the Fifo. If P1 is zero, ** push the result onto the stack. Otherwise, store the read integer ** in register P1. ** ** If the Fifo is empty do not push an entry onto the stack or set ** a memory register but instead jump to P2. */ | | | 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 | ** Attempt to read a single integer from the Fifo. If P1 is zero, ** push the result onto the stack. Otherwise, store the read integer ** in register P1. ** ** If the Fifo is empty do not push an entry onto the stack or set ** a memory register but instead jump to P2. */ case OP_FifoRead: { /* jump */ i64 v; CHECK_FOR_INTERRUPT; if( sqlite3VdbeFifoPop(&p->sFifo, &v)==SQLITE_DONE ){ pc = pOp->p2 - 1; }else{ Mem *pOut = &p->aMem[pOp->p1]; assert( pOp->p1>0 && pOp->p1<=p->nMem ); |
︙ | ︙ | |||
4687 4688 4689 4690 4691 4692 4693 | /* Opcode: IfMemPos P1 P2 * ** ** If the value of memory cell P1 is 1 or greater, jump to P2. ** ** It is illegal to use this instruction on a memory cell that does ** not contain an integer. An assertion fault will result if you try. */ | | | | | | 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 | /* Opcode: IfMemPos P1 P2 * ** ** If the value of memory cell P1 is 1 or greater, jump to P2. ** ** It is illegal to use this instruction on a memory cell that does ** not contain an integer. An assertion fault will result if you try. */ case OP_IfMemPos: { /* no-push, jump */ int i = pOp->p1; Mem *pMem; assert( i>0 && i<=p->nMem ); pMem = &p->aMem[i]; assert( pMem->flags==MEM_Int ); if( pMem->u.i>0 ){ pc = pOp->p2 - 1; } break; } /* Opcode: IfMemNeg P1 P2 * ** ** If the value of memory cell P1 is less than zero, jump to P2. ** ** It is illegal to use this instruction on a memory cell that does ** not contain an integer. An assertion fault will result if you try. */ case OP_IfMemNeg: { /* no-push, jump */ int i = pOp->p1; Mem *pMem; assert( i>0 && i<=p->nMem ); pMem = &p->aMem[i]; assert( pMem->flags==MEM_Int ); if( pMem->u.i<0 ){ pc = pOp->p2 - 1; } break; } /* Opcode: IfMemZero P1 P2 * ** ** If the value of memory cell P1 is exactly 0, jump to P2. ** ** It is illegal to use this instruction on a memory cell that does ** not contain an integer. An assertion fault will result if you try. */ case OP_IfMemZero: { /* no-push, jump */ int i = pOp->p1; Mem *pMem; assert( i>0 && i<=p->nMem ); pMem = &p->aMem[i]; assert( pMem->flags==MEM_Int ); if( pMem->u.i==0 ){ pc = pOp->p2 - 1; } break; } /* Opcode: IfMemNull P1 P2 * ** ** If the value of memory cell P1 is NULL, jump to P2. */ case OP_IfMemNull: { /* no-push, jump */ int i = pOp->p1; assert( i>0 && i<=p->nMem ); if( p->aMem[i].flags & MEM_Null ){ pc = pOp->p2 - 1; } break; } |
︙ | ︙ | |||
4896 4897 4898 4899 4900 4901 4902 | #if !defined(SQLITE_OMIT_AUTOVACUUM) /* Opcode: IncrVacuum P1 P2 * ** ** Perform a single step of the incremental vacuum procedure on ** the P1 database. If the vacuum has finished, jump to instruction ** P2. Otherwise, fall through to the next instruction. */ | | | 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 | #if !defined(SQLITE_OMIT_AUTOVACUUM) /* Opcode: IncrVacuum P1 P2 * ** ** Perform a single step of the incremental vacuum procedure on ** the P1 database. If the vacuum has finished, jump to instruction ** P2. Otherwise, fall through to the next instruction. */ case OP_IncrVacuum: { /* no-push, jump */ Btree *pBt; assert( pOp->p1>=0 && pOp->p1<db->nDb ); assert( (p->btreeMask & (1<<pOp->p1))!=0 ); pBt = db->aDb[pOp->p1].pBt; rc = sqlite3BtreeIncrVacuum(pBt); if( rc==SQLITE_DONE ){ |
︙ | ︙ | |||
5056 5057 5058 5059 5060 5061 5062 | ** P3. Register P3+1 stores the argc parameter to be passed to the ** xFilter method. Registers P3+2..P3+1+argc are the argc additional ** parametersneath additional parameters which are passed to ** xFilter as argv. Register P3+2 becomes argv[0] when passed to xFilter. ** ** A jump is made to P2 if the result set after filtering would be empty. */ | | | 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 | ** P3. Register P3+1 stores the argc parameter to be passed to the ** xFilter method. Registers P3+2..P3+1+argc are the argc additional ** parametersneath additional parameters which are passed to ** xFilter as argv. Register P3+2 becomes argv[0] when passed to xFilter. ** ** A jump is made to P2 if the result set after filtering would be empty. */ case OP_VFilter: { /* no-push, jump */ int nArg; int iQuery; const sqlite3_module *pModule; Mem *pQuery = &p->aMem[pOp->p3]; Mem *pArgc = &pQuery[1]; Cursor *pCur = p->apCsr[pOp->p1]; |
︙ | ︙ | |||
5198 5199 5200 5201 5202 5203 5204 | #ifndef SQLITE_OMIT_VIRTUALTABLE /* Opcode: VNext P1 P2 * ** ** Advance virtual table P1 to the next row in its result set and ** jump to instruction P2. Or, if the virtual table has reached ** the end of its result set, then fall through to the next instruction. */ | | | 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 | #ifndef SQLITE_OMIT_VIRTUALTABLE /* Opcode: VNext P1 P2 * ** ** Advance virtual table P1 to the next row in its result set and ** jump to instruction P2. Or, if the virtual table has reached ** the end of its result set, then fall through to the next instruction. */ case OP_VNext: { /* no-push, jump */ const sqlite3_module *pModule; int res = 0; Cursor *pCur = p->apCsr[pOp->p1]; assert( pCur->pVtabCursor ); pModule = pCur->pVtabCursor->pVtab->pModule; if( pModule->xNext==0 ){ |
︙ | ︙ |
Changes to src/vdbeInt.h.
︙ | ︙ | |||
396 397 398 399 400 401 402 403 404 405 | void sqlite3VdbeIntegerAffinity(Mem*); int sqlite3VdbeMemRealify(Mem*); int sqlite3VdbeMemNumerify(Mem*); int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*); void sqlite3VdbeMemRelease(Mem *p); int sqlite3VdbeMemFinalize(Mem*, FuncDef*); const char *sqlite3OpcodeName(int); #ifndef NDEBUG void sqlite3VdbeMemSanity(Mem*); | > < | 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 | void sqlite3VdbeIntegerAffinity(Mem*); int sqlite3VdbeMemRealify(Mem*); int sqlite3VdbeMemNumerify(Mem*); int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*); void sqlite3VdbeMemRelease(Mem *p); int sqlite3VdbeMemFinalize(Mem*, FuncDef*); const char *sqlite3OpcodeName(int); int sqlite3VdbeOpcodeHasProperty(int, int); #ifndef NDEBUG void sqlite3VdbeMemSanity(Mem*); #endif int sqlite3VdbeMemTranslate(Mem*, u8); #ifdef SQLITE_DEBUG void sqlite3VdbePrintSql(Vdbe*); void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf); #endif int sqlite3VdbeMemHandleBom(Mem *pMem); |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
228 229 230 231 232 233 234 | assert( p->magic==VDBE_MAGIC_INIT ); assert( j>=0 && j<p->nLabel ); if( p->aLabel ){ p->aLabel[j] = p->nOp; } } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 228 229 230 231 232 233 234 235 236 237 238 239 240 241 | assert( p->magic==VDBE_MAGIC_INIT ); assert( j>=0 && j<p->nLabel ); if( p->aLabel ){ p->aLabel[j] = p->nOp; } } /* ** Loop through the program looking for P2 values that are negative. ** Each such value is a label. Resolve the label by setting the P2 ** value to its correct non-zero value. ** ** This routine is called once after all opcodes have been inserted. ** |
︙ | ︙ | |||
334 335 336 337 338 339 340 | int n; assert( p->nOp - i >= 3 ); assert( pOp[-1].opcode==OP_MemInt ); n = pOp[-1].p1; if( n>nMaxArgs ) nMaxArgs = n; #endif } | | | 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 | int n; assert( p->nOp - i >= 3 ); assert( pOp[-1].opcode==OP_MemInt ); n = pOp[-1].p1; if( n>nMaxArgs ) nMaxArgs = n; #endif } if( !sqlite3VdbeOpcodeHasProperty(opcode, OPFLG_PUSH) ){ nMaxStack--; } if( pOp->p2>=0 ) continue; assert( -1-pOp->p2<p->nLabel ); pOp->p2 = aLabel[-1-pOp->p2]; } |
︙ | ︙ |