mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
gc: tweak and enable escape analysis
-s now means *disable* escape analysis. Fix escape leaks for struct/slice/map literals. Add ... tracking. Rewrite new(T) and slice literal into stack allocation when safe. Add annotations to reflect. Reflect is too chummy with the compiler, so changes like these affect it more than they should. R=lvd, dave, gustavo CC=golang-dev https://golang.org/cl/4954043
This commit is contained in:
parent
2a80882601
commit
db5f9da425
11 changed files with 567 additions and 321 deletions
|
|
@ -322,8 +322,31 @@ func packValue(flag uint32, typ *runtime.Type, word iword) Value {
|
|||
return Value{Internal: *(*interface{})(unsafe.Pointer(&eface))}
|
||||
}
|
||||
|
||||
var dummy struct {
|
||||
b bool
|
||||
x interface{}
|
||||
}
|
||||
|
||||
// Dummy annotation marking that the value x escapes,
|
||||
// for use in cases where the reflect code is so clever that
|
||||
// the compiler cannot follow.
|
||||
func escapes(x interface{}) {
|
||||
if dummy.b {
|
||||
dummy.x = x
|
||||
}
|
||||
}
|
||||
|
||||
// valueFromAddr returns a Value using the given type and address.
|
||||
func valueFromAddr(flag uint32, typ Type, addr unsafe.Pointer) Value {
|
||||
// TODO(rsc): Eliminate this terrible hack.
|
||||
// The escape analysis knows that addr is a pointer
|
||||
// but it doesn't see addr get passed to anything
|
||||
// that keeps it. packValue keeps it, but packValue
|
||||
// takes a uintptr (iword(addr)), and integers (non-pointers)
|
||||
// are assumed not to matter. The escapes function works
|
||||
// because return values always escape (for now).
|
||||
escapes(addr)
|
||||
|
||||
if flag&flagAddr != 0 {
|
||||
// Addressable, so the internal value is
|
||||
// an interface containing a pointer to the real value.
|
||||
|
|
@ -1678,6 +1701,14 @@ func ValueOf(i interface{}) Value {
|
|||
if i == nil {
|
||||
return Value{}
|
||||
}
|
||||
|
||||
// TODO(rsc): Eliminate this terrible hack.
|
||||
// In the call to packValue, eface.typ doesn't escape,
|
||||
// and eface.word is an integer. So it looks like
|
||||
// i (= eface) doesn't escape. But really it does,
|
||||
// because eface.word is actually a pointer.
|
||||
escapes(i)
|
||||
|
||||
// For an interface value with the noAddr bit set,
|
||||
// the representation is identical to an empty interface.
|
||||
eface := *(*emptyInterface)(unsafe.Pointer(&i))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue