diff options
Diffstat (limited to 'tools/build/src/engine/boehm_gc/include/gc_inline.h')
-rw-r--r-- | tools/build/src/engine/boehm_gc/include/gc_inline.h | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/tools/build/src/engine/boehm_gc/include/gc_inline.h b/tools/build/src/engine/boehm_gc/include/gc_inline.h new file mode 100644 index 000000000..da7e2e91f --- /dev/null +++ b/tools/build/src/engine/boehm_gc/include/gc_inline.h @@ -0,0 +1,128 @@ +/* + * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers + * Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved. + * Copyright (c) 2005 Hewlett-Packard Development Company, L.P. + * + * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED + * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. + * + * Permission is hereby granted to use or copy this program + * for any purpose, provided the above notices are retained on all copies. + * Permission to modify the code and to distribute modified code is granted, + * provided the above notices are retained, and a notice that the code was + * modified is included with the above copyright notice. + */ + +/* USE OF THIS FILE IS NOT RECOMMENDED unless GC_all_interior_pointers */ +/* is not set, or the collector has been built with */ +/* -DDONT_ADD_BYTE_AT_END, or the specified size includes a pointerfree */ +/* word at the end. In the standard collector configuration, */ +/* the final word of each object may not be scanned. */ +/* This interface is most useful for compilers that generate C. */ +/* It is also used internally for thread-local allocation, in which */ +/* case, the size is suitably adjusted by the caller. */ +/* Manual use is hereby discouraged. */ + +#include "gc.h" +#include "gc_tiny_fl.h" + +#if __GNUC__ >= 3 +# define GC_EXPECT(expr, outcome) __builtin_expect(expr,outcome) + /* Equivalent to (expr), but predict that usually (expr)==outcome. */ +#else +# define GC_EXPECT(expr, outcome) (expr) +#endif /* __GNUC__ */ + +/* The ultimately general inline allocation macro. Allocate an object */ +/* of size bytes, putting the resulting pointer in result. Tiny_fl is */ +/* a "tiny" free list array, which will be used first, if the size */ +/* is appropriate. If bytes is too large, we allocate with */ +/* default_expr instead. If we need to refill the free list, we use */ +/* GC_generic_malloc_many with the indicated kind. */ +/* Tiny_fl should be an array of GC_TINY_FREELISTS void * pointers. */ +/* If num_direct is nonzero, and the individual free list pointers */ +/* are initialized to (void *)1, then we allocate numdirect granules */ +/* directly using gmalloc before putting multiple objects into the */ +/* tiny_fl entry. If num_direct is zero, then the free lists may also */ +/* be initialized to (void *)0. */ +/* We rely on much of this hopefully getting optimized away in the */ +/* num_direct = 0 case. */ +/* Particularly if bytes is constant, this should generate a small */ +/* amount of code. */ +# 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)) { \ + /* Entry contains counter or NULL */ \ + if ((GC_word)my_entry - 1 < num_direct) { \ + /* Small counter value, not NULL */ \ + *my_fl = (ptr_t)my_entry + granules + 1; \ + result = default_expr; \ + goto out; \ + } else { \ + /* Large counter or NULL */ \ + 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) + +/* Allocate n words (NOT BYTES). X is made to point to the result. */ +/* This should really only be used if GC_all_interior_pointers is */ +/* not set, or DONT_ADD_BYTE_AT_END is set. See above. */ +/* The semantics changed in version 7.0; we no longer lock, and */ +/* the caller is responsible for supplying a cleared tiny_fl */ +/* free list array. For single-threaded applications, this may be */ +/* a global array. */ +# 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), \ + /* no initialization */); \ +} + + +/* And once more for two word initialized objects: */ +# 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); \ +} |