Browse Source

Merge pull request #2663 from ckennelly/varint-size

Inline branch-less VarintSize32/VarintSize64 implementations.
Adam Cozzette 8 years ago
parent
commit
38b14408c5
2 changed files with 17 additions and 26 deletions
  1. 0 19
      src/google/protobuf/io/coded_stream.cc
  2. 17 7
      src/google/protobuf/io/coded_stream.h

+ 0 - 19
src/google/protobuf/io/coded_stream.cc

@@ -816,25 +816,6 @@ bool CodedOutputStream::Refresh() {
   }
   }
 }
 }
 
 
-size_t CodedOutputStream::VarintSize32Fallback(uint32 value) {
-  // This computes floor(log2(value)) / 7 + 1
-  // Use an explicit multiplication to implement the divide of
-  // a number in the 1..31 range.
-  GOOGLE_DCHECK_NE(0, value);  // This is enforced by our caller.
-
-  uint32 log2value = Bits::Log2FloorNonZero(value);
-  return static_cast<size_t>((log2value * 9 + 73) / 64);
-}
-
-size_t CodedOutputStream::VarintSize64(uint64 value) {
-  // This computes value == 0 ? 1 : floor(log2(value)) / 7 + 1
-  // Use an explicit multiplication to implement the divide of
-  // a number in the 1..63 range.
-  // Explicit OR 0x1 to avoid calling clz(0), which is undefined.
-  uint32 log2value = Bits::Log2FloorNonZero64(value | 0x1);
-  return static_cast<size_t>((log2value * 9 + 73) / 64);
-}
-
 uint8* CodedOutputStream::WriteStringWithSizeToArray(const string& str,
 uint8* CodedOutputStream::WriteStringWithSizeToArray(const string& str,
                                                      uint8* target) {
                                                      uint8* target) {
   GOOGLE_DCHECK_LE(str.size(), kuint32max);
   GOOGLE_DCHECK_LE(str.size(), kuint32max);

+ 17 - 7
src/google/protobuf/io/coded_stream.h

@@ -903,8 +903,6 @@ class LIBPROTOBUF_EXPORT CodedOutputStream {
   void WriteVarint32SlowPath(uint32 value);
   void WriteVarint32SlowPath(uint32 value);
   void WriteVarint64SlowPath(uint64 value);
   void WriteVarint64SlowPath(uint64 value);
 
 
-  static size_t VarintSize32Fallback(uint32 value);
-
   // See above.  Other projects may use "friend" to allow them to call this.
   // See above.  Other projects may use "friend" to allow them to call this.
   // Requires: no protocol buffer serialization in progress.
   // Requires: no protocol buffer serialization in progress.
   friend void ::google::protobuf::internal::MapTestForceDeterministic();
   friend void ::google::protobuf::internal::MapTestForceDeterministic();
@@ -1290,11 +1288,23 @@ inline uint8* CodedOutputStream::WriteTagToArray(
 }
 }
 
 
 inline size_t CodedOutputStream::VarintSize32(uint32 value) {
 inline size_t CodedOutputStream::VarintSize32(uint32 value) {
-  if (value < (1 << 7)) {
-    return 1;
-  } else  {
-    return VarintSize32Fallback(value);
-  }
+  // This computes value == 0 ? 1 : floor(log2(value)) / 7 + 1
+  // Use an explicit multiplication to implement the divide of
+  // a number in the 1..31 range.
+  // Explicit OR 0x1 to avoid calling Bits::Log2FloorNonZero(0), which is
+  // undefined.
+  uint32 log2value = Bits::Log2FloorNonZero(value | 0x1);
+  return static_cast<size_t>((log2value * 9 + 73) / 64);
+}
+
+inline size_t CodedOutputStream::VarintSize64(uint64 value) {
+  // This computes value == 0 ? 1 : floor(log2(value)) / 7 + 1
+  // Use an explicit multiplication to implement the divide of
+  // a number in the 1..63 range.
+  // Explicit OR 0x1 to avoid calling Bits::Log2FloorNonZero(0), which is
+  // undefined.
+  uint32 log2value = Bits::Log2FloorNonZero64(value | 0x1);
+  return static_cast<size_t>((log2value * 9 + 73) / 64);
 }
 }
 
 
 inline size_t CodedOutputStream::VarintSize32SignExtended(int32 value) {
 inline size_t CodedOutputStream::VarintSize32SignExtended(int32 value) {