builtin: compile the gc statically by default (#14063)
							parent
							
								
									56a3539ea9
								
							
						
					
					
						commit
						775c4c34b5
					
				| 
						 | 
				
			
			@ -131,7 +131,7 @@ jobs:
 | 
			
		|||
        run: |
 | 
			
		||||
          ./v -gc boehm_leak -o testcase_leak vlib/v/tests/testcase_leak.vv
 | 
			
		||||
          ./testcase_leak 2>leaks.txt
 | 
			
		||||
          grep "Found 1 leaked object" leaks.txt && grep ", sz=1000," leaks.txt
 | 
			
		||||
          grep "Found 1 leaked object" leaks.txt && grep -P ", sz=\s?1000," leaks.txt
 | 
			
		||||
      - name: Test leak detector not being active for `-gc boehm`
 | 
			
		||||
        run: |
 | 
			
		||||
          ./v -gc boehm -o testcase_leak vlib/v/tests/testcase_leak.vv
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
/* This file is installed for backward compatibility. */
 | 
			
		||||
#include <gc/gc.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,377 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 1993-1994 by Xerox Corporation.  All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Cords are immutable character strings.  A number of operations
 | 
			
		||||
 * on long cords are much more efficient than their strings.h counterpart.
 | 
			
		||||
 * In particular, concatenation takes constant time independent of the length
 | 
			
		||||
 * of the arguments.  (Cords are represented as trees, with internal
 | 
			
		||||
 * nodes representing concatenation and leaves consisting of either C
 | 
			
		||||
 * strings or a functional description of the string.)
 | 
			
		||||
 *
 | 
			
		||||
 * The following are reasonable applications of cords.  They would perform
 | 
			
		||||
 * unacceptably if C strings were used:
 | 
			
		||||
 * - A compiler that produces assembly language output by repeatedly
 | 
			
		||||
 *   concatenating instructions onto a cord representing the output file.
 | 
			
		||||
 * - A text editor that converts the input file to a cord, and then
 | 
			
		||||
 *   performs editing operations by producing a new cord representing
 | 
			
		||||
 *   the file after each character change (and keeping the old ones in an
 | 
			
		||||
 *   edit history)
 | 
			
		||||
 *
 | 
			
		||||
 * For optimal performance, cords should be built by
 | 
			
		||||
 * concatenating short sections.
 | 
			
		||||
 * This interface is designed for maximum compatibility with C strings.
 | 
			
		||||
 * ASCII NUL characters may be embedded in cords using CORD_from_fn.
 | 
			
		||||
 * This is handled correctly, but CORD_to_char_star will produce a string
 | 
			
		||||
 * with embedded NULs when given such a cord.
 | 
			
		||||
 *
 | 
			
		||||
 * This interface is fairly big, largely for performance reasons.
 | 
			
		||||
 * The most basic constants and functions:
 | 
			
		||||
 *
 | 
			
		||||
 * CORD - the type of a cord;
 | 
			
		||||
 * CORD_EMPTY - empty cord;
 | 
			
		||||
 * CORD_len(cord) - length of a cord;
 | 
			
		||||
 * CORD_cat(cord1,cord2) - concatenation of two cords;
 | 
			
		||||
 * CORD_substr(cord, start, len) - substring (or subcord);
 | 
			
		||||
 * CORD_pos i;  CORD_FOR(i, cord) {  ... CORD_pos_fetch(i) ... } -
 | 
			
		||||
 *    examine each character in a cord.  CORD_pos_fetch(i) is the char.
 | 
			
		||||
 * CORD_fetch(int i) - Retrieve i'th character (slowly).
 | 
			
		||||
 * CORD_cmp(cord1, cord2) - compare two cords.
 | 
			
		||||
 * CORD_from_file(FILE * f) - turn a read-only file into a cord.
 | 
			
		||||
 * CORD_to_char_star(cord) - convert to C string.
 | 
			
		||||
 *   (Non-NULL C constant strings are cords.)
 | 
			
		||||
 * CORD_printf (etc.) - cord version of printf. Use %r for cords.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef CORD_H
 | 
			
		||||
#define CORD_H
 | 
			
		||||
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
  extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(GC_DLL) && !defined(CORD_NOT_DLL)
 | 
			
		||||
  /* Same as for GC_API in gc_config_macros.h.  */
 | 
			
		||||
# ifdef CORD_BUILD
 | 
			
		||||
#   if defined(__MINGW32__) || defined(__CEGCC__)
 | 
			
		||||
#     define CORD_API __declspec(dllexport)
 | 
			
		||||
#   elif defined(_MSC_VER) || defined(__DMC__) || defined(__BORLANDC__) \
 | 
			
		||||
         || defined(__CYGWIN__) || defined(__WATCOMC__)
 | 
			
		||||
#     define CORD_API extern __declspec(dllexport)
 | 
			
		||||
#   elif defined(__GNUC__) && !defined(GC_NO_VISIBILITY) \
 | 
			
		||||
         && (__GNUC__ >= 4 || defined(GC_VISIBILITY_HIDDEN_SET))
 | 
			
		||||
    /* Only matters if used in conjunction with -fvisibility=hidden option. */
 | 
			
		||||
#     define CORD_API extern __attribute__((__visibility__("default")))
 | 
			
		||||
#   endif
 | 
			
		||||
# else
 | 
			
		||||
#   if defined(__MINGW32__) || defined(__CEGCC__) || defined(_MSC_VER) \
 | 
			
		||||
       || defined(__DMC__) || defined(__BORLANDC__) || defined(__CYGWIN__)
 | 
			
		||||
#     define CORD_API __declspec(dllimport)
 | 
			
		||||
#   elif defined(__WATCOMC__)
 | 
			
		||||
#     define CORD_API extern __declspec(dllimport)
 | 
			
		||||
#   endif
 | 
			
		||||
# endif /* !CORD_BUILD */
 | 
			
		||||
#endif /* GC_DLL */
 | 
			
		||||
 | 
			
		||||
#ifndef CORD_API
 | 
			
		||||
# define CORD_API extern
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Cords have type const char *.  This is cheating quite a bit, and not */
 | 
			
		||||
/* 100% portable.  But it means that nonempty character string          */
 | 
			
		||||
/* constants may be used as cords directly, provided the string is      */
 | 
			
		||||
/* never modified in place.  The empty cord is represented by, and      */
 | 
			
		||||
/* can be written as, 0.                                                */
 | 
			
		||||
 | 
			
		||||
typedef const char * CORD;
 | 
			
		||||
 | 
			
		||||
/* An empty cord is always represented as nil   */
 | 
			
		||||
#define CORD_EMPTY 0
 | 
			
		||||
 | 
			
		||||
/* Is a nonempty cord represented as a C string? */
 | 
			
		||||
#define CORD_IS_STRING(s) (*(s) != '\0')
 | 
			
		||||
 | 
			
		||||
/* Concatenate two cords.  If the arguments are C strings, they may     */
 | 
			
		||||
/* not be subsequently altered.                                         */
 | 
			
		||||
CORD_API CORD CORD_cat(CORD x, CORD y);
 | 
			
		||||
 | 
			
		||||
/* Concatenate a cord and a C string with known length.  Except for the */
 | 
			
		||||
/* empty string case, this is a special case of CORD_cat.  Since the    */
 | 
			
		||||
/* length is known, it can be faster.                                   */
 | 
			
		||||
/* The string y is shared with the resulting CORD.  Hence it should     */
 | 
			
		||||
/* not be altered by the caller.                                        */
 | 
			
		||||
CORD_API CORD CORD_cat_char_star(CORD x, const char * y, size_t leny);
 | 
			
		||||
 | 
			
		||||
/* Compute the length of a cord */
 | 
			
		||||
CORD_API size_t CORD_len(CORD x);
 | 
			
		||||
 | 
			
		||||
/* Cords may be represented by functions defining the ith character */
 | 
			
		||||
typedef char (* CORD_fn)(size_t i, void * client_data);
 | 
			
		||||
 | 
			
		||||
/* Turn a functional description into a cord.   */
 | 
			
		||||
CORD_API CORD CORD_from_fn(CORD_fn fn, void * client_data, size_t len);
 | 
			
		||||
 | 
			
		||||
/* Return the substring (subcord really) of x with length at most n,    */
 | 
			
		||||
/* starting at position i.  (The initial character has position 0.)     */
 | 
			
		||||
CORD_API CORD CORD_substr(CORD x, size_t i, size_t n);
 | 
			
		||||
 | 
			
		||||
/* Return the argument, but rebalanced to allow more efficient          */
 | 
			
		||||
/* character retrieval, substring operations, and comparisons.          */
 | 
			
		||||
/* This is useful only for cords that were built using repeated         */
 | 
			
		||||
/* concatenation.  Guarantees log time access to the result, unless     */
 | 
			
		||||
/* x was obtained through a large number of repeated substring ops      */
 | 
			
		||||
/* or the embedded functional descriptions take longer to evaluate.     */
 | 
			
		||||
/* May reallocate significant parts of the cord.  The argument is not   */
 | 
			
		||||
/* modified; only the result is balanced.                               */
 | 
			
		||||
CORD_API CORD CORD_balance(CORD x);
 | 
			
		||||
 | 
			
		||||
/* The following traverse a cord by applying a function to each         */
 | 
			
		||||
/* character.  This is occasionally appropriate, especially where       */
 | 
			
		||||
/* speed is crucial.  But, since C doesn't have nested functions,       */
 | 
			
		||||
/* clients of this sort of traversal are clumsy to write.  Consider     */
 | 
			
		||||
/* the functions that operate on cord positions instead.                */
 | 
			
		||||
 | 
			
		||||
/* Function to iteratively apply to individual characters in cord.      */
 | 
			
		||||
typedef int (* CORD_iter_fn)(char c, void * client_data);
 | 
			
		||||
 | 
			
		||||
/* Function to apply to substrings of a cord.  Each substring is a      */
 | 
			
		||||
/* a C character string, not a general cord.                            */
 | 
			
		||||
typedef int (* CORD_batched_iter_fn)(const char * s, void * client_data);
 | 
			
		||||
#define CORD_NO_FN ((CORD_batched_iter_fn)0)
 | 
			
		||||
 | 
			
		||||
/* Apply f1 to each character in the cord, in ascending order,          */
 | 
			
		||||
/* starting at position i. If                                           */
 | 
			
		||||
/* f2 is not CORD_NO_FN, then multiple calls to f1 may be replaced by   */
 | 
			
		||||
/* a single call to f2.  The parameter f2 is provided only to allow     */
 | 
			
		||||
/* some optimization by the client.  This terminates when the right     */
 | 
			
		||||
/* end of this string is reached, or when f1 or f2 return != 0.  In the */
 | 
			
		||||
/* latter case CORD_iter returns != 0.  Otherwise it returns 0.         */
 | 
			
		||||
/* The specified value of i must be < CORD_len(x).                      */
 | 
			
		||||
CORD_API int CORD_iter5(CORD x, size_t i, CORD_iter_fn f1,
 | 
			
		||||
                        CORD_batched_iter_fn f2, void * client_data);
 | 
			
		||||
 | 
			
		||||
/* A simpler version that starts at 0, and without f2:  */
 | 
			
		||||
CORD_API int CORD_iter(CORD x, CORD_iter_fn f1, void * client_data);
 | 
			
		||||
#define CORD_iter(x, f1, cd) CORD_iter5(x, 0, f1, CORD_NO_FN, cd)
 | 
			
		||||
 | 
			
		||||
/* Similar to CORD_iter5, but end-to-beginning. No provisions for       */
 | 
			
		||||
/* CORD_batched_iter_fn.                                                */
 | 
			
		||||
CORD_API int CORD_riter4(CORD x, size_t i, CORD_iter_fn f1, void * client_data);
 | 
			
		||||
 | 
			
		||||
/* A simpler version that starts at the end:    */
 | 
			
		||||
CORD_API int CORD_riter(CORD x, CORD_iter_fn f1, void * client_data);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
  } /* extern "C" */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Functions that operate on cord positions.  The easy way to traverse  */
 | 
			
		||||
/* cords.  A cord position is logically a pair consisting of a cord     */
 | 
			
		||||
/* and an index into that cord.  But it is much faster to retrieve a    */
 | 
			
		||||
/* character based on a position than on an index.  Unfortunately,      */
 | 
			
		||||
/* positions are big (order of a few 100 bytes), so allocate them with  */
 | 
			
		||||
/* caution.                                                             */
 | 
			
		||||
/* Things in cord_pos.h should be treated as opaque, except as          */
 | 
			
		||||
/* described below.  Also note that                                     */
 | 
			
		||||
/* CORD_pos_fetch, CORD_next and CORD_prev have both macro and function */
 | 
			
		||||
/* definitions.  The former may evaluate their argument more than once. */
 | 
			
		||||
#include "cord_pos.h"
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
  extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
        Visible definitions from above:
 | 
			
		||||
 | 
			
		||||
        typedef <OPAQUE but fairly big> CORD_pos[1];
 | 
			
		||||
 | 
			
		||||
        * Extract the cord from a position:
 | 
			
		||||
        CORD CORD_pos_to_cord(CORD_pos p);
 | 
			
		||||
 | 
			
		||||
        * Extract the current index from a position:
 | 
			
		||||
        size_t CORD_pos_to_index(CORD_pos p);
 | 
			
		||||
 | 
			
		||||
        * Fetch the character located at the given position:
 | 
			
		||||
        char CORD_pos_fetch(CORD_pos p);
 | 
			
		||||
 | 
			
		||||
        * Initialize the position to refer to the given cord and index.
 | 
			
		||||
        * Note that this is the most expensive function on positions:
 | 
			
		||||
        void CORD_set_pos(CORD_pos p, CORD x, size_t i);
 | 
			
		||||
 | 
			
		||||
        * Advance the position to the next character.
 | 
			
		||||
        * P must be initialized and valid.
 | 
			
		||||
        * Invalidates p if past end:
 | 
			
		||||
        void CORD_next(CORD_pos p);
 | 
			
		||||
 | 
			
		||||
        * Move the position to the preceding character.
 | 
			
		||||
        * P must be initialized and valid.
 | 
			
		||||
        * Invalidates p if past beginning:
 | 
			
		||||
        void CORD_prev(CORD_pos p);
 | 
			
		||||
 | 
			
		||||
        * Is the position valid, i.e. inside the cord?
 | 
			
		||||
        int CORD_pos_valid(CORD_pos p);
 | 
			
		||||
*/
 | 
			
		||||
#define CORD_FOR(pos, cord) \
 | 
			
		||||
    for (CORD_set_pos(pos, cord, 0); CORD_pos_valid(pos); CORD_next(pos))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* An out of memory handler to call.  May be supplied by client.        */
 | 
			
		||||
/* Must not return.                                                     */
 | 
			
		||||
extern void (* CORD_oom_fn)(void);
 | 
			
		||||
 | 
			
		||||
/* Dump the representation of x to stdout in an implementation defined  */
 | 
			
		||||
/* manner.  Intended for debugging only.                                */
 | 
			
		||||
CORD_API void CORD_dump(CORD x);
 | 
			
		||||
 | 
			
		||||
/* The following could easily be implemented by the client.  They are   */
 | 
			
		||||
/* provided in cordxtra.c for convenience.                              */
 | 
			
		||||
 | 
			
		||||
/* Concatenate a character to the end of a cord.        */
 | 
			
		||||
CORD_API CORD CORD_cat_char(CORD x, char c);
 | 
			
		||||
 | 
			
		||||
/* Concatenate n cords. */
 | 
			
		||||
CORD_API CORD CORD_catn(int n, /* CORD */ ...);
 | 
			
		||||
 | 
			
		||||
/* Return the character in CORD_substr(x, i, 1)         */
 | 
			
		||||
CORD_API char CORD_fetch(CORD x, size_t i);
 | 
			
		||||
 | 
			
		||||
/* Return < 0, 0, or > 0, depending on whether x < y, x = y, x > y      */
 | 
			
		||||
CORD_API int CORD_cmp(CORD x, CORD y);
 | 
			
		||||
 | 
			
		||||
/* A generalization that takes both starting positions for the          */
 | 
			
		||||
/* comparison, and a limit on the number of characters to be compared.  */
 | 
			
		||||
