diff options
Diffstat (limited to 'snappy.cc')
-rw-r--r-- | snappy.cc | 72 |
1 files changed, 50 insertions, 22 deletions
@@ -435,12 +435,26 @@ char* CompressFragment(const char* input, // bool CheckLength() const; // // // Called repeatedly during decompression -// bool Append(const char* ip, uint32 length, bool allow_fast_path); +// bool Append(const char* ip, uint32 length); // bool AppendFromSelf(uint32 offset, uint32 length); -// }; // -// "allow_fast_path" is a parameter that says if there is at least 16 -// readable bytes in "ip". It is currently only used by SnappyArrayWriter. +// // The difference between TryFastAppend and Append is that TryFastAppend +// // is allowed to read up to <available> bytes from the input buffer, +// // whereas Append is allowed to read <length>. +// // +// // Also, TryFastAppend is allowed to return false, declining the append, +// // without it being a fatal error -- just "return false" would be +// // a perfectly legal implementation of TryFastAppend. The intention +// // is for TryFastAppend to allow a fast path in the common case of +// // a small append. +// // +// // NOTE(user): TryFastAppend must always return decline (return false) +// // if <length> is 61 or more, as in this case the literal length is not +// // decoded fully. In practice, this should not be a big problem, +// // as it is unlikely that one would implement a fast path accepting +// // this much data. +// bool TryFastAppend(const char* ip, uint32 available, uint32 length); +// }; // ----------------------------------------------------------------------- // Lookup table for decompression code. Generated by ComputeTable() below. @@ -665,19 +679,23 @@ class SnappyDecompressor { const unsigned char c = *(reinterpret_cast<const unsigned char*>(ip++)); if ((c & 0x3) == LITERAL) { - uint32 literal_length = c >> 2; - if (PREDICT_FALSE(literal_length >= 60)) { + uint32 literal_length = (c >> 2) + 1; + if (writer->TryFastAppend(ip, ip_limit_ - ip, literal_length)) { + DCHECK_LT(literal_length, 61); + ip += literal_length; + continue; + } + if (PREDICT_FALSE(literal_length >= 61)) { // Long literal. - const uint32 literal_length_length = literal_length - 59; + const uint32 literal_length_length = literal_length - 60; literal_length = - LittleEndian::Load32(ip) & wordmask[literal_length_length]; + (LittleEndian::Load32(ip) & wordmask[literal_length_length]) + 1; ip += literal_length_length; } - ++literal_length; uint32 avail = ip_limit_ - ip; while (avail < literal_length) { - if (!writer->Append(ip, avail, false)) return; + if (!writer->Append(ip, avail)) return; literal_length -= avail; reader_->Skip(peeked_); size_t n; @@ -687,8 +705,7 @@ class SnappyDecompressor { if (avail == 0) return; // Premature end of input ip_limit_ = ip + avail; } - bool allow_fast_path = (avail >= 16); - if (!writer->Append(ip, literal_length, allow_fast_path)) { + if (!writer->Append(ip, literal_length)) { return; } ip += literal_length; @@ -902,21 +919,29 @@ class SnappyArrayWriter { return op_ == op_limit_; } - inline bool Append(const char* ip, uint32 len, bool allow_fast_path) { + inline bool Append(const char* ip, uint32 len) { char* op = op_; const int space_left = op_limit_ - op; - if (allow_fast_path && len <= 16 && space_left >= 16) { - // Fast path, used for the majority (about 90%) of dynamic invocations. + if (space_left < len) { + return false; + } + memcpy(op, ip, len); + op_ = op + len; + return true; + } + + inline bool TryFastAppend(const char* ip, uint32 available, uint32 len) { + char* op = op_; + const int space_left = op_limit_ - op; + if (len <= 16 && available >= 16 && space_left >= 16) { + // Fast path, used for the majority (about 95%) of invocations. UNALIGNED_STORE64(op, UNALIGNED_LOAD64(ip)); UNALIGNED_STORE64(op + 8, UNALIGNED_LOAD64(ip + 8)); + op_ = op + len; + return true; } else { - if (space_left < len) { - return false; - } - memcpy(op, ip, len); + return false; } - op_ = op + len; - return true; } inline bool AppendFromSelf(uint32 offset, uint32 len) { @@ -985,10 +1010,13 @@ class SnappyDecompressionValidator { inline bool CheckLength() const { return expected_ == produced_; } - inline bool Append(const char* ip, uint32 len, bool allow_fast_path) { + inline bool Append(const char* ip, uint32 len) { produced_ += len; return produced_ <= expected_; } + inline bool TryFastAppend(const char* ip, uint32 available, uint32 length) { + return false; + } inline bool AppendFromSelf(uint32 offset, uint32 len) { if (produced_ <= offset - 1u) return false; // -1u catches offset==0 produced_ += len; |