Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Remove the OP_HexBlob instruction and code OP_Blob directly. Reduce the amount of memory allocation required to encode blob literals. Remove the "out2" instruction type. Other minor optimizations. (CVS 4726) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
0e50c0200a3c1c04e63cbb55a7255cdb |
User & Date: | drh 2008-01-18 14:08:24.000 |
Context
2008-01-18
| ||
14:17 | Remove an absolute path from crash5.test. (CVS 4727) (check-in: 42d8a37755 user: danielk1977 tags: trunk) | |
14:08 | Remove the OP_HexBlob instruction and code OP_Blob directly. Reduce the amount of memory allocation required to encode blob literals. Remove the "out2" instruction type. Other minor optimizations. (CVS 4726) (check-in: 0e50c0200a user: drh tags: trunk) | |
13:42 | Add a test (and fix) for possible corruption if malloc() fails during a CREATE INDEX statement, the application continues with the transaction, then crashes. (CVS 4725) (check-in: 65245d9904 user: danielk1977 tags: trunk) | |
Changes
Changes to mkopcodeh.awk.
︙ | ︙ | |||
51 52 53 54 55 56 57 | sub("\r","",name) op[name] = -1 jump[name] = 0 out2_prerelease[name] = 0 in1[name] = 0 in2[name] = 0 in3[name] = 0 | < | 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | sub("\r","",name) op[name] = -1 jump[name] = 0 out2_prerelease[name] = 0 in1[name] = 0 in2[name] = 0 in3[name] = 0 out3[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 |
︙ | ︙ | |||
73 74 75 76 77 78 79 | out2_prerelease[name] = 1 }else if(x=="in1"){ in1[name] = 1 }else if(x=="in2"){ in2[name] = 1 }else if(x=="in3"){ in3[name] = 1 | < < | 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | out2_prerelease[name] = 1 }else if(x=="in1"){ in1[name] = 1 }else if(x=="in2"){ in2[name] = 1 }else if(x=="in3"){ in3[name] = 1 }else if(x=="out3"){ out3[name] = 1 } } } # Assign numbers to all opcodes and output the result. |
︙ | ︙ | |||
129 130 131 132 133 134 135 | a0 = a1 = a2 = a3 = a4 = a5 = a6 = a7 = 0 # a8 = a9 = a10 = a11 = a12 = a13 = a14 = a15 = 0 if( jump[name] ) a0 = 1; if( out2_prerelease[name] ) a1 = 2; if( in1[name] ) a2 = 4; if( in2[name] ) a3 = 8; if( in3[name] ) a4 = 16; | < | | < | | 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 | a0 = a1 = a2 = a3 = a4 = a5 = a6 = a7 = 0 # a8 = a9 = a10 = a11 = a12 = a13 = a14 = a15 = 0 if( jump[name] ) a0 = 1; if( out2_prerelease[name] ) a1 = 2; if( in1[name] ) a2 = 4; if( in2[name] ) a3 = 8; if( in3[name] ) a4 = 16; if( out3[name] ) a5 = 32; # bv[x] = a0+a1+a2+a3+a4+a5+a6+a7+a8+a9+a10+a11+a12+a13+a14+a15; bv[x] = a0+a1+a2+a3+a4+a5+a6+a7; } 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 0x0001 /* jump: P2 holds jmp target */" print "#define OPFLG_OUT2_PRERELEASE 0x0002 /* out2-prerelease: */" print "#define OPFLG_IN1 0x0004 /* in1: P1 is an input */" print "#define OPFLG_IN2 0x0008 /* in2: P2 is an input */" print "#define OPFLG_IN3 0x0010 /* in3: P3 is an input */" print "#define OPFLG_OUT3 0x0020 /* out3: P3 is an output */" print "#define OPFLG_INITIALIZER {\\" for(i=0; i<=max; i++){ if( i%8==0 ) printf("/* %3d */",i) printf " 0x%02x,", bv[i] if( i%8==7 ) printf("\\\n"); } print "}" } |
Changes to src/expr.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** ** $Id: expr.c,v 1.350 2008/01/18 14:08:24 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** Return the 'affinity' of the expression pExpr if any. ** |
︙ | ︙ | |||
2000 2001 2002 2003 2004 2005 2006 | sqlite3VdbeAddOp2(v, OP_Null, 0, target); break; } #ifndef SQLITE_OMIT_BLOB_LITERAL case TK_BLOB: { int n; const char *z; | > | > > > < < | < | | 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 | sqlite3VdbeAddOp2(v, OP_Null, 0, target); break; } #ifndef SQLITE_OMIT_BLOB_LITERAL case TK_BLOB: { int n; const char *z; char *zBlob; assert( pExpr->token.n>=3 ); assert( pExpr->token.z[0]=='x' || pExpr->token.z[0]=='X' ); assert( pExpr->token.z[1]=='\'' ); assert( pExpr->token.z[pExpr->token.n-1]=='\'' ); n = pExpr->token.n - 3; z = (char*)pExpr->token.z + 2; zBlob = sqlite3HexToBlob(sqlite3VdbeDb(v), z, n); sqlite3VdbeAddOp4(v, OP_Blob, n/2, target, 0, zBlob, P4_DYNAMIC); break; } #endif case TK_VARIABLE: { sqlite3VdbeAddOp2(v, OP_Variable, pExpr->iTable, target); if( pExpr->token.n>1 ){ sqlite3VdbeChangeP4(v, -1, (char*)pExpr->token.z, pExpr->token.n); |
︙ | ︙ |
Changes to src/sqliteInt.h.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.652 2008/01/18 14:08:24 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ /* ** The macro unlikely() is a hint that surrounds a boolean ** expression that is usually false. Macro likely() surrounds |
︙ | ︙ | |||
1885 1886 1887 1888 1889 1890 1891 | void sqlite3IndexAffinityStr(Vdbe *, Index *); void sqlite3TableAffinityStr(Vdbe *, Table *); char sqlite3CompareAffinity(Expr *pExpr, char aff2); int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity); char sqlite3ExprAffinity(Expr *pExpr); int sqlite3Atoi64(const char*, i64*); void sqlite3Error(sqlite3*, int, const char*,...); | | | 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 | void sqlite3IndexAffinityStr(Vdbe *, Index *); void sqlite3TableAffinityStr(Vdbe *, Table *); char sqlite3CompareAffinity(Expr *pExpr, char aff2); int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity); char sqlite3ExprAffinity(Expr *pExpr); int sqlite3Atoi64(const char*, i64*); void sqlite3Error(sqlite3*, int, const char*,...); void *sqlite3HexToBlob(sqlite3*, const char *z, int n); int sqlite3TwoPartName(Parse *, Token *, Token *, Token **); const char *sqlite3ErrStr(int); int sqlite3ReadSchema(Parse *pParse); CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char *,int,int); CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName, int nName); CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr); Expr *sqlite3ExprSetColl(Parse *pParse, Expr *, Token *); |
︙ | ︙ |
Changes to src/util.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** ** $Id: util.c,v 1.214 2008/01/18 14:08:25 drh Exp $ */ #include "sqliteInt.h" #include <stdarg.h> #include <ctype.h> /* |
︙ | ︙ | |||
633 634 635 636 637 638 639 | #if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC) /* ** Convert a BLOB literal of the form "x'hhhhhh'" into its binary ** value. Return a pointer to its binary value. Space to hold the ** binary value has been obtained from malloc and must be freed by ** the calling routine. */ | | < < | > > | 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 | #if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC) /* ** Convert a BLOB literal of the form "x'hhhhhh'" into its binary ** value. Return a pointer to its binary value. Space to hold the ** binary value has been obtained from malloc and must be freed by ** the calling routine. */ void *sqlite3HexToBlob(sqlite3 *db, const char *z, int n){ char *zBlob; int i; zBlob = (char *)sqlite3DbMallocRaw(db, n/2 + 1); n--; if( zBlob ){ for(i=0; i<n; i+=2){ zBlob[i/2] = (hexToInt(z[i])<<4) | hexToInt(z[i+1]); } zBlob[i/2] = 0; } return zBlob; } #endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */ /* |
︙ | ︙ |
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.699 2008/01/18 14:08:25 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> #include "vdbeInt.h" /* ** The following global variable is incremented every time a cursor |
︙ | ︙ | |||
88 89 90 91 92 93 94 95 96 97 98 99 100 101 | ** or MEM_Str that has been used by a VDBE opcode. The test procedures ** use this information to make sure that the zero-blob functionality ** is working correctly. This variable has no function other than to ** help verify the correct operation of the library. */ #ifdef SQLITE_TEST int sqlite3_max_blobsize = 0; #endif /* ** Test a register to see if it exceeds the current maximum blob size. ** If it does, record the new maximum blob size. */ #ifdef SQLITE_TEST | > > > > > | < < | 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | ** or MEM_Str that has been used by a VDBE opcode. The test procedures ** use this information to make sure that the zero-blob functionality ** is working correctly. This variable has no function other than to ** help verify the correct operation of the library. */ #ifdef SQLITE_TEST int sqlite3_max_blobsize = 0; static void updateMaxBlobsize(Mem *p){ if( (p->flags & (MEM_Str|MEM_Blob))!=0 && p->n>sqlite3_max_blobsize ){ sqlite3_max_blobsize = p->n; } } #endif /* ** Test a register to see if it exceeds the current maximum blob size. ** If it does, record the new maximum blob size. */ #ifdef SQLITE_TEST # define UPDATE_MAX_BLOBSIZE(P) updateMaxBlobsize(P) #else # define UPDATE_MAX_BLOBSIZE(P) #endif /* ** Release the memory associated with a register. This ** leaves the Mem.flags field in an inconsistent state. |
︙ | ︙ | |||
505 506 507 508 509 510 511 | unsigned long long start; /* CPU clock count at start of opcode */ int origPc; /* Program counter at start of opcode */ #endif #ifndef SQLITE_OMIT_PROGRESS_CALLBACK int nProgressOps = 0; /* Opcodes executed since progress callback. */ #endif | | | 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 | unsigned long long start; /* CPU clock count at start of opcode */ int origPc; /* Program counter at start of opcode */ #endif #ifndef SQLITE_OMIT_PROGRESS_CALLBACK int nProgressOps = 0; /* Opcodes executed since progress callback. */ #endif assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */ assert( db->magic==SQLITE_MAGIC_BUSY ); sqlite3BtreeMutexArrayEnter(&p->aMutex); if( p->rc==SQLITE_NOMEM ){ /* This happens if a malloc() inside a call to sqlite3_column_text() or ** sqlite3_column_text16() failed. */ goto no_mem; } |
︙ | ︙ | |||
617 618 619 620 621 622 623 | /* Do common setup for opcodes marked with one of the following ** combinations of properties. ** ** in1 ** in1 in2 ** in1 in2 out3 ** in1 in3 | < | 620 621 622 623 624 625 626 627 628 629 630 631 632 633 | /* Do common setup for opcodes marked with one of the following ** combinations of properties. ** ** in1 ** in1 in2 ** in1 in2 out3 ** in1 in3 ** ** Variables pIn1, pIn2, and pIn3 are made to point to appropriate ** registers for inputs. Variable pOut points to the output register. */ if( (opProperty & OPFLG_IN1)!=0 ){ assert( pOp->p1>0 ); assert( pOp->p1<=p->nMem ); |
︙ | ︙ | |||
642 643 644 645 646 647 648 | pOut = &p->aMem[pOp->p3]; } }else if( (opProperty & OPFLG_IN3)!=0 ){ assert( pOp->p3>0 ); assert( pOp->p3<=p->nMem ); pIn3 = &p->aMem[pOp->p3]; REGISTER_TRACE(pOp->p3, pIn3); | < < < < | 644 645 646 647 648 649 650 651 652 653 654 655 656 657 | pOut = &p->aMem[pOp->p3]; } }else if( (opProperty & OPFLG_IN3)!=0 ){ assert( pOp->p3>0 ); assert( pOp->p3<=p->nMem ); pIn3 = &p->aMem[pOp->p3]; REGISTER_TRACE(pOp->p3, pIn3); } }else if( (opProperty & OPFLG_IN2)!=0 ){ assert( pOp->p2>0 ); assert( pOp->p2<=p->nMem ); pIn2 = &p->aMem[pOp->p2]; REGISTER_TRACE(pOp->p2, pIn2); }else if( (opProperty & OPFLG_IN3)!=0 ){ |
︙ | ︙ | |||
868 869 870 871 872 873 874 | */ case OP_Null: { /* out2-prerelease */ break; } #ifndef SQLITE_OMIT_BLOB_LITERAL | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 866 867 868 869 870 871 872 873 874 875 876 877 878 879 | */ case OP_Null: { /* out2-prerelease */ break; } #ifndef SQLITE_OMIT_BLOB_LITERAL /* Opcode: Blob P1 P2 * P4 ** ** P4 points to a blob of data P1 bytes long. Store this ** blob in register P2. This instruction is not coded directly ** by the compiler. Instead, the compiler layer specifies ** an OP_HexBlob opcode, with the hex string representation of ** the blob as P4. This opcode is transformed to an OP_Blob |
︙ | ︙ | |||
4810 4811 4812 4813 4814 4815 4816 | */ #ifndef NDEBUG assert( pc>=-1 && pc<p->nOp ); #ifdef SQLITE_DEBUG if( p->trace ){ if( rc!=0 ) fprintf(p->trace,"rc=%d\n",rc); | | | | 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 | */ #ifndef NDEBUG assert( pc>=-1 && pc<p->nOp ); #ifdef SQLITE_DEBUG if( p->trace ){ if( rc!=0 ) fprintf(p->trace,"rc=%d\n",rc); if( opProperty & OPFLG_OUT2_PRERELEASE ){ registerTrace(p->trace, pOp->p2, pOut); } if( opProperty & OPFLG_OUT3 ){ registerTrace(p->trace, pOp->p3, pOut); } } #endif /* SQLITE_DEBUG */ #endif /* NDEBUG */ } /* The end of the for(;;) loop the loops through opcodes */ |
︙ | ︙ |
Changes to src/vdbemem.c.
︙ | ︙ | |||
985 986 987 988 989 990 991 992 | pVal->u.i = -1 * pVal->u.i; pVal->r = -1.0 * pVal->r; } } #ifndef SQLITE_OMIT_BLOB_LITERAL else if( op==TK_BLOB ){ int nVal; pVal = sqlite3ValueNew(db); | > > > > | < < | | | | 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 | pVal->u.i = -1 * pVal->u.i; pVal->r = -1.0 * pVal->r; } } #ifndef SQLITE_OMIT_BLOB_LITERAL else if( op==TK_BLOB ){ int nVal; assert( pExpr->token.n>=3 ); assert( pExpr->token.z[0]=='x' || pExpr->token.z[0]=='X' ); assert( pExpr->token.z[1]=='\'' ); assert( pExpr->token.z[pExpr->token.n-1]=='\'' ); pVal = sqlite3ValueNew(db); nVal = pExpr->token.n - 3; zVal = (char*)pExpr->token.z + 2; sqlite3VdbeMemSetStr(pVal, sqlite3HexToBlob(db, zVal, nVal), nVal/2, 0, sqlite3_free); } #endif *ppVal = pVal; return SQLITE_OK; no_mem: |
︙ | ︙ |