Migrate Bio to RefCounted.

Bug: 42290295
Change-Id: I2a3e8758873d8e60cb6ae2f227b0114e6a6a6964
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/89189
Reviewed-by: Xiangfei Ding <xfding@google.com>
Commit-Queue: Xiangfei Ding <xfding@google.com>
diff --git a/crypto/bio/bio.cc b/crypto/bio/bio.cc
index 7f6a052..e3c3ee3 100644
--- a/crypto/bio/bio.cc
+++ b/crypto/bio/bio.cc
@@ -33,51 +33,43 @@
 static CRYPTO_EX_DATA_CLASS g_ex_data_class =
     CRYPTO_EX_DATA_CLASS_INIT_WITH_APP_DATA;
 
+Bio::Bio(const BIO_METHOD *m) : RefCounted(CheckSubClass()), method(m) {
+  CRYPTO_new_ex_data(&ex_data);
+}
+
 BIO *BIO_new(const BIO_METHOD *method) {
-  Bio *ret = NewZeroed<Bio>();
+  UniquePtr<Bio> ret(New<Bio>(method));
   if (ret == nullptr) {
     return nullptr;
   }
 
-  ret->method = method;
-  ret->shutdown = 1;
-  ret->references = 1;
-  CRYPTO_new_ex_data(&ret->ex_data);
-
-  if (method->create != nullptr && !method->create(ret)) {
-    Delete(ret);
+  if (method->create != nullptr && !method->create(ret.get())) {
     return nullptr;
   }
 
-  return ret;
+  return ret.release();
+}
+
+Bio::~Bio() {
+  if (method != nullptr && method->destroy != nullptr) {
+    method->destroy(this);
+  }
+  CRYPTO_free_ex_data(&g_ex_data_class, &ex_data);
+  BIO_free(BIO_pop(this));
 }
 
 int BIO_free(BIO *bio) {
-  auto *impl = FromOpaque(bio);
-
-  Bio *next_bio;
-
-  for (; impl != nullptr; impl = next_bio) {
-    if (!CRYPTO_refcount_dec_and_test_zero(&impl->references)) {
-      return 0;
-    }
-
-    next_bio = FromOpaque(BIO_pop(impl));
-
-    if (impl->method != nullptr && impl->method->destroy != nullptr) {
-      impl->method->destroy(impl);
-    }
-
-    CRYPTO_free_ex_data(&g_ex_data_class, &impl->ex_data);
-    Delete(impl);
+  if (bio == nullptr) {
+    return 1;
   }
+  auto *impl = FromOpaque(bio);
+  impl->DecRefInternal();
   return 1;
 }
 
 int BIO_up_ref(BIO *bio) {
   auto *impl = FromOpaque(bio);
-
-  CRYPTO_refcount_inc(&impl->references);
+  impl->UpRefInternal();
   return 1;
 }
 
diff --git a/crypto/bio/internal.h b/crypto/bio/internal.h
index 6c9e02e..77cd8a8 100644
--- a/crypto/bio/internal.h
+++ b/crypto/bio/internal.h
@@ -20,6 +20,7 @@
 #include <openssl/ex_data.h>
 
 #include "../internal.h"
+#include "../mem_internal.h"
 
 #if !defined(OPENSSL_NO_SOCK)
 #if !defined(OPENSSL_WINDOWS)
@@ -52,8 +53,10 @@
 
 BSSL_NAMESPACE_BEGIN
 
-class Bio : public bio_st {
+class Bio : public bio_st, public RefCounted<Bio> {
  public:
+  explicit Bio(const BIO_METHOD *m);
+
   const BIO_METHOD *method;
   CRYPTO_EX_DATA ex_data;
 
@@ -61,23 +64,26 @@
   // integrated into |flags|, to save memory.
 
   // init is non-zero if this |BIO| has been initialised.
-  int init;
+  int init = 0;
   // shutdown is often used by specific |BIO_METHOD|s to determine whether
   // they own some underlying resource. This flag can often be controlled by
   // |BIO_set_close|. For example, whether an fd BIO closes the underlying fd
   // when it, itself, is closed.
-  int shutdown;
-  int flags;
-  int retry_reason;
+  int shutdown = 1;
+  int flags = 0;
+  int retry_reason = 0;
   // num is a BIO-specific value. For example, in fd BIOs it's used to store a
   // file descriptor.
-  int num;
-  bssl::CRYPTO_refcount_t references;
-  void *ptr;
+  int num = 0;
+  void *ptr = nullptr;
   // next_bio points to the next |BIO| in a chain. This |BIO| owns a reference
   // to |next_bio|.
-  Bio *next_bio;  // used by filter BIOs
-  uint64_t num_read, num_write;
+  Bio *next_bio = nullptr;  // used by filter BIOs
+  uint64_t num_read = 0, num_write = 0;
+
+ private:
+  friend RefCounted;
+  ~Bio();
 };
 
 #if !defined(OPENSSL_NO_SOCK)