/ Check-in [6ee2950b]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Keep generated opcode values grouped together when required, even when they do not correspond to a token.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 6ee2950b272ede475e485bfaa7d413eaa81482fe9dd6452aeeaf95ff7938f7da
User & Date: mistachkin 2018-07-25 15:12:29
Context
2018-07-25
15:25
Fix a buffer overread in fts5. check-in: 0e3de8ab user: dan tags: trunk
15:12
Keep generated opcode values grouped together when required, even when they do not correspond to a token. check-in: 6ee2950b user: mistachkin tags: trunk
07:29
Fix a typo in the documentation for sqlite3_snapshot_get(). check-in: cd9713c9 user: dan tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/vdbe.c.

  3888   3888   ** else jump immediately to P2.  When the cursor is OPFLAG_SEEKEQ, this
  3889   3889   ** opcode must be followed by an IdxGE opcode with the same arguments.
  3890   3890   ** The IdxGE opcode will be skipped if this opcode succeeds, but the
  3891   3891   ** IdxGE opcode will be used on subsequent loop iterations.
  3892   3892   **
  3893   3893   ** See also: Found, NotFound, SeekGt, SeekGe, SeekLt
  3894   3894   */
  3895         -case OP_SeekLT:         /* jump, in3 */
  3896         -case OP_SeekLE:         /* jump, in3 */
  3897         -case OP_SeekGE:         /* jump, in3 */
  3898         -case OP_SeekGT: {       /* jump, in3 */
         3895  +case OP_SeekLT:         /* jump, in3, group */
         3896  +case OP_SeekLE:         /* jump, in3, group */
         3897  +case OP_SeekGE:         /* jump, in3, group */
         3898  +case OP_SeekGT: {       /* jump, in3, group */
  3899   3899     int res;           /* Comparison result */
  3900   3900     int oc;            /* Opcode */
  3901   3901     VdbeCursor *pC;    /* The cursor to seek */
  3902   3902     UnpackedRecord r;  /* The key to seek for */
  3903   3903     int nField;        /* Number of columns or fields in the key */
  3904   3904     i64 iKey;          /* The rowid we are to seek to */
  3905   3905     int eqOnly;        /* Only interested in == results */
................................................................................
  7215   7215   ** automatically converted into an sqlite3_context object and the operation
  7216   7216   ** changed to this OP_Function opcode.  In this way, the initialization of
  7217   7217   ** the sqlite3_context object occurs only once, rather than once for each
  7218   7218   ** evaluation of the function.
  7219   7219   **
  7220   7220   ** See also: Function0, AggStep, AggFinal
  7221   7221   */
  7222         -case OP_PureFunc0:
  7223         -case OP_Function0: {
         7222  +case OP_PureFunc0:              /* group */
         7223  +case OP_Function0: {            /* group */
  7224   7224     int n;
  7225   7225     sqlite3_context *pCtx;
  7226   7226   
  7227   7227     assert( pOp->p4type==P4_FUNCDEF );
  7228   7228     n = pOp->p5;
  7229   7229     assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
  7230   7230     assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem+1 - p->nCursor)+1) );
................................................................................
  7240   7240     pOp->p4type = P4_FUNCCTX;
  7241   7241     pOp->p4.pCtx = pCtx;
  7242   7242     assert( OP_PureFunc == OP_PureFunc0+2 );
  7243   7243     assert( OP_Function == OP_Function0+2 );
  7244   7244     pOp->opcode += 2;
  7245   7245     /* Fall through into OP_Function */
  7246   7246   }
  7247         -case OP_PureFunc:
  7248         -case OP_Function: {
         7247  +case OP_PureFunc:              /* group */
         7248  +case OP_Function: {            /* group */
  7249   7249     int i;
  7250   7250     sqlite3_context *pCtx;
  7251   7251   
  7252   7252     assert( pOp->p4type==P4_FUNCCTX );
  7253   7253     pCtx = pOp->p4.pCtx;
  7254   7254   
  7255   7255     /* If this function is inside of a trigger, the register array in aMem[]

Changes to tool/mkopcodeh.tcl.

    20     20   # during code generation, we need to generate corresponding opcodes like
    21     21   # OP_Add and OP_Divide.  By making TK_ADD==OP_Add and TK_DIVIDE==OP_Divide,
    22     22   # code to translate from one to the other is avoided.  This makes the
    23     23   # code generator smaller and faster.
    24     24   #
    25     25   # This script also scans for lines of the form:
    26     26   #
    27         -#       case OP_aaaa:       /* jump, in1, in2, in3, out2-prerelease, out3 */
           27  +#       case OP_aaaa:       /* jump, in1, in2, in3, out2, out3 */
    28     28   #
    29     29   # When such comments are found on an opcode, it means that certain
    30     30   # properties apply to that opcode.  Set corresponding flags using the
    31     31   # OPFLG_INITIALIZER macro.
    32     32   #
    33     33   
    34     34   set in stdin
    35     35   set currentOp {}
           36  +set prevName {}
    36     37   set nOp 0
           38  +set nGroup 0
    37     39   while {![eof $in]} {
    38     40     set line [gets $in]
    39     41   
    40     42     # Remember the TK_ values from the parse.h file. 
    41     43     # NB:  The "TK_" prefix stands for "ToKen", not the graphical Tk toolkit
    42     44     # commonly associated with TCL.
    43     45     #
................................................................................
    73     75     # Scan for "case OP_aaaa:" lines in the vdbe.c file
    74     76     #
    75     77     if {[regexp {^case OP_} $line]} {
    76     78       set line [split $line]
    77     79       set name [string trim [lindex $line 1] :]
    78     80       if {$name=="OP_Abortable"} continue;  # put OP_Abortable last 
    79     81       set op($name) -1
           82  +    set group($name) 0
    80     83       set jump($name) 0
    81     84       set in1($name) 0
    82     85       set in2($name) 0
    83     86       set in3($name) 0
    84     87       set out2($name) 0
    85     88       set out3($name) 0
    86     89       for {set i 3} {$i<[llength $line]-1} {incr i} {
................................................................................
    93     96                set val $tk($sym)
    94     97                set op($name) $val
    95     98                set used($val) 1
    96     99                set sameas($val) $sym
    97    100                set def($val) $name
    98    101              }
    99    102            }
   100         -         jump {set jump($name) 1}
   101         -         in1  {set in1($name) 1}
   102         -         in2  {set in2($name) 1}
   103         -         in3  {set in3($name) 1}
   104         -         out2 {set out2($name) 1}
   105         -         out3 {set out3($name) 1}
          103  +         group {set group($name) 1}
          104  +         jump  {set jump($name) 1}
          105  +         in1   {set in1($name) 1}
          106  +         in2   {set in2($name) 1}
          107  +         in3   {set in3($name) 1}
          108  +         out2  {set out2($name) 1}
          109  +         out3  {set out3($name) 1}
   106    110          }
          111  +    }
          112  +    if {$group($name)} {
          113  +      set newGroup 0
          114  +      if {[info exists groups($nGroup)]} {
          115  +        if {$prevName=="" || !$group($prevName)} {
          116  +          set newGroup 1
          117  +        }
          118  +      }
          119  +      lappend groups($nGroup) $name
          120  +      if {$newGroup} {incr nGroup}
          121  +    } else {
          122  +      if {$prevName!="" && $group($prevName)} {
          123  +        incr nGroup
          124  +      }
   107    125       }
   108    126       set order($nOp) $name
          127  +    set prevName $name
   109    128       incr nOp
   110    129     }
   111    130   }
   112    131   
   113    132   # Assign numbers to all opcodes and output the result.
   114    133   #
   115    134   puts "/* Automatically generated.  Do not edit */"
