boehm-gc: revert all CACAO-specific modifications; this is now an exact copy of the...
[cacao.git] / src / mm / boehm-gc / include / gc_inline.h
index db62d1d58a815eaef9a376d0627873eacaf938d8..5b5e51a3a117ca0f8982431eb1d09e6cb921f668 100644 (file)
@@ -1 +1,132 @@
-# include "gc_inl.h"
+/* 
+ * 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.
+ */
+/* 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              */
+/* -DDONT_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__ */
+
+/* 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_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); \
+}