Skip to content

Commit 8dc8893

Browse files
committed
Merge remote-tracking branch 'upstream/master'
2 parents f8e5474 + 1647896 commit 8dc8893

File tree

2 files changed

+47
-8
lines changed

2 files changed

+47
-8
lines changed

src/cmd/compile/internal/ssagen/ssa.go

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -701,20 +701,42 @@ func (s *state) paramsToHeap() {
701701
do(typ.Results())
702702
}
703703

704+
// allocSizeAndAlign returns the size and alignment of t.
705+
// Normally just t.Size() and t.Alignment(), but there
706+
// is a special case to handle 64-bit atomics on 32-bit systems.
707+
func allocSizeAndAlign(t *types.Type) (int64, int64) {
708+
size, align := t.Size(), t.Alignment()
709+
if types.PtrSize == 4 && align == 4 && size >= 8 {
710+
// For 64-bit atomics on 32-bit systems.
711+
size = types.RoundUp(size, 8)
712+
align = 8
713+
}
714+
return size, align
715+
}
716+
func allocSize(t *types.Type) int64 {
717+
size, _ := allocSizeAndAlign(t)
718+
return size
719+
}
720+
func allocAlign(t *types.Type) int64 {
721+
_, align := allocSizeAndAlign(t)
722+
return align
723+
}
724+
704725
// newHeapaddr allocates heap memory for n and sets its heap address.
705726
func (s *state) newHeapaddr(n *ir.Name) {
706-
if n.Type().HasPointers() || n.Type().Size() >= maxAggregatedHeapAllocation || n.Type().Size() == 0 {
727+
size := allocSize(n.Type())
728+
if n.Type().HasPointers() || size >= maxAggregatedHeapAllocation || size == 0 {
707729
s.setHeapaddr(n.Pos(), n, s.newObject(n.Type(), nil))
708730
return
709731
}
710732

711733
// Do we have room together with our pending allocations?
712734
// If not, flush all the current ones.
713-
var size int64
735+
var used int64
714736
for _, v := range s.pendingHeapAllocations {
715-
size += v.Type.Elem().Size()
737+
used += allocSize(v.Type.Elem())
716738
}
717-
if size+n.Type().Size() > maxAggregatedHeapAllocation {
739+
if used+size > maxAggregatedHeapAllocation {
718740
s.flushPendingHeapAllocations()
719741
}
720742

@@ -757,16 +779,16 @@ func (s *state) flushPendingHeapAllocations() {
757779
// This way we never have to worry about padding.
758780
// (Stable not required; just cleaner to keep program order among equal alignments.)
759781
slices.SortStableFunc(pending, func(x, y *ssa.Value) int {
760-
return cmp.Compare(y.Type.Elem().Alignment(), x.Type.Elem().Alignment())
782+
return cmp.Compare(allocAlign(y.Type.Elem()), allocAlign(x.Type.Elem()))
761783
})
762784

763785
// Figure out how much data we need allocate.
764786
var size int64
765787
for _, v := range pending {
766788
v.AuxInt = size // Adjust OffPtr to the right value while we are here.
767-
size += v.Type.Elem().Size()
789+
size += allocSize(v.Type.Elem())
768790
}
769-
align := pending[0].Type.Elem().Alignment()
791+
align := allocAlign(pending[0].Type.Elem())
770792
size = types.RoundUp(size, align)
771793

772794
// Convert newObject call to a mallocgc call.

src/cmd/compile/internal/test/locals_test.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44

55
package test
66

7-
import "testing"
7+
import (
8+
"sync/atomic"
9+
"testing"
10+
)
811

912
func locals() {
1013
var x int64
@@ -51,6 +54,19 @@ func closure() func() {
5154
}
5255
}
5356

57+
//go:noinline
58+
func atomicFn() {
59+
var x int32
60+
var y int64
61+
var z int16
62+
var w int8
63+
sink32 = &x
64+
sink64 = &y
65+
sink16 = &z
66+
sink8 = &w
67+
atomic.StoreInt64(&y, 7)
68+
}
69+
5470
var sink64 *int64
5571
var sink32 *int32
5672
var sink16 *int16
@@ -67,6 +83,7 @@ func TestLocalAllocations(t *testing.T) {
6783
{"args", func() { args(1, 2, 3, 4) }, 1},
6884
{"half", func() { half(1, 2) }, 1},
6985
{"closure", func() { _ = closure() }, 2},
86+
{"atomic", atomicFn, 1},
7087
} {
7188
allocs := testing.AllocsPerRun(100, tst.f)
7289
if allocs != float64(tst.want) {

0 commit comments

Comments
 (0)