CORD_API int CORD_ncmp(CORD x, size_t x_start, CORD y, size_t y_start,
 | 
			
		||||
                       size_t len);
 | 
			
		||||
 | 
			
		||||
/* Find the first occurrence of s in x at position start or later.      */
 | 
			
		||||
/* Return the position of the first character of s in x, or             */
 | 
			
		||||
/* CORD_NOT_FOUND if there is none.                                     */
 | 
			
		||||
CORD_API size_t CORD_str(CORD x, size_t start, CORD s);
 | 
			
		||||
 | 
			
		||||
/* Return a cord consisting of i copies of (possibly NUL) c.  Dangerous */
 | 
			
		||||
/* in conjunction with CORD_to_char_star.                               */
 | 
			
		||||
/* The resulting representation takes constant space, independent of i. */
 | 
			
		||||
CORD_API CORD CORD_chars(char c, size_t i);
 | 
			
		||||
#define CORD_nul(i) CORD_chars('\0', (i))
 | 
			
		||||
 | 
			
		||||
/* Turn a file into cord.  The file must be seekable.  Its contents     */
 | 
			
		||||
/* must remain constant.  The file may be accessed as an immediate      */
 | 
			
		||||
/* result of this call and/or as a result of subsequent accesses to     */
 | 
			
		||||
/* the cord.  Short files are likely to be immediately read, but        */
 | 
			
		||||
/* long files are likely to be read on demand, possibly relying on      */
 | 
			
		||||
/* stdio for buffering.                                                 */
 | 
			
		||||
/* We must have exclusive access to the descriptor f, i.e. we may       */
 | 
			
		||||
/* read it at any time, and expect the file pointer to be               */
 | 
			
		||||
/* where we left it.  Normally this should be invoked as                */
 | 
			
		||||
/* CORD_from_file(fopen(...))                                           */
 | 
			
		||||
/* CORD_from_file arranges to close the file descriptor when it is no   */
 | 
			
		||||
/* longer needed (e.g. when the result becomes inaccessible).           */
 | 
			
		||||
/* The file f must be such that ftell reflects the actual character     */
 | 
			
		||||
/* position in the file, i.e. the number of characters that can be      */
 | 
			
		||||
/* or were read with fread.  On UNIX systems this is always true.  On   */
 | 
			
		||||
/* MS Windows systems, f must be opened in binary mode.                 */
 | 
			
		||||
CORD_API CORD CORD_from_file(FILE * f);
 | 
			
		||||
 | 
			
		||||
/* Equivalent to the above, except that the entire file will be read    */
 | 
			
		||||
/* and the file pointer will be closed immediately.                     */
 | 
			
		||||
/* The binary mode restriction from above does not apply.               */
 | 
			
		||||
CORD_API CORD CORD_from_file_eager(FILE * f);
 | 
			
		||||
 | 
			
		||||
/* Equivalent to the above, except that the file will be read on demand.*/
 | 
			
		||||
/* The binary mode restriction applies.                                 */
 | 
			
		||||
CORD_API CORD CORD_from_file_lazy(FILE * f);
 | 
			
		||||
 | 
			
		||||
/* Turn a cord into a C string. The result shares no structure with     */
 | 
			
		||||
/* x, and is thus modifiable.                                           */
 | 
			
		||||
CORD_API char * CORD_to_char_star(CORD x);
 | 
			
		||||
 | 
			
		||||
/* Turn a C string into a CORD.  The C string is copied, and so may     */
 | 
			
		||||
/* subsequently be modified.                                            */
 | 
			
		||||
CORD_API CORD CORD_from_char_star(const char *s);
 | 
			
		||||
 | 
			
		||||
/* Identical to the above, but the result may share structure with      */
 | 
			
		||||
/* the argument and is thus not modifiable.                             */
 | 
			
		||||
CORD_API const char * CORD_to_const_char_star(CORD x);
 | 
			
		||||
 | 
			
		||||
/* Write a cord to a file, starting at the current position.  No        */
 | 
			
		||||
/* trailing NULs are newlines are added.                                */
 | 
			
		||||
/* Returns EOF if a write error occurs, 1 otherwise.                    */
 | 
			
		||||
CORD_API int CORD_put(CORD x, FILE * f);
 | 
			
		||||
 | 
			
		||||
/* "Not found" result for the following two functions.                  */
 | 
			
		||||
#define CORD_NOT_FOUND ((size_t)(-1))
 | 
			
		||||
 | 
			
		||||
/* A vague analog of strchr.  Returns the position (an integer, not     */
 | 
			
		||||
/* a pointer) of the first occurrence of (char) c inside x at position  */
 | 
			
		||||
/* i or later. The value i must be < CORD_len(x).                       */
 | 
			
		||||
CORD_API size_t CORD_chr(CORD x, size_t i, int c);
 | 
			
		||||
 | 
			
		||||
/* A vague analog of strrchr.  Returns index of the last occurrence     */
 | 
			
		||||
/* of (char) c inside x at position i or earlier. The value i           */
 | 
			
		||||
/* must be < CORD_len(x).                                               */
 | 
			
		||||
CORD_API size_t CORD_rchr(CORD x, size_t i, int c);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
  } /* extern "C" */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* The following are also not primitive, but are implemented in         */
 | 
			
		||||
/* cordprnt.c.  They provide functionality similar to the ANSI C        */
 | 
			
		||||
/* functions with corresponding names, but with the following           */
 | 
			
		||||
/* additions and changes:                                               */
 | 
			
		||||
/* 1. A %r conversion specification specifies a CORD argument.  Field   */
 | 
			
		||||
/*    width, precision, etc. have the same semantics as for %s.         */
 | 
			
		||||
/*    (Note that %c, %C, and %S were already taken.)                    */
 | 
			
		||||
/* 2. The format string is represented as a CORD.                       */
 | 
			
		||||
/* 3. CORD_sprintf and CORD_vsprintf assign the result through the 1st  */
 | 
			
		||||
/*    argument. Unlike their ANSI C versions, there is no need to guess */
 | 
			
		||||
/*    the correct buffer size.                                          */
 | 
			
		||||
/* 4. Most of the conversions are implement through the native          */
 | 
			
		||||
/*    vsprintf.  Hence they are usually no faster, and                  */
 | 
			
		||||
/*    idiosyncrasies of the native printf are preserved.  However,      */
 | 
			
		||||
/*    CORD arguments to CORD_sprintf and CORD_vsprintf are NOT copied;  */
 | 
			
		||||
/*    the result shares the original structure.  This may make them     */
 | 
			
		||||
/*    very efficient in some unusual applications.                      */
 | 
			
		||||
/*    The format string is copied.                                      */
 | 
			
		||||
/* All functions return the number of characters generated or -1 on     */
 | 
			
		||||
/* error.  This complies with the ANSI standard, but is inconsistent    */
 | 
			
		||||
/* with some older implementations of sprintf.                          */
 | 
			
		||||
 | 
			
		||||
/* The implementation of these is probably less portable than the rest  */
 | 
			
		||||
/* of this package.                                                     */
 | 
			
		||||
 | 
			
		||||
#ifndef CORD_NO_IO
 | 
			
		||||
 | 
			
		||||
#include <stdarg.h>
 | 
			
		||||
 | 
			
		||||
# ifdef __cplusplus
 | 
			
		||||
    extern "C" {
 | 
			
		||||
# endif
 | 
			
		||||
 | 
			
		||||
CORD_API int CORD_sprintf(CORD * out, CORD format, ...);
 | 
			
		||||
CORD_API int CORD_vsprintf(CORD * out, CORD format, va_list args);
 | 
			
		||||
CORD_API int CORD_fprintf(FILE * f, CORD format, ...);
 | 
			
		||||
CORD_API int CORD_vfprintf(FILE * f, CORD format, va_list args);
 | 
			
		||||
CORD_API int CORD_printf(CORD format, ...);
 | 
			
		||||
CORD_API int CORD_vprintf(CORD format, va_list args);
 | 
			
		||||
 | 
			
		||||
# ifdef __cplusplus
 | 
			
		||||
    } /* extern "C" */
 | 
			
		||||
# endif
 | 
			
		||||
 | 
			
		||||
#endif /* CORD_NO_IO */
 | 
			
		||||
 | 
			
		||||
#endif /* CORD_H */
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,128 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 1993-1994 by Xerox Corporation.  All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* This should never be included directly; included only from cord.h.   */
 | 
			
		||||
#if !defined(CORD_POSITION_H) && defined(CORD_H)
 | 
			
		||||
#define CORD_POSITION_H
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
  extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* The representation of CORD_position.  This is private to the */
 | 
			
		||||
/* implementation, but the size is known to clients.  Also      */
 | 
			
		||||
/* the implementation of some exported macros relies on it.     */
 | 
			
		||||
/* Don't use anything defined here and not in cord.h.           */
 | 
			
		||||
 | 
			
		||||
# define MAX_DEPTH 48
 | 
			
		||||
        /* The maximum depth of a balanced cord + 1.            */
 | 
			
		||||
        /* We don't let cords get deeper than MAX_DEPTH.        */
 | 
			
		||||
 | 
			
		||||
struct CORD_pe {
 | 
			
		||||
    CORD pe_cord;
 | 
			
		||||
    size_t pe_start_pos;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* A structure describing an entry on the path from the root    */
 | 
			
		||||
/* to current position.                                         */
 | 
			
		||||
typedef struct CORD_Pos {
 | 
			
		||||
    size_t cur_pos;
 | 
			
		||||
    int path_len;
 | 
			
		||||
#       define CORD_POS_INVALID (0x55555555)
 | 
			
		||||
                /* path_len == INVALID <==> position invalid */
 | 
			
		||||
    const char *cur_leaf;       /* Current leaf, if it is a string.     */
 | 
			
		||||
                                /* If the current leaf is a function,   */
 | 
			
		||||
                                /* then this may point to function_buf  */
 | 
			
		||||
                                /* containing the next few characters.  */
 | 
			
		||||
                                /* Always points to a valid string      */
 | 
			
		||||
                                /* containing the current character     */
 | 
			
		||||
                                /* unless cur_end is 0.                 */
 | 
			
		||||
    size_t cur_start;   /* Start position of cur_leaf   */
 | 
			
		||||
    size_t cur_end;     /* Ending position of cur_leaf  */
 | 
			
		||||
                        /* 0 if cur_leaf is invalid.    */
 | 
			
		||||
    struct CORD_pe path[MAX_DEPTH + 1];
 | 
			
		||||
        /* path[path_len] is the leaf corresponding to cur_pos  */
 | 
			
		||||
        /* path[0].pe_cord is the cord we point to.             */
 | 
			
		||||
#   define FUNCTION_BUF_SZ 8
 | 
			
		||||
    char function_buf[FUNCTION_BUF_SZ]; /* Space for next few chars     */
 | 
			
		||||
                                        /* from function node.          */
 | 
			
		||||
} CORD_pos[1];
 | 
			
		||||
 | 
			
		||||
/* Extract the cord from a position:    */
 | 
			
		||||
CORD_API CORD CORD_pos_to_cord(CORD_pos p);
 | 
			
		||||
 | 
			
		||||
/* Extract the current index from a position:   */
 | 
			
		||||
CORD_API size_t CORD_pos_to_index(CORD_pos p);
 | 
			
		||||
 | 
			
		||||
/* Fetch the character located at the given position:   */
 | 
			
		||||
CORD_API char CORD_pos_fetch(CORD_pos p);
 | 
			
		||||
 | 
			
		||||
/* Initialize the position to refer to the give cord and index. */
 | 
			
		||||
/* Note that this is the most expensive function on positions:  */
 | 
			
		||||
CORD_API void CORD_set_pos(CORD_pos p, CORD x, size_t i);
 | 
			
		||||
 | 
			
		||||
/* Advance the position to the next character.  */
 | 
			
		||||
/* P must be initialized and valid.             */
 | 
			
		||||
/* Invalidates p if past end:                   */
 | 
			
		||||
CORD_API void CORD_next(CORD_pos p);
 | 
			
		||||
 | 
			
		||||
/* Move the position to the preceding character.        */
 | 
			
		||||
/* P must be initialized and valid.                     */
 | 
			
		||||
/* Invalidates p if past beginning:                     */
 | 
			
		||||
CORD_API void CORD_prev(CORD_pos p);
 | 
			
		||||
 | 
			
		||||
/* Is the position valid, i.e. inside the cord?         */
 | 
			
		||||
CORD_API int CORD_pos_valid(CORD_pos p);
 | 
			
		||||
 | 
			
		||||
CORD_API char CORD__pos_fetch(CORD_pos);
 | 
			
		||||
CORD_API void CORD__next(CORD_pos);
 | 
			
		||||
CORD_API void CORD__prev(CORD_pos);
 | 
			
		||||
 | 
			
		||||
#define CORD_pos_fetch(p)       \
 | 
			
		||||
    (((p)[0].cur_end != 0)? \
 | 
			
		||||
        (p)[0].cur_leaf[(p)[0].cur_pos - (p)[0].cur_start] \
 | 
			
		||||
        : CORD__pos_fetch(p))
 | 
			
		||||
 | 
			
		||||
#define CORD_next(p)    \
 | 
			
		||||
    (((p)[0].cur_pos + 1 < (p)[0].cur_end)? \
 | 
			
		||||
        (p)[0].cur_pos++ \
 | 
			
		||||
        : (CORD__next(p), 0))
 | 
			
		||||
 | 
			
		||||
#define CORD_prev(p)    \
 | 
			
		||||
    (((p)[0].cur_end != 0 && (p)[0].cur_pos > (p)[0].cur_start)? \
 | 
			
		||||
        (p)[0].cur_pos-- \
 | 
			
		||||
        : (CORD__prev(p), 0))
 | 
			
		||||
 | 
			
		||||
#define CORD_pos_to_index(p) ((p)[0].cur_pos)
 | 
			
		||||
 | 
			
		||||
#define CORD_pos_to_cord(p) ((p)[0].path[0].pe_cord)
 | 
			
		||||
 | 
			
		||||
#define CORD_pos_valid(p) ((p)[0].path_len != CORD_POS_INVALID)
 | 
			
		||||
 | 
			
		||||
/* Some grubby stuff for performance-critical friends:  */
 | 
			
		||||
#define CORD_pos_chars_left(p) ((long)((p)[0].cur_end) - (long)((p)[0].cur_pos))
 | 
			
		||||
        /* Number of characters in cache.  <= 0 ==> none        */
 | 
			
		||||
 | 
			
		||||
#define CORD_pos_advance(p,n) ((p)[0].cur_pos += (n) - 1, CORD_next(p))
 | 
			
		||||
        /* Advance position by n characters     */
 | 
			
		||||
        /* 0 < n < CORD_pos_chars_left(p)       */
 | 
			
		||||
 | 
			
		||||
#define CORD_pos_cur_char_addr(p) \
 | 
			
		||||
        (p)[0].cur_leaf + ((p)[0].cur_pos - (p)[0].cur_start)
 | 
			
		||||
        /* address of current character in cache.       */
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
  } /* extern "C" */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,89 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 1993-1994 by Xerox Corporation.  All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * 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 EC_H
 | 
			
		||||
#define EC_H
 | 
			
		||||
 | 
			
		||||
# ifndef CORD_H
 | 
			
		||||
#  include "cord.h"
 | 
			
		||||
# endif
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
  extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Extensible cords are strings that may be destructively appended to.  */
 | 
			
		||||
/* They allow fast construction of cords from characters that are       */
 | 
			
		||||
/* being read from a stream.                                            */
 | 
			
		||||
