1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-12 13:01:09 +03:00

Replace the NOPUSH_MASKs with a bit-vector mechanism that can contain

several different properties about each opcode. (CVS 4677)

FossilOrigin-Name: 042dcb9621934d0318a7c6e9cd08b20a569db367
This commit is contained in:
drh
2008-01-04 16:50:09 +00:00
parent dd2fb29be8
commit 3a40f696d4
6 changed files with 144 additions and 132 deletions

View File

@@ -1,5 +1,5 @@
C Modify\sFifoRead\sand\sFifoWrite\sto\swork\sexclusively\swith\smemory\scells.\s(CVS\s4676) C Replace\sthe\sNOPUSH_MASKs\swith\sa\sbit-vector\smechanism\sthat\scan\scontain\nseveral\sdifferent\sproperties\sabout\seach\sopcode.\s(CVS\s4677)
D 2008-01-04T13:57:26 D 2008-01-04T16:50:09
F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
F Makefile.in 30789bf70614bad659351660d76b8e533f3340e9 F Makefile.in 30789bf70614bad659351660d76b8e533f3340e9
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -69,7 +69,7 @@ F mkdll.sh 5f8438dcac98e795d7df6529159a1ec566de0183
F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f
F mkextw.sh 1a866b53637dab137191341cc875575a5ca110fb F mkextw.sh 1a866b53637dab137191341cc875575a5ca110fb
F mkopcodec.awk 3fb9bf077053c968451f4dd03d11661ac373f9d1 F mkopcodec.awk 3fb9bf077053c968451f4dd03d11661ac373f9d1
F mkopcodeh.awk 799a299eaf3173c0f8ac0bd7c4b49c0f4d4590ca F mkopcodeh.awk 1ae5b01fef9105aa04c3b943223b80ad116e7161
F mkso.sh 24bde4c09e6fe80f718db3c31c068f45e13a2f2c F mkso.sh 24bde4c09e6fe80f718db3c31c068f45e13a2f2c
F publish.sh 1c0658c63d70f182a8f5e17cc28422f1b237f51d F publish.sh 1c0658c63d70f182a8f5e17cc28422f1b237f51d
F publish_osx.sh eca87df1e3d43d128d97d3261fd48b3d6877996e F publish_osx.sh eca87df1e3d43d128d97d3261fd48b3d6877996e
@@ -168,11 +168,11 @@ F src/update.c eaacf59269bd076adca6fab6f5d16ce53419380b
F src/utf.c ef4b7d83bae533b76c3e1bf635b113fdad86a736 F src/utf.c ef4b7d83bae533b76c3e1bf635b113fdad86a736
F src/util.c 05f31144bbd3f1a24f4139ae029c42545cb72624 F src/util.c 05f31144bbd3f1a24f4139ae029c42545cb72624
F src/vacuum.c 3f34f278809bf3eb0b62ec46ff779e9c385b28f0 F src/vacuum.c 3f34f278809bf3eb0b62ec46ff779e9c385b28f0
F src/vdbe.c c562e01b491b589f6e0f830bec7ab1507d1ac844 F src/vdbe.c 8e42b5ce4d69ecf2d17bffd8e520343324785d3e
F src/vdbe.h bb128757b84280504a1243c450fd13ead248ede5 F src/vdbe.h bb128757b84280504a1243c450fd13ead248ede5
F src/vdbeInt.h 869d0f550354c1364dde1d3611d770bd1c767505 F src/vdbeInt.h 31bd686595356284d5484592e2dc6e58025aa346
F src/vdbeapi.c f14174843bf4be2c9afdf2ef48b61e7c3ac62d7c F src/vdbeapi.c f14174843bf4be2c9afdf2ef48b61e7c3ac62d7c
F src/vdbeaux.c eaf5bef96a4564eb0a9b473aa8628b3b5889839d F src/vdbeaux.c 02fef605e37abe4bcec3dbfa42925aac638e5e2b
F src/vdbeblob.c b90f7494c408d47ce6835000b01e40b371e27baf F src/vdbeblob.c b90f7494c408d47ce6835000b01e40b371e27baf
F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6 F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6
F src/vdbemem.c 123994fcd344993d2fb050a83b91b341bbbd08b4 F src/vdbemem.c 123994fcd344993d2fb050a83b91b341bbbd08b4
@@ -603,7 +603,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5 F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
P 173f281334d340290e1978abea5d1ea804141910 P 2c913908a47e7ace7d964067e3566d232ee2d494
R 94a66c73f79f80d8b0a98041731b34af R 7c9e5a234b0556d1a08e9283ee39d755
U danielk1977 U drh
Z fb5d354c01f2e7900c511aa6a77f6954 Z 240c930bb8f98d16c4e85e184409b234

