-
Notifications
You must be signed in to change notification settings - Fork 18.4k
Description
What version of Go are you using (go version
)?
$ go version 1.16.3
Does this issue reproduce with the latest release?
Yes.
What operating system and processor architecture are you using (go env
)?
go env
Output
$ go env GOHOSTARCH="amd64" GOHOSTOS="darwin"
What did you do?
Run go pointer analysis under the directory /grpc-go/examples/features/xds/client (master with commit e38032e927812bb354297adcab933bedeff6c177) to analyze the main.go file. I do not think the commit is a necessary, probably the code from recent master is also able to reproduce the issue. I used the program below to run pointer analysis:
func main() {
cfg := &packages.Config{
Mode: packages.LoadAllSyntax, // the level of information returned for each package
Dir: "", // directory in which to run the build system's query tool
Tests: false, // setting Tests will include related test packages
}
initial, err := packages.Load(cfg)
if err != nil {
panic(fmt.Sprintln(err))
}
prog, pkgs := ssautil.AllPackages(initial, 0)
prog.Build()
mains, err := findMainPackages(pkgs)
if err != nil {
return
}
logfile, _ := os.Create("/Users/bozhen/Documents/GO2/default-x-tools/_logs/my_log_0") //replace with your log
config := &pointer.Config{
Mains: mains,
BuildCallGraph: true,
Reflection: false,
Log: logfile,
}
result, err := pointer.Analyze(config)
if err != nil {
panic(err) // internal error in pointer analysis
}
cg := result.CallGraph
fmt.Println(cg)
}
func findMainPackages(pkgs []*ssa.Package) ([]*ssa.Package, error) {
var mains []*ssa.Package
for _, p := range pkgs {
if p.Pkg.Name() == "main" && p.Func("main") != nil {
mains = append(mains, p)
}
}
if len(mains) == 0 {
return nil, fmt.Errorf("no main packages")
}
return mains, nil
}
What did you expect to see?
In the log, the constraints generated for IR statementt40 = next t34
in function (*google.golang.org/grpc/xds/internal/balancer/edsbalancer.balancerGroup).close
should be:
; t40 = next t34
localobj[t33] = n0
load n319631 <- n319625[4]
where n319631 (the base pointer of the load) is from "Creating nodes for local values":
create n319629 bool for t40#0
create n319630 invalid type for t40#1
create n319631 *google.golang.org/grpc/xds/internal/balancer/edsbalancer.subBalancerWithConfig for t40#2
val[t40] = n319629 (*ssa.Next)
What did you see instead?
Instead, the generated constraints are:
; t40 = next t34
localobj[t33] = n0
load n319634 <- n319625[4]
where n319634 is from a irrelevant local variable at the begging of this function:
; *t4 = false:bool
create n319634 bool for false:bool
globalobj[false:bool] = n0
val[false:bool] = n319634 (*ssa.Const)
store n319598[0] <- n319634
I copied the grpc function here with which source code the above two IR statements mapped to:
func (bg *balancerGroup) close() {
bg.incomingMu.Lock()
if bg.incomingStarted { // !! this maps to IR: *t4 = false:bool
bg.incomingStarted = false
for _, pState := range bg.idToPickerState {
// Reset everything to IDLE but keep the entry in map (to keep the
// weight).
pState.picker = nil
pState.state = connectivity.Idle
}
// Also remove all SubConns.
for sc := range bg.scToSubBalancer {
bg.cc.RemoveSubConn(sc)
delete(bg.scToSubBalancer, sc)
}
}
bg.incomingMu.Unlock()
bg.outgoingMu.Lock()
if bg.outgoingStarted {
bg.outgoingStarted = false
for _, config := range bg.idToBalancerConfig { // !! this maps to IR: t40 = next t34
config.stopBalancer()
}
}
bg.outgoingMu.Unlock()
// Clear(true) runs clear function to close sub-balancers in cache. It
// must be called out of outgoing mutex.
bg.balancerCache.Clear(true)
}
So, why is the node for t40 replaced by the node for t4 in the generated constraints, if my understanding is correct?
I checked the source code a little bit, found that the wrong mapping is because of the computation of odst += ksize
when generating constraints for *ssa.Next and the key type is invalid (the code is at go/pointer/gen.go:1078 of the most recent commit when I submit this issue). Should not this be odst += 1
? Because the algorithm only creates three pointers/nodes for this *ssa.Next instruction: ok, key and value. There is no flatten copy for key or value pointers. So, if the key type is invalid, shouldn't it skip this key node and use the value node (+= 1) as the load base, since the value will be extract later?
Thanks.