1
2
3
4
5 package buildcfg
6
7 import (
8 "fmt"
9 "reflect"
10 "strings"
11
12 "internal/goexperiment"
13 )
14
15
16
17
18
19
20
21
22
23
24 var Experiment, experimentBaseline = func() (goexperiment.Flags, goexperiment.Flags) {
25 flags, baseline, err := ParseGOEXPERIMENT(GOOS, GOARCH, envOr("GOEXPERIMENT", defaultGOEXPERIMENT))
26 if err != nil {
27 Error = err
28 }
29 return flags, baseline
30 }()
31
32 const DefaultGOEXPERIMENT = defaultGOEXPERIMENT
33
34
35
36
37
38
39
40
41 var FramePointerEnabled = GOARCH == "amd64" || GOARCH == "arm64"
42
43
44
45
46
47
48 func ParseGOEXPERIMENT(goos, goarch, goexp string) (flags, baseline goexperiment.Flags, err error) {
49 regabiSupported := false
50 switch goarch {
51 case "amd64", "arm64", "ppc64le", "ppc64":
52 regabiSupported = true
53 }
54
55 baseline = goexperiment.Flags{
56 RegabiWrappers: regabiSupported,
57 RegabiReflect: regabiSupported,
58 RegabiArgs: regabiSupported,
59 PacerRedesign: true,
60 }
61
62
63 flags = baseline
64
65
66
67
68 if goexp != "" {
69
70 names := make(map[string]func(bool))
71 rv := reflect.ValueOf(&flags).Elem()
72 rt := rv.Type()
73 for i := 0; i < rt.NumField(); i++ {
74 field := rv.Field(i)
75 names[strings.ToLower(rt.Field(i).Name)] = field.SetBool
76 }
77
78
79
80
81
82 names["regabi"] = func(v bool) {
83 flags.RegabiWrappers = v
84 flags.RegabiReflect = v
85 flags.RegabiArgs = v
86 }
87
88
89 for _, f := range strings.Split(goexp, ",") {
90 if f == "" {
91 continue
92 }
93 if f == "none" {
94
95
96
97 flags = goexperiment.Flags{}
98 continue
99 }
100 val := true
101 if strings.HasPrefix(f, "no") {
102 f, val = f[2:], false
103 }
104 set, ok := names[f]
105 if !ok {
106 err = fmt.Errorf("unknown GOEXPERIMENT %s", f)
107 return
108 }
109 set(val)
110 }
111 }
112
113
114 if goarch == "amd64" {
115 flags.RegabiWrappers = true
116 flags.RegabiReflect = true
117 flags.RegabiArgs = true
118 }
119
120 if !regabiSupported {
121 flags.RegabiReflect = false
122 flags.RegabiArgs = false
123 }
124
125 if flags.RegabiArgs && !(flags.RegabiWrappers && flags.RegabiReflect) {
126 err = fmt.Errorf("GOEXPERIMENT regabiargs requires regabiwrappers,regabireflect")
127 }
128 return
129 }
130
131
132
133
134
135 func expList(exp, base *goexperiment.Flags, all bool) []string {
136 var list []string
137 rv := reflect.ValueOf(exp).Elem()
138 var rBase reflect.Value
139 if base != nil {
140 rBase = reflect.ValueOf(base).Elem()
141 }
142 rt := rv.Type()
143 for i := 0; i < rt.NumField(); i++ {
144 name := strings.ToLower(rt.Field(i).Name)
145 val := rv.Field(i).Bool()
146 baseVal := false
147 if base != nil {
148 baseVal = rBase.Field(i).Bool()
149 }
150 if all || val != baseVal {
151 if val {
152 list = append(list, name)
153 } else {
154 list = append(list, "no"+name)
155 }
156 }
157 }
158 return list
159 }
160
161
162
163
164
165 func GOEXPERIMENT() string {
166 goexp := strings.Join(expList(&Experiment, &experimentBaseline, false), ",")
167 if goexp == "" && DefaultGOEXPERIMENT != "" {
168 goexp = ","
169 }
170 return goexp
171 }
172
173
174
175 func EnabledExperiments() []string {
176 return expList(&Experiment, nil, false)
177 }
178
179
180
181 func AllExperiments() []string {
182 return expList(&Experiment, nil, true)
183 }
184
185
186
187
188 func UpdateExperiments(goos, goarch, goexperiment string) {
189 var err error
190 Experiment, experimentBaseline, err = ParseGOEXPERIMENT(goos, goarch, goexperiment)
191 if err != nil {
192 Error = err
193 }
194 }
195
View as plain text