@@ -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