7474 result .inc
7575 i = i * 2
7676 result
77- ExtraSizeBuckets = 2
7877
7978type
8079 PTrunk = ptr Trunk
131130 SmallChunk = object of BaseChunk
132131 next, prev: PSmallChunk # chunks of the same size
133132 alignment: int # alignment value for this chunk
134- alignmentOffset: int # byte offset from addr(c.data) to where Cell pointers start
135- extraSize: int # extra size used for alignment (e.g. sizeof(Cell))
136133 freeList: ptr FreeCell # Singly linked list of cells. They may be from foreign chunks or from the current chunk.
137134 # Should be `nil` when the chunk isn't active in `a.freeSmallChunks`.
138135 free: int32 # Bytes this chunk is able to provide using both the accumulator and free cells.
159156 MemRegion = object
160157 when not defined (gcDestructors):
161158 minLargeObj, maxLargeObj: int
162- freeSmallChunks: array [0 .. max (1 , SmallChunkSize div MemAlign - 1 ), array [Alignments , array [ ExtraSizeBuckets , PSmallChunk ] ]]
159+ freeSmallChunks: array [0 .. max (1 , SmallChunkSize div MemAlign - 1 ), array [Alignments , PSmallChunk ]]
163160 # List of available chunks per size and alignment class. Only one is expected to be active per class.
164161 when defined (gcDestructors):
165162 sharedFreeLists: array [0 .. max (1 , SmallChunkSize div MemAlign - 1 ), ptr FreeCell ]
@@ -486,9 +483,6 @@ proc alignmentIndex(alignment: int): int {.inline.} =
486483 a = a * 2
487484 inc result
488485
489- template extraSizeIndex (extraSize: int ): int =
490- (if extraSize == 0 : 0 else : 1 )
491-
492486iterator allObjects (m: var MemRegion ): pointer {.inline .} =
493487 m.locked = true
494488 for s in elements (m.chunkStarts):
@@ -763,23 +757,22 @@ else:
763757 # # checks some (not all yet) invariants of the allocator's data structures.
764758 for s in low (a.freeSmallChunks).. high (a.freeSmallChunks):
765759 for ai in 0 ..< Alignments :
766- for ei in 0 ..< ExtraSizeBuckets :
767- var c = a.freeSmallChunks[s][ai][ei]
768- while not (c == nil ):
769- if c.next == c:
770- echo " [SYSASSERT] c.next == c"
771- return false
772- if not (c.size == s * MemAlign ):
773- echo " [SYSASSERT] c.size != s * MemAlign"
760+ var c = a.freeSmallChunks[s][ai]
761+ while not (c == nil ):
762+ if c.next == c:
763+ echo " [SYSASSERT] c.next == c"
764+ return false
765+ if not (c.size == s * MemAlign ):
766+ echo " [SYSASSERT] c.size != s * MemAlign"
767+ return false
768+ var it = c.freeList
769+ while not (it == nil ):
770+ if not (it.zeroField == 0 ):
771+ echo " [SYSASSERT] it.zeroField != 0"
772+ c_printf (" %ld %p\n " , it.zeroField, it)
774773 return false
775- var it = c.freeList
776- while not (it == nil ):
777- if not (it.zeroField == 0 ):
778- echo " [SYSASSERT] it.zeroField != 0"
779- c_printf (" %ld %p\n " , it.zeroField, it)
780- return false
781- it = it.next
782- c = c.next
774+ it = it.next
775+ c = c.next
783776 result = true
784777
785778when false :
@@ -917,8 +910,7 @@ proc rawAlloc(a: var MemRegion, requestedSize: int, alignment: int = MemAlign, e
917910 # allocate a small block: for small chunks, we use only its next pointer
918911 let s = size div MemAlign
919912 let ai = alignmentIndex (clampedAlignment)
920- let ei = extraSizeIndex (extraSize)
921- var c = a.freeSmallChunks[s][ai][ei]
913+ var c = a.freeSmallChunks[s][ai]
922914 if c == nil :
923915 # There is no free chunk of the requested size available, we need a new one.
924916 c = getSmallChunk (a)
@@ -940,9 +932,7 @@ proc rawAlloc(a: var MemRegion, requestedSize: int, alignment: int = MemAlign, e
940932 c.alignment = clampedAlignment
941933 c.acc = 0
942934 let alignmentOffset = startAddr - baseAddr
943- c.alignmentOffset = alignmentOffset
944- c.extraSize = extraSize
945- c.free = SmallChunkSize - smallChunkOverhead () - alignmentOffset.int32
935+ c.free = SmallChunkSize - smallChunkOverhead () - size.int32 - alignmentOffset.int32
946936 sysAssert c.owner == addr (a), " rawAlloc: No owner set!"
947937 c.next = nil
948938 c.prev = nil
@@ -952,7 +942,7 @@ proc rawAlloc(a: var MemRegion, requestedSize: int, alignment: int = MemAlign, e
952942 if c.free >= size:
953943 # Because removals from `a.freeSmallChunks[s][ai]` only happen in the other alloc branch and during dealloc,
954944 # we must not add it to the list if it cannot be used the next time a pointer of `size` bytes is needed.
955- listAdd (a.freeSmallChunks[s][ai][ei] , c)
945+ listAdd (a.freeSmallChunks[s][ai], c)
956946 result = cast [pointer ](startAddr)
957947 inc (c.acc, size)
958948 # Verify alignment of user data
@@ -964,13 +954,12 @@ proc rawAlloc(a: var MemRegion, requestedSize: int, alignment: int = MemAlign, e
964954 # There is a free chunk of the requested size available, use it.
965955 sysAssert (allocInv (a), " rawAlloc: begin c != nil" )
966956 sysAssert (c.alignment == clampedAlignment, " rawAlloc: chunk alignment mismatch" )
967- sysAssert (c.extraSize == extraSize, " rawAlloc: chunk extraSize mismatch" )
968957 sysAssert c.next != c, " rawAlloc 5"
969958 # if c.size != size:
970959 # c_fprintf(stdout, "csize: %lld; size %lld\n", c.size, size)
971960 sysAssert c.size == size, " rawAlloc 6"
972961 let baseAddr = cast [int ](addr (c.data))
973- let startAddr = baseAddr + c.alignmentOffset
962+ let startAddr = baseAddr
974963 if c.freeList == nil :
975964 sysAssert (c.acc.int + smallChunkOverhead () <= SmallChunkSize ,
976965 " rawAlloc 7" )
@@ -1006,7 +995,7 @@ proc rawAlloc(a: var MemRegion, requestedSize: int, alignment: int = MemAlign, e
1006995 if c.free < size:
1007996 # Even after fetching shared cells the chunk has no usable memory left. It is no longer the active chunk
1008997 sysAssert (allocInv (a), " rawAlloc: before listRemove test" )
1009- listRemove (a.freeSmallChunks[s][ai][ei] , c)
998+ listRemove (a.freeSmallChunks[s][ai], c)
1010999 sysAssert (allocInv (a), " rawAlloc: end listRemove test" )
10111000 # Verify that cells are at expected boundaries
10121001 let baseAddr = cast [int ](addr (c.data))
@@ -1098,8 +1087,7 @@ proc rawDealloc(a: var MemRegion, p: pointer) =
10981087 nimSetMem (cast [pointer ](cast [int ](p) +% sizeof (FreeCell )), - 1 'i32 ,
10991088 s -% sizeof (FreeCell ))
11001089 let ai = alignmentIndex (c.alignment)
1101- let ei = extraSizeIndex (c.extraSize)
1102- let activeChunk = a.freeSmallChunks[s div MemAlign ][ai][ei]
1090+ let activeChunk = a.freeSmallChunks[s div MemAlign ][ai]
11031091 if activeChunk != nil and c != activeChunk:
11041092 # This pointer is not part of the active chunk, lend it out
11051093 # and do not adjust the current chunk (same logic as compensateCounters.)
@@ -1115,15 +1103,15 @@ proc rawDealloc(a: var MemRegion, p: pointer) =
11151103 c.freeList = f
11161104 if c.free < s:
11171105 # The chunk could not have been active as it didn't have enough space to give
1118- listAdd (a.freeSmallChunks[s div MemAlign ][ai][ei] , c)
1106+ listAdd (a.freeSmallChunks[s div MemAlign ][ai], c)
11191107 inc (c.free, s)
11201108 else :
11211109 inc (c.free, s)
11221110 # Free only if the entire chunk is unused and there are no borrowed cells.
11231111 # If the chunk were to be freed while it references foreign cells,
11241112 # the foreign chunks will leak memory and can never be freed.
1125- if c.free == SmallChunkSize - smallChunkOverhead () - c.alignmentOffset and c.foreignCells == 0 :
1126- listRemove (a.freeSmallChunks[s div MemAlign ][ai][ei] , c)
1113+ if c.free == SmallChunkSize - smallChunkOverhead () and c.foreignCells == 0 :
1114+ listRemove (a.freeSmallChunks[s div MemAlign ][ai], c)
11271115 c.size = SmallChunkSize
11281116 freeBigChunk (a, cast [PBigChunk ](c))
11291117 else :
@@ -1155,12 +1143,9 @@ when not defined(gcDestructors):
11551143 if not chunkUnused (c):
11561144 if isSmallChunk (c):
11571145 var c = cast [PSmallChunk ](c)
1158- let baseAddr = cast [int ](addr (c.data))
1159- let cellStart = baseAddr + c.alignmentOffset
1160- var offset = cast [int ](p) - cellStart
1161- # Check if this is a valid Cell pointer at the right offset boundary
1162- let maxOffset = SmallChunkSize - smallChunkOverhead () - c.alignmentOffset
1163- result = (offset >= 0 ) and (offset < maxOffset) and (offset %% c.size == 0 ) and
1146+ let alignedDataStart = (cast [int ](addr (c.data)) + c.alignment - 1 ) and not (c.alignment - 1 )
1147+ var offset = cast [int ](p) - alignedDataStart
1148+ result = (offset >= 0 ) and (c.acc.int > offset) and (offset %% c.size == 0 ) and
11641149 (cast [ptr FreeCell ](p).zeroField > % 1 )
11651150 else :
11661151 var c = cast [PBigChunk ](c)
@@ -1181,13 +1166,11 @@ when not defined(gcDestructors):
11811166 if not chunkUnused (c):
11821167 if isSmallChunk (c):
11831168 var c = cast [PSmallChunk ](c)
1184- let baseAddr = cast [int ](addr (c.data))
1185- let cellStart = baseAddr + c.alignmentOffset
1186- var offset = cast [int ](p) - cellStart
1187- let maxOffset = SmallChunkSize - smallChunkOverhead () - c.alignmentOffset
1188- if offset >= 0 and offset < maxOffset:
1189- # Find the Cell at the cell boundary containing this pointer
1190- var d = cast [ptr FreeCell ](cellStart +%
1169+ var offset = (cast [int ](p) and (PageSize - 1 )) -% smallChunkOverhead ()
1170+ if c.acc.int > % offset:
1171+ sysAssert (cast [int ](addr (c.data)) +% offset ==
1172+ cast [int ](p), " offset is not what you think it is" )
1173+ var d = cast [ptr FreeCell ](cast [int ](addr (c.data)) +%
11911174 offset -% (offset %% c.size))
11921175 if d.zeroField > % 1 :
11931176 result = d
0 commit comments