Differences From
Artifact [de24aef2de]:
179 179 end)
180 180
181 181 struct m.pool {
182 182 -- implements growable memory pools. EVERY THREAD MUST HAVE ITS OWN
183 183 storage: &opaque
184 184 cursor: &opaque
185 185 sz: intptr
186 + debris: &m.pool
186 187 }
187 188
188 189 terra m.pool:cue(sz: intptr)
189 190 if self.storage == nil then
190 191 self.storage = m.heapa_raw(sz)
191 192 self.cursor = self.storage
192 193 self.sz = sz
193 194 else
194 195 if self.sz >= sz then return self end
195 - var ofs = [&uint8](self.cursor) - [&uint8](self.storage)
196 - self.storage = m.heapr_raw(self.storage, sz)
197 - self.cursor = [&opaque]([&uint8](self.storage) + ofs)
198 - self.sz = sz
196 + var oldblock = @self
197 + self:init(sz)
198 + @self.debris = oldblock
199 199 end
200 200 return self
201 201 end
202 202
203 203 terra m.pool:init(sz: intptr)
204 - self.storage = nil
205 - self:cue(sz)
204 + var b = m.heapa_raw(sz + sizeof(m.pool))
205 + self.storage = [&uint8](b) + sizeof(m.pool)
206 + self.cursor = self.storage
207 + self.sz = sz
208 + self.debris = [&m.pool](b)
209 + self.debris.storage = nil
206 210 return self
207 211 end
208 212
209 -terra m.pool:free()
210 - m.heapf(self.storage)
213 +terra m.pool:free(): {}
214 +lib.io.fmt('DRAINING POOL %p\n',self.storage)
215 + if self.storage == nil then return end
216 + if self.debris.storage ~= nil then self.debris:free() end
217 + m.heapf(self.debris) -- storage + debris field allocated in one block
211 218 self.storage = nil
212 219 self.cursor = nil
213 220 self.sz = 0
221 + self.debris = nil
214 222 end
215 223
216 224 terra m.pool:clear()
225 + if self.debris.storage ~= nil then self.debris:free() end
217 226 self.cursor = self.storage
218 227 return self
219 228 end
220 229
221 230 terra m.pool:alloc_bytes(sz: intptr): &opaque
222 231 var space = self.sz - ([&uint8](self.cursor) - [&uint8](self.storage))
223 - if space < sz then self:cue(space + sz + 256) end
232 +lib.io.fmt('%p / %p @ allocating %llu bytes in %llu of space\n',self.storage,self.cursor,sz,space)
233 + if space < sz then
234 +lib.dbg('reserving more space')
235 + self:cue(space + sz + 256) end
224 236 var ptr = self.cursor
225 237 self.cursor = [&opaque]([&uint8](self.cursor) + sz)
226 238 return ptr
227 239 end
228 240
229 -m.pool.methods.alloc = macro(function(self,ty,sz)
230 - return `[ty](self:alloc_bytes(sizeof(ty) * sz))
241 +terra m.pool:realloc_bytes(oldptr: &opaque, oldsz: intptr, newsz: intptr): &opaque
242 + var space = self.sz - ([&uint8](self.cursor) - [&uint8](self.storage))
243 + var cur = [&uint8](self.cursor)
244 + if cur - [&uint8](oldptr) == oldsz and newsz - oldsz < space then
245 + lib.dbg('moving pool cursor')
246 + cur = cur + (newsz - oldsz)
247 + self.cursor = [&opaque](cur)
248 + return oldptr
249 + else
250 + lib.dbg('copying pool object')
251 + var new = self:alloc_bytes(newsz)
252 + m.cpy(new, oldptr, oldsz)
253 + return new
254 + end
255 +end
256 +
257 +m.pool.methods.alloc = macro(function(self,typ,sz)
258 + local ty = typ:astype()
259 + return `[m.ptr(ty)] {
260 + ptr = [&ty](self:alloc_bytes(sizeof([ty]) * [sz]));
261 + ct = [sz];
262 + }
263 +end)
264 +
265 +m.pool.methods.realloc = macro(function(self,ptr,oldsz,newsz)
266 + local ty = self.tree.type.type
267 + return `[m.ptr(ty)] {
268 + ptr = [&ty](self:realloc_bytes(ptr,
269 + sizeof(ty) * oldsz,
270 + sizeof(ty) * newsz));
271 + ct = sz;
272 + }
231 273 end)
232 274
233 275 terra m.pool:frame() -- stack-style linear mgmt
234 276 return self.cursor
235 277 end
236 278
237 279 terra m.pool:reset(frame: &opaque)
238 - self.cursor = frame
280 + if frame >= self.storage and frame <= self.cursor then
281 + self.cursor = frame
282 + else -- trying to rewind into a previous block! not possible
283 + self.cursor = self.storage
284 + end
239 285 return self
240 286 end
241 287
242 288
243 289 return m