mirror of
https://github.com/golang/go
synced 2024-11-23 07:20:06 -07:00
77527a316b
This adds a //go:notinheap pragma for declarations of types that must not be heap allocated. We ensure these rules by disallowing new(T), make([]T), append([]T), or implicit allocation of T, by disallowing conversions to notinheap types, and by propagating notinheap to any struct or array that contains notinheap elements. The utility of this pragma is that we can eliminate write barriers for writes to pointers to go:notinheap types, since the write barrier is guaranteed to be a no-op. This will let us mark several scheduler and memory allocator structures as go:notinheap, which will let us disallow write barriers in the scheduler and memory allocator much more thoroughly and also eliminate some problematic hybrid write barriers. This also makes go:nowritebarrierrec and go:yeswritebarrierrec much more powerful. Currently we use go:nowritebarrier all over the place, but it's almost never what you actually want: when write barriers are illegal, they're typically illegal for a whole dynamic scope. Partly this is because go:nowritebarrier has been around longer, but it's also because go:nowritebarrierrec couldn't be used in situations that had no-op write barriers or where some nested scope did allow write barriers. go:notinheap eliminates many no-op write barriers and go:yeswritebarrierrec makes it possible to opt back in to write barriers, so these two changes will let us use go:nowritebarrierrec far more liberally. This updates #13386, which is about controlling pointers from non-GC'd memory to GC'd memory. That would require some additional pragma (or pragmas), but could build on this pragma. Change-Id: I6314f8f4181535dd166887c9ec239977b54940bd Reviewed-on: https://go-review.googlesource.com/30939 Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
44 lines
708 B
Go
44 lines
708 B
Go
// errorcheck -+
|
|
|
|
// Copyright 2016 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// Test walk errors for go:notinheap.
|
|
|
|
package p
|
|
|
|
//go:notinheap
|
|
type nih struct {
|
|
next *nih
|
|
}
|
|
|
|
// Globals and stack variables are okay.
|
|
|
|
var x nih
|
|
|
|
func f() {
|
|
var y nih
|
|
x = y
|
|
}
|
|
|
|
// Heap allocation is not okay.
|
|
|
|
var y *nih
|
|
var z []nih
|
|
|
|
func g() {
|
|
y = new(nih) // ERROR "heap allocation disallowed"
|
|
z = make([]nih, 1) // ERROR "heap allocation disallowed"
|
|
z = append(z, x) // ERROR "heap allocation disallowed"
|
|
}
|
|
|
|
// Writes don't produce write barriers.
|
|
|
|
var p *nih
|
|
|
|
//go:nowritebarrier
|
|
func h() {
|
|
y.next = p.next
|
|
}
|