mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile: add sizeCalculationDisabled flag
Use it to ensure that dowidth is not called from the backend on a type whose size has not yet been calculated. This is an alternative to CL 42016. Change-Id: I8c7b4410ee4c2a68573102f6b9b635f4fdcf392e Reviewed-on: https://go-review.googlesource.com/42018 Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
dae5389d3d
commit
c51559813f
4 changed files with 22 additions and 15 deletions
|
|
@ -9,6 +9,10 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// sizeCalculationDisabled indicates whether it is safe
|
||||||
|
// to calculate Types' widths and alignments. See dowidth.
|
||||||
|
var sizeCalculationDisabled bool
|
||||||
|
|
||||||
// machine size and rounding alignment is dictated around
|
// machine size and rounding alignment is dictated around
|
||||||
// the size of a pointer, set in betypeinit (see ../amd64/galign.go).
|
// the size of a pointer, set in betypeinit (see ../amd64/galign.go).
|
||||||
var defercalc int
|
var defercalc int
|
||||||
|
|
@ -151,6 +155,10 @@ func widstruct(errtype *types.Type, t *types.Type, o int64, flag int) int64 {
|
||||||
return o
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// dowidth calculates and stores the size and alignment for t.
|
||||||
|
// If sizeCalculationDisabled is set, and the size/alignment
|
||||||
|
// have not already been calculated, it calls Fatal.
|
||||||
|
// This is used to prevent data races in the back end.
|
||||||
func dowidth(t *types.Type) {
|
func dowidth(t *types.Type) {
|
||||||
if Widthptr == 0 {
|
if Widthptr == 0 {
|
||||||
Fatalf("dowidth without betypeinit")
|
Fatalf("dowidth without betypeinit")
|
||||||
|
|
@ -174,6 +182,10 @@ func dowidth(t *types.Type) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if sizeCalculationDisabled {
|
||||||
|
Fatalf("width not calculated: %v", t)
|
||||||
|
}
|
||||||
|
|
||||||
// break infinite recursion if the broken recursive type
|
// break infinite recursion if the broken recursive type
|
||||||
// is referenced again
|
// is referenced again
|
||||||
if t.Broke() && t.Width == 0 {
|
if t.Broke() && t.Width == 0 {
|
||||||
|
|
|
||||||
|
|
@ -254,6 +254,7 @@ func compileSSA(fn *Node, worker int) {
|
||||||
// and waits for them to complete.
|
// and waits for them to complete.
|
||||||
func compileFunctions() {
|
func compileFunctions() {
|
||||||
if len(compilequeue) != 0 {
|
if len(compilequeue) != 0 {
|
||||||
|
sizeCalculationDisabled = true // not safe to calculate sizes concurrently
|
||||||
if raceEnabled {
|
if raceEnabled {
|
||||||
// Randomize compilation order to try to shake out races.
|
// Randomize compilation order to try to shake out races.
|
||||||
tmp := make([]*Node, len(compilequeue))
|
tmp := make([]*Node, len(compilequeue))
|
||||||
|
|
@ -287,6 +288,7 @@ func compileFunctions() {
|
||||||
close(c)
|
close(c)
|
||||||
compilequeue = nil
|
compilequeue = nil
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
sizeCalculationDisabled = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1519,8 +1519,8 @@ func (s *state) expr(n *Node) *ssa.Value {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
from.AssertWidthCalculated()
|
dowidth(from)
|
||||||
to.AssertWidthCalculated()
|
dowidth(to)
|
||||||
if from.Width != to.Width {
|
if from.Width != to.Width {
|
||||||
s.Fatalf("CONVNOP width mismatch %v (%d) -> %v (%d)\n", from, from.Width, to, to.Width)
|
s.Fatalf("CONVNOP width mismatch %v (%d) -> %v (%d)\n", from, from.Width, to, to.Width)
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -2321,7 +2321,7 @@ func (s *state) assign(left *Node, right *ssa.Value, deref bool, skip skipMask)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t := left.Type
|
t := left.Type
|
||||||
t.AssertWidthCalculated()
|
dowidth(t)
|
||||||
if s.canSSA(left) {
|
if s.canSSA(left) {
|
||||||
if deref {
|
if deref {
|
||||||
s.Fatalf("can SSA LHS %v but not RHS %s", left, right)
|
s.Fatalf("can SSA LHS %v but not RHS %s", left, right)
|
||||||
|
|
@ -3095,7 +3095,7 @@ func (s *state) call(n *Node, k callKind) *ssa.Value {
|
||||||
}
|
}
|
||||||
rcvr = s.newValue1(ssa.OpIData, types.Types[TUINTPTR], i)
|
rcvr = s.newValue1(ssa.OpIData, types.Types[TUINTPTR], i)
|
||||||
}
|
}
|
||||||
fn.Type.AssertWidthCalculated()
|
dowidth(fn.Type)
|
||||||
stksize := fn.Type.ArgWidth() // includes receiver
|
stksize := fn.Type.ArgWidth() // includes receiver
|
||||||
|
|
||||||
// Run all argument assignments. The arg slots have already
|
// Run all argument assignments. The arg slots have already
|
||||||
|
|
@ -3351,7 +3351,7 @@ func (s *state) canSSA(n *Node) bool {
|
||||||
|
|
||||||
// canSSA reports whether variables of type t are SSA-able.
|
// canSSA reports whether variables of type t are SSA-able.
|
||||||
func canSSAType(t *types.Type) bool {
|
func canSSAType(t *types.Type) bool {
|
||||||
t.AssertWidthCalculated()
|
dowidth(t)
|
||||||
if t.Width > int64(4*Widthptr) {
|
if t.Width > int64(4*Widthptr) {
|
||||||
// 4*Widthptr is an arbitrary constant. We want it
|
// 4*Widthptr is an arbitrary constant. We want it
|
||||||
// to be at least 3*Widthptr so slices can be registerized.
|
// to be at least 3*Widthptr so slices can be registerized.
|
||||||
|
|
@ -4972,7 +4972,7 @@ func (e *ssafn) namedAuto(name string, typ ssa.Type, pos src.XPos) ssa.GCNode {
|
||||||
n.Esc = EscNever
|
n.Esc = EscNever
|
||||||
n.Name.Curfn = e.curfn
|
n.Name.Curfn = e.curfn
|
||||||
e.curfn.Func.Dcl = append(e.curfn.Func.Dcl, n)
|
e.curfn.Func.Dcl = append(e.curfn.Func.Dcl, n)
|
||||||
t.AssertWidthCalculated()
|
dowidth(t)
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -849,13 +849,6 @@ func (t *Type) WidthCalculated() bool {
|
||||||
return t.Align > 0
|
return t.Align > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// AssertWidthCalculated calls Fatalf if t's width has not yet been calculated.
|
|
||||||
func (t *Type) AssertWidthCalculated() {
|
|
||||||
if !t.WidthCalculated() {
|
|
||||||
Fatalf("width not calculated: %v", t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ArgWidth returns the total aligned argument size for a function.
|
// ArgWidth returns the total aligned argument size for a function.
|
||||||
// It includes the receiver, parameters, and results.
|
// It includes the receiver, parameters, and results.
|
||||||
func (t *Type) ArgWidth() int64 {
|
func (t *Type) ArgWidth() int64 {
|
||||||
|
|
@ -864,12 +857,12 @@ func (t *Type) ArgWidth() int64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Type) Size() int64 {
|
func (t *Type) Size() int64 {
|
||||||
t.AssertWidthCalculated()
|
Dowidth(t)
|
||||||
return t.Width
|
return t.Width
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Type) Alignment() int64 {
|
func (t *Type) Alignment() int64 {
|
||||||
t.AssertWidthCalculated()
|
Dowidth(t)
|
||||||
return int64(t.Align)
|
return int64(t.Align)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue