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:
parent
bf3bec51fc
commit
1014a9adbf
@ -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");
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user