View File

@@ -1 +1 @@
2c913908a47e7ace7d964067e3566d232ee2d494 042dcb9621934d0318a7c6e9cd08b20a569db367

View File

@@ -50,6 +50,13 @@
sub(/:/,"",name) sub(/:/,"",name)
sub("\r","",name) sub("\r","",name)
op[name] = -1 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++){ for(i=3; i<NF; i++){
if($i=="same" && $(i+1)=="as"){ if($i=="same" && $(i+1)=="as"){
sym = $(i+2) sym = $(i+2)
@@ -58,8 +65,23 @@
used[op[name]] = 1 used[op[name]] = 1
sameas[op[name]] = sym sameas[op[name]] = sym
} }
sub(",","",$i)
if($i=="no-push"){ if($i=="no-push"){
nopush[name] = 1 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
} }
} }
} }
@@ -96,32 +118,46 @@ END {
} }
} }
# Generate the 10 16-bit bitmasks used by function opcodeUsesStack() # Generate the bitvectors:
# in vdbeaux.c. See comments in that function for details. #
# # bit 0: jump
nopush[0] = 0 # 0..15 # bit 1: output on P1
nopush[1] = 0 # 16..31 # bit 2: output on P2
nopush[2] = 0 # 32..47 # bit 3: output on P3
nopush[3] = 0 # 48..63 # bit 4: input on P1
nopush[4] = 0 # 64..79 # bit 5: input on P2
nopush[5] = 0 # 80..95 # bit 6: input on P3
nopush[6] = 0 # 96..111 # bit 7: pushes a result onto stack
nopush[7] = 0 # 112..127 #
nopush[8] = 0 # 128..143 for(i=0; i<=max; i++) bv[i] = 0;
nopush[9] = 0 # 144..159
for(name in op){ for(name in op){
if( nopush[name] ){ x = op[name]
n = op[name] if( jump[name] ) bv[x] += 0x01;
j = n%16 if( out1[name] ) bv[x] += 0x02;
i = ((n - j)/16) if( out2[name] ) bv[x] += 0x04;
nopush[i] = nopush[i] + (2^j) 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;
} }
printf "\n" print "\n"
print "/* Opcodes that are guaranteed to never push a value onto the stack" print "/* Properties such as \"out2\" or \"jump\" that are specified in"
print "** contain a 1 their corresponding position of the following mask" print "** comments following the "case" for each opcode in the vdbe.c"
print "** set. See the opcodeNoPush() function in vdbeaux.c */" print "** are encoded into bitvectors as follows:"
for(i=0; i<10; i++){ print "*/"
printf "#define NOPUSH_MASK_%d 0x%04x\n", i, nopush[i] 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 "}"
} }

View File

