Skip to content

Commit

Permalink
Simplify algorithm
Browse files Browse the repository at this point in the history
  • Loading branch information
HattoriHanzo031 committed Sep 9, 2023
1 parent 75f82df commit 27f42da
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 24 deletions.
4 changes: 2 additions & 2 deletions builder/sizes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ func TestBinarySize(t *testing.T) {
// This is a small number of very diverse targets that we want to test.
tests := []sizeTest{
// microcontrollers
{"hifive1b", "examples/echo", 4720, 280, 0, 2252},
{"microbit", "examples/serial", 2820, 388, 8, 2256},
{"hifive1b", "examples/echo", 4716, 280, 0, 2252},
{"microbit", "examples/serial", 2816, 388, 8, 2256},
{"wioterminal", "examples/pininterrupt", 6091, 1485, 116, 6816},

// TODO: also check wasm. Right now this is difficult, because
Expand Down
34 changes: 12 additions & 22 deletions src/runtime/gc_blocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,35 +123,25 @@ func (b gcBlock) address() uintptr {
return addr
}

// findHead returns the head (first block) of an object, assuming the block
// points to an allocated object. It returns the same block if this block
// already points to the head.
func (b gcBlock) findHead() gcBlock {
stateBytePtr := (*uint8)(unsafe.Add(metadataStart, b/blocksPerStateByte))

// XOR the stateByte with byte containing all tails to turn tail bits to 0
// and shift out the bits that are not part of the object
stateByte := ((*stateBytePtr) ^ blockStateByteAllTails) << ((blocksPerStateByte - (b%blocksPerStateByte + 1)) * stateBits)
// if stateByte is 0 that means all blocks are tails so we loop trough subsequent states,
// byte at a time to find the first byte that is not all tails
if stateByte == 0 {
// subtract the number of object blocks that were in the first byte
b -= (b%blocksPerStateByte + 1)
// skip to next byte
// XOR the stateByte with byte containing all tails to turn tail bits to 0 and
// mask out the bits that are not part of the object
otherObjectBlocks := int(blocksPerStateByte - (b%blocksPerStateByte + 1))
stateByte := ((*stateBytePtr) ^ blockStateByteAllTails) & (uint8(1<<(8-(otherObjectBlocks*stateBits))) - 1)

// loop until state byte is not all tails
for stateByte == 0 {
stateBytePtr = (*uint8)(unsafe.Add(unsafe.Pointer(stateBytePtr), -1))
// loop until state byte is not all tails
for (*stateBytePtr)^blockStateByteAllTails == 0 {
stateBytePtr = (*uint8)(unsafe.Add(unsafe.Pointer(stateBytePtr), -1))
b -= blocksPerStateByte
}
// set stateByte variable to the first byte that is not all tails and turn all tail bits to zeroes
stateByte = (*stateBytePtr) ^ blockStateByteAllTails
b -= blocksPerStateByte
}

// at this point stateByte is set to the first state byte of the object that we encountered which is not all tails
// and all tail bits in it are turned to zero. We count number of bytes that are 0 (tail) using LeadingZeros8
// and divide it by stateBits to get the number of tail blocks in state bits.
b -= gcBlock(bits.LeadingZeros8(stateByte) / stateBits)
// in the first state byte which is not all tails, count the number of leading bits that are 0 and
// divide it by stateBits to get the number of tail blocks. Subtract otherObjectBlocks to exclude
// blocks that are not part of the object
b -= gcBlock((bits.LeadingZeros8(stateByte) / stateBits) - otherObjectBlocks)

if gcAsserts {
if b.state() != blockStateHead && b.state() != blockStateMark {
Expand Down

0 comments on commit 27f42da

Please sign in to comment.