/*
 | 
			
		||||
 * A client might look like:
 | 
			
		||||
 *
 | 
			
		||||
 *      {
 | 
			
		||||
 *          CORD_ec x;
 | 
			
		||||
 *          CORD result;
 | 
			
		||||
 *          char c;
 | 
			
		||||
 *          FILE *f;
 | 
			
		||||
 *
 | 
			
		||||
 *          ...
 | 
			
		||||
 *          CORD_ec_init(x);
 | 
			
		||||
 *          while(...) {
 | 
			
		||||
 *              c = getc(f);
 | 
			
		||||
 *              ...
 | 
			
		||||
 *              CORD_ec_append(x, c);
 | 
			
		||||
 *          }
 | 
			
		||||
 *          result = CORD_balance(CORD_ec_to_cord(x));
 | 
			
		||||
 *
 | 
			
		||||
 * If a C string is desired as the final result, the call to CORD_balance
 | 
			
		||||
 * may be replaced by a call to CORD_to_char_star.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
# ifndef CORD_BUFSZ
 | 
			
		||||
#   define CORD_BUFSZ 128
 | 
			
		||||
# endif
 | 
			
		||||
 | 
			
		||||
typedef struct CORD_ec_struct {
 | 
			
		||||
    CORD ec_cord;
 | 
			
		||||
    char * ec_bufptr;
 | 
			
		||||
    char ec_buf[CORD_BUFSZ+1];
 | 
			
		||||
} CORD_ec[1];
 | 
			
		||||
 | 
			
		||||
/* This structure represents the concatenation of ec_cord with  */
 | 
			
		||||
/* ec_buf[0 ... (ec_bufptr-ec_buf-1)]                           */
 | 
			
		||||
 | 
			
		||||
/* Flush the buffer part of the extended cord into ec_cord.     */
 | 
			
		||||
/* Note that this is almost the only real function, and it is   */
 | 
			
		||||
/* implemented in 6 lines in cordxtra.c                         */
 | 
			
		||||
void CORD_ec_flush_buf(CORD_ec x);
 | 
			
		||||
 | 
			
		||||
/* Convert an extensible cord to a cord. */
 | 
			
		||||
# define CORD_ec_to_cord(x) (CORD_ec_flush_buf(x), (x)[0].ec_cord)
 | 
			
		||||
 | 
			
		||||
/* Initialize an extensible cord. */
 | 
			
		||||
#define CORD_ec_init(x) \
 | 
			
		||||
                ((x)[0].ec_cord = 0, (void)((x)[0].ec_bufptr = (x)[0].ec_buf))
 | 
			
		||||
 | 
			
		||||
/* Append a character to an extensible cord.    */
 | 
			
		||||
#define CORD_ec_append(x, c) \
 | 
			
		||||
                ((void)((x)[0].ec_bufptr == (x)[0].ec_buf + CORD_BUFSZ \
 | 
			
		||||
                        ? (CORD_ec_flush_buf(x), 0) : 0), \
 | 
			
		||||
                 (void)(*(x)[0].ec_bufptr++ = (c)))
 | 
			
		||||
 | 
			
		||||
/* Append a cord to an extensible cord.  Structure remains shared with  */
 | 
			
		||||
/* original.                                                            */
 | 
			
		||||
void CORD_ec_append_cord(CORD_ec x, CORD s);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
  } /* extern "C" */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* EC_H */
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
				
			
			@ -0,0 +1,96 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 1994 by Xerox Corporation.  All rights reserved.
 | 
			
		||||
 * Copyright (c) 1996 by Silicon Graphics.  All rights reserved.
 | 
			
		||||
 * Copyright (c) 1998 by Fergus Henderson.  All rights reserved.
 | 
			
		||||
 * Copyright (c) 2000-2009 by Hewlett-Packard Development Company.
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This is a simple API to implement pointer back tracing, i.e.
 | 
			
		||||
 * to answer questions such as "who is pointing to this" or
 | 
			
		||||
 * "why is this object being retained by the collector"
 | 
			
		||||
 *
 | 
			
		||||
 * Most of these calls yield useful information on only after
 | 
			
		||||
 * a garbage collection.  Usually the client will first force
 | 
			
		||||
 * a full collection and then gather information, preferably
 | 
			
		||||
 * before much intervening allocation.
 | 
			
		||||
 *
 | 
			
		||||
 * The implementation of the interface is only about 99.9999%
 | 
			
		||||
 * correct.  It is intended to be good enough for profiling,
 | 
			
		||||
 * but is not intended to be used with production code.
 | 
			
		||||
 *
 | 
			
		||||
 * Results are likely to be much more useful if all allocation is
 | 
			
		||||
 * accomplished through the debugging allocators.
 | 
			
		||||
 *
 | 
			
		||||
 * The implementation idea is due to A. Demers.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef GC_BACKPTR_H
 | 
			
		||||
#define GC_BACKPTR_H
 | 
			
		||||
 | 
			
		||||
#ifndef GC_H
 | 
			
		||||
# include "gc.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
  extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Store information about the object referencing dest in *base_p     */
 | 
			
		||||
/* and *offset_p.                                                     */
 | 
			
		||||
/* If multiple objects or roots point to dest, the one reported       */
 | 
			
		||||
/* will be the last on used by the garbage collector to trace the     */
 | 
			
		||||
/* object.                                                            */
 | 
			
		||||
/*   source is root ==> *base_p = address, *offset_p = 0              */
 | 
			
		||||
/*   source is heap object ==> *base_p != 0, *offset_p = offset       */
 | 
			
		||||
/*   Returns 1 on success, 0 if source couldn't be determined.        */
 | 
			
		||||
/* Dest can be any address within a heap object.                      */
 | 
			
		||||
typedef enum {
 | 
			
		||||
    GC_UNREFERENCED,    /* No reference info available.         */
 | 
			
		||||
    GC_NO_SPACE,        /* Dest not allocated with debug alloc. */
 | 
			
		||||
    GC_REFD_FROM_ROOT,  /* Referenced directly by root *base_p. */
 | 
			
		||||
    GC_REFD_FROM_REG,   /* Referenced from a register, i.e.     */
 | 
			
		||||
                        /* a root without an address.           */
 | 
			
		||||
    GC_REFD_FROM_HEAP,  /* Referenced from another heap obj.    */
 | 
			
		||||
    GC_FINALIZER_REFD   /* Finalizable and hence accessible.    */
 | 
			
		||||
} GC_ref_kind;
 | 
			
		||||
 | 
			
		||||
GC_API GC_ref_kind GC_CALL GC_get_back_ptr_info(void * /* dest */,
 | 
			
		||||
                                void ** /* base_p */, size_t * /* offset_p */)
 | 
			
		||||
                                GC_ATTR_NONNULL(1);
 | 
			
		||||
 | 
			
		||||
/* Generate a random heap address.            */
 | 
			
		||||
/* The resulting address is in the heap, but  */
 | 
			
		||||
/* not necessarily inside a valid object.     */
 | 
			
		||||
GC_API void * GC_CALL GC_generate_random_heap_address(void);
 | 
			
		||||
 | 
			
		||||
/* Generate a random address inside a valid marked heap object. */
 | 
			
		||||
GC_API void * GC_CALL GC_generate_random_valid_address(void);
 | 
			
		||||
 | 
			
		||||
/* Force a garbage collection and generate a backtrace from a   */
 | 
			
		||||
/* random heap address.                                         */
 | 
			
		||||
/* This uses the GC logging mechanism (GC_printf) to produce    */
 | 
			
		||||
/* output.  It can often be called from a debugger.  The        */
 | 
			
		||||
/* source in dbg_mlc.c also serves as a sample client.          */
 | 
			
		||||
GC_API void GC_CALL GC_generate_random_backtrace(void);
 | 
			
		||||
 | 
			
		||||
/* Print a backtrace from a specific address.  Used by the      */
 | 
			
		||||
/* above.  The client should call GC_gcollect() immediately     */
 | 
			
		||||
/* before invocation.                                           */
 | 
			
		||||
GC_API void GC_CALL GC_print_backtrace(void *) GC_ATTR_NONNULL(1);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
  } /* extern "C" */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* GC_BACKPTR_H */
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,457 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 1994 by Xerox Corporation.  All rights reserved.
 | 
			
		||||
 * Copyright (c) 1996 by Silicon Graphics.  All rights reserved.
 | 
			
		||||
 * Copyright (c) 1998 by Fergus Henderson.  All rights reserved.
 | 
			
		||||
 * Copyright (c) 2000-2009 by Hewlett-Packard Development Company.
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 * Copyright (c) 2008-2020 Ivan Maidanski
 | 
			
		||||
 *
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* This should never be included directly; it is included only from gc.h. */
 | 
			
		||||
/* We separate it only to make gc.h more suitable as documentation.       */
 | 
			
		||||
#if defined(GC_H)
 | 
			
		||||
 | 
			
		||||
/* Convenient internal macro to test version of GCC.    */
 | 
			
		||||
#if defined(__GNUC__) && defined(__GNUC_MINOR__)
 | 
			
		||||
# define GC_GNUC_PREREQ(major, minor) \
 | 
			
		||||
            ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((major) << 16) + (minor))
 | 
			
		||||
#else
 | 
			
		||||
# define GC_GNUC_PREREQ(major, minor) 0 /* FALSE */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Some tests for old macros.  These violate our namespace rules and    */
 | 
			
		||||
/* will disappear shortly.  Use the GC_ names.                          */
 | 
			
		||||
#if defined(SOLARIS_THREADS) || defined(_SOLARIS_THREADS) \
 | 
			
		||||
    || defined(_SOLARIS_PTHREADS) || defined(GC_SOLARIS_PTHREADS)
 | 
			
		||||
  /* We no longer support old style Solaris threads.            */
 | 
			
		||||
  /* GC_SOLARIS_THREADS now means pthreads.                     */
 | 
			
		||||
# ifndef GC_SOLARIS_THREADS
 | 
			
		||||
#   define GC_SOLARIS_THREADS
 | 
			
		||||
# endif
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(IRIX_THREADS)
 | 
			
		||||
# define GC_IRIX_THREADS
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(DGUX_THREADS) && !defined(GC_DGUX386_THREADS)
 | 
			
		||||
# define GC_DGUX386_THREADS
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(AIX_THREADS)
 | 
			
		||||
# define GC_AIX_THREADS
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(HPUX_THREADS)
 | 
			
		||||
# define GC_HPUX_THREADS
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(OSF1_THREADS)
 | 
			
		||||
# define GC_OSF1_THREADS
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(LINUX_THREADS)
 | 
			
		||||
# define GC_LINUX_THREADS
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(WIN32_THREADS)
 | 
			
		||||
# define GC_WIN32_THREADS
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(RTEMS_THREADS)
 | 
			
		||||
# define GC_RTEMS_PTHREADS
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(USE_LD_WRAP)
 | 
			
		||||
# define GC_USE_LD_WRAP
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(GC_WIN32_PTHREADS) && !defined(GC_WIN32_THREADS)
 | 
			
		||||
  /* Using pthreads-win32 library (or other Win32 implementation).  */
 | 
			
		||||
# define GC_WIN32_THREADS
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(GC_AIX_THREADS) || defined(GC_DARWIN_THREADS) \
 | 
			
		||||
    || defined(GC_DGUX386_THREADS) || defined(GC_FREEBSD_THREADS) \
 | 
			
		||||
    || defined(GC_HPUX_THREADS) \
 | 
			
		||||
    || defined(GC_IRIX_THREADS) || defined(GC_LINUX_THREADS) \
 | 
			
		||||
    || defined(GC_NETBSD_THREADS) || defined(GC_OPENBSD_THREADS) \
 | 
			
		||||
    || defined(GC_OSF1_THREADS) || defined(GC_SOLARIS_THREADS) \
 | 
			
		||||
    || defined(GC_WIN32_THREADS) || defined(GC_RTEMS_PTHREADS)
 | 
			
		||||
# ifndef GC_THREADS
 | 
			
		||||
#   define GC_THREADS
 | 
			
		||||
# endif
 | 
			
		||||
#elif defined(GC_THREADS)
 | 
			
		||||
# if defined(__linux__)
 | 
			
		||||
#   define GC_LINUX_THREADS
 | 
			
		||||
# elif defined(__OpenBSD__)
 | 
			
		||||
#   define GC_OPENBSD_THREADS
 | 
			
		||||
# elif defined(_PA_RISC1_1) || defined(_PA_RISC2_0) || defined(hppa) \
 | 
			
		||||
       || defined(__HPPA) || (defined(__ia64) && defined(_HPUX_SOURCE))
 | 
			
		||||
#   define GC_HPUX_THREADS
 | 
			
		||||
# elif defined(__HAIKU__)
 | 
			
		||||
#   define GC_HAIKU_THREADS
 | 
			
		||||
# elif (defined(__DragonFly__) || defined(__FreeBSD_kernel__) \
 | 
			
		||||
        || defined(__FreeBSD__)) && !defined(GC_NO_FREEBSD)
 | 
			
		||||
#   define GC_FREEBSD_THREADS
 | 
			
		||||
# elif defined(__NetBSD__)
 | 
			
		||||
#   define GC_NETBSD_THREADS
 | 
			
		||||
# elif defined(__alpha) || defined(__alpha__) /* && !Linux && !xBSD */
 | 
			
		||||
#   define GC_OSF1_THREADS
 | 
			
		||||
# elif (defined(mips) || defined(__mips) || defined(_mips)) \
 | 
			
		||||
        && !(defined(nec_ews) || defined(_nec_ews) \
 | 
			
		||||
             || defined(ultrix) || defined(__ultrix))
 | 
			
		||||
#   define GC_IRIX_THREADS
 | 
			
		||||
# elif defined(__sparc) /* && !Linux */ \
 | 
			
		||||
       || ((defined(sun) || defined(__sun)) \
 | 
			
		||||
           && (defined(i386) || defined(__i386__) \
 | 
			
		||||
               || defined(__amd64) || defined(__amd64__)))
 | 
			
		||||
#   define GC_SOLARIS_THREADS
 | 
			
		||||
# elif defined(__APPLE__) && defined(__MACH__)
 | 
			
		||||
#   define GC_DARWIN_THREADS
 | 
			
		||||
# endif
 | 
			
		||||
# if defined(DGUX) && (defined(i386) || defined(__i386__))
 | 
			
		||||
#   define GC_DGUX386_THREADS
 | 
			
		||||
# endif
 | 
			
		||||
# if defined(_AIX)
 | 
			
		||||
#   define GC_AIX_THREADS
 | 
			
		||||
# endif
 | 
			
		||||
# if (defined(_WIN32) || defined(_MSC_VER) || defined(__BORLANDC__) \
 | 
			
		||||
      || defined(__CYGWIN32__) || defined(__CYGWIN__) || defined(__CEGCC__) \
 | 
			
		||||
      || defined(_WIN32_WCE) || defined(__MINGW32__)) \
 | 
			
		||||
     && !defined(GC_WIN32_THREADS)
 | 
			
		||||
    /* Either posix or native Win32 threads. */
 | 
			
		||||
#   define GC_WIN32_THREADS
 | 
			
		||||
# endif
 | 
			
		||||
# if defined(__rtems__) && (defined(i386) || defined(__i386__))
 | 
			
		||||
#   define GC_RTEMS_PTHREADS
 | 
			
		||||
# endif
 | 
			
		||||
#endif /* GC_THREADS */
 | 
			
		||||
 | 
			
		||||
#undef GC_PTHREADS
 | 
			
		||||
#if (!defined(GC_WIN32_THREADS) || defined(GC_WIN32_PTHREADS) \
 | 
			
		||||
     || defined(__CYGWIN32__) || defined(__CYGWIN__)) && defined(GC_THREADS) \
 | 
			
		||||
    && !defined(NN_PLATFORM_CTR) && !defined(NN_BUILD_TARGET_PLATFORM_NX)
 | 
			
		||||
  /* Posix threads. */
 | 
			
		||||
# define GC_PTHREADS
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if !defined(_PTHREADS) && defined(GC_NETBSD_THREADS)
 | 
			
		||||
# define _PTHREADS
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(GC_DGUX386_THREADS) && !defined(_POSIX4A_DRAFT10_SOURCE)
 | 
			
		||||
# define _POSIX4A_DRAFT10_SOURCE 1
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if !defined(_REENTRANT) && defined(GC_PTHREADS) && !defined(GC_WIN32_THREADS)
 | 
			
		||||
  /* Better late than never.  This fails if system headers that depend  */
 | 
			
		||||
  /* on this were previously included.                                  */
 | 
			
		||||
# define _REENTRANT 1
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define __GC
 | 
			
		||||
#if !defined(_WIN32_WCE) || defined(__GNUC__)
 | 
			
		||||
# include <stddef.h>
 | 
			
		||||
