summaryrefslogtreecommitdiff
path: root/tools/build/src/engine/boehm_gc/include/gc_inline.h
diff options
context:
space:
mode:
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.h128
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); \
+}