diff --git a/src/cmd/compile/internal/types/size.go b/src/cmd/compile/internal/types/size.go index 397819309d..e655a3672d 100644 --- a/src/cmd/compile/internal/types/size.go +++ b/src/cmd/compile/internal/types/size.go @@ -184,6 +184,13 @@ func calcStructOffset(errtype *Type, t *Type, o int64, flag int) int64 { } CalcSize(f.Type) + // If type T contains a field F marked as not-in-heap, + // then T must also be a not-in-heap type. Otherwise, + // you could heap allocate T and then get a pointer F, + // which would be a heap pointer to a not-in-heap type. + if f.Type.NotInHeap() { + t.SetNotInHeap(true) + } if int32(f.Type.align) > maxalign { maxalign = int32(f.Type.align) } @@ -391,6 +398,7 @@ func CalcSize(t *Type) { } CalcSize(t.Elem()) + t.SetNotInHeap(t.Elem().NotInHeap()) if t.Elem().width != 0 { cap := (uint64(MaxWidth) - 1) / uint64(t.Elem().width) if uint64(t.NumElem()) > cap { @@ -412,6 +420,10 @@ func CalcSize(t *Type) { if t.IsFuncArgStruct() { base.Fatalf("CalcSize fn struct %v", t) } + // Recognize and mark runtime/internal/sys.nih as not-in-heap. + if sym := t.Sym(); sym != nil && sym.Pkg.Path == "runtime/internal/sys" && sym.Name == "nih" { + t.SetNotInHeap(true) + } w = calcStructOffset(t, t, 0, 1) // make fake type to check later to diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index 9e229a59c6..a69245ea69 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -625,7 +625,6 @@ func NewArray(elem *Type, bound int64) *Type { } t := newType(TARRAY) t.extra = &Array{Elem: elem, Bound: bound} - t.SetNotInHeap(elem.NotInHeap()) if elem.HasTParam() { t.SetHasTParam(true) } @@ -1061,17 +1060,6 @@ func (t *Type) SetFields(fields []*Field) { base.Fatalf("SetFields of %v: width previously calculated", t) } t.wantEtype(TSTRUCT) - for _, f := range fields { - // If type T contains a field F with a go:notinheap - // type, then T must also be go:notinheap. Otherwise, - // you could heap allocate T and then get a pointer F, - // which would be a heap pointer to a go:notinheap - // type. - if f.Type != nil && f.Type.NotInHeap() { - t.SetNotInHeap(true) - break - } - } t.Fields().Set(fields) } @@ -1676,7 +1664,7 @@ func (t *Type) IsUntyped() bool { } // HasPointers reports whether t contains a heap pointer. -// Note that this function ignores pointers to go:notinheap types. +// Note that this function ignores pointers to not-in-heap types. func (t *Type) HasPointers() bool { return PtrDataSize(t) > 0 } diff --git a/src/runtime/internal/sys/nih.go b/src/runtime/internal/sys/nih.go index 2e3c9794e6..17eab67345 100644 --- a/src/runtime/internal/sys/nih.go +++ b/src/runtime/internal/sys/nih.go @@ -4,9 +4,8 @@ package sys -// TODO: make this as a compiler intrinsic type, and remove go:notinheap -// -//go:notinheap +// NOTE: keep in sync with cmd/compile/internal/types.CalcSize +// to make the compiler recognize this as an intrinsic type. type nih struct{} // NotInHeap is a type must never be allocated from the GC'd heap or on the stack,