Skip to content

Commit e282884

Browse files
FilipVranesevicHattoriHanzo031
authored andcommitted
Scan optimization
1 parent e9d8a9b commit e282884

File tree

1 file changed

+31
-2
lines changed

1 file changed

+31
-2
lines changed

src/runtime/gc_blocks.go

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ package runtime
3232

3333
import (
3434
"internal/task"
35+
"math/bits"
3536
"runtime/interrupt"
3637
"unsafe"
3738
)
@@ -74,6 +75,11 @@ const (
7475
blockStateMask blockState = 3 // 11
7576
)
7677

78+
// blockStateByteAllTails is a byte containing 4 times blockStateTail bits.
79+
// It assumes there are 2 state bits per block, otherwise it might have to be
80+
// turned into variable and assigned using inline function.
81+
const blockStateByteAllTails = uint8(blockStateTail<<(stateBits*3) | blockStateTail<<(stateBits*2) | blockStateTail<<(stateBits*1) | blockStateTail<<(stateBits*0))
82+
7783
// String returns a human-readable version of the block state, for debugging.
7884
func (s blockState) String() string {
7985
switch s {
@@ -121,9 +127,32 @@ func (b gcBlock) address() uintptr {
121127
// points to an allocated object. It returns the same block if this block
122128
// already points to the head.
123129
func (b gcBlock) findHead() gcBlock {
124-
for b.state() == blockStateTail {
125-
b--
130+
stateBytePtr := (*uint8)(unsafe.Add(metadataStart, b/blocksPerStateByte))
131+
132+
// XOR the stateByte with byte containing all tails to turn tail bits to 0
133+
// and shift out the bits that are not part of the object
134+
stateByte := ((*stateBytePtr) ^ blockStateByteAllTails) << ((blocksPerStateByte - (b%blocksPerStateByte + 1)) * stateBits)
135+
// if stateByte is 0 that means all blocks are tails so we loop trough subsequent states,
136+
// byte at a time to find the first byte that is not all tails
137+
if stateByte == 0 {
138+
// subtract the number of object blocks that were in the first byte
139+
b -= (b%blocksPerStateByte + 1)
140+
// skip to next byte
141+
stateBytePtr = (*uint8)(unsafe.Add(unsafe.Pointer(stateBytePtr), -1))
142+
// loop until state byte is not all tails
143+
for (*stateBytePtr)^blockStateByteAllTails == 0 {
144+
stateBytePtr = (*uint8)(unsafe.Add(unsafe.Pointer(stateBytePtr), -1))
145+
b -= blocksPerStateByte
146+
}
147+
// set stateByte variable to the first byte that is not all tails and turn all tail bits to zeroes
148+
stateByte = (*stateBytePtr) ^ blockStateByteAllTails
126149
}
150+
151+
// at this point stateByte is set to the first state byte of the object that we encountered which is not all tails
152+
// and all tail bits in it are turned to zero. We count number of bytes that are 0 (tail) using LeadingZeros8
153+
// and divide it by stateBits to get the number of tail blocks in state bits.
154+
b -= gcBlock(bits.LeadingZeros8(stateByte) / stateBits)
155+
127156
if gcAsserts {
128157
if b.state() != blockStateHead && b.state() != blockStateMark {
129158
runtimePanic("gc: found tail without head")

0 commit comments

Comments
 (0)