From b675e52e9592ba3db1a3cf2dc9c4bc02c89e03a8 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Tue, 6 Apr 2021 13:35:48 -0400 Subject: [PATCH] internal/goexperiment: consolidate experiment-enabled constants Currently, we have boolean and integral constants for GOEXPERIMENTs in various places. Consolidate these into automatically generated constants in the internal/goexperiment package. Change-Id: I42a49aba2a3b4c722fedea23a613162cd8a67bee Reviewed-on: https://go-review.googlesource.com/c/go/+/307818 Trust: Austin Clements Run-TryBot: Austin Clements TryBot-Result: Go Bot Reviewed-by: Cherry Zhang Reviewed-by: Matthew Dempsky --- src/go/build/deps_test.go | 4 +- .../goexperiment/exp_fieldtrack_off.go | 9 +++ .../goexperiment/exp_fieldtrack_on.go | 9 +++ .../goexperiment/exp_preemptibleloops_off.go | 9 +++ .../goexperiment/exp_preemptibleloops_on.go | 9 +++ src/internal/goexperiment/exp_regabi_off.go | 9 +++ src/internal/goexperiment/exp_regabi_on.go | 9 +++ .../goexperiment/exp_regabiargs_off.go | 9 +++ .../goexperiment/exp_regabiargs_on.go | 9 +++ .../goexperiment/exp_regabidefer_off.go | 9 +++ .../goexperiment/exp_regabidefer_on.go | 9 +++ src/internal/goexperiment/exp_regabig_off.go | 9 +++ src/internal/goexperiment/exp_regabig_on.go | 9 +++ .../goexperiment/exp_regabireflect_off.go | 9 +++ .../goexperiment/exp_regabireflect_on.go | 9 +++ .../goexperiment/exp_regabiwrappers_off.go | 9 +++ .../goexperiment/exp_regabiwrappers_on.go | 9 +++ .../goexperiment/exp_staticlockranking_off.go | 9 +++ .../goexperiment/exp_staticlockranking_on.go | 9 +++ src/internal/goexperiment/flags.go | 9 ++- src/internal/goexperiment/mkconsts.go | 74 +++++++++++++++++++ src/reflect/abi.go | 7 +- src/reflect/regabiargs_off.go | 10 --- src/reflect/regabiargs_on.go | 10 --- src/runtime/panic.go | 25 ++++--- src/runtime/proc.go | 5 +- src/runtime/regabiargs_off.go | 10 --- src/runtime/regabiargs_on.go | 10 --- src/runtime/regabidefer_off.go | 10 --- src/runtime/regabidefer_on.go | 10 --- src/runtime/stubs.go | 3 +- 31 files changed, 267 insertions(+), 82 deletions(-) create mode 100644 src/internal/goexperiment/exp_fieldtrack_off.go create mode 100644 src/internal/goexperiment/exp_fieldtrack_on.go create mode 100644 src/internal/goexperiment/exp_preemptibleloops_off.go create mode 100644 src/internal/goexperiment/exp_preemptibleloops_on.go create mode 100644 src/internal/goexperiment/exp_regabi_off.go create mode 100644 src/internal/goexperiment/exp_regabi_on.go create mode 100644 src/internal/goexperiment/exp_regabiargs_off.go create mode 100644 src/internal/goexperiment/exp_regabiargs_on.go create mode 100644 src/internal/goexperiment/exp_regabidefer_off.go create mode 100644 src/internal/goexperiment/exp_regabidefer_on.go create mode 100644 src/internal/goexperiment/exp_regabig_off.go create mode 100644 src/internal/goexperiment/exp_regabig_on.go create mode 100644 src/internal/goexperiment/exp_regabireflect_off.go create mode 100644 src/internal/goexperiment/exp_regabireflect_on.go create mode 100644 src/internal/goexperiment/exp_regabiwrappers_off.go create mode 100644 src/internal/goexperiment/exp_regabiwrappers_on.go create mode 100644 src/internal/goexperiment/exp_staticlockranking_off.go create mode 100644 src/internal/goexperiment/exp_staticlockranking_on.go create mode 100644 src/internal/goexperiment/mkconsts.go delete mode 100644 src/reflect/regabiargs_off.go delete mode 100644 src/reflect/regabiargs_on.go delete mode 100644 src/runtime/regabiargs_off.go delete mode 100644 src/runtime/regabiargs_on.go delete mode 100644 src/runtime/regabidefer_off.go delete mode 100644 src/runtime/regabidefer_on.go diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index 63ef2428b1..a1a4324331 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -71,7 +71,7 @@ var depsRules = ` # No dependencies allowed for any of these packages. NONE < container/list, container/ring, - internal/cfg, internal/cpu, + internal/cfg, internal/cpu, internal/goexperiment, internal/goversion, internal/nettrace, unicode/utf8, unicode/utf16, unicode, unsafe; @@ -81,7 +81,7 @@ var depsRules = ` < internal/abi; # RUNTIME is the core runtime group of packages, all of them very light-weight. - internal/abi, internal/cpu, unsafe + internal/abi, internal/cpu, internal/goexperiment, unsafe < internal/bytealg < internal/itoa < internal/unsafeheader diff --git a/src/internal/goexperiment/exp_fieldtrack_off.go b/src/internal/goexperiment/exp_fieldtrack_off.go new file mode 100644 index 0000000000..e5e132660e --- /dev/null +++ b/src/internal/goexperiment/exp_fieldtrack_off.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build !goexperiment.fieldtrack +// +build !goexperiment.fieldtrack + +package goexperiment + +const FieldTrack = false +const FieldTrackInt = 0 diff --git a/src/internal/goexperiment/exp_fieldtrack_on.go b/src/internal/goexperiment/exp_fieldtrack_on.go new file mode 100644 index 0000000000..0d8c447246 --- /dev/null +++ b/src/internal/goexperiment/exp_fieldtrack_on.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build goexperiment.fieldtrack +// +build goexperiment.fieldtrack + +package goexperiment + +const FieldTrack = true +const FieldTrackInt = 1 diff --git a/src/internal/goexperiment/exp_preemptibleloops_off.go b/src/internal/goexperiment/exp_preemptibleloops_off.go new file mode 100644 index 0000000000..7a26088e80 --- /dev/null +++ b/src/internal/goexperiment/exp_preemptibleloops_off.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build !goexperiment.preemptibleloops +// +build !goexperiment.preemptibleloops + +package goexperiment + +const PreemptibleLoops = false +const PreemptibleLoopsInt = 0 diff --git a/src/internal/goexperiment/exp_preemptibleloops_on.go b/src/internal/goexperiment/exp_preemptibleloops_on.go new file mode 100644 index 0000000000..a9ca28c57c --- /dev/null +++ b/src/internal/goexperiment/exp_preemptibleloops_on.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build goexperiment.preemptibleloops +// +build goexperiment.preemptibleloops + +package goexperiment + +const PreemptibleLoops = true +const PreemptibleLoopsInt = 1 diff --git a/src/internal/goexperiment/exp_regabi_off.go b/src/internal/goexperiment/exp_regabi_off.go new file mode 100644 index 0000000000..5d8823843d --- /dev/null +++ b/src/internal/goexperiment/exp_regabi_off.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build !goexperiment.regabi +// +build !goexperiment.regabi + +package goexperiment + +const Regabi = false +const RegabiInt = 0 diff --git a/src/internal/goexperiment/exp_regabi_on.go b/src/internal/goexperiment/exp_regabi_on.go new file mode 100644 index 0000000000..c08d58e9b2 --- /dev/null +++ b/src/internal/goexperiment/exp_regabi_on.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build goexperiment.regabi +// +build goexperiment.regabi + +package goexperiment + +const Regabi = true +const RegabiInt = 1 diff --git a/src/internal/goexperiment/exp_regabiargs_off.go b/src/internal/goexperiment/exp_regabiargs_off.go new file mode 100644 index 0000000000..31a139bbf1 --- /dev/null +++ b/src/internal/goexperiment/exp_regabiargs_off.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build !goexperiment.regabiargs +// +build !goexperiment.regabiargs + +package goexperiment + +const RegabiArgs = false +const RegabiArgsInt = 0 diff --git a/src/internal/goexperiment/exp_regabiargs_on.go b/src/internal/goexperiment/exp_regabiargs_on.go new file mode 100644 index 0000000000..9b26f3c9cb --- /dev/null +++ b/src/internal/goexperiment/exp_regabiargs_on.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build goexperiment.regabiargs +// +build goexperiment.regabiargs + +package goexperiment + +const RegabiArgs = true +const RegabiArgsInt = 1 diff --git a/src/internal/goexperiment/exp_regabidefer_off.go b/src/internal/goexperiment/exp_regabidefer_off.go new file mode 100644 index 0000000000..b47c0c2cf5 --- /dev/null +++ b/src/internal/goexperiment/exp_regabidefer_off.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build !goexperiment.regabidefer +// +build !goexperiment.regabidefer + +package goexperiment + +const RegabiDefer = false +const RegabiDeferInt = 0 diff --git a/src/internal/goexperiment/exp_regabidefer_on.go b/src/internal/goexperiment/exp_regabidefer_on.go new file mode 100644 index 0000000000..bbf2f6c69b --- /dev/null +++ b/src/internal/goexperiment/exp_regabidefer_on.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build goexperiment.regabidefer +// +build goexperiment.regabidefer + +package goexperiment + +const RegabiDefer = true +const RegabiDeferInt = 1 diff --git a/src/internal/goexperiment/exp_regabig_off.go b/src/internal/goexperiment/exp_regabig_off.go new file mode 100644 index 0000000000..1b37d45186 --- /dev/null +++ b/src/internal/goexperiment/exp_regabig_off.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build !goexperiment.regabig +// +build !goexperiment.regabig + +package goexperiment + +const RegabiG = false +const RegabiGInt = 0 diff --git a/src/internal/goexperiment/exp_regabig_on.go b/src/internal/goexperiment/exp_regabig_on.go new file mode 100644 index 0000000000..7e5b162e0b --- /dev/null +++ b/src/internal/goexperiment/exp_regabig_on.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build goexperiment.regabig +// +build goexperiment.regabig + +package goexperiment + +const RegabiG = true +const RegabiGInt = 1 diff --git a/src/internal/goexperiment/exp_regabireflect_off.go b/src/internal/goexperiment/exp_regabireflect_off.go new file mode 100644 index 0000000000..515f4a53e6 --- /dev/null +++ b/src/internal/goexperiment/exp_regabireflect_off.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build !goexperiment.regabireflect +// +build !goexperiment.regabireflect + +package goexperiment + +const RegabiReflect = false +const RegabiReflectInt = 0 diff --git a/src/internal/goexperiment/exp_regabireflect_on.go b/src/internal/goexperiment/exp_regabireflect_on.go new file mode 100644 index 0000000000..e8a3e9c06a --- /dev/null +++ b/src/internal/goexperiment/exp_regabireflect_on.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build goexperiment.regabireflect +// +build goexperiment.regabireflect + +package goexperiment + +const RegabiReflect = true +const RegabiReflectInt = 1 diff --git a/src/internal/goexperiment/exp_regabiwrappers_off.go b/src/internal/goexperiment/exp_regabiwrappers_off.go new file mode 100644 index 0000000000..bfa0fa3779 --- /dev/null +++ b/src/internal/goexperiment/exp_regabiwrappers_off.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build !goexperiment.regabiwrappers +// +build !goexperiment.regabiwrappers + +package goexperiment + +const RegabiWrappers = false +const RegabiWrappersInt = 0 diff --git a/src/internal/goexperiment/exp_regabiwrappers_on.go b/src/internal/goexperiment/exp_regabiwrappers_on.go new file mode 100644 index 0000000000..11ffffbbff --- /dev/null +++ b/src/internal/goexperiment/exp_regabiwrappers_on.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build goexperiment.regabiwrappers +// +build goexperiment.regabiwrappers + +package goexperiment + +const RegabiWrappers = true +const RegabiWrappersInt = 1 diff --git a/src/internal/goexperiment/exp_staticlockranking_off.go b/src/internal/goexperiment/exp_staticlockranking_off.go new file mode 100644 index 0000000000..3d546c04b4 --- /dev/null +++ b/src/internal/goexperiment/exp_staticlockranking_off.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build !goexperiment.staticlockranking +// +build !goexperiment.staticlockranking + +package goexperiment + +const StaticLockRanking = false +const StaticLockRankingInt = 0 diff --git a/src/internal/goexperiment/exp_staticlockranking_on.go b/src/internal/goexperiment/exp_staticlockranking_on.go new file mode 100644 index 0000000000..78188fb810 --- /dev/null +++ b/src/internal/goexperiment/exp_staticlockranking_on.go @@ -0,0 +1,9 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build goexperiment.staticlockranking +// +build goexperiment.staticlockranking + +package goexperiment + +const StaticLockRanking = true +const StaticLockRankingInt = 1 diff --git a/src/internal/goexperiment/flags.go b/src/internal/goexperiment/flags.go index 46800b4e0f..c5e3d2c91a 100644 --- a/src/internal/goexperiment/flags.go +++ b/src/internal/goexperiment/flags.go @@ -17,11 +17,12 @@ // - Build tag goexperiment.x is set if experiment x (lower case) is // enabled. // +// - For each experiment x (in camel case), this package contains a +// boolean constant x and an integer constant xInt. +// // - In runtime assembly, the macro GOEXPERIMENT_x is defined if // experiment x (lower case) is enabled. // -// - TODO(austin): More to come. -// // In the toolchain, the set of experiments enabled for the current // build should be accessed via objabi.Experiment. // @@ -29,11 +30,15 @@ // go doc internal/experiment.Flags. package goexperiment +//go:generate go run mkconsts.go + // Flags is the set of experiments that can be enabled or disabled in // the current toolchain. // // When specified in the GOEXPERIMENT environment variable or as build // tags, experiments use the strings.ToLower of their field name. +// +// If you change this struct definition, run "go generate". type Flags struct { FieldTrack bool PreemptibleLoops bool diff --git a/src/internal/goexperiment/mkconsts.go b/src/internal/goexperiment/mkconsts.go new file mode 100644 index 0000000000..204ca9d9aa --- /dev/null +++ b/src/internal/goexperiment/mkconsts.go @@ -0,0 +1,74 @@ +// Copyright 2021 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. + +//go:build ignore +// +build ignore + +// mkconsts generates const definition files for each GOEXPERIMENT. +package main + +import ( + "bytes" + "fmt" + "internal/goexperiment" + "log" + "os" + "reflect" + "strings" +) + +func main() { + // Delete existing experiment constant files. + ents, err := os.ReadDir(".") + if err != nil { + log.Fatal(err) + } + for _, ent := range ents { + name := ent.Name() + if !strings.HasPrefix(name, "exp_") { + continue + } + // Check that this is definitely a generated file. + data, err := os.ReadFile(name) + if err != nil { + log.Fatalf("reading %s: %v", name, err) + } + if !bytes.Contains(data, []byte("Code generated by mkconsts")) { + log.Fatalf("%s: expected generated file", name) + } + if err := os.Remove(name); err != nil { + log.Fatal(err) + } + } + + // Generate new experiment constant files. + rt := reflect.TypeOf(&goexperiment.Flags{}).Elem() + for i := 0; i < rt.NumField(); i++ { + f := rt.Field(i).Name + buildTag := "goexperiment." + strings.ToLower(f) + for _, val := range []bool{false, true} { + name := fmt.Sprintf("exp_%s_%s.go", strings.ToLower(f), pick(val, "off", "on")) + data := fmt.Sprintf(`// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build %s%s +// +build %s%s + +package goexperiment + +const %s = %v +const %sInt = %s +`, pick(val, "!", ""), buildTag, pick(val, "!", ""), buildTag, f, val, f, pick(val, "0", "1")) + if err := os.WriteFile(name, []byte(data), 0666); err != nil { + log.Fatalf("writing %s: %v", name, err) + } + } + } +} + +func pick(v bool, f, t string) string { + if v { + return t + } + return f +} diff --git a/src/reflect/abi.go b/src/reflect/abi.go index 6a422d06d1..caa770fcb0 100644 --- a/src/reflect/abi.go +++ b/src/reflect/abi.go @@ -6,6 +6,7 @@ package reflect import ( "internal/abi" + "internal/goexperiment" "unsafe" ) @@ -28,9 +29,9 @@ import ( // commented out there should be the actual values once // we're ready to use the register ABI everywhere. var ( - intArgRegs = abi.IntArgRegs * experimentRegabiArgs - floatArgRegs = abi.FloatArgRegs * experimentRegabiArgs - floatRegSize = uintptr(abi.EffectiveFloatRegSize * experimentRegabiArgs) + intArgRegs = abi.IntArgRegs * goexperiment.RegabiArgsInt + floatArgRegs = abi.FloatArgRegs * goexperiment.RegabiArgsInt + floatRegSize = uintptr(abi.EffectiveFloatRegSize * goexperiment.RegabiArgsInt) ) // abiStep represents an ABI "instruction." Each instruction diff --git a/src/reflect/regabiargs_off.go b/src/reflect/regabiargs_off.go deleted file mode 100644 index 655e955474..0000000000 --- a/src/reflect/regabiargs_off.go +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2021 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. - -//go:build !goexperiment.regabiargs -// +build !goexperiment.regabiargs - -package reflect - -const experimentRegabiArgs = 0 diff --git a/src/reflect/regabiargs_on.go b/src/reflect/regabiargs_on.go deleted file mode 100644 index 0f33b22ff9..0000000000 --- a/src/reflect/regabiargs_on.go +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2021 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. - -//go:build goexperiment.regabiargs -// +build goexperiment.regabiargs - -package reflect - -const experimentRegabiArgs = 1 diff --git a/src/runtime/panic.go b/src/runtime/panic.go index d33441a0d8..c437553012 100644 --- a/src/runtime/panic.go +++ b/src/runtime/panic.go @@ -6,6 +6,7 @@ package runtime import ( "internal/abi" + "internal/goexperiment" "runtime/internal/atomic" "runtime/internal/sys" "unsafe" @@ -228,7 +229,7 @@ func deferproc(siz int32, fn *funcval) { // arguments of fn follow fn throw("defer on system stack") } - if experimentRegabiDefer && siz != 0 { + if goexperiment.RegabiDefer && siz != 0 { // TODO: Make deferproc just take a func(). throw("defer with non-empty frame") } @@ -285,7 +286,7 @@ func deferprocStack(d *_defer) { // go code on the system stack can't defer throw("defer on system stack") } - if experimentRegabiDefer && d.siz != 0 { + if goexperiment.RegabiDefer && d.siz != 0 { throw("defer with non-empty frame") } // siz and fn are already set. @@ -387,8 +388,8 @@ func deferArgs(d *_defer) unsafe.Pointer { // that experiment, we should change the type of d.fn. //go:nosplit func deferFunc(d *_defer) func() { - if !experimentRegabiDefer { - throw("requires experimentRegabiDefer") + if !goexperiment.RegabiDefer { + throw("requires GOEXPERIMENT=regabidefer") } var fn func() *(**funcval)(unsafe.Pointer(&fn)) = d.fn @@ -648,7 +649,7 @@ func Goexit() { addOneOpenDeferFrame(gp, 0, nil) } } else { - if experimentRegabiDefer { + if goexperiment.RegabiDefer { // Save the pc/sp in deferCallSave(), so we can "recover" back to this // loop if necessary. deferCallSave(&p, deferFunc(d)) @@ -850,7 +851,7 @@ func runOpenDeferFrame(gp *g, d *_defer) bool { argWidth, fd = readvarintUnsafe(fd) closureOffset, fd = readvarintUnsafe(fd) nArgs, fd = readvarintUnsafe(fd) - if experimentRegabiDefer && argWidth != 0 { + if goexperiment.RegabiDefer && argWidth != 0 { throw("defer with non-empty frame") } if deferBits&(1<