| 271 | } |
| 272 | |
| 273 | void * |
| 274 | large_ralloc(tsdn_t *tsdn, arena_t *arena, void *ptr, size_t usize, |
| 275 | size_t alignment, bool zero, tcache_t *tcache, |
| 276 | hook_ralloc_args_t *hook_args) { |
| 277 | extent_t *extent = iealloc(tsdn, ptr); |
| 278 | |
| 279 | size_t oldusize = extent_usize_get(extent); |
| 280 | /* The following should have been caught by callers. */ |
| 281 | assert(usize > 0 && usize <= SC_LARGE_MAXCLASS); |
| 282 | /* Both allocation sizes must be large to avoid a move. */ |
| 283 | assert(oldusize >= SC_LARGE_MINCLASS |
| 284 | && usize >= SC_LARGE_MINCLASS); |
| 285 | |
| 286 | /* Try to avoid moving the allocation. */ |
| 287 | if (!large_ralloc_no_move(tsdn, extent, usize, usize, zero)) { |
| 288 | hook_invoke_expand(hook_args->is_realloc |
| 289 | ? hook_expand_realloc : hook_expand_rallocx, ptr, oldusize, |
| 290 | usize, (uintptr_t)ptr, hook_args->args); |
| 291 | return extent_addr_get(extent); |
| 292 | } |
| 293 | |
| 294 | /* |
| 295 | * usize and old size are different enough that we need to use a |
| 296 | * different size class. In that case, fall back to allocating new |
| 297 | * space and copying. |
| 298 | */ |
| 299 | void *ret = large_ralloc_move_helper(tsdn, arena, usize, alignment, |
| 300 | zero); |
| 301 | if (ret == NULL) { |
| 302 | return NULL; |
| 303 | } |
| 304 | |
| 305 | hook_invoke_alloc(hook_args->is_realloc |
| 306 | ? hook_alloc_realloc : hook_alloc_rallocx, ret, (uintptr_t)ret, |
| 307 | hook_args->args); |
| 308 | hook_invoke_dalloc(hook_args->is_realloc |
| 309 | ? hook_dalloc_realloc : hook_dalloc_rallocx, ptr, hook_args->args); |
| 310 | |
| 311 | size_t copysize = (usize < oldusize) ? usize : oldusize; |
| 312 | memcpy(ret, extent_addr_get(extent), copysize); |
| 313 | isdalloct(tsdn, extent_addr_get(extent), oldusize, tcache, NULL, true); |
| 314 | return ret; |
| 315 | } |
| 316 | |
| 317 | /* |
| 318 | * junked_locked indicates whether the extent's data have been junk-filled, and |
no test coverage detected