@@ -453,15 +453,14 @@ func (v Value) call(op string, in []Value) []Value {
453
453
454
454
var ret []Value
455
455
if nout == 0 {
456
- // This is untyped because the frame is really a
457
- // stack, even though it's a heap object.
458
- memclrNoHeapPointers (args , frametype .size )
456
+ typedmemclr (frametype , args )
459
457
framePool .Put (args )
460
458
} else {
461
459
// Zero the now unused input area of args,
462
460
// because the Values returned by this function contain pointers to the args object,
463
461
// and will thus keep the args object alive indefinitely.
464
- memclrNoHeapPointers (args , retOffset )
462
+ typedmemclrpartial (frametype , args , 0 , retOffset )
463
+
465
464
// Wrap Values around return values in args.
466
465
ret = make ([]Value , nout )
467
466
off = retOffset
@@ -472,6 +471,10 @@ func (v Value) call(op string, in []Value) []Value {
472
471
if tv .Size () != 0 {
473
472
fl := flagIndir | flag (tv .Kind ())
474
473
ret [i ] = Value {tv .common (), add (args , off , "tv.Size() != 0" ), fl }
474
+ // Note: this does introduce false sharing between results -
475
+ // if any result is live, they are all live.
476
+ // (And the space for the args is live as well, but as we've
477
+ // cleared that space it isn't as big a deal.)
475
478
} else {
476
479
// For zero-sized return value, args+off may point to the next object.
477
480
// In this case, return the zero value instead.
@@ -660,6 +663,8 @@ func callMethod(ctxt *methodValue, frame unsafe.Pointer) {
660
663
}
661
664
662
665
// Call.
666
+ // Call copies the arguments from args to the stack, calls fn,
667
+ // and then copies the results back into args.
663
668
call (frametype , fn , args , uint32 (frametype .size ), uint32 (retOffset ))
664
669
665
670
// Copy return values. On amd64p32, the beginning of return values
@@ -673,16 +678,14 @@ func callMethod(ctxt *methodValue, frame unsafe.Pointer) {
673
678
if runtime .GOARCH == "amd64p32" {
674
679
callerRetOffset = align (argSize - ptrSize , 8 )
675
680
}
676
- typedmemmovepartial ( frametype ,
677
- add (frame , callerRetOffset , "frametype.size > retOffset" ),
681
+ // This copies to the stack. Write barriers are not needed.
682
+ memmove ( add (frame , callerRetOffset , "frametype.size > retOffset" ),
678
683
add (args , retOffset , "frametype.size > retOffset" ),
679
- retOffset ,
680
684
frametype .size - retOffset )
681
685
}
682
686
683
- // This is untyped because the frame is really a stack, even
684
- // though it's a heap object.
685
- memclrNoHeapPointers (args , frametype .size )
687
+ // Put the args scratch space back in the pool.
688
+ typedmemclr (frametype , args )
686
689
framePool .Put (args )
687
690
688
691
// See the comment in callReflect.
@@ -2569,6 +2572,10 @@ func call(argtype *rtype, fn, arg unsafe.Pointer, n uint32, retoffset uint32)
2569
2572
2570
2573
func ifaceE2I (t * rtype , src interface {}, dst unsafe.Pointer )
2571
2574
2575
+ // memmove copies size bytes to dst from src. No write barriers are used.
2576
+ //go:noescape
2577
+ func memmove (dst , src unsafe.Pointer , size uintptr )
2578
+
2572
2579
// typedmemmove copies a value of type t to dst from src.
2573
2580
//go:noescape
2574
2581
func typedmemmove (t * rtype , dst , src unsafe.Pointer )
@@ -2578,14 +2585,20 @@ func typedmemmove(t *rtype, dst, src unsafe.Pointer)
2578
2585
//go:noescape
2579
2586
func typedmemmovepartial (t * rtype , dst , src unsafe.Pointer , off , size uintptr )
2580
2587
2588
+ // typedmemclr zeros the value at ptr of type t.
2589
+ //go:noescape
2590
+ func typedmemclr (t * rtype , ptr unsafe.Pointer )
2591
+
2592
+ // typedmemclrpartial is like typedmemclr but assumes that
2593
+ // dst points off bytes into the value and only clears size bytes.
2594
+ //go:noescape
2595
+ func typedmemclrpartial (t * rtype , ptr unsafe.Pointer , off , size uintptr )
2596
+
2581
2597
// typedslicecopy copies a slice of elemType values from src to dst,
2582
2598
// returning the number of elements copied.
2583
2599
//go:noescape
2584
2600
func typedslicecopy (elemType * rtype , dst , src sliceHeader ) int
2585
2601
2586
- //go:noescape
2587
- func memclrNoHeapPointers (ptr unsafe.Pointer , n uintptr )
2588
-
2589
2602
// Dummy annotation marking that the value x escapes,
2590
2603
// for use in cases where the reflect code is so clever that
2591
2604
// the compiler cannot follow.
0 commit comments