Initial project import

This commit is contained in:
Agila Forge Importer committed 2026-07-13 15:20:32 +00:00
commit 23f2d29e32
11957 files changed
+1754577

No files matched your search

+50
View File
@@ -0,0 +1,50 @@
The libgc source is distributed here as an amalgamation (https://sqlite.org/amalgamation.html).
This means that, rather than mirroring the entire bdwgc repo here, the amalgamate tool
was used to bundle all C files and local includes together into a single C file, which is
much easier to handle. This helps keep the V source distribution small, can reduce compile
times by 3%-15%, and can help C compilers generate more optimized code.
For generating the libgc amalgamation, the following commands were used:
git clone https://github.com/ivmai/bdwgc.git
cd bdwgc
./autogen.sh
./configure --enable-threads=pthreads \
--enable-static \
--enable-shared=no \
--enable-thread-local-alloc=no \
--enable-parallel-mark \
--enable-single-obj-compilation \
--enable-gc-debug
../../../cmd/tools/amalgamate -o ../gc.c \
-b atomic_ops.h \
-b gc/gc.h \
-b gc/gc_backptr.h \
-b gc/gc_disclaim.h \
-b gc/gc_gcj.h \
-b gc/gc_inline.h \
-b gc/gc_mark.h \
-b gc/gc_pthread_redirects.h \
-b gc/gc_tiny_fl.h \
-b gc/gc_typed.h \
-b gc/javaxfc.h \
-b il/PCR_IL.h \
-b mm/PCR_MM.h \
-b psp2-support.h \
-b stubinfo.h \
-b th/PCR_ThCtl.h \
-b vd/PCR_VD.h \
-s include \
-s include/private \
extra/gc.c
The updated header files are then copied into the include/gc directory. We can delete
include/gc/gc_cpp.h since this header is not needed by V. And, we can remove the git
repo for bdwgc.
cp include/gc/*.h ../include/gc
cd ..
rm include/gc/gc_cpp.h
rm -rf bdwgc
+45849
View File
File diff suppressed because it is too large. Load diff
+16
View File
@@ -0,0 +1,16 @@
/* This file is installed for backward compatibility. */
#include "gc/gc.h"
/* Fix for vlang/v#27179: the original version of this file cast the
* pointer argument to V's `u64` type, which makes the header illegal
* to include from standalone C (any C shim doing `#include <gc.h>`
* via V's -I@VEXEROOT/thirdparty/libgc/include path would fail with
* "unknown type: u64"). `GC_word` is the libgc-defined type that
* `GC_noop1` actually takes (gc/gc.h, typedef'd to uintptr_t on most
* platforms) — using it makes this header valid both from V code and
* from plain C shims. */
#ifndef _MSC_VER
__attribute__ ((weak)) GC_API void GC_CALL GC_noop1_ptr(volatile void *p) {
GC_noop1((GC_word)p);
}
#endif
+426
View File
@@ -0,0 +1,426 @@
/*
* 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 counterpart in platform
* `strings.h` file. 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 NUL characters when given such a cord.
*
* This interface is fairly big, largely for performance reasons.
* The most basic constants, functions and types:
*
* - `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(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(CORD format, ...)` and friends - cord's variant 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) && !defined(CORD_API)
/* Same as for `GC_API` in `gc_config_macros.h` file. */
# ifdef CORD_BUILD
# if defined(__MINGW32__) && !defined(__cplusplus) || defined(__CEGCC__)
# define CORD_API __declspec(dllexport)
# elif defined(_MSC_VER) || defined(__DMC__) || defined(__BORLANDC__) \
|| defined(__CYGWIN__) || defined(__MINGW32__) \
|| 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 /* !CORD_BUILD */
# if defined(__BORLANDC__) || defined(__CEGCC__) || defined(__CYGWIN__) \
|| defined(__DMC__) || defined(_MSC_VER)
# define CORD_API __declspec(dllimport)
# elif defined(__MINGW32__) || defined(__WATCOMC__)
# define CORD_API extern __declspec(dllimport)
# endif
# endif
#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, `NULL`.
*/
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, CORD);
/**
* 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 /* `y_len` */);
/** Compute the length of a cord. */
CORD_API size_t CORD_len(CORD);
/** Cords may be represented by functions defining the `i`-th 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, 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 zero.)
*/
CORD_API CORD CORD_substr(CORD, 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
* the argument was obtained through a large number of repeated
* substring operations 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);
/*
* The following traverse a cord by applying a function to each
* character. This is occasionally appropriate, especially where
* speed is crucial. But, since C does not 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, void * /* `client_data` */);
/**
* Function to apply to substrings of a cord. Each substring is
* a C character string, not a general cord.
*/
typedef int (*CORD_batched_iter_fn)(const char *, 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 latter 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 a nonzero value.
* In the latter case this function returns a nonzero value; otherwise
* it returns 0. The specified value of `i` must be less than `CORD_len(x)`.
*/
CORD_API int CORD_iter5(CORD, size_t /* `i` */, CORD_iter_fn /* `f1` */,
CORD_batched_iter_fn /* `f2` */,
void * /* `client_data` */);
/** A simpler variant of `CORD_iter5` that starts at 0, and without `f2`. */
CORD_API int CORD_iter(CORD, 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, size_t /* `i` */, CORD_iter_fn /* `f1` */,
void * /* `client_data` */);
/** A simpler variant of `CORD_riter4` that starts at the end. */
CORD_API int CORD_riter(CORD, 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`
* file 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"
/*
* Visible definitions from above:
* - `typedef <OPAQUE_but_fairly_big> CORD_pos[1]`;
* - `CORD CORD_pos_to_cord(CORD_pos p)` - extract the cord from
* a position;
* - `size_t CORD_pos_to_index(CORD_pos p)` - extract the current index
* from a position;
* - `char CORD_pos_fetch(CORD_pos p)` - fetch the character located at
* the given position;
* - `void CORD_set_pos(CORD_pos p, CORD x, size_t i)` - initialize the
* position to refer to the given cord and index;
* - `void CORD_next(CORD_pos p)` - advance the position to the next
* character;
* - `void CORD_prev(CORD_pos p)` - move the position to the preceding
* character;
* - `int CORD_pos_valid(CORD_pos p)` - check whether the position is
* valid, i.e. inside the cord.
*/
#ifdef __cplusplus
extern "C" {
#endif
#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. Zero value means do nothing special,
* just abort. Use of the setter and getter is preferred over the direct
* access to the global variable.
*/
typedef void (*CORD_oom_fn_t)(void);
CORD_API void CORD_set_oom_fn(CORD_oom_fn_t);
CORD_API CORD_oom_fn_t CORD_get_oom_fn(void);
#ifndef CORD_DONT_DECLARE_OOM_FN
CORD_API CORD_oom_fn_t CORD_oom_fn;
#endif
#ifdef CORD_BUILD
/* no export */ void CORD__call_oom_fn(void);
#endif
/**
* 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 by the cord library for convenience.
*/
/** Concatenate a character to the end of a cord. */
CORD_API CORD CORD_cat_char(CORD, char);
/** 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 a negative value, zero, or a positive value, depending on
* whether `x < y`, `x == y`, or `x > y`, respectively.
*/
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 `c`. Dangerous in
* conjunction with `CORD_to_char_star`. `c` could be a NUL character.
* 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 `f` 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(...))`. The latter (`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 Windows systems,
* `f` must be opened in binary mode.
*/
CORD_API CORD CORD_from_file(FILE * /* `f` */);
/**
* Equivalent to `CORD_from_file`, except that the entire file will be
* read and the file pointer will be closed immediately. The binary mode
* restriction of `CORD_from_file` does not apply.
*/
CORD_API CORD CORD_from_file_eager(FILE *);
/**
* Equivalent to `CORD_from_file`, except that the file will be read on
* demand. The binary mode restriction applies.
*/
CORD_API CORD CORD_from_file_lazy(FILE *);
/**
* 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 *);
/**
* Identical to `CORD_from_char_star`, but the result may share structure
* with the argument and is thus not modifiable.
*/
CORD_API const char *CORD_to_const_char_star(CORD);
/**
* Write a cord to a file, starting at the current position.
* No trailing NUL characters and newlines are added. Returns `EOF`
* if a write error occurs, 1 otherwise.
*/
CORD_API int CORD_put(CORD, FILE *);
/** "Not found" result for `CORD_chr()` and `CORD_rchr()`. */
#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 less than `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 less than `CORD_len(x)`.
*/
CORD_API size_t CORD_rchr(CORD /* `x` */, size_t /* `i` */, int /* `c` */);
#ifdef __cplusplus
} /* extern "C" */
#endif
#ifndef CORD_NO_IO
# include <stdarg.h>
# ifdef __cplusplus
extern "C" {
# endif
/**
* The following ones 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 variants, there is no need
* to guess the correct buffer size.
* 4. Most of the conversions are implemented through the native
* `vsprintf`. Hence they are usually no faster, and idiosyncrasies
* of the native `printf` are preserved. However, `CORD` arguments
* to `CORD_sprintf`, `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.
*
* The 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`.
*/
CORD_API int CORD_sprintf(CORD * /* `out` */, CORD /* `format` */, ...);
CORD_API int CORD_vsprintf(CORD * /* `out` */, CORD /* `format` */, va_list);
CORD_API int CORD_fprintf(FILE *, CORD /* `format` */, ...);
CORD_API int CORD_vfprintf(FILE *, CORD /* `format` */, va_list);
CORD_API int CORD_printf(CORD /* `format` */, ...);
CORD_API int CORD_vprintf(CORD /* `format` */, va_list);
# ifdef __cplusplus
} /* extern "C" */
# endif
#endif /* CORD_NO_IO */
#endif /* CORD_H */
+151
View File
@@ -0,0 +1,151 @@
/*
* 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` file. */
#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. Do not use anything defined here
* and not in `cord.h` file.
*/
/**
* The maximum depth of a balanced cord plus one. We do not let cords get
* deeper than this maximum.
*/
# define CORD_MAX_DEPTH 48
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;
/* `path_len` is `CORD_POS_INVALID` if and only if position is invalid. */
# define CORD_POS_INVALID 0x55555555
/*
* 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 zero.
*/
const char *cur_leaf;
/* Start position of `cur_leaf`. */
size_t cur_start;
/* Ending position of `cur_leaf`; zero if `cur_leaf` is invalid. */
size_t cur_end;
/*
* `path[path_len]` is the leaf corresponding to `cur_pos`;
* `path[0].pe_cord` is the cord we point to.
*/
struct CORD_pe path[CORD_MAX_DEPTH + 1];
# define CORD_FUNCTION_BUF_SZ 8
/* Space for next few chars from function node. */
char function_buf[CORD_FUNCTION_BUF_SZ];
} CORD_pos[1];
/** Extract the cord from a position. */
CORD_API CORD CORD_pos_to_cord(CORD_pos);
/** Extract the current index from a position. */
CORD_API size_t CORD_pos_to_index(CORD_pos);
/** Fetch the character located at the given position. */
CORD_API char CORD_pos_fetch(CORD_pos);
/**
* Initialize the position to refer to the given cord and `index`.
* Note that this is the most expensive function on positions.
*/
CORD_API void CORD_set_pos(CORD_pos, CORD, size_t /* `index` */);
/**
* 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);
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), 0U))
# define CORD_prev(p) \
((p)[0].cur_end != 0 && (p)[0].cur_pos > (p)[0].cur_start \
? (p)[0].cur_pos-- \
: (CORD__prev(p), 0U))
# 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. */
/** Number of characters in cache. A non-positive value means none. */
# define CORD_pos_chars_left(p) ((long)(p)[0].cur_end - (long)(p)[0].cur_pos)
/**
* Advance position by `n` characters; `n` should be positive and less
* than `CORD_pos_chars_left(p)`.
*/
# define CORD_pos_advance(p, n) \
((p)[0].cur_pos += (n) - (size_t)1, CORD_next(p))
/** Address of the current character in cache. */
# define CORD_pos_cur_char_addr(p) \
((p)[0].cur_leaf + ((p)[0].cur_pos - (p)[0].cur_start))
# ifdef __cplusplus
} /* extern "C" */
# endif
#endif
+91
View File
@@ -0,0 +1,91 @@
/*
* 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
/**
* This structure represents the concatenation of `ec_cord` with
* `ec_buf[0 .. ec_bufptr - ec_buf - 1]`.
*/
typedef struct CORD_ec_struct {
CORD ec_cord;
char *ec_bufptr;
char ec_buf[CORD_BUFSZ + 1];
} CORD_ec[1];
/** Flush the buffer part of the extended cord into extensible cord. */
CORD_API void CORD_ec_flush_buf(CORD_ec);
/** 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
* the original.
*/
CORD_API void CORD_ec_append_cord(CORD_ec, CORD);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* EC_H */
File diff suppressed because it is too large. Load diff
+480
View File
@@ -0,0 +1,480 @@
/*
* Copyright (c) 1996-1997 Silicon Graphics Computer Systems, Inc.
* Copyright (c) 2002 Hewlett-Packard Company
*
* 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 implements standard-conforming allocators that interact with
* the garbage collector. `gc_allocator<T>` allocates garbage-collectible
* objects of type `T`. `traceable_allocator<T>` allocates objects that
* are not themselves garbage-collected ones, but are scanned by the
* collector for pointers to collectible objects. `traceable_allocator<T>`
* should be used for explicitly managed STL containers that may point to
* collectible objects.
*
* This code was derived from an earlier version of the GNU C++ standard
* library, which itself was derived from the SGI STL implementation.
*
* Ignore-off-page allocator: George T. Talbot
*/
#ifndef GC_ALLOCATOR_H
#define GC_ALLOCATOR_H
#include "gc.h"
#include <new> // for placement `new` and `bad_alloc`
#ifdef GC_NAMESPACE_ALLOCATOR
namespace boehmgc
{
#endif
#if !defined(GC_NO_MEMBER_TEMPLATES) && defined(_MSC_VER) && _MSC_VER <= 1200
// MSVC++ 6.0 do not support member templates.
# define GC_NO_MEMBER_TEMPLATES
#endif
#if defined(GC_NEW_ABORTS_ON_OOM) || defined(_LIBCPP_NO_EXCEPTIONS)
# define GC_ALLOCATOR_THROW_OR_ABORT() GC_abort_on_oom()
#else
# define GC_ALLOCATOR_THROW_OR_ABORT() throw std::bad_alloc()
#endif
#if __cplusplus >= 201103L
# define GC_ALCTR_PTRDIFF_T std::ptrdiff_t
# define GC_ALCTR_SIZE_T std::size_t
#else
# define GC_ALCTR_PTRDIFF_T ptrdiff_t
# define GC_ALCTR_SIZE_T size_t
#endif
// First some helpers to allow us to dispatch on whether or not a type
// is known to be pointer-free. These are private, except that the client
// may invoke the `GC_DECLARE_PTRFREE` macro.
struct GC_true_type {
};
struct GC_false_type {
};
template <class GC_tp> struct GC_type_traits {
GC_false_type GC_is_ptr_free;
};
#define GC_DECLARE_PTRFREE(T) \
template <> struct GC_type_traits<T> { \
GC_true_type GC_is_ptr_free; \
}
GC_DECLARE_PTRFREE(char);
GC_DECLARE_PTRFREE(signed char);
GC_DECLARE_PTRFREE(unsigned char);
GC_DECLARE_PTRFREE(signed short);
GC_DECLARE_PTRFREE(unsigned short);
GC_DECLARE_PTRFREE(signed int);
GC_DECLARE_PTRFREE(unsigned int);
GC_DECLARE_PTRFREE(signed long);
GC_DECLARE_PTRFREE(unsigned long);
GC_DECLARE_PTRFREE(float);
GC_DECLARE_PTRFREE(double);
GC_DECLARE_PTRFREE(long double);
// The client may want to add others.
// In the following `GC_Tp` is `GC_true_type` if we are allocating
// a pointer-free object.
template <class GC_Tp>
inline void *
GC_selective_alloc(GC_ALCTR_SIZE_T n, GC_Tp, bool ignore_off_page)
{
void *obj = ignore_off_page ? GC_MALLOC_IGNORE_OFF_PAGE(n) : GC_MALLOC(n);
if (0 == obj)
GC_ALLOCATOR_THROW_OR_ABORT();
return obj;
}
#if !defined(__WATCOMC__)
// Note: template-id not supported in this context by Watcom compiler.
template <>
inline void *
GC_selective_alloc<GC_true_type>(GC_ALCTR_SIZE_T n, GC_true_type,
bool ignore_off_page)
{
void *obj = ignore_off_page ? GC_MALLOC_ATOMIC_IGNORE_OFF_PAGE(n)
: GC_MALLOC_ATOMIC(n);
if (0 == obj)
GC_ALLOCATOR_THROW_OR_ABORT();
return obj;
}
#endif
// Now the public `gc_allocator<T>` class.
template <class GC_Tp> class gc_allocator
{
public:
typedef GC_ALCTR_SIZE_T size_type;
typedef GC_ALCTR_PTRDIFF_T difference_type;
typedef GC_Tp *pointer;
typedef const GC_Tp *const_pointer;
typedef GC_Tp &reference;
typedef const GC_Tp &const_reference;
typedef GC_Tp value_type;
template <class GC_Tp1> struct rebind {
typedef gc_allocator<GC_Tp1> other;
};
GC_CONSTEXPR
gc_allocator() GC_NOEXCEPT
{
// Empty.
}
GC_CONSTEXPR
gc_allocator(const gc_allocator &) GC_NOEXCEPT
{
// Empty.
}
#ifndef GC_NO_MEMBER_TEMPLATES
template <class GC_Tp1>
GC_ATTR_EXPLICIT GC_CONSTEXPR
gc_allocator(const gc_allocator<GC_Tp1> &) GC_NOEXCEPT
{
}
#endif
GC_CONSTEXPR ~gc_allocator() GC_NOEXCEPT {}
GC_CONSTEXPR pointer
address(reference GC_x) const
{
return &GC_x;
}
GC_CONSTEXPR const_pointer
address(const_reference GC_x) const
{
return &GC_x;
}
// `GC_n` is permitted to be 0. The C++ standard says nothing about what
// the return value is when `GC_n` is zero.
GC_CONSTEXPR GC_Tp *
allocate(size_type GC_n, const void * = 0)
{
GC_type_traits<GC_Tp> traits;
return static_cast<GC_Tp *>(GC_selective_alloc(
GC_n * sizeof(GC_Tp), traits.GC_is_ptr_free, false));
}
GC_CONSTEXPR void
deallocate(pointer __p, size_type /* `GC_n` */) GC_NOEXCEPT
{
GC_FREE(__p);
}
GC_CONSTEXPR size_type
max_size() const GC_NOEXCEPT
{
return static_cast<GC_ALCTR_SIZE_T>(-1) / sizeof(GC_Tp);
}
GC_CONSTEXPR void
construct(pointer __p, const GC_Tp &__val)
{
new (__p) GC_Tp(__val);
}
GC_CONSTEXPR void
destroy(pointer __p)
{
__p->~GC_Tp();
}
};
template <> class gc_allocator<void>
{
public:
typedef GC_ALCTR_SIZE_T size_type;
typedef GC_ALCTR_PTRDIFF_T difference_type;
typedef void *pointer;
typedef const void *const_pointer;
typedef void value_type;
template <class GC_Tp1> struct rebind {
typedef gc_allocator<GC_Tp1> other;
};
};
template <class GC_T1, class GC_T2>
GC_CONSTEXPR inline bool
operator==(const gc_allocator<GC_T1> &,
const gc_allocator<GC_T2> &) GC_NOEXCEPT
{
return true;
}
template <class GC_T1, class GC_T2>
GC_CONSTEXPR inline bool
operator!=(const gc_allocator<GC_T1> &,
const gc_allocator<GC_T2> &) GC_NOEXCEPT
{
return false;
}
// Now the public `gc_allocator_ignore_off_page<T>` class.
template <class GC_Tp> class gc_allocator_ignore_off_page
{
public:
typedef GC_ALCTR_SIZE_T size_type;
typedef GC_ALCTR_PTRDIFF_T difference_type;
typedef GC_Tp *pointer;
typedef const GC_Tp *const_pointer;
typedef GC_Tp &reference;
typedef const GC_Tp &const_reference;
typedef GC_Tp value_type;
template <class GC_Tp1> struct rebind {
typedef gc_allocator_ignore_off_page<GC_Tp1> other;
};
GC_CONSTEXPR
gc_allocator_ignore_off_page() GC_NOEXCEPT
{
// Empty.
}
GC_CONSTEXPR
gc_allocator_ignore_off_page(const gc_allocator_ignore_off_page &)
GC_NOEXCEPT
{
// Empty.
}
#ifndef GC_NO_MEMBER_TEMPLATES
template <class GC_Tp1>
GC_ATTR_EXPLICIT GC_CONSTEXPR
gc_allocator_ignore_off_page(const gc_allocator_ignore_off_page<GC_Tp1> &)
GC_NOEXCEPT
{
}
#endif
GC_CONSTEXPR ~gc_allocator_ignore_off_page() GC_NOEXCEPT {}
GC_CONSTEXPR pointer
address(reference GC_x) const
{
return &GC_x;
}
GC_CONSTEXPR const_pointer
address(const_reference GC_x) const
{
return &GC_x;
}
// `GC_n` is permitted to be 0. The C++ standard says nothing about what
// the return value is when `GC_n` is zero.
GC_CONSTEXPR GC_Tp *
allocate(size_type GC_n, const void * = 0)
{
GC_type_traits<GC_Tp> traits;
return static_cast<GC_Tp *>(
GC_selective_alloc(GC_n * sizeof(GC_Tp), traits.GC_is_ptr_free, true));
}
GC_CONSTEXPR void
deallocate(pointer __p, size_type /* `GC_n` */) GC_NOEXCEPT
{
GC_FREE(__p);
}
GC_CONSTEXPR size_type
max_size() const GC_NOEXCEPT
{
return static_cast<GC_ALCTR_SIZE_T>(-1) / sizeof(GC_Tp);
}
GC_CONSTEXPR void
construct(pointer __p, const GC_Tp &__val)
{
new (__p) GC_Tp(__val);
}
GC_CONSTEXPR void
destroy(pointer __p)
{
__p->~GC_Tp();
}
};
template <> class gc_allocator_ignore_off_page<void>
{
public:
typedef GC_ALCTR_SIZE_T size_type;
typedef GC_ALCTR_PTRDIFF_T difference_type;
typedef void *pointer;
typedef const void *const_pointer;
typedef void value_type;
template <class GC_Tp1> struct rebind {
typedef gc_allocator_ignore_off_page<GC_Tp1> other;
};
};
template <class GC_T1, class GC_T2>
GC_CONSTEXPR inline bool
operator==(const gc_allocator_ignore_off_page<GC_T1> &,
const gc_allocator_ignore_off_page<GC_T2> &) GC_NOEXCEPT
{
return true;
}
template <class GC_T1, class GC_T2>
GC_CONSTEXPR inline bool
operator!=(const gc_allocator_ignore_off_page<GC_T1> &,
const gc_allocator_ignore_off_page<GC_T2> &) GC_NOEXCEPT
{
return false;
}
// And the public `traceable_allocator<T>` class.
// Note that we currently do not specialize the pointer-free case,
// since a pointer-free traceable container does not make that much sense,
// though it could become an issue due to abstraction boundaries.
template <class GC_Tp> class traceable_allocator
{
public:
typedef GC_ALCTR_SIZE_T size_type;
typedef GC_ALCTR_PTRDIFF_T difference_type;
typedef GC_Tp *pointer;
typedef const GC_Tp *const_pointer;
typedef GC_Tp &reference;
typedef const GC_Tp &const_reference;
typedef GC_Tp value_type;
template <class GC_Tp1> struct rebind {
typedef traceable_allocator<GC_Tp1> other;
};
GC_CONSTEXPR
traceable_allocator() GC_NOEXCEPT
{
// Empty.
}
GC_CONSTEXPR
traceable_allocator(const traceable_allocator &) GC_NOEXCEPT
{
// Empty.
}
#ifndef GC_NO_MEMBER_TEMPLATES
template <class GC_Tp1>
GC_ATTR_EXPLICIT GC_CONSTEXPR
traceable_allocator(const traceable_allocator<GC_Tp1> &) GC_NOEXCEPT
{
}
#endif
GC_CONSTEXPR ~traceable_allocator() GC_NOEXCEPT {}
GC_CONSTEXPR pointer
address(reference GC_x) const
{
return &GC_x;
}
GC_CONSTEXPR const_pointer
address(const_reference GC_x) const
{
return &GC_x;
}
// `GC_n` is permitted to be 0. The C++ standard says nothing about what
// the return value is when `GC_n` is zero.
GC_CONSTEXPR GC_Tp *
allocate(size_type GC_n, const void * = 0)
{
void *obj = GC_MALLOC_UNCOLLECTABLE(GC_n * sizeof(GC_Tp));
if (0 == obj)
GC_ALLOCATOR_THROW_OR_ABORT();
return static_cast<GC_Tp *>(obj);
}
GC_CONSTEXPR void
deallocate(pointer __p, size_type /* `GC_n` */) GC_NOEXCEPT
{
GC_FREE(__p);
}
GC_CONSTEXPR size_type
max_size() const GC_NOEXCEPT
{
return static_cast<GC_ALCTR_SIZE_T>(-1) / sizeof(GC_Tp);
}
GC_CONSTEXPR void
construct(pointer __p, const GC_Tp &__val)
{
new (__p) GC_Tp(__val);
}
GC_CONSTEXPR void
destroy(pointer __p)
{
__p->~GC_Tp();
}
};
template <> class traceable_allocator<void>
{
public:
typedef GC_ALCTR_SIZE_T size_type;
typedef GC_ALCTR_PTRDIFF_T difference_type;
typedef void *pointer;
typedef const void *const_pointer;
typedef void value_type;
template <class GC_Tp1> struct rebind {
typedef traceable_allocator<GC_Tp1> other;
};
};
template <class GC_T1, class GC_T2>
GC_CONSTEXPR inline bool
operator==(const traceable_allocator<GC_T1> &,
const traceable_allocator<GC_T2> &) GC_NOEXCEPT
{
return true;
}
template <class GC_T1, class GC_T2>
GC_CONSTEXPR inline bool
operator!=(const traceable_allocator<GC_T1> &,
const traceable_allocator<GC_T2> &) GC_NOEXCEPT
{
return false;
}
#undef GC_ALCTR_PTRDIFF_T
#undef GC_ALCTR_SIZE_T
#ifdef GC_NAMESPACE_ALLOCATOR
}
#endif
#endif /* GC_ALLOCATOR_H */
+109
View File
@@ -0,0 +1,109 @@
/*
* 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
typedef enum {
/** No reference info available. */
GC_UNREFERENCED,
/** `dest` is not allocated with a debug allocation routine. */
GC_NO_SPACE,
/** Referenced directly by root `*base_p`. */
GC_REFD_FROM_ROOT,
/** Referenced from a register, i.e. a root without an address. */
GC_REFD_FROM_REG,
/** Referenced from another heap object. */
GC_REFD_FROM_HEAP,
/** Finalizable and hence accessible. */
GC_FINALIZER_REFD
} GC_ref_kind;
/**
* Store information about the source object referencing `dest` in
* `*base_p` and `*offset_p`. If multiple objects or roots point to
* `dest`, then the one reported will be the last one used by the
* garbage collector to trace the object. If the source is root, then
* `*base_p` is the address and `*offset_p` is zero. If the source is
* a heap object, then `*base_p` is non-`NULL` and `*offset_p` is the
* offset. `dest` can be any address within a heap object.
* The allocator lock is not acquired by design (despite of the
* possibility of a race); anyway the function should not be used in
* production code.
*/
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.
* The caller should hold the allocator lock.
*/
GC_API void *GC_CALL GC_generate_random_heap_address(void);
/**
* Generate a random address inside a valid marked heap object.
* The caller should hold the allocator lock.
*/
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 collector logging mechanism (`GC_printf`)
* to produce output. It can often be called from a debugger.
*/
GC_API void GC_CALL GC_generate_random_backtrace(void);
/**
* Print a backtrace from a specific address. The client should call
* `GC_gcollect()` right before the invocation. Used e.g. by
* `GC_generate_random_backtrace()`.
*/
GC_API void GC_CALL GC_print_backtrace(void *) GC_ATTR_NONNULL(1);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* GC_BACKPTR_H */
+548
View File
@@ -0,0 +1,548 @@
/*
* 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-2025 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` file. We separate it only to make `gc.h` file 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__ << 8) + __GNUC_MINOR__ >= ((major) << 8) + (minor))
# else
# define GC_GNUC_PREREQ(major, minor) 0 /*< false */
# endif
/*
* A macro to define integer types of a pointer size. There seems to
* be no way to do this even semi-portably. The following is probably
* no better/worse than almost anything else.
* The ANSI standard suggests that `size_t` and `ptrdiff_t` might be
* better choices. But those had incorrect definitions on some older
* systems; notably `typedef int size_t` is wrong.
*/
# ifdef _WIN64
# if defined(__int64) && !defined(CPPCHECK)
# define GC_SIGNEDWORD __int64
# else
# define GC_SIGNEDWORD long long
# endif
# else
# define GC_SIGNEDWORD long
# endif
# define GC_UNSIGNEDWORD unsigned GC_SIGNEDWORD
/* Size of a pointer in bytes. */
# if defined(__SIZEOF_POINTER__)
# define GC_SIZEOF_PTR __SIZEOF_POINTER__
# elif defined(__LP64__) || defined(_LP64) || defined(_WIN64) \
|| defined(__alpha__) || defined(__arch64__) || defined(__powerpc64__) \
|| defined(__s390x__) || defined(__sparcv9) \
|| (defined(__x86_64__) && !defined(__ILP32__))
# define GC_SIZEOF_PTR 8
# else
# define GC_SIZEOF_PTR 4
# endif
/*
* The return type of `GC_get_version()`. A 32-bit unsigned integer
* or longer.
*/
# define GC_VERSION_VAL_T unsigned
/*
* Some tests for old macros. These violate our namespace rules and
* are deprecated. Use the `GC_` names instead.
*/
# 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__) || defined(__native_client__)
# 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__) /*< not Linux, not 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) /* `&& !defined(__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 (`pthreads`). */
# 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
# if defined(__clang__) && defined(__CYGWIN__) && defined(GC_THREADS) \
&& defined(__LP64__)
/*
* Workaround "__stdcall__ ignored for this target" clang warning.
* Note: `__stdcall` is defined implicitly based on `__stdcall__`.
*/
# define __stdcall__ /*< empty */
# endif
# define __GC
# if !defined(_WIN32_WCE) || defined(__GNUC__)
# include <stddef.h>
# if defined(__MINGW32__) && !defined(_WIN32_WCE) \
|| defined(__CHERI_PURE_CAPABILITY__)
# include <stdint.h>
/*
* We mention `uintptr_t`. Perhaps this should be included in pure
* MS environments as well.
*/
# endif
# else
/* Yet more kludges for WinCE. */
# include <stdlib.h> /*< for `size_t` */
# 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 the client should define
* `GC_OOM_FUNC_RETURNS_ALIAS` macro.
*/
# 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
# ifndef GC_ATTR_NORETURN
# if GC_GNUC_PREREQ(2, 7)
# define GC_ATTR_NORETURN __attribute__((__noreturn__))
# elif defined(_MSC_VER) && _MSC_VER >= 1310 /*< VS 2003+ */
# define GC_ATTR_NORETURN __declspec(noreturn)
# elif defined(__NORETURN) /*< used in Solaris */
# define GC_ATTR_NORETURN __NORETURN
# else
# define GC_ATTR_NORETURN /*< empty */
# endif
# endif
# if defined(__sgi) && !defined(__GNUC__) && _COMPILER_VERSION >= 720
# define GC_ADD_CALLER
# define GC_RETURN_ADDR ((GC_return_addr_t)__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 /* v12.0+ (MSVC 6.0+) */) \
&& !defined(_M_ARM) && !defined(_M_ARM64) && !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) \
|| defined(__sparc)
# define GC_CAN_SAVE_CALL_STACKS
# endif
/*
* If we are on a platform on which we cannot save call stacks, but
* gcc is normally used, we go ahead and define `GC_ADD_CALLER` macro.
* 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 do not know how to
* generate call stacks.
*/
# define GC_RETURN_ADDR ((GC_return_addr_t)__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_return_addr_t)__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 ((GC_return_addr_t)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(__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(GC_LINUX_THREADS) && !defined(HOST_ANDROID) \
&& !defined(__ANDROID__)) \
|| defined(GC_SOLARIS_THREADS) || defined(__COSMOPOLITAN__))
/* Intercept `pthread_exit()` where available and needed. */
# define GC_HAVE_PTHREAD_EXIT
# define GC_PTHREAD_EXIT_ATTRIBUTE GC_ATTR_NORETURN
# 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
# ifndef GC_CONSTEXPR
# if __cplusplus >= 202002L
# define GC_CONSTEXPR constexpr
# else
# define GC_CONSTEXPR /*< empty */
# endif
# endif
# endif /* __cplusplus */
#endif
+85
View File
@@ -0,0 +1,85 @@
/*
* Copyright (c) 2007-2011 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.
*/
#ifndef GC_DISCLAIM_H
#define GC_DISCLAIM_H
#include "gc.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* This API is defined only if the library has been suitably compiled
* (i.e. with `ENABLE_DISCLAIM` macro defined).
*/
/**
* Prepare the object kind used by `GC_finalized_malloc`. Call it from
* your initialization code or, at least, at some point before using
* finalized allocations. The function is thread-safe.
*/
GC_API void GC_CALL GC_init_finalized_malloc(void);
/** Type of a disclaim callback. Called with the allocator lock held. */
typedef int(GC_CALLBACK *GC_disclaim_proc)(void * /* `obj` */);
/**
* Register `proc` to be called on each object (of given `kind`) ready
* to be reclaimed. If `proc()` returns a nonzero value, the
* collector will not reclaim the object on this collection cycle
* (`proc()` should not try to resurrect the object otherwise); objects
* reachable from `proc()` (including the referred closure object) will
* be protected from collection if `mark_from_all` is nonzero, but at
* the expense that long chains of objects will take many cycles to
* reclaim. Any call to `GC_free()` deallocates the object (pointed by
* the argument) without inquiring `proc()`. Acquires the allocator lock.
* No-op in the find-leak mode.
*/
GC_API void GC_CALL GC_register_disclaim_proc(int /* `kind` */,
GC_disclaim_proc /* `proc` */,
int /* `mark_from_all` */);
/** The finalizer closure used by `GC_finalized_malloc`. */
struct GC_finalizer_closure {
GC_finalization_proc proc;
void *cd;
};
/**
* Allocate an object which is to be finalized by the given closure.
* This uses a dedicated object kind with a disclaim procedure, and
* is more efficient than `GC_register_finalizer` and friends.
* `GC_init_finalized_malloc` must be called before using this.
* The collector will reclaim the object during this collection cycle
* (thus, `fc->proc()` should not try to resurrect the object).
* The other objects reachable from `fc->proc()` (including the closure
* object in case it is a heap-allocated one) will be protected from
* collection. Note that `GC_size()` (applied to such allocated object)
* returns a value slightly bigger than the specified allocation size,
* and that `GC_base()` result points to a "pointer-sized" word prior
* to the start of the allocated object.
* The disclaim procedure is not invoked in the find-leak mode.
* There is no debugging variant of this allocation function.
*/
GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL
GC_finalized_malloc(size_t /* `size` */,
const struct GC_finalizer_closure * /* `fc` */)
GC_ATTR_NONNULL(2);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif
+123
View File
@@ -0,0 +1,123 @@
/*
* Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
* Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved.
* Copyright 1996-1999 by Silicon Graphics. All rights reserved.
* Copyright 1999 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 file assumes the collector has been compiled with `GC_GCJ_SUPPORT`
* macro defined.
*/
/*
* We allocate objects whose first element contains a pointer to a structure
* describing the object type. This structure contains a garbage collector
* mark descriptor at offset `GC_GCJ_MARK_DESCR_OFFSET`.
* Alternatively, the objects may be marked by the mark procedure passed
* to `GC_init_gcj_malloc_mp()`.
*/
#ifndef GC_GCJ_H
#define GC_GCJ_H
#ifndef GC_H
# include "gc.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*
* The offset of the garbage collector mark descriptor inside the
* structure describing the object type ("vtable"). `gcj` keeps the
* mark descriptor as the second "pointer-sized" word of "vtable".
* Probably this needs to be adjusted for other clients. It is assumed
* that this offset is not smaller than the size of a pointer (the
* assumption allows objects on the free list to be marked normally).
*/
#ifndef GC_GCJ_MARK_DESCR_OFFSET
# define GC_GCJ_MARK_DESCR_OFFSET GC_SIZEOF_PTR
#endif
/**
* This function must be called before the `gcj` allocators are invoked.
* `mp_index` and `mp` are the index and mark procedure (see `gc_mark.h`
* file), respectively, for the allocated objects. `mp` will be used to
* build the descriptor for objects allocated through the debugging
* interface; it will be invoked on all such objects with an `env` value
* of 1. The client may choose to use the same mark procedure (`mp`) for
* some of its generated mark descriptors. In that case, it should use
* a different `env` value to detect the presence or absence of the debug
* header. `mp` is really of type `GC_mark_proc`, as defined in `gc_mark.h`
* file; we do not want to include that here for namespace pollution reasons.
* Passing in `mp_index` here instead of having `GC_init_gcj_malloc()`
* internally call `GC_new_proc()` is quite ugly, but in typical usage
* scenarios a compiler also has to know about `mp_index`, so generating it
* dynamically is not acceptable. The `mp_index` will typically be
* an integer less than `RESERVED_MARK_PROCS`, so that it does not collide
* with indices allocated by `GC_new_proc()`. If the application needs
* no other reserved indices, zero (`GC_GCJ_RESERVED_MARK_PROC_INDEX` in
* `gc_mark.h` file) is an obvious choice. Deprecated, portable clients
* should include `gc_mark.h` file and use `GC_init_gcj_malloc_mp()` instead.
*/
GC_API GC_ATTR_DEPRECATED void GC_CALL GC_init_gcj_malloc(int /* `mp_index` */,
void * /* `mp` */);
/**
* Allocate an object, clear it, and store the pointer to the type
* structure ("vtable" in `gcj`). This adds a byte at the end of the
* object if `GC_malloc()` would. In case of out of memory,
* `GC_oom_fn()` is called and its result is returned.
*/
GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL
GC_gcj_malloc(size_t /* `lb` */, const void * /* `vtable_ptr` */);
/**
* Similar to `GC_gcj_malloc`, but add the debug info. This is allocated
* with `GC_gcj_debug_kind`.
*/
GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL
GC_debug_gcj_malloc(size_t /* `lb` */, const void * /* `vtable_ptr` */,
GC_EXTRA_PARAMS);
/**
* Similar to `GC_gcj_malloc`, but assumes that a pointer to near the
* beginning (i.e. within the first heap block) of the allocated object
* is always maintained.
*/
GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL
GC_gcj_malloc_ignore_off_page(size_t /* `lb` */,
const void * /* `vtable_ptr` */);
/**
* The kind numbers of normal and debug `gcj` objects. Useful only for
* debug support, we hope.
*/
GC_API int GC_gcj_kind;
GC_API int GC_gcj_debug_kind;
#ifdef GC_DEBUG
# define GC_GCJ_MALLOC(s, d) GC_debug_gcj_malloc(s, d, GC_EXTRAS)
# define GC_GCJ_MALLOC_IGNORE_OFF_PAGE(s, d) GC_GCJ_MALLOC(s, d)
#else
# define GC_GCJ_MALLOC(s, d) GC_gcj_malloc(s, d)
# define GC_GCJ_MALLOC_IGNORE_OFF_PAGE(s, d) \
GC_gcj_malloc_ignore_off_page(s, d)
#endif
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* GC_GCJ_H */
+261
View File
@@ -0,0 +1,261 @@
/*
* 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.
* Copyright (c) 2008-2025 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.
*/
#ifndef GC_INLINE_H
#define GC_INLINE_H
/*
* *Warning*: Note that for these routines, it is the client`s 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 "pointer-sized"
* word in the resulting object. This is not an issue if
* `GC_get_all_interior_pointers()` returns zero or if
* `GC_get_dont_add_byte_at_end()` returns 1. This interface is most useful
* for compilers that generate C code. It is also used internally for
* thread-local allocation. A manual use is hereby discouraged.
* Multi-threaded clients should include `atomic_ops.h` file (or similar)
* before this header. There is no debugging variant of this allocation API.
*/
#include "gc.h"
#include "gc_tiny_fl.h"
#if GC_GNUC_PREREQ(3, 0) || defined(__clang__)
/* Equivalent to `(expr)`, but predict that usually `expr == outcome`. */
# define GC_EXPECT(expr, outcome) __builtin_expect(expr, outcome)
#else
# define GC_EXPECT(expr, outcome) (expr)
#endif
#ifndef GC_ASSERT
# ifdef NDEBUG
# define GC_ASSERT(expr) (void)0
# else
# include <assert.h>
# define GC_ASSERT(expr) assert(expr)
# endif
#endif
#ifndef GC_PREFETCH_FOR_WRITE
# if (GC_GNUC_PREREQ(3, 0) || defined(__clang__)) \
&& !defined(GC_NO_PREFETCH_FOR_WRITE)
# define GC_PREFETCH_FOR_WRITE(x) __builtin_prefetch((x), 1 /* write */)
# elif defined(_MSC_VER) && !defined(GC_NO_PREFETCH_FOR_WRITE) \
&& (defined(_M_IX86) || defined(_M_X64)) && !defined(_CHPE_ONLY_) \
&& (_MSC_VER >= 1900 /* VS 2015+ */)
# include <intrin.h>
# define GC_PREFETCH_FOR_WRITE(x) _m_prefetchw(x)
/* TODO: Support also `_M_ARM` (`__prefetchw`). */
# else
# define GC_PREFETCH_FOR_WRITE(x) (void)0
# endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* Object kinds (exposed to public). */
#define GC_I_PTRFREE 0
#define GC_I_NORMAL 1
/**
* Determine if the collector has been configured not to pad the
* allocated objects even in the all-interior-pointers mode.
* Meaningful only if `GC_get_all_interior_pointers()` returns 1.
*/
GC_API int GC_CALL GC_get_dont_add_byte_at_end(void);
/**
* Return a list of one or more objects of the indicated size, linked
* through the first pointer in each object. This has the advantage
* that it acquires the allocator lock only once, and may greatly
* reduce time wasted contending for the allocator lock. Typical usage
* would be in a thread that requires many items of the same size.
* It would keep its own free list in a thread-local storage, and call
* `GC_malloc_many()` or friends to replenish it. (We do not round up
* object sizes, since a call indicates the intention to consume many
* objects of exactly this size.) We assume that the size is nonzero
* and a multiple of `GC_GRANULE_BYTES`, and that the size already
* includes the value returned by `GC_get_all_interior_pointers()`
* (unless `GC_get_dont_add_byte_at_end()` returns a nonzero value).
* We return the free-list by assigning it to `*result`, since it is
* not safe to return a linked list of pointer-free objects, since the
* collector would not retain the entire list if it were invoked just
* as we were returning; the client must make sure that `*result` is
* traced even if objects are pointer-free. Note also that the client
* should usually clear the link field.
*/
GC_API void GC_CALL GC_generic_malloc_many(size_t /* `lb_adjusted` */,
int /* `kind` */,
void ** /* `result` */);
/**
* A generalized variant 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 /* `kind` */);
#ifdef GC_THREADS
/* Same as `GC_malloc_kind` 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 /* `kind` */);
#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) (void)(*(my_fl) = (next))
#elif defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ > __SIZEOF_SIZE_T__)
/*
* Directly use the gcc atomic intrinsic as the size of a pointer is
* bigger than that of `AO_t`.
*/
# define GC_FAST_M_AO_STORE(my_fl, next) \
__atomic_store_n(my_fl, next, __ATOMIC_RELAXED)
#else
# define GC_FAST_M_AO_STORE(my_fl, next) \
AO_store((volatile AO_t *)(my_fl), (size_t)(next))
#endif
/**
* The ultimately general inline allocation macro. Allocate an object
* of size `lg` (in 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 `lg` argument is too large, then we
* allocate with `default_expr` instead. If we need to refill the free
* list, we use `GC_generic_malloc_many()` with the indicated kind `k`.
* `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 `GC_generic_malloc_many()` before putting multiple
* objects into the `tiny_fl` entry. If `num_direct` is zero, then the
* free lists may also be initialized to `NULL`. Note that we use the
* zeroth free list to hold objects of 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 case of `num_direct` is 0. Particularly,
* if `lg` argument is constant, this should generate a small amount of code.
*/
#define GC_FAST_MALLOC_GRANS(result, lg, tiny_fl, num_direct, k, \
default_expr, init) \
do { \
if (GC_EXPECT((lg) >= GC_TINY_FREELISTS, 0)) { \
result = (default_expr); \
} else { \
void **my_fl = (tiny_fl) + (lg); \
void *my_entry = *my_fl; \
void *next; \
\
for (;;) { \
if (GC_EXPECT((GC_word)(GC_uintptr_t)my_entry \
> (num_direct) + GC_TINY_FREELISTS + 1, \
1)) { \
next = *(void **)(my_entry); \
result = my_entry; \
GC_FAST_M_AO_STORE(my_fl, next); \
init; \
GC_PREFETCH_FOR_WRITE(next); \
if ((k) != GC_I_PTRFREE) { \
GC_end_stubborn_change(my_fl); \
GC_reachable_here(next); \
} \
GC_ASSERT(GC_size(result) >= GC_RAW_BYTES_FROM_INDEX(lg)); \
GC_ASSERT((k) == GC_I_PTRFREE \
|| 0 /* `NULL` */ == ((void **)result)[1]); \
break; \
} \
/* Entry contains counter or `NULL`. */ \
if ((GC_signed_word)(GC_uintptr_t)my_entry \
- (GC_signed_word)(num_direct) \
<= 0 /*< `(GC_uintptr_t)my_entry <= num_direct` */ \
&& my_entry != 0 /* NULL */) { \
/* Small counter value, not `NULL`. */ \
GC_FAST_M_AO_STORE(my_fl, (char *)my_entry + (lg) + 1); \
result = (default_expr); \
break; \
} else { \
/* Large counter or `NULL`. */ \
size_t lb_adj = GC_RAW_BYTES_FROM_INDEX(0 == (lg) ? 1 : (lg)); \
\
GC_generic_malloc_many(lb_adj, k, my_fl); \
my_entry = *my_fl; \
if (0 /* `NULL` */ == my_entry) { \
result = (*GC_get_oom_fn())(lb_adj); \
break; \
} \
} \
} \
} \
} while (0)
/**
* Allocate `n` "pointer-sized" words. The allocation size is rounded
* up to a granule size. The pointer is stored to `result`.
* Should not be used unless `GC_get_all_interior_pointers()` returns zero
* or if `GC_get_dont_add_byte_at_end()` returns 1. Does not acquire
* the allocator 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, k, init) \
do { \
size_t lg = GC_PTRS_TO_WHOLE_GRANULES(n); \
\
GC_FAST_MALLOC_GRANS(result, lg, tiny_fl, 0 /* `num_direct` */, k, \
GC_malloc_kind(GC_RAW_BYTES_FROM_INDEX(lg), k), \
init); \
} while (0)
#define GC_MALLOC_WORDS(result, n, tiny_fl) \
GC_MALLOC_WORDS_KIND(result, n, tiny_fl, GC_I_NORMAL, \
(void)(*(void **)(result) = 0 /* `NULL` */))
#define GC_MALLOC_ATOMIC_WORDS(result, n, tiny_fl) \
GC_MALLOC_WORDS_KIND(result, n, tiny_fl, GC_I_PTRFREE, (void)0)
/** Allocate a two-pointer initialized object. */
#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)
/**
* Print address of each object in the free list for the given `kind`
* and size `lg` (in granules). The caller should hold the allocator
* lock at least in the reader mode. Defined only if the library has
* been compiled without `NO_DEBUGGING` macro defined.
*/
GC_API void GC_CALL GC_print_free_list(int /* `kind` */, size_t /* `lg` */);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* !GC_INLINE_H */
+516
View File
@@ -0,0 +1,516 @@
/*
* Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
* Copyright (c) 2001 by Hewlett-Packard Company. All rights reserved.
* Copyright (c) 2009-2025 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 contains interfaces to the garbage collector 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
#define GC_PROC_BYTES 100
#if defined(GC_BUILD) || defined(NOT_GCBUILD)
struct GC_ms_entry;
struct GC_hblk_s;
#else
struct GC_ms_entry {
void *opaque;
};
struct GC_hblk_s {
void *opaque;
};
#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 (which is located at the beginning of each
* object). Thus mark procedures may not count on the presence of a
* type descriptor, and must handle this case correctly somehow. Also,
* a mark procedure should be prepared to be executed concurrently from
* the marker threads (the latter ones are created only if the client
* has called `GC_start_mark_threads()` or started a user thread
* previously). For the compatibility reason, `addr` is a pointer to
* `GC_word`, but it should be treated as a pointer to `void` pointer.
*/
typedef struct GC_ms_entry *(GC_CALLBACK *GC_mark_proc)(
GC_word * /* `addr` */, struct GC_ms_entry * /* `mark_stack_top` */,
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 is necessary to assign statically known indices to
* certain mark procedures. 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 rest
* (high-order) bits.
*/
#define GC_DS_TAG_BITS 2
#define GC_DS_TAGS ((1U << GC_DS_TAG_BITS) - 1)
/**
* The entire descriptor is a length in bytes that must be a multiple of 4.
*/
#define GC_DS_LENGTH 0
/**
* The high-order bits are describing pointer fields. The most
* significant bit is set if the first "pointer-sized" word is a pointer.
* (This unconventional ordering sometimes makes the marker slightly faster.)
* Zeros indicate definite non-pointers; ones indicate possible pointers.
* *Note*: only usable if pointers are aligned on the size of a pointer (thus,
* extra care should be taken by client on cris and m68k architectures).
*/
#define GC_DS_BITMAP 1
/**
* 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_DS_PROC 2
/**
* 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 at the beginning of the object. Note that in the
* multi-threaded environments per-object descriptors must be located
* in either the first two or last two "pointer-sized" words of the
* object, since only those are guaranteed to be cleared while the
* allocator lock is held.
*/
#define GC_DS_PER_OBJECT 3
#define GC_INDIR_PER_OBJ_BIAS 0x10
#define GC_MAKE_PROC(proc_index, env) \
((((((GC_word)(env)) << GC_LOG_MAX_MARK_PROCS) | (unsigned)(proc_index)) \
<< GC_DS_TAG_BITS) \
| (GC_word)GC_DS_PROC)
/**
* Bounds on the heap. Guaranteed to be valid. Likely to include future
* heap expansion. Hence the bounded range usually includes not-yet-mapped
* memory, or might overlap with other data roots. The address of any heap
* object is larger than `GC_least_plausible_heap_addr` and less than
* `GC_greatest_plausible_heap_addr`.
*/
GC_API void *GC_least_plausible_heap_addr;
GC_API void *GC_greatest_plausible_heap_addr;
/**
* Specify the pointer address mask. Works only if the collector is
* built with `DYNAMIC_POINTER_MASK` macro defined. These primitives
* are normally needed only to support systems that use high-order
* pointer tags. The setter is expected to be called, if needed,
* before the collector initialization or, at least, before the first
* object is allocated. Both the setter and the getter are unsynchronized.
*/
GC_API void GC_CALL GC_set_pointer_mask(GC_word);
GC_API GC_word GC_CALL GC_get_pointer_mask(void);
/**
* Similar to `GC_set_pointer_mask`/`GC_get_pointer_mask` but for the
* pointer address shift. The value should be less than the size of
* `GC_word`, in bits. Applied after the mask.
*/
GC_API void GC_CALL GC_set_pointer_shift(unsigned);
GC_API unsigned GC_CALL GC_get_pointer_shift(void);
/**
* 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 the 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_top` */,
struct GC_ms_entry * /* `mark_stack_limit` */, void ** /* `src` */);
#define GC_MARK_AND_PUSH(obj, msp, lim, src) \
(GC_ADDR_LT((char *)GC_least_plausible_heap_addr, (char *)(obj)) \
&& GC_ADDR_LT((char *)(obj), \
(char *)GC_greatest_plausible_heap_addr) \
? GC_mark_and_push(obj, msp, lim, src) \
: (msp))
GC_API void GC_CALL GC_push_proc(GC_word /* `descr` */, void * /* `obj` */);
GC_API struct GC_ms_entry *GC_CALL
GC_custom_push_proc(GC_word /* `descr` */, void * /* `obj` */,
struct GC_ms_entry * /* `mark_stack_top` */,
struct GC_ms_entry * /* `mark_stack_limit` */);
GC_API struct GC_ms_entry *GC_CALL
GC_custom_push_range(void * /* `bottom` */, void * /* `top` */,
struct GC_ms_entry * /* `mark_stack_top` */,
struct GC_ms_entry * /* `mark_stack_limit` */);
/**
* 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 as `GC_get_debug_header_size()` 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;
/**
* Return the heap block size. Each heap block is devoted to a single size
* and kind of object.
*/
GC_API GC_ATTR_CONST size_t GC_CALL GC_get_hblk_size(void);
typedef void(GC_CALLBACK *GC_walk_hblk_fn)(struct GC_hblk_s *,
void * /* `client_data` */);
/**
* Apply `fn` to each allocated heap block. It is the responsibility
* of the caller to avoid data race during the function execution
* (e.g. by acquiring the allocator lock at least in the reader mode).
*/
GC_API void GC_CALL GC_apply_to_all_blocks(GC_walk_hblk_fn,
void * /* `client_data` */)
GC_ATTR_NONNULL(1);
/* Same as `GC_walk_hblk_fn` but with index of the free list. */
typedef void(GC_CALLBACK *GC_walk_free_blk_fn)(struct GC_hblk_s *,
int /* `index` */,
void * /* `client_data` */);
/**
* Apply `fn` to each completely empty heap block. It is the responsibility
* of the caller to avoid data race during the function execution (e.g. by
* acquiring the allocator lock at least in the reader mode).
*/
GC_API void GC_CALL GC_iterate_free_hblks(GC_walk_free_blk_fn,
void * /* `client_data` */)
GC_ATTR_NONNULL(1);
/**
* If there are likely to be false references to a block starting at
* `h` of the indicated length (`len`), then return the next plausible
* starting location for `h` that might avoid these false references.
* (In other words: Is the block starting at `h` of size `len` bytes
* black-listed? If so, then return the address of the next plausible
* `r` such that (`r`,`len`) might not be black-listed. Note that
* pointer `r` may not actually be in the heap, we guarantee only that
* every smaller value of `r` after `h` is also black-listed.)
* Otherwise `NULL` is returned. Assumes the allocator lock is held at
* least in the reader mode, but no assertion about it by design.
*/
GC_API struct GC_hblk_s *GC_CALL
GC_is_black_listed(struct GC_hblk_s * /* `h` */, size_t /* `len` */);
/**
* Return the number of set mark bits for the heap block where object `p`
* is located. Defined only if the library has been compiled without
* `NO_DEBUGGING` macro defined.
*/
GC_API unsigned GC_CALL GC_count_set_marks_in_hblk(const void * /* `p` */);
/*
* And some routines to support creation of new "kinds", e.g. with custom
* mark procedures, by language runtimes. The `_inner` variants assume
* the caller holds the allocator 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. The last two parameters must be zero
* or one.
*/
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);
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);
/**
* Similar to `GC_init_gcj_malloc()` described in `gc_gcj.h` file but with
* the proper types of the arguments and an additional runtime checking.
* `GC_GCJ_MARK_DESCR_OFFSET` should be passed to `descr_offset` argument.
* Defined only if the library has been compiled with `GC_GCJ_SUPPORT`
* macro defined.
*/
GC_API void GC_CALL GC_init_gcj_malloc_mp(unsigned /* `mp_index` */,
GC_mark_proc /* `mp` */,
size_t /* `descr_offset` */);
/**
* 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
* collector 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 do not 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 /* `kind` */);
/**
* Same as `GC_generic_malloc()`, but pointers to past the first heap block
* of the resulting object are ignored. We avoid holding the allocator lock
* while we clear the memory.
*/
GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL
GC_generic_malloc_ignore_off_page(size_t /* `lb` */, int /* `kind` */);
/**
* A generalized variant of `GC_malloc_uncollectable()` and
* `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 /* `kind` */);
/**
* Same as `GC_generic_malloc()`, 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 /* `kind` */);
GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void *GC_CALL
GC_debug_generic_or_special_malloc(size_t /* `size` */, int /* `kind` */,
GC_EXTRA_PARAMS);
#ifdef GC_DEBUG
# define GC_GENERIC_OR_SPECIAL_MALLOC(sz, k) \
GC_debug_generic_or_special_malloc(sz, k, GC_EXTRAS)
#else
# define GC_GENERIC_OR_SPECIAL_MALLOC(sz, k) \
GC_generic_or_special_malloc(sz, k)
#endif /* !GC_DEBUG */
/**
* Similar to `GC_size` but returns object kind. The size is returned too
* if `psize` is not `NULL`. The object pointer should be non-`NULL`.
*/
GC_API int GC_CALL GC_get_kind_and_size(const void *, size_t * /* `psize` */)
GC_ATTR_NONNULL(1);
/**
* 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.
*/
typedef void(GC_CALLBACK *GC_describe_type_fn)(void * /* `p` */,
char * /* `out_buf` */);
#define GC_TYPE_DESCR_LEN 40
/**
* Register a `describe_type` function to be used when printing objects
* of a particular `kind`.
*/
GC_API void GC_CALL GC_register_describe_type_fn(int /* `kind` */,
GC_describe_type_fn);
/**
* 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.
* The argument may be `NULL`.
*/
GC_API void *GC_CALL GC_clear_stack(void *);
/**
* Set/get the client notifier on collections. The client-supplied procedure
* is called at the start of every full collection (called with the allocator
* 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 collector from
* within the callback procedure. Both the setter and the getter acquire the
* allocator lock (in the reader mode in case of the getter).
*/
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 should hold the
* allocator lock. The argument should be the real address of an object
* (i.e. the address of the debug header if there is one).
*/
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);
/**
* Get the mark bit. Returns 1 (true) or 0. The caller should hold the
* allocator lock at least in the reader mode. The argument should be
* the real address of an object (i.e. the address of the debug header
* if there is one).
*/
GC_API int GC_CALL GC_is_marked(const void *) GC_ATTR_NONNULL(1);
/**
* Push everything in the given range onto the mark stack. `bottom` is
* the first location to be scanned; `top` is one past the last location
* to be scanned. Should only be used if there is no possibility of mark
* stack overflow.
*/
GC_API void GC_CALL GC_push_all(void * /* `bottom` */, void * /* `top` */);
/**
* Similar to `GC_push_all` but treats all interior pointers as valid and
* scans the entire region immediately (not just schedules it for scanning),
* in case the contents change.
*/
GC_API void GC_CALL GC_push_all_eager(void * /* `bottom` */,
void * /* `top` */);
/**
* Similar to `GC_push_all` but processes either all or only dirty pages
* depending on `all` argument.
*/
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/get the client push-other-roots procedure. A client-supplied
* procedure should also call the original one. Note that both the setter
* and the 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 allocator lock at least in the reader mode. Object base
* pointer, object size and client custom data are passed to the callback
* (holding the allocator lock in the same mode as the caller does).
*/
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);
/**
* Is the given address in one of the temporary static root sections?
* Acquires the allocator lock in the reader mode. For the debugging
* purpose only.
*/
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` */);
/**
* Set the client for when mark stack is empty. A client can use this
* callback to process (un)marked objects and push additional work onto
* the stack. Useful for implementing ephemerons. Both the setter and
* the getter acquire the allocator lock (in the reader mode in case of
* the getter).
*/
typedef struct GC_ms_entry *(GC_CALLBACK *GC_on_mark_stack_empty_proc)(
struct GC_ms_entry * /* `mark_stack_top` */,
struct GC_ms_entry * /* `mark_stack_limit` */);
GC_API void GC_CALL GC_set_on_mark_stack_empty(GC_on_mark_stack_empty_proc);
GC_API GC_on_mark_stack_empty_proc GC_CALL GC_get_on_mark_stack_empty(void);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* GC_MARK_H */
@@ -0,0 +1,140 @@
/*
* 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.
*/
/*
* The collector `pthreads` 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` file only. Included only if `GC_PTHREADS` macro
* is defined.
*/
#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.
* Such 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
* `pthread_key_create()`. 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
/* This is needed anyway for proper redirection. */
# include <signal.h>
# 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
# ifndef GC_NO_PTHREAD_SIGMASK
# if defined(GC_PTHREAD_SIGMASK_NEEDED) || defined(__COSMOPOLITAN__) \
|| defined(GC_HAVE_PTHREAD_SIGMASK) || defined(_BSD_SOURCE) \
|| defined(_GNU_SOURCE) || defined(_NETBSD_SOURCE) \
|| (_POSIX_C_SOURCE >= 199506L) || (_XOPEN_SOURCE >= 500) \
|| (__POSIX_VISIBLE >= 199506) /*< xBSD internal macro */
GC_API int GC_pthread_sigmask(int /* `how` */, const sigset_t *,
sigset_t * /* `oset` */);
# else
# define GC_NO_PTHREAD_SIGMASK
# 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
* platform `pthread.h` file redefines some POSIX thread functions to use
* mangled names. Anyway, it is 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 */
+107
View File
@@ -0,0 +1,107 @@
/*
* 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 and inlined allocators.
* Each global free list also essentially starts with one of these.
* However, global free lists are known to the collector.
* "Tiny" free lists are basically private to the client.
* Their contents are viewed as "in use" and marked accordingly by the
* core of the collector. 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
* architectures (e.g. i686), 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.
* `GC_GRANULE_BYTES` should not be overridden in any instances of the
* collector library that may be shared between applications, since it
* affects the ABI (application binary interface) to the library.
*/
#if defined(CPPCHECK) && GC_GRANULE_BYTES == 1
# undef GC_GRANULE_BYTES
#endif
#ifdef GC_GRANULE_BYTES
# define GC_GRANULE_PTRS (GC_GRANULE_BYTES / GC_SIZEOF_PTR)
#else
# define GC_GRANULE_PTRS 2 /*< in pointers */
# define GC_GRANULE_BYTES (GC_GRANULE_PTRS * GC_SIZEOF_PTR)
#endif /* !GC_GRANULE_BYTES */
/** Convert size in pointers to that in granules. */
#define GC_PTRS_TO_GRANULES(n) ((n) / GC_GRANULE_PTRS)
/**
* Convert size in pointers to that in granules, but rounding up the
* result.
*/
#define GC_PTRS_TO_WHOLE_GRANULES(n) \
GC_PTRS_TO_GRANULES((n) + GC_GRANULE_PTRS - 1)
/*
* A "tiny" free-list header contains `GC_TINY_FREELISTS` pointers to
* singly-linked lists of objects of different sizes, the `i`-th one
* containing objects of `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 `i`-th free list corresponds to size `i * GC_GRANULE_BYTES`.
* Internally to the collector, the index `i` can be computed with
* `ALLOC_REQUEST_GRANS()`. The latter also depends on the values
* returned by `GC_get_dont_add_byte_at_end()` and
* `GC_get_all_interior_pointers()`.
*/
/**
* 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) (GC_GRANULE_BYTES * (i))
/* Deprecated. Use `GC_GRANULE_PTRS` instead. */
#undef GC_GRANULE_WORDS
#define GC_GRANULE_WORDS GC_GRANULE_PTRS
/* Deprecated. Use `GC_PTRS_TO_GRANULES()` instead. */
#define GC_WORDS_TO_GRANULES(n) GC_PTRS_TO_GRANULES(n)
/* Deprecated. */
#define GC_WORDS_TO_WHOLE_GRANULES(n) GC_PTRS_TO_WHOLE_GRANULES(n)
#endif /* GC_TINY_FL_H */
+196
View File
@@ -0,0 +1,196 @@
/*
* 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.
*
* Note for cris and m68k architectures (and for bcc and wcc compilers):
* this API expects all pointers in the type (`T`) are aligned by the size
* of a pointer (which might differ from `ALIGNMENT`).
*/
#ifndef GC_TYPED_H
#define GC_TYPED_H
#ifndef GC_H
# include "gc.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/** The size of `GC_word` (not a pointer) type in bits. */
#define GC_WORDSZ (8 * sizeof(GC_word))
/** The size of a type `t` in pointers. The value is rounded down. */
#define GC_SIZEOF_IN_PTRS(t) (sizeof(t) / sizeof(void *))
/** The offset of a field in pointers. */
#define GC_OFFSETOF_IN_PTRS(t, f) (offsetof(t, f) / sizeof(void *))
/**
* The bitmap type. The least significant bit of the first `GC_word` is one
* if the first "pointer-sized" word in the object may be a pointer.
*/
typedef GC_word *GC_bitmap;
/**
* The number of elements (of `GC_word` type) of a bitmap array to
* create for a given type `t`. The bitmap is intended to be passed to
* `GC_make_descriptor()`.
*/
#define GC_BITMAP_SIZE(t) ((GC_SIZEOF_IN_PTRS(t) + GC_WORDSZ - 1) / GC_WORDSZ)
/**
* The setter and getter of the bitmap. The `bm` argument should be of
* `GC_bitmap` type; `i` argument should be of some `unsigned` type and
* should not have side effects.
*/
#define GC_set_bit(bm, i) \
((bm)[(i) / GC_WORDSZ] |= (GC_word)1 << ((i) % GC_WORDSZ))
#define GC_get_bit(bm, i) (((bm)[(i) / GC_WORDSZ] >> ((i) % GC_WORDSZ)) & 1)
typedef GC_word GC_descr;
/**
* Return a type descriptor for the object whose layout is described
* by the first argument. The least significant bit of the first
* `GC_word` is one if the first "pointer-sized" word in the object may
* be a pointer. The second argument (`number_of_bits_in_bitmap`)
* specifies the number of meaningful bits in the bitmap.
* The actual object may be larger (but not smaller); any additional
* "pointer-sized" 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 a type, not once per an
* allocation.
*
* It is possible to generate a descriptor for a client type `T` with
* aligned pointer fields `f1`, `f2`, ... as follows:
* ```
* GC_descr t_descr;
* {
* GC_word bm[GC_BITMAP_SIZE(T)] = { 0 };
* GC_set_bit(bm, GC_OFFSETOF_IN_PTRS(T, f1));
* GC_set_bit(bm, GC_OFFSETOF_IN_PTRS(T, f2));
* ...
* t_descr = GC_make_descriptor(bm, GC_SIZEOF_IN_PTRS(T));
* }
* ```
*/
GC_API GC_descr GC_CALL
GC_make_descriptor(const GC_word * /* `GC_bitmap` `bm` */,
size_t /* `number_of_bits_in_bitmap` */);
/**
* Allocate an object whose layout is described by `d`. The size
* (`size_in_bytes`) may *not* be less than the number of meaningful
* bits in the bitmap of `d` multiplied by the size of a pointer.
* 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(size_t /* `size_in_bytes` */,
GC_descr /* `d` */);
/** The ignore-off-page variant of `GC_malloc_explicitly_typed()`. */
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` */);
/**
* Allocate an array of `nelements` elements, each of the given size
* (`element_size_in_bytes`), and with the given descriptor (`d`).
* 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, `element_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 the size of a pointer.
* The returned object is cleared.
*/
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 */);
#define GC_CALLOC_TYPED_DESCR_PTRS 1
#define GC_CALLOC_TYPED_DESCR_WORDS 8 /*< includes space for pointers */
#ifdef GC_BUILD
struct GC_calloc_typed_descr_s;
# define GC_calloc_typed_descr_s GC_calloc_typed_descr_opaque_s
#endif
struct GC_calloc_typed_descr_s {
GC_uintptr_t opaque_p[GC_CALLOC_TYPED_DESCR_PTRS];
GC_word opaque[GC_CALLOC_TYPED_DESCR_WORDS - GC_CALLOC_TYPED_DESCR_PTRS];
};
#undef GC_calloc_typed_descr_s
/**
* This is same as `GC_calloc_explicitly_typed` but more optimal in
* terms of the performance and memory usage if the client needs to
* allocate multiple typed object arrays with the same layout and
* number of elements. The client should call it to be prepared for
* the subsequent allocations by `GC_calloc_do_explicitly_typed()`, one
* or many. The result of the preparation is stored to `*pctd`, even
* in case of a failure. The prepared structure could be just dropped
* when no longer needed. Returns 0 on failure, 1 on success; the
* result could be ignored (as it is also stored to `*pctd` and checked
* later by `GC_calloc_do_explicitly_typed()`).
*/
GC_API int GC_CALL GC_calloc_prepare_explicitly_typed(
struct GC_calloc_typed_descr_s * /* `pctd` */, size_t /* `sizeof_ctd` */,
size_t /* `nelements` */, size_t /* `element_size_in_bytes` */, GC_descr);
/** The actual object allocation for the prepared description. */
GC_API GC_ATTR_MALLOC void *GC_CALL GC_calloc_do_explicitly_typed(
const struct GC_calloc_typed_descr_s * /* `pctd` */,
size_t /* `sizeof_ctd` */);
#ifdef GC_DEBUG
# define GC_MALLOC_EXPLICITLY_TYPED(bytes, d) ((void)(d), GC_MALLOC(bytes))
# define GC_MALLOC_EXPLICITLY_TYPED_IGNORE_OFF_PAGE(bytes, d) \
GC_MALLOC_EXPLICITLY_TYPED(bytes, d)
# 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_MALLOC_EXPLICITLY_TYPED_IGNORE_OFF_PAGE(bytes, d) \
GC_malloc_explicitly_typed_ignore_off_page(bytes, d)
# define GC_CALLOC_EXPLICITLY_TYPED(n, bytes, d) \
GC_calloc_explicitly_typed(n, bytes, d)
#endif
/* Deprecated. Use `GC_SIZEOF_IN_PTRS()` instead. */
#define GC_WORD_LEN(t) GC_SIZEOF_IN_PTRS(t)
/* Deprecated. Use `GC_OFFSETOF_IN_PTRS()` instead. */
#define GC_WORD_OFFSET(t, f) GC_OFFSETOF_IN_PTRS(t, f)
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* GC_TYPED_H */
+55
View File
@@ -0,0 +1,55 @@
/*
* 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` file.
*/
#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 files `CMakeLists.txt`,
* `build.zig.zon` and `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 3
# define GC_TMP_VERSION_MICRO 0 /*< 8.3.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
+76
View File
@@ -0,0 +1,76 @@
/*
* 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.
*/
#ifndef GC_JAVAXFC_H
#define GC_JAVAXFC_H
#ifndef GC_H
# include "gc.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* Invoke all remaining finalizers that have not yet been run. (Since the
* notifier is not called, this should be called from a separate thread.)
* This function is needed for strict compliance with the Java standard,
* which can make the runtime guarantee that all finalizers are run.
* This is problematic for several reasons:
* 1. It means that finalizers, and all methods called by them, must be
* prepared to deal with objects that have been finalized in spite of
* the fact that they are still referenced by statically allocated
* pointer variables (i.e. finalizers run at this point must be
* prepared to deal with a mostly broken world);
* 2. The Java standard implies we have to keep running finalizers until
* there are no more left, thus it may mean that we get stuck in
* an infinite loop running finalizers that create new finalizable
* objects, though that is probably unlikely.
* Thus this is not recommended for general use.
* Acquires the allocator lock (to enqueue all finalizers).
*/
GC_API void GC_CALL GC_finalize_all(void);
#ifdef GC_THREADS
/**
* External thread suspension support. No thread suspension count
* (so a thread which has been suspended numerous times will be resumed
* with the very first call to `GC_resume_thread()`). Acquires the
* allocator lock. Thread should be registered in the collector.
* Unimplemented on some platforms. Not recommended for general use.
*/
# ifndef GC_SUSPEND_THREAD_ID
# define GC_SUSPEND_THREAD_ID void *
# endif
GC_API void GC_CALL GC_suspend_thread(GC_SUSPEND_THREAD_ID);
GC_API void GC_CALL GC_resume_thread(GC_SUSPEND_THREAD_ID);
/**
* Is the given thread suspended externally? The result is either
* 1 (true) or 0. Acquires the allocator lock in the reader mode.
* Note: returns 0 (false) if the thread is not registered in the collector.
* Unimplemented on some platforms (same as `GC_suspend_thread()`).
*/
GC_API int GC_CALL GC_is_thread_suspended(GC_SUSPEND_THREAD_ID);
#endif /* GC_THREADS */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* GC_JAVAXFC_H */
+120
View File
@@ -0,0 +1,120 @@
/*
* 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 this header file (e.g., via gcc `--include` option) to turn
* the collector into a leak detector.
*/
#ifndef GC_DEBUG
# define GC_DEBUG
#endif
#include "gc.h"
#ifndef GC_DONT_INCLUDE_STDLIB
/*
* We ensure the platform `stdlib.h` and `string.h` files 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 reallocarray
#define reallocarray(p, m, n) GC_REALLOC(p, (m) * (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` macro defined
* as well to redirect `wcsdup`.
*/
# include <wchar.h>
# undef wcsdup
# define wcsdup(s) GC_WCSDUP(s)
#endif
/*
* The following routines for the aligned objects allocation
* (`aligned_alloc`, `valloc`, etc.) do not have their debugging
* counterparts. Note that `free()` called for such objects may output
* a warning that the pointer has no debugging info.
*/
#undef aligned_alloc
#define aligned_alloc(a, n) GC_memalign(a, n) /*< identical to `memalign` */
#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)
/* These are defined in the C23 standard. */
#undef free_sized
#define free_sized(p, n) (free(p), (void)(n))
#undef free_aligned_sized
#define free_aligned_sized(p, a, n) \
(GC_free(p) /* non-debug */, (void)(a), (void)(n))
#undef cfree /*< obsolete */
#if defined(sun) || defined(__sun)
# define cfree(p, m, n) ((void)(m), (void)(n), free(p))
#else
# define cfree(p) free(p)
#endif
#undef _aligned_malloc
#define _aligned_malloc(n, a) GC_memalign(a, n) /*< reverse args order */
#undef _aligned_free
#define _aligned_free(p) GC_free(p) /*< non-debug */
#ifndef GC_NO_VALLOC
# undef valloc
# define valloc(n) GC_valloc(n)
# undef pvalloc
# define pvalloc(n) GC_pvalloc(n) /*< obsolete */
#endif
#undef malloc_usable_size /*< available in `glibc` */
#define malloc_usable_size(p) GC_size(p)
#undef malloc_size /*< available in Darwin */
#define malloc_size(p) GC_size(p)
#undef _msize /*< available in Windows CRT */
#define _msize(p) GC_size(p)
#ifndef CHECK_LEAKS
/**
* Note 1: `CHECK_LEAKS` does not have `GC_` prefix (preserved for
* backward compatibility).
* Note 2: `GC_gcollect()` is also called automatically in the
* find-leak mode at program exit.
*/
# define CHECK_LEAKS() GC_gcollect()
#endif
#endif /* GC_LEAK_DETECTOR_H */