Skip to content

cmd/compile: bad liveness map #20029

@randall77

Description

@randall77
package main

import "runtime"

func f(m map[int]int) {
outer:
        for i := 0; i < 10; i++ {
                for k := range m {
                        if k == 5 {
                                continue outer
                        }
                }
                runtime.GC()
                break
        }
        runtime.GC()
}
$ go tool compile -live tmp1.go
tmp1.go:5:18: live at entry to f: m
tmp1.go:8:12: live at call to mapiterinit: m .autotmp_4
tmp1.go:8:12: live at call to mapiternext: m .autotmp_4
tmp1.go:16:12: f: .autotmp_4 (type map.iter[int]int) is ambiguously live
tmp1.go:16:12: live at call to GC: .autotmp_4

The hiter for the inner loop (.autotmp_4) should not be live at the outer runtime.GC. It is live because liveness analysis sort of gives up on it (the "ambiguously live" comment there).
That's not so bad in and of itself; it's just imprecise.

But at the end of the inner loop we issue a VARKILL of .autotmp_4, so it definitely isn't live at the first runtime.GC (nothing with a pointer is live at that call, so it isn't even listed by -live). That means .autotmp_4 is live, then it isn't, then it is again. The first runtime.GC will free m, as nothing is holding m live at this point. The second runtime.GC finds m inside .autotmp_4 and tries to scan an already freed map. Boom.

This seems like a bad interaction between ambiguously live and VARKILL. Maybe fundamentally bad. Time to put my pondering cap on...

@aclements

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions