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:
20
manifest
20
manifest
@@ -1,5 +1,5 @@
|
||||
C Modify\sFifoRead\sand\sFifoWrite\sto\swork\sexclusively\swith\smemory\scells.\s(CVS\s4676)
|
||||
D 2008-01-04T13:57:26
|
||||
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-04T16:50:09
|
||||
F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
|
||||
F Makefile.in 30789bf70614bad659351660d76b8e533f3340e9
|
||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||
@@ -69,7 +69,7 @@ F mkdll.sh 5f8438dcac98e795d7df6529159a1ec566de0183
|
||||
F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f
|
||||
F mkextw.sh 1a866b53637dab137191341cc875575a5ca110fb
|
||||
F mkopcodec.awk 3fb9bf077053c968451f4dd03d11661ac373f9d1
|
||||
F mkopcodeh.awk 799a299eaf3173c0f8ac0bd7c4b49c0f4d4590ca
|
||||
F mkopcodeh.awk 1ae5b01fef9105aa04c3b943223b80ad116e7161
|
||||
F mkso.sh 24bde4c09e6fe80f718db3c31c068f45e13a2f2c
|
||||
F publish.sh 1c0658c63d70f182a8f5e17cc28422f1b237f51d
|
||||
F publish_osx.sh eca87df1e3d43d128d97d3261fd48b3d6877996e
|
||||
@@ -168,11 +168,11 @@ F src/update.c eaacf59269bd076adca6fab6f5d16ce53419380b
|
||||
F src/utf.c ef4b7d83bae533b76c3e1bf635b113fdad86a736
|
||||
F src/util.c 05f31144bbd3f1a24f4139ae029c42545cb72624
|
||||
F src/vacuum.c 3f34f278809bf3eb0b62ec46ff779e9c385b28f0
|
||||
F src/vdbe.c c562e01b491b589f6e0f830bec7ab1507d1ac844
|
||||
F src/vdbe.c 8e42b5ce4d69ecf2d17bffd8e520343324785d3e
|
||||
F src/vdbe.h bb128757b84280504a1243c450fd13ead248ede5
|
||||
F src/vdbeInt.h 869d0f550354c1364dde1d3611d770bd1c767505
|
||||
F src/vdbeInt.h 31bd686595356284d5484592e2dc6e58025aa346
|
||||
F src/vdbeapi.c f14174843bf4be2c9afdf2ef48b61e7c3ac62d7c
|
||||
F src/vdbeaux.c eaf5bef96a4564eb0a9b473aa8628b3b5889839d
|
||||
F src/vdbeaux.c 02fef605e37abe4bcec3dbfa42925aac638e5e2b
|
||||
F src/vdbeblob.c b90f7494c408d47ce6835000b01e40b371e27baf
|
||||
F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6
|
||||
F src/vdbemem.c 123994fcd344993d2fb050a83b91b341bbbd08b4
|
||||
@@ -603,7 +603,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
|
||||
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
||||
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
||||
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
|
||||
P 173f281334d340290e1978abea5d1ea804141910
|
||||
R 94a66c73f79f80d8b0a98041731b34af
|
||||
U danielk1977
|
||||
Z fb5d354c01f2e7900c511aa6a77f6954
|
||||
P 2c913908a47e7ace7d964067e3566d232ee2d494
|
||||
R 7c9e5a234b0556d1a08e9283ee39d755
|
||||
U drh
|
||||
Z 240c930bb8f98d16c4e85e184409b234
|
||||
|
||||
@@ -1 +1 @@
|
||||
2c913908a47e7ace7d964067e3566d232ee2d494
|
||||
042dcb9621934d0318a7c6e9cd08b20a569db367
|
||||
@@ -50,6 +50,13 @@
|
||||
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)
|
||||
@@ -58,8 +65,23 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -96,32 +118,46 @@ END {
|
||||
}
|
||||
}
|
||||
|
||||
# Generate the 10 16-bit bitmasks used by function opcodeUsesStack()
|
||||
# in vdbeaux.c. See comments in that function for details.
|
||||
#
|
||||
nopush[0] = 0 # 0..15
|
||||
nopush[1] = 0 # 16..31
|
||||
nopush[2] = 0 # 32..47
|
||||
nopush[3] = 0 # 48..63
|
||||
nopush[4] = 0 # 64..79
|
||||
nopush[5] = 0 # 80..95
|
||||
nopush[6] = 0 # 96..111
|
||||
nopush[7] = 0 # 112..127
|
||||
nopush[8] = 0 # 128..143
|
||||
nopush[9] = 0 # 144..159
|
||||
# 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){
|
||||
if( nopush[name] ){
|
||||
n = op[name]
|
||||
j = n%16
|
||||
i = ((n - j)/16)
|
||||
nopush[i] = nopush[i] + (2^j)
|
||||
}
|
||||
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;
|
||||
}
|
||||
printf "\n"
|
||||
print "/* Opcodes that are guaranteed to never push a value onto the stack"
|
||||
print "** contain a 1 their corresponding position of the following mask"
|
||||
print "** set. See the opcodeNoPush() function in vdbeaux.c */"
|
||||
for(i=0; i<10; i++){
|
||||
printf "#define NOPUSH_MASK_%d 0x%04x\n", i, nopush[i]
|
||||
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 "}"
|
||||
}
|
||||
|
||||
122
src/vdbe.c
122
src/vdbe.c
@@ -43,7 +43,7 @@
|
||||
** 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.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 <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.
|
||||
*/
|
||||
@@ -559,18 +584,11 @@ int sqlite3VdbeExec(
|
||||
#endif
|
||||
|
||||
#ifndef NDEBUG
|
||||
/* This is to check that the return value of static function
|
||||
** opcodeNoPush() (see vdbeaux.c) returns values that match the
|
||||
** 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.
|
||||
/* This is to check to make sure that the OPFLG_PUSH property
|
||||
** is set correctly on all opcodes.
|
||||
*/
|
||||
pStackLimit = pTos;
|
||||
if( !sqlite3VdbeOpcodeNoPush(pOp->opcode) ){
|
||||
if( sqlite3VdbeOpcodeHasProperty(pOp->opcode, OPFLG_PUSH) ){
|
||||
pStackLimit++;
|
||||
}
|
||||
#endif
|
||||
@@ -619,7 +637,7 @@ int sqlite3VdbeExec(
|
||||
** the one at index P2 from the beginning of
|
||||
** the program.
|
||||
*/
|
||||
case OP_Goto: { /* no-push */
|
||||
case OP_Goto: { /* no-push, jump */
|
||||
CHECK_FOR_INTERRUPT;
|
||||
pc = pOp->p2 - 1;
|
||||
break;
|
||||
@@ -635,7 +653,7 @@ case OP_Goto: { /* no-push */
|
||||
** the return address stack will fill up and processing will abort
|
||||
** 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]) );
|
||||
p->returnStack[p->returnDepth++] = pc+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
|
||||
** greater than its current value if P1==1.
|
||||
*/
|
||||
case OP_ForceInt: { /* no-push */
|
||||
case OP_ForceInt: { /* no-push, jump */
|
||||
i64 v;
|
||||
assert( pTos>=p->aStack );
|
||||
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
|
||||
** of the stack is unchanged.
|
||||
*/
|
||||
case OP_MustBeInt: { /* no-push */
|
||||
case OP_MustBeInt: { /* no-push, jump */
|
||||
assert( pTos>=p->aStack );
|
||||
applyAffinity(pTos, SQLITE_AFF_NUMERIC, encoding);
|
||||
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
|
||||
** top of the stack. See the Eq opcode for additional information.
|
||||
*/
|
||||
case OP_Eq: /* same as TK_EQ, no-push */
|
||||
case OP_Ne: /* same as TK_NE, no-push */
|
||||
case OP_Lt: /* same as TK_LT, no-push */
|
||||
case OP_Le: /* same as TK_LE, no-push */
|
||||
case OP_Gt: /* same as TK_GT, no-push */
|
||||
case OP_Ge: { /* same as TK_GE, no-push */
|
||||
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;
|
||||
@@ -1957,8 +1975,8 @@ case OP_Noop: { /* no-push */
|
||||
** 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 */
|
||||
case OP_IfNot: { /* no-push */
|
||||
case OP_If: /* no-push, jump */
|
||||
case OP_IfNot: { /* no-push, jump */
|
||||
int c;
|
||||
assert( pTos>=p->aStack );
|
||||
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
|
||||
** 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 ){
|
||||
pc = pOp->p2-1;
|
||||
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,
|
||||
** 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;
|
||||
cnt = pOp->p1;
|
||||
if( cnt<0 ) cnt = -cnt;
|
||||
@@ -2346,8 +2364,8 @@ op_column_out:
|
||||
*/
|
||||
case OP_RegMakeRec:
|
||||
case OP_RegMakeIRec:
|
||||
case OP_MakeIdxRec:
|
||||
case OP_MakeRecord: {
|
||||
case OP_MakeIdxRec: /* jump */
|
||||
case OP_MakeRecord: { /* jump */
|
||||
/* Assuming the record contains N fields, the record format looks
|
||||
** like this:
|
||||
**
|
||||
@@ -3068,10 +3086,10 @@ case OP_Close: { /* no-push */
|
||||
**
|
||||
** See also: Found, NotFound, Distinct, MoveGt, MoveGe, MoveLt
|
||||
*/
|
||||
case OP_MoveLt: /* no-push */
|
||||
case OP_MoveLe: /* no-push */
|
||||
case OP_MoveGe: /* no-push */
|
||||
case OP_MoveGt: { /* no-push */
|
||||
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;
|
||||
|
||||
@@ -3201,9 +3219,9 @@ case OP_MoveGt: { /* no-push */
|
||||
**
|
||||
** See also: Distinct, Found, MoveTo, NotExists, IsUnique
|
||||
*/
|
||||
case OP_Distinct: /* no-push */
|
||||
case OP_NotFound: /* no-push */
|
||||
case OP_Found: { /* no-push */
|
||||
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;
|
||||
@@ -3260,7 +3278,7 @@ case OP_Found: { /* no-push */
|
||||
**
|
||||
** See also: Distinct, NotFound, NotExists, Found
|
||||
*/
|
||||
case OP_IsUnique: { /* no-push */
|
||||
case OP_IsUnique: { /* no-push, jump */
|
||||
int i = pOp->p1;
|
||||
Mem *pNos = &pTos[-1];
|
||||
Cursor *pCx;
|
||||
@@ -3360,7 +3378,7 @@ case OP_IsUnique: { /* no-push */
|
||||
**
|
||||
** See also: Distinct, Found, MoveTo, NotFound, IsUnique
|
||||
*/
|
||||
case OP_NotExists: { /* no-push */
|
||||
case OP_NotExists: { /* no-push, jump */
|
||||
int i = pOp->p1;
|
||||
Cursor *pC;
|
||||
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
|
||||
** to the following instruction.
|
||||
*/
|
||||
case OP_Last: { /* no-push */
|
||||
case OP_Last: { /* no-push, jump */
|
||||
int i = pOp->p1;
|
||||
Cursor *pC;
|
||||
BtCursor *pCrsr;
|
||||
@@ -3931,7 +3949,7 @@ case OP_Last: { /* no-push */
|
||||
** regression tests can determine whether or not the optimizer is
|
||||
** correctly optimizing out sorts.
|
||||
*/
|
||||
case OP_Sort: { /* no-push */
|
||||
case OP_Sort: { /* no-push, jump */
|
||||
#ifdef SQLITE_TEST
|
||||
sqlite3_sort_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
|
||||
** to the following instruction.
|
||||
*/
|
||||
case OP_Rewind: { /* no-push */
|
||||
case OP_Rewind: { /* no-push, jump */
|
||||
int i = pOp->p1;
|
||||
Cursor *pC;
|
||||
BtCursor *pCrsr;
|
||||
@@ -3986,8 +4004,8 @@ case OP_Rewind: { /* no-push */
|
||||
** to the following instruction. But if the cursor backup was successful,
|
||||
** jump immediately to P2.
|
||||
*/
|
||||
case OP_Prev: /* no-push */
|
||||
case OP_Next: { /* no-push */
|
||||
case OP_Prev: /* no-push, jump */
|
||||
case OP_Next: { /* no-push, jump */
|
||||
Cursor *pC;
|
||||
BtCursor *pCrsr;
|
||||
|
||||
@@ -4172,9 +4190,9 @@ case OP_IdxRowid: {
|
||||
** an epsilon prior to the comparison. This makes the opcode work
|
||||
** like IdxLE.
|
||||
*/
|
||||
case OP_IdxLT: /* no-push */
|
||||
case OP_IdxGT: /* no-push */
|
||||
case OP_IdxGE: { /* no-push */
|
||||
case OP_IdxLT: /* no-push, jump */
|
||||
case OP_IdxGT: /* no-push, jump */
|
||||
case OP_IdxGE: { /* no-push, jump */
|
||||
int i= pOp->p1;
|
||||
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
|
||||
** a memory register but instead jump to P2.
|
||||
*/
|
||||
case OP_FifoRead: {
|
||||
case OP_FifoRead: { /* jump */
|
||||
i64 v;
|
||||
CHECK_FOR_INTERRUPT;
|
||||
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
|
||||
** 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;
|
||||
Mem *pMem;
|
||||
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
|
||||
** 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;
|
||||
Mem *pMem;
|
||||
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
|
||||
** 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;
|
||||
Mem *pMem;
|
||||
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.
|
||||
*/
|
||||
case OP_IfMemNull: { /* no-push */
|
||||
case OP_IfMemNull: { /* no-push, jump */
|
||||
int i = pOp->p1;
|
||||
assert( i>0 && i<=p->nMem );
|
||||
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
|
||||
** P2. Otherwise, fall through to the next instruction.
|
||||
*/
|
||||
case OP_IncrVacuum: { /* no-push */
|
||||
case OP_IncrVacuum: { /* no-push, jump */
|
||||
Btree *pBt;
|
||||
|
||||
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.
|
||||
*/
|
||||
case OP_VFilter: { /* no-push */
|
||||
case OP_VFilter: { /* no-push, jump */
|
||||
int nArg;
|
||||
int iQuery;
|
||||
const sqlite3_module *pModule;
|
||||
@@ -5202,7 +5220,7 @@ case OP_VColumn: {
|
||||
** 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 */
|
||||
case OP_VNext: { /* no-push, jump */
|
||||
const sqlite3_module *pModule;
|
||||
int res = 0;
|
||||
|
||||
|
||||
@@ -400,10 +400,10 @@ 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*);
|
||||
int sqlite3VdbeOpcodeNoPush(u8);
|
||||
#endif
|
||||
int sqlite3VdbeMemTranslate(Mem*, u8);
|
||||
#ifdef SQLITE_DEBUG
|
||||
|
||||
@@ -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.
|
||||
** 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;
|
||||
#endif
|
||||
}
|
||||
if( opcodeNoPush(opcode) ){
|
||||
if( !sqlite3VdbeOpcodeHasProperty(opcode, OPFLG_PUSH) ){
|
||||
nMaxStack--;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user