decompress_bunzip2: relieve register pressure in hot function read_bunzip

function                                             old     new   delta
unpack_bz2_stream                                    318     329     +11
read_bunzip                                          268     262      -6

Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
This commit is contained in:
Denys Vlasenko 2010-10-29 19:01:58 +02:00
parent bf3bec51fc
commit 1014a9adbf
2 changed files with 15 additions and 7 deletions

View 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 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 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. 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) int FAST_FUNC read_bunzip(bunzip_data *bd, char *outbuf, int len)
{ {
const uint32_t *dbuf; const uint32_t *dbuf;
int pos, current, previous, out_count; int pos, current, previous;
uint32_t CRC; uint32_t CRC;
/* If we already have error/end indicator, return it */ /* If we already have error/end indicator, return it */
if (bd->writeCount < 0) if (bd->writeCount < 0)
return bd->writeCount; return bd->writeCount;
out_count = 0;
dbuf = bd->dbuf; dbuf = bd->dbuf;
/* Register-cached state (hopefully): */ /* Register-cached state (hopefully): */
@ -520,7 +523,7 @@ int FAST_FUNC read_bunzip(bunzip_data *bd, char *outbuf, int len)
for (;;) { for (;;) {
/* If the output buffer is full, save cached state and return */ /* If the output buffer is full, save cached state and return */
if (out_count >= len) { if (--len < 0) {
/* Unlikely branch. /* Unlikely branch.
* Use of "goto" instead of keeping code here * Use of "goto" instead of keeping code here
* helps compiler to realize this. */ * 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 */ /* Write next byte into output buffer, updating CRC */
outbuf[out_count++] = current; *outbuf++ = current;
CRC = (CRC << 8) ^ bd->crc32Table[(CRC >> 24) ^ current]; CRC = (CRC << 8) ^ bd->crc32Table[(CRC >> 24) ^ current];
/* Loop now if we're outputting multiple copies of this byte */ /* 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); int r = get_next_block(bd);
if (r) { /* error/end */ if (r) { /* error/end */
bd->writeCount = r; 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++; bd->writeCopies++;
return out_count; return 0;
} }
/* Allocate the structure, read file header. If in_fd==-1, inbuf must contain /* 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) { if (i == 0) {
while (1) { /* "Produce some output bytes" loop */ while (1) { /* "Produce some output bytes" loop */
i = read_bunzip(bd, outbuf, IOBUF_SIZE); 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; break;
if (i != full_write(dst_fd, outbuf, i)) { if (i != full_write(dst_fd, outbuf, i)) {
bb_error_msg("short write"); bb_error_msg("short write");

View 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: */ /* A bit of bunzip2 internals are exposed for compressed help support: */
typedef struct bunzip_data bunzip_data; typedef struct bunzip_data bunzip_data;
int start_bunzip(bunzip_data **bdp, int in_fd, const void *inbuf, int len) FAST_FUNC; 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; int read_bunzip(bunzip_data *bd, char *outbuf, int len) FAST_FUNC;
void dealloc_bunzip(bunzip_data *bd) FAST_FUNC; void dealloc_bunzip(bunzip_data *bd) FAST_FUNC;