@@ -43,7 +43,7 @@
** in this file for details. If in doubt, do not deviate from existing ** in this file for details. If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code. ** commenting and indentation practices when changing or adding code.
** **
** $Id: vdbe.c,v 1.676 2008/01/04 13:57:26 danielk1977 Exp $ ** $Id: vdbe.c,v 1.677 2008/01/04 16:50:09 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include <ctype.h> #include <ctype.h>
@@ -172,6 +172,31 @@ static void _storeTypeInfo(Mem *pMem){
} }
} }
/*
** 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. ** Pop the stack N times.
*/ */
@@ -559,18 +584,11 @@ int sqlite3VdbeExec(
#endif #endif
#ifndef NDEBUG #ifndef NDEBUG
/* This is to check that the return value of static function /* This is to check to make sure that the OPFLG_PUSH property
** opcodeNoPush() (see vdbeaux.c) returns values that match the ** is set correctly on all opcodes.
** implementation of the virtual machine in this file. If
** opcodeNoPush() returns non-zero, then the stack is guarenteed
** not to grow when the opcode is executed. If it returns zero, then
** the stack may grow by at most 1.
**
** The global wrapper function sqlite3VdbeOpcodeUsesStack() is not
** available if NDEBUG is defined at build time.
*/ */
pStackLimit = pTos; pStackLimit = pTos;
if( !sqlite3VdbeOpcodeNoPush(pOp->opcode) ){ if( sqlite3VdbeOpcodeHasProperty(pOp->opcode, OPFLG_PUSH) ){
pStackLimit++; pStackLimit++;
} }
#endif #endif
@@ -619,7 +637,7 @@ int sqlite3VdbeExec(
** the one at index P2 from the beginning of ** the one at index P2 from the beginning of
** the program. ** the program.
*/ */
case OP_Goto: { /* no-push */ case OP_Goto: { /* no-push, jump */
CHECK_FOR_INTERRUPT; CHECK_FOR_INTERRUPT;
pc = pOp->p2 - 1; pc = pOp->p2 - 1;
break; break;
@@ -635,7 +653,7 @@ case OP_Goto: { /* no-push */
** the return address stack will fill up and processing will abort ** the return address stack will fill up and processing will abort
** with a fatal error. ** with a fatal error.
*/ */
case OP_Gosub: { /* no-push */ case OP_Gosub: { /* no-push, jump */
assert( p->returnDepth<sizeof(p->returnStack)/sizeof(p->returnStack[0]) ); assert( p->returnDepth<sizeof(p->returnStack)/sizeof(p->returnStack[0]) );
p->returnStack[p->returnDepth++] = pc+1; p->returnStack[p->returnDepth++] = pc+1;
pc = pOp->p2 - 1; pc = pOp->p2 - 1;
@@ -1483,7 +1501,7 @@ case OP_AddImm: { /* no-push */
** current value if P1==0, or to the least integer that is strictly ** current value if P1==0, or to the least integer that is strictly
** greater than its current value if P1==1. ** greater than its current value if P1==1.
*/ */
case OP_ForceInt: { /* no-push */ case OP_ForceInt: { /* no-push, jump */
i64 v; i64 v;
assert( pTos>=p->aStack ); assert( pTos>=p->aStack );
applyAffinity(pTos, SQLITE_AFF_NUMERIC, encoding); applyAffinity(pTos, SQLITE_AFF_NUMERIC, encoding);
@@ -1519,7 +1537,7 @@ case OP_ForceInt: { /* no-push */
** P1 is 1, then the stack is popped. In all other cases, the depth ** P1 is 1, then the stack is popped. In all other cases, the depth
** of the stack is unchanged. ** of the stack is unchanged.
*/ */
case OP_MustBeInt: { /* no-push */ case OP_MustBeInt: { /* no-push, jump */
assert( pTos>=p->aStack ); assert( pTos>=p->aStack );
applyAffinity(pTos, SQLITE_AFF_NUMERIC, encoding); applyAffinity(pTos, SQLITE_AFF_NUMERIC, encoding);
if( (pTos->flags & MEM_Int)==0 ){ if( (pTos->flags & MEM_Int)==0 ){
@@ -1724,12 +1742,12 @@ case OP_ToReal: { /* same as TK_TO_REAL, no-push */
** the 2nd element down on the stack is greater than or equal to the ** 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. ** top of the stack. See the Eq opcode for additional information.
*/ */
case OP_Eq: /* same as TK_EQ, no-push */ case OP_Eq: /* same as TK_EQ, no-push, jump */
case OP_Ne: /* same as TK_NE, no-push */ case OP_Ne: /* same as TK_NE, no-push, jump */
case OP_Lt: /* same as TK_LT, no-push */ case OP_Lt: /* same as TK_LT, no-push, jump */
case OP_Le: /* same as TK_LE, no-push */ case OP_Le: /* same as TK_LE, no-push, jump */
case OP_Gt: /* same as TK_GT, no-push */ case OP_Gt: /* same as TK_GT, no-push, jump */
case OP_Ge: { /* same as TK_GE, no-push */ case OP_Ge: { /* same as TK_GE, no-push, jump */
Mem *pNos; Mem *pNos;
int flags; int flags;
int res; int res;
@@ -1957,8 +1975,8 @@ case OP_Noop: { /* no-push */
** If the value popped of the stack is NULL, then take the jump if P1 ** If the value popped of the stack is NULL, then take the jump if P1
** is true and fall through if P1 is false. ** is true and fall through if P1 is false.
*/ */
case OP_If: /* no-push */ case OP_If: /* no-push, jump */
case OP_IfNot: { /* no-push */ case OP_IfNot: { /* no-push, jump */
int c; int c;
assert( pTos>=p->aStack ); assert( pTos>=p->aStack );
if( pTos->flags & MEM_Null ){ if( pTos->flags & MEM_Null ){
@@ -1985,7 +2003,7 @@ case OP_IfNot: { /* no-push */
** pop -P1 elements from the stack only if the jump is taken and leave ** pop -P1 elements from the stack only if the jump is taken and leave
** the stack unchanged if the jump is not taken. ** the stack unchanged if the jump is not taken.
*/ */
case OP_IsNull: { /* same as TK_ISNULL, no-push */ case OP_IsNull: { /* same as TK_ISNULL, no-push, jump */
if( pTos->flags & MEM_Null ){ if( pTos->flags & MEM_Null ){
pc = pOp->p2-1; pc = pOp->p2-1;
if( pOp->p1<0 ){ if( pOp->p1<0 ){
@@ -2005,7 +2023,7 @@ case OP_IsNull: { /* same as TK_ISNULL, no-push */
** P1 times if P1 is greater than zero. But if P1 is negative, ** P1 times if P1 is greater than zero. But if P1 is negative,
** leave the stack unchanged. ** leave the stack unchanged.
*/ */
case OP_NotNull: { /* same as TK_NOTNULL, no-push */ case OP_NotNull: { /* same as TK_NOTNULL, no-push, jump */
int i, cnt; int i, cnt;
cnt = pOp->p1; cnt = pOp->p1;
if( cnt<0 ) cnt = -cnt; if( cnt<0 ) cnt = -cnt;
@@ -2346,8 +2364,8 @@ op_column_out:
*/ */
case OP_RegMakeRec: case OP_RegMakeRec:
case OP_RegMakeIRec: case OP_RegMakeIRec:
case OP_MakeIdxRec: case OP_MakeIdxRec: /* jump */
case OP_MakeRecord: { case OP_MakeRecord: { /* jump */
/* Assuming the record contains N fields, the record format looks /* Assuming the record contains N fields, the record format looks
** like this: ** like this:
** **
@@ -3068,10 +3086,10 @@ case OP_Close: { /* no-push */
** **
** See also: Found, NotFound, Distinct, MoveGt, MoveGe, MoveLt ** See also: Found, NotFound, Distinct, MoveGt, MoveGe, MoveLt
*/ */
case OP_MoveLt: /* no-push */ case OP_MoveLt: /* no-push, jump */
case OP_MoveLe: /* no-push */ case OP_MoveLe: /* no-push, jump */
case OP_MoveGe: /* no-push */ case OP_MoveGe: /* no-push, jump */
case OP_MoveGt: { /* no-push */ case OP_MoveGt: { /* no-push, jump */
int i = pOp->p1; int i = pOp->p1;
Cursor *pC; Cursor *pC;
@@ -3201,9 +3219,9 @@ case OP_MoveGt: { /* no-push */
** **
** See also: Distinct, Found, MoveTo, NotExists, IsUnique ** See also: Distinct, Found, MoveTo, NotExists, IsUnique
*/ */
case OP_Distinct: /* no-push */ case OP_Distinct: /* no-push, jump */
case OP_NotFound: /* no-push */ case OP_NotFound: /* no-push, jump */
case OP_Found: { /* no-push */ case OP_Found: { /* no-push, jump */
int i = pOp->p1; int i = pOp->p1;
int alreadyExists = 0; int alreadyExists = 0;
Cursor *pC; Cursor *pC;
@@ -3260,7 +3278,7 @@ case OP_Found: { /* no-push */
** **
** See also: Distinct, NotFound, NotExists, Found ** See also: Distinct, NotFound, NotExists, Found
*/ */
case OP_IsUnique: { /* no-push */ case OP_IsUnique: { /* no-push, jump */
int i = pOp->p1; int i = pOp->p1;
Mem *pNos = &pTos[-1]; Mem *pNos = &pTos[-1];
Cursor *pCx; Cursor *pCx;
@@ -3360,7 +3378,7 @@ case OP_IsUnique: { /* no-push */
** **
** See also: Distinct, Found, MoveTo, NotFound, IsUnique ** See also: Distinct, Found, MoveTo, NotFound, IsUnique
*/ */
case OP_NotExists: { /* no-push */ case OP_NotExists: { /* no-push, jump */
int i = pOp->p1; int i = pOp->p1;
Cursor *pC; Cursor *pC;
BtCursor *pCrsr; BtCursor *pCrsr;
@@ -3895,7 +3913,7 @@ case OP_NullRow: { /* no-push */
** If P2 is 0 or if the table or index is not empty, fall through ** If P2 is 0 or if the table or index is not empty, fall through
** to the following instruction. ** to the following instruction.
*/ */
case OP_Last: { /* no-push */ case OP_Last: { /* no-push, jump */
int i = pOp->p1; int i = pOp->p1;
Cursor *pC; Cursor *pC;
BtCursor *pCrsr; BtCursor *pCrsr;
@@ -3931,7 +3949,7 @@ case OP_Last: { /* no-push */
** regression tests can determine whether or not the optimizer is ** regression tests can determine whether or not the optimizer is
** correctly optimizing out sorts. ** correctly optimizing out sorts.
*/ */
case OP_Sort: { /* no-push */ case OP_Sort: { /* no-push, jump */
#ifdef SQLITE_TEST #ifdef SQLITE_TEST
sqlite3_sort_count++; sqlite3_sort_count++;
sqlite3_search_count--; sqlite3_search_count--;
@@ -3946,7 +3964,7 @@ case OP_Sort: { /* no-push */
** If P2 is 0 or if the table or index is not empty, fall through ** If P2 is 0 or if the table or index is not empty, fall through
** to the following instruction. ** to the following instruction.
*/ */
case OP_Rewind: { /* no-push */ case OP_Rewind: { /* no-push, jump */
int i = pOp->p1; int i = pOp->p1;
Cursor *pC; Cursor *pC;
BtCursor *pCrsr; BtCursor *pCrsr;
@@ -3986,8 +4004,8 @@ case OP_Rewind: { /* no-push */
** to the following instruction. But if the cursor backup was successful, ** to the following instruction. But if the cursor backup was successful,
** jump immediately to P2. ** jump immediately to P2.
*/ */
case OP_Prev: /* no-push */ case OP_Prev: /* no-push, jump */
case OP_Next: { /* no-push */ case OP_Next: { /* no-push, jump */
Cursor *pC; Cursor *pC;
BtCursor *pCrsr; BtCursor *pCrsr;
@@ -4172,9 +4190,9 @@ case OP_IdxRowid: {
** an epsilon prior to the comparison. This makes the opcode work ** an epsilon prior to the comparison. This makes the opcode work
** like IdxLE. ** like IdxLE.
*/ */
case OP_IdxLT: /* no-push */ case OP_IdxLT: /* no-push, jump */
case OP_IdxGT: /* no-push */ case OP_IdxGT: /* no-push, jump */
case OP_IdxGE: { /* no-push */ case OP_IdxGE: { /* no-push, jump */
int i= pOp->p1; int i= pOp->p1;
Cursor *pC; Cursor *pC;
@@ -4546,7 +4564,7 @@ case OP_FifoWrite: { /* no-push */
** If the Fifo is empty do not push an entry onto the stack or set ** If the Fifo is empty do not push an entry onto the stack or set
** a memory register but instead jump to P2. ** a memory register but instead jump to P2.
*/ */
case OP_FifoRead: { case OP_FifoRead: { /* jump */
i64 v; i64 v;
CHECK_FOR_INTERRUPT; CHECK_FOR_INTERRUPT;
if( sqlite3VdbeFifoPop(&p->sFifo, &v)==SQLITE_DONE ){ if( sqlite3VdbeFifoPop(&p->sFifo, &v)==SQLITE_DONE ){
@@ -4691,7 +4709,7 @@ case OP_MemIncr: { /* no-push */
** It is illegal to use this instruction on a memory cell that does ** 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. ** not contain an integer. An assertion fault will result if you try.
*/ */
case OP_IfMemPos: { /* no-push */ case OP_IfMemPos: { /* no-push, jump */
int i = pOp->p1; int i = pOp->p1;
Mem *pMem; Mem *pMem;
assert( i>0 && i<=p->nMem ); assert( i>0 && i<=p->nMem );
@@ -4710,7 +4728,7 @@ case OP_IfMemPos: { /* no-push */
** It is illegal to use this instruction on a memory cell that does ** 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. ** not contain an integer. An assertion fault will result if you try.
*/ */
case OP_IfMemNeg: { /* no-push */ case OP_IfMemNeg: { /* no-push, jump */
int i = pOp->p1; int i = pOp->p1;
Mem *pMem; Mem *pMem;
assert( i>0 && i<=p->nMem ); assert( i>0 && i<=p->nMem );
@@ -4729,7 +4747,7 @@ case OP_IfMemNeg: { /* no-push */
** It is illegal to use this instruction on a memory cell that does ** 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. ** not contain an integer. An assertion fault will result if you try.
*/ */
case OP_IfMemZero: { /* no-push */ case OP_IfMemZero: { /* no-push, jump */
int i = pOp->p1; int i = pOp->p1;
Mem *pMem; Mem *pMem;
assert( i>0 && i<=p->nMem ); assert( i>0 && i<=p->nMem );
@@ -4745,7 +4763,7 @@ case OP_IfMemZero: { /* no-push */
** **
** If the value of memory cell P1 is NULL, jump to P2. ** If the value of memory cell P1 is NULL, jump to P2.
*/ */
case OP_IfMemNull: { /* no-push */ case OP_IfMemNull: { /* no-push, jump */
int i = pOp->p1; int i = pOp->p1;
assert( i>0 && i<=p->nMem ); assert( i>0 && i<=p->nMem );
if( p->aMem[i].flags & MEM_Null ){ if( p->aMem[i].flags & MEM_Null ){
@@ -4900,7 +4918,7 @@ case OP_Vacuum: { /* no-push */
** the P1 database. If the vacuum has finished, jump to instruction ** the P1 database. If the vacuum has finished, jump to instruction
** P2. Otherwise, fall through to the next instruction. ** P2. Otherwise, fall through to the next instruction.
*/ */
case OP_IncrVacuum: { /* no-push */ case OP_IncrVacuum: { /* no-push, jump */
Btree *pBt; Btree *pBt;
assert( pOp->p1>=0 && pOp->p1<db->nDb ); assert( pOp->p1>=0 && pOp->p1<db->nDb );
@@ -5060,7 +5078,7 @@ case OP_VOpen: { /* no-push */
** **
** A jump is made to P2 if the result set after filtering would be empty. ** A jump is made to P2 if the result set after filtering would be empty.
*/ */
case OP_VFilter: { /* no-push */ case OP_VFilter: { /* no-push, jump */
int nArg; int nArg;
int iQuery; int iQuery;
const sqlite3_module *pModule; const sqlite3_module *pModule;
@@ -5202,7 +5220,7 @@ case OP_VColumn: {
** jump to instruction P2. Or, if the virtual table has reached ** jump to instruction P2. Or, if the virtual table has reached
** the end of its result set, then fall through to the next instruction. ** the end of its result set, then fall through to the next instruction.
*/ */
case OP_VNext: { /* no-push */ case OP_VNext: { /* no-push, jump */
const sqlite3_module *pModule; const sqlite3_module *pModule;
int res = 0; int res = 0;

View File

@@ -400,10 +400,10 @@ int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*);
void sqlite3VdbeMemRelease(Mem *p); void sqlite3VdbeMemRelease(Mem *p);
int sqlite3VdbeMemFinalize(Mem*, FuncDef*); int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
const char *sqlite3OpcodeName(int); const char *sqlite3OpcodeName(int);
int sqlite3VdbeOpcodeHasProperty(int, int);
#ifndef NDEBUG #ifndef NDEBUG
void sqlite3VdbeMemSanity(Mem*); void sqlite3VdbeMemSanity(Mem*);
int sqlite3VdbeOpcodeNoPush(u8);
#endif #endif
int sqlite3VdbeMemTranslate(Mem*, u8); int sqlite3VdbeMemTranslate(Mem*, u8);
#ifdef SQLITE_DEBUG #ifdef SQLITE_DEBUG

View File

@@ -232,48 +232,6 @@ void sqlite3VdbeResolveLabel(Vdbe *p, int x){
} }
} }
/*
** Return non-zero if opcode 'op' is guarenteed not to push more values
** onto the VDBE stack than it pops off.
*/
static int opcodeNoPush(u8 op){
/* The 10 NOPUSH_MASK_n constants are defined in the automatically
** generated header file opcodes.h. Each is a 16-bit bitmask, one
** bit corresponding to each opcode implemented by the virtual
** machine in vdbe.c. The bit is true if the word "no-push" appears
** in a comment on the same line as the "case OP_XXX:" in
** sqlite3VdbeExec() in vdbe.c.
**
** If the bit is true, then the corresponding opcode is guarenteed not
** to grow the stack when it is executed. Otherwise, it may grow the
** stack by at most one entry.
**
** NOPUSH_MASK_0 corresponds to opcodes 0 to 15. NOPUSH_MASK_1 contains
** one bit for opcodes 16 to 31, and so on.
**
** 16-bit bitmasks (rather than 32-bit) are specified in opcodes.h
** because the file is generated by an awk program. Awk manipulates
** all numbers as floating-point and we don't want to risk a rounding
** error if someone builds with an awk that uses (for example) 32-bit
** IEEE floats.
*/
static const u32 masks[5] = {
NOPUSH_MASK_0 + (((unsigned)NOPUSH_MASK_1)<<16),
NOPUSH_MASK_2 + (((unsigned)NOPUSH_MASK_3)<<16),
NOPUSH_MASK_4 + (((unsigned)NOPUSH_MASK_5)<<16),
NOPUSH_MASK_6 + (((unsigned)NOPUSH_MASK_7)<<16),
NOPUSH_MASK_8 + (((unsigned)NOPUSH_MASK_9)<<16)
};
assert( op<32*5 );
return (masks[op>>5] & (1<<(op&0x1F)));
}
#ifndef NDEBUG
int sqlite3VdbeOpcodeNoPush(u8 op){
return opcodeNoPush(op);
}
#endif
/* /*
** Loop through the program looking for P2 values that are negative. ** Loop through the program looking for P2 values that are negative.
** Each such value is a label. Resolve the label by setting the P2 ** Each such value is a label. Resolve the label by setting the P2
@@ -338,7 +296,7 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs, int *pMaxStack){
if( n>nMaxArgs ) nMaxArgs = n; if( n>nMaxArgs ) nMaxArgs = n;
#endif #endif
} }
if( opcodeNoPush(opcode) ){ if( !sqlite3VdbeOpcodeHasProperty(opcode, OPFLG_PUSH) ){
nMaxStack--; nMaxStack--;
} }