decompress_bunzip2: relieve register pressure in hot function read_bunzip
authorDenys Vlasenko <dvlasenk@redhat.com>
Fri, 29 Oct 2010 17:01:58 +0000 (19:01 +0200)
committerDenys Vlasenko <dvlasenk@redhat.com>
Fri, 29 Oct 2010 17:01:58 +0000 (19:01 +0200)
function                                             old     new   delta
unpack_bz2_stream                                    318     329     +11
read_bunzip                                          268     262      -6

Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
archival/libunarchive/decompress_bunzip2.c
include/unarchive.h

index 8d7746a79788916b87db74aa6f26d221d413ef78..00ec47c7517c01d2359853f06fdb4549b710edc8 100644 (file)
@@ -488,18 +488,21 @@ static int get_next_block(bunzip_data *bd)
    data are written to outbuf.  Return value is number of bytes written or
    error (all errors are negative numbers).  If out_fd!=-1, outbuf and len
    are ignored, data is written to out_fd and return is RETVAL_OK or error.
+
+   NB: read_bunzip returns < 0 on error, or the number of *unfilled* bytes
+   in outbuf. IOW: on EOF returns len ("all bytes are not filled"), not 0.
+   (Why? This allows to get rid of one local variable)
 */
 int FAST_FUNC read_bunzip(bunzip_data *bd, char *outbuf, int len)
 {
        const uint32_t *dbuf;
-       int pos, current, previous, out_count;
+       int pos, current, previous;
        uint32_t CRC;
 
        /* If we already have error/end indicator, return it */
        if (bd->writeCount < 0)
                return bd->writeCount;
 
-       out_count = 0;
        dbuf = bd->dbuf;
 
        /* Register-cached state (hopefully): */
@@ -520,7 +523,7 @@ int FAST_FUNC read_bunzip(bunzip_data *bd, char *outbuf, int len)
                for (;;) {
 
                        /* If the output buffer is full, save cached state and return */
-                       if (out_count >= len) {
+                       if (--len < 0) {
                                /* Unlikely branch.
                                 * Use of "goto" instead of keeping code here
                                 * helps compiler to realize this. */
@@ -528,7 +531,7 @@ int FAST_FUNC read_bunzip(bunzip_data *bd, char *outbuf, int len)
                        }
 
                        /* Write next byte into output buffer, updating CRC */
-                       outbuf[out_count++] = current;
+                       *outbuf++ = current;
                        CRC = (CRC << 8) ^ bd->crc32Table[(CRC >> 24) ^ current];
 
                        /* Loop now if we're outputting multiple copies of this byte */
@@ -587,7 +590,7 @@ int FAST_FUNC read_bunzip(bunzip_data *bd, char *outbuf, int len)
                int r = get_next_block(bd);
                if (r) { /* error/end */
                        bd->writeCount = r;
-                       return (r != RETVAL_LAST_BLOCK) ? r : out_count;
+                       return (r != RETVAL_LAST_BLOCK) ? r : len;
                }
        }
 
@@ -604,7 +607,7 @@ int FAST_FUNC read_bunzip(bunzip_data *bd, char *outbuf, int len)
 
        bd->writeCopies++;
 
-       return out_count;
+       return 0;
 }
 
 /* Allocate the structure, read file header.  If in_fd==-1, inbuf must contain
@@ -698,7 +701,10 @@ unpack_bz2_stream(int src_fd, int dst_fd)
                if (i == 0) {
                        while (1) { /* "Produce some output bytes" loop */
                                i = read_bunzip(bd, outbuf, IOBUF_SIZE);
-                               if (i <= 0)
+                               if (i < 0) /* error? */
+                                       break;
+                               i = IOBUF_SIZE - i; /* number of bytes produced */
+                               if (i == 0) /* EOF? */
                                        break;
                                if (i != full_write(dst_fd, outbuf, i)) {
                                        bb_error_msg("short write");
index 11d8c77a02b0e036c1a93806d7868ed423f9e82a..ba6d323e0458e6e43f982daef8ee0869b7aeac5c 100644 (file)
@@ -194,6 +194,8 @@ extern const llist_t *find_list_entry2(const llist_t *list, const char *filename
 /* A bit of bunzip2 internals are exposed for compressed help support: */
 typedef struct bunzip_data bunzip_data;
 int start_bunzip(bunzip_data **bdp, int in_fd, const void *inbuf, int len) FAST_FUNC;
+/* NB: read_bunzip returns < 0 on error, or the number of *unfilled* bytes
+ * in outbuf. IOW: on EOF returns len ("all bytes are not filled"), not 0: */
 int read_bunzip(bunzip_data *bd, char *outbuf, int len) FAST_FUNC;
 void dealloc_bunzip(bunzip_data *bd) FAST_FUNC;