#!/usr/bin/tcl # # This script makes modifications to the vdbe.c source file which reduce # the amount of stack space required by the sqlite3VdbeExec() routine. # # The modifications performed by this script are optional. The vdbe.c # source file will compile correctly with and without the modifications # performed by this script. And all routines within vdbe.c will compute # the same result. The modifications made by this script merely help # the C compiler to generate code for sqlite3VdbeExec() that uses less # stack space. # # Script usage: # # mv vdbe.c vdbe.c.template # tclsh vdbe-compress.tcl vdbe.c # # Modifications made: # # All modifications are within the sqlite3VdbeExec() function. The # modifications seek to reduce the amount of stack space allocated by # this routine by moving local variable declarations out of individual # opcode implementations and into a single large union. The union contains # a separate structure for each opcode and that structure contains the # local variables used by that opcode. In this way, the total amount # of stack space required by sqlite3VdbeExec() is reduced from the # sum of all local variables to the maximum of the local variable space # required for any single opcode. # # In order to be recognized by this script, local variables must appear # on the first line after the open curly-brace that begins a new opcode # implementation. Local variables must not have initializers, though they # may be commented. # # The union definition is inserted in place of a special marker comment # in the preamble to the sqlite3VdbeExec() implementation. # ############################################################################# # set beforeUnion {} ;# C code before union set unionDef {} ;# C code of the union set afterUnion {} ;# C code after the union set sCtr 0 ;# Context counter # Read program text up to the spot where the union should be # inserted. # while {![eof stdin]} { set line [gets stdin] if {[regexp {INSERT STACK UNION HERE} $line]} break append beforeUnion $line\n } # Process the remaining text. Build up the union definition as we go. # set vlist {} set seenDecl 0 set namechars {abcdefghijklmnopqrstuvwxyz} set nnc [string length $namechars] while {![eof stdin]} { set line [gets stdin] if {[regexp "^case (OP_\\w+): \173" $line all operator]} { append afterUnion $line\n set vlist {} while {![eof stdin]} { set line [gets stdin] if {[regexp {^ +(const )?\w+ \*?(\w+)(\[.*\])?;} $line \ all constKeyword vname notused1]} { if {!$seenDecl} { set sname {} append sname [string index $namechars [expr {$sCtr/$nnc}]] append sname [string index $namechars [expr {$sCtr%$nnc}]] incr sCtr append unionDef " struct ${operator}_stack_vars \173\n" append afterUnion \ "#if 0 /* local variables moved into u.$sname */\n" set seenDecl 1 } append unionDef " $line\n" append afterUnion $line\n lappend vlist $vname } else { break } } if {$seenDecl} { append unionDef " \175 $sname;\n" append afterUnion "#endif /* local variables moved into u.$sname */\n" } set seenDecl 0 } if {[regexp "^\175" $line]} { append afterUnion $line\n set vlist {} } elseif {[llength $vlist]>0} { append line " " foreach v $vlist { regsub -all "(\[^a-zA-Z0-9>.\])${v}(\\W)" $line "\\1u.$sname.$v\\2" line } append afterUnion [string trimright $line]\n } elseif {$line=="" && [eof stdin]} { # no-op } else { append afterUnion $line\n } } # Output the resulting text. # puts -nonewline $beforeUnion puts " /********************************************************************" puts " ** Automatically generated code" puts " **" puts " ** The following union is automatically generated by the" puts " ** vdbe-compress.tcl script. The purpose of this union is to" puts " ** reduce the amount of stack space required by this function." puts " ** See comments in the vdbe-compress.tcl script for details." puts " */" puts " union vdbeExecUnion \173" puts -nonewline $unionDef puts " \175 u;" puts " /* End automatically generated code" puts " ********************************************************************/" puts -nonewline $afterUnion