|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "gc.h" |
|
|
#include "gc_tiny_fl.h" |
|
|
|
|
|
#if __GNUC__ >= 3 |
|
|
# define GC_EXPECT(expr, outcome) __builtin_expect(expr,outcome) |
|
|
|
|
|
#else |
|
|
# define GC_EXPECT(expr, outcome) (expr) |
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# define GC_FAST_MALLOC_GRANS(result,granules,tiny_fl,num_direct,\ |
|
|
kind,default_expr,init) \ |
|
|
{ \ |
|
|
if (GC_EXPECT(granules >= GC_TINY_FREELISTS,0)) { \ |
|
|
result = default_expr; \ |
|
|
} else { \ |
|
|
void **my_fl = tiny_fl + granules; \ |
|
|
void *my_entry=*my_fl; \ |
|
|
void *next; \ |
|
|
\ |
|
|
while (GC_EXPECT((GC_word)my_entry \ |
|
|
<= num_direct + GC_TINY_FREELISTS + 1, 0)) { \ |
|
|
\ |
|
|
if ((GC_word)my_entry - 1 < num_direct) { \ |
|
|
\ |
|
|
*my_fl = (ptr_t)my_entry + granules + 1; \ |
|
|
result = default_expr; \ |
|
|
goto out; \ |
|
|
} else { \ |
|
|
\ |
|
|
GC_generic_malloc_many(((granules) == 0? GC_GRANULE_BYTES : \ |
|
|
RAW_BYTES_FROM_INDEX(granules)), \ |
|
|
kind, my_fl); \ |
|
|
my_entry = *my_fl; \ |
|
|
if (my_entry == 0) { \ |
|
|
result = GC_oom_fn(bytes); \ |
|
|
goto out; \ |
|
|
} \ |
|
|
} \ |
|
|
} \ |
|
|
next = *(void **)(my_entry); \ |
|
|
result = (void *)my_entry; \ |
|
|
*my_fl = next; \ |
|
|
init; \ |
|
|
PREFETCH_FOR_WRITE(next); \ |
|
|
GC_ASSERT(GC_size(result) >= bytes + EXTRA_BYTES); \ |
|
|
GC_ASSERT((kind) == PTRFREE || ((GC_word *)result)[1] == 0); \ |
|
|
out: ; \ |
|
|
} \ |
|
|
} |
|
|
|
|
|
# define GC_WORDS_TO_WHOLE_GRANULES(n) \ |
|
|
GC_WORDS_TO_GRANULES((n) + GC_GRANULE_WORDS - 1) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# define GC_MALLOC_WORDS(result,n,tiny_fl) \ |
|
|
{ \ |
|
|
size_t grans = WORDS_TO_WHOLE_GRANULES(n); \ |
|
|
GC_FAST_MALLOC_GRANS(result, grans, tiny_fl, 0, \ |
|
|
NORMAL, GC_malloc(grans*GRANULE_BYTES), \ |
|
|
*(void **)result = 0); \ |
|
|
} |
|
|
|
|
|
# define GC_MALLOC_ATOMIC_WORDS(result,n,tiny_fl) \ |
|
|
{ \ |
|
|
size_t grans = WORDS_TO_WHOLE_GRANULES(n); \ |
|
|
GC_FAST_MALLOC_GRANS(result, grans, tiny_fl, 0, \ |
|
|
PTRFREE, GC_malloc_atomic(grans*GRANULE_BYTES), \ |
|
|
); \ |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
# define GC_CONS(result, first, second, tiny_fl) \ |
|
|
{ \ |
|
|
size_t grans = WORDS_TO_WHOLE_GRANULES(2); \ |
|
|
GC_FAST_MALLOC_GRANS(result, grans, tiny_fl, 0, \ |
|
|
NORMAL, GC_malloc(grans*GRANULE_BYTES), \ |
|
|
*(void **)result = (void *)(first)); \ |
|
|
((void **)(result))[1] = (void *)(second); \ |
|
|
} |
|
|
|