summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorDave Watson <davejwatson@fb.com>2019-01-25 22:40:27 (GMT)
committerDave Watson <davejwatson@fb.com>2019-02-08 21:57:23 (GMT)
commit59332a3026eaff40e4c6d3c627bdb51bfd26fea1 (patch)
treecde6ebde62f52e2738679e142ee6e456afa345d2 /lib
parent5dfa7d422ba6c184a7c7694f56bcd36e38e5ed1a (diff)
downloadlz4-59332a3026eaff40e4c6d3c627bdb51bfd26fea1.zip
lz4-59332a3026eaff40e4c6d3c627bdb51bfd26fea1.tar.gz
lz4-59332a3026eaff40e4c6d3c627bdb51bfd26fea1.tar.bz2
decompress_generic: Optimize literal copies
Use LZ4_wildCopy16 for variable-length literals. For literal counts that fit in the flag byte, copy directly. We can also omit oend checks for roughly the same reason as the previous shortcut: We check once that both match length and literal length fit in FASTLOOP_SAFE_DISTANCE, including wildcopy distance.
Diffstat (limited to 'lib')
-rw-r--r--lib/lz4.c33
1 files changed, 21 insertions, 12 deletions
diff --git a/lib/lz4.c b/lib/lz4.c
index 1e938d0..978a957 100644
--- a/lib/lz4.c
+++ b/lib/lz4.c
@@ -1545,22 +1545,31 @@ LZ4_decompress_generic(
/* decode literal length */
if (length == RUN_MASK) {
- variable_length_error error = ok;
- length += read_variable_length(&ip, iend-RUN_MASK, endOnInput, endOnInput, &error);
- if (error == initial_error) goto _output_error;
+ variable_length_error error = ok;
+ length += read_variable_length(&ip, iend-RUN_MASK, endOnInput, endOnInput, &error);
+ if (error == initial_error) goto _output_error;
if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)(op))) goto _output_error; /* overflow detection */
if ((safeDecode) && unlikely((uptrval)(ip)+length<(uptrval)(ip))) goto _output_error; /* overflow detection */
- }
- /* copy literals */
- cpy = op+length;
- LZ4_STATIC_ASSERT(MFLIMIT >= WILDCOPYLENGTH);
- if ( ((endOnInput) && ((cpy>oend-FASTLOOP_SAFE_DISTANCE) || (ip+length>iend-(2+1+LASTLITERALS))) )
- || ((!endOnInput) && (cpy>oend-FASTLOOP_SAFE_DISTANCE)) )
- {
- goto safe_literal_copy;
+ /* copy literals */
+ cpy = op+length;
+ LZ4_STATIC_ASSERT(MFLIMIT >= WILDCOPYLENGTH);
+ if ( ((endOnInput) && ((cpy>oend-FASTLOOP_SAFE_DISTANCE) || (ip+length>iend-(2+1+LASTLITERALS))) )
+ || ((!endOnInput) && (cpy>oend-FASTLOOP_SAFE_DISTANCE)) )
+ {
+ goto safe_literal_copy;
+ }
+ LZ4_wildCopy16(op, ip, cpy);
+ ip += length; op = cpy;
} else {
- LZ4_wildCopy(op, ip, cpy); /* may overwrite up to WILDCOPYLENGTH beyond cpy */
+ cpy = op+length;
+ /* We don't need to check oend, since we check it once for each loop below */
+ if ( ((endOnInput) && (ip+16>iend-(2+1+LASTLITERALS))))
+ {
+ goto safe_literal_copy;
+ }
+ /* Literals can only be 14, but hope compilers optimize if we copy by a register size */
+ memcpy(op, ip, 16);
ip += length; op = cpy;
}