................................................................................
   177    196   set mxJump -1
   178    197   for {set i 0} {$i<$nOp} {incr i} {
   179    198     set name $order($i)
   180    199     if {$jump($name) && $op($name)>$mxJump} {set mxJump $op($name)}
   181    200   }
   182    201   
   183    202   
   184         -# Generate the numeric values for all remaining opcodes
          203  +# Generate the numeric values for all remaining opcodes, while
          204  +# preserving any groupings of opcodes (i.e. those that must be
          205  +# together).
   185    206   #
          207  +for {set g 0} {$g<$nGroup} {incr g} {
          208  +  set gLen [llength $groups($g)]
          209  +  set ok 0; set start -1
          210  +  while {!$ok} {
          211  +    set seek $cnt; incr seek
          212  +    while {[info exists used($seek)]} {incr seek}
          213  +    set ok 1; set start $seek
          214  +    for {set j 0} {$j<$gLen} {incr j} {
          215  +      incr seek
          216  +      if {[info exists used($seek)]} {
          217  +        set ok 0; break
          218  +      }
          219  +    }
          220  +  }
          221  +  if {$ok} {
          222  +    set next $start
          223  +    for {set j 0} {$j<$gLen} {incr j} {
          224  +      set name [lindex $groups($g) $j]
          225  +      if {$op($name)>=0} continue
          226  +      set op($name) $next
          227  +      set used($next) 1
          228  +      set def($next) $name
          229  +      incr next
          230  +    }
          231  +  } else {
          232  +    error "cannot find opcodes for group: $groups($g)"
          233  +  }
          234  +}
          235  +
   186    236   for {set i 0} {$i<$nOp} {incr i} {
   187    237     set name $order($i)
   188    238     if {$op($name)<0} {
   189    239       incr cnt
   190    240       while {[info exists used($cnt)]} {incr cnt}
   191    241       set op($name) $cnt
   192    242       set used($cnt) 1
................................................................................
   199    249     if {![info exists used($i)]} {
   200    250       set def($i) "OP_NotUsed_$i"
   201    251     }
   202    252     if {$i>$max} {set max $i}
   203    253     set name $def($i)
   204    254     puts -nonewline [format {#define %-16s %3d} $name $i]
   205    255     set com {}
   206         -  if {$jump($name)} {
          256  +  if {[info exists jump($name)] && $jump($name)} {
   207    257       lappend com "jump"
   208    258     }
   209    259     if {[info exists sameas($i)]} {
   210    260       lappend com "same as $sameas($i)"
   211    261     }
   212    262     if {[info exists synopsis($name)]} {
   213    263       lappend com "synopsis: $synopsis($name)"