OLD | NEW |
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ | 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 /* This Source Code Form is subject to the terms of the Mozilla Public | 2 /* This Source Code Form is subject to the terms of the Mozilla Public |
3 * License, v. 2.0. If a copy of the MPL was not distributed with this | 3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
5 | 5 |
6 /* | 6 /* |
7 * Lifetime-based fast allocation, inspired by much prior art, including | 7 * Lifetime-based fast allocation, inspired by much prior art, including |
8 * "Fast Allocation and Deallocation of Memory Based on Object Lifetimes" | 8 * "Fast Allocation and Deallocation of Memory Based on Object Lifetimes" |
9 * David R. Hanson, Software -- Practice and Experience, Vol. 20(1). | 9 * David R. Hanson, Software -- Practice and Experience, Vol. 20(1). |
10 */ | 10 */ |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
146 char *rp; /* returned pointer */ | 146 char *rp; /* returned pointer */ |
147 | 147 |
148 PR_ASSERT((nb & pool->mask) == 0); | 148 PR_ASSERT((nb & pool->mask) == 0); |
149 | 149 |
150 nb = (PRUword)PL_ARENA_ALIGN(pool, nb); /* force alignment */ | 150 nb = (PRUword)PL_ARENA_ALIGN(pool, nb); /* force alignment */ |
151 | 151 |
152 /* attempt to allocate from arenas at pool->current */ | 152 /* attempt to allocate from arenas at pool->current */ |
153 { | 153 { |
154 a = pool->current; | 154 a = pool->current; |
155 do { | 155 do { |
156 if ( a->avail +nb <= a->limit ) { | 156 if ( nb <= a->limit - a->avail ) { |
157 pool->current = a; | 157 pool->current = a; |
158 rp = (char *)a->avail; | 158 rp = (char *)a->avail; |
159 a->avail += nb; | 159 a->avail += nb; |
160 return rp; | 160 return rp; |
161 } | 161 } |
162 } while( NULL != (a = a->next) ); | 162 } while( NULL != (a = a->next) ); |
163 } | 163 } |
164 | 164 |
165 /* attempt to allocate from arena_freelist */ | 165 /* attempt to allocate from arena_freelist */ |
166 { | 166 { |
167 PLArena *p; /* previous pointer, for unlinking from freelist */ | 167 PLArena *p; /* previous pointer, for unlinking from freelist */ |
168 | 168 |
169 /* lock the arena_freelist. Make access to the freelist MT-Safe */ | 169 /* lock the arena_freelist. Make access to the freelist MT-Safe */ |
170 if ( PR_FAILURE == LockArena()) | 170 if ( PR_FAILURE == LockArena()) |
171 return(0); | 171 return(0); |
172 | 172 |
173 for ( a = arena_freelist, p = NULL; a != NULL ; p = a, a = a->next ) { | 173 for ( a = arena_freelist, p = NULL; a != NULL ; p = a, a = a->next ) { |
174 if ( a->base +nb <= a->limit ) { | 174 if ( nb <= a->limit - a->base ) { |
175 if ( p == NULL ) | 175 if ( p == NULL ) |
176 arena_freelist = a->next; | 176 arena_freelist = a->next; |
177 else | 177 else |
178 p->next = a->next; | 178 p->next = a->next; |
179 UnlockArena(); | 179 UnlockArena(); |
180 a->avail = a->base; | 180 a->avail = a->base; |
181 rp = (char *)a->avail; | 181 rp = (char *)a->avail; |
182 a->avail += nb; | 182 a->avail += nb; |
183 /* the newly allocated arena is linked after pool->current | 183 /* the newly allocated arena is linked after pool->current |
184 * and becomes pool->current */ | 184 * and becomes pool->current */ |
185 a->next = pool->current->next; | 185 a->next = pool->current->next; |
186 pool->current->next = a; | 186 pool->current->next = a; |
187 pool->current = a; | 187 pool->current = a; |
188 if ( NULL == pool->first.next ) | 188 if ( NULL == pool->first.next ) |
189 pool->first.next = a; | 189 pool->first.next = a; |
190 return(rp); | 190 return(rp); |
191 } | 191 } |
192 } | 192 } |
193 UnlockArena(); | 193 UnlockArena(); |
194 } | 194 } |
195 | 195 |
196 /* attempt to allocate from the heap */ | 196 /* attempt to allocate from the heap */ |
197 { | 197 { |
198 PRUint32 sz = PR_MAX(pool->arenasize, nb); | 198 PRUint32 sz = PR_MAX(pool->arenasize, nb); |
199 sz += sizeof *a + pool->mask; /* header and alignment slop */ | 199 if (PR_UINT32_MAX - sz < sizeof *a + pool->mask) { |
200 a = (PLArena*)PR_MALLOC(sz); | 200 a = NULL; |
| 201 } else { |
| 202 sz += sizeof *a + pool->mask; /* header and alignment slop */ |
| 203 a = (PLArena*)PR_MALLOC(sz); |
| 204 } |
201 if ( NULL != a ) { | 205 if ( NULL != a ) { |
202 a->limit = (PRUword)a + sz; | 206 a->limit = (PRUword)a + sz; |
203 a->base = a->avail = (PRUword)PL_ARENA_ALIGN(pool, a + 1); | 207 a->base = a->avail = (PRUword)PL_ARENA_ALIGN(pool, a + 1); |
| 208 PL_MAKE_MEM_NOACCESS((void*)a->avail, a->limit - a->avail); |
204 rp = (char *)a->avail; | 209 rp = (char *)a->avail; |
205 a->avail += nb; | 210 a->avail += nb; |
206 /* the newly allocated arena is linked after pool->current | 211 /* the newly allocated arena is linked after pool->current |
207 * and becomes pool->current */ | 212 * and becomes pool->current */ |
208 a->next = pool->current->next; | 213 a->next = pool->current->next; |
209 pool->current->next = a; | 214 pool->current->next = a; |
210 pool->current = a; | 215 pool->current = a; |
211 if ( NULL == pool->first.next ) | 216 if ( NULL == pool->first.next ) |
212 pool->first.next = a; | 217 pool->first.next = a; |
213 PL_COUNT_ARENA(pool,++); | 218 PL_COUNT_ARENA(pool,++); |
(...skipping 16 matching lines...) Expand all Loading... |
230 memcpy(newp, p, size); | 235 memcpy(newp, p, size); |
231 return newp; | 236 return newp; |
232 } | 237 } |
233 | 238 |
234 static void ClearArenaList(PLArena *a, PRInt32 pattern) | 239 static void ClearArenaList(PLArena *a, PRInt32 pattern) |
235 { | 240 { |
236 | 241 |
237 for (; a; a = a->next) { | 242 for (; a; a = a->next) { |
238 PR_ASSERT(a->base <= a->avail && a->avail <= a->limit); | 243 PR_ASSERT(a->base <= a->avail && a->avail <= a->limit); |
239 a->avail = a->base; | 244 a->avail = a->base; |
240 » PL_CLEAR_UNUSED_PATTERN(a, pattern); | 245 PL_CLEAR_UNUSED_PATTERN(a, pattern); |
| 246 PL_MAKE_MEM_NOACCESS((void*)a->avail, a->limit - a->avail); |
241 } | 247 } |
242 } | 248 } |
243 | 249 |
244 PR_IMPLEMENT(void) PL_ClearArenaPool(PLArenaPool *pool, PRInt32 pattern) | 250 PR_IMPLEMENT(void) PL_ClearArenaPool(PLArenaPool *pool, PRInt32 pattern) |
245 { | 251 { |
246 ClearArenaList(pool->first.next, pattern); | 252 ClearArenaList(pool->first.next, pattern); |
247 } | 253 } |
248 | 254 |
249 /* | 255 /* |
250 * Free tail arenas linked after head, which may not be the true list head. | 256 * Free tail arenas linked after head, which may not be the true list head. |
(...skipping 15 matching lines...) Expand all Loading... |
266 if (reallyFree) { | 272 if (reallyFree) { |
267 do { | 273 do { |
268 *ap = a->next; | 274 *ap = a->next; |
269 PL_CLEAR_ARENA(a); | 275 PL_CLEAR_ARENA(a); |
270 PL_COUNT_ARENA(pool,--); | 276 PL_COUNT_ARENA(pool,--); |
271 PR_DELETE(a); | 277 PR_DELETE(a); |
272 } while ((a = *ap) != 0); | 278 } while ((a = *ap) != 0); |
273 } else { | 279 } else { |
274 /* Insert the whole arena chain at the front of the freelist. */ | 280 /* Insert the whole arena chain at the front of the freelist. */ |
275 do { | 281 do { |
| 282 PL_MAKE_MEM_NOACCESS((void*)(*ap)->base, |
| 283 (*ap)->limit - (*ap)->base); |
276 ap = &(*ap)->next; | 284 ap = &(*ap)->next; |
277 } while (*ap); | 285 } while (*ap); |
278 LockArena(); | 286 LockArena(); |
279 *ap = arena_freelist; | 287 *ap = arena_freelist; |
280 arena_freelist = a; | 288 arena_freelist = a; |
281 head->next = 0; | 289 head->next = 0; |
282 UnlockArena(); | 290 UnlockArena(); |
283 } | 291 } |
284 | 292 |
285 pool->current = head; | 293 pool->current = head; |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
338 } | 346 } |
339 arena_freelist = NULL; | 347 arena_freelist = NULL; |
340 | 348 |
341 if (arenaLock) { | 349 if (arenaLock) { |
342 PR_DestroyLock(arenaLock); | 350 PR_DestroyLock(arenaLock); |
343 arenaLock = NULL; | 351 arenaLock = NULL; |
344 } | 352 } |
345 once = pristineCallOnce; | 353 once = pristineCallOnce; |
346 } | 354 } |
347 | 355 |
| 356 PR_IMPLEMENT(size_t) PL_SizeOfArenaPoolExcludingPool( |
| 357 const PLArenaPool *pool, PLMallocSizeFn mallocSizeOf) |
| 358 { |
| 359 /* |
| 360 * The first PLArena is within |pool|, so don't measure it. Subsequent |
| 361 * PLArenas are separate and must be measured. |
| 362 */ |
| 363 size_t size = 0; |
| 364 const PLArena *arena = pool->first.next; |
| 365 while (arena) { |
| 366 size += mallocSizeOf(arena); |
| 367 arena = arena->next; |
| 368 } |
| 369 return size; |
| 370 } |
| 371 |
348 #ifdef PL_ARENAMETER | 372 #ifdef PL_ARENAMETER |
349 PR_IMPLEMENT(void) PL_ArenaCountAllocation(PLArenaPool *pool, PRUint32 nb) | 373 PR_IMPLEMENT(void) PL_ArenaCountAllocation(PLArenaPool *pool, PRUint32 nb) |
350 { | 374 { |
351 pool->stats.nallocs++; | 375 pool->stats.nallocs++; |
352 pool->stats.nbytes += nb; | 376 pool->stats.nbytes += nb; |
353 if (nb > pool->stats.maxalloc) | 377 if (nb > pool->stats.maxalloc) |
354 pool->stats.maxalloc = nb; | 378 pool->stats.maxalloc = nb; |
355 pool->stats.variance += nb * nb; | 379 pool->stats.variance += nb * nb; |
356 } | 380 } |
357 | 381 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
409 fprintf(fp, " number of in-place growths: %u\n", stats->ninplace); | 433 fprintf(fp, " number of in-place growths: %u\n", stats->ninplace); |
410 fprintf(fp, "number of released allocations: %u\n", stats->nreleases); | 434 fprintf(fp, "number of released allocations: %u\n", stats->nreleases); |
411 fprintf(fp, " number of fast releases: %u\n", stats->nfastrels); | 435 fprintf(fp, " number of fast releases: %u\n", stats->nfastrels); |
412 fprintf(fp, " total bytes allocated: %u\n", stats->nbytes); | 436 fprintf(fp, " total bytes allocated: %u\n", stats->nbytes); |
413 fprintf(fp, " mean allocation size: %g\n", mean); | 437 fprintf(fp, " mean allocation size: %g\n", mean); |
414 fprintf(fp, " standard deviation: %g\n", sqrt(variance)); | 438 fprintf(fp, " standard deviation: %g\n", sqrt(variance)); |
415 fprintf(fp, " maximum allocation size: %u\n", stats->maxalloc); | 439 fprintf(fp, " maximum allocation size: %u\n", stats->maxalloc); |
416 } | 440 } |
417 } | 441 } |
418 #endif /* PL_ARENAMETER */ | 442 #endif /* PL_ARENAMETER */ |
OLD | NEW |