@@ -76,6 +76,13 @@ const (
76
76
blockStateMask blockState = 3 // 11
77
77
)
78
78
79
+ // The byte value of a block where every block is a 'tail' block.
80
+ const blockStateByteAllTails = 0 |
81
+ uint8 (blockStateTail << (stateBits * 3 )) |
82
+ uint8 (blockStateTail << (stateBits * 2 )) |
83
+ uint8 (blockStateTail << (stateBits * 1 )) |
84
+ uint8 (blockStateTail << (stateBits * 0 ))
85
+
79
86
// String returns a human-readable version of the block state, for debugging.
80
87
func (s blockState ) String () string {
81
88
switch s {
@@ -123,7 +130,25 @@ func (b gcBlock) address() uintptr {
123
130
// points to an allocated object. It returns the same block if this block
124
131
// already points to the head.
125
132
func (b gcBlock ) findHead () gcBlock {
126
- for b .state () == blockStateTail {
133
+ for {
134
+ // Optimization: check whether the current block state byte (which
135
+ // contains the state of multiple blocks) is composed entirely of tail
136
+ // blocks. If so, we can skip back to the last block in the previous
137
+ // state byte.
138
+ // This optimization speeds up findHead for pointers that point into a
139
+ // large allocation.
140
+ stateByte := b .stateByte ()
141
+ if stateByte == blockStateByteAllTails {
142
+ b -= (b % blocksPerStateByte ) + 1
143
+ continue
144
+ }
145
+
146
+ // Check whether we've found a non-tail block, which means we found the
147
+ // head.
148
+ state := b .stateFromByte (stateByte )
149
+ if state != blockStateTail {
150
+ break
151
+ }
127
152
b --
128
153
}
129
154
if gcAsserts {
@@ -146,10 +171,19 @@ func (b gcBlock) findNext() gcBlock {
146
171
return b
147
172
}
148
173
174
+ func (b gcBlock ) stateByte () byte {
175
+ return * (* uint8 )(unsafe .Add (metadataStart , b / blocksPerStateByte ))
176
+ }
177
+
178
+ // Return the block state given a state byte. The state byte must have been
179
+ // obtained using b.stateByte(), otherwise the result is incorrect.
180
+ func (b gcBlock ) stateFromByte (stateByte byte ) blockState {
181
+ return blockState (stateByte >> ((b % blocksPerStateByte )* stateBits )) & blockStateMask
182
+ }
183
+
149
184
// State returns the current block state.
150
185
func (b gcBlock ) state () blockState {
151
- stateBytePtr := (* uint8 )(unsafe .Add (metadataStart , b / blocksPerStateByte ))
152
- return blockState (* stateBytePtr >> ((b % blocksPerStateByte )* stateBits )) & blockStateMask
186
+ return b .stateFromByte (b .stateByte ())
153
187
}
154
188
155
189
// setState sets the current block to the given state, which must contain more
0 commit comments