Skip to content

Commit 19a30ea

Browse files
committed
cmd/compile: call generated size-specialized malloc functions directly
This change creates calls to size-specialized malloc functions instead of calls to newObject when we know the size of the allocation at compilation time. Most of it is a matter of calling the newObject function (which will create calls to the size-specialized functions) rather then the newObjectNonSpecialized function (which won't). In the newHeapaddr, small, non-pointer case, we'll create a non specialized newObject and transform that into the appropriate size-specialized function when we produce the mallocgc in flushPendingHeapAllocations. We have to update some of the rewrites in generic.rules to also apply to the size-specialized functions when they apply to newObject. The messiest thing is we have to adjust the offset we use to save the memory profiler stack, because the depth of the call to profilealloc is two frames fewer in the size-specialized malloc functions compared to when newObject calls mallocgc. A bunch of tests have been adjusted to account for that. Change-Id: I6a6a6964c9037fb6719e392c4a498ed700b617d7 Reviewed-on: https://go-review.googlesource.com/c/go/+/707856 Reviewed-by: Michael Knyszek <[email protected]> Reviewed-by: Michael Matloob <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Keith Randall <[email protected]>
1 parent 80f3bb5 commit 19a30ea

File tree

16 files changed

+228
-116
lines changed

16 files changed

+228
-116
lines changed

src/cmd/compile/internal/ir/symtab.go

Lines changed: 44 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -13,47 +13,50 @@ import (
1313
var Syms symsStruct
1414

1515
type symsStruct struct {
16-
AssertE2I *obj.LSym
17-
AssertE2I2 *obj.LSym
18-
Asanread *obj.LSym
19-
Asanwrite *obj.LSym
20-
CgoCheckMemmove *obj.LSym
21-
CgoCheckPtrWrite *obj.LSym
22-
CheckPtrAlignment *obj.LSym
23-
Deferproc *obj.LSym
24-
Deferprocat *obj.LSym
25-
DeferprocStack *obj.LSym
26-
Deferreturn *obj.LSym
27-
Duffcopy *obj.LSym
28-
Duffzero *obj.LSym
29-
GCWriteBarrier [8]*obj.LSym
30-
Goschedguarded *obj.LSym
31-
Growslice *obj.LSym
32-
InterfaceSwitch *obj.LSym
33-
MallocGC *obj.LSym
34-
Memmove *obj.LSym
35-
Msanread *obj.LSym
36-
Msanwrite *obj.LSym
37-
Msanmove *obj.LSym
38-
Newobject *obj.LSym
39-
Newproc *obj.LSym
40-
PanicBounds *obj.LSym
41-
PanicExtend *obj.LSym
42-
Panicdivide *obj.LSym
43-
Panicshift *obj.LSym
44-
PanicdottypeE *obj.LSym
45-
PanicdottypeI *obj.LSym
46-
Panicnildottype *obj.LSym
47-
Panicoverflow *obj.LSym
48-
Racefuncenter *obj.LSym
49-
Racefuncexit *obj.LSym
50-
Raceread *obj.LSym
51-
Racereadrange *obj.LSym
52-
Racewrite *obj.LSym
53-
Racewriterange *obj.LSym
54-
TypeAssert *obj.LSym
55-
WBZero *obj.LSym
56-
WBMove *obj.LSym
16+
AssertE2I *obj.LSym
17+
AssertE2I2 *obj.LSym
18+
Asanread *obj.LSym
19+
Asanwrite *obj.LSym
20+
CgoCheckMemmove *obj.LSym
21+
CgoCheckPtrWrite *obj.LSym
22+
CheckPtrAlignment *obj.LSym
23+
Deferproc *obj.LSym
24+
Deferprocat *obj.LSym
25+
DeferprocStack *obj.LSym
26+
Deferreturn *obj.LSym
27+
Duffcopy *obj.LSym
28+
Duffzero *obj.LSym
29+
GCWriteBarrier [8]*obj.LSym
30+
Goschedguarded *obj.LSym
31+
Growslice *obj.LSym
32+
InterfaceSwitch *obj.LSym
33+
MallocGC *obj.LSym
34+
MallocGCSmallNoScan [27]*obj.LSym
35+
MallocGCSmallScanNoHeader [27]*obj.LSym
36+
MallocGCTiny [16]*obj.LSym
37+
Memmove *obj.LSym
38+
Msanread *obj.LSym
39+
Msanwrite *obj.LSym
40+
Msanmove *obj.LSym
41+
Newobject *obj.LSym
42+
Newproc *obj.LSym
43+
PanicBounds *obj.LSym
44+
PanicExtend *obj.LSym
45+
Panicdivide *obj.LSym
46+
Panicshift *obj.LSym
47+
PanicdottypeE *obj.LSym
48+
PanicdottypeI *obj.LSym
49+
Panicnildottype *obj.LSym
50+
Panicoverflow *obj.LSym
51+
Racefuncenter *obj.LSym
52+
Racefuncexit *obj.LSym
53+
Raceread *obj.LSym
54+
Racereadrange *obj.LSym
55+
Racewrite *obj.LSym
56+
Racewriterange *obj.LSym
57+
TypeAssert *obj.LSym
58+
WBZero *obj.LSym
59+
WBMove *obj.LSym
5760
// Wasm
5861
SigPanic *obj.LSym
5962
Staticuint64s *obj.LSym

src/cmd/compile/internal/ssa/_gen/generic.rules

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2065,28 +2065,32 @@
20652065
// for rewriting results of some late-expanded rewrites (below)
20662066
(SelectN [n] m:(MakeResult ___)) => m.Args[n]
20672067

2068+
// TODO(matloob): Try out having non-zeroing mallocs for prointerless
2069+
// memory, and leaving the zeroing here. Then the compiler can remove
2070+
// the zeroing if the user has explicit writes to the whole object.
2071+
20682072
// for late-expanded calls, recognize newobject and remove zeroing and nilchecks
2069-
(Zero (SelectN [0] call:(StaticLECall _ _)) mem:(SelectN [1] call))
2070-
&& isSameCall(call.Aux, "runtime.newobject")
2073+
(Zero (SelectN [0] call:(StaticLECall ___)) mem:(SelectN [1] call))
2074+
&& isMalloc(call.Aux)
20712075
=> mem
20722076

2073-
(Store (SelectN [0] call:(StaticLECall _ _)) x mem:(SelectN [1] call))
2077+
(Store (SelectN [0] call:(StaticLECall ___)) x mem:(SelectN [1] call))
20742078
&& isConstZero(x)
2075-
&& isSameCall(call.Aux, "runtime.newobject")
2079+
&& isMalloc(call.Aux)
20762080
=> mem
20772081

2078-
(Store (OffPtr (SelectN [0] call:(StaticLECall _ _))) x mem:(SelectN [1] call))
2082+
(Store (OffPtr (SelectN [0] call:(StaticLECall ___))) x mem:(SelectN [1] call))
20792083
&& isConstZero(x)
2080-
&& isSameCall(call.Aux, "runtime.newobject")
2084+
&& isMalloc(call.Aux)
20812085
=> mem
20822086

2083-
(NilCheck ptr:(SelectN [0] call:(StaticLECall _ _)) _)
2084-
&& isSameCall(call.Aux, "runtime.newobject")
2087+
(NilCheck ptr:(SelectN [0] call:(StaticLECall ___)) _)
2088+
&& isMalloc(call.Aux)
20852089
&& warnRule(fe.Debug_checknil(), v, "removed nil check")
20862090
=> ptr
20872091

2088-
(NilCheck ptr:(OffPtr (SelectN [0] call:(StaticLECall _ _))) _)
2089-
&& isSameCall(call.Aux, "runtime.newobject")
2092+
(NilCheck ptr:(OffPtr (SelectN [0] call:(StaticLECall ___))) _)
2093+
&& isMalloc(call.Aux)
20902094
&& warnRule(fe.Debug_checknil(), v, "removed nil check")
20912095
=> ptr
20922096

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,26 @@ func isSameCall(aux Aux, name string) bool {
456456
return fn != nil && fn.String() == name
457457
}
458458

459+
func isMalloc(aux Aux) bool {
460+
return isNewObject(aux) || isSpecializedMalloc(aux)
461+
}
462+
463+
func isNewObject(aux Aux) bool {
464+
fn := aux.(*AuxCall).Fn
465+
return fn != nil && fn.String() == "runtime.newobject"
466+
}
467+
468+
func isSpecializedMalloc(aux Aux) bool {
469+
fn := aux.(*AuxCall).Fn
470+
if fn == nil {
471+
return false
472+
}
473+
name := fn.String()
474+
return strings.HasPrefix(name, "runtime.mallocgcSmallNoScanSC") ||
475+
strings.HasPrefix(name, "runtime.mallocgcSmallScanNoHeaderSC") ||
476+
strings.HasPrefix(name, "runtime.mallocTiny")
477+
}
478+
459479
// canLoadUnaligned reports if the architecture supports unaligned load operations.
460480
func canLoadUnaligned(c *Config) bool {
461481
return c.ctxt.Arch.Alignment == 1

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

Lines changed: 24 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

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

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -798,7 +798,16 @@ func IsNewObject(v *Value, select1 []*Value) (mem *Value, ok bool) {
798798
if call.Op != OpStaticCall {
799799
return nil, false
800800
}
801-
if !isSameCall(call.Aux, "runtime.newobject") {
801+
// Check for new object, or for new object calls that have been transformed into size-specialized malloc calls.
802+
// Calls that have return type unsafe pointer may have originally been produced by flushPendingHeapAllocations
803+
// in the ssa generator, so may have not originally been newObject calls.
804+
var numParameters int64
805+
switch {
806+
case isNewObject(call.Aux):
807+
numParameters = 1
808+
case isSpecializedMalloc(call.Aux) && !v.Type.IsUnsafePtr():
809+
numParameters = 3
810+
default:
802811
return nil, false
803812
}
804813
if f.ABIDefault == f.ABI1 && len(c.intParamRegs) >= 1 {
@@ -813,7 +822,7 @@ func IsNewObject(v *Value, select1 []*Value) (mem *Value, ok bool) {
813822
if v.Args[0].Args[0].Op != OpSP {
814823
return nil, false
815824
}
816-
if v.Args[0].AuxInt != c.ctxt.Arch.FixedFrameSize+c.RegSize { // offset of return value
825+
if v.Args[0].AuxInt != c.ctxt.Arch.FixedFrameSize+numParameters*c.RegSize { // offset of return value
817826
return nil, false
818827
}
819828
return mem, true

0 commit comments

Comments
 (0)