5252 metadataStart unsafe.Pointer // pointer to the start of the heap metadata
5353 nextAlloc gcBlock // the next block that should be tried by the allocator
5454 endBlock gcBlock // the block just past the end of the available space
55+ maxBlock gcBlock // maximum block that has been allocated
5556 gcTotalAlloc uint64 // total number of bytes allocated
5657 gcTotalBlocks uint64 // total number of allocated blocks
5758 gcMallocs uint64 // total number of allocations
@@ -377,6 +378,9 @@ func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer {
377378 size -= add
378379 }
379380 memzero (pointer , size )
381+ if nextAlloc > maxBlock {
382+ maxBlock = nextAlloc - 1
383+ }
380384 return pointer
381385 }
382386 }
@@ -586,7 +590,7 @@ func finishMark() {
586590 for stackOverflow {
587591 // Re-mark all blocks.
588592 stackOverflow = false
589- for block := gcBlock (0 ); block < endBlock ; block ++ {
593+ for block := gcBlock (0 ); block <= maxBlock ; block ++ {
590594 if block .state () != blockStateMark {
591595 // Block is not marked, so we do not need to rescan it.
592596 continue
@@ -621,9 +625,10 @@ func markRoot(addr, root uintptr) {
621625// Sweep goes through all memory and frees unmarked memory.
622626// It returns how many bytes are free in the heap after the sweep.
623627func sweep () (freeBytes uintptr ) {
628+ var lastBlock gcBlock
624629 freeCurrentObject := false
625630 var freed uint64
626- for block := gcBlock (0 ); block < endBlock ; block ++ {
631+ for block := gcBlock (0 ); block <= maxBlock ; block ++ {
627632 switch block .state () {
628633 case blockStateHead :
629634 // Unmarked head. Free it, including all tail blocks following it.
@@ -637,19 +642,29 @@ func sweep() (freeBytes uintptr) {
637642 // Free it now.
638643 block .markFree ()
639644 freed ++
645+ freeBytes += bytesPerBlock
646+ } else {
647+ lastBlock = block
640648 }
641649 case blockStateMark :
642650 // This is a marked object. The next tail blocks must not be freed,
643651 // but the mark bit must be removed so the next GC cycle will
644652 // collect this object if it is unreferenced then.
645653 block .unmark ()
646654 freeCurrentObject = false
655+ lastBlock = block
647656 case blockStateFree :
648657 freeBytes += bytesPerBlock
649658 }
650659 }
660+
651661 gcFreedBlocks += freed
652662 freeBytes += uintptr (freed ) * bytesPerBlock
663+
664+ if gcAsserts && lastBlock > maxBlock {
665+ runtimePanic ("gc: lastblock > maxBlock" )
666+ }
667+ maxBlock = lastBlock
653668 return
654669}
655670
0 commit comments