From: drh Date: Fri, 4 Jan 2008 16:50:09 +0000 (+0000) Subject: Replace the NOPUSH_MASKs with a bit-vector mechanism that can contain X-Git-Tag: version-3.6.10~1500 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3a40f696d4ba25bf22328acfe7aa08b36553b10a;p=thirdparty%2Fsqlite.git Replace the NOPUSH_MASKs with a bit-vector mechanism that can contain several different properties about each opcode. (CVS 4677) FossilOrigin-Name: 042dcb9621934d0318a7c6e9cd08b20a569db367 --- diff --git a/manifest b/manifest index ebf39717b1..214d3862d7 100644 --- a/manifest +++ b/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 diff --git a/manifest.uuid b/manifest.uuid index af77656b1b..c4afdf30f5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2c913908a47e7ace7d964067e3566d232ee2d494 \ No newline at end of file +042dcb9621934d0318a7c6e9cd08b20a569db367 \ No newline at end of file diff --git a/mkopcodeh.awk b/mkopcodeh.awk index 53dab1eda4..97c291de77 100644 --- a/mkopcodeh.awk +++ b/mkopcodeh.awk @@ -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 @@ -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 && opcodeopcode) ){ + 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->returnDepthreturnStack)/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->p1nDb ); @@ -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; diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 988c85b4dd..36c71e728e 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -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 diff --git a/src/vdbeaux.c b/src/vdbeaux.c index bbd98382d8..120e440dd7 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -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--; }