Devirtualize base::BindState to save 1% of Chrome's binary size (1MB)

Every call to base::Bind results in a new class declaration. Since
base::internal::BindState is a virtual class, this also results in a
bespoke vtable being defined. And that's a lot of vtables. Like 1MB
worth of vtables, or 1% of Chrome's binary size.

However, this vtable's sole purpose is for RefCountedThreadSafe::
Release(). Release() _does_ need to know precisely how to delete the
BindState, but it doesn't need a vtable to do it. All it needs is a
function pointer.

This CL de-virtualizes base::BindState and instead moves the vtable
pointer (which is merely an array holding the destructor) to a function
pointer that contains the destructor instead. Since BindState previously
contained a pointer-to-vtable the net memory effect of having the
function pointer instead should be offset.

And of course a 1MB binary size drop also means reduced memory
requirements for the shared text-segment pages.

Locally produced numbers for ChromiumFramework on Mac:
pre-strip:
 - before: 192,031kB
 - after: 185,800kB
post-strip:
 - before: 101,353kB
 - after: 100,353kB

BUG=486594

Review URL: https://codereview.chromium.org/1129353003

Cr-Commit-Position: refs/heads/master@{#329818}


CrOS-Libchrome-Original-Commit: e7e804c7d491ea23cfbf5b57a9ec1f8fa78b44a7
diff --git a/base/callback_internal.h b/base/callback_internal.h
index 8a5c437..fefd7a2 100644
--- a/base/callback_internal.h
+++ b/base/callback_internal.h
@@ -10,15 +10,19 @@
 
 #include <stddef.h>
 
+#include "base/atomic_ref_count.h"
 #include "base/base_export.h"
+#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/template_util.h"
 
 template <typename T>
 class ScopedVector;
 
 namespace base {
 namespace internal {
+class CallbackBase;
 
 // BindStateBase is used to provide an opaque handle that the Callback
 // class can use to represent a function object with bound arguments.  It
@@ -26,10 +30,30 @@
 // DoInvoke function to perform the function execution.  This allows
 // us to shield the Callback class from the types of the bound argument via
 // "type erasure."
-class BindStateBase : public RefCountedThreadSafe<BindStateBase> {
+// At the base level, the only task is to add reference counting data. Don't use
+// RefCountedThreadSafe since it requires the destructor to be a virtual method.
+// Creating a vtable for every BindState template instantiation results in a lot
+// of bloat. Its only task is to call the destructor which can be done with a
+// function pointer.
+class BindStateBase {
  protected:
-  friend class RefCountedThreadSafe<BindStateBase>;
-  virtual ~BindStateBase() {}
+  explicit BindStateBase(void (*destructor)(BindStateBase*))
+      : ref_count_(0), destructor_(destructor) {}
+  ~BindStateBase() = default;
+
+ private:
+  friend class scoped_refptr<BindStateBase>;
+  friend class CallbackBase;
+
+  void AddRef();
+  void Release();
+
+  AtomicRefCount ref_count_;
+
+  // Pointer to a function that will properly destroy |this|.
+  void (*destructor_)(BindStateBase*);
+
+  DISALLOW_COPY_AND_ASSIGN(BindStateBase);
 };
 
 // Holds the Callback methods that don't require specialization to reduce