# if defined(__MINGW32__) && !defined(_WIN32_WCE)
 | 
			
		||||
#   include <stdint.h>
 | 
			
		||||
    /* We mention uintptr_t.                                            */
 | 
			
		||||
    /* Perhaps this should be included in pure msft environments        */
 | 
			
		||||
    /* as well?                                                         */
 | 
			
		||||
# endif
 | 
			
		||||
#else /* _WIN32_WCE */
 | 
			
		||||
  /* Yet more kludges for WinCE.        */
 | 
			
		||||
# include <stdlib.h> /* size_t is defined here */
 | 
			
		||||
# ifndef _PTRDIFF_T_DEFINED
 | 
			
		||||
    /* ptrdiff_t is not defined */
 | 
			
		||||
#   define _PTRDIFF_T_DEFINED
 | 
			
		||||
    typedef long ptrdiff_t;
 | 
			
		||||
# endif
 | 
			
		||||
#endif /* _WIN32_WCE */
 | 
			
		||||
 | 
			
		||||
#if !defined(GC_NOT_DLL) && !defined(GC_DLL) \
 | 
			
		||||
    && ((defined(_DLL) && !defined(__GNUC__)) \
 | 
			
		||||
        || (defined(DLL_EXPORT) && defined(GC_BUILD)))
 | 
			
		||||
# define GC_DLL
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(GC_DLL) && !defined(GC_API)
 | 
			
		||||
 | 
			
		||||
# if defined(__CEGCC__)
 | 
			
		||||
#   if defined(GC_BUILD)
 | 
			
		||||
#     define GC_API __declspec(dllexport)
 | 
			
		||||
#   else
 | 
			
		||||
#     define GC_API __declspec(dllimport)
 | 
			
		||||
#   endif
 | 
			
		||||
 | 
			
		||||
# elif defined(__MINGW32__)
 | 
			
		||||
#   if defined(__cplusplus) && defined(GC_BUILD)
 | 
			
		||||
#     define GC_API extern __declspec(dllexport)
 | 
			
		||||
#   elif defined(GC_BUILD) || defined(__MINGW32_DELAY_LOAD__)
 | 
			
		||||
#     define GC_API __declspec(dllexport)
 | 
			
		||||
#   else
 | 
			
		||||
#     define GC_API extern __declspec(dllimport)
 | 
			
		||||
#   endif
 | 
			
		||||
 | 
			
		||||
# elif defined(_MSC_VER) || defined(__DMC__) || defined(__BORLANDC__) \
 | 
			
		||||
        || defined(__CYGWIN__)
 | 
			
		||||
#   ifdef GC_BUILD
 | 
			
		||||
#     define GC_API extern __declspec(dllexport)
 | 
			
		||||
#   else
 | 
			
		||||
#     define GC_API __declspec(dllimport)
 | 
			
		||||
#   endif
 | 
			
		||||
 | 
			
		||||
# elif defined(__WATCOMC__)
 | 
			
		||||
#   ifdef GC_BUILD
 | 
			
		||||
#     define GC_API extern __declspec(dllexport)
 | 
			
		||||
#   else
 | 
			
		||||
#     define GC_API extern __declspec(dllimport)
 | 
			
		||||
#   endif
 | 
			
		||||
 | 
			
		||||
# elif defined(__SYMBIAN32__)
 | 
			
		||||
#   ifdef GC_BUILD
 | 
			
		||||
#     define GC_API extern EXPORT_C
 | 
			
		||||
#   else
 | 
			
		||||
#     define GC_API extern IMPORT_C
 | 
			
		||||
#   endif
 | 
			
		||||
 | 
			
		||||
# elif defined(__GNUC__)
 | 
			
		||||
    /* Only matters if used in conjunction with -fvisibility=hidden option. */
 | 
			
		||||
#   if defined(GC_BUILD) && !defined(GC_NO_VISIBILITY) \
 | 
			
		||||
            && (GC_GNUC_PREREQ(4, 0) || defined(GC_VISIBILITY_HIDDEN_SET))
 | 
			
		||||
#     define GC_API extern __attribute__((__visibility__("default")))
 | 
			
		||||
#   endif
 | 
			
		||||
# endif
 | 
			
		||||
#endif /* GC_DLL */
 | 
			
		||||
 | 
			
		||||
#ifndef GC_API
 | 
			
		||||
# define GC_API extern
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef GC_CALL
 | 
			
		||||
# define GC_CALL
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef GC_CALLBACK
 | 
			
		||||
# define GC_CALLBACK GC_CALL
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef GC_ATTR_MALLOC
 | 
			
		||||
  /* 'malloc' attribute should be used for all malloc-like functions    */
 | 
			
		||||
  /* (to tell the compiler that a function may be treated as if any     */
 | 
			
		||||
  /* non-NULL pointer it returns cannot alias any other pointer valid   */
 | 
			
		||||
  /* when the function returns).  If the client code violates this rule */
 | 
			
		||||
  /* by using custom GC_oom_func then define GC_OOM_FUNC_RETURNS_ALIAS. */
 | 
			
		||||
# ifdef GC_OOM_FUNC_RETURNS_ALIAS
 | 
			
		||||
#   define GC_ATTR_MALLOC /* empty */
 | 
			
		||||
# elif GC_GNUC_PREREQ(3, 1)
 | 
			
		||||
#   define GC_ATTR_MALLOC __attribute__((__malloc__))
 | 
			
		||||
# elif defined(_MSC_VER) && (_MSC_VER >= 1900) && !defined(__EDG__)
 | 
			
		||||
#   define GC_ATTR_MALLOC \
 | 
			
		||||
                __declspec(allocator) __declspec(noalias) __declspec(restrict)
 | 
			
		||||
# elif defined(_MSC_VER) && _MSC_VER >= 1400
 | 
			
		||||
#   define GC_ATTR_MALLOC __declspec(noalias) __declspec(restrict)
 | 
			
		||||
# else
 | 
			
		||||
#   define GC_ATTR_MALLOC
 | 
			
		||||
# endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef GC_ATTR_ALLOC_SIZE
 | 
			
		||||
  /* 'alloc_size' attribute improves __builtin_object_size correctness. */
 | 
			
		||||
# undef GC_ATTR_CALLOC_SIZE
 | 
			
		||||
# ifdef __clang__
 | 
			
		||||
#   if __has_attribute(__alloc_size__)
 | 
			
		||||
#     define GC_ATTR_ALLOC_SIZE(argnum) __attribute__((__alloc_size__(argnum)))
 | 
			
		||||
#     define GC_ATTR_CALLOC_SIZE(n, s) __attribute__((__alloc_size__(n, s)))
 | 
			
		||||
#   else
 | 
			
		||||
#     define GC_ATTR_ALLOC_SIZE(argnum) /* empty */
 | 
			
		||||
#   endif
 | 
			
		||||
# elif GC_GNUC_PREREQ(4, 3) && !defined(__ICC)
 | 
			
		||||
#   define GC_ATTR_ALLOC_SIZE(argnum) __attribute__((__alloc_size__(argnum)))
 | 
			
		||||
#   define GC_ATTR_CALLOC_SIZE(n, s) __attribute__((__alloc_size__(n, s)))
 | 
			
		||||
# else
 | 
			
		||||
#   define GC_ATTR_ALLOC_SIZE(argnum) /* empty */
 | 
			
		||||
# endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef GC_ATTR_CALLOC_SIZE
 | 
			
		||||
# define GC_ATTR_CALLOC_SIZE(n, s) /* empty */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef GC_ATTR_NONNULL
 | 
			
		||||
# if GC_GNUC_PREREQ(4, 0)
 | 
			
		||||
#   define GC_ATTR_NONNULL(argnum) __attribute__((__nonnull__(argnum)))
 | 
			
		||||
# else
 | 
			
		||||
#   define GC_ATTR_NONNULL(argnum) /* empty */
 | 
			
		||||
# endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef GC_ATTR_CONST
 | 
			
		||||
# if GC_GNUC_PREREQ(4, 0)
 | 
			
		||||
#   define GC_ATTR_CONST __attribute__((__const__))
 | 
			
		||||
# else
 | 
			
		||||
#   define GC_ATTR_CONST /* empty */
 | 
			
		||||
# endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef GC_ATTR_DEPRECATED
 | 
			
		||||
# ifdef GC_BUILD
 | 
			
		||||
#   undef GC_ATTR_DEPRECATED
 | 
			
		||||
#   define GC_ATTR_DEPRECATED /* empty */
 | 
			
		||||
# elif GC_GNUC_PREREQ(4, 0)
 | 
			
		||||
#   define GC_ATTR_DEPRECATED __attribute__((__deprecated__))
 | 
			
		||||
# elif defined(_MSC_VER) && _MSC_VER >= 1200
 | 
			
		||||
#   define GC_ATTR_DEPRECATED __declspec(deprecated)
 | 
			
		||||
# else
 | 
			
		||||
#   define GC_ATTR_DEPRECATED /* empty */
 | 
			
		||||
# endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(__sgi) && !defined(__GNUC__) && _COMPILER_VERSION >= 720
 | 
			
		||||
# define GC_ADD_CALLER
 | 
			
		||||
# define GC_RETURN_ADDR (GC_word)__return_address
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(__linux__) || defined(__GLIBC__)
 | 
			
		||||
# if !defined(__native_client__)
 | 
			
		||||
#   include <features.h>
 | 
			
		||||
# endif
 | 
			
		||||
# if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1 || __GLIBC__ > 2) \
 | 
			
		||||
        && !defined(__ia64__) \
 | 
			
		||||
        && !defined(GC_MISSING_EXECINFO_H) \
 | 
			
		||||
        && !defined(GC_HAVE_BUILTIN_BACKTRACE)
 | 
			
		||||
#   define GC_HAVE_BUILTIN_BACKTRACE
 | 
			
		||||
# endif
 | 
			
		||||
# if defined(__i386__) || defined(__amd64__) || defined(__x86_64__)
 | 
			
		||||
#   define GC_CAN_SAVE_CALL_STACKS
 | 
			
		||||
# endif
 | 
			
		||||
#endif /* GLIBC */
 | 
			
		||||
 | 
			
		||||
#if defined(_MSC_VER) && _MSC_VER >= 1200 /* version 12.0+ (MSVC 6.0+) */ \
 | 
			
		||||
        && !defined(_AMD64_) && !defined(_M_X64) && !defined(_WIN32_WCE) \
 | 
			
		||||
        && !defined(GC_HAVE_NO_BUILTIN_BACKTRACE) \
 | 
			
		||||
        && !defined(GC_HAVE_BUILTIN_BACKTRACE)
 | 
			
		||||
# define GC_HAVE_BUILTIN_BACKTRACE
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(GC_HAVE_BUILTIN_BACKTRACE) && !defined(GC_CAN_SAVE_CALL_STACKS)
 | 
			
		||||
# define GC_CAN_SAVE_CALL_STACKS
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(__sparc__)
 | 
			
		||||
# define GC_CAN_SAVE_CALL_STACKS
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* If we're on a platform on which we can't save call stacks, but       */
 | 
			
		||||
/* gcc is normally used, we go ahead and define GC_ADD_CALLER.          */
 | 
			
		||||
/* We make this decision independent of whether gcc is actually being   */
 | 
			
		||||
/* used, in order to keep the interface consistent, and allow mixing    */
 | 
			
		||||
/* of compilers.                                                        */
 | 
			
		||||
/* This may also be desirable if it is possible but expensive to        */
 | 
			
		||||
/* retrieve the call chain.                                             */
 | 
			
		||||
#if (defined(__linux__) || defined(__DragonFly__) || defined(__FreeBSD__) \
 | 
			
		||||
     || defined(__FreeBSD_kernel__) || defined(__HAIKU__) \
 | 
			
		||||
     || defined(__NetBSD__) || defined(__OpenBSD__) \
 | 
			
		||||
     || defined(HOST_ANDROID) || defined(__ANDROID__)) \
 | 
			
		||||
    && !defined(GC_CAN_SAVE_CALL_STACKS)
 | 
			
		||||
# define GC_ADD_CALLER
 | 
			
		||||
# if GC_GNUC_PREREQ(2, 95)
 | 
			
		||||
    /* gcc knows how to retrieve return address, but we don't know      */
 | 
			
		||||
    /* how to generate call stacks.                                     */
 | 
			
		||||
#   define GC_RETURN_ADDR (GC_word)__builtin_return_address(0)
 | 
			
		||||
#   if GC_GNUC_PREREQ(4, 0) && (defined(__i386__) || defined(__amd64__) \
 | 
			
		||||
                        || defined(__x86_64__) /* and probably others... */) \
 | 
			
		||||
       && !defined(GC_NO_RETURN_ADDR_PARENT)
 | 
			
		||||
#     define GC_HAVE_RETURN_ADDR_PARENT
 | 
			
		||||
#     define GC_RETURN_ADDR_PARENT \
 | 
			
		||||
        (GC_word)__builtin_extract_return_addr(__builtin_return_address(1))
 | 
			
		||||
            /* Note: a compiler might complain that calling                 */
 | 
			
		||||
            /* __builtin_return_address with a nonzero argument is unsafe.  */
 | 
			
		||||
#   endif
 | 
			
		||||
# else
 | 
			
		||||
    /* Just pass 0 for gcc compatibility.       */
 | 
			
		||||
#   define GC_RETURN_ADDR 0
 | 
			
		||||
# endif
 | 
			
		||||
#endif /* !GC_CAN_SAVE_CALL_STACKS */
 | 
			
		||||
 | 
			
		||||
#ifdef GC_PTHREADS
 | 
			
		||||
 | 
			
		||||
# if (defined(GC_DARWIN_THREADS) || defined(GC_WIN32_PTHREADS) \
 | 
			
		||||
      || defined(__native_client__) || defined(GC_RTEMS_PTHREADS)) \
 | 
			
		||||
      && !defined(GC_NO_DLOPEN)
 | 
			
		||||
    /* Either there is no dlopen() or we do not need to intercept it.   */
 | 
			
		||||
#   define GC_NO_DLOPEN
 | 
			
		||||
# endif
 | 
			
		||||
 | 
			
		||||
# if (defined(GC_DARWIN_THREADS) || defined(GC_WIN32_PTHREADS) \
 | 
			
		||||
      || defined(GC_OPENBSD_THREADS) || defined(__native_client__)) \
 | 
			
		||||
     && !defined(GC_NO_PTHREAD_SIGMASK)
 | 
			
		||||
    /* Either there is no pthread_sigmask() or no need to intercept it. */
 | 
			
		||||
#   define GC_NO_PTHREAD_SIGMASK
 | 
			
		||||
# endif
 | 
			
		||||
 | 
			
		||||
# if defined(__native_client__)
 | 
			
		||||
    /* At present, NaCl pthread_create() prototype does not have        */
 | 
			
		||||
    /* "const" for its "attr" argument; also, NaCl pthread_exit() one   */
 | 
			
		||||
    /* does not have "noreturn" attribute.                              */
 | 
			
		||||
#   ifndef GC_PTHREAD_CREATE_CONST
 | 
			
		||||
#     define GC_PTHREAD_CREATE_CONST /* empty */
 | 
			
		||||
#   endif
 | 
			
		||||
#   ifndef GC_HAVE_PTHREAD_EXIT
 | 
			
		||||
#     define GC_HAVE_PTHREAD_EXIT
 | 
			
		||||
#     define GC_PTHREAD_EXIT_ATTRIBUTE /* empty */
 | 
			
		||||
#   endif
 | 
			
		||||
# endif
 | 
			
		||||
 | 
			
		||||
# if !defined(GC_HAVE_PTHREAD_EXIT) \
 | 
			
		||||
     && !defined(HOST_ANDROID) && !defined(__ANDROID__) \
 | 
			
		||||
     && (defined(GC_LINUX_THREADS) || defined(GC_SOLARIS_THREADS))
 | 
			
		||||
#   define GC_HAVE_PTHREAD_EXIT
 | 
			
		||||
    /* Intercept pthread_exit on Linux and Solaris.     */
 | 
			
		||||
#   if GC_GNUC_PREREQ(2, 7)
 | 
			
		||||
#     define GC_PTHREAD_EXIT_ATTRIBUTE __attribute__((__noreturn__))
 | 
			
		||||
