this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

internal/pkg: avoid repeating the args adt.Value slice in CallCtxt

The type embeds adt.CallContext, which has that slice already,
accessible via the Value method.

This helps make CallCtxt a little bit smaller,
reducing the allocated space overhead per func call.

│ old │ new │
│ B/op │ B/op vs base │
VetInventory 4.703Gi ± ∞ ¹ 4.687Gi ± ∞ ¹ -0.34% (p=1.000 n=1)

│ old │ new │
│ allocs/op │ allocs/op vs base │
VetInventory 49.86M ± ∞ ¹ 49.86M ± ∞ ¹ +0.00% (p=1.000 n=1)

Signed-off-by: Daniel Martí <mvdan@mvdan.cc>
Change-Id: Ibbce4a10173193979b624b37d3dfab52c6d1c5a0
Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1229427
Reviewed-by: Matthew Sackman <matthew@cue.works>
TryBot-Result: CUEcueckoo <cueckoo@cuelang.org>
Unity-Result: CUE porcuepine <cue.porcuepine@gmail.com>

+24 -26
-2
internal/pkg/builtin.go
··· 132 132 } 133 133 x.Func = func(call adt.CallContext) (ret adt.Expr) { 134 134 ctx := call.OpContext() 135 - args := call.Args() 136 135 137 136 // call, _ := ctx.Source().(*ast.CallExpr) 138 137 c := &CallCtxt{ 139 138 CallContext: call, 140 139 ctx: ctx, 141 - args: args, 142 140 builtin: b, 143 141 } 144 142 defer func() {
+24 -24
internal/pkg/context.go
··· 33 33 builtin *Builtin 34 34 Err any 35 35 Ret any 36 - 37 - args []adt.Value 38 36 } 39 37 40 38 func (c *CallCtxt) Name() string { ··· 58 56 59 57 // Value returns a finalized cue.Value for the ith argument. 60 58 func (c *CallCtxt) Value(i int) cue.Value { 61 - v := value.Make(c.ctx, c.args[i]) 59 + v := value.Make(c.ctx, c.CallContext.Value(i)) 62 60 if c.builtin.NonConcrete { 63 61 // In case NonConcrete is false, the concreteness is already checked 64 62 // at call time. We may want to use finalize semantics in both cases, ··· 74 72 } 75 73 76 74 func (c *CallCtxt) Struct(i int) Struct { 77 - x := c.args[i] 75 + x := c.CallContext.Value(i) 78 76 if c.builtin.NonConcrete { 79 77 x = adt.Default(x) 80 78 } ··· 91 89 if b, ok := x.(*adt.Bottom); ok { 92 90 err = &callError{b} 93 91 } 94 - c.invalidArgType(c.args[i], i, "struct", err) 92 + c.invalidArgType(x, i, "struct", err) 95 93 } else { 96 94 err := c.ctx.NewErrf("non-concrete struct for argument %d", i) 97 95 err.Code = adt.IncompleteError ··· 108 106 func (c *CallCtxt) Int64(i int) int64 { return c.intValue(i, 64, "int64") } 109 107 110 108 func (c *CallCtxt) intValue(i, bitLen int, typ string) int64 { 111 - arg := c.args[i] 109 + arg := c.CallContext.Value(i) 112 110 if num, _ := c.ctx.EvaluateKeepState(arg).(*adt.Num); num != nil { 113 111 // In the happy path, avoid converting to the public [cue.Value] API, which is wasteful. 114 112 if n, err := num.X.Int64(); err == nil && bits.Len64(uint64(n)) <= bitLen { ··· 137 135 func (c *CallCtxt) Uint64(i int) uint64 { return c.uintValue(i, 64, "uint64") } 138 136 139 137 func (c *CallCtxt) uintValue(i, bitLen int, typ string) uint64 { 140 - arg := c.args[i] 138 + arg := c.CallContext.Value(i) 141 139 if num, _ := c.ctx.EvaluateKeepState(arg).(*adt.Num); num != nil { 142 140 // In the happy path, avoid converting to the public [cue.Value] API, which is wasteful. 143 141 // Note that [apd.Decimal] has an Int64 method, but no Uint64 method, ··· 146 144 return uint64(n) 147 145 } 148 146 } 149 - x := value.Make(c.ctx, c.args[i]) 147 + x := value.Make(c.ctx, arg) 150 148 n, err := x.Int(nil) 151 149 if err != nil || n.Sign() < 0 { 152 - c.invalidArgType(c.args[i], i, typ, err) 150 + c.invalidArgType(arg, i, typ, err) 153 151 return 0 154 152 } 155 153 if n.BitLen() > bitLen { ··· 161 159 } 162 160 163 161 func (c *CallCtxt) Decimal(i int) *apd.Decimal { 164 - arg := c.args[i] 162 + arg := c.CallContext.Value(i) 165 163 if num, _ := c.ctx.EvaluateKeepState(arg).(*adt.Num); num != nil { 166 164 // In the happy path, avoid converting to the public [cue.Value] API, which is wasteful. 167 165 return &num.X ··· 176 174 } 177 175 178 176 func (c *CallCtxt) Float64(i int) float64 { 179 - arg := c.args[i] 177 + arg := c.CallContext.Value(i) 180 178 if num, _ := c.ctx.EvaluateKeepState(arg).(*adt.Num); num != nil { 181 179 // In the happy path, avoid converting to the public [cue.Value] API, which is wasteful. 182 180 if f, err := num.X.Float64(); err == nil { ··· 193 191 } 194 192 195 193 func (c *CallCtxt) BigInt(i int) *big.Int { 196 - arg := c.args[i] 194 + arg := c.CallContext.Value(i) 197 195 if num, _ := c.ctx.EvaluateKeepState(arg).(*adt.Num); num != nil { 198 196 // In the happy path, avoid converting to the public [cue.Value] API, which is wasteful. 199 197 return num.BigInt(nil) ··· 210 208 var ten = big.NewInt(10) 211 209 212 210 func (c *CallCtxt) BigFloat(i int) *big.Float { 213 - x := value.Make(c.ctx, c.args[i]) 211 + arg := c.CallContext.Value(i) 212 + x := value.Make(c.ctx, arg) 214 213 var mant big.Int 215 214 exp, err := x.MantExp(&mant) 216 215 if err != nil { 217 - c.invalidArgType(c.args[i], i, "float", err) 216 + c.invalidArgType(arg, i, "float", err) 218 217 return nil 219 218 } 220 219 f := &big.Float{} ··· 228 227 } 229 228 230 229 func (c *CallCtxt) String(i int) string { 231 - arg := c.args[i] 230 + arg := c.CallContext.Value(i) 232 231 if str, _ := c.ctx.EvaluateKeepState(arg).(*adt.String); str != nil { 233 232 // In the happy path, avoid converting to the public [cue.Value] API, which is wasteful. 234 233 return str.Str ··· 243 242 } 244 243 245 244 func (c *CallCtxt) Bytes(i int) []byte { 246 - arg := c.args[i] 245 + arg := c.CallContext.Value(i) 247 246 if bs, _ := c.ctx.EvaluateKeepState(arg).(*adt.Bytes); bs != nil { 248 247 // In the happy path, avoid converting to the public [cue.Value] API, which is wasteful. 249 248 return bs.B ··· 258 257 } 259 258 260 259 func (c *CallCtxt) Reader(i int) io.Reader { 261 - x := value.Make(c.ctx, c.args[i]) 260 + arg := c.CallContext.Value(i) 261 + x := value.Make(c.ctx, arg) 262 262 // TODO: optimize for string and bytes cases 263 263 r, err := x.Reader() 264 264 if err != nil { 265 - c.invalidArgType(c.args[i], i, "bytes|string", err) 265 + c.invalidArgType(arg, i, "bytes|string", err) 266 266 return nil 267 267 } 268 268 return r 269 269 } 270 270 271 271 func (c *CallCtxt) Bool(i int) bool { 272 - arg := c.args[i] 272 + arg := c.CallContext.Value(i) 273 273 if b, _ := c.ctx.EvaluateKeepState(arg).(*adt.Bool); b != nil { 274 274 // In the happy path, avoid converting to the public [cue.Value] API, which is wasteful. 275 275 return b.B ··· 284 284 } 285 285 286 286 func (c *CallCtxt) List(i int) (a []cue.Value) { 287 - arg := c.args[i] 287 + arg := c.CallContext.Value(i) 288 288 x := value.Make(c.ctx, arg) 289 289 v, err := x.List() 290 290 if err != nil { 291 - c.invalidArgType(c.args[i], i, "list", err) 291 + c.invalidArgType(arg, i, "list", err) 292 292 return a 293 293 } 294 294 for v.Next() { ··· 306 306 } 307 307 308 308 func (c *CallCtxt) Iter(i int) (a cue.Iterator) { 309 - arg := c.args[i] 309 + arg := c.CallContext.Value(i) 310 310 x := value.Make(c.ctx, arg) 311 311 v, err := x.List() 312 312 if err != nil { ··· 316 316 } 317 317 318 318 func (c *CallCtxt) getList(i int) *adt.Vertex { 319 - x := c.args[i] 319 + x := c.CallContext.Value(i) 320 320 if c.builtin.NonConcrete { 321 321 x = adt.Default(x) 322 322 } ··· 338 338 if b, ok := x.(*adt.Bottom); ok { 339 339 err = &callError{b} 340 340 } 341 - c.invalidArgType(c.args[i], i, "list", err) 341 + c.invalidArgType(x, i, "list", err) 342 342 } else { 343 343 err := c.ctx.NewErrf("non-concrete list for argument %d", i) 344 344 err.Code = adt.IncompleteError