]> Cypherpunks.ru repositories - gostls13.git/commit
go/types, types2: make each method instantiation independently lazy
authorRobert Findley <rfindley@google.com>
Mon, 24 Jan 2022 15:37:59 +0000 (10:37 -0500)
committerRobert Findley <rfindley@google.com>
Tue, 25 Jan 2022 21:57:38 +0000 (21:57 +0000)
commitb66bc0a9d5eba193f7d7f4977ca64a77527f4b3b
treebf0ad6acc6d214e80b261b8fb4a930260ef966e0
parent078ddecc327a20cec4751e66911197409e01f6d9
go/types, types2: make each method instantiation independently lazy

Method signatures can introduce a significant number of edges into the
type graph. One can imagine a generic type with many methods, each of
which may use other instantiated types, etc. For performance, when type
checking generic code, we should avoid unnecessary instantiation of
methods wherever possible.

This CL achieves this by making method instantiation lazy at the
individual method level. It abstracts method access into a methodList
type, which may be either eager or lazy. In the lazy case, methods are
only instantiated when they are accessed via the Named.Method,
MethodSet, or LookupFieldOrMethod APIs. Factoring out a methodList type
makes it easier to verify that we're not leaking the methods slice
anywhere, and as a side benefit reduces the size of *Named types in the
case where there are no methods. The effective memory footprint of Named
types with methods increases by a pointer (to hold the slice of guards),
and the footprint of instantiated named types increases additionally by
a sync.Once per method. We estimate that this memory increase is more
than offset by the reduction in the number of instantiated methods.

This also simplifies the code. Previously we had to work around the fact
that named type expansion could occur before all signatures were set-up,
by stashing the instantiated receiver into a partially filled-out *Func.
With fully lazy methods, we can rely on the invariant that any use of
methods in valid code can only occur after all signatures can be type
checked. This means that we can fully instantiate the *Func, and don't
need to deal with partially instantiated stubs.

Finally, this CL fixes a bug (issue #50619), where traversing
Method->Receiver Type->Method did not get us back where we started. This
is fixed by not instantiating a new method if t is already the receiver
base of the original method.

A test is added to explicitly verify the invariant above, and more test
cases are added for the behavior of Info with respect to generic code.

Fixes #50619

Change-Id: I5b6d2bdc4404c9f5dcb583a29cb64e8af9794c54
Reviewed-on: https://go-review.googlesource.com/c/go/+/380499
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
Reviewed-by: Robert Griesemer <gri@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
21 files changed:
src/cmd/compile/internal/types2/api_test.go
src/cmd/compile/internal/types2/decl.go
src/cmd/compile/internal/types2/instantiate.go
src/cmd/compile/internal/types2/lookup.go
src/cmd/compile/internal/types2/methodlist.go [new file with mode: 0644]
src/cmd/compile/internal/types2/methodlist_test.go [new file with mode: 0644]
src/cmd/compile/internal/types2/named.go
src/cmd/compile/internal/types2/object.go
src/cmd/compile/internal/types2/sizeof_test.go
src/cmd/compile/internal/types2/typexpr.go
src/go/types/api_test.go
src/go/types/decl.go
src/go/types/instantiate.go
src/go/types/lookup.go
src/go/types/methodlist.go [new file with mode: 0644]
src/go/types/methodlist_test.go [new file with mode: 0644]
src/go/types/methodset.go
src/go/types/named.go
src/go/types/object.go
src/go/types/sizeof_test.go
src/go/types/typexpr.go