#   elif defined(__NORETURN) /* used in Solaris */
 | 
			
		||||
#     define GC_PTHREAD_EXIT_ATTRIBUTE __NORETURN
 | 
			
		||||
#   else
 | 
			
		||||
#     define GC_PTHREAD_EXIT_ATTRIBUTE /* empty */
 | 
			
		||||
#   endif
 | 
			
		||||
# endif
 | 
			
		||||
 | 
			
		||||
# if (!defined(GC_HAVE_PTHREAD_EXIT) || defined(__native_client__)) \
 | 
			
		||||
     && !defined(GC_NO_PTHREAD_CANCEL)
 | 
			
		||||
    /* Either there is no pthread_cancel() or no need to intercept it.  */
 | 
			
		||||
#   define GC_NO_PTHREAD_CANCEL
 | 
			
		||||
# endif
 | 
			
		||||
 | 
			
		||||
#endif /* GC_PTHREADS */
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
 | 
			
		||||
#ifndef GC_ATTR_EXPLICIT
 | 
			
		||||
# if __cplusplus >= 201103L && !defined(__clang__) || _MSVC_LANG >= 201103L \
 | 
			
		||||
     || defined(CPPCHECK)
 | 
			
		||||
#   define GC_ATTR_EXPLICIT explicit
 | 
			
		||||
# else
 | 
			
		||||
#   define GC_ATTR_EXPLICIT /* empty */
 | 
			
		||||
# endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef GC_NOEXCEPT
 | 
			
		||||
# if defined(__DMC__) || (defined(__BORLANDC__) \
 | 
			
		||||
        && (defined(_RWSTD_NO_EXCEPTIONS) || defined(_RWSTD_NO_EX_SPEC))) \
 | 
			
		||||
     || (defined(_MSC_VER) && defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS) \
 | 
			
		||||
     || (defined(__WATCOMC__) && !defined(_CPPUNWIND))
 | 
			
		||||
#   define GC_NOEXCEPT /* empty */
 | 
			
		||||
#   ifndef GC_NEW_ABORTS_ON_OOM
 | 
			
		||||
#     define GC_NEW_ABORTS_ON_OOM
 | 
			
		||||
#   endif
 | 
			
		||||
# elif __cplusplus >= 201103L || _MSVC_LANG >= 201103L
 | 
			
		||||
#   define GC_NOEXCEPT noexcept
 | 
			
		||||
# else
 | 
			
		||||
#   define GC_NOEXCEPT throw()
 | 
			
		||||
# endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* __cplusplus */
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,208 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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 GC_GNUC_PREREQ(3, 0)
 | 
			
		||||
# 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
 | 
			
		||||
 | 
			
		||||
#ifndef GC_ASSERT
 | 
			
		||||
# ifdef NDEBUG
 | 
			
		||||
#   define GC_ASSERT(expr) /* empty */
 | 
			
		||||
# else
 | 
			
		||||
#   include <assert.h>
 | 
			
		||||
#   define GC_ASSERT(expr) assert(expr)
 | 
			
		||||
# endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
  extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef GC_PREFETCH_FOR_WRITE
 | 
			
		||||
# if GC_GNUC_PREREQ(3, 0) && !defined(GC_NO_PREFETCH_FOR_WRITE)
 | 
			
		||||
#   define GC_PREFETCH_FOR_WRITE(x) __builtin_prefetch((x), 1)
 | 
			
		||||
# else
 | 
			
		||||
#   define GC_PREFETCH_FOR_WRITE(x) (void)0
 | 
			
		||||
# endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Object kinds; must match PTRFREE, NORMAL in gc_priv.h.       */
 | 
			
		||||
#define GC_I_PTRFREE 0
 | 
			
		||||
#define GC_I_NORMAL 1
 | 
			
		||||
 | 
			
		||||
/* 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 */);
 | 
			
		||||
 | 
			
		||||
/* Generalized version of GC_malloc and GC_malloc_atomic.               */
 | 
			
		||||
/* Uses appropriately the thread-local (if available) or the global     */
 | 
			
		||||
/* free-list of the specified kind.                                     */
 | 
			
		||||
GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
 | 
			
		||||
        GC_malloc_kind(size_t /* lb */, int /* k */);
 | 
			
		||||
 | 
			
		||||
#ifdef GC_THREADS
 | 
			
		||||
  /* Same as above but uses only the global free-list.  */
 | 
			
		||||
  GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
 | 
			
		||||
        GC_malloc_kind_global(size_t /* lb */, int /* k */);
 | 
			
		||||
#else
 | 
			
		||||
# define GC_malloc_kind_global GC_malloc_kind
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* An internal macro to update the free list pointer atomically (if     */
 | 
			
		||||
/* the AO primitives are available) to avoid race with the marker.      */
 | 
			
		||||
#if defined(GC_THREADS) && defined(AO_HAVE_store)
 | 
			
		||||
# define GC_FAST_M_AO_STORE(my_fl, next) \
 | 
			
		||||
                AO_store((volatile AO_t *)(my_fl), (AO_t)(next))
 | 
			
		||||
#else
 | 
			
		||||
# define GC_FAST_M_AO_STORE(my_fl, next) (void)(*(my_fl) = (next))
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* 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 num_direct granules   */
 | 
			
		||||
/* directly using generic_malloc 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) \
 | 
			
		||||
  do { \
 | 
			
		||||
    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; \
 | 
			
		||||
    \
 | 
			
		||||
        for (;;) { \
 | 
			
		||||
            if (GC_EXPECT((GC_word)my_entry \
 | 
			
		||||
                          > (num_direct) + GC_TINY_FREELISTS + 1, 1)) { \
 | 
			
		||||
                next = *(void **)(my_entry); \
 | 
			
		||||
                result = (void *)my_entry; \
 | 
			
		||||
                GC_FAST_M_AO_STORE(my_fl, next); \
 | 
			
		||||
                init; \
 | 
			
		||||
                GC_PREFETCH_FOR_WRITE(next); \
 | 
			
		||||
                if ((kind) != GC_I_PTRFREE) { \
 | 
			
		||||
                    GC_end_stubborn_change(my_fl); \
 | 
			
		||||
                    GC_reachable_here(next); \
 | 
			
		||||
                } \
 | 
			
		||||
                GC_ASSERT(GC_size(result) >= (granules)*GC_GRANULE_BYTES); \
 | 
			
		||||
                GC_ASSERT((kind) == GC_I_PTRFREE \
 | 
			
		||||
                          || ((GC_word *)result)[1] == 0); \
 | 
			
		||||
                break; \
 | 
			
		||||
            } \
 | 
			
		||||
            /* Entry contains counter or NULL */ \
 | 
			
		||||
            if ((GC_signed_word)my_entry - (GC_signed_word)(num_direct) <= 0 \
 | 
			
		||||
                    /* (GC_word)my_entry <= (num_direct) */ \
 | 
			
		||||
                    && my_entry != 0 /* NULL */) { \
 | 
			
		||||
                /* Small counter value, not NULL */ \
 | 
			
		||||
                GC_FAST_M_AO_STORE(my_fl, (char *)my_entry \
 | 
			
		||||
                                          + (granules) + 1); \
 | 
			
		||||
                result = (default_expr); \
 | 
			
		||||
                break; \
 | 
			
		||||
            } 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); \
 | 
			
		||||
                    break; \
 | 
			
		||||
                } \
 | 
			
		||||
            } \
 | 
			
		||||
        } \
 | 
			
		||||
    } \
 | 
			
		||||
  } while (0)
 | 
			
		||||
 | 
			
		||||
# 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.                 */
 | 
			
		||||
/* Does not acquire lock.  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_KIND(result,n,tiny_fl,kind,init) \
 | 
			
		||||
    do { \
 | 
			
		||||
      size_t granules = GC_WORDS_TO_WHOLE_GRANULES(n); \
 | 
			
		||||
      GC_FAST_MALLOC_GRANS(result, granules, tiny_fl, 0, kind, \
 | 
			
		||||
                           GC_malloc_kind(granules*GC_GRANULE_BYTES, kind), \
 | 
			
		||||
                           init); \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
# define GC_MALLOC_WORDS(result,n,tiny_fl) \
 | 
			
		||||
        GC_MALLOC_WORDS_KIND(result, n, tiny_fl, GC_I_NORMAL, \
 | 
			
		||||
                             *(void **)(result) = 0)
 | 
			
		||||
 | 
			
		||||
# define GC_MALLOC_ATOMIC_WORDS(result,n,tiny_fl) \
 | 
			
		||||
        GC_MALLOC_WORDS_KIND(result, n, tiny_fl, GC_I_PTRFREE, (void)0)
 | 
			
		||||
 | 
			
		||||
/* And once more for two word initialized objects: */
 | 
			
		||||
# define GC_CONS(result, first, second, tiny_fl) \
 | 
			
		||||
    do { \
 | 
			
		||||
      void *l = (void *)(first); \
 | 
			
		||||
      void *r = (void *)(second); \
 | 
			
		||||
      GC_MALLOC_WORDS_KIND(result, 2, tiny_fl, GC_I_NORMAL, (void)0); \
 | 
			
		||||
      if ((result) != 0 /* NULL */) { \
 | 
			
		||||
        *(void **)(result) = l; \
 | 
			
		||||
        GC_PTR_STORE_AND_DIRTY((void **)(result) + 1, r); \
 | 
			
		||||
        GC_reachable_here(l); \
 | 
			
		||||
      } \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
GC_API void GC_CALL GC_print_free_list(int /* kind */,
 | 
			
		||||
                                       size_t /* sz_in_granules */);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
  } /* extern "C" */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* !GC_INLINE_H */
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,328 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
 | 
			
		||||
 * Copyright (c) 2001 by Hewlett-Packard Company. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * 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.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This contains interfaces to the GC marker that are likely to be useful to
 | 
			
		||||
 * clients that provide detailed heap layout information to the collector.
 | 
			
		||||
 * This interface should not be used by normal C or C++ clients.
 | 
			
		||||
 * It will be useful to runtimes for other languages.
 | 
			
		||||
 *
 | 
			
		||||
 * This is an experts-only interface!  There are many ways to break the
 | 
			
		||||
 * collector in subtle ways by using this functionality.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef GC_MARK_H
 | 
			
		||||
#define GC_MARK_H
 | 
			
		||||
 | 
			
		||||
#ifndef GC_H
 | 
			
		||||
# include "gc.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
  extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* A client supplied mark procedure.  Returns new mark stack pointer.   */
 | 
			
		||||
/* Primary effect should be to push new entries on the mark stack.      */
 | 
			
		||||
/* Mark stack pointer values are passed and returned explicitly.        */
 | 
			
		||||
/* Global variables describing mark stack are not necessarily valid.    */
 | 
			
		||||
/* (This usually saves a few cycles by keeping things in registers.)    */
 | 
			
		||||
/* Assumed to scan about GC_PROC_BYTES on average.  If it needs to do   */
 | 
			
		||||
/* much more work than that, it should do it in smaller pieces by       */
 | 
			
		||||
/* pushing itself back on the mark stack.                               */
 | 
			
		||||
/* Note that it should always do some work (defined as marking some     */
 | 
			
		||||
/* objects) before pushing more than one entry on the mark stack.       */
 | 
			
		||||
/* This is required to ensure termination in the event of mark stack    */
 | 
			
		||||
/* overflows.                                                           */
 | 
			
		||||
/* This procedure is always called with at least one empty entry on the */
 | 
			
		||||
/* mark stack.                                                          */
 | 
			
		||||
/* Currently we require that mark procedures look for pointers in a     */
 | 
			
		||||
/* subset of the places the conservative marker would.  It must be safe */
 | 
			
		||||
/* to invoke the normal mark procedure instead.                         */
 | 
			
		||||
/* WARNING: Such a mark procedure may be invoked on an unused object    */
 | 
			
		||||
/* residing on a free list.  Such objects are cleared, except for a     */
 | 
			
		||||
/* free list link field in the first word.  Thus mark procedures may    */
 | 
			
		||||
/* not count on the presence of a type descriptor, and must handle this */
 | 
			
		||||
/* case correctly somehow.                                              */
 | 
			
		||||
#define GC_PROC_BYTES 100
 | 
			
		||||
 | 
			
		||||
#if defined(GC_BUILD) || defined(NOT_GCBUILD)
 | 
			
		||||
  struct GC_ms_entry;
 | 
			
		||||
#else
 | 
			
		||||
  struct GC_ms_entry { void *opaque; };
 | 
			
		||||
#endif
 | 
			
		||||
typedef struct GC_ms_entry * (*GC_mark_proc)(GC_word * /* addr */,
 | 
			
		||||
                                struct GC_ms_entry * /* mark_stack_ptr */,
 | 
			
		||||
                                struct GC_ms_entry * /* mark_stack_limit */,
 | 
			
		||||
                                GC_word /* env */);
 | 
			
		||||
 | 
			
		||||
#define GC_LOG_MAX_MARK_PROCS 6
 | 
			
		||||
#define GC_MAX_MARK_PROCS (1 << GC_LOG_MAX_MARK_PROCS)
 | 
			
		||||
 | 
			
		||||
/* In a few cases it's necessary to assign statically known indices to  */
 | 
			
		||||
/* certain mark procs.  Thus we reserve a few for well known clients.   */
 | 
			
		||||
/* (This is necessary if mark descriptors are compiler generated.)      */
 | 
			
		||||
#define GC_RESERVED_MARK_PROCS 8
 | 
			
		||||
#define GC_GCJ_RESERVED_MARK_PROC_INDEX 0
 | 
			
		||||
 | 
			
		||||
/* Object descriptors on mark stack or in objects.  Low order two       */
 | 
			
		||||
/* bits are tags distinguishing among the following 4 possibilities     */
 | 
			
		||||
/* for the high order 30 bits.                                          */
 | 
			
		||||
#define GC_DS_TAG_BITS 2
 | 
			
		||||
#define GC_DS_TAGS   ((1 << GC_DS_TAG_BITS) - 1)
 | 
			
		||||
#define GC_DS_LENGTH 0  /* The entire word is a length in bytes that    */
 | 
			
		||||
                        /* must be a multiple of 4.                     */
 | 
			
		||||
#define GC_DS_BITMAP 1  /* 30 (62) bits are a bitmap describing pointer */
 | 
			
		||||
                        /* fields.  The msb is 1 if the first word      */
 | 
			
		||||
                        /* is a pointer.                                */
 | 
			
		||||
                        /* (This unconventional ordering sometimes      */
 | 
			
		||||
                        /* makes the marker slightly faster.)           */
 | 
			
		||||
                        /* Zeroes indicate definite nonpointers.  Ones  */
 | 
			
		||||
                        /* indicate possible pointers.                  */
 | 
			
		||||
                        /* Only usable if pointers are word aligned.    */
 | 
			
		||||
#define GC_DS_PROC   2
 | 
			
		||||
                        /* The objects referenced by this object can be */
 | 
			
		||||
                        /* pushed on the mark stack by invoking         */
 | 
			
		||||
                        /* PROC(descr).  ENV(descr) is passed as the    */
 | 
			
		||||
                        /* last argument.                               */
 | 
			
		||||
#define GC_MAKE_PROC(proc_index, env) \
 | 
			
		||||
            (((((env) << GC_LOG_MAX_MARK_PROCS) \
 | 
			
		||||
               | (proc_index)) << GC_DS_TAG_BITS) | GC_DS_PROC)
 | 
			
		||||
#define GC_DS_PER_OBJECT 3  /* The real descriptor is at the            */
 | 
			
		||||
                        /* byte displacement from the beginning of the  */
 | 
			
		||||
                        /* object given by descr & ~GC_DS_TAGS.         */
 | 
			
		||||
                        /* If the descriptor is negative, the real      */
 | 
			
		||||
                        /* descriptor is at (*<object_start>) -         */
 | 
			
		||||
                        /* (descr&~GC_DS_TAGS) - GC_INDIR_PER_OBJ_BIAS  */
 | 
			
		||||
                        /* The latter alternative can be used if each   */
 | 
			
		||||
                        /* object contains a type descriptor in the     */
 | 
			
		||||
                        /* first word.                                  */
 | 
			
		||||
                        /* Note that in the multi-threaded environments */
 | 
			
		||||
                        /* per-object descriptors must be located in    */
 | 
			
		||||
                        /* either the first two or last two words of    */
 | 
			
		||||
                        /* the object, since only those are guaranteed  */
 | 
			
		||||
                        /* to be cleared while the allocation lock is   */
 | 
			
		||||
                        /* held.                                        */
 | 
			
		||||
