internal/impl: precompute required bit in validator

Required field validation populates a bitmask of observed required
fields. Store a uint64 containing the bit to set in the validationInfo
rather than the index of the bit. Provides a noticeable speed increase
in validation.

name                             old time/op  new time/op  delta
EmptyMessage/Wire/Unmarshal      40.2ns ± 1%  40.2ns ± 2%    ~     (p=0.860 n=35+37)
EmptyMessage/Wire/Unmarshal-12   7.13ns ± 5%  7.12ns ± 1%    ~     (p=0.112 n=37+37)
RepeatedInt32/Wire/Unmarshal     6.57µs ± 1%  6.46µs ± 1%  -1.56%  (p=0.000 n=39+35)
RepeatedInt32/Wire/Unmarshal-12  1.05µs ± 2%  1.05µs ± 2%    ~     (p=0.659 n=37+33)
Required/Wire/Unmarshal           258ns ± 1%   251ns ± 1%  -2.87%  (p=0.000 n=32+38)
Required/Wire/Unmarshal-12       44.3ns ± 2%  42.4ns ± 1%  -4.36%  (p=0.000 n=36+37)

Change-Id: Ib1cb74d3e348355a6a2f66aecf8fdc4b58cd84d4
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/216420
Reviewed-by: Joe Tsai <joetsai@google.com>
diff --git a/internal/impl/decode.go b/internal/impl/decode.go
index 4a1d631..4b1bc6d 100644
--- a/internal/impl/decode.go
+++ b/internal/impl/decode.go
@@ -143,9 +143,10 @@
 			var o unmarshalOutput
 			o, err = f.funcs.unmarshal(b, p.Apply(f.offset), wtyp, opts)
 			n = o.n
-			if reqi := f.validation.requiredIndex; reqi > 0 && err == nil {
-				requiredMask |= 1 << (reqi - 1)
+			if err != nil {
+				break
 			}
+			requiredMask |= f.validation.requiredBit
 			if f.funcs.isInit != nil && !o.initialized {
 				initialized = false
 			}
diff --git a/internal/impl/validate.go b/internal/impl/validate.go
index cb6a820..093f078 100644
--- a/internal/impl/validate.go
+++ b/internal/impl/validate.go
@@ -77,11 +77,13 @@
 	typ              validationType
 	keyType, valType validationType
 
-	// For non-required fields, requiredIndex is 0.
+	// For non-required fields, requiredBit is 0.
 	//
-	// For required fields, requiredIndex is unique index in the range
-	// (0, MessageInfo.numRequiredFields].
-	requiredIndex uint8
+	// For required fields, requiredBit's nth bit is set, where n is a
+	// unique index in the range [0, MessageInfo.numRequiredFields).
+	//
+	// If there are more than 64 required fields, requiredBit is 0.
+	requiredBit uint64
 }
 
 type validationType uint8
@@ -131,7 +133,7 @@
 		// of the required fields past 64.
 		if mi.numRequiredFields < math.MaxUint8 {
 			mi.numRequiredFields++
-			vi.requiredIndex = mi.numRequiredFields
+			vi.requiredBit = 1 << (mi.numRequiredFields - 1)
 		}
 	}
 	return vi
@@ -272,7 +274,7 @@
 				case 2:
 					vi.typ = st.valType
 					vi.mi = st.mi
-					vi.requiredIndex = 1
+					vi.requiredBit = 1
 				}
 			default:
 				var f *coderFieldInfo
@@ -321,7 +323,7 @@
 					vi = getExtensionFieldInfo(xt).validation
 				}
 			}
-			if vi.requiredIndex > 0 {
+			if vi.requiredBit != 0 {
 				// Check that the field has a compatible wire type.
 				// We only need to consider non-repeated field types,
 				// since repeated fields (and maps) can never be required.
@@ -337,7 +339,7 @@
 					ok = wtyp == wire.BytesType
 				}
 				if ok {
-					st.requiredMask |= 1 << (vi.requiredIndex - 1)
+					st.requiredMask |= vi.requiredBit
 				}
 			}
 			switch vi.typ {