proto: CSE ProtoReflect() and TypeDescriptor() in proto.HasExtension

No need to call them multiple times, no matter how cheap they are. Mild
improvements, this CL is 01-cse-hasextension:

    $ perflock -socket=@perflock -shared -cores 12 go test -tags=protolegacy -test.bench=BenchmarkExtension -test.benchmem -test.run=^# -test.count 10 internal/benchmarks/micro/micro_test.go

    goarch: amd64
    cpu: AMD Ryzen Threadripper PRO 3995WX 64-Cores
                          │ 00-cse-messageinfo │        01-cse-hasextension         │
                          │       sec/op       │   sec/op     vs base               │
    Extension/Has/None-12         103.30n ± 3%   96.73n ± 1%  -6.36% (p=0.000 n=10)
    Extension/Has/Set-12           113.0n ± 3%   107.1n ± 1%  -5.22% (p=0.000 n=10)
    Extension/Get/None-12          182.7n ± 2%   176.3n ± 2%  -3.48% (p=0.000 n=10)
    Extension/Get/Set-12           140.1n ± 2%   138.0n ± 1%  -1.46% (p=0.024 n=10)
    Extension/Set-12               218.6n ± 2%   219.5n ± 1%       ~ (p=0.172 n=10)
    geomean                        145.6n        140.8n       -3.25%

Change-Id: Ide1a0c0fe4e562ed24f88dc829249fca0f052d48
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/576315
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Nicolas Hillegeer <aktau@google.com>
Reviewed-by: Michael Stapelberg <stapelberg@google.com>
diff --git a/proto/extension.go b/proto/extension.go
index 17899a3..c9c8721 100644
--- a/proto/extension.go
+++ b/proto/extension.go
@@ -11,18 +11,21 @@
 // HasExtension reports whether an extension field is populated.
 // It returns false if m is invalid or if xt does not extend m.
 func HasExtension(m Message, xt protoreflect.ExtensionType) bool {
-	// Treat nil message interface as an empty message; no populated fields.
-	if m == nil {
+	// Treat nil message interface or descriptor as an empty message; no populated
+	// fields.
+	if m == nil || xt == nil {
 		return false
 	}
 
 	// As a special-case, we reports invalid or mismatching descriptors
 	// as always not being populated (since they aren't).
-	if xt == nil || m.ProtoReflect().Descriptor() != xt.TypeDescriptor().ContainingMessage() {
+	mr := m.ProtoReflect()
+	xd := xt.TypeDescriptor()
+	if mr.Descriptor() != xd.ContainingMessage() {
 		return false
 	}
 
-	return m.ProtoReflect().Has(xt.TypeDescriptor())
+	return mr.Has(xd)
 }
 
 // ClearExtension clears an extension field such that subsequent