in alloc.go [639:682]
func (a *dataAllocator) Free(st *txAllocState, id PageID) {
traceln("free page:", id)
if id < 2 || id >= a.data.endMarker {
panic(fmt.Sprintf("freed page ID %v out of bounds", id))
}
a.onFree(st, 1)
if !st.data.new.Has(id) {
// fast-path, page has not been allocated in current transaction
st.data.freed.Add(id)
return
}
// page has been allocated in current transaction -> return to allocator for immediate re-use
a.data.freelist.AddRegion(region{id: id, count: 1})
if st.data.endMarker >= id {
// allocation from within old data region
return
}
// allocation was from past the old end-marker. Check if we can shrink the
// end marker again
regions := a.data.freelist.regions
last := len(regions) - 1
start, end := regions[last].Range()
if end < a.data.endMarker {
// in middle of new data region -> can not adjust end marker -> keep update to freelist
return
}
if st.data.endMarker > start {
start = st.data.endMarker
count := uint(end - start)
regions[last].count -= uint32(count)
a.data.freelist.avail -= count
} else {
a.data.freelist.avail -= uint(regions[last].count)
a.data.freelist.regions = regions[:last]
}
a.data.endMarker = start
}