#define GC_INDIR_PER_OBJ_BIAS 0x10
 | 
			
		||||
 | 
			
		||||
GC_API void * GC_least_plausible_heap_addr;
 | 
			
		||||
GC_API void * GC_greatest_plausible_heap_addr;
 | 
			
		||||
                        /* Bounds on the heap.  Guaranteed valid        */
 | 
			
		||||
                        /* Likely to include future heap expansion.     */
 | 
			
		||||
                        /* Hence usually includes not-yet-mapped        */
 | 
			
		||||
                        /* memory.                                      */
 | 
			
		||||
 | 
			
		||||
/* Handle nested references in a custom mark procedure.                 */
 | 
			
		||||
/* Check if obj is a valid object. If so, ensure that it is marked.     */
 | 
			
		||||
/* If it was not previously marked, push its contents onto the mark     */
 | 
			
		||||
/* stack for future scanning.  The object will then be scanned using    */
 | 
			
		||||
/* its mark descriptor.                                                 */
 | 
			
		||||
/* Returns the new mark stack pointer.                                  */
 | 
			
		||||
/* Handles mark stack overflows correctly.                              */
 | 
			
		||||
/* Since this marks first, it makes progress even if there are mark     */
 | 
			
		||||
/* stack overflows.                                                     */
 | 
			
		||||
/* Src is the address of the pointer to obj, which is used only         */
 | 
			
		||||
/* for back pointer-based heap debugging.                               */
 | 
			
		||||
/* It is strongly recommended that most objects be handled without mark */
 | 
			
		||||
/* procedures, e.g. with bitmap descriptors, and that mark procedures   */
 | 
			
		||||
/* be reserved for exceptional cases.  That will ensure that            */
 | 
			
		||||
/* performance of this call is not extremely performance critical.      */
 | 
			
		||||
/* (Otherwise we would need to inline GC_mark_and_push completely,      */
 | 
			
		||||
/* which would tie the client code to a fixed collector version.)       */
 | 
			
		||||
/* Note that mark procedures should explicitly call FIXUP_POINTER()     */
 | 
			
		||||
/* if required.                                                         */
 | 
			
		||||
GC_API struct GC_ms_entry * GC_CALL GC_mark_and_push(void * /* obj */,
 | 
			
		||||
                                struct GC_ms_entry * /* mark_stack_ptr */,
 | 
			
		||||
                                struct GC_ms_entry * /* mark_stack_limit */,
 | 
			
		||||
                                void ** /* src */);
 | 
			
		||||
 | 
			
		||||
#define GC_MARK_AND_PUSH(obj, msp, lim, src) \
 | 
			
		||||
          ((GC_word)(obj) >= (GC_word)GC_least_plausible_heap_addr && \
 | 
			
		||||
           (GC_word)(obj) <= (GC_word)GC_greatest_plausible_heap_addr ? \
 | 
			
		||||
           GC_mark_and_push(obj, msp, lim, src) : (msp))
 | 
			
		||||
 | 
			
		||||
/* The size of the header added to objects allocated through the        */
 | 
			
		||||
/* GC_debug routines.  Defined as a function so that client mark        */
 | 
			
		||||
/* procedures do not need to be recompiled for the collector library    */
 | 
			
		||||
/* version changes.                                                     */
 | 
			
		||||
GC_API GC_ATTR_CONST size_t GC_CALL GC_get_debug_header_size(void);
 | 
			
		||||
#define GC_USR_PTR_FROM_BASE(p) \
 | 
			
		||||
                ((void *)((char *)(p) + GC_get_debug_header_size()))
 | 
			
		||||
 | 
			
		||||
/* The same but defined as a variable.  Exists only for the backward    */
 | 
			
		||||
/* compatibility.  Some compilers do not accept "const" together with   */
 | 
			
		||||
/* deprecated or dllimport attributes, so the symbol is exported as     */
 | 
			
		||||
/* a non-constant one.                                                  */
 | 
			
		||||
GC_API GC_ATTR_DEPRECATED
 | 
			
		||||
# ifdef GC_BUILD
 | 
			
		||||
    const
 | 
			
		||||
# endif
 | 
			
		||||
  size_t GC_debug_header_size;
 | 
			
		||||
 | 
			
		||||
/* And some routines to support creation of new "kinds", e.g. with      */
 | 
			
		||||
/* custom mark procedures, by language runtimes.                        */
 | 
			
		||||
/* The _inner versions assume the caller holds the allocation lock.     */
 | 
			
		||||
 | 
			
		||||
/* Return a new free list array.        */
 | 
			
		||||
GC_API void ** GC_CALL GC_new_free_list(void);
 | 
			
		||||
GC_API void ** GC_CALL GC_new_free_list_inner(void);
 | 
			
		||||
 | 
			
		||||
/* Return a new kind, as specified. */
 | 
			
		||||
GC_API unsigned GC_CALL GC_new_kind(void ** /* free_list */,
 | 
			
		||||
                            GC_word /* mark_descriptor_template */,
 | 
			
		||||
                            int /* add_size_to_descriptor */,
 | 
			
		||||
                            int /* clear_new_objects */) GC_ATTR_NONNULL(1);
 | 
			
		||||
                /* The last two parameters must be zero or one. */
 | 
			
		||||
GC_API unsigned GC_CALL GC_new_kind_inner(void ** /* free_list */,
 | 
			
		||||
                            GC_word /* mark_descriptor_template */,
 | 
			
		||||
                            int /* add_size_to_descriptor */,
 | 
			
		||||
                            int /* clear_new_objects */) GC_ATTR_NONNULL(1);
 | 
			
		||||
 | 
			
		||||
/* Return a new mark procedure identifier, suitable for use as  */
 | 
			
		||||
/* the first argument in GC_MAKE_PROC.                          */
 | 
			
		||||
GC_API unsigned GC_CALL GC_new_proc(GC_mark_proc);
 | 
			
		||||
GC_API unsigned GC_CALL GC_new_proc_inner(GC_mark_proc);
 | 
			
		||||
 | 
			
		||||
/* Allocate an object of a given kind.  By default, there are only      */
 | 
			
		||||
/* a few kinds: composite (pointerful), atomic, uncollectible, etc.     */
 | 
			
		||||
/* We claim it is possible for clever client code that understands the  */
 | 
			
		||||
/* GC internals to add more, e.g. to communicate object layout          */
 | 
			
		||||
/* information to the collector.  Note that in the multi-threaded       */
 | 
			
		||||
/* contexts, this is usually unsafe for kinds that have the descriptor  */
 | 
			
		||||
/* in the object itself, since there is otherwise a window in which     */
 | 
			
		||||
/* the descriptor is not correct.  Even in the single-threaded case,    */
 | 
			
		||||
/* we need to be sure that cleared objects on a free list don't         */
 | 
			
		||||
/* cause a GC crash if they are accidentally traced.                    */
 | 
			
		||||
GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL GC_generic_malloc(
 | 
			
		||||
                                                            size_t /* lb */,
 | 
			
		||||
                                                            int /* knd */);
 | 
			
		||||
 | 
			
		||||
GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
 | 
			
		||||
                                        GC_generic_malloc_ignore_off_page(
 | 
			
		||||
                                            size_t /* lb */, int /* knd */);
 | 
			
		||||
                                /* As above, but pointers to past the   */
 | 
			
		||||
                                /* first page of the resulting object   */
 | 
			
		||||
                                /* are ignored.                         */
 | 
			
		||||
 | 
			
		||||
/* Generalized version of GC_malloc_[atomic_]uncollectable.     */
 | 
			
		||||
GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
 | 
			
		||||
                                        GC_generic_malloc_uncollectable(
 | 
			
		||||
                                            size_t /* lb */, int /* knd */);
 | 
			
		||||
 | 
			
		||||
/* Same as above but primary for allocating an object of the same kind  */
 | 
			
		||||
/* as an existing one (kind obtained by GC_get_kind_and_size).          */
 | 
			
		||||
/* Not suitable for GCJ and typed-malloc kinds.                         */
 | 
			
		||||
GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
 | 
			
		||||
                                        GC_generic_or_special_malloc(
 | 
			
		||||
                                            size_t /* size */, int /* knd */);
 | 
			
		||||
GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
 | 
			
		||||
                                        GC_debug_generic_or_special_malloc(
 | 
			
		||||
                                            size_t /* size */, int /* knd */,
 | 
			
		||||
                                            GC_EXTRA_PARAMS);
 | 
			
		||||
 | 
			
		||||
#ifdef GC_DEBUG
 | 
			
		||||
# define GC_GENERIC_OR_SPECIAL_MALLOC(sz, knd) \
 | 
			
		||||
                GC_debug_generic_or_special_malloc(sz, knd, GC_EXTRAS)
 | 
			
		||||
#else
 | 
			
		||||
# define GC_GENERIC_OR_SPECIAL_MALLOC(sz, knd) \
 | 
			
		||||
                GC_generic_or_special_malloc(sz, knd)
 | 
			
		||||
#endif /* !GC_DEBUG */
 | 
			
		||||
 | 
			
		||||
/* Similar to GC_size but returns object kind.  Size is returned too    */
 | 
			
		||||
/* if psize is not NULL.                                                */
 | 
			
		||||
GC_API int GC_CALL GC_get_kind_and_size(const void *, size_t * /* psize */)
 | 
			
		||||
                                                        GC_ATTR_NONNULL(1);
 | 
			
		||||
 | 
			
		||||
typedef void (GC_CALLBACK * GC_describe_type_fn)(void * /* p */,
 | 
			
		||||
                                                 char * /* out_buf */);
 | 
			
		||||
                                /* A procedure which                    */
 | 
			
		||||
                                /* produces a human-readable            */
 | 
			
		||||
                                /* description of the "type" of object  */
 | 
			
		||||
                                /* p into the buffer out_buf of length  */
 | 
			
		||||
                                /* GC_TYPE_DESCR_LEN.  This is used by  */
 | 
			
		||||
                                /* the debug support when printing      */
 | 
			
		||||
                                /* objects.                             */
 | 
			
		||||
                                /* These functions should be as robust  */
 | 
			
		||||
                                /* as possible, though we do avoid      */
 | 
			
		||||
                                /* invoking them on objects on the      */
 | 
			
		||||
                                /* global free list.                    */
 | 
			
		||||
#define GC_TYPE_DESCR_LEN 40
 | 
			
		||||
 | 
			
		||||
GC_API void GC_CALL GC_register_describe_type_fn(int /* kind */,
 | 
			
		||||
                                                 GC_describe_type_fn);
 | 
			
		||||
                                /* Register a describe_type function    */
 | 
			
		||||
                                /* to be used when printing objects     */
 | 
			
		||||
                                /* of a particular kind.                */
 | 
			
		||||
 | 
			
		||||
/* Clear some of the inaccessible part of the stack.  Returns its       */
 | 
			
		||||
/* argument, so it can be used in a tail call position, hence clearing  */
 | 
			
		||||
/* another frame.  Argument may be NULL.                                */
 | 
			
		||||
GC_API void * GC_CALL GC_clear_stack(void *);
 | 
			
		||||
 | 
			
		||||
/* Set and get the client notifier on collections.  The client function */
 | 
			
		||||
/* is called at the start of every full GC (called with the allocation  */
 | 
			
		||||
/* lock held).  May be 0.  This is a really tricky interface to use     */
 | 
			
		||||
/* correctly.  Unless you really understand the collector internals,    */
 | 
			
		||||
/* the callback should not, directly or indirectly, make any GC_ or     */
 | 
			
		||||
/* potentially blocking calls.  In particular, it is not safe to        */
 | 
			
		||||
/* allocate memory using the garbage collector from within the callback */
 | 
			
		||||
/* function.  Both the setter and getter acquire the GC lock.           */
 | 
			
		||||
typedef void (GC_CALLBACK * GC_start_callback_proc)(void);
 | 
			
		||||
GC_API void GC_CALL GC_set_start_callback(GC_start_callback_proc);
 | 
			
		||||
GC_API GC_start_callback_proc GC_CALL GC_get_start_callback(void);
 | 
			
		||||
 | 
			
		||||
/* Slow/general mark bit manipulation.  The caller must hold the        */
 | 
			
		||||
/* allocation lock.  GC_is_marked returns 1 (TRUE) or 0.                */
 | 
			
		||||
GC_API int GC_CALL GC_is_marked(const void *) GC_ATTR_NONNULL(1);
 | 
			
		||||
GC_API void GC_CALL GC_clear_mark_bit(const void *) GC_ATTR_NONNULL(1);
 | 
			
		||||
GC_API void GC_CALL GC_set_mark_bit(const void *) GC_ATTR_NONNULL(1);
 | 
			
		||||
 | 
			
		||||
/* Push everything in the given range onto the mark stack.              */
 | 
			
		||||
/* (GC_push_conditional pushes either all or only dirty pages depending */
 | 
			
		||||
/* on the third argument.)  GC_push_all_eager also ensures that stack   */
 | 
			
		||||
/* is scanned immediately, not just scheduled for scanning.             */
 | 
			
		||||
GC_API void GC_CALL GC_push_all(void * /* bottom */, void * /* top */);
 | 
			
		||||
GC_API void GC_CALL GC_push_all_eager(void * /* bottom */, void * /* top */);
 | 
			
		||||
GC_API void GC_CALL GC_push_conditional(void * /* bottom */, void * /* top */,
 | 
			
		||||
                                        int /* bool all */);
 | 
			
		||||
GC_API void GC_CALL GC_push_finalizer_structures(void);
 | 
			
		||||
 | 
			
		||||
/* Set and get the client push-other-roots procedure.  A client         */
 | 
			
		||||
/* supplied procedure should also call the original procedure.          */
 | 
			
		||||
/* Note that both the setter and getter require some external           */
 | 
			
		||||
/* synchronization to avoid data race.                                  */
 | 
			
		||||
typedef void (GC_CALLBACK * GC_push_other_roots_proc)(void);
 | 
			
		||||
GC_API void GC_CALL GC_set_push_other_roots(GC_push_other_roots_proc);
 | 
			
		||||
GC_API GC_push_other_roots_proc GC_CALL GC_get_push_other_roots(void);
 | 
			
		||||
 | 
			
		||||
/* Walk the GC heap visiting all reachable objects.  Assume the caller  */
 | 
			
		||||
/* holds the allocation lock.  Object base pointer, object size and     */
 | 
			
		||||
/* client custom data are passed to the callback (holding the lock).    */
 | 
			
		||||
typedef void (GC_CALLBACK *GC_reachable_object_proc)(void * /* obj */,
 | 
			
		||||
                                                size_t /* bytes */,
 | 
			
		||||
                                                void * /* client_data */);
 | 
			
		||||
GC_API void GC_CALL GC_enumerate_reachable_objects_inner(
 | 
			
		||||
                                GC_reachable_object_proc,
 | 
			
		||||
                                void * /* client_data */) GC_ATTR_NONNULL(1);
 | 
			
		||||
 | 
			
		||||
GC_API int GC_CALL GC_is_tmp_root(void *);
 | 
			
		||||
 | 
			
		||||
GC_API void GC_CALL GC_print_trace(GC_word /* gc_no */);
 | 
			
		||||
GC_API void GC_CALL GC_print_trace_inner(GC_word /* gc_no */);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
  } /* extern "C" */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* GC_MARK_H */
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,124 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 1994 by Xerox Corporation.  All rights reserved.
 | 
			
		||||
 * Copyright (c) 1996 by Silicon Graphics.  All rights reserved.
 | 
			
		||||
 * Copyright (c) 1998 by Fergus Henderson.  All rights reserved.
 | 
			
		||||
 * Copyright (c) 2000-2010 by Hewlett-Packard Development Company.
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Our pthread support normally needs to intercept a number of thread   */
 | 
			
		||||
