Skip to content

Commit 51df92b

Browse files
committed
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 <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent e7fb31a commit 51df92b

File tree

3 files changed

+37
-52
lines changed

3 files changed

+37
-52
lines changed

go/callgraph/rta/rta.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ func (r *rta) visitDynCall(site ssa.CallInstruction) {
232232
func (r *rta) addInvokeEdge(site ssa.CallInstruction, C types.Type) {
233233
// Ascertain the concrete method of C to be called.
234234
imethod := site.Common().Method
235-
cmethod := r.prog.MethodValue(r.prog.MethodSets.MethodSet(C).Lookup(imethod.Pkg(), imethod.Name()))
235+
cmethod := r.prog.LookupMethod(C, imethod.Pkg(), imethod.Name())
236236
r.addEdge(site.Parent(), site, cmethod, true)
237237
}
238238

go/callgraph/vta/vta.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,9 @@ func propFunc(p propType, c ssa.CallInstruction, cache methodCache) []*ssa.Funct
154154
// ssa.Program.MethodSets and ssa.Program.MethodValue
155155
// APIs. The cache is used to speed up querying of
156156
// methods of a type as the mentioned APIs are expensive.
157+
//
158+
// TODO(adonovan): Program.MethodValue already does this kind of
159+
// caching. Is this really necessary?
157160
type methodCache map[types.Type]map[string][]*ssa.Function
158161

159162
// methods returns methods of a type `t` named `name`. First consults

go/ssa/methods.go

Lines changed: 33 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,39 @@ func (prog *Program) MethodValue(sel *types.Selection) *Function {
4242

4343
var cr creator
4444

45-
prog.methodsMu.Lock()
46-
m := prog.addMethod(prog.createMethodSet(T), sel, &cr)
47-
prog.methodsMu.Unlock()
45+
m := func() *Function {
46+
prog.methodsMu.Lock()
47+
defer prog.methodsMu.Unlock()
48+
49+
// Get or create SSA method set.
50+
mset, ok := prog.methodSets.At(T).(*methodSet)
51+
if !ok {
52+
mset = &methodSet{mapping: make(map[string]*Function)}
53+
prog.methodSets.Set(T, mset)
54+
}
55+
56+
// Get or create SSA method.
57+
id := sel.Obj().Id()
58+
fn, ok := mset.mapping[id]
59+
if !ok {
60+
obj := sel.Obj().(*types.Func)
61+
_, ptrObj := deptr(recvType(obj))
62+
_, ptrRecv := deptr(T)
63+
needsPromotion := len(sel.Index()) > 1
64+
needsIndirection := !ptrObj && ptrRecv
65+
if needsPromotion || needsIndirection {
66+
fn = createWrapper(prog, toSelection(sel), &cr)
67+
} else {
68+
fn = prog.objectMethod(obj, &cr)
69+
}
70+
if fn.Signature.Recv() == nil {
71+
panic(fn)
72+
}
73+
mset.mapping[id] = fn
74+
}
75+
76+
return fn
77+
}()
4878

4979
b := builder{created: &cr}
5080
b.iterate()
@@ -111,54 +141,6 @@ type methodSet struct {
111141
mapping map[string]*Function // populated lazily
112142
}
113143

114-
// Precondition: T is a concrete type, e.g. !isInterface(T) and not parameterized.
115-
// Requires prog.methodsMu.
116-
func (prog *Program) createMethodSet(T types.Type) *methodSet {
117-
if prog.mode&SanityCheckFunctions != 0 {
118-
if types.IsInterface(T) || prog.parameterized.isParameterized(T) {
119-
panic("type is interface or parameterized")
120-
}
121-
}
122-
123-
mset, ok := prog.methodSets.At(T).(*methodSet)
124-
if !ok {
125-
mset = &methodSet{mapping: make(map[string]*Function)}
126-
prog.methodSets.Set(T, mset)
127-
}
128-
return mset
129-
}
130-
131-
// Adds any created functions to cr.
132-
// Precondition: T is a concrete type, e.g. !isInterface(T) and not parameterized.
133-
// Requires prog.methodsMu.
134-
func (prog *Program) addMethod(mset *methodSet, sel *types.Selection, cr *creator) *Function {
135-
if sel.Kind() == types.MethodExpr {
136-
panic(sel)
137-
}
138-
id := sel.Obj().Id()
139-
fn := mset.mapping[id]
140-
if fn == nil {
141-
sel := toSelection(sel)
142-
obj := sel.obj.(*types.Func)
143-
144-
_, ptrObj := deptr(recvType(obj))
145-
_, ptrRecv := deptr(sel.recv)
146-
147-
needsPromotion := len(sel.index) > 1
148-
needsIndirection := !ptrObj && ptrRecv
149-
if needsPromotion || needsIndirection {
150-
fn = createWrapper(prog, sel, cr)
151-
} else {
152-
fn = prog.objectMethod(obj, cr)
153-
}
154-
if fn.Signature.Recv() == nil {
155-
panic(fn) // missing receiver
156-
}
157-
mset.mapping[id] = fn
158-
}
159-
return fn
160-
}
161-
162144
// RuntimeTypes returns a new unordered slice containing all types in
163145
// the program for which a runtime type is required.
164146
//

0 commit comments

Comments
 (0)