Until now, the same Function was used to represent a method
(T)func() and the "method expression" function func(T) formed
from it. So the SSA code for this:
var buf bytes.Buffer
f := Buffer.Bytes
f(buf)
buf.Bytes()
would involve an implicit cast (ChangeType) on line 2.
However, compilers based on go/ssa may want to use different
calling conventions for them, like gccgo does (see issue
7839). This change decouples them by using an anonymous
function called a "thunk", rather like this:
f := func(r *bytes.Buffer) []byte { return r.Bytes() }
Thunks are similar to method wrappers; both are created by
makeWrapper.
"Interface method wrappers" were a special case of thunks for
direct calls (no indirection/fields) of interface methods.
They are now subsumed by thunks and have been deleted. Now
that only the needed thunks are built, we don't need to
populate the concrete method sets of interface types at all,
so (*Program).Method and LookupMethod return nil for them.
This results in a slight reduction in function count (>1%) and
instruction count (<<1%).
Details:
go/ssa:
- API: ChangeType no longer supports func/method conversions.
- API: (*Program).FuncValue now returns nil for abstract
(interface) methods.
- API: (*Function).RelString simplified.
"$bound" is now a suffix not a prefix, and the receiver
type is rendered package-relative.
- API: Function.Object is now defined for all wrappers too.
- API: (*Program).Method and LookupMethod return nil for
abstract methods.
- emitConv no longer permits (non-identical)
Signature->Signature conversions. Added assertion.
- add and use isInterface helper
- sanity: we check packages after Build, not Create, otherwise
cross-package refs might fail.
go/pointer:
- update tests for new function strings.
- pointer_test: don't add non-pointerlike probes to analysis.
(The error was checked, but too late, causing a panic.)
- fixed a minor bug: if a test probe print(x) was the sole
reference to x, no nodes were generated for x.
- (reflect.Type).MethodByName: updated due to ssa API changes.
Also, fixed incorrect testdata/funcreflect.go expectation
for MethodByName on interfaces.
oracle:
- fix for new FuncValue semantics.
- a "pointsto" query on an I.f thunk now returns an error.
Fixesgolang/go#7839
LGTM=gri
R=gri
CC=golang-codereviews, pcc
https://golang.org/cl/93780044
Observation: not all alias facts are interesting.
- A channel-peers query also cares about pointers of kind chan.
- An oracle "points-to" query on an expression of kind map
only cares about maps.
- We always care about func, interface and reflect.Value,
since they're needed for sound analysis of dynamic dispatch.
We needn't bother collecting alias information for
uninteresting pointers, and this massively reduces the number
of labels flowing in to the constraint system.
The only constraints that create new labels are addressOf
and offsetAddr; both are now selectively emitted by type.
We compute the set of type kinds to track, based on the
{Indirect,}Query types. (We could enable tracking at an
even finer grain if we want.)
This requires that we can see all the {Indirect,}Query
value types a priori, which is not the case for the PrintCalls
mechanism used in the tests, so I have rewritten the latter
to use {Indirect,}Query instead.
This reduces the solver-phase time for the entire standard
library and tests from >8m to <2m. Similar speedups are
obtained on small and medium-sized programs.
Details:
- shouldTrack inspects the flattened form of a type to see if
it contains fields we must track. It memoizes the result.
- added precondition checks to (*Config).Add{,Indirect}Query.
- added (*ssa.Program).LookupMethod convenience method.
- added Example of how to use the Query mechanism.
- removed code made dead by a recent invariant:
the only pointerlike Const value is nil.
- don't generate constraints for any functions in "reflect".
(we had forgotten to skip synthetic wrappers too).
- write PTA warnings to the log.
- add annotations for more intrinsics.
LGTM=gri, crawshaw
R=crawshaw, gri
CC=golang-codereviews
https://golang.org/cl/62540043
Method-set caching is now performed externally using a MethodSetCache (if desired), not by the Types themselves.
This a minor deoptimization due to the extra maps, but avoids a situation in which method-sets are computed and frozen prematurely. (See b/7114)
LGTM=gri
R=gri
CC=golang-codereviews
https://golang.org/cl/61430045