PageRenderTime 15ms CodeModel.GetById 10ms app.highlight 2ms RepoModel.GetById 1ms app.codeStats 0ms

/libs/headers/gc/gc_inline.h

http://github.com/nddrylliog/ooc
C++ Header | 128 lines | 71 code | 9 blank | 48 comment | 11 complexity | eae1f65e7530dbdd1d4fef3ec18c5cc0 MD5 | raw file
  1/* 
  2 * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
  3 * Copyright (c) 1991-1995 by Xerox Corporation.  All rights reserved.
  4 * Copyright (c) 2005 Hewlett-Packard Development Company, L.P.
  5 *
  6 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
  7 * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  8 *
  9 * Permission is hereby granted to use or copy this program
 10 * for any purpose,  provided the above notices are retained on all copies.
 11 * Permission to modify the code and to distribute modified code is granted,
 12 * provided the above notices are retained, and a notice that the code was
 13 * modified is included with the above copyright notice.
 14 */
 15 
 16/* USE OF THIS FILE IS NOT RECOMMENDED unless GC_all_interior_pointers	*/
 17/* is not set, or the collector has been built with			*/
 18/* -DDONT_ADD_BYTE_AT_END, or the specified size includes a pointerfree	*/
 19/* word at the end.  In the standard collector configuration,		*/
 20/* the final word of each object may not be scanned.			*/
 21/* This interface is most useful for compilers that generate C.		*/
 22/* It is also used internally for thread-local allocation, in which	*/
 23/* case, the size is suitably adjusted by the caller.			*/
 24/* Manual use is hereby discouraged.					*/
 25
 26#include "gc.h"
 27#include "gc_tiny_fl.h"
 28
 29#if __GNUC__ >= 3
 30# define GC_EXPECT(expr, outcome) __builtin_expect(expr,outcome)
 31  /* Equivalent to (expr), but predict that usually (expr)==outcome. */
 32#else
 33# define GC_EXPECT(expr, outcome) (expr)
 34#endif /* __GNUC__ */
 35
 36/* The ultimately general inline allocation macro.  Allocate an object	*/
 37/* of size granules, putting the resulting pointer in result.  Tiny_fl  */
 38/* is a "tiny" free list array, which will be used first, if the size	*/
 39/* is appropriate.  If granules is too large, we allocate with 		*/
 40/* default_expr instead.  If we need to refill the free list, we use	*/
 41/* GC_generic_malloc_many with the indicated kind.			*/
 42/* Tiny_fl should be an array of GC_TINY_FREELISTS void * pointers.	*/
 43/* If num_direct is nonzero, and the individual free list pointers	*/
 44/* are initialized to (void *)1, then we allocate numdirect granules	*/
 45/* directly using gmalloc before putting multiple objects into the	*/
 46/* tiny_fl entry.  If num_direct is zero, then the free lists may also	*/
 47/* be initialized to (void *)0.						*/
 48/* We rely on much of this hopefully getting optimized away in the	*/
 49/* num_direct = 0 case.							*/
 50/* Particularly if granules is constant, this should generate a small	*/
 51/* amount of code.							*/
 52# define GC_FAST_MALLOC_GRANS(result,granules,tiny_fl,num_direct,\
 53			      kind,default_expr,init) \
 54{ \
 55    if (GC_EXPECT(granules >= GC_TINY_FREELISTS,0)) { \
 56        result = default_expr; \
 57    } else { \
 58	void **my_fl = tiny_fl + granules; \
 59        void *my_entry=*my_fl; \
 60	void *next; \
 61 \
 62	while (GC_EXPECT((GC_word)my_entry \
 63				<= num_direct + GC_TINY_FREELISTS + 1, 0)) { \
 64	    /* Entry contains counter or NULL */ \
 65	    if ((GC_word)my_entry - 1 < num_direct) { \
 66		/* Small counter value, not NULL */ \
 67                *my_fl = (char *)my_entry + granules + 1; \
 68                result = default_expr; \
 69		goto out; \
 70            } else { \
 71		/* Large counter or NULL */ \
 72                GC_generic_malloc_many(((granules) == 0? GC_GRANULE_BYTES : \
 73					  GC_RAW_BYTES_FROM_INDEX(granules)), \
 74				       kind, my_fl); \
 75		my_entry = *my_fl; \
 76                if (my_entry == 0) { \
 77		    result = GC_oom_fn(granules*GC_GRANULE_BYTES); \
 78		    goto out; \
 79		} \
 80	    } \
 81        } \
 82        next = *(void **)(my_entry); \
 83        result = (void *)my_entry; \
 84        *my_fl = next; \
 85	init; \
 86        PREFETCH_FOR_WRITE(next); \
 87        GC_ASSERT(GC_size(result) >= granules*GC_GRANULE_BYTES); \
 88        GC_ASSERT((kind) == PTRFREE || ((GC_word *)result)[1] == 0); \
 89      out: ; \
 90   } \
 91}
 92
 93# define GC_WORDS_TO_WHOLE_GRANULES(n) \
 94	GC_WORDS_TO_GRANULES((n) + GC_GRANULE_WORDS - 1)
 95
 96/* Allocate n words (NOT BYTES).  X is made to point to the result.	*/
 97/* This should really only be used if GC_all_interior_pointers is	*/
 98/* not set, or DONT_ADD_BYTE_AT_END is set.  See above.			*/
 99/* The semantics changed in version 7.0; we no longer lock, and		*/
100/* the caller is responsible for supplying a cleared tiny_fl		*/
101/* free list array.  For single-threaded applications, this may be	*/
102/* a global array.							*/
103# define GC_MALLOC_WORDS(result,n,tiny_fl) \
104{	\
105    size_t grans = GC_WORDS_TO_WHOLE_GRANULES(n); \
106    GC_FAST_MALLOC_GRANS(result, grans, tiny_fl, 0, \
107			 NORMAL, GC_malloc(grans*GC_GRANULE_BYTES), \
108			 *(void **)result = 0); \
109}
110
111# define GC_MALLOC_ATOMIC_WORDS(result,n,tiny_fl) \
112{	\
113    size_t grans = GC_WORDS_TO_WHOLE_GRANULES(n); \
114    GC_FAST_MALLOC_GRANS(result, grans, tiny_fl, 0, \
115			 PTRFREE, GC_malloc_atomic(grans*GC_GRANULE_BYTES), \
116			 /* no initialization */); \
117}
118
119
120/* And once more for two word initialized objects: */
121# define GC_CONS(result, first, second, tiny_fl) \
122{	\
123    size_t grans = GC_WORDS_TO_WHOLE_GRANULES(2); \
124    GC_FAST_MALLOC_GRANS(result, grans, tiny_fl, 0, \
125			 NORMAL, GC_malloc(grans*GC_GRANULE_BYTES), \
126			 *(void **)result = (void *)(first)); \
127    ((void **)(result))[1] = (void *)(second);	\
128}