@@ -33,8 +33,48 @@ when notJSnotNims:
3333 # # otherwise. Like any procedure dealing with raw memory this is
3434 # # **unsafe**.
3535
36- when hasAlloc:
37- proc alloc * (size: Natural ): pointer {.noconv , rtl , tags : [], benign , raises : [].}
36+ when hasAlloc and not defined (js):
37+
38+ proc allocImpl * (size: Natural ): pointer {.noconv , rtl , tags : [], benign , raises : [].}
39+ proc alloc0Impl * (size: Natural ): pointer {.noconv , rtl , tags : [], benign , raises : [].}
40+ proc deallocImpl * (p: pointer ) {.noconv , rtl , tags : [], benign , raises : [].}
41+ proc reallocImpl * (p: pointer , newSize: Natural ): pointer {.noconv , rtl , tags : [], benign , raises : [].}
42+ proc realloc0Impl * (p: pointer , oldSize, newSize: Natural ): pointer {.noconv , rtl , tags : [], benign , raises : [].}
43+
44+ proc allocSharedImpl * (size: Natural ): pointer {.noconv , compilerproc , rtl , benign , raises : [], tags : [].}
45+ proc allocShared0Impl * (size: Natural ): pointer {.noconv , rtl , benign , raises : [], tags : [].}
46+ proc deallocSharedImpl * (p: pointer ) {.noconv , rtl , benign , raises : [], tags : [].}
47+ proc reallocSharedImpl * (p: pointer , newSize: Natural ): pointer {.noconv , rtl , tags : [], benign , raises : [].}
48+ proc reallocShared0Impl * (p: pointer , oldSize, newSize: Natural ): pointer {.noconv , rtl , tags : [], benign , raises : [].}
49+
50+ # Allocator statistics for memory leak tests
51+
52+ {.push stackTrace : off .}
53+
54+ type AllocStats * = object
55+ allocCount: int
56+ deallocCount: int
57+
58+ proc `-` * (a, b: AllocStats ): AllocStats =
59+ result .allocCount = a.allocCount - b.allocCount
60+ result .deallocCount = a.deallocCount - b.deallocCount
61+
62+ template dumpAllocstats * (code: untyped ) =
63+ let stats1 = getAllocStats ()
64+ code
65+ let stats2 = getAllocStats ()
66+ echo $ (stats2 - stats1)
67+
68+ when defined (allocStats):
69+ var stats: AllocStats
70+ template incStat (what: untyped ) = inc stats.what
71+ proc getAllocStats * (): AllocStats = stats
72+
73+ else :
74+ template incStat (what: untyped ) = discard
75+ proc getAllocStats * (): AllocStats = discard
76+
77+ template alloc * (size: Natural ): pointer =
3878 # # Allocates a new memory block with at least ``size`` bytes.
3979 # #
4080 # # The block has to be freed with `realloc(block, 0) <#realloc,pointer,Natural>`_
@@ -47,6 +87,9 @@ when hasAlloc:
4787 # #
4888 # # See also:
4989 # # * `alloc0 <#alloc0,Natural>`_
90+ incStat (allocCount)
91+ allocImpl (size)
92+
5093 proc createU * (T: typedesc , size = 1 .Positive ): ptr T {.inline , benign , raises : [].} =
5194 # # Allocates a new memory block with at least ``T.sizeof * size`` bytes.
5295 # #
@@ -62,7 +105,7 @@ when hasAlloc:
62105 # # * `create <#create,typedesc>`_
63106 cast [ptr T](alloc (T.sizeof * size))
64107
65- proc alloc0 * (size: Natural ): pointer {. noconv , rtl , tags : [], benign , raises : [].}
108+ template alloc0 * (size: Natural ): pointer =
66109 # # Allocates a new memory block with at least ``size`` bytes.
67110 # #
68111 # # The block has to be freed with `realloc(block, 0) <#realloc,pointer,Natural>`_
@@ -72,6 +115,9 @@ when hasAlloc:
72115 # #
73116 # # The allocated memory belongs to its allocating thread!
74117 # # Use `allocShared0 <#allocShared0,Natural>`_ to allocate from a shared heap.
118+ incStat (allocCount)
119+ alloc0Impl (size)
120+
75121 proc create * (T: typedesc , size = 1 .Positive ): ptr T {.inline , benign , raises : [].} =
76122 # # Allocates a new memory block with at least ``T.sizeof * size`` bytes.
77123 # #
@@ -84,8 +130,7 @@ when hasAlloc:
84130 # # Use `createShared <#createShared,typedesc>`_ to allocate from a shared heap.
85131 cast [ptr T](alloc0 (sizeof (T) * size))
86132
87- proc realloc * (p: pointer , newSize: Natural ): pointer {.noconv , rtl , tags : [],
88- benign , raises : [].}
133+ template realloc * (p: pointer , newSize: Natural ): pointer =
89134 # # Grows or shrinks a given memory block.
90135 # #
91136 # # If `p` is **nil** then a new memory block is returned.
@@ -97,8 +142,9 @@ when hasAlloc:
97142 # # The allocated memory belongs to its allocating thread!
98143 # # Use `reallocShared <#reallocShared,pointer,Natural>`_ to reallocate
99144 # # from a shared heap.
100- proc realloc0 * (p: pointer , oldSize, newSize: Natural ): pointer {.noconv , rtl , tags : [],
101- benign , raises : [].}
145+ reallocImpl (p, newSize)
146+
147+ template realloc0 * (p: pointer , oldSize, newSize: Natural ): pointer =
102148 # # Grows or shrinks a given memory block.
103149 # #
104150 # # If `p` is **nil** then a new memory block is returned.
@@ -113,6 +159,8 @@ when hasAlloc:
113159 # # The allocated memory belongs to its allocating thread!
114160 # # Use `reallocShared <#reallocShared,pointer,Natural>`_ to reallocate
115161 # # from a shared heap.
162+ realloc0Impl (p, oldSize, newSize)
163+
116164 proc resize * [T](p: ptr T, newSize: Natural ): ptr T {.inline , benign , raises : [].} =
117165 # # Grows or shrinks a given memory block.
118166 # #
@@ -126,7 +174,7 @@ when hasAlloc:
126174 # # from a shared heap.
127175 cast [ptr T](realloc (p, T.sizeof * newSize))
128176
129- proc dealloc * (p: pointer ) {. noconv , rtl , tags : [], benign , raises : [].}
177+ template dealloc * (p: pointer ) =
130178 # # Frees the memory allocated with ``alloc``, ``alloc0`` or
131179 # # ``realloc``.
132180 # #
@@ -137,8 +185,10 @@ when hasAlloc:
137185 # #
138186 # # The freed memory must belong to its allocating thread!
139187 # # Use `deallocShared <#deallocShared,pointer>`_ to deallocate from a shared heap.
188+ incStat (deallocCount)
189+ deallocImpl (p)
140190
141- proc allocShared * (size: Natural ): pointer {. noconv , compilerproc , rtl , benign , raises : [], tags : [].}
191+ template allocShared * (size: Natural ): pointer =
142192 # # Allocates a new memory block on the shared heap with at
143193 # # least ``size`` bytes.
144194 # #
@@ -151,6 +201,9 @@ when hasAlloc:
151201 # #
152202 # # See also:
153203 # # `allocShared0 <#allocShared0,Natural>`_.
204+ incStat (allocCount)
205+ allocSharedImpl (size)
206+
154207 proc createSharedU * (T: typedesc , size = 1 .Positive ): ptr T {.inline , tags : [],
155208 benign , raises : [].} =
156209 # # Allocates a new memory block on the shared heap with at
@@ -167,7 +220,7 @@ when hasAlloc:
167220 # # * `createShared <#createShared,typedesc>`_
168221 cast [ptr T](allocShared (T.sizeof * size))
169222
170- proc allocShared0 * (size: Natural ): pointer {. noconv , rtl , benign , raises : [], tags : [].}
223+ template allocShared0 * (size: Natural ): pointer =
171224 # # Allocates a new memory block on the shared heap with at
172225 # # least ``size`` bytes.
173226 # #
@@ -178,6 +231,9 @@ when hasAlloc:
178231 # # The block is initialized with all bytes
179232 # # containing zero, so it is somewhat safer than
180233 # # `allocShared <#allocShared,Natural>`_.
234+ incStat (allocCount)
235+ allocShared0Impl (size)
236+
181237 proc createShared * (T: typedesc , size = 1 .Positive ): ptr T {.inline .} =
182238 # # Allocates a new memory block on the shared heap with at
183239 # # least ``T.sizeof * size`` bytes.
@@ -191,8 +247,7 @@ when hasAlloc:
191247 # # `createSharedU <#createSharedU,typedesc>`_.
192248 cast [ptr T](allocShared0 (T.sizeof * size))
193249
194- proc reallocShared * (p: pointer , newSize: Natural ): pointer {.noconv , rtl , tags : [],
195- benign , raises : [].}
250+ template reallocShared * (p: pointer , newSize: Natural ): pointer =
196251 # # Grows or shrinks a given memory block on the heap.
197252 # #
198253 # # If `p` is **nil** then a new memory block is returned.
@@ -201,8 +256,9 @@ when hasAlloc:
201256 # # ``deallocShared(p)``.
202257 # # In other cases the block has to be freed with
203258 # # `deallocShared <#deallocShared,pointer>`_.
204- proc reallocShared0 * (p: pointer , oldSize, newSize: Natural ): pointer {.noconv , rtl , tags : [],
205- benign , raises : [].}
259+ reallocSharedImpl (p, newSize)
260+
261+ template reallocShared0 * (p: pointer , oldSize, newSize: Natural ): pointer =
206262 # # Grows or shrinks a given memory block on the heap.
207263 # #
208264 # # When growing, the new bytes of the block is initialized with all bytes
@@ -214,6 +270,8 @@ when hasAlloc:
214270 # # ``deallocShared(p)``.
215271 # # In other cases the block has to be freed with
216272 # # `deallocShared <#deallocShared,pointer>`_.
273+ reallocShared0Impl (p, oldSize, newSize)
274+
217275 proc resizeShared * [T](p: ptr T, newSize: Natural ): ptr T {.inline , raises : [].} =
218276 # # Grows or shrinks a given memory block on the heap.
219277 # #
@@ -225,14 +283,17 @@ when hasAlloc:
225283 # # `freeShared <#freeShared,ptr.T>`_.
226284 cast [ptr T](reallocShared (p, T.sizeof * newSize))
227285
228- proc deallocShared * (p: pointer ) {.noconv , compilerproc , rtl , benign , raises : [], tags : [].}
286+ proc deallocShared * (p: pointer ) {.noconv , compilerproc , rtl , benign , raises : [], tags : [].} =
229287 # # Frees the memory allocated with ``allocShared``, ``allocShared0`` or
230288 # # ``reallocShared``.
231289 # #
232290 # # **This procedure is dangerous!**
233291 # # If one forgets to free the memory a leak occurs; if one tries to
234292 # # access freed memory (or just freeing it twice!) a core dump may happen
235293 # # or other memory may be corrupted.
294+ incStat (deallocCount)
295+ deallocSharedImpl (p)
296+
236297 proc freeShared * [T](p: ptr T) {.inline , benign , raises : [].} =
237298 # # Frees the memory allocated with ``createShared``, ``createSharedU`` or
238299 # # ``resizeShared``.
@@ -243,6 +304,7 @@ when hasAlloc:
243304 # # or other memory may be corrupted.
244305 deallocShared (p)
245306
307+ {.pop .}
246308
247309# GC interface:
248310
0 commit comments