@@ -30,8 +30,7 @@ const minPhysPageSize = 4096
30
30
//go:notinheap
31
31
type mheap struct {
32
32
lock mutex
33
- free mTreap // free and non-scavenged spans
34
- scav mTreap // free and scavenged spans
33
+ free mTreap // free spans
35
34
sweepgen uint32 // sweep generation, see comment in mspan
36
35
sweepdone uint32 // all spans are swept
37
36
sweepers uint32 // number of active sweepone calls
@@ -60,7 +59,7 @@ type mheap struct {
60
59
// on the swept stack.
61
60
sweepSpans [2 ]gcSweepBuf
62
61
63
- _ uint32 // align uint64 fields on 32-bit for atomics
62
+ // _ uint32 // align uint64 fields on 32-bit for atomics
64
63
65
64
// Proportional sweep
66
65
//
@@ -464,7 +463,7 @@ func (h *mheap) coalesce(s *mspan) {
464
463
465
464
// The size is potentially changing so the treap needs to delete adjacent nodes and
466
465
// insert back as a combined node.
467
- h .treapForSpan ( other ) .removeSpan (other )
466
+ h .free .removeSpan (other )
468
467
other .state = mSpanDead
469
468
h .spanalloc .free (unsafe .Pointer (other ))
470
469
}
@@ -482,7 +481,7 @@ func (h *mheap) coalesce(s *mspan) {
482
481
return
483
482
}
484
483
// Since we're resizing other, we must remove it from the treap.
485
- h .treapForSpan ( other ) .removeSpan (other )
484
+ h .free .removeSpan (other )
486
485
487
486
// Round boundary to the nearest physical page size, toward the
488
487
// scavenged span.
@@ -500,7 +499,7 @@ func (h *mheap) coalesce(s *mspan) {
500
499
h .setSpan (boundary , b )
501
500
502
501
// Re-insert other now that it has a new size.
503
- h .treapForSpan ( other ) .insert (other )
502
+ h .free .insert (other )
504
503
}
505
504
506
505
// Coalesce with earlier, later spans.
@@ -1101,57 +1100,27 @@ func (h *mheap) setSpans(base, npage uintptr, s *mspan) {
1101
1100
}
1102
1101
}
1103
1102
1104
- // treapForSpan returns the appropriate treap for a span for
1105
- // insertion and removal.
1106
- func (h * mheap ) treapForSpan (span * mspan ) * mTreap {
1107
- if span .scavenged {
1108
- return & h .scav
1109
- }
1110
- return & h .free
1111
- }
1112
-
1113
- // pickFreeSpan acquires a free span from internal free list
1114
- // structures if one is available. Otherwise returns nil.
1115
- // h must be locked.
1116
- func (h * mheap ) pickFreeSpan (npage uintptr ) * mspan {
1117
- tf := h .free .find (npage )
1118
- ts := h .scav .find (npage )
1119
-
1120
- // Check for whichever treap gave us the smaller, non-nil result.
1121
- // Note that we want the _smaller_ free span, i.e. the free span
1122
- // closer in size to the amount we requested (npage).
1123
- var s * mspan
1124
- if tf .valid () && (! ts .valid () || tf .span ().base () <= ts .span ().base ()) {
1125
- s = tf .span ()
1126
- h .free .erase (tf )
1127
- } else if ts .valid () && (! tf .valid () || tf .span ().base () > ts .span ().base ()) {
1128
- s = ts .span ()
1129
- h .scav .erase (ts )
1130
- }
1131
- return s
1132
- }
1133
-
1134
1103
// Allocates a span of the given size. h must be locked.
1135
1104
// The returned span has been removed from the
1136
1105
// free structures, but its state is still mSpanFree.
1137
1106
func (h * mheap ) allocSpanLocked (npage uintptr , stat * uint64 ) * mspan {
1138
- var s * mspan
1139
-
1140
- s = h .pickFreeSpan (npage )
1141
- if s != nil {
1107
+ t := h .free .find (npage )
1108
+ if t .valid () {
1142
1109
goto HaveSpan
1143
1110
}
1144
- // On failure, grow the heap and try again.
1145
1111
if ! h .grow (npage ) {
1146
1112
return nil
1147
1113
}
1148
- s = h .pickFreeSpan (npage )
1149
- if s != nil {
1114
+ t = h .free . find (npage )
1115
+ if t . valid () {
1150
1116
goto HaveSpan
1151
1117
}
1152
1118
throw ("grew heap, but no adequate free span found" )
1153
1119
1154
1120
HaveSpan:
1121
+ s := t .span ()
1122
+ h .free .erase (t )
1123
+
1155
1124
// Mark span in use.
1156
1125
if s .state != mSpanFree {
1157
1126
throw ("candidate mspan for allocation is not free" )
@@ -1339,8 +1308,8 @@ func (h *mheap) freeSpanLocked(s *mspan, acctinuse, acctidle bool, unusedsince i
1339
1308
// Coalesce span with neighbors.
1340
1309
h .coalesce (s )
1341
1310
1342
- // Insert s into the appropriate treap.
1343
- h .treapForSpan ( s ) .insert (s )
1311
+ // Insert s into the treap.
1312
+ h .free .insert (s )
1344
1313
}
1345
1314
1346
1315
// scavengeLocked scavenges nbytes worth of spans in the free treap by
@@ -1355,10 +1324,11 @@ func (h *mheap) scavengeLocked(nbytes uintptr) {
1355
1324
h .scavengeCredit -= nbytes
1356
1325
return
1357
1326
}
1358
- // Iterate over the treap backwards (from highest address to lowest address)
1359
- // scavenging spans until we've reached our quota of nbytes.
1327
+ // Iterate over the unscavenged spans in the treap backwards (from highest
1328
+ // address to lowest address) scavenging spans until we've reached our
1329
+ // quota of nbytes.
1360
1330
released := uintptr (0 )
1361
- for t := h .free .end (); released < nbytes && t .valid (); {
1331
+ for t := h .free .end (treapIterScav , 0 ); released < nbytes && t .valid (); {
1362
1332
s := t .span ()
1363
1333
r := s .scavenge ()
1364
1334
if r == 0 {
@@ -1373,7 +1343,7 @@ func (h *mheap) scavengeLocked(nbytes uintptr) {
1373
1343
// the same scavenged state adjacent to each other.
1374
1344
h .coalesce (s )
1375
1345
t = n
1376
- h .scav .insert (s )
1346
+ h .free .insert (s )
1377
1347
released += r
1378
1348
}
1379
1349
// If we over-scavenged, turn that extra amount into credit.
@@ -1386,20 +1356,19 @@ func (h *mheap) scavengeLocked(nbytes uintptr) {
1386
1356
// treapNode's span. It then removes the scavenged span from
1387
1357
// unscav and adds it into scav before continuing. h must be locked.
1388
1358
func (h * mheap ) scavengeAllLocked (now , limit uint64 ) uintptr {
1389
- // Iterate over the treap scavenging spans if unused for at least limit time.
1359
+ // Iterate over the unscavenged spans in the treap scavenging spans
1360
+ // if unused for at least limit time.
1390
1361
released := uintptr (0 )
1391
- for t := h .free .start (); t .valid (); {
1362
+ for t := h .free .start (treapIterScav , 0 ); t .valid (); {
1392
1363
s := t .span ()
1393
1364
n := t .next ()
1394
1365
if (now - uint64 (s .unusedsince )) > limit {
1395
1366
r := s .scavenge ()
1396
1367
if r != 0 {
1397
1368
h .free .erase (t )
1398
- // Now that s is scavenged, we must eagerly coalesce it
1399
- // with its neighbors to prevent having two spans with
1400
- // the same scavenged state adjacent to each other.
1369
+ // See (*mheap).scavenge.
1401
1370
h .coalesce (s )
1402
- h .scav .insert (s )
1371
+ h .free .insert (s )
1403
1372
released += r
1404
1373
}
1405
1374
}
0 commit comments