Instantiate LogMessage::CopyToEncodedBuffer separately for literals and non-literals to save an instruction at each operator<<(string) callsite.

The operator<<s get inlined at the callsite.  The saved instruction is a 'load immediate' to put the StringType argument in a register for passing.

This does make the logging TU slightly larger, but it will be an overall size win for all but the smallest programs.  Smaller, faster code at callsites is worth it anyway.

PiperOrigin-RevId: 528569773
Change-Id: Id8185266a975a12ab6f1a553c2c0846261822396
diff --git a/absl/log/internal/log_message.cc b/absl/log/internal/log_message.cc
index 4deca72..10ac245 100644
--- a/absl/log/internal/log_message.cc
+++ b/absl/log/internal/log_message.cc
@@ -353,12 +353,12 @@
 }
 
 LogMessage& LogMessage::operator<<(const std::string& v) {
-  CopyToEncodedBuffer(v, StringType::kNotLiteral);
+  CopyToEncodedBuffer<StringType::kNotLiteral>(v);
   return *this;
 }
 
 LogMessage& LogMessage::operator<<(absl::string_view v) {
-  CopyToEncodedBuffer(v, StringType::kNotLiteral);
+  CopyToEncodedBuffer<StringType::kNotLiteral>(v);
   return *this;
 }
 LogMessage& LogMessage::operator<<(std::ostream& (*m)(std::ostream& os)) {
@@ -525,8 +525,8 @@
 // containing the specified string data using a `Value` field appropriate to
 // `str_type`.  Truncates `str` if necessary, but emits nothing and marks the
 // buffer full if  even the field headers do not fit.
-void LogMessage::CopyToEncodedBuffer(absl::string_view str,
-                                     StringType str_type) {
+template <LogMessage::StringType str_type>
+void LogMessage::CopyToEncodedBuffer(absl::string_view str) {
   auto encoded_remaining_copy = data_->encoded_remaining;
   auto start = EncodeMessageStart(
       EventTag::kValue, BufferSizeFor(WireType::kLengthDelimited) + str.size(),
@@ -547,7 +547,12 @@
     data_->encoded_remaining.remove_suffix(data_->encoded_remaining.size());
   }
 }
-void LogMessage::CopyToEncodedBuffer(char ch, size_t num, StringType str_type) {
+template void LogMessage::CopyToEncodedBuffer<LogMessage::StringType::kLiteral>(
+    absl::string_view str);
+template void LogMessage::CopyToEncodedBuffer<
+    LogMessage::StringType::kNotLiteral>(absl::string_view str);
+template <LogMessage::StringType str_type>
+void LogMessage::CopyToEncodedBuffer(char ch, size_t num) {
   auto encoded_remaining_copy = data_->encoded_remaining;
   auto value_start = EncodeMessageStart(
       EventTag::kValue, BufferSizeFor(WireType::kLengthDelimited) + num,
@@ -568,6 +573,10 @@
     data_->encoded_remaining.remove_suffix(data_->encoded_remaining.size());
   }
 }
+template void LogMessage::CopyToEncodedBuffer<LogMessage::StringType::kLiteral>(
+    char ch, size_t num);
+template void LogMessage::CopyToEncodedBuffer<
+    LogMessage::StringType::kNotLiteral>(char ch, size_t num);
 
 LogMessageFatal::LogMessageFatal(const char* file, int line)
     : LogMessage(file, line, absl::LogSeverity::kFatal) {}
diff --git a/absl/log/internal/log_message.h b/absl/log/internal/log_message.h
index 6fdfa7b..4693772 100644
--- a/absl/log/internal/log_message.h
+++ b/absl/log/internal/log_message.h
@@ -231,10 +231,10 @@
     kLiteral,
     kNotLiteral,
   };
-  void CopyToEncodedBuffer(absl::string_view str,
-                           StringType str_type) ABSL_ATTRIBUTE_NOINLINE;
-  void CopyToEncodedBuffer(char ch, size_t num,
-                           StringType str_type) ABSL_ATTRIBUTE_NOINLINE;
+  template <StringType str_type>
+  void CopyToEncodedBuffer(absl::string_view str) ABSL_ATTRIBUTE_NOINLINE;
+  template <StringType str_type>
+  void CopyToEncodedBuffer(char ch, size_t num) ABSL_ATTRIBUTE_NOINLINE;
 
   // Returns `true` if the message is fatal or enabled debug-fatal.
   bool IsFatal() const;
@@ -264,12 +264,12 @@
   explicit StringifySink(LogMessage& message) : message_(message) {}
 
   void Append(size_t count, char ch) {
-    message_.CopyToEncodedBuffer(ch, count,
-                                 LogMessage::StringType::kNotLiteral);
+    message_.CopyToEncodedBuffer<LogMessage::StringType::kNotLiteral>(ch,
+                                                                      count);
   }
 
   void Append(absl::string_view v) {
-    message_.CopyToEncodedBuffer(v, LogMessage::StringType::kNotLiteral);
+    message_.CopyToEncodedBuffer<LogMessage::StringType::kNotLiteral>(v);
   }
 
   // For types that implement `AbslStringify` using `absl::Format()`.
@@ -304,14 +304,14 @@
 
 template <int SIZE>
 LogMessage& LogMessage::operator<<(const char (&buf)[SIZE]) {
-  CopyToEncodedBuffer(buf, StringType::kLiteral);
+  CopyToEncodedBuffer<StringType::kLiteral>(buf);
   return *this;
 }
 
 // Note: the following is declared `ABSL_ATTRIBUTE_NOINLINE`
 template <int SIZE>
 LogMessage& LogMessage::operator<<(char (&buf)[SIZE]) {
-  CopyToEncodedBuffer(buf, StringType::kNotLiteral);
+  CopyToEncodedBuffer<StringType::kNotLiteral>(buf);
   return *this;
 }
 // We instantiate these specializations in the library's TU to save space in
@@ -339,6 +339,16 @@
 extern template LogMessage& LogMessage::operator<<(const double& v);
 extern template LogMessage& LogMessage::operator<<(const bool& v);
 
+extern template void LogMessage::CopyToEncodedBuffer<
+    LogMessage::StringType::kLiteral>(absl::string_view str);
+extern template void LogMessage::CopyToEncodedBuffer<
+    LogMessage::StringType::kNotLiteral>(absl::string_view str);
+extern template void
+LogMessage::CopyToEncodedBuffer<LogMessage::StringType::kLiteral>(char ch,
+                                                                  size_t num);
+extern template void LogMessage::CopyToEncodedBuffer<
+    LogMessage::StringType::kNotLiteral>(char ch, size_t num);
+
 // `LogMessageFatal` ensures the process will exit in failure after logging this
 // message.
 class LogMessageFatal final : public LogMessage {
diff --git a/absl/log/internal/structured.h b/absl/log/internal/structured.h
index 08caea6..5223dbc 100644
--- a/absl/log/internal/structured.h
+++ b/absl/log/internal/structured.h
@@ -42,7 +42,7 @@
     return os << as_literal.str_;
   }
   void AddToMessage(log_internal::LogMessage& m) {
-    m.CopyToEncodedBuffer(str_, log_internal::LogMessage::StringType::kLiteral);
+    m.CopyToEncodedBuffer<log_internal::LogMessage::StringType::kLiteral>(str_);
   }
   friend log_internal::LogMessage& operator<<(log_internal::LogMessage& m,
                                               AsLiteralImpl as_literal) {