diff options
author | dotdotisdead <dotdotisdead@a3eca27d-f21b-0410-9b4a-6511e771f64e> | 2007-01-20 21:31:07 +0000 |
---|---|---|
committer | dotdotisdead <dotdotisdead@a3eca27d-f21b-0410-9b4a-6511e771f64e> | 2007-01-20 21:31:07 +0000 |
commit | 46bc79f71df9953b6b3c8c079f4621054bec44e8 (patch) | |
tree | bcf4a9e53a66ef7d0b30b7f331f0f0ce0cd50e3a | |
parent | cb71b68706e9ca39b3d98162610cf1b3726a294c (diff) |
Changes to support -I IOPT_SIZE on the commandline. New support for unlimited instruction
buffer size set by -I 0. The default remains 4096.
-rwxr-xr-x | xdelta3/xdelta3-main.h | 40 | ||||
-rwxr-xr-x | xdelta3/xdelta3-regtest.py | 12 | ||||
-rwxr-xr-x | xdelta3/xdelta3-test.h | 6 | ||||
-rwxr-xr-x | xdelta3/xdelta3.c | 134 | ||||
-rwxr-xr-x | xdelta3/xdelta3.h | 21 |
5 files changed, 143 insertions, 70 deletions
diff --git a/xdelta3/xdelta3-main.h b/xdelta3/xdelta3-main.h index cada82b..44bd6e5 100755 --- a/xdelta3/xdelta3-main.h +++ b/xdelta3/xdelta3-main.h | |||
@@ -248,7 +248,7 @@ static int option_quiet = 0; | |||
248 | static int option_level = 5; | 248 | static int option_level = 5; |
249 | static int option_use_appheader = 1; | 249 | static int option_use_appheader = 1; |
250 | static uint8_t* option_appheader = NULL; | 250 | static uint8_t* option_appheader = NULL; |
251 | static int option_use_secondary = /* until-standardized, leave this off */ 0; | 251 | static int option_use_secondary = 0; |
252 | static char* option_secondary = NULL; | 252 | static char* option_secondary = NULL; |
253 | static int option_use_checksum = 1; | 253 | static int option_use_checksum = 1; |
254 | static int option_use_altcodetable = 0; | 254 | static int option_use_altcodetable = 0; |
@@ -257,6 +257,7 @@ static int option_no_compress = 0; | |||
257 | static int option_no_output = 0; /* go through the motions, but do not open or write output */ | 257 | static int option_no_output = 0; /* go through the motions, but do not open or write output */ |
258 | static const char *option_source_filename = NULL; | 258 | static const char *option_source_filename = NULL; |
259 | 259 | ||
260 | static int option_iopt_size = XD3_DEFAULT_IOPT_SIZE; | ||
260 | static usize_t option_winsize = XD3_DEFAULT_WINSIZE; | 261 | static usize_t option_winsize = XD3_DEFAULT_WINSIZE; |
261 | static usize_t option_srcwinsz = XD3_DEFAULT_SRCWINSZ; | 262 | static usize_t option_srcwinsz = XD3_DEFAULT_SRCWINSZ; |
262 | static int option_srcwinsz_set = 0; | 263 | static int option_srcwinsz_set = 0; |
@@ -2267,6 +2268,7 @@ main_input (xd3_cmd cmd, | |||
2267 | config.sec_data.ngroups = 1; | 2268 | config.sec_data.ngroups = 1; |
2268 | config.sec_addr.ngroups = 1; | 2269 | config.sec_addr.ngroups = 1; |
2269 | config.sec_inst.ngroups = 1; | 2270 | config.sec_inst.ngroups = 1; |
2271 | config.iopt_size = option_iopt_size; | ||
2270 | 2272 | ||
2271 | /* TODO: eliminate static variables. */ | 2273 | /* TODO: eliminate static variables. */ |
2272 | do_not_lru = 0; | 2274 | do_not_lru = 0; |
@@ -2553,12 +2555,22 @@ main_input (xd3_cmd cmd, | |||
2553 | { | 2555 | { |
2554 | if (IS_ENCODE (cmd) || cmd == CMD_DECODE) | 2556 | if (IS_ENCODE (cmd) || cmd == CMD_DECODE) |
2555 | { | 2557 | { |
2556 | int used_source = xd3_encoder_used_source (& stream); | 2558 | if (! option_quiet && IS_ENCODE (cmd)) |
2557 | |||
2558 | if (! option_quiet && IS_ENCODE (cmd) && main_file_isopen (sfile) && ! used_source) | ||
2559 | { | 2559 | { |
2560 | XPR(NT "warning: input position %"Q"u no source copies\n", | 2560 | /* Warn when no source copies are found */ |
2561 | stream.current_window * option_winsize); | 2561 | if (main_file_isopen (sfile) && ! xd3_encoder_used_source (& stream)) |
2562 | { | ||
2563 | XPR(NT "warning: input position %"Q"u no source copies\n", | ||
2564 | stream.current_window * option_winsize); | ||
2565 | } | ||
2566 | |||
2567 | /* Warn about bad compression due to limited instruction buffer */ | ||
2568 | if (stream.i_slots_used > stream.iopt_size) | ||
2569 | { | ||
2570 | XPR(NT "warning: input position %"Q"u overflowed instruction buffer, " | ||
2571 | "needed %u (vs. %u)\n", | ||
2572 | stream.current_window * option_winsize, stream.i_slots_used, stream.iopt_size); | ||
2573 | } | ||
2562 | } | 2574 | } |
2563 | 2575 | ||
2564 | if (option_verbose) | 2576 | if (option_verbose) |
@@ -2723,7 +2735,7 @@ main (int argc, char **argv) | |||
2723 | main_file ifile; | 2735 | main_file ifile; |
2724 | main_file ofile; | 2736 | main_file ofile; |
2725 | main_file sfile; | 2737 | main_file sfile; |
2726 | static char *flags = "0123456789cdefhnqvDJNORTVs:B:C:E:F:L:O:P:M:W:A::S::"; | 2738 | static char *flags = "0123456789cdefhnqvDJNORTVs:B:C:E:F:I:L:O:P:M:W:A::S::"; |
2727 | int my_optind; | 2739 | int my_optind; |
2728 | char *my_optarg; | 2740 | char *my_optarg; |
2729 | char *my_optstr; | 2741 | char *my_optstr; |
@@ -2925,6 +2937,13 @@ main (int argc, char **argv) | |||
2925 | goto exit; | 2937 | goto exit; |
2926 | } | 2938 | } |
2927 | break; | 2939 | break; |
2940 | case 'I': | ||
2941 | if ((ret = main_atou (my_optarg, & option_iopt_size, 0, | ||
2942 | 0, 'I'))) | ||
2943 | { | ||
2944 | goto exit; | ||
2945 | } | ||
2946 | break; | ||
2928 | case 'W': | 2947 | case 'W': |
2929 | if ((ret = main_atou (my_optarg, & option_winsize, XD3_ALLOCSIZE, | 2948 | if ((ret = main_atou (my_optarg, & option_winsize, XD3_ALLOCSIZE, |
2930 | XD3_HARDMAXWINSIZE, 'W'))) | 2949 | XD3_HARDMAXWINSIZE, 'W'))) |
@@ -3126,6 +3145,7 @@ main_help (void) | |||
3126 | P(RINT "memory options:\n"); | 3145 | P(RINT "memory options:\n"); |
3127 | P(RINT " -B bytes source window size\n"); | 3146 | P(RINT " -B bytes source window size\n"); |
3128 | P(RINT " -W bytes input window size\n"); | 3147 | P(RINT " -W bytes input window size\n"); |
3148 | P(RINT " -I size instruction buffer size (0 = unlimited)\n"); | ||
3129 | 3149 | ||
3130 | P(RINT "compression options:\n"); | 3150 | P(RINT "compression options:\n"); |
3131 | P(RINT " -s source source file to copy from (if any)\n"); | 3151 | P(RINT " -s source source file to copy from (if any)\n"); |
@@ -3133,15 +3153,15 @@ main_help (void) | |||
3133 | P(RINT " -N disable small string-matching compression\n"); | 3153 | P(RINT " -N disable small string-matching compression\n"); |
3134 | P(RINT " -D disable external decompression (encode/decode)\n"); | 3154 | P(RINT " -D disable external decompression (encode/decode)\n"); |
3135 | P(RINT " -R disable external recompression (decode)\n"); | 3155 | P(RINT " -R disable external recompression (decode)\n"); |
3156 | P(RINT " -n disable checksum (encode/decode)\n"); | ||
3157 | P(RINT " -C soft config (encode, undocumented)\n"); | ||
3158 | P(RINT " -A [apphead] disable/provide application header (encode)\n"); | ||
3136 | 3159 | ||
3137 | #if XD3_DEBUG > 0 | 3160 | #if XD3_DEBUG > 0 |
3138 | P(RINT "developer options:\n"); | 3161 | P(RINT "developer options:\n"); |
3139 | P(RINT " -A [apphead] disable/provide application header\n"); | ||
3140 | P(RINT " -C soft config (see xdelta3-cfgs.h)\n"); | ||
3141 | P(RINT " -J disable output (check/compute only)\n"); | 3162 | P(RINT " -J disable output (check/compute only)\n"); |
3142 | P(RINT " -P repeat count (for profiling)\n"); | 3163 | P(RINT " -P repeat count (for profiling)\n"); |
3143 | P(RINT " -T use alternate code table\n"); | 3164 | P(RINT " -T use alternate code table\n"); |
3144 | P(RINT " -n disable checksum (encode/decode)\n"); | ||
3145 | #endif | 3165 | #endif |
3146 | return EXIT_FAILURE; | 3166 | return EXIT_FAILURE; |
3147 | } | 3167 | } |
diff --git a/xdelta3/xdelta3-regtest.py b/xdelta3/xdelta3-regtest.py index 7bb7a1c..bf064bb 100755 --- a/xdelta3/xdelta3-regtest.py +++ b/xdelta3/xdelta3-regtest.py | |||
@@ -611,15 +611,15 @@ def BigFileRun(f1, f2): | |||
611 | def RandomBigRun(f1, f2): | 611 | def RandomBigRun(f1, f2): |
612 | 612 | ||
613 | input_ranges = [ | 613 | input_ranges = [ |
614 | (7, 9, 'large_look'), | 614 | (7, 20, 'large_look'), |
615 | (1, 10, 'large_step'), | 615 | (1, 30, 'large_step'), |
616 | (4, 5, 'small_look'), | 616 | (4, 5, 'small_look'), |
617 | (1, 20, 'small_chain'), | 617 | (1, 32, 'small_chain'), |
618 | (1, 10, 'small_lchain'), | 618 | (1, 16, 'small_lchain'), |
619 | (0, 1, 'ssmatch'), | 619 | (0, 1, 'ssmatch'), |
620 | (0, 1, 'trylazy'), | 620 | (0, 1, 'trylazy'), |
621 | (1, 32, 'max_lazy'), | 621 | (1, 128, 'max_lazy'), |
622 | (1, 64, 'long_enough'), | 622 | (1, 256, 'long_enough'), |
623 | (0, 1, 'promote'), | 623 | (0, 1, 'promote'), |
624 | ] | 624 | ] |
625 | 625 | ||
diff --git a/xdelta3/xdelta3-test.h b/xdelta3/xdelta3-test.h index 2c7af22..36166c6 100755 --- a/xdelta3/xdelta3-test.h +++ b/xdelta3/xdelta3-test.h | |||
@@ -2049,9 +2049,9 @@ test_string_matching (xd3_stream *stream, int ignore) | |||
2049 | if ((ret = stream->smatcher.string_match (stream))) { return ret; } | 2049 | if ((ret = stream->smatcher.string_match (stream))) { return ret; } |
2050 | 2050 | ||
2051 | *rptr = 0; | 2051 | *rptr = 0; |
2052 | while (! xd3_rlist_empty (& stream->iopt.used)) | 2052 | while (! xd3_rlist_empty (& stream->iopt_used)) |
2053 | { | 2053 | { |
2054 | xd3_rinst *inst = xd3_rlist_pop_front (& stream->iopt.used); | 2054 | xd3_rinst *inst = xd3_rlist_pop_front (& stream->iopt_used); |
2055 | 2055 | ||
2056 | switch (inst->type) | 2056 | switch (inst->type) |
2057 | { | 2057 | { |
@@ -2072,7 +2072,7 @@ test_string_matching (xd3_stream *stream, int ignore) | |||
2072 | 2072 | ||
2073 | *rptr++ = ' '; | 2073 | *rptr++ = ' '; |
2074 | 2074 | ||
2075 | xd3_rlist_push_back (& stream->iopt.free, inst); | 2075 | xd3_rlist_push_back (& stream->iopt_free, inst); |
2076 | } | 2076 | } |
2077 | 2077 | ||
2078 | if (rptr != rbuf) | 2078 | if (rptr != rbuf) |
diff --git a/xdelta3/xdelta3.c b/xdelta3/xdelta3.c index 14a3c08..97c3390 100755 --- a/xdelta3/xdelta3.c +++ b/xdelta3/xdelta3.c | |||
@@ -550,7 +550,7 @@ static void* xd3_alloc0 (xd3_stream *stream, | |||
550 | static xd3_output* xd3_alloc_output (xd3_stream *stream, | 550 | static xd3_output* xd3_alloc_output (xd3_stream *stream, |
551 | xd3_output *old_output); | 551 | xd3_output *old_output); |
552 | 552 | ||
553 | 553 | static int xd3_alloc_iopt (xd3_stream *stream, int elts); | |
554 | 554 | ||
555 | static void xd3_free_output (xd3_stream *stream, | 555 | static void xd3_free_output (xd3_stream *stream, |
556 | xd3_output *output); | 556 | xd3_output *output); |
@@ -2281,11 +2281,20 @@ xd3_free_output (xd3_stream *stream, | |||
2281 | void | 2281 | void |
2282 | xd3_free_stream (xd3_stream *stream) | 2282 | xd3_free_stream (xd3_stream *stream) |
2283 | { | 2283 | { |
2284 | xd3_iopt_buflist *blist = stream->iopt_alloc; | ||
2285 | |||
2286 | do | ||
2287 | { | ||
2288 | xd3_iopt_buflist *tmp = blist; | ||
2289 | blist = blist->next; | ||
2290 | xd3_free (stream, tmp->buffer); | ||
2291 | xd3_free (stream, tmp); | ||
2292 | } | ||
2293 | while (blist != NULL); | ||
2284 | 2294 | ||
2285 | xd3_free (stream, stream->large_table); | 2295 | xd3_free (stream, stream->large_table); |
2286 | xd3_free (stream, stream->small_table); | 2296 | xd3_free (stream, stream->small_table); |
2287 | xd3_free (stream, stream->small_prev); | 2297 | xd3_free (stream, stream->small_prev); |
2288 | xd3_free (stream, stream->iopt.buffer); | ||
2289 | 2298 | ||
2290 | #if XD3_ENCODER | 2299 | #if XD3_ENCODER |
2291 | { | 2300 | { |
@@ -2393,6 +2402,12 @@ xd3_config_stream(xd3_stream *stream, | |||
2393 | stream->srcwin_size = config->srcwin_size ? config->srcwin_size : XD3_DEFAULT_CKSUM_ADVANCE; | 2402 | stream->srcwin_size = config->srcwin_size ? config->srcwin_size : XD3_DEFAULT_CKSUM_ADVANCE; |
2394 | stream->srcwin_maxsz = config->srcwin_maxsz ? config->srcwin_maxsz : XD3_DEFAULT_SRCWINSZ; | 2403 | stream->srcwin_maxsz = config->srcwin_maxsz ? config->srcwin_maxsz : XD3_DEFAULT_SRCWINSZ; |
2395 | 2404 | ||
2405 | if (stream->iopt_size == 0) | ||
2406 | { | ||
2407 | stream->iopt_size = XD3_ALLOCSIZE / sizeof(xd3_rinst); | ||
2408 | stream->iopt_unlimited = 1; | ||
2409 | } | ||
2410 | |||
2396 | stream->getblk = config->getblk; | 2411 | stream->getblk = config->getblk; |
2397 | stream->alloc = config->alloc ? config->alloc : __xd3_alloc_func; | 2412 | stream->alloc = config->alloc ? config->alloc : __xd3_alloc_func; |
2398 | stream->free = config->freef ? config->freef : __xd3_free_func; | 2413 | stream->free = config->freef ? config->freef : __xd3_free_func; |
@@ -2663,8 +2678,8 @@ xd3_set_appheader (xd3_stream *stream, | |||
2663 | static int | 2678 | static int |
2664 | xd3_iopt_check (xd3_stream *stream) | 2679 | xd3_iopt_check (xd3_stream *stream) |
2665 | { | 2680 | { |
2666 | int ul = xd3_rlist_length (& stream->iopt.used); | 2681 | int ul = xd3_rlist_length (& stream->iopt_used); |
2667 | int fl = xd3_rlist_length (& stream->iopt.free); | 2682 | int fl = xd3_rlist_length (& stream->iopt_free); |
2668 | 2683 | ||
2669 | return (ul + fl + (stream->iout ? 1 : 0)) == stream->iopt_size; | 2684 | return (ul + fl + (stream->iout ? 1 : 0)) == stream->iopt_size; |
2670 | } | 2685 | } |
@@ -2674,7 +2689,7 @@ static xd3_rinst* | |||
2674 | xd3_iopt_free (xd3_stream *stream, xd3_rinst *i) | 2689 | xd3_iopt_free (xd3_stream *stream, xd3_rinst *i) |
2675 | { | 2690 | { |
2676 | xd3_rinst *n = xd3_rlist_remove (i); | 2691 | xd3_rinst *n = xd3_rlist_remove (i); |
2677 | xd3_rlist_push_back (& stream->iopt.free, i); | 2692 | xd3_rlist_push_back (& stream->iopt_free, i); |
2678 | return n; | 2693 | return n; |
2679 | } | 2694 | } |
2680 | 2695 | ||
@@ -2683,7 +2698,7 @@ xd3_iopt_free_nonadd (xd3_stream *stream, xd3_rinst *i) | |||
2683 | { | 2698 | { |
2684 | if (i->type != XD3_ADD) | 2699 | if (i->type != XD3_ADD) |
2685 | { | 2700 | { |
2686 | xd3_rlist_push_back (& stream->iopt.free, i); | 2701 | xd3_rlist_push_back (& stream->iopt_free, i); |
2687 | } | 2702 | } |
2688 | } | 2703 | } |
2689 | 2704 | ||
@@ -2885,7 +2900,7 @@ xd3_iopt_add_finalize (xd3_stream *stream) | |||
2885 | static int | 2900 | static int |
2886 | xd3_iopt_flush_instructions (xd3_stream *stream, int force) | 2901 | xd3_iopt_flush_instructions (xd3_stream *stream, int force) |
2887 | { | 2902 | { |
2888 | xd3_rinst *r1 = xd3_rlist_front (& stream->iopt.used); | 2903 | xd3_rinst *r1 = xd3_rlist_front (& stream->iopt_used); |
2889 | xd3_rinst *r2; | 2904 | xd3_rinst *r2; |
2890 | xd3_rinst *r3; | 2905 | xd3_rinst *r3; |
2891 | usize_t r1end; | 2906 | usize_t r1end; |
@@ -2901,8 +2916,8 @@ xd3_iopt_flush_instructions (xd3_stream *stream, int force) | |||
2901 | /* Note: once tried to skip this step if it's possible to assert there are no | 2916 | /* Note: once tried to skip this step if it's possible to assert there are no |
2902 | * overlapping instructions. Doesn't work because xd3_opt_erase leaves overlapping | 2917 | * overlapping instructions. Doesn't work because xd3_opt_erase leaves overlapping |
2903 | * instructions. */ | 2918 | * instructions. */ |
2904 | while (! xd3_rlist_end (& stream->iopt.used, r1) && | 2919 | while (! xd3_rlist_end (& stream->iopt_used, r1) && |
2905 | ! xd3_rlist_end (& stream->iopt.used, r2 = xd3_rlist_next (r1))) | 2920 | ! xd3_rlist_end (& stream->iopt_used, r2 = xd3_rlist_next (r1))) |
2906 | { | 2921 | { |
2907 | r1end = r1->pos + r1->size; | 2922 | r1end = r1->pos + r1->size; |
2908 | 2923 | ||
@@ -2919,7 +2934,7 @@ xd3_iopt_flush_instructions (xd3_stream *stream, int force) | |||
2919 | XD3_ASSERT (r2end > (r1end + LEAST_MATCH_INCR)); | 2934 | XD3_ASSERT (r2end > (r1end + LEAST_MATCH_INCR)); |
2920 | 2935 | ||
2921 | /* If r3 is available... */ | 2936 | /* If r3 is available... */ |
2922 | if (! xd3_rlist_end (& stream->iopt.used, r3 = xd3_rlist_next (r2))) | 2937 | if (! xd3_rlist_end (& stream->iopt_used, r3 = xd3_rlist_next (r2))) |
2923 | { | 2938 | { |
2924 | /* If r3 starts before r1 finishes or just about, r2 is irrelevant */ | 2939 | /* If r3 starts before r1 finishes or just about, r2 is irrelevant */ |
2925 | if (r3->pos <= r1end + 1) | 2940 | if (r3->pos <= r1end + 1) |
@@ -3026,9 +3041,9 @@ xd3_iopt_flush_instructions (xd3_stream *stream, int force) | |||
3026 | 3041 | ||
3027 | /* If forcing, pick instructions until the list is empty, otherwise this empties 50% of | 3042 | /* If forcing, pick instructions until the list is empty, otherwise this empties 50% of |
3028 | * the queue. */ | 3043 | * the queue. */ |
3029 | for (flushed = 0; ! xd3_rlist_empty (& stream->iopt.used); ) | 3044 | for (flushed = 0; ! xd3_rlist_empty (& stream->iopt_used); ) |
3030 | { | 3045 | { |
3031 | xd3_rinst *renc = xd3_rlist_pop_front (& stream->iopt.used); | 3046 | xd3_rinst *renc = xd3_rlist_pop_front (& stream->iopt_used); |
3032 | if ((ret = xd3_iopt_add_encoding (stream, renc))) | 3047 | if ((ret = xd3_iopt_add_encoding (stream, renc))) |
3033 | { | 3048 | { |
3034 | return ret; | 3049 | return ret; |
@@ -3044,10 +3059,10 @@ xd3_iopt_flush_instructions (xd3_stream *stream, int force) | |||
3044 | /* If there are only two instructions remaining, break, because they were | 3059 | /* If there are only two instructions remaining, break, because they were |
3045 | * not optimized. This means there were more than 50% eliminated by the | 3060 | * not optimized. This means there were more than 50% eliminated by the |
3046 | * loop above. */ | 3061 | * loop above. */ |
3047 | r1 = xd3_rlist_front (& stream->iopt.used); | 3062 | r1 = xd3_rlist_front (& stream->iopt_used); |
3048 | if (xd3_rlist_end(& stream->iopt.used, r1) || | 3063 | if (xd3_rlist_end(& stream->iopt_used, r1) || |
3049 | xd3_rlist_end(& stream->iopt.used, r2 = xd3_rlist_next (r1)) || | 3064 | xd3_rlist_end(& stream->iopt_used, r2 = xd3_rlist_next (r1)) || |
3050 | xd3_rlist_end(& stream->iopt.used, r3 = xd3_rlist_next (r2))) | 3065 | xd3_rlist_end(& stream->iopt_used, r3 = xd3_rlist_next (r2))) |
3051 | { | 3066 | { |
3052 | break; | 3067 | break; |
3053 | } | 3068 | } |
@@ -3056,7 +3071,7 @@ xd3_iopt_flush_instructions (xd3_stream *stream, int force) | |||
3056 | 3071 | ||
3057 | XD3_ASSERT (xd3_iopt_check (stream)); | 3072 | XD3_ASSERT (xd3_iopt_check (stream)); |
3058 | 3073 | ||
3059 | XD3_ASSERT (!force || xd3_rlist_length (& stream->iopt.used) == 0); | 3074 | XD3_ASSERT (!force || xd3_rlist_length (& stream->iopt_used) == 0); |
3060 | 3075 | ||
3061 | return 0; | 3076 | return 0; |
3062 | } | 3077 | } |
@@ -3067,19 +3082,33 @@ xd3_iopt_get_slot (xd3_stream *stream, xd3_rinst** iptr) | |||
3067 | xd3_rinst *i; | 3082 | xd3_rinst *i; |
3068 | int ret; | 3083 | int ret; |
3069 | 3084 | ||
3070 | if (xd3_rlist_empty (& stream->iopt.free)) | 3085 | if (xd3_rlist_empty (& stream->iopt_free)) |
3071 | { | 3086 | { |
3072 | if ((ret = xd3_iopt_flush_instructions (stream, 0))) { return ret; } | 3087 | if (stream->iopt_unlimited) |
3088 | { | ||
3089 | int elts = XD3_ALLOCSIZE / sizeof(xd3_rinst); | ||
3090 | if ((ret = xd3_alloc_iopt (stream, elts))) | ||
3091 | { | ||
3092 | return ret; | ||
3093 | } | ||
3094 | stream->iopt_size += elts; | ||
3095 | } | ||
3096 | else | ||
3097 | { | ||
3098 | if ((ret = xd3_iopt_flush_instructions (stream, 0))) { return ret; } | ||
3073 | 3099 | ||
3074 | XD3_ASSERT (! xd3_rlist_empty (& stream->iopt.free)); | 3100 | XD3_ASSERT (! xd3_rlist_empty (& stream->iopt_free)); |
3101 | } | ||
3075 | } | 3102 | } |
3076 | 3103 | ||
3077 | i = xd3_rlist_pop_back (& stream->iopt.free); | 3104 | i = xd3_rlist_pop_back (& stream->iopt_free); |
3078 | 3105 | ||
3079 | xd3_rlist_push_back (& stream->iopt.used, i); | 3106 | xd3_rlist_push_back (& stream->iopt_used, i); |
3080 | 3107 | ||
3081 | (*iptr) = i; | 3108 | (*iptr) = i; |
3082 | 3109 | ||
3110 | ++stream->i_slots_used; | ||
3111 | |||
3083 | return 0; | 3112 | return 0; |
3084 | } | 3113 | } |
3085 | 3114 | ||
@@ -3090,9 +3119,9 @@ xd3_iopt_get_slot (xd3_stream *stream, xd3_rinst** iptr) | |||
3090 | static void | 3119 | static void |
3091 | xd3_iopt_erase (xd3_stream *stream, usize_t pos, usize_t size) | 3120 | xd3_iopt_erase (xd3_stream *stream, usize_t pos, usize_t size) |
3092 | { | 3121 | { |
3093 | while (! xd3_rlist_empty (& stream->iopt.used)) | 3122 | while (! xd3_rlist_empty (& stream->iopt_used)) |
3094 | { | 3123 | { |
3095 | xd3_rinst *r = xd3_rlist_back (& stream->iopt.used); | 3124 | xd3_rinst *r = xd3_rlist_back (& stream->iopt_used); |
3096 | 3125 | ||
3097 | /* Verify that greedy is working. The previous instruction should end before the | 3126 | /* Verify that greedy is working. The previous instruction should end before the |
3098 | * new one begins. */ | 3127 | * new one begins. */ |
@@ -3110,7 +3139,8 @@ xd3_iopt_erase (xd3_stream *stream, usize_t pos, usize_t size) | |||
3110 | 3139 | ||
3111 | /* Otherwise, the new instruction covers the old one, delete it and repeat. */ | 3140 | /* Otherwise, the new instruction covers the old one, delete it and repeat. */ |
3112 | xd3_rlist_remove (r); | 3141 | xd3_rlist_remove (r); |
3113 | xd3_rlist_push_back (& stream->iopt.free, r); | 3142 | xd3_rlist_push_back (& stream->iopt_free, r); |
3143 | --stream->i_slots_used; | ||
3114 | } | 3144 | } |
3115 | } | 3145 | } |
3116 | 3146 | ||
@@ -3120,12 +3150,12 @@ xd3_iopt_last_matched (xd3_stream *stream) | |||
3120 | { | 3150 | { |
3121 | xd3_rinst *r; | 3151 | xd3_rinst *r; |
3122 | 3152 | ||
3123 | if (xd3_rlist_empty (& stream->iopt.used)) | 3153 | if (xd3_rlist_empty (& stream->iopt_used)) |
3124 | { | 3154 | { |
3125 | return 0; | 3155 | return 0; |
3126 | } | 3156 | } |
3127 | 3157 | ||
3128 | r = xd3_rlist_back (& stream->iopt.used); | 3158 | r = xd3_rlist_back (& stream->iopt_used); |
3129 | 3159 | ||
3130 | return r->pos + r->size; | 3160 | return r->pos + r->size; |
3131 | } | 3161 | } |
@@ -3430,6 +3460,31 @@ xd3_encode_buffer_leftover (xd3_stream *stream) | |||
3430 | return 0; | 3460 | return 0; |
3431 | } | 3461 | } |
3432 | 3462 | ||
3463 | /* Allocates one block of xd3_rlist elements */ | ||
3464 | static int | ||
3465 | xd3_alloc_iopt (xd3_stream *stream, int elts) | ||
3466 | { | ||
3467 | int i; | ||
3468 | xd3_iopt_buflist* next = stream->iopt_alloc; | ||
3469 | xd3_iopt_buflist* last = xd3_alloc (stream, sizeof (xd3_iopt_buflist), 1); | ||
3470 | |||
3471 | if (last == NULL || | ||
3472 | (last->buffer = xd3_alloc (stream, sizeof (xd3_rinst), elts)) == NULL) | ||
3473 | { | ||
3474 | return ENOMEM; | ||
3475 | } | ||
3476 | |||
3477 | last->next = next; | ||
3478 | stream->iopt_alloc = last; | ||
3479 | |||
3480 | for (i = 0; i < elts; i += 1) | ||
3481 | { | ||
3482 | xd3_rlist_push_back (& stream->iopt_free, & last->buffer[i]); | ||
3483 | } | ||
3484 | |||
3485 | return 0; | ||
3486 | } | ||
3487 | |||
3433 | /* This function allocates all memory initially used by the encoder. */ | 3488 | /* This function allocates all memory initially used by the encoder. */ |
3434 | static int | 3489 | static int |
3435 | xd3_encode_init (xd3_stream *stream) | 3490 | xd3_encode_init (xd3_stream *stream) |
@@ -3454,9 +3509,9 @@ xd3_encode_init (xd3_stream *stream) | |||
3454 | 3509 | ||
3455 | if (small_comp) | 3510 | if (small_comp) |
3456 | { | 3511 | { |
3457 | /* Hard-coded, keeps table small because small matches become inefficient. */ | 3512 | /* Hard-coded, keeps table small because small matches become inefficient. |
3458 | // TODO: verify this | 3513 | * TODO: verify this stuff. */ |
3459 | usize_t hash_values = min(stream->winsize, 65536U); | 3514 | usize_t hash_values = min(stream->winsize, XD3_DEFAULT_SPREVSZ); |
3460 | 3515 | ||
3461 | xd3_size_hashtable (stream, | 3516 | xd3_size_hashtable (stream, |
3462 | hash_values, | 3517 | hash_values, |
@@ -3474,21 +3529,13 @@ xd3_encode_init (xd3_stream *stream) | |||
3474 | } | 3529 | } |
3475 | 3530 | ||
3476 | /* iopt buffer */ | 3531 | /* iopt buffer */ |
3477 | xd3_rlist_init (& stream->iopt.used); | 3532 | xd3_rlist_init (& stream->iopt_used); |
3478 | xd3_rlist_init (& stream->iopt.free); | 3533 | xd3_rlist_init (& stream->iopt_free); |
3479 | 3534 | ||
3480 | if ((stream->iopt.buffer = xd3_alloc (stream, sizeof (xd3_rinst), stream->iopt_size)) == NULL) | 3535 | if (xd3_alloc_iopt (stream, stream->iopt_size) != 0) { goto fail; } |
3481 | { | ||
3482 | goto fail; | ||
3483 | } | ||
3484 | |||
3485 | for (i = 0; i < stream->iopt_size; i += 1) | ||
3486 | { | ||
3487 | xd3_rlist_push_back (& stream->iopt.free, & stream->iopt.buffer[i]); | ||
3488 | } | ||
3489 | 3536 | ||
3490 | XD3_ASSERT (xd3_rlist_length (& stream->iopt.free) == stream->iopt_size); | 3537 | XD3_ASSERT (xd3_rlist_length (& stream->iopt_free) == stream->iopt_size); |
3491 | XD3_ASSERT (xd3_rlist_length (& stream->iopt.used) == 0); | 3538 | XD3_ASSERT (xd3_rlist_length (& stream->iopt_used) == 0); |
3492 | 3539 | ||
3493 | /* address cache, code table */ | 3540 | /* address cache, code table */ |
3494 | stream->acache.s_near = stream->code_table_desc->near_modes; | 3541 | stream->acache.s_near = stream->code_table_desc->near_modes; |
@@ -3532,6 +3579,7 @@ xd3_encode_reset (xd3_stream *stream) | |||
3532 | IF_DEBUG (stream->n_emit = 0); | 3579 | IF_DEBUG (stream->n_emit = 0); |
3533 | stream->avail_in = 0; | 3580 | stream->avail_in = 0; |
3534 | stream->small_reset = 1; | 3581 | stream->small_reset = 1; |
3582 | stream->i_slots_used = 0; | ||
3535 | 3583 | ||
3536 | if (stream->src != NULL) | 3584 | if (stream->src != NULL) |
3537 | { | 3585 | { |
diff --git a/xdelta3/xdelta3.h b/xdelta3/xdelta3.h index a9ca8f1..c2fe0a6 100755 --- a/xdelta3/xdelta3.h +++ b/xdelta3/xdelta3.h | |||
@@ -74,7 +74,8 @@ | |||
74 | 74 | ||
75 | /* The IOPT_SIZE value sets the size of a buffer used to batch overlapping copy | 75 | /* The IOPT_SIZE value sets the size of a buffer used to batch overlapping copy |
76 | * instructions before they are optimized by picking the best non-overlapping ranges. The | 76 | * instructions before they are optimized by picking the best non-overlapping ranges. The |
77 | * larger this buffer, the longer a forced xd3_srcwin_setup() decision is held off. */ | 77 | * larger this buffer, the longer a forced xd3_srcwin_setup() decision is held off. |
78 | * Setting this value to 0 causes an unlimited buffer to be used. */ | ||
78 | #ifndef XD3_DEFAULT_IOPT_SIZE | 79 | #ifndef XD3_DEFAULT_IOPT_SIZE |
79 | #define XD3_DEFAULT_IOPT_SIZE (1U<<12) | 80 | #define XD3_DEFAULT_IOPT_SIZE (1U<<12) |
80 | #endif | 81 | #endif |
@@ -192,7 +193,7 @@ typedef struct _xd3_rpage xd3_rpage; | |||
192 | typedef struct _xd3_addr_cache xd3_addr_cache; | 193 | typedef struct _xd3_addr_cache xd3_addr_cache; |
193 | typedef struct _xd3_output xd3_output; | 194 | typedef struct _xd3_output xd3_output; |
194 | typedef struct _xd3_desect xd3_desect; | 195 | typedef struct _xd3_desect xd3_desect; |
195 | typedef struct _xd3_iopt_buf xd3_iopt_buf; | 196 | typedef struct _xd3_iopt_buflist xd3_iopt_buflist; |
196 | typedef struct _xd3_rlist xd3_rlist; | 197 | typedef struct _xd3_rlist xd3_rlist; |
197 | typedef struct _xd3_sec_type xd3_sec_type; | 198 | typedef struct _xd3_sec_type xd3_sec_type; |
198 | typedef struct _xd3_sec_cfg xd3_sec_cfg; | 199 | typedef struct _xd3_sec_cfg xd3_sec_cfg; |
@@ -484,13 +485,12 @@ struct _xd3_addr_cache | |||
484 | usize_t *same_array; /* array of size s_same*256 */ | 485 | usize_t *same_array; /* array of size s_same*256 */ |
485 | }; | 486 | }; |
486 | 487 | ||
487 | /* the IOPT buffer has a used list of (ordered) instructions, possibly overlapping in | 488 | /* the IOPT buffer list is just a list of buffers, which may be allocated |
488 | * target addresses, awaiting a flush */ | 489 | * during encode when using an unlimited buffer. */ |
489 | struct _xd3_iopt_buf | 490 | struct _xd3_iopt_buflist |
490 | { | 491 | { |
491 | xd3_rlist used; | ||
492 | xd3_rlist free; | ||
493 | xd3_rinst *buffer; | 492 | xd3_rinst *buffer; |
493 | xd3_iopt_buflist *next; | ||
494 | }; | 494 | }; |
495 | 495 | ||
496 | /* This is the record of a pre-compiled configuration, a subset of xd3_config. */ | 496 | /* This is the record of a pre-compiled configuration, a subset of xd3_config. */ |
@@ -634,6 +634,7 @@ struct _xd3_stream | |||
634 | usize_t sprevsz; /* small string, previous window size (power of 2) */ | 634 | usize_t sprevsz; /* small string, previous window size (power of 2) */ |
635 | usize_t sprevmask; /* small string, previous window size mask */ | 635 | usize_t sprevmask; /* small string, previous window size mask */ |
636 | uint iopt_size; | 636 | uint iopt_size; |
637 | uint iopt_unlimited; | ||
637 | uint srcwin_size; | 638 | uint srcwin_size; |
638 | uint srcwin_maxsz; | 639 | uint srcwin_maxsz; |
639 | 640 | ||
@@ -698,8 +699,10 @@ struct _xd3_stream | |||
698 | xd3_output *enc_heads[4]; /* array of encoded outputs: head of chain */ | 699 | xd3_output *enc_heads[4]; /* array of encoded outputs: head of chain */ |
699 | xd3_output *enc_tails[4]; /* array of encoded outputs: tail of chain */ | 700 | xd3_output *enc_tails[4]; /* array of encoded outputs: tail of chain */ |
700 | 701 | ||
701 | xd3_iopt_buf iopt; /* instruction optimizing buffer */ | 702 | xd3_rlist iopt_used; /* instruction optimizing buffer */ |
703 | xd3_rlist iopt_free; | ||
702 | xd3_rinst *iout; /* next single instruction */ | 704 | xd3_rinst *iout; /* next single instruction */ |
705 | xd3_iopt_buflist *iopt_alloc; | ||
703 | 706 | ||
704 | const uint8_t *enc_appheader; /* application header to encode */ | 707 | const uint8_t *enc_appheader; /* application header to encode */ |
705 | usize_t enc_appheadsz; /* application header size */ | 708 | usize_t enc_appheadsz; /* application header size */ |
@@ -785,6 +788,8 @@ struct _xd3_stream | |||
785 | xoff_t l_add; | 788 | xoff_t l_add; |
786 | xoff_t l_run; | 789 | xoff_t l_run; |
787 | 790 | ||
791 | usize_t i_slots_used; | ||
792 | |||
788 | #if XD3_DEBUG | 793 | #if XD3_DEBUG |
789 | usize_t sh_searches; | 794 | usize_t sh_searches; |
790 | usize_t sh_compares; | 795 | usize_t sh_compares; |