go/ssa: two minor cleanups

1. inline sole uses of addMethod, createMethodSet.
2. simplify MethodValue call to LookupMethod in go/callgraph.

Change-Id: Ifa94d0dd7c2a522551c0d76341213dc9c8a73501
Reviewed-on: https://go-review.googlesource.com/c/tools/+/540216
Reviewed-by: Tim King <taking@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
diff --git a/go/callgraph/rta/rta.go b/go/callgraph/rta/rta.go
index 36fe93f..d0ae0fc 100644
--- a/go/callgraph/rta/rta.go
+++ b/go/callgraph/rta/rta.go
@@ -232,7 +232,7 @@
 func (r *rta) addInvokeEdge(site ssa.CallInstruction, C types.Type) {
 	// Ascertain the concrete method of C to be called.
 	imethod := site.Common().Method
-	cmethod := r.prog.MethodValue(r.prog.MethodSets.MethodSet(C).Lookup(imethod.Pkg(), imethod.Name()))
+	cmethod := r.prog.LookupMethod(C, imethod.Pkg(), imethod.Name())
 	r.addEdge(site.Parent(), site, cmethod, true)
 }
 
diff --git a/go/callgraph/vta/vta.go b/go/callgraph/vta/vta.go
index 5839360..2303fcf 100644
--- a/go/callgraph/vta/vta.go
+++ b/go/callgraph/vta/vta.go
@@ -154,6 +154,9 @@
 // ssa.Program.MethodSets and ssa.Program.MethodValue
 // APIs. The cache is used to speed up querying of
 // methods of a type as the mentioned APIs are expensive.
+//
+// TODO(adonovan): Program.MethodValue already does this kind of
+// caching. Is this really necessary?
 type methodCache map[types.Type]map[string][]*ssa.Function
 
 // methods returns methods of a type `t` named `name`. First consults
diff --git a/go/ssa/methods.go b/go/ssa/methods.go
index 2700d26..03ef625 100644
--- a/go/ssa/methods.go
+++ b/go/ssa/methods.go
@@ -42,9 +42,39 @@
 
 	var cr creator
 
-	prog.methodsMu.Lock()
-	m := prog.addMethod(prog.createMethodSet(T), sel, &cr)
-	prog.methodsMu.Unlock()
+	m := func() *Function {
+		prog.methodsMu.Lock()
+		defer prog.methodsMu.Unlock()
+
+		// Get or create SSA method set.
+		mset, ok := prog.methodSets.At(T).(*methodSet)
+		if !ok {
+			mset = &methodSet{mapping: make(map[string]*Function)}
+			prog.methodSets.Set(T, mset)
+		}
+
+		// Get or create SSA method.
+		id := sel.Obj().Id()
+		fn, ok := mset.mapping[id]
+		if !ok {
+			obj := sel.Obj().(*types.Func)
+			_, ptrObj := deptr(recvType(obj))
+			_, ptrRecv := deptr(T)
+			needsPromotion := len(sel.Index()) > 1
+			needsIndirection := !ptrObj && ptrRecv
+			if needsPromotion || needsIndirection {
+				fn = createWrapper(prog, toSelection(sel), &cr)
+			} else {
+				fn = prog.objectMethod(obj, &cr)
+			}
+			if fn.Signature.Recv() == nil {
+				panic(fn)
+			}
+			mset.mapping[id] = fn
+		}
+
+		return fn
+	}()
 
 	b := builder{created: &cr}
 	b.iterate()
@@ -111,54 +141,6 @@
 	mapping map[string]*Function // populated lazily
 }
 
-// Precondition: T is a concrete type, e.g. !isInterface(T) and not parameterized.
-// Requires prog.methodsMu.
-func (prog *Program) createMethodSet(T types.Type) *methodSet {
-	if prog.mode&SanityCheckFunctions != 0 {
-		if types.IsInterface(T) || prog.parameterized.isParameterized(T) {
-			panic("type is interface or parameterized")
-		}
-	}
-
-	mset, ok := prog.methodSets.At(T).(*methodSet)
-	if !ok {
-		mset = &methodSet{mapping: make(map[string]*Function)}
-		prog.methodSets.Set(T, mset)
-	}
-	return mset
-}
-
-// Adds any created functions to cr.
-// Precondition: T is a concrete type, e.g. !isInterface(T) and not parameterized.
-// Requires prog.methodsMu.
-func (prog *Program) addMethod(mset *methodSet, sel *types.Selection, cr *creator) *Function {
-	if sel.Kind() == types.MethodExpr {
-		panic(sel)
-	}
-	id := sel.Obj().Id()
-	fn := mset.mapping[id]
-	if fn == nil {
-		sel := toSelection(sel)
-		obj := sel.obj.(*types.Func)
-
-		_, ptrObj := deptr(recvType(obj))
-		_, ptrRecv := deptr(sel.recv)
-
-		needsPromotion := len(sel.index) > 1
-		needsIndirection := !ptrObj && ptrRecv
-		if needsPromotion || needsIndirection {
-			fn = createWrapper(prog, sel, cr)
-		} else {
-			fn = prog.objectMethod(obj, cr)
-		}
-		if fn.Signature.Recv() == nil {
-			panic(fn) // missing receiver
-		}
-		mset.mapping[id] = fn
-	}
-	return fn
-}
-
 // RuntimeTypes returns a new unordered slice containing all types in
 // the program for which a runtime type is required.
 //