@@ -33,8 +33,48 @@ when notJSnotNims:
33
33
# # otherwise. Like any procedure dealing with raw memory this is
34
34
# # **unsafe**.
35
35
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 =
38
78
# # Allocates a new memory block with at least ``size`` bytes.
39
79
# #
40
80
# # The block has to be freed with `realloc(block, 0) <#realloc,pointer,Natural>`_
@@ -47,6 +87,9 @@ when hasAlloc:
47
87
# #
48
88
# # See also:
49
89
# # * `alloc0 <#alloc0,Natural>`_
90
+ incStat(allocCount)
91
+ allocImpl(size)
92
+
50
93
proc createU* (T: typedesc , size = 1 .Positive): ptr T {.inline, benign, raises: [].} =
51
94
# # Allocates a new memory block with at least ``T.sizeof * size`` bytes.
52
95
# #
@@ -62,7 +105,7 @@ when hasAlloc:
62
105
# # * `create <#create,typedesc>`_
63
106
cast [ptr T](alloc(T.sizeof * size))
64
107
65
- proc alloc0*(size: Natural): pointer {.noconv, rtl, tags: [], benign, raises: [].}
108
+ template alloc0*(size: Natural): pointer =
66
109
## Allocates a new memory block with at least ``size`` bytes.
67
110
##
68
111
## The block has to be freed with `realloc(block, 0) <#realloc,pointer ,Natural>`_
@@ -72,6 +115,9 @@ when hasAlloc:
72
115
##
73
116
## The allocated memory belongs to its allocating thread!
74
117
## Use `allocShared0 <#allocShared0,Natural>`_ to allocate from a shared heap.
118
+ incStat(allocCount)
119
+ alloc0Impl(size)
120
+
75
121
proc create*(T: typedesc , size = 1.Positive): ptr T {.inline, benign, raises: [].} =
76
122
## Allocates a new memory block with at least ``T.sizeof * size`` bytes.
77
123
##
@@ -84,8 +130,7 @@ when hasAlloc:
84
130
## Use `createShared <#createShared,typedesc >`_ to allocate from a shared heap.
85
131
cast[ptr T](alloc0(sizeof(T) * size))
86
132
87
- proc realloc*(p: pointer , newSize: Natural): pointer {.noconv, rtl, tags: [],
88
- benign, raises: [].}
133
+ template realloc*(p: pointer , newSize: Natural): pointer =
89
134
## Grows or shrinks a given memory block.
90
135
##
91
136
## If `p` is **nil** then a new memory block is returned.
@@ -97,8 +142,9 @@ when hasAlloc:
97
142
## The allocated memory belongs to its allocating thread!
98
143
## Use `reallocShared <#reallocShared,pointer ,Natural>`_ to reallocate
99
144
## 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 =
102
148
## Grows or shrinks a given memory block.
103
149
##
104
150
## If `p` is **nil** then a new memory block is returned.
@@ -113,6 +159,8 @@ when hasAlloc:
113
159
## The allocated memory belongs to its allocating thread!
114
160
## Use `reallocShared <#reallocShared,pointer ,Natural>`_ to reallocate
115
161
## from a shared heap.
162
+ realloc0Impl(p, oldSize, newSize)
163
+
116
164
proc resize*[T](p: ptr T, newSize: Natural): ptr T {.inline, benign, raises: [].} =
117
165
## Grows or shrinks a given memory block.
118
166
##
@@ -126,7 +174,7 @@ when hasAlloc:
126
174
## from a shared heap.
127
175
cast[ptr T](realloc(p, T.sizeof * newSize))
128
176
129
- proc dealloc*(p: pointer ) {.noconv, rtl, tags: [], benign, raises: [].}
177
+ template dealloc*(p: pointer ) =
130
178
## Frees the memory allocated with ``alloc``, ``alloc0`` or
131
179
## ``realloc``.
132
180
##
@@ -137,8 +185,10 @@ when hasAlloc:
137
185
##
138
186
## The freed memory must belong to its allocating thread!
139
187
## Use `deallocShared <#deallocShared,pointer >`_ to deallocate from a shared heap.
188
+ incStat(deallocCount)
189
+ deallocImpl(p)
140
190
141
- proc allocShared*(size: Natural): pointer {.noconv, compilerproc, rtl, benign, raises: [], tags: [].}
191
+ template allocShared*(size: Natural): pointer =
142
192
## Allocates a new memory block on the shared heap with at
143
193
## least ``size`` bytes.
144
194
##
@@ -151,6 +201,9 @@ when hasAlloc:
151
201
##
152
202
## See also:
153
203
## `allocShared0 <#allocShared0,Natural>`_.
204
+ incStat(allocCount)
205
+ allocSharedImpl(size)
206
+
154
207
proc createSharedU*(T: typedesc , size = 1.Positive): ptr T {.inline, tags: [],
155
208
benign, raises: [].} =
156
209
## Allocates a new memory block on the shared heap with at
@@ -167,7 +220,7 @@ when hasAlloc:
167
220
## * `createShared <#createShared,typedesc >`_
168
221
cast[ptr T](allocShared(T.sizeof * size))
169
222
170
- proc allocShared0*(size: Natural): pointer {.noconv, rtl, benign, raises: [], tags: [].}
223
+ template allocShared0*(size: Natural): pointer =
171
224
## Allocates a new memory block on the shared heap with at
172
225
## least ``size`` bytes.
173
226
##
@@ -178,6 +231,9 @@ when hasAlloc:
178
231
## The block is initialized with all bytes
179
232
## containing zero, so it is somewhat safer than
180
233
## `allocShared <#allocShared,Natural>`_.
234
+ incStat(allocCount)
235
+ allocShared0Impl(size)
236
+
181
237
proc createShared*(T: typedesc , size = 1.Positive): ptr T {.inline.} =
182
238
## Allocates a new memory block on the shared heap with at
183
239
## least ``T.sizeof * size`` bytes.
@@ -191,8 +247,7 @@ when hasAlloc:
191
247
## `createSharedU <#createSharedU,typedesc >`_.
192
248
cast[ptr T](allocShared0(T.sizeof * size))
193
249
194
- proc reallocShared*(p: pointer , newSize: Natural): pointer {.noconv, rtl, tags: [],
195
- benign, raises: [].}
250
+ template reallocShared*(p: pointer , newSize: Natural): pointer =
196
251
## Grows or shrinks a given memory block on the heap.
197
252
##
198
253
## If `p` is **nil** then a new memory block is returned.
@@ -201,8 +256,9 @@ when hasAlloc:
201
256
## ``deallocShared(p)``.
202
257
## In other cases the block has to be freed with
203
258
## `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 =
206
262
## Grows or shrinks a given memory block on the heap.
207
263
##
208
264
## When growing, the new bytes of the block is initialized with all bytes
@@ -214,6 +270,8 @@ when hasAlloc:
214
270
## ``deallocShared(p)``.
215
271
## In other cases the block has to be freed with
216
272
## `deallocShared <#deallocShared,pointer >`_.
273
+ reallocShared0Impl(p, oldSize, newSize)
274
+
217
275
proc resizeShared*[T](p: ptr T, newSize: Natural): ptr T {.inline, raises: [].} =
218
276
## Grows or shrinks a given memory block on the heap.
219
277
##
@@ -225,14 +283,17 @@ when hasAlloc:
225
283
## `freeShared <#freeShared,ptr .T>`_.
226
284
cast[ptr T](reallocShared(p, T.sizeof * newSize))
227
285
228
- proc deallocShared*(p: pointer ) {.noconv, compilerproc, rtl, benign, raises: [], tags: [].}
286
+ proc deallocShared*(p: pointer ) {.noconv, compilerproc, rtl, benign, raises: [], tags: [].} =
229
287
## Frees the memory allocated with ``allocShared``, ``allocShared0`` or
230
288
## ``reallocShared``.
231
289
##
232
290
## **This procedure is dangerous!**
233
291
## If one forgets to free the memory a leak occurs; if one tries to
234
292
## access freed memory (or just freeing it twice!) a core dump may happen
235
293
## or other memory may be corrupted.
294
+ incStat(deallocCount)
295
+ deallocSharedImpl(p)
296
+
236
297
proc freeShared*[T](p: ptr T) {.inline, benign, raises: [].} =
237
298
## Frees the memory allocated with ``createShared``, ``createSharedU`` or
238
299
## ``resizeShared``.
@@ -243,6 +304,7 @@ when hasAlloc:
243
304
## or other memory may be corrupted.
244
305
deallocShared(p)
245
306
307
+ {.pop.}
246
308
247
309
# GC interface:
248
310
0 commit comments