[email protected] | 997e2222 | 2009-09-18 18:27:25 | [diff] [blame] | 1 | #!/usr/bin/tcl |
| 2 | # |
| 3 | # This script makes modifications to the vdbe.c source file which reduce |
| 4 | # the amount of stack space required by the sqlite3VdbeExec() routine. |
| 5 | # |
| 6 | # The modifications performed by this script are optional. The vdbe.c |
| 7 | # source file will compile correctly with and without the modifications |
| 8 | # performed by this script. And all routines within vdbe.c will compute |
| 9 | # the same result. The modifications made by this script merely help |
| 10 | # the C compiler to generate code for sqlite3VdbeExec() that uses less |
| 11 | # stack space. |
| 12 | # |
| 13 | # Script usage: |
| 14 | # |
| 15 | # mv vdbe.c vdbe.c.template |
| 16 | # tclsh vdbe-compress.tcl <vdbe.c.template >vdbe.c |
| 17 | # |
| 18 | # Modifications made: |
| 19 | # |
| 20 | # All modifications are within the sqlite3VdbeExec() function. The |
| 21 | # modifications seek to reduce the amount of stack space allocated by |
| 22 | # this routine by moving local variable declarations out of individual |
| 23 | # opcode implementations and into a single large union. The union contains |
| 24 | # a separate structure for each opcode and that structure contains the |
| 25 | # local variables used by that opcode. In this way, the total amount |
| 26 | # of stack space required by sqlite3VdbeExec() is reduced from the |
| 27 | # sum of all local variables to the maximum of the local variable space |
| 28 | # required for any single opcode. |
| 29 | # |
| 30 | # In order to be recognized by this script, local variables must appear |
| 31 | # on the first line after the open curly-brace that begins a new opcode |
| 32 | # implementation. Local variables must not have initializers, though they |
| 33 | # may be commented. |
| 34 | # |
| 35 | # The union definition is inserted in place of a special marker comment |
| 36 | # in the preamble to the sqlite3VdbeExec() implementation. |
| 37 | # |
| 38 | ############################################################################# |
| 39 | # |
| 40 | set beforeUnion {} ;# C code before union |
| 41 | set unionDef {} ;# C code of the union |
| 42 | set afterUnion {} ;# C code after the union |
| 43 | set sCtr 0 ;# Context counter |
| 44 | |
| 45 | # Read program text up to the spot where the union should be |
| 46 | # inserted. |
| 47 | # |
| 48 | while {![eof stdin]} { |
| 49 | set line [gets stdin] |
| 50 | if {[regexp {INSERT STACK UNION HERE} $line]} break |
| 51 | append beforeUnion $line\n |
| 52 | } |
| 53 | |
| 54 | # Process the remaining text. Build up the union definition as we go. |
| 55 | # |
| 56 | set vlist {} |
| 57 | set seenDecl 0 |
| 58 | set namechars {abcdefghijklmnopqrstuvwxyz} |
| 59 | set nnc [string length $namechars] |
| 60 | while {![eof stdin]} { |
| 61 | set line [gets stdin] |
| 62 | if {[regexp "^case (OP_\\w+): \173" $line all operator]} { |
| 63 | append afterUnion $line\n |
| 64 | set vlist {} |
| 65 | while {![eof stdin]} { |
| 66 | set line [gets stdin] |
| 67 | if {[regexp {^ +(const )?\w+ \**(\w+)(\[.*\])?;} $line \ |
| 68 | all constKeyword vname notused1]} { |
| 69 | if {!$seenDecl} { |
| 70 | set sname {} |
| 71 | append sname [string index $namechars [expr {$sCtr/$nnc}]] |
| 72 | append sname [string index $namechars [expr {$sCtr%$nnc}]] |
| 73 | incr sCtr |
| 74 | append unionDef " struct ${operator}_stack_vars \173\n" |
| 75 | append afterUnion \ |
| 76 | "#if 0 /* local variables moved into u.$sname */\n" |
| 77 | set seenDecl 1 |
| 78 | } |
| 79 | append unionDef " $line\n" |
| 80 | append afterUnion $line\n |
| 81 | lappend vlist $vname |
| 82 | } else { |
| 83 | break |
| 84 | } |
| 85 | } |
| 86 | if {$seenDecl} { |
| 87 | append unionDef " \175 $sname;\n" |
| 88 | append afterUnion "#endif /* local variables moved into u.$sname */\n" |
| 89 | } |
| 90 | set seenDecl 0 |
| 91 | } |
| 92 | if {[regexp "^\175" $line]} { |
| 93 | append afterUnion $line\n |
| 94 | set vlist {} |
| 95 | } elseif {[llength $vlist]>0} { |
| 96 | append line " " |
| 97 | foreach v $vlist { |
| 98 | regsub -all "(\[^a-zA-Z0-9>.\])${v}(\\W)" $line "\\1u.$sname.$v\\2" line |
| 99 | regsub -all "(\[^a-zA-Z0-9>.\])${v}(\\W)" $line "\\1u.$sname.$v\\2" line |
| 100 | } |
| 101 | append afterUnion [string trimright $line]\n |
| 102 | } elseif {$line=="" && [eof stdin]} { |
| 103 | # no-op |
| 104 | } else { |
| 105 | append afterUnion $line\n |
| 106 | } |
| 107 | } |
| 108 | |
| 109 | # Output the resulting text. |
| 110 | # |
| 111 | puts -nonewline $beforeUnion |
| 112 | puts " /********************************************************************" |
| 113 | puts " ** Automatically generated code" |
| 114 | puts " **" |
| 115 | puts " ** The following union is automatically generated by the" |
| 116 | puts " ** vdbe-compress.tcl script. The purpose of this union is to" |
| 117 | puts " ** reduce the amount of stack space required by this function." |
| 118 | puts " ** See comments in the vdbe-compress.tcl script for details." |
| 119 | puts " */" |
| 120 | puts " union vdbeExecUnion \173" |
| 121 | puts -nonewline $unionDef |
| 122 | puts " \175 u;" |
| 123 | puts " /* End automatically generated code" |
| 124 | puts " ********************************************************************/" |
| 125 | puts -nonewline $afterUnion |