Skip to content

Commit 8c960c1

Browse files
committed
Apply makeArgs stack slice and //go:noescape optimizations.
1 parent 45bae64 commit 8c960c1

File tree

1 file changed

+31
-6
lines changed

1 file changed

+31
-6
lines changed

src/syscall/js/js.go

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ func ValueOf(x interface{}) Value {
209209
}
210210
}
211211

212+
//go:noescape
212213
func stringVal(x string) ref
213214

214215
// Type represents the JavaScript type of a Value.
@@ -292,6 +293,7 @@ func (v Value) Get(p string) Value {
292293
return r
293294
}
294295

296+
//go:noescape
295297
func valueGet(v ref, p string) ref
296298

297299
// Set sets the JavaScript property p of value v to ValueOf(x).
@@ -306,6 +308,7 @@ func (v Value) Set(p string, x interface{}) {
306308
runtime.KeepAlive(xv)
307309
}
308310

311+
//go:noescape
309312
func valueSet(v ref, p string, x ref)
310313

311314
// Delete deletes the JavaScript property p of value v.
@@ -318,6 +321,7 @@ func (v Value) Delete(p string) {
318321
runtime.KeepAlive(v)
319322
}
320323

324+
//go:noescape
321325
func valueDelete(v ref, p string)
322326

323327
// Index returns JavaScript index i of value v.
@@ -347,15 +351,29 @@ func (v Value) SetIndex(i int, x interface{}) {
347351

348352
func valueSetIndex(v ref, i int, x ref)
349353

350-
func makeArgs(args []interface{}) ([]Value, []ref) {
351-
argVals := make([]Value, len(args))
352-
argRefs := make([]ref, len(args))
354+
func makeArgs(args []interface{}) (argVals []Value, argRefs []ref) {
355+
// value chosen for being power of two, and enough to handle all web APIs
356+
// in particular, note that WebGL2's texImage2D takes up to 10 arguments
357+
const maxStackArgs = 16
358+
if len(args) <= maxStackArgs {
359+
// as long as makeArgs is inlined, these will be stack-allocated
360+
argVals = make([]Value, len(args), maxStackArgs)
361+
argRefs = make([]ref, len(args), maxStackArgs)
362+
} else {
363+
// allocates on the heap, but exceeding maxStackArgs should be rare
364+
argVals = make([]Value, len(args))
365+
argRefs = make([]ref, len(args))
366+
}
367+
return
368+
}
369+
370+
func storeArgs(args []interface{}, argValsDst []Value, argRefsDst []ref) {
371+
// would go in makeArgs if the combined func was simple enough to inline
353372
for i, arg := range args {
354373
v := ValueOf(arg)
355-
argVals[i] = v
356-
argRefs[i] = v.ref
374+
argValsDst[i] = v
375+
argRefsDst[i] = v.ref
357376
}
358-
return argVals, argRefs
359377
}
360378

361379
// Length returns the JavaScript property "length" of v.
@@ -376,6 +394,7 @@ func valueLength(v ref) int
376394
// The arguments get mapped to JavaScript values according to the ValueOf function.
377395
func (v Value) Call(m string, args ...interface{}) Value {
378396
argVals, argRefs := makeArgs(args)
397+
storeArgs(args, argVals, argRefs)
379398
res, ok := valueCall(v.ref, m, argRefs)
380399
runtime.KeepAlive(v)
381400
runtime.KeepAlive(argVals)
@@ -391,13 +410,15 @@ func (v Value) Call(m string, args ...interface{}) Value {
391410
return makeValue(res)
392411
}
393412

413+
//go:noescape
394414
func valueCall(v ref, m string, args []ref) (ref, bool)
395415

396416
// Invoke does a JavaScript call of the value v with the given arguments.
397417
// It panics if v is not a JavaScript function.
398418
// The arguments get mapped to JavaScript values according to the ValueOf function.
399419
func (v Value) Invoke(args ...interface{}) Value {
400420
argVals, argRefs := makeArgs(args)
421+
storeArgs(args, argVals, argRefs)
401422
res, ok := valueInvoke(v.ref, argRefs)
402423
runtime.KeepAlive(v)
403424
runtime.KeepAlive(argVals)
@@ -410,13 +431,15 @@ func (v Value) Invoke(args ...interface{}) Value {
410431
return makeValue(res)
411432
}
412433

434+
//go:noescape
413435
func valueInvoke(v ref, args []ref) (ref, bool)
414436

415437
// New uses JavaScript's "new" operator with value v as constructor and the given arguments.
416438
// It panics if v is not a JavaScript function.
417439
// The arguments get mapped to JavaScript values according to the ValueOf function.
418440
func (v Value) New(args ...interface{}) Value {
419441
argVals, argRefs := makeArgs(args)
442+
storeArgs(args, argVals, argRefs)
420443
res, ok := valueNew(v.ref, argRefs)
421444
runtime.KeepAlive(v)
422445
runtime.KeepAlive(argVals)
@@ -429,6 +452,7 @@ func (v Value) New(args ...interface{}) Value {
429452
return makeValue(res)
430453
}
431454

455+
//go:noescape
432456
func valueNew(v ref, args []ref) (ref, bool)
433457

434458
func (v Value) isNumber() bool {
@@ -580,4 +604,5 @@ func CopyBytesToJS(dst Value, src []byte) int {
580604
return n
581605
}
582606

607+
//go:noescape
583608
func copyBytesToJS(dst ref, src []byte) (int, bool)

0 commit comments

Comments
 (0)