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}
diff --git a/base/callback_internal.cc b/base/callback_internal.cc
index f360388..2553fe7 100644
--- a/base/callback_internal.cc
+++ b/base/callback_internal.cc
@@ -9,6 +9,15 @@
 namespace base {
 namespace internal {
 
+void BindStateBase::AddRef() {
+  AtomicRefCountInc(&ref_count_);
+}
+
+void BindStateBase::Release() {
+  if (!AtomicRefCountDec(&ref_count_))
+    destructor_(this);
+}
+
 CallbackBase::CallbackBase(const CallbackBase& c) = default;
 CallbackBase& CallbackBase::operator=(const CallbackBase& c) = default;
 
@@ -27,7 +36,7 @@
 CallbackBase::CallbackBase(BindStateBase* bind_state)
     : bind_state_(bind_state),
       polymorphic_invoke_(NULL) {
-  DCHECK(!bind_state_.get() || bind_state_->HasOneRef());
+  DCHECK(!bind_state_.get() || bind_state_->ref_count_ == 1);
 }
 
 CallbackBase::~CallbackBase() {