Skip to content

Commit ac5ae28

Browse files
committed
fixes
1 parent 9070c89 commit ac5ae28

File tree

1 file changed

+33
-50
lines changed

1 file changed

+33
-50
lines changed

lib/system/alloc.nim

Lines changed: 33 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@ const
7474
result.inc
7575
i = i * 2
7676
result
77-
ExtraSizeBuckets = 2
7877

7978
type
8079
PTrunk = ptr Trunk
@@ -131,8 +130,6 @@ type
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.
@@ -159,7 +156,7 @@ type
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-
492486
iterator 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

785778
when 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

Comments
 (0)