Use virtual destructor for Protobuf Messages.

PiperOrigin-RevId: 560717708
diff --git a/src/google/protobuf/repeated_ptr_field.cc b/src/google/protobuf/repeated_ptr_field.cc
index e51c1a1..36dac0e 100644
--- a/src/google/protobuf/repeated_ptr_field.cc
+++ b/src/google/protobuf/repeated_ptr_field.cc
@@ -185,6 +185,10 @@
   return result;
 }
 
+void InternalOutOfLineDeleteMessageLite(MessageLite* message) {
+  delete message;
+}
+
 }  // namespace internal
 
 }  // namespace protobuf
diff --git a/src/google/protobuf/repeated_ptr_field.h b/src/google/protobuf/repeated_ptr_field.h
index 5b5d770..9839852 100644
--- a/src/google/protobuf/repeated_ptr_field.h
+++ b/src/google/protobuf/repeated_ptr_field.h
@@ -843,6 +843,8 @@
   void* tagged_rep_or_elem_;
 };
 
+void InternalOutOfLineDeleteMessageLite(MessageLite* message);
+
 template <typename GenericType>
 class GenericTypeHandler {
  public:
@@ -860,9 +862,18 @@
     return New(arena);
   }
   static inline void Delete(GenericType* value, Arena* arena) {
-    if (arena == nullptr) {
+    if (arena != nullptr) return;
+#ifdef __cpp_if_constexpr
+    if constexpr (std::is_base_of<MessageLite, GenericType>::value) {
+      // Using virtual destructor to reduce generated code size that would have
+      // happened otherwise due to inlined `~GenericType`.
+      InternalOutOfLineDeleteMessageLite(value);
+    } else {
       delete value;
     }
+#else
+    delete value;
+#endif
   }
   static inline Arena* GetOwningArena(GenericType* value) {
     return Arena::InternalGetOwningArena(value);