Skip to content

Commit c34ea10

Browse files
committed
Introduced realloc0 and reallocShared0, these procs are now used by
strs_v2 and seqs_v2. This also allowed the -d:useMalloc allocator to drop the extra header with allocation length.
1 parent 7c22f51 commit c34ea10

File tree

7 files changed

+91
-39
lines changed

7 files changed

+91
-39
lines changed

lib/system/alloc.nim

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -948,13 +948,18 @@ proc dealloc(allocator: var MemRegion, p: pointer) =
948948
949949
proc realloc(allocator: var MemRegion, p: pointer, newsize: Natural): pointer =
950950
if newsize > 0:
951-
result = alloc0(allocator, newsize)
951+
result = alloc(allocator, newsize)
952952
if p != nil:
953953
copyMem(result, p, min(ptrSize(p), newsize))
954954
dealloc(allocator, p)
955955
elif p != nil:
956956
dealloc(allocator, p)
957957
958+
proc realloc0(allocator: var MemRegion, p: pointer, oldsize, newsize: Natural): pointer =
959+
result = realloc(allocator, p, newsize)
960+
if newsize > oldsize:
961+
zeroMem(cast[pointer](cast[int](result) + oldsize), newsize - oldsize)
962+
958963
proc deallocOsPages(a: var MemRegion) =
959964
# we free every 'ordinarily' allocated page by iterating over the page bits:
960965
var it = addr(a.heapLinks)
@@ -1009,6 +1014,11 @@ template instantiateForRegion(allocator: untyped) {.dirty.} =
10091014
proc realloc(p: pointer, newSize: Natural): pointer =
10101015
result = realloc(allocator, p, newSize)
10111016
1017+
proc realloc0(p: pointer, oldSize, newSize: Natural): pointer =
1018+
result = realloc(allocator, p, newSize)
1019+
if newSize > oldSize:
1020+
zeroMem(cast[pointer](cast[int](result) + oldSize), newSize - oldSize)
1021+
10121022
when false:
10131023
proc countFreeMem(): int =
10141024
# only used for assertions
@@ -1062,6 +1072,14 @@ template instantiateForRegion(allocator: untyped) {.dirty.} =
10621072
else:
10631073
result = realloc(p, newSize)
10641074
1075+
proc reallocShared0(p: pointer, oldSize, newSize: Natural): pointer =
1076+
when hasThreadSupport:
1077+
acquireSys(heapLock)
1078+
result = realloc0(sharedHeap, p, oldSize, newSize)
1079+
releaseSys(heapLock)
1080+
else:
1081+
result = realloc0(p, oldSize, newSize)
1082+
10651083
when hasThreadSupport:
10661084
template sharedMemStatsShared(v: int) =
10671085
acquireSys(heapLock)

