Compute num_captures_ eagerly.

Change-Id: I7f77eece4c553956e61c746a77c72e095fb1d0e5
Reviewed-on: https://code-review.googlesource.com/c/36874
Reviewed-by: Paul Wankadia <junyer@google.com>
diff --git a/re2/re2.cc b/re2/re2.cc
index f3f96ae..4e42f8b 100644
--- a/re2/re2.cc
+++ b/re2/re2.cc
@@ -177,10 +177,10 @@
   entire_regexp_ = NULL;
   suffix_regexp_ = NULL;
   prog_ = NULL;
+  num_captures_ = -1;
   rprog_ = NULL;
   error_ = empty_string;
   error_code_ = NoError;
-  num_captures_ = -1;
   named_groups_ = NULL;
   group_names_ = NULL;
 
@@ -218,6 +218,11 @@
     return;
   }
 
+  // We used to compute this lazily, but it's used during the
+  // typical control flow for a match call, so we now compute
+  // it eagerly, which avoids the overhead of std::once_flag.
+  num_captures_ = suffix_regexp_->NumCaptures();
+
   // Could delay this until the first match call that
   // cares about submatch information, but the one-pass
   // machine's memory gets cut from the DFA memory budget,
@@ -301,16 +306,6 @@
   return Fanout(prog, histogram);
 }
 
-// Returns num_captures_, computing it if needed, or -1 if the
-// regexp wasn't valid on construction.
-int RE2::NumberOfCapturingGroups() const {
-  std::call_once(num_captures_once_, [](const RE2* re) {
-    if (re->suffix_regexp_ != NULL)
-      re->num_captures_ = re->suffix_regexp_->NumCaptures();
-  }, this);
-  return num_captures_;
-}
-
 // Returns named_groups_, computing it if needed.
 const std::map<string, int>& RE2::NamedCapturingGroups() const {
   std::call_once(named_groups_once_, [](const RE2* re) {
diff --git a/re2/re2.h b/re2/re2.h
index c93de56..f846029 100644
--- a/re2/re2.h
+++ b/re2/re2.h
@@ -479,7 +479,7 @@
   // Return the number of capturing subpatterns, or -1 if the
   // regexp wasn't valid on construction.  The overall match ($0)
   // does not count: if the regexp is "(a)(b)", returns 2.
-  int NumberOfCapturingGroups() const;
+  int NumberOfCapturingGroups() const { return num_captures_; }
 
   // Return a map from names to capturing indices.
   // The map records the index of the leftmost group
@@ -744,6 +744,7 @@
   re2::Regexp*  entire_regexp_;    // parsed regular expression
   re2::Regexp*  suffix_regexp_;    // parsed regular expression, prefix removed
   re2::Prog*    prog_;             // compiled program for regexp
+  int           num_captures_;     // Number of capturing groups
   bool          is_one_pass_;      // can use prog_->SearchOnePass?
 
   mutable re2::Prog*     rprog_;         // reverse program for regexp
@@ -751,7 +752,6 @@
                                          // (or points to empty string)
   mutable ErrorCode      error_code_;    // Error code
   mutable string         error_arg_;     // Fragment of regexp showing error
-  mutable int            num_captures_;  // Number of capturing groups
 
   // Map from capture names to indices
   mutable const std::map<string, int>* named_groups_;
@@ -761,7 +761,6 @@
 
   // Onces for lazy computations.
   mutable std::once_flag rprog_once_;
-  mutable std::once_flag num_captures_once_;
   mutable std::once_flag named_groups_once_;
   mutable std::once_flag group_names_once_;