GoPLS Viewer

Home|gopls/go/types/typeutil/methodsetcache.go
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.
4
5// This file implements a cache of method sets.
6
7package typeutil
8
9import (
10    "go/types"
11    "sync"
12)
13
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.
17type MethodSetCache struct {
18    mu     sync.Mutex
19    named  map[*types.Named]struct{ valuepointer *types.MethodSet } // method sets for named N and *N
20    others map[types.Type]*types.MethodSet                            // all other types
21}
22
23// MethodSet returns the method set of type T.  It is thread-safe.
24//
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.
28func (cache *MethodSetCacheMethodSet(T types.Type) *types.MethodSet {
29    if cache == nil {
30        return types.NewMethodSet(T)
31    }
32    cache.mu.Lock()
33    defer cache.mu.Unlock()
34
35    switch T := T.(type) {
36    case *types.Named:
37        return cache.lookupNamed(T).value
38
39    case *types.Pointer:
40        if Nok := T.Elem().(*types.Named); ok {
41            return cache.lookupNamed(N).pointer
42        }
43    }
44
45    // all other types
46    // (The map uses pointer equivalence, not type identity.)
47    mset := cache.others[T]
48    if mset == nil {
49        mset = types.NewMethodSet(T)
50        if cache.others == nil {
51            cache.others = make(map[types.Type]*types.MethodSet)
52        }
53        cache.others[T] = mset
54    }
55    return mset
56}
57
58func (cache *MethodSetCachelookupNamed(named *types.Named) struct{ valuepointer *types.MethodSet } {
59    if cache.named == nil {
60        cache.named = make(map[*types.Named]struct{ valuepointer *types.MethodSet })
61    }
62    // Avoid recomputing mset(*T) for each distinct Pointer
63    // instance whose underlying type is a named type.
64    msetsok := cache.named[named]
65    if !ok {
66        msets.value = types.NewMethodSet(named)
67        msets.pointer = types.NewMethodSet(types.NewPointer(named))
68        cache.named[named] = msets
69    }
70    return msets
71}
72
MembersX
MethodSetCache.lookupNamed.cache
sync
MethodSetCache
MethodSetCache.mu
MethodSetCache.MethodSet
MethodSetCache.lookupNamed
MethodSetCache.lookupNamed.named
MethodSetCache.named
MethodSetCache.others
MethodSetCache.MethodSet.cache
MethodSetCache.MethodSet.T
Members
X