- Info.InitOrder now provides list of Initializers
(vars + init expr), handling n:1 decls and blank
identifiers
- added respective API test
- cycles detected through function "mentions"
Missing: cycles through method "mentions" and via
closures
R=adonovan
CC=golang-dev
https://golang.org/cl/21810043
On big corpuses, the indexer was spending most of its time waiting
for filesystem operations (especially with network filesystems)
and not actually indexing. This keeps the filesystem busy and indexer
running in different goroutines.
Also, add a hook to let godoc hosts disable indexing of certain
directories.
And finally, start adding tests for godoc, which required
fleshing out (and testing) the mapfs code.
R=golang-dev, adg, bgarcia
CC=golang-dev
https://golang.org/cl/21520045
The symbolic names such as NOSPLIT for annotations on the TEXT
directive appeared after vet started checking .s files. This CL tweaks
the regular expression to allow CAPITALS and the symbols | and +
as well as digits in that field, and interprets NOSPLIT as equivalent
to 7 in that field. All magic.
Fixesgolang/go#6695
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/18700044
Missing:
- dependencies via functions (incl. closures and methods)
- more tests (incl. API test)
R=adonovan
CC=golang-dev
https://golang.org/cl/20510043
Added test for []*map composite literals containing nested
literal subelements. This required implementing
(reflect.Value).Map{Keys,Index} in ssa/interp.
Plus two minor fixes in ssa/interp.
R=gri
CC=golang-dev
https://golang.org/cl/20470043
This CL makes gotype usable again. Removed -r
(recursive) mode; use go/build to determine
the correct set of Go files when processing
a directory. The -v (verbose) mode now prints
some basic stats (duration, number of files,
lines, and lines/s).
Thoroughly restructured the code.
Applying gotype -v -a . to the go/types directory:
128.94141ms (40 files, 12008 lines, 93127 lines/s)
On a 2.8 GHz Quad-Core Intel Xeon, 800 MHz DDR2 FB-DIMM,
with go/types built with the (interal) debug flag set to
false. There's still quite a bit of room for performance
improvement in all parts of the code since no tuning has
been done.
R=golang-dev, adonovan
CC=golang-dev
https://golang.org/cl/19930043
This makes imports independent of the process's working
directory. (Perhaps this was a feature, but I haven't found a
situation in which it actually works.)
R=gri
CC=golang-dev
https://golang.org/cl/19420043
This lets godoc implementations provide a more efficient means
of getting this information, without reading files and parsing the
package docs.
This is especially important when the files themselves don't
actually exist and the VFS is synthesizing them on demand
(e.g. protocol buffer files -> their generated *.pb.go files).
This means corpus.Init can run quickly, without generating
every protocol file in a large corpus (or fetching it from a
cache).
In the future, this hook could also be used for caching the summaries of
regular packages.
R=golang-dev, adg
CC=golang-dev
https://golang.org/cl/19440043
The implementation follows the basic pattern of an indirect
function call (genDynamicCall).
We use the same trick as SetFinalizer so that direct calls to
(r.V).Call, which are overwhelmingly the norm, are inlined.
Bug fix (and simplification): calling untag() to unbox a
reflect.Value is wrong for reflect.Values containing interfaces
(rare). Now, we call untag for concrete types and typeFilter
for interface types, and we can use this pattern in all cases.
It corresponds to the ssa.TypeAssert operator, so we call
it typeAssert. Added tests to cover this.
We also specialize reflect.{In,Out} when the operand is an int
literal.
+ Tests.
Also:
- make taggedValue() panic, not return nil, eliminating many checks.
We call isTaggedValue for the one place that cares.
- pointer_test: recover from panics in Analyze() and dump the log.
R=crawshaw
CC=golang-dev
https://golang.org/cl/14426050
When computing the time for the "updated" tag of the atom feed, the
current code checks if there is more than one article and if that is
not true, it sets the time to the zero time.Time. This means that
the feed also gets the zero time in this tag when there is exactly one
article.
This trivial patch fixes this so that when there is exactly one
article, the time is set to that article's time.
R=golang-dev, adg
CC=golang-dev
https://golang.org/cl/18420044
Massive win for high-latency network filesystems.
Also benefits the local disk/ssd case too, though.
R=golang-dev, bgarcia
CC=golang-dev
https://golang.org/cl/18650043
reflect.Values may point to tagged objects with
interface type, e.g. x := reflect.ValueOf(new(interface{})).Elem().
We failed to consider this when implementing Elem.
Also, (reflect.Value).Interface() must do one "unboxing"
when it encounters such tagged objects.
i.e., x.Elem().Interface() and x.Interface() are equivalent
in that case.
Also:
- add example of tagged object with interface type.
- untabify (Label).String docstring.
- added tests.
R=crawshaw
CC=golang-dev
https://golang.org/cl/18020044
The blog code is quite generic and with the replacement of template and
static files, it can be re-used. But the atom feed title is hard-coded
into the code. This patch adds a field to set the atom feed title to
the Config structure and uses it in the code where the title was
previously hard-coded.
A CL sent separately will set this Config field in the main package in
the go.blog sub-repository. (See CL 16850043 for that other patch).
R=golang-dev, adg
CC=golang-dev
https://golang.org/cl/16830043
- better error messages
- in contrast to a long-standing TODO, comparisons
between interface and non-interface types always
worked correctly
R=adonovan
CC=golang-dev
https://golang.org/cl/17310043
A DebugRef associates a source expression E with an ssa.Value
V, but until now did not record whether V was the value or the
address of E. So, we would guess from the "pointerness" of
the Value, leading to confusion in some cases, e.g.
type N *N
var n N
n = &n // lvalue and rvalue are both pointers
Now we explicitly record 'IsAddress bool' in DebugRef, and
plumb this everywhere: through (*Function).ValueForExpr and
(*Program).VarValue, all the way to forming the pointer
analysis query.
Also:
- VarValue now treats each reference to a global distinctly,
just like it does for other vars. So:
var g int
func f() {
g = 1 // VarValue(g) == Const(1:int), !isAddress
print(g) // VarValue(g) == Global(g), isAddress
}
- DebugRefs are not emitted for references to predeclared
identifiers (nil, built-in).
- DebugRefs no longer prevent lifting of an Alloc var into a
register; now we update or discard the debug info.
- TestValueForExpr: improve coverage of ssa.EnclosingFunction
by putting expectations in methods and init funcs, not just
normal funcs.
- oracle: fix golden file broken by recent
(*types.Var).IsField change.
R=gri
CC=golang-dev
https://golang.org/cl/16610045
The spec does not exclude blank _ method names in interfaces
from the uniqueness criteria; i.e., at most one blank method
may appear in an interface type.
Arguably the spec is vague (and possibly incorrect) here.
gccgo handles it the same way. gc crashes with an internal
compiler error.
R=adonovan
CC=golang-dev
https://golang.org/cl/16380043
This allows us to run/analyze multiple tests.
Also it causes the production code packages to be properly initialized.
Also:
- cmd/ssadump: improved usage message (add example;
incorporate LoadInitialPackages usage; explain how -run
finds main).
- pointer, oracle, ssa/interp: use CreateTestMainPackage.
- ssa/builder.go: remove 'rundefers' instruction from package init,
which no longer uses 'defer'.
R=gri
CC=golang-dev
https://golang.org/cl/15920047
Motivation:
Previously, we assumed that the set of types for which a
complete method set (containing all synthesized wrapper
functions) is required at runtime was the set of types
used as operands to some *ssa.MakeInterface instruction.
In fact, this is an underapproximation because types can
be derived from other ones via reflection, and some of
these may need methods. The reflect.Type API allows *T to
be derived from T, and these may have different method
sets. Reflection also allows almost any subcomponent of a
type to be accessed (with one exception: given T, defined
'type T struct{S}', you can reach S but not struct{S}).
As a result, the pointer analysis was unable to generate
all necessary constraints before running the solver,
causing a crash when reflection derives types whose
methods are unavailable. (A similar problem would afflict
an ahead-of-time compiler based on ssa. The ssa/interp
interpreter was immune only because it does not require
all wrapper methods to be created before execution
begins.)
Description:
This change causes the SSA builder to record, for each
package, the set of all types with non-empty method sets that
are referenced within that package. This set is accessed via
Packages.TypesWithMethodSets(). Program.TypesWithMethodSets()
returns its union across all packages.
The set of references that matter are:
- types of operands to some MakeInterface instruction (as before)
- types of all exported package members
- all subcomponents of the above, recursively.
This is a conservative approximation to the set of types
whose methods may be called dynamically.
We define the owning package of a type as follows:
- the owner of a named type is the package in which it is defined;
- the owner of a pointer-to-named type is the owner of that named type;
- the owner of all other types is nil.
A package must include the method sets for all types that it
owns, and all subcomponents of that type that are not owned by
another package, recursively. Types with an owner appear in
exactly one package; types with no owner (such as struct{T})
may appear within multiple packages.
(A typical Go compiler would emit multiple copies of these
methods as weak symbols; a typical linker would eliminate
duplicates.)
Also:
- go/types/typemap: implement hash function for *Tuple.
- pointer: generate nodes/constraints for all of
ssa.Program.TypesWithMethodSets().
Add rtti.go regression test.
- Add API test of Package.TypesWithMethodSets().
- Set Function.Pkg to nil (again) for wrapper functions,
since these may be shared by many packages.
- Remove a redundant logging statement.
- Document that ssa CREATE phase is in fact sequential.
Fixesgolang/go#6605
R=gri
CC=golang-dev
https://golang.org/cl/14920056
Support for:
(*reflect.rtype).Field
(*reflect.rtype).FieldByName
reflect.MakeSlice
runtime.SetFinalizer
Details:
- analysis locates ssa.Functions for (reflect.Value).Call
and runtime.SetFinalizer during startup to that it can
special-case them during genCall. ('Call' is forthcoming.)
- The callsite.targets mechanism is only used for dynamic
calls now. For static calls we call callEdge during constraint
generation; this is a minor optimisation.
- Static calls to SetFinalizer are inlined so that the call
appears to go direct to the finalizer. (We'll use the same
trick for (reflect.Value).Call.)
- runtime.FuncForPC: treat as a no-op.
- Fixed pointer_test to properly deal with expectations
that are multi-sets.
- Inlined rtypeMethodByNameConstraint.addMethod.
- More tests.
R=crawshaw
CC=golang-dev
https://golang.org/cl/14682045
This will make it a bit easier to create commonly used "custom" sizes for types.
With this CL, interfaces are now by default 2*WordSize (= 16) instead of 1*WordSize
as before.
Also: minor unrelated cleanups.
R=adonovan
CC=golang-dev
https://golang.org/cl/14719043
A function such as this:
func one() (x int) {
defer func() { recover() }()
x = 1
panic("return")
}
that combines named return parameters (NRPs) with deferred calls
that call recover, may return non-zero values despite the
fact it doesn't even contain a return statement. (!)
This requires a change to the SSA API: all functions'
control-flow graphs now have a second entry point, called
Recover, which is the block at which control flow resumes
after a recovered panic. The Recover block simply loads the
NRPs and returns them.
As an optimization, most functions don't need a Recover block,
so it is omitted. In fact it is only needed for functions that
have NRPs and defer a call to another function that _may_ call
recover.
Dataflow analysis of SSA now requires extra work, since every
may-panic instruction has an implicit control-flow edge to
the Recover block. The only dataflow analysis so far implemented
is SSA renaming, for which we make the following simplifying
assumption: the Recover block only loads the NRPs and returns.
This means we don't really need to analyze it, we can just
skip the "lifting" of such NRPs. We also special-case the Recover
block in the dominance computation.
Rejected alternative approaches:
- Specifying a Recover block for every defer instruction (like a
traditional exception handler).
This seemed like excessive generality, since Go programs
only need the same degenerate form of Recover block.
- Adding an instruction to set the Recover block immediately
after the named return values are set up, so that dominance
can be computed without special-casing.
This didn't seem worth the effort.
Interpreter:
- This CL completely reimplements the panic/recover/
defer logic in the interpreter. It's clearer and simpler
and closer to the model in the spec.
- Some runtime panic messages have been changed to be closer
to gc's, since tests depend on it.
- The interpreter now requires that the runtime.runtimeError
type be part of the SSA program. This requires that clients
import this package prior to invoking the interpreter.
This in turn requires (Importer).ImportPackage(path string),
which this CL adds.
- All $GOROOT/test/recover{,1,2,3}.go tests are now passing.
NB, the bug described in coverage.go (defer/recover in a concatenated
init function) remains. Will be fixed in a follow-up.
Fixesgolang/go#6381
R=gri
CC=crawshaw, golang-dev
https://golang.org/cl/13844043
Before, we would concatenate all the init() blocks together,
resulting in incorrect treatment of a recovered panic in one
init block: the implicit return would cause the subsequent ones
to be skipped.
The result is simpler, and closer to what gc does.
The additional functions are visible in the call graph,
so some tests required updating.
R=gri
CC=crawshaw, golang-dev
https://golang.org/cl/14671044
Various reflect operations permit assignability conversions,
i.e. their internals behave unlike y=x.(T) which unpacks only
those interface values in x that are identical to T.
We split typeAssertConstraint y=x.(T) into two constraints:
1) typeFilter, for when T is an interface type and no
representation change occurs.
2) unpack, for when T is a concrete type and the payload of the
tagged object is extracted. This constraint has an 'exact'
parameter indicating whether to use the predicate
IsIdentical (for type assertions) or
IsAssignable (for reflect operators).
+ Tests.
R=crawshaw
CC=golang-dev
https://golang.org/cl/14547043