X-Git-Url: http://wien.tomnetworks.com/gitweb/?p=hs-boehmgc.git;a=blobdiff_plain;f=gc-7.2%2Finclude%2Fgc_inline.h;fp=gc-7.2%2Finclude%2Fgc_inline.h;h=cc49da228648ea589d25f30d2c3a849cc695706c;hp=0000000000000000000000000000000000000000;hb=324587ba93dc77f37406d41fd2a20d0e0d94fb1d;hpb=2a4ea609491b225a1ceb06da70396e93916f137a diff --git a/gc-7.2/include/gc_inline.h b/gc-7.2/include/gc_inline.h new file mode 100644 index 0000000..cc49da2 --- /dev/null +++ b/gc-7.2/include/gc_inline.h @@ -0,0 +1,146 @@ +/* + * 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. + */ + +#ifndef GC_INLINE_H +#define GC_INLINE_H + +/* WARNING: */ +/* Note that for these routines, it is the clients responsibility to */ +/* add the extra byte at the end to deal with one-past-the-end pointers.*/ +/* In the standard collector configuration, the collector assumes that */ +/* such a byte has been added, and hence does not trace the last word */ +/* in the resulting object. */ +/* This is not an issue if the collector is compiled with */ +/* DONT_ADD_BYTE_AT_END, or if GC_all_interior_pointers is not set. */ +/* This interface is most useful for compilers that generate C. */ +/* It is also used internally for thread-local allocation. */ +/* 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__ */ + +#ifndef GC_ASSERT +# define GC_ASSERT(expr) /* empty */ +#endif + +/* Store a pointer to a list of newly allocated objects of kind k and */ +/* size lb in *result. The caller must make sure that *result is */ +/* traced even if objects are ptrfree. */ +GC_API void GC_CALL GC_generic_malloc_many(size_t /* lb */, int /* k */, + void ** /* result */); + +/* The ultimately general inline allocation macro. Allocate an object */ +/* of size granules, 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 granules 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. */ +/* Note that we use the zeroth free list to hold objects 1 granule in */ +/* size that are used to satisfy size 0 allocation requests. */ +/* We rely on much of this hopefully getting optimized away in the */ +/* num_direct = 0 case. */ +/* Particularly if granules 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 = (char *)my_entry + (granules) + 1; \ + result = (default_expr); \ + goto out; \ + } else { \ + /* Large counter or NULL */ \ + GC_generic_malloc_many(((granules) == 0? GC_GRANULE_BYTES : \ + GC_RAW_BYTES_FROM_INDEX(granules)), \ + kind, my_fl); \ + my_entry = *my_fl; \ + if (my_entry == 0) { \ + result = (*GC_get_oom_fn())((granules)*GC_GRANULE_BYTES); \ + goto out; \ + } \ + } \ + } \ + next = *(void **)(my_entry); \ + result = (void *)my_entry; \ + *my_fl = next; \ + init; \ + PREFETCH_FOR_WRITE(next); \ + GC_ASSERT(GC_size(result) >= (granules)*GC_GRANULE_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 = GC_WORDS_TO_WHOLE_GRANULES(n); \ + GC_FAST_MALLOC_GRANS(result, grans, tiny_fl, 0, \ + NORMAL, GC_malloc(grans*GC_GRANULE_BYTES), \ + *(void **)(result) = 0); \ +} + +# define GC_MALLOC_ATOMIC_WORDS(result,n,tiny_fl) \ +{ \ + size_t grans = GC_WORDS_TO_WHOLE_GRANULES(n); \ + GC_FAST_MALLOC_GRANS(result, grans, tiny_fl, 0, \ + PTRFREE, GC_malloc_atomic(grans*GC_GRANULE_BYTES), \ + (void)0 /* no initialization */); \ +} + +/* And once more for two word initialized objects: */ +# define GC_CONS(result, first, second, tiny_fl) \ +{ \ + size_t grans = GC_WORDS_TO_WHOLE_GRANULES(2); \ + GC_FAST_MALLOC_GRANS(result, grans, tiny_fl, 0, \ + NORMAL, GC_malloc(grans*GC_GRANULE_BYTES), \ + *(void **)(result) = (void *)(first)); \ + ((void **)(result))[1] = (void *)(second); \ +} + +#endif /* !GC_INLINE_H */