Ticket #688: faster_pbc_to_exe_win32_also.patch

File faster_pbc_to_exe_win32_also.patch, 7.1 KB (added by Util, 13 years ago)

Second test patch

  • parrot/tools/dev/pbc_to_exe.pir

     
    3232    (infile, cfile, objfile, exefile) = 'handle_args'(argv) 
    3333    unless infile > '' goto err_infile 
    3434 
     35    # Generate the string (on non-Win32) or string table (on Win32) that 
     36    # contains all the bytecode. Also generate the get_program_code function 
     37    # that masks the difference between the two representations. 
    3538    .local string codestring 
     39    $P0 = '_config'() 
     40    .local string osname 
     41    osname = $P0['osname'] 
     42    # XXX This needs to test for MS compiler, not just Win32; Mingw32 does not need the slow version. 
     43    unless osname == 'MSWin32' goto code_for_non_windows 
     44  code_for_windows: 
     45    codestring = 'generate_code_win32'(infile) 
     46    goto code_end 
     47  code_for_non_windows: 
    3648    codestring = 'generate_code'(infile) 
     49  code_end: 
    3750 
     51 
    3852  open_outfile: 
    3953    .local pmc outfh 
    4054    outfh = open cfile, 'w' 
     
    4761    print outfh, codestring 
    4862 
    4963    print outfh, <<'MAIN' 
     64 
    5065        int main(int argc, char *argv[]) 
    5166        { 
    5267            PackFile     *pf; 
    5368            Parrot_Interp interp; 
    5469 
     70            const char   * const program_code = get_program_code(); 
     71            if (!program_code) 
     72                return 1; 
     73 
    5574            Parrot_set_config_hash(); 
    5675 
    5776            interp = Parrot_new( NULL ); 
     
    172191    .return(infile, cfile, objfile, exefile) 
    173192.end 
    174193 
     194# The PBC will be represented as a C string, so this sub builds a table 
     195# of the C representation of each ASCII character, for lookup by ordinal value. 
     196.sub 'generate_encoding_table' 
     197    # Use '\%o' for speed, or '\x%02x' for readability 
     198    .const string encoding_format = '\%o' 
     199 
     200    # The 'sprintf' op requires the arglist to be in an array, even when 
     201    # there is only one arg. 
     202    .local pmc one_number 
     203    one_number    = new 'FixedIntegerArray' 
     204    set one_number, 1 
     205 
     206    .local pmc coded_strings 
     207    coded_strings = new 'FixedStringArray' 
     208    set coded_strings, 256 
     209 
     210    .local int index 
     211    index = 0 
     212 
     213  next_index: 
     214    one_number[0] = index 
     215    $S0 = sprintf encoding_format, one_number 
     216    coded_strings[index] = $S0 
     217    inc index 
     218    if index < 256 goto next_index 
     219 
     220    .return (coded_strings) 
     221.end 
     222 
     223# With GCC (and all other known non-Microsoft compilers), huge string constants 
     224# are allowed. We generate a single C string to represent the entire bytecode. 
     225# The get_program_code function simply returns a pointer to the compile-time 
     226# string. 
    175227.sub 'generate_code' 
    176228    .param string infile 
    177229    .local pmc ifh 
    178230    ifh = open infile, 'r' 
    179231    unless ifh goto err_infile 
     232 
     233    .local pmc encoding_table 
     234    encoding_table = 'generate_encoding_table'() 
     235 
    180236    .local string codestring 
    181237    .local int size 
    182     codestring = "const Parrot_UInt1 program_code[] = {" 
     238    codestring = "const char * const program_code_raw =\n" 
     239    codestring .= '"' 
    183240    size = 0 
    184241 
    185242  read_loop: 
     
    195252  code_loop: 
    196253    unless pos < pbclength goto code_done 
    197254    $I0 = ord pbcstring, pos 
    198     $S0 = $I0 
     255    $S0 = encoding_table[$I0] 
    199256    codestring .= $S0 
    200     codestring .= ',' 
    201257    inc pos 
    202258    inc size 
    203259    $I0 = size % 32 
    204260    unless $I0 == 0 goto code_loop 
     261    codestring .= '"' 
    205262    codestring .= "\n" 
     263    codestring .= '"' 
    206264    goto code_loop 
    207265  code_done: 
    208266    goto read_loop 
     
    210268  read_done: 
    211269    close ifh 
    212270 
    213     codestring .= "\n};\n\n" 
     271    codestring .= '"' 
     272    codestring .= "\n;\n\n" 
    214273    codestring .= "const int bytecode_size = " 
    215274    $S0 = size 
    216275    codestring .= $S0 
    217276    codestring .= ";\n" 
     277 
     278    $S0 = <<'SUBROUTINE' 
     279        const char * get_program_code(void); 
     280        const char * get_program_code(void) 
     281        { 
     282            return program_code_raw; 
     283        } 
     284SUBROUTINE 
     285    codestring .= $S0 
     286 
    218287    .return (codestring) 
    219288 
    220289  err_infile: 
    221290    die "cannot open infile" 
    222291.end 
    223292 
     293 
     294# On the most limited known version of the Microsoft C compiler, 16KB is the 
     295# maximum size of a string. We generate an array of C strings to represent 
     296# the bytecode; each string is of a fixed size smaller than 16KB. 
     297# The get_program_code() function allocates a block large enough to contain 
     298# the entire bytecode, then fills the block with the C strings at run-time. 
     299.sub 'generate_code_win32' 
     300    .param string infile 
     301    .local pmc ifh 
     302    ifh = open infile, 'r' 
     303    unless ifh goto err_infile 
     304 
     305    # Since we cannot use the last byte (the end-of-string NULL), the maximum 
     306    # block size would be 16384-1. However, we will use 16384-32 (the number 
     307    # of bytes in each line) to simplify the code. 
     308    .const int line_length = 32 
     309    .const int max_block_size = 16352 
     310 
     311    .local pmc encoding_table 
     312    encoding_table = 'generate_encoding_table'() 
     313 
     314    .local string codestring 
     315    .local int size 
     316    codestring = "const char * const program_code_array[] = {\n" 
     317    size = 0 
     318 
     319  read_loop: 
     320    .local string pbcstring 
     321    .local int pbclength 
     322 
     323    pbcstring = read ifh, max_block_size 
     324    pbclength = length pbcstring 
     325    unless pbclength > 0 goto read_done 
     326 
     327    # This padding is to keep the memcpy() from ever having to deal with a short block. 
     328  pad_to_full_block: 
     329    unless pbclength < max_block_size goto end_pad 
     330    pbcstring .= "\0" 
     331    inc pbclength 
     332    goto pad_to_full_block 
     333  end_pad: 
     334 
     335    if size == 0 goto skip_comma_separating_strings 
     336    codestring .= ",\n" 
     337  skip_comma_separating_strings: 
     338 
     339 
     340    .local int pos 
     341    pos = 0 
     342  code_loop: 
     343    unless pos < pbclength goto code_done 
     344 
     345    $I0 = pos % line_length 
     346    unless $I0 == 0 goto skip_line_start_quote 
     347    codestring .= '  "' 
     348  skip_line_start_quote: 
     349 
     350 
     351    $I0 = ord pbcstring, pos 
     352    $S0 = encoding_table[$I0] 
     353    codestring .= $S0 
     354    inc pos 
     355    inc size 
     356 
     357 
     358    $I0 = size % line_length 
     359    unless $I0 == 0 goto skip_line_end_quote 
     360    codestring .= '"' 
     361    codestring .= "\n" 
     362  skip_line_end_quote: 
     363 
     364    goto code_loop 
     365  code_done: 
     366    goto read_loop 
     367 
     368  read_done: 
     369    close ifh 
     370 
     371    codestring .= ",\nNULL\n" 
     372    codestring .= "};\n\n" 
     373 
     374    codestring .= "const int bytecode_size = " 
     375    $S0 = size 
     376    codestring .= $S0 
     377    codestring .= ";\n" 
     378 
     379    codestring .= "const int max_block_size = " 
     380    $S0 = max_block_size 
     381    codestring .= $S0 
     382    codestring .= ";\n" 
     383 
     384    $S0 = <<'SUBROUTINE' 
     385        const char * get_program_code(void); 
     386        const char * get_program_code(void) 
     387        { 
     388            int i; 
     389            char *p, *program_code_in_one_block; 
     390 
     391            program_code_in_one_block = malloc( bytecode_size ); 
     392            if (!program_code_in_one_block) 
     393                return NULL; 
     394 
     395            for ( i = 0, p = program_code_in_one_block; program_code_array[i]; i++, p += max_block_size ) 
     396                memcpy( p, program_code_array[i], max_block_size ); 
     397 
     398            return program_code_in_one_block; 
     399        } 
     400SUBROUTINE 
     401    codestring .= $S0 
     402 
     403    .return (codestring) 
     404 
     405  err_infile: 
     406    die "cannot open infile" 
     407.end 
     408 
     409 
    224410# util functions 
    225411.sub 'compile_file' 
    226412    .param string cfile