/* calls.  We arrange to do that here, if appropriate.                  */
 | 
			
		||||
 | 
			
		||||
#ifndef GC_PTHREAD_REDIRECTS_H
 | 
			
		||||
#define GC_PTHREAD_REDIRECTS_H
 | 
			
		||||
 | 
			
		||||
/* Included from gc.h only.  Included only if GC_PTHREADS.              */
 | 
			
		||||
#if defined(GC_H) && defined(GC_PTHREADS)
 | 
			
		||||
 | 
			
		||||
/* We need to intercept calls to many of the threads primitives, so     */
 | 
			
		||||
/* that we can locate thread stacks and stop the world.                 */
 | 
			
		||||
/* Note also that the collector cannot always see thread specific data. */
 | 
			
		||||
/* Thread specific data should generally consist of pointers to         */
 | 
			
		||||
/* uncollectible objects (allocated with GC_malloc_uncollectable,       */
 | 
			
		||||
/* not the system malloc), which are deallocated using the destructor   */
 | 
			
		||||
/* facility in thr_keycreate.  Alternatively, keep a redundant pointer  */
 | 
			
		||||
/* to thread specific data on the thread stack.                         */
 | 
			
		||||
 | 
			
		||||
#ifndef GC_PTHREAD_REDIRECTS_ONLY
 | 
			
		||||
 | 
			
		||||
# include <pthread.h>
 | 
			
		||||
# ifndef GC_NO_DLOPEN
 | 
			
		||||
#   include <dlfcn.h>
 | 
			
		||||
# endif
 | 
			
		||||
# ifndef GC_NO_PTHREAD_SIGMASK
 | 
			
		||||
#   include <signal.h>  /* needed anyway for proper redirection */
 | 
			
		||||
# endif
 | 
			
		||||
 | 
			
		||||
# ifdef __cplusplus
 | 
			
		||||
    extern "C" {
 | 
			
		||||
# endif
 | 
			
		||||
 | 
			
		||||
# ifndef GC_SUSPEND_THREAD_ID
 | 
			
		||||
#   define GC_SUSPEND_THREAD_ID pthread_t
 | 
			
		||||
# endif
 | 
			
		||||
 | 
			
		||||
# ifndef GC_NO_DLOPEN
 | 
			
		||||
    GC_API void *GC_dlopen(const char * /* path */, int /* mode */);
 | 
			
		||||
# endif /* !GC_NO_DLOPEN */
 | 
			
		||||
 | 
			
		||||
# ifndef GC_NO_PTHREAD_SIGMASK
 | 
			
		||||
#   if defined(GC_PTHREAD_SIGMASK_NEEDED) \
 | 
			
		||||
        || defined(_BSD_SOURCE) || defined(_GNU_SOURCE) \
 | 
			
		||||
        || (_POSIX_C_SOURCE >= 199506L) || (_XOPEN_SOURCE >= 500)
 | 
			
		||||
      GC_API int GC_pthread_sigmask(int /* how */, const sigset_t *,
 | 
			
		||||
                                    sigset_t * /* oset */);
 | 
			
		||||
#   endif
 | 
			
		||||
# endif /* !GC_NO_PTHREAD_SIGMASK */
 | 
			
		||||
 | 
			
		||||
# ifndef GC_PTHREAD_CREATE_CONST
 | 
			
		||||
    /* This is used for pthread_create() only.    */
 | 
			
		||||
#   define GC_PTHREAD_CREATE_CONST const
 | 
			
		||||
# endif
 | 
			
		||||
 | 
			
		||||
  GC_API int GC_pthread_create(pthread_t *,
 | 
			
		||||
                               GC_PTHREAD_CREATE_CONST pthread_attr_t *,
 | 
			
		||||
                               void *(*)(void *), void * /* arg */);
 | 
			
		||||
  GC_API int GC_pthread_join(pthread_t, void ** /* retval */);
 | 
			
		||||
  GC_API int GC_pthread_detach(pthread_t);
 | 
			
		||||
 | 
			
		||||
# ifndef GC_NO_PTHREAD_CANCEL
 | 
			
		||||
    GC_API int GC_pthread_cancel(pthread_t);
 | 
			
		||||
# endif
 | 
			
		||||
 | 
			
		||||
# if defined(GC_HAVE_PTHREAD_EXIT) && !defined(GC_PTHREAD_EXIT_DECLARED)
 | 
			
		||||
#   define GC_PTHREAD_EXIT_DECLARED
 | 
			
		||||
    GC_API void GC_pthread_exit(void *) GC_PTHREAD_EXIT_ATTRIBUTE;
 | 
			
		||||
# endif
 | 
			
		||||
 | 
			
		||||
# ifdef __cplusplus
 | 
			
		||||
    } /* extern "C" */
 | 
			
		||||
# endif
 | 
			
		||||
 | 
			
		||||
#endif /* !GC_PTHREAD_REDIRECTS_ONLY */
 | 
			
		||||
 | 
			
		||||
#if !defined(GC_NO_THREAD_REDIRECTS) && !defined(GC_USE_LD_WRAP)
 | 
			
		||||
  /* Unless the compiler supports #pragma extern_prefix, the Tru64      */
 | 
			
		||||
  /* UNIX <pthread.h> redefines some POSIX thread functions to use      */
 | 
			
		||||
  /* mangled names.  Anyway, it's safe to undef them before redefining. */
 | 
			
		||||
# undef pthread_create
 | 
			
		||||
# undef pthread_join
 | 
			
		||||
# undef pthread_detach
 | 
			
		||||
# define pthread_create GC_pthread_create
 | 
			
		||||
# define pthread_join GC_pthread_join
 | 
			
		||||
# define pthread_detach GC_pthread_detach
 | 
			
		||||
 | 
			
		||||
# ifndef GC_NO_PTHREAD_SIGMASK
 | 
			
		||||
#   undef pthread_sigmask
 | 
			
		||||
#   define pthread_sigmask GC_pthread_sigmask
 | 
			
		||||
# endif
 | 
			
		||||
# ifndef GC_NO_DLOPEN
 | 
			
		||||
#   undef dlopen
 | 
			
		||||
#   define dlopen GC_dlopen
 | 
			
		||||
# endif
 | 
			
		||||
# ifndef GC_NO_PTHREAD_CANCEL
 | 
			
		||||
#   undef pthread_cancel
 | 
			
		||||
#   define pthread_cancel GC_pthread_cancel
 | 
			
		||||
# endif
 | 
			
		||||
# ifdef GC_HAVE_PTHREAD_EXIT
 | 
			
		||||
#   undef pthread_exit
 | 
			
		||||
#   define pthread_exit GC_pthread_exit
 | 
			
		||||
# endif
 | 
			
		||||
#endif /* !GC_NO_THREAD_REDIRECTS */
 | 
			
		||||
 | 
			
		||||
#endif /* GC_PTHREADS */
 | 
			
		||||
 | 
			
		||||
#endif /* GC_PTHREAD_REDIRECTS_H */
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,90 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 1999-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_TINY_FL_H
 | 
			
		||||
#define GC_TINY_FL_H
 | 
			
		||||
/*
 | 
			
		||||
 * Constants and data structures for "tiny" free lists.
 | 
			
		||||
 * These are used for thread-local allocation or in-lined allocators.
 | 
			
		||||
 * Each global free list also essentially starts with one of these.
 | 
			
		||||
 * However, global free lists are known to the GC.  "Tiny" free lists
 | 
			
		||||
 * are basically private to the client.  Their contents are viewed as
 | 
			
		||||
 * "in use" and marked accordingly by the core of the GC.
 | 
			
		||||
 *
 | 
			
		||||
 * Note that inlined code might know about the layout of these and the constants
 | 
			
		||||
 * involved.  Thus any change here may invalidate clients, and such changes should
 | 
			
		||||
 * be avoided.  Hence we keep this as simple as possible.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * We always set GC_GRANULE_BYTES to twice the length of a pointer.
 | 
			
		||||
 * This means that all allocation requests are rounded up to the next
 | 
			
		||||
 * multiple of 16 on 64-bit architectures or 8 on 32-bit architectures.
 | 
			
		||||
 * This appears to be a reasonable compromise between fragmentation overhead
 | 
			
		||||
 * and space usage for mark bits (usually mark bytes).
 | 
			
		||||
 * On many 64-bit architectures some memory references require 16-byte
 | 
			
		||||
 * alignment, making this necessary anyway.
 | 
			
		||||
 * For a few 32-bit architecture (e.g. x86), we may also need 16-byte alignment
 | 
			
		||||
 * for certain memory references.  But currently that does not seem to be the
 | 
			
		||||
 * default for all conventional malloc implementations, so we ignore that
 | 
			
		||||
 * problem.
 | 
			
		||||
 * It would always be safe, and often useful, to be able to allocate very
 | 
			
		||||
 * small objects with smaller alignment.  But that would cost us mark bit
 | 
			
		||||
 * space, so we no longer do so.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef GC_GRANULE_BYTES
 | 
			
		||||
  /* GC_GRANULE_BYTES should not be overridden in any instances of the GC */
 | 
			
		||||
  /* library that may be shared between applications, since it affects    */
 | 
			
		||||
  /* the binary interface to the library.                                 */
 | 
			
		||||
# if defined(__LP64__) || defined (_LP64) || defined(_WIN64) \
 | 
			
		||||
        || defined(__s390x__) \
 | 
			
		||||
        || (defined(__x86_64__) && !defined(__ILP32__)) \
 | 
			
		||||
        || defined(__alpha__) || defined(__powerpc64__) \
 | 
			
		||||
        || defined(__arch64__)
 | 
			
		||||
#  define GC_GRANULE_BYTES 16
 | 
			
		||||
#  define GC_GRANULE_WORDS 2
 | 
			
		||||
# else
 | 
			
		||||
#  define GC_GRANULE_BYTES 8
 | 
			
		||||
#  define GC_GRANULE_WORDS 2
 | 
			
		||||
# endif
 | 
			
		||||
#endif /* !GC_GRANULE_BYTES */
 | 
			
		||||
 | 
			
		||||
#if GC_GRANULE_WORDS == 2
 | 
			
		||||
#  define GC_WORDS_TO_GRANULES(n) ((n)>>1)
 | 
			
		||||
#else
 | 
			
		||||
#  define GC_WORDS_TO_GRANULES(n) ((n)*sizeof(void *)/GC_GRANULE_BYTES)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* A "tiny" free list header contains TINY_FREELISTS pointers to        */
 | 
			
		||||
/* singly linked lists of objects of different sizes, the ith one       */
 | 
			
		||||
/* containing objects i granules in size.  Note that there is a list    */
 | 
			
		||||
/* of size zero objects.                                                */
 | 
			
		||||
#ifndef GC_TINY_FREELISTS
 | 
			
		||||
# if GC_GRANULE_BYTES == 16
 | 
			
		||||
#   define GC_TINY_FREELISTS 25
 | 
			
		||||
# else
 | 
			
		||||
#   define GC_TINY_FREELISTS 33 /* Up to and including 256 bytes */
 | 
			
		||||
# endif
 | 
			
		||||
#endif /* !GC_TINY_FREELISTS */
 | 
			
		||||
 | 
			
		||||
/* The ith free list corresponds to size i*GC_GRANULE_BYTES     */
 | 
			
		||||
/* Internally to the collector, the index can be computed with  */
 | 
			
		||||
/* ROUNDED_UP_GRANULES.  Externally, we don't know whether      */
 | 
			
		||||
/* DONT_ADD_BYTE_AT_END is set, but the client should know.     */
 | 
			
		||||
 | 
			
		||||
/* Convert a free list index to the actual size of objects      */
 | 
			
		||||
/* on that list, including extra space we added.  Not an        */
 | 
			
		||||
/* inverse of the above.                                        */
 | 
			
		||||
#define GC_RAW_BYTES_FROM_INDEX(i) ((i) * GC_GRANULE_BYTES)
 | 
			
		||||
 | 
			
		||||
#endif /* GC_TINY_FL_H */
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,122 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
 | 
			
		||||
 * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
 | 
			
		||||
 * Copyright 1996 Silicon Graphics.  All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Some simple primitives for allocation with explicit type information.
 | 
			
		||||
 * Facilities for dynamic type inference may be added later.
 | 
			
		||||
 * Should be used only for extremely performance critical applications,
 | 
			
		||||
 * or if conservative collector leakage is otherwise a problem (unlikely).
 | 
			
		||||
 * Note that this is implemented completely separately from the rest
 | 
			
		||||
 * of the collector, and is not linked in unless referenced.
 | 
			
		||||
 * This does not currently support GC_DEBUG in any interesting way.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef GC_TYPED_H
 | 
			
		||||
#define GC_TYPED_H
 | 
			
		||||
 | 
			
		||||
#ifndef GC_H
 | 
			
		||||
# include "gc.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
  extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
typedef GC_word * GC_bitmap;
 | 
			
		||||
        /* The least significant bit of the first word is one if        */
 | 
			
		||||
        /* the first word in the object may be a pointer.               */
 | 
			
		||||
 | 
			
		||||
#define GC_WORDSZ (8 * sizeof(GC_word))
 | 
			
		||||
#define GC_get_bit(bm, index) \
 | 
			
		||||
            (((bm)[(index) / GC_WORDSZ] >> ((index) % GC_WORDSZ)) & 1)
 | 
			
		||||
#define GC_set_bit(bm, index) \
 | 
			
		||||
            ((bm)[(index) / GC_WORDSZ] |= (GC_word)1 << ((index) % GC_WORDSZ))
 | 
			
		||||
#define GC_WORD_OFFSET(t, f) (offsetof(t,f) / sizeof(GC_word))
 | 
			
		||||
#define GC_WORD_LEN(t) (sizeof(t) / sizeof(GC_word))
 | 
			
		||||
#define GC_BITMAP_SIZE(t) ((GC_WORD_LEN(t) + GC_WORDSZ - 1) / GC_WORDSZ)
 | 
			
		||||
 | 
			
		||||
typedef GC_word GC_descr;
 | 
			
		||||
 | 
			
		||||
GC_API GC_descr GC_CALL GC_make_descriptor(const GC_word * /* GC_bitmap bm */,
 | 
			
		||||
                                size_t /* len (number_of_bits_in_bitmap) */);
 | 
			
		||||
                /* Return a type descriptor for the object whose layout */
 | 
			
		||||
                /* is described by the argument.                        */
 | 
			
		||||
                /* The least significant bit of the first word is one   */
 | 
			
		||||
                /* if the first word in the object may be a pointer.    */
 | 
			
		||||
                /* The second argument specifies the number of          */
 | 
			
		||||
                /* meaningful bits in the bitmap.  The actual object    */
 | 
			
		||||
                /* may be larger (but not smaller).  Any additional     */
 | 
			
		||||
                /* words in the object are assumed not to contain       */
 | 
			
		||||
                /* pointers.                                            */
 | 
			
		||||
                /* Returns a conservative approximation in the          */
 | 
			
		||||
                /* (unlikely) case of insufficient memory to build      */
 | 
			
		||||
                /* the descriptor.  Calls to GC_make_descriptor         */
 | 
			
		||||
                /* may consume some amount of a finite resource.  This  */
 | 
			
		||||
                /* is intended to be called once per type, not once     */
 | 
			
		||||
                /* per allocation.                                      */
 | 
			
		||||
 | 
			
		||||
/* It is possible to generate a descriptor for a C type T with  */
 | 
			
		||||
/* word aligned pointer fields f1, f2, ... as follows:                  */
 | 
			
		||||
/*                                                                      */
 | 
			
		||||
/* GC_descr T_descr;                                                    */
 | 
			
		||||
/* GC_word T_bitmap[GC_BITMAP_SIZE(T)] = {0};                           */
 | 
			
		||||
/* GC_set_bit(T_bitmap, GC_WORD_OFFSET(T,f1));                          */
 | 
			
		||||
/* GC_set_bit(T_bitmap, GC_WORD_OFFSET(T,f2));                          */
 | 
			
		||||
/* ...                                                                  */
 | 
			
		||||
/* T_descr = GC_make_descriptor(T_bitmap, GC_WORD_LEN(T));              */
 | 
			
		||||
 | 
			
		||||
GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
 | 
			
		||||
        GC_malloc_explicitly_typed(size_t /* size_in_bytes */,
 | 
			
		||||
                                   GC_descr /* d */);
 | 
			
		||||
                /* Allocate an object whose layout is described by d.   */
 | 
			
		||||
                /* The size may NOT be less than the number of          */
 | 
			
		||||
                /* meaningful bits in the bitmap of d multiplied by     */
 | 
			
		||||
                /* sizeof GC_word.  The returned object is cleared.     */
 | 
			
		||||
                /* The returned object may NOT be passed to GC_realloc. */
 | 
			
		||||
 | 
			
		||||
GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
 | 
			
		||||
        GC_malloc_explicitly_typed_ignore_off_page(size_t /* size_in_bytes */,
 | 
			
		||||
                                                   GC_descr /* d */);
 | 
			
		||||
 | 
			
		||||
GC_API GC_ATTR_MALLOC GC_ATTR_CALLOC_SIZE(1, 2) void * GC_CALL
 | 
			
		||||
        GC_calloc_explicitly_typed(size_t /* nelements */,
 | 
			
		||||
                                   size_t /* element_size_in_bytes */,
 | 
			
		||||
                                   GC_descr /* d */);
 | 
			
		||||
        /* Allocate an array of nelements elements, each of the */
 | 
			
		||||
        /* given size, and with the given descriptor.           */
 | 
			
		||||
        /* The element size must be a multiple of the byte      */
 | 
			
		||||
        /* alignment required for pointers.  E.g. on a 32-bit   */
 | 
			
		||||
        /* machine with 16-bit aligned pointers, size_in_bytes  */
 | 
			
		||||
        /* must be a multiple of 2.  The element size may NOT   */
 | 
			
		||||
        /* be less than the number of meaningful bits in the    */
 | 
			
		||||
        /* bitmap of d multiplied by sizeof GC_word.            */
 | 
			
		||||
        /* Returned object is cleared.                          */
 | 
			
		||||
 | 
			
		||||
#ifdef GC_DEBUG
 | 
			
		||||
# define GC_MALLOC_EXPLICITLY_TYPED(bytes, d) ((void)(d), GC_MALLOC(bytes))
 | 
			
		||||
# define GC_CALLOC_EXPLICITLY_TYPED(n, bytes, d) \
 | 
			
		||||
                        ((void)(d), GC_MALLOC((n) * (bytes)))
 | 
			
		||||
#else
 | 
			
		||||
# define GC_MALLOC_EXPLICITLY_TYPED(bytes, d) \
 | 
			
		||||
                        GC_malloc_explicitly_typed(bytes, d)
 | 
			
		||||
# define GC_CALLOC_EXPLICITLY_TYPED(n, bytes, d) \
 | 
			
		||||
                        GC_calloc_explicitly_typed(n, bytes, d)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
  } /* extern "C" */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* GC_TYPED_H */
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,47 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 1994 by Xerox Corporation.  All rights reserved.
 | 
			
		||||
 * Copyright (c) 1996 by Silicon Graphics.  All rights reserved.
 | 
			
		||||
 * Copyright (c) 1998 by Fergus Henderson.  All rights reserved.
 | 
			
		||||
 * Copyright (c) 2000-2009 by Hewlett-Packard Development Company.
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* This should never be included directly; it is included only from gc.h. */
 | 
			
		||||
#if defined(GC_H)
 | 
			
		||||
 | 
			
		||||
/* The policy regarding version numbers: development code has odd       */
 | 
			
		||||
/* "minor" number (and "micro" part is 0); when development is finished */
 | 
			
		||||
/* and a release is prepared, "minor" number is incremented (keeping    */
 | 
			
		||||
/* "micro" number still zero), whenever a defect is fixed a new release */
 | 
			
		||||
/* is prepared incrementing "micro" part to odd value (the most stable  */
 | 
			
		||||
/* release has the biggest "micro" number).                             */
 | 
			
		||||
 | 
			
		||||
/* The version here should match that in configure/configure.ac */
 | 
			
		||||
/* Eventually this one may become unnecessary.  For now we need */
 | 
			
		||||
/* it to keep the old-style build process working.              */
 | 
			
		||||
#define GC_TMP_VERSION_MAJOR 8
 | 
			
		||||
#define GC_TMP_VERSION_MINOR 2
 | 
			
		||||
#define GC_TMP_VERSION_MICRO 0 /* 8.2.0 */
 | 
			
		||||
 | 
			
		||||
#ifdef GC_VERSION_MAJOR
 | 
			
		||||
# if GC_TMP_VERSION_MAJOR != GC_VERSION_MAJOR \
 | 
			
		||||
     || GC_TMP_VERSION_MINOR != GC_VERSION_MINOR \
 | 
			
		||||
     || GC_TMP_VERSION_MICRO != GC_VERSION_MICRO
 | 
			
		||||
#   error Inconsistent version info.  Check README.md, include/gc_version.h and configure.ac.
 | 
			
		||||
# endif
 | 
			
		||||
#else
 | 
			
		||||
# define GC_VERSION_MAJOR GC_TMP_VERSION_MAJOR
 | 
			
		||||
# define GC_VERSION_MINOR GC_TMP_VERSION_MINOR
 | 
			
		||||
# define GC_VERSION_MICRO GC_TMP_VERSION_MICRO
 | 
			
		||||
#endif /* !GC_VERSION_MAJOR */
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,68 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2000-2011 by Hewlett-Packard Development Company.
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * 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_LEAK_DETECTOR_H
 | 
			
		||||
#define GC_LEAK_DETECTOR_H
 | 
			
		||||
 | 
			
		||||
/* Include leak_detector.h (e.g., via GCC --include directive)  */
 | 
			
		||||
/* to turn BoehmGC into a Leak Detector.                        */
 | 
			
		||||
 | 
			
		||||
#ifndef GC_DEBUG
 | 
			
		||||
# define GC_DEBUG
 | 
			
		||||
#endif
 | 
			
		||||
#include "gc.h"
 | 
			
		||||
 | 
			
		||||
#ifndef GC_DONT_INCLUDE_STDLIB
 | 
			
		||||
  /* We ensure stdlib.h and string.h are included before        */
 | 
			
		||||
  /* redirecting malloc() and the accompanying functions.       */
 | 
			
		||||
# include <stdlib.h>
 | 
			
		||||
# include <string.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#undef malloc
 | 
			
		||||
#define malloc(n) GC_MALLOC(n)
 | 
			
		||||
#undef calloc
 | 
			
		||||
#define calloc(m,n) GC_MALLOC((m)*(n))
 | 
			
		||||
#undef free
 | 
			
		||||
#define free(p) GC_FREE(p)
 | 
			
		||||
#undef realloc
 | 
			
		||||
#define realloc(p,n) GC_REALLOC(p,n)
 | 
			
		||||
 | 
			
		||||
#undef strdup
 | 
			
		||||
#define strdup(s) GC_STRDUP(s)
 | 
			
		||||
#undef strndup
 | 
			
		||||
#define strndup(s,n) GC_STRNDUP(s,n)
 | 
			
		||||
 | 
			
		||||
#ifdef GC_REQUIRE_WCSDUP
 | 
			
		||||
  /* The collector should be built with GC_REQUIRE_WCSDUP       */
 | 
			
		||||
  /* defined as well to redirect wcsdup().                      */
 | 
			
		||||
# include <wchar.h>
 | 
			
		||||
# undef wcsdup
 | 
			
		||||
# define wcsdup(s) GC_WCSDUP(s)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#undef memalign
 | 
			
		||||
#define memalign(a,n) GC_memalign(a,n)
 | 
			
		||||
#undef posix_memalign
 | 
			
		||||
#define posix_memalign(p,a,n) GC_posix_memalign(p,a,n)
 | 
			
		||||
 | 
			
		||||
#ifndef CHECK_LEAKS
 | 
			
		||||
# define CHECK_LEAKS() GC_gcollect()
 | 
			
		||||
  /* Note 1: CHECK_LEAKS does not have GC prefix (preserved for */
 | 
			
		||||
  /* backward compatibility).                                   */
 | 
			
		||||
  /* Note 2: GC_gcollect() is also called automatically in the  */
 | 
			
		||||
  /* leak-finding mode at program exit.                         */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* GC_LEAK_DETECTOR_H */
 | 
			
		||||
| 
						 | 
				
			
			@ -1,65 +1,73 @@
 | 
			
		|||
module builtin
 | 
			
		||||
 | 
			
		||||
$if freebsd {
 | 
			
		||||
	// Tested on FreeBSD 13.0-RELEASE-p3, with clang, gcc and tcc:
 | 
			
		||||
	#flag -DBUS_PAGE_FAULT=T_PAGEFLT
 | 
			
		||||
	$if !tinyc {
 | 
			
		||||
		#flag -DGC_THREADS=1
 | 
			
		||||
		#flag -DGC_BUILTIN_ATOMIC=1
 | 
			
		||||
		#flag @VEXEROOT/thirdparty/libgc/gc.o
 | 
			
		||||
		#flag -lpthread
 | 
			
		||||
	}
 | 
			
		||||
} $else {
 | 
			
		||||
	#flag -DGC_THREADS=1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
$if static_boehm ? {
 | 
			
		||||
	$if macos {
 | 
			
		||||
		#flag -I$first_existing("/opt/homebrew/include",     "/usr/local/include")
 | 
			
		||||
		#flag   $first_existing("/opt/homebrew/lib/libgc.a", "/usr/local/lib/libgc.a")
 | 
			
		||||
	} $else $if linux {
 | 
			
		||||
		#flag -l:libgc.a
 | 
			
		||||
	} $else $if openbsd {
 | 
			
		||||
		#flag -I/usr/local/include
 | 
			
		||||
		#flag /usr/local/lib/libgc.a
 | 
			
		||||
		#flag -lpthread
 | 
			
		||||
	} $else $if windows {
 | 
			
		||||
		#flag -DGC_NOT_DLL=1
 | 
			
		||||
$if dynamic_boehm ? {
 | 
			
		||||
	$if windows {
 | 
			
		||||
		$if tinyc {
 | 
			
		||||
			#flag -I@VEXEROOT/thirdparty/libgc/include
 | 
			
		||||
			#flag -L@VEXEROOT/thirdparty/libgc
 | 
			
		||||
			#flag -L@VEXEROOT/thirdparty/tcc/lib
 | 
			
		||||
			#flag -lgc
 | 
			
		||||
		} $else $if msvc {
 | 
			
		||||
			#flag -DGC_BUILTIN_ATOMIC=1
 | 
			
		||||
			#flag -I@VEXEROOT/thirdparty/libgc/include
 | 
			
		||||
		} $else {
 | 
			
		||||
			#flag -DGC_WIN32_THREADS=1
 | 
			
		||||
			#flag -DGC_BUILTIN_ATOMIC=1
 | 
			
		||||
			#flag -I@VEXEROOT/thirdparty/libgc
 | 
			
		||||
			#flag @VEXEROOT/thirdparty/libgc/gc.o
 | 
			
		||||
		}
 | 
			
		||||
	} $else {
 | 
			
		||||
		#flag -lgc
 | 
			
		||||
		$if $pkgconfig('bdw-gc') {
 | 
			
		||||
			#pkgconfig bdw-gc
 | 
			
		||||
		} $else {
 | 
			
		||||
			$if openbsd || freebsd {
 | 
			
		||||
				#flag -I/usr/local/include
 | 
			
		||||
				#flag -L/usr/local/lib
 | 
			
		||||
			}
 | 
			
		||||
			#flag -lgc
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
} $else {
 | 
			
		||||
	$if macos {
 | 
			
		||||
		#pkgconfig bdw-gc
 | 
			
		||||
	} $else $if openbsd || freebsd {
 | 
			
		||||
	#flag -DGC_THREADS=1
 | 
			
		||||
	#flag -DGC_BUILTIN_ATOMIC=1
 | 
			
		||||
	$if macos || linux {
 | 
			
		||||
		#flag -DGC_PTHREADS=1
 | 
			
		||||
		#flag -I@VEXEROOT/thirdparty/libgc/include
 | 
			
		||||
		#flag -lpthread -ldl
 | 
			
		||||
		$if (prod && !tinyc && !debug) || !(amd64 || arm64 || i386 || arm32) {
 | 
			
		||||
			// TODO: replace the architecture check with a `!$exists("@VEXEROOT/thirdparty/tcc/lib/libgc.a")` comptime call
 | 
			
		||||
			#flag @VEXEROOT/thirdparty/libgc/gc.o
 | 
			
		||||
		} $else {
 | 
			
		||||
			#flag @VEXEROOT/thirdparty/tcc/lib/libgc.a
 | 
			
		||||
		}
 | 
			
		||||
	} $else $if freebsd {
 | 
			
		||||
		// Tested on FreeBSD 13.0-RELEASE-p3, with clang, gcc and tcc:
 | 
			
		||||
		#flag -DBUS_PAGE_FAULT=T_PAGEFLT
 | 
			
		||||
		#flag -DGC_PTHREADS=1
 | 
			
		||||
		$if !tinyc {
 | 
			
		||||
			#flag @VEXEROOT/thirdparty/libgc/gc.o
 | 
			
		||||
		} $else {
 | 
			
		||||
			#flag -I/usr/local/include
 | 
			
		||||
			#flag $first_existing("/usr/local/lib/libgc.a", "/usr/lib/libgc.a")
 | 
			
		||||
		}
 | 
			
		||||
		#flag -lpthread
 | 
			
		||||
	} $else $if openbsd {
 | 
			
		||||
		#flag -I/usr/local/include
 | 
			
		||||
		#flag -L/usr/local/lib
 | 
			
		||||
	}
 | 
			
		||||
	$if windows {
 | 
			
		||||
		#flag $first_existing("/usr/local/lib/libgc.a", "/usr/lib/libgc.a")
 | 
			
		||||
		#flag -lpthread
 | 
			
		||||
	} $else $if windows {
 | 
			
		||||
		$if tinyc {
 | 
			
		||||
			#flag -I@VEXEROOT/thirdparty/libgc/include
 | 
			
		||||
			#flag -L@VEXEROOT/thirdparty/libgc
 | 
			
		||||
			#flag -L@VEXEROOT/thirdparty/tcc/lib
 | 
			
		||||
			#flag -lgc
 | 
			
		||||
		} $else $if msvc {
 | 
			
		||||
		} $else {
 | 
			
		||||
			#flag -DGC_NOT_DLL=1
 | 
			
		||||
			#flag -DGC_WIN32_THREADS=1
 | 
			
		||||
			#flag -DGC_BUILTIN_ATOMIC=1
 | 
			
		||||
			#flag -I@VEXEROOT/thirdparty/libgc/include
 | 
			
		||||
		} $else {
 | 
			
		||||
			#flag -DGC_BUILTIN_ATOMIC=1
 | 
			
		||||
			#flag -I@VEXEROOT/thirdparty/libgc
 | 
			
		||||
			#flag @VEXEROOT/thirdparty/libgc/gc.o
 | 
			
		||||
		}
 | 
			
		||||
	} $else $if $pkgconfig('bdw-gc') {
 | 
			
		||||
		#pkgconfig bdw-gc
 | 
			
		||||
	} $else {
 | 
			
		||||
		#flag -lgc
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -85,7 +93,7 @@ fn C.GC_REALLOC(ptr voidptr, n usize) voidptr
 | 
			
		|||
 | 
			
		||||
fn C.GC_FREE(ptr voidptr)
 | 
			
		||||
 | 
			
		||||
// explicitely perform garbage collection now! Garbage collections
 | 
			
		||||
// explicitly perform garbage collection now! Garbage collections
 | 
			
		||||
// are done automatically when needed, so this function is hardly needed
 | 
			
		||||
fn C.GC_gcollect()
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -117,7 +117,7 @@ pub fn (cflags []CFlag) defines_others_libs() ([]string, []string, []string) {
 | 
			
		|||
	mut others := []string{}
 | 
			
		||||
	mut libs := []string{}
 | 
			
		||||
	for copt in copts_without_obj_files {
 | 
			
		||||
		if copt.starts_with('-l') {
 | 
			
		||||
		if copt.starts_with('-l') || copt.ends_with('.a') {
 | 
			
		||||
			libs << copt
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue