1 // Copyright 2014 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // This file implements a cache of method sets.
14 // A MethodSetCache records the method set of each type T for which
15 // MethodSet(T) is called so that repeat queries are fast.
16 // The zero value is a ready-to-use cache instance.
17 type MethodSetCache struct {
19 named map[*types.Named]struct{ value, pointer *types.MethodSet } // method sets for named N and *N
20 others map[types.Type]*types.MethodSet // all other types
23 // MethodSet returns the method set of type T. It is thread-safe.
25 // If cache is nil, this function is equivalent to types.NewMethodSet(T).
26 // Utility functions can thus expose an optional *MethodSetCache
27 // parameter to clients that care about performance.
29 func (cache *MethodSetCache) MethodSet(T types.Type) *types.MethodSet {
31 return types.NewMethodSet(T)
34 defer cache.mu.Unlock()
36 switch T := T.(type) {
38 return cache.lookupNamed(T).value
41 if N, ok := T.Elem().(*types.Named); ok {
42 return cache.lookupNamed(N).pointer
47 // (The map uses pointer equivalence, not type identity.)
48 mset := cache.others[T]
50 mset = types.NewMethodSet(T)
51 if cache.others == nil {
52 cache.others = make(map[types.Type]*types.MethodSet)
54 cache.others[T] = mset
59 func (cache *MethodSetCache) lookupNamed(named *types.Named) struct{ value, pointer *types.MethodSet } {
60 if cache.named == nil {
61 cache.named = make(map[*types.Named]struct{ value, pointer *types.MethodSet })
63 // Avoid recomputing mset(*T) for each distinct Pointer
64 // instance whose underlying type is a named type.
65 msets, ok := cache.named[named]
67 msets.value = types.NewMethodSet(named)
68 msets.pointer = types.NewMethodSet(types.NewPointer(named))
69 cache.named[named] = msets