lib/system/ansi_c.nim

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ proc c_sprintf*(buf, frmt: cstring): cint {.
140140

141141
proc c_malloc*(size: csize_t): pointer {.
142142
importc: "malloc", header: "<stdlib.h>".}
143+
proc c_calloc*(nmemb, size: csize_t): pointer {.
144+
importc: "calloc", header: "<stdlib.h>".}
143145
proc c_free*(p: pointer) {.
144146
importc: "free", header: "<stdlib.h>".}
145147
proc c_realloc*(p: pointer, newsize: csize_t): pointer {.

lib/system/gc_regions.nim

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,11 @@ proc alloc0(size: Natural): pointer =
386386
proc realloc(p: pointer, newsize: Natural): pointer =
387387
result = c_realloc(p, cast[csize_t](newsize))
388388
if result == nil: raiseOutOfMem()
389+
proc realloc0(p: pointer, oldsize, newsize: Natural): pointer =
390+
result = c_realloc(p, cast[csize_t](newsize))
391+
if result == nil: raiseOutOfMem()
392+
if newsize > oldsize:
393+
zeroMem(cast[pointer](cast[int](result) + oldsize), newsize - oldsize)
389394
proc dealloc(p: pointer) = c_free(p)
390395
391396
proc alloc0(r: var MemRegion; size: Natural): pointer =
@@ -409,6 +414,11 @@ proc allocShared0(size: Natural): pointer =
409414
proc reallocShared(p: pointer, newsize: Natural): pointer =
410415
result = c_realloc(p, cast[csize_t](newsize))
411416
if result == nil: raiseOutOfMem()
417+
proc reallocShared0(p: pointer, oldsize, newsize: Natural): pointer =
418+
result = c_realloc(p, cast[csize_t](newsize))
419+
if result == nil: raiseOutOfMem()
420+
if newsize > oldsize:
421+
zeroMem(cast[pointer](cast[int](result) + oldsize), newsize - oldsize)
412422
proc deallocShared(p: pointer) = c_free(p)
413423
414424
when hasThreadSupport:

lib/system/memalloc.nim

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,22 @@ when hasAlloc:
9797
## The allocated memory belongs to its allocating thread!
9898
## Use `reallocShared <#reallocShared,pointer,Natural>`_ to reallocate
9999
## from a shared heap.
100+
proc realloc0*(p: pointer, oldSize, newSize: Natural): pointer {.noconv, rtl, tags: [],
101+
benign, raises: [].}
102+
## Grows or shrinks a given memory block.
103+
##
104+
## If `p` is **nil** then a new memory block is returned.
105+
## In either way the block has at least ``newSize`` bytes.
106+
## If ``newSize == 0`` and `p` is not **nil** ``realloc`` calls ``dealloc(p)``.
107+
## In other cases the block has to be freed with
108+
## `dealloc(block) <#dealloc,pointer>`_.
109+
##
110+
## The block is initialized with all bytes containing zero, so it is
111+
## somewhat safer then realloc
112+
##
113+
## The allocated memory belongs to its allocating thread!
114+
## Use `reallocShared <#reallocShared,pointer,Natural>`_ to reallocate
115+
## from a shared heap.
100116
proc resize*[T](p: ptr T, newSize: Natural): ptr T {.inline, benign, raises: [].} =
101117
## Grows or shrinks a given memory block.
102118
##
@@ -185,6 +201,19 @@ when hasAlloc:
185201
## ``deallocShared(p)``.
186202
## In other cases the block has to be freed with
187203
## `deallocShared <#deallocShared,pointer>`_.
204+
proc reallocShared0*(p: pointer, oldSize, newSize: Natural): pointer {.noconv, rtl, tags: [],
205+
benign, raises: [].}
206+
## Grows or shrinks a given memory block on the heap.
207+
##
208+
## When growing, the new bytes of the block is initialized with all bytes
209+
## containing zero, so it is somewhat safer then reallocShared
210+
##
211+
## If `p` is **nil** then a new memory block is returned.
212+
## In either way the block has at least ``newSize`` bytes.
213+
## If ``newSize == 0`` and `p` is not **nil** ``reallocShared`` calls
214+
## ``deallocShared(p)``.
215+
## In other cases the block has to be freed with
216+
## `deallocShared <#deallocShared,pointer>`_.
188217
proc resizeShared*[T](p: ptr T, newSize: Natural): ptr T {.inline, raises: [].} =
189218
## Grows or shrinks a given memory block on the heap.
190219
##
@@ -239,11 +268,13 @@ when defined(js):
239268
proc alloc(size: Natural): pointer = discard
240269
proc alloc0(size: Natural): pointer = discard
241270
proc realloc(p: pointer, newsize: Natural): pointer = discard
271+
proc realloc0(p: pointer, oldsize, newsize: Natural): pointer = discard
242272
243273
proc allocShared(size: Natural): pointer = discard
244274
proc allocShared0(size: Natural): pointer = discard
245275
proc deallocShared(p: pointer) = discard
246276
proc reallocShared(p: pointer, newsize: Natural): pointer = discard
277+
proc reallocShared0(p: pointer, oldsize, newsize: Natural): pointer = discard
247278
248279
249280
when hasAlloc and hasThreadSupport:

lib/system/mmdisp.nim

Lines changed: 25 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -115,17 +115,18 @@ when defined(boehmgc):
115115
proc realloc(p: pointer, newSize: Natural): pointer =
116116
result = boehmRealloc(p, newSize)
117117
if result == nil: raiseOutOfMem()
118-
proc dealloc(p: pointer) = boehmDealloc(p)
119-
120-
proc allocShared(size: Natural): pointer =
121-
result = boehmAlloc(size)
122-
if result == nil: raiseOutOfMem()
123-
proc allocShared0(size: Natural): pointer =
124-
result = allocShared(size)
125-
proc reallocShared(p: pointer, newSize: Natural): pointer =
118+
proc realloc0(p: pointer, oldSize, newSize: Natural): pointer =
126119
result = boehmRealloc(p, newSize)
127120
if result == nil: raiseOutOfMem()
128-
proc deallocShared(p: pointer) = boehmDealloc(p)
121+
if newsize > oldsize:
122+
zeroMem(cast[pointer](cast[int](result) + oldsize), newsize - oldsize)
123+
proc dealloc(p: pointer) = boehmDealloc(p)
124+
125+
proc allocShared(size: Natural): pointer = alloc(size)
126+
proc allocShared0(size: Natural): pointer = alloc(size)
127+
proc reallocShared(p: pointer, newSize: Natural): pointer = realloc(p, newSize)
128+
proc reallocShared0(p: pointer, oldSize, newSize: Natural): pointer = realloc0(p, newSize, oldSize)
129+
proc deallocShared(p: pointer) = dealloc(p)
129130

130131
when hasThreadSupport:
131132
proc getFreeSharedMem(): int =
@@ -274,6 +275,9 @@ elif defined(gogc):
274275
proc realloc(p: pointer, newsize: Natural): pointer =
275276
doAssert false, "not implemented"
276277
278+
proc realloc0(p: pointer, oldsize, newsize: Natural): pointer =
279+
doAssert false, "not implemented"
280+
277281
proc dealloc(p: pointer) =
278282
discard
279283
@@ -286,6 +290,9 @@ elif defined(gogc):
286290
proc reallocShared(p: pointer, newsize: Natural): pointer =
287291
result = realloc(p, newsize)
288292
293+
proc reallocShared0(p: pointer, oldsize, newsize: Natural): pointer =
294+
result = realloc0(p, oldsize, newsize)
295+
289296
proc deallocShared(p: pointer) = dealloc(p)
290297
291298
when hasThreadSupport:
@@ -356,39 +363,21 @@ elif defined(gogc):
356363
357364
elif (defined(nogc) or defined(gcDestructors)) and defined(useMalloc):
358365
359-
# libc realloc() does not zero out memory, so this is handled here. Every
360-
# allocated buffer is prepended with the size of the allocation which is used
361-
# to deduce which part of the buffer to zero.
362-
363366
when not defined(useNimRtl):
364367
365-
proc alloc(size: Natural): pointer =
366-
var x = c_malloc (size + sizeof(size)).csize_t
367-
if x == nil: raiseOutOfMem()
368-
cast[ptr int](x)[] = size
369-
result = cast[pointer](cast[int](x) + sizeof(size))
370-
371-
proc alloc0(size: Natural): pointer =
372-
result = alloc(size)
373-
zeroMem(result, size)
374-
375-
proc realloc(p: pointer, newsize: Natural): pointer =
376-
var x = cast[pointer](cast[int](p) - sizeof(newsize))
377-
let oldsize = cast[ptr int](x)[]
378-
x = c_realloc(x, (newsize + sizeof(newsize)).csize_t)
379-
if x == nil: raiseOutOfMem()
380-
cast[ptr int](x)[] = newsize
381-
result = cast[pointer](cast[int](x) + sizeof(newsize))
368+
proc alloc(size: Natural): pointer = c_malloc(size.csize_t)
369+
proc alloc0(size: Natural): pointer = c_calloc(size.csize_t, 1)
370+
proc realloc(p: pointer, newsize: Natural): pointer = c_realloc(p, newSize.csize_t)
371+
proc realloc0(p: pointer, oldsize, newsize: Natural): pointer =
372+
result = realloc(p, newsize.csize_t)
382373
if newsize > oldsize:
383374
zeroMem(cast[pointer](cast[int](result) + oldsize), newsize - oldsize)
375+
proc dealloc(p: pointer) = c_free(p)
384376
385-
proc dealloc(p: pointer) = c_free(cast[pointer](cast[int](p) - sizeof(int)))
386-
387-
# Shared allocators map to the regular ones
388-
389-
proc allocShared(size: Natural): pointer = alloc(size.csize_t)
377+
proc allocShared(size: Natural): pointer = alloc(size)
390378
proc allocShared0(size: Natural): pointer = alloc0(size)
391-
proc reallocShared(p: pointer, newsize: Natural): pointer = realloc(p, newsize.csize_t)
379+
proc reallocShared(p: pointer, newsize: Natural): pointer = realloc(p, newsize)
380+
proc reallocShared0(p: pointer, oldsize, newsize: Natural): pointer = realloc0(p, oldsize, newsize)
392381
proc deallocShared(p: pointer) = dealloc(p)
393382
394383
proc GC_disable() = discard

lib/system/seqs_v2.nim

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,9 @@ proc prepareSeqAdd(len: int; p: pointer; addlen, elemSize: int): pointer {.
6969
q.cap = cap
7070
result = q
7171
else:
72-
var q = cast[ptr NimSeqPayloadBase](reallocShared(p, headerSize + elemSize * cap))
72+
let oldSize = headerSize + elemSize * p.cap
73+
let newSize = headerSize + elemSize * cap
74+
var q = cast[ptr NimSeqPayloadBase](reallocShared0(p, oldSize, newSize))
7375
q.allocated = 1
7476
q.cap = cap
7577
result = q

lib/system/strs_v2.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ proc prepareAdd(s: var NimStringV2; addlen: int) {.compilerRtl.} =
5151
copyMem(unsafeAddr s.p.data[0], unsafeAddr oldP.data[0], s.len)
5252
elif s.len + addlen > s.p.cap:
5353
let cap = max(s.len + addlen, resize(s.p.cap))
54-
s.p = cast[ptr NimStrPayload](reallocShared(s.p, contentSize(cap)))
54+
s.p = cast[ptr NimStrPayload](reallocShared0(s.p, contentSize(s.p.cap), contentSize(cap)))
5555
s.p.cap = cap
5656
5757
proc nimAddCharV1(s: var NimStringV2; c: char) {.compilerRtl.} =

0 commit comments

Comments
 (0)