mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	include/ruby/internal/memory.h: add doxygen
Must not be a bad idea to improve documents. [ci skip]
This commit is contained in:
		
							parent
							
								
									00ff6b68e4
								
							
						
					
					
						commit
						4397e737c5
					
				
				
				Notes:
				
					git
				
				2021-09-10 20:01:50 +09:00 
				
			
			
			
		
		
					 1 changed files with 408 additions and 19 deletions
				
			
		| 
						 | 
				
			
			@ -62,6 +62,8 @@
 | 
			
		|||
#include "ruby/backward/2/assume.h"
 | 
			
		||||
#include "ruby/defines.h"
 | 
			
		||||
 | 
			
		||||
/** @cond INTENAL_MACRO  */
 | 
			
		||||
 | 
			
		||||
/* Make alloca work the best possible way.  */
 | 
			
		||||
#if defined(alloca)
 | 
			
		||||
# /* Take that. */
 | 
			
		||||
| 
						 | 
				
			
			@ -75,18 +77,86 @@ extern "C" void *alloca(size_t);
 | 
			
		|||
extern void *alloca();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(HAVE_INT128_T) && SIZEOF_SIZE_T <= 8
 | 
			
		||||
/** @endcond  */
 | 
			
		||||
 | 
			
		||||
#if defined(__DOXYGEN__)
 | 
			
		||||
/**
 | 
			
		||||
 * @private
 | 
			
		||||
 *
 | 
			
		||||
 * Type that is as twice wider as  size_t.  This is an implementation detail of
 | 
			
		||||
 * rb_mul_size_overflow().  People should not use it.   This is not a good name
 | 
			
		||||
 * either.
 | 
			
		||||
 */
 | 
			
		||||
typedef uint128_t DSIZE_T;
 | 
			
		||||
#elif defined(HAVE_INT128_T) && SIZEOF_SIZE_T <= 8
 | 
			
		||||
# define DSIZE_T uint128_t
 | 
			
		||||
#elif SIZEOF_SIZE_T * 2 <= SIZEOF_LONG_LONG
 | 
			
		||||
# define DSIZE_T unsigned LONG_LONG
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @private
 | 
			
		||||
 *
 | 
			
		||||
 * Maximum  possible  number  of  bytes  that  #RB_ALLOCV  can  allocate  using
 | 
			
		||||
 * `alloca`.  Anything  beyond this  is allocated  using rb_alloc_tmp_buffer().
 | 
			
		||||
 * This selection is transparent to users.  People don't have to bother.
 | 
			
		||||
 */
 | 
			
		||||
#ifdef C_ALLOCA
 | 
			
		||||
# define RUBY_ALLOCV_LIMIT 0
 | 
			
		||||
#else
 | 
			
		||||
# define RUBY_ALLOCV_LIMIT 1024
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Prevents premature  destruction of local objects.   Ruby's garbage collector
 | 
			
		||||
 * is conservative; it  scans the C level machine stack  as well.  Possible in-
 | 
			
		||||
 * use Ruby  objects must  remain visible  on stack, to  be properly  marked as
 | 
			
		||||
 * such.  However  contemporary C  compilers do not  interface well  with this.
 | 
			
		||||
 * Consider the following example:
 | 
			
		||||
 *
 | 
			
		||||
 * ```CXX
 | 
			
		||||
 * auto s = rb_str_new_cstr(" world");
 | 
			
		||||
 * auto sptr = RSTRING_PTR(s);
 | 
			
		||||
 * auto t = rb_str_new_cstr("hello,"); // Possible GC invocation
 | 
			
		||||
 * auto u = rb_str_cat_cstr(t, sptr);
 | 
			
		||||
 *
 | 
			
		||||
 * RB_GC_GUARD(s); // ensure `s` (and thus `sptr`) do not get GC-ed
 | 
			
		||||
 * ```
 | 
			
		||||
 *
 | 
			
		||||
 * Here, without the #RB_GC_GUARD, the last use of `s` is _before_ the last use
 | 
			
		||||
 * of `sptr`.  Compilers  could thus think `s` and `t`  are allowed to overlap.
 | 
			
		||||
 * That would eliminate `s`  from the stack, while `sptr` is  still in use.  If
 | 
			
		||||
 * our GC  ran at  that very moment,  `s` gets swept  out, which  also destroys
 | 
			
		||||
 * `sptr`.  Boom!  You got a SEGV.
 | 
			
		||||
 *
 | 
			
		||||
 * In order  to prevent this scenario  #RB_GC_GUARD must be placed  _after_ the
 | 
			
		||||
 * last use of `sptr`.  Placing  #RB_GC_GUARD before dereferencing `sptr` would
 | 
			
		||||
 * be of no use.
 | 
			
		||||
 *
 | 
			
		||||
 * #RB_GC_GUARD would  not be  necessary at  all in the  above example  if non-
 | 
			
		||||
 * inlined  function  calls are  made  on  the  `s`  variable after  `sptr`  is
 | 
			
		||||
 * dereferenced.  Thus, in  the above example, calling  any un-inlined function
 | 
			
		||||
 * on `s`  such as `rb_str_modify(s);`  will ensure `s`  stays on the  stack or
 | 
			
		||||
 * register to prevent a GC invocation from prematurely freeing it.
 | 
			
		||||
 *
 | 
			
		||||
 * Using the #RB_GC_GUARD  macro is preferable to using  the `volatile` keyword
 | 
			
		||||
 * in C.  #RB_GC_GUARD has the following advantages:
 | 
			
		||||
 *
 | 
			
		||||
 *  - the intent of the macro use is clear.
 | 
			
		||||
 *
 | 
			
		||||
 *  - #RB_GC_GUARD only affects its call  site.  OTOH `volatile` generates some
 | 
			
		||||
 *    extra code every time the variable is used, hurting optimisation.
 | 
			
		||||
 *
 | 
			
		||||
 *  - `volatile` implementations  may be  buggy/inconsistent in  some compilers
 | 
			
		||||
 *    and   architectures.     #RB_GC_GUARD   is   customisable    for   broken
 | 
			
		||||
 *    systems/compilers without negatively affecting other systems.
 | 
			
		||||
 *
 | 
			
		||||
 *  - C++  since C++20  deprecates  `volatile`.  If  you  write your  extension
 | 
			
		||||
 *    library in that language there is no escape but to use this macro.
 | 
			
		||||
 *
 | 
			
		||||
 * @param  v  A variable of ::VALUE type.
 | 
			
		||||
 * @post   `v` is still alive.
 | 
			
		||||
 */
 | 
			
		||||
#ifdef __GNUC__
 | 
			
		||||
#define RB_GC_GUARD(v) \
 | 
			
		||||
    (*__extension__ ({ \
 | 
			
		||||
| 
						 | 
				
			
			@ -101,65 +171,316 @@ extern void *alloca();
 | 
			
		|||
#define RB_GC_GUARD(v) (*rb_gc_guarded_ptr_val(&(v),(v)))
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Casts needed because void* is NOT compaible with others in C++. */
 | 
			
		||||
/* Casts needed because void* is NOT compatible with others in C++. */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Convenient macro that allocates an array of n elements.
 | 
			
		||||
 *
 | 
			
		||||
 * @param      type            Type of array elements.
 | 
			
		||||
 * @param      n               Length of the array.
 | 
			
		||||
 * @exception  rb_eNoMemError  No space left for allocation.
 | 
			
		||||
 * @exception  rb_eArgError    Integer overflow trying  to calculate the length
 | 
			
		||||
 *                             of continuous  memory region of `n`  elements of
 | 
			
		||||
 *                             `type`.
 | 
			
		||||
 * @return     Storage  instance  that  is  capable of  storing  at  least  `n`
 | 
			
		||||
 *             elements of type `type`.
 | 
			
		||||
 * @note       It doesn't return NULL, even when `n` is zero.
 | 
			
		||||
 * @warning    The return  value shall  be invalidated  exactly once  by either
 | 
			
		||||
 *             ruby_xfree(),  ruby_xrealloc(), or  ruby_xrealloc2().   It is  a
 | 
			
		||||
 *             failure to pass it to system free(), because the system and Ruby
 | 
			
		||||
 *             might or might not share the same malloc() implementation.
 | 
			
		||||
 */
 | 
			
		||||
#define RB_ALLOC_N(type,n)  RBIMPL_CAST((type *)ruby_xmalloc2((n), sizeof(type)))
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Shorthand of #RB_ALLOC_N with `n=1`.
 | 
			
		||||
 *
 | 
			
		||||
 * @param      type            Type of allocation.
 | 
			
		||||
 * @exception  rb_eNoMemError  No space left for allocation.
 | 
			
		||||
 * @return     Storage instance that can hold an `type` object.
 | 
			
		||||
 * @note       It doesn't return NULL.
 | 
			
		||||
 * @warning    The return  value shall  be invalidated  exactly once  by either
 | 
			
		||||
 *             ruby_xfree(),  ruby_xrealloc(), or  ruby_xrealloc2().   It is  a
 | 
			
		||||
 *             failure to pass it to system free(), because the system and Ruby
 | 
			
		||||
 *             might or might not share the same malloc() implementation.
 | 
			
		||||
 */
 | 
			
		||||
#define RB_ALLOC(type)      RBIMPL_CAST((type *)ruby_xmalloc(sizeof(type)))
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Identical to  #RB_ALLOC_N() but also  nullifies the allocated  region before
 | 
			
		||||
 * returning.
 | 
			
		||||
 *
 | 
			
		||||
 * @param      type            Type of array elements.
 | 
			
		||||
 * @param      n               Length of the array.
 | 
			
		||||
 * @exception  rb_eNoMemError  No space left for allocation.
 | 
			
		||||
 * @exception  rb_eArgError    Integer overflow trying  to calculate the length
 | 
			
		||||
 *                             of continuous  memory region of `n`  elements of
 | 
			
		||||
 *                             `type`.
 | 
			
		||||
 * @return     Storage  instance  that  is  capable of  storing  at  least  `n`
 | 
			
		||||
 *             elements of type `type`.
 | 
			
		||||
 * @post       Returned array is filled with zeros.
 | 
			
		||||
 * @note       It doesn't return NULL, even when `n` is zero.
 | 
			
		||||
 * @warning    The return  value shall  be invalidated  exactly once  by either
 | 
			
		||||
 *             ruby_xfree(),  ruby_xrealloc(), or  ruby_xrealloc2().   It is  a
 | 
			
		||||
 *             failure to pass it to system free(), because the system and Ruby
 | 
			
		||||
 *             might or might not share the same malloc() implementation.
 | 
			
		||||
 */
 | 
			
		||||
#define RB_ZALLOC_N(type,n) RBIMPL_CAST((type *)ruby_xcalloc((n), sizeof(type)))
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Shorthand of #RB_ZALLOC_N with `n=1`.
 | 
			
		||||
 *
 | 
			
		||||
 * @param      type            Type of allocation.
 | 
			
		||||
 * @exception  rb_eNoMemError  No space left for allocation.
 | 
			
		||||
 * @return     Storage instance that can hold an `type` object.
 | 
			
		||||
 * @post       Returned object is filled with zeros.
 | 
			
		||||
 * @note       It doesn't return NULL.
 | 
			
		||||
 * @warning    The return  value shall  be invalidated  exactly once  by either
 | 
			
		||||
 *             ruby_xfree(),  ruby_xrealloc(), or  ruby_xrealloc2().   It is  a
 | 
			
		||||
 *             failure to pass it to system free(), because the system and Ruby
 | 
			
		||||
 *             might or might not share the same malloc() implementation.
 | 
			
		||||
 */
 | 
			
		||||
#define RB_ZALLOC(type)     (RB_ZALLOC_N(type, 1))
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Convenient macro that reallocates an array with a new size.
 | 
			
		||||
 *
 | 
			
		||||
 * @param      var             A variable of `type`,  which points to a storage
 | 
			
		||||
 *                             instance  that  was   previously  returned  from
 | 
			
		||||
 *                             either
 | 
			
		||||
 *                               - ruby_xmalloc(),
 | 
			
		||||
 *                               - ruby_xmalloc2(),
 | 
			
		||||
 *                               - ruby_xcalloc(),
 | 
			
		||||
 *                               - ruby_xrealloc(), or
 | 
			
		||||
 *                               - ruby_xrealloc2().
 | 
			
		||||
 * @param      type            Type of allocation.
 | 
			
		||||
 * @param      n               Requested new size of each element.
 | 
			
		||||
 * @exception  rb_eNoMemError  No space left for  allocation.
 | 
			
		||||
 * @exception  rb_eArgError    Integer overflow trying  to calculate the length
 | 
			
		||||
 *                             of continuous  memory region of `n`  elements of
 | 
			
		||||
 *                             `type`.
 | 
			
		||||
 * @return     Storage  instance  that  is  capable of  storing  at  least  `n`
 | 
			
		||||
 *             elements of type `type`.
 | 
			
		||||
 * @pre        The passed variable must point to a valid live storage instance.
 | 
			
		||||
 *             It is a  failure to pass a variable that  holds an already-freed
 | 
			
		||||
 *             pointer.
 | 
			
		||||
 * @note       It doesn't return NULL, even when `n` is zero.
 | 
			
		||||
 * @warning    Do not  assume anything  on the alignment  of the  return value.
 | 
			
		||||
 *             There is  no guarantee  that it  inherits the  passed argument's
 | 
			
		||||
 *             one.
 | 
			
		||||
 * @warning    The return  value shall  be invalidated  exactly once  by either
 | 
			
		||||
 *             ruby_xfree(),  ruby_xrealloc(), or  ruby_xrealloc2().   It is  a
 | 
			
		||||
 *             failure to pass it to system free(), because the system and Ruby
 | 
			
		||||
 *             might or might not share the same malloc() implementation.
 | 
			
		||||
 */
 | 
			
		||||
#define RB_REALLOC_N(var,type,n) \
 | 
			
		||||
    ((var) = RBIMPL_CAST((type *)ruby_xrealloc2((void *)(var), (n), sizeof(type))))
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @deprecated  This  macro is  dangerous (does  not bother  stack overflow  at
 | 
			
		||||
 *              all).  #RB_ALLOCV is the modern way to do the same thing.
 | 
			
		||||
 * @param       type  Type of array elements.
 | 
			
		||||
 * @param       n     Length of the array.
 | 
			
		||||
 * @return      A pointer on stack.
 | 
			
		||||
 */
 | 
			
		||||
#define ALLOCA_N(type,n) \
 | 
			
		||||
    RBIMPL_CAST((type *)alloca(rbimpl_size_mul_or_raise(sizeof(type), (n))))
 | 
			
		||||
 | 
			
		||||
/* allocates _n_ bytes temporary buffer and stores VALUE including it
 | 
			
		||||
 * in _v_.  _n_ may be evaluated twice. */
 | 
			
		||||
/**
 | 
			
		||||
 * Identical to #RB_ALLOCV_N(), except it  implicitly assumes the type of array
 | 
			
		||||
 * is ::VALUE.
 | 
			
		||||
 *
 | 
			
		||||
 * @param   v  A variable to hold the just-in-case opaque Ruby object.
 | 
			
		||||
 * @param   n  Size of allocation, in bytes.
 | 
			
		||||
 * @return  An array of `n` bytes of ::VALUE.
 | 
			
		||||
 * @note    `n` may be evaluated twice.
 | 
			
		||||
 */
 | 
			
		||||
#define RB_ALLOCV(v, n)        \
 | 
			
		||||
    ((n) < RUBY_ALLOCV_LIMIT ? \
 | 
			
		||||
     ((v) = 0, alloca(n)) :    \
 | 
			
		||||
     rb_alloc_tmp_buffer(&(v), (n)))
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Allocates a  memory region, possibly  on stack.   If the given  size exceeds
 | 
			
		||||
 * #RUBY_ALLOCV_LIMIT, it allocates a dedicated  opaque ruby object instead and
 | 
			
		||||
 * let our GC sweep that region after use.  Either way you can fire-and-forget.
 | 
			
		||||
 *
 | 
			
		||||
 * ```CXX
 | 
			
		||||
 * #include <sys/types.h>
 | 
			
		||||
 *
 | 
			
		||||
 * VALUE
 | 
			
		||||
 * foo(int n)
 | 
			
		||||
 * {
 | 
			
		||||
 *     VALUE v;
 | 
			
		||||
 *     auto ptr = RB_ALLOCV(struct tms, v, n);
 | 
			
		||||
 *     ...
 | 
			
		||||
 *     // no need to free `ptr`.
 | 
			
		||||
 * }
 | 
			
		||||
 * ```
 | 
			
		||||
 *
 | 
			
		||||
 * If you want to  be super-duper polite you can also  explicitly state the end
 | 
			
		||||
 * of use of such memory region by calling #RB_ALLOCV_END().
 | 
			
		||||
 *
 | 
			
		||||
 * @param   type  The type of array elements.
 | 
			
		||||
 * @param   v     A variable to hold the just-in-case opaque Ruby object.
 | 
			
		||||
 * @param   n     Number of elements requested to allocate.
 | 
			
		||||
 * @return  An array of `n` elements of `type`.
 | 
			
		||||
 * @note    `n` may be evaluated twice.
 | 
			
		||||
 */
 | 
			
		||||
#define RB_ALLOCV_N(type, v, n)                             \
 | 
			
		||||
    RBIMPL_CAST((type *)                                     \
 | 
			
		||||
        (((size_t)(n) < RUBY_ALLOCV_LIMIT / sizeof(type)) ? \
 | 
			
		||||
         ((v) = 0, alloca((n) * sizeof(type))) :            \
 | 
			
		||||
         rb_alloc_tmp_buffer2(&(v), (n), sizeof(type))))
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Polite way to declare that the given  array is not used any longer.  Calling
 | 
			
		||||
 * this not mandatory.  Our GC can baby-sit  you.  However it is not a very bad
 | 
			
		||||
 * idea to use it when possible.  Doing so could reduce memory footprint.
 | 
			
		||||
 *
 | 
			
		||||
 * @param  v  A variable previously passed to either #RB_ALLOCV/#RB_ALLOCV_N.
 | 
			
		||||
 */
 | 
			
		||||
#define RB_ALLOCV_END(v) rb_free_tmp_buffer(&(v))
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Handy macro to erase a region of memory.
 | 
			
		||||
 *
 | 
			
		||||
 * @param   p     Target pointer.
 | 
			
		||||
 * @param   type  Type of `p[0]`
 | 
			
		||||
 * @param   n     Length of `p`.
 | 
			
		||||
 * @return  `p`.
 | 
			
		||||
 * @post    First `n` elements of `p` are squashed.
 | 
			
		||||
 */
 | 
			
		||||
#define MEMZERO(p,type,n) memset((p), 0, rbimpl_size_mul_or_raise(sizeof(type), (n)))
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Handy macro to call memcpy.
 | 
			
		||||
 *
 | 
			
		||||
 * @param   p1    Destination pointer.
 | 
			
		||||
 * @param   p2    Source pointer.
 | 
			
		||||
 * @param   type  Type of `p2[0]`
 | 
			
		||||
 * @param   n     Length of `p2`.
 | 
			
		||||
 * @return  `p1`.
 | 
			
		||||
 * @post    First `n` elements of `p2` are copied into `p1`.
 | 
			
		||||
 */
 | 
			
		||||
#define MEMCPY(p1,p2,type,n) memcpy((p1), (p2), rbimpl_size_mul_or_raise(sizeof(type), (n)))
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Handy macro to call memmove.
 | 
			
		||||
 *
 | 
			
		||||
 * @param  p1    Destination pointer.
 | 
			
		||||
 * @param  p2    Source pointer.
 | 
			
		||||
 * @param  type  Type of `p2[0]`
 | 
			
		||||
 * @param  n     Length of `p2`.
 | 
			
		||||
 * @return `p1`.
 | 
			
		||||
 * @post   First `n` elements of `p2` are copied into `p1`.
 | 
			
		||||
 */
 | 
			
		||||
#define MEMMOVE(p1,p2,type,n) memmove((p1), (p2), rbimpl_size_mul_or_raise(sizeof(type), (n)))
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Handy macro to call memcmp
 | 
			
		||||
 *
 | 
			
		||||
 * @param   p1    Target LHS.
 | 
			
		||||
 * @param   p2    Target RHS.
 | 
			
		||||
 * @param   type  Type of `p1[0]`
 | 
			
		||||
 * @param   n     Length of `p1`.
 | 
			
		||||
 * @retval  <0    `p1` is "less" than `p2`.
 | 
			
		||||
 * @retval  0     `p1` is equal to `p2`.
 | 
			
		||||
 * @retval  >0    `p1` is "greater" than `p2`.
 | 
			
		||||
 */
 | 
			
		||||
#define MEMCMP(p1,p2,type,n) memcmp((p1), (p2), rbimpl_size_mul_or_raise(sizeof(type), (n)))
 | 
			
		||||
 | 
			
		||||
#define ALLOC_N    RB_ALLOC_N
 | 
			
		||||
#define ALLOC      RB_ALLOC
 | 
			
		||||
#define ZALLOC_N   RB_ZALLOC_N
 | 
			
		||||
#define ZALLOC     RB_ZALLOC
 | 
			
		||||
#define REALLOC_N  RB_REALLOC_N
 | 
			
		||||
#define ALLOCV     RB_ALLOCV
 | 
			
		||||
#define ALLOCV_N   RB_ALLOCV_N
 | 
			
		||||
#define ALLOCV_END RB_ALLOCV_END
 | 
			
		||||
#define ALLOC_N    RB_ALLOC_N    /**< @old{RB_ALLOC_N} */
 | 
			
		||||
#define ALLOC      RB_ALLOC      /**< @old{RB_ALLOC} */
 | 
			
		||||
#define ZALLOC_N   RB_ZALLOC_N   /**< @old{RB_ZALLOC_N} */
 | 
			
		||||
#define ZALLOC     RB_ZALLOC     /**< @old{RB_ZALLOC} */
 | 
			
		||||
#define REALLOC_N  RB_REALLOC_N  /**< @old{RB_REALLOC_N} */
 | 
			
		||||
#define ALLOCV     RB_ALLOCV     /**< @old{RB_ALLOCV} */
 | 
			
		||||
#define ALLOCV_N   RB_ALLOCV_N   /**< @old{RB_ALLOCV_N} */
 | 
			
		||||
#define ALLOCV_END RB_ALLOCV_END /**< @old{RB_ALLOCV_END} */
 | 
			
		||||
 | 
			
		||||
/* Expecting this struct to be eliminated by function inlinings */
 | 
			
		||||
/**
 | 
			
		||||
 * @private
 | 
			
		||||
 *
 | 
			
		||||
 * This is an implementation detail of rbimpl_size_mul_overflow().
 | 
			
		||||
 *
 | 
			
		||||
 * @internal
 | 
			
		||||
 *
 | 
			
		||||
 * Expecting  this struct  to be  eliminated  by function  inlinings.  This  is
 | 
			
		||||
 * nothing more than std::variant<std::size_t> if  we could use recent C++, but
 | 
			
		||||
 * reality is we cannot.
 | 
			
		||||
 */
 | 
			
		||||
struct rbimpl_size_mul_overflow_tag {
 | 
			
		||||
    bool left;
 | 
			
		||||
    size_t right;
 | 
			
		||||
    bool left;                  /**< Whether overflow happened or not. */
 | 
			
		||||
    size_t right;               /**< Multiplication result. */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
RBIMPL_SYMBOL_EXPORT_BEGIN()
 | 
			
		||||
RBIMPL_ATTR_RESTRICT()
 | 
			
		||||
RBIMPL_ATTR_RETURNS_NONNULL()
 | 
			
		||||
RBIMPL_ATTR_ALLOC_SIZE((2))
 | 
			
		||||
RBIMPL_ATTR_NONNULL(())
 | 
			
		||||
/**
 | 
			
		||||
 * @private
 | 
			
		||||
 *
 | 
			
		||||
 * This is  an implementation  detail of #RB_ALLOCV().   People don't  use this
 | 
			
		||||
 * directly.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[out]  store  Pointer to a variable.
 | 
			
		||||
 * @param[in]   len    Requested number of bytes to allocate.
 | 
			
		||||
 * @return      Allocated `len` bytes array.
 | 
			
		||||
 * @post        `store` holds the corresponding tmp buffer object.
 | 
			
		||||
 */
 | 
			
		||||
void *rb_alloc_tmp_buffer(volatile VALUE *store, long len);
 | 
			
		||||
 | 
			
		||||
RBIMPL_ATTR_RESTRICT()
 | 
			
		||||
RBIMPL_ATTR_RETURNS_NONNULL()
 | 
			
		||||
RBIMPL_ATTR_ALLOC_SIZE((2,3))
 | 
			
		||||
RBIMPL_ATTR_NONNULL(())
 | 
			
		||||
/**
 | 
			
		||||
 * @private
 | 
			
		||||
 *
 | 
			
		||||
 * This is an  implementation detail of #RB_ALLOCV_N().  People  don't use this
 | 
			
		||||
 * directly.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[out]  store  Pointer to a variable.
 | 
			
		||||
 * @param[in]   len    Requested number of bytes to allocate.
 | 
			
		||||
 * @param[in]   count  Number of elements in an array.
 | 
			
		||||
 * @return      Allocated `len` bytes array.
 | 
			
		||||
 * @post        `store` holds the corresponding tmp buffer object.
 | 
			
		||||
 *
 | 
			
		||||
 * @internal
 | 
			
		||||
 *
 | 
			
		||||
 * Although  the  meaning  of  `count` variable  is  clear,  @shyouhei  doesn't
 | 
			
		||||
 * understand its needs.
 | 
			
		||||
 */
 | 
			
		||||
void *rb_alloc_tmp_buffer_with_count(volatile VALUE *store, size_t len,size_t count);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @private
 | 
			
		||||
 *
 | 
			
		||||
 * This is an implementation detail of #RB_ALLOCV_END().  People don't use this
 | 
			
		||||
 * directly.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[out]  store  Pointer to a variable.
 | 
			
		||||
 * @pre         `store` is a NULL, or a pointer to a tmp buffer object.
 | 
			
		||||
 * @post        `*store` is ::RUBY_Qfalse.
 | 
			
		||||
 * @post        The object formerly stored in `store` is destroyed.
 | 
			
		||||
 */
 | 
			
		||||
void rb_free_tmp_buffer(volatile VALUE *store);
 | 
			
		||||
 | 
			
		||||
RBIMPL_ATTR_NORETURN()
 | 
			
		||||
void ruby_malloc_size_overflow(size_t, size_t);
 | 
			
		||||
/**
 | 
			
		||||
 * @private
 | 
			
		||||
 *
 | 
			
		||||
 * This is an  implementation detail of #RB_ALLOCV_N().  People  don't use this
 | 
			
		||||
 * directly.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in]  x             Arbitrary value.
 | 
			
		||||
 * @param[in]  y             Arbitrary value.
 | 
			
		||||
 * @exception  rb_eArgError  `x` * `y` would integer overflow.
 | 
			
		||||
 */
 | 
			
		||||
void ruby_malloc_size_overflow(size_t x, size_t y);
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_RB_GC_GUARDED_PTR_VAL
 | 
			
		||||
volatile VALUE *rb_gc_guarded_ptr_val(volatile VALUE *ptr, VALUE val);
 | 
			
		||||
| 
						 | 
				
			
			@ -169,6 +490,15 @@ RBIMPL_SYMBOL_EXPORT_END()
 | 
			
		|||
#ifdef _MSC_VER
 | 
			
		||||
# pragma optimize("", off)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @private
 | 
			
		||||
 *
 | 
			
		||||
 * This is an  implementation detail of #RB_GC_GUARD().  People  don't use this
 | 
			
		||||
 * directly.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in]  ptr  A pointer to an on-stack C variable.
 | 
			
		||||
 * @return     `ptr` as-is.
 | 
			
		||||
 */
 | 
			
		||||
static inline volatile VALUE *
 | 
			
		||||
rb_gc_guarded_ptr(volatile VALUE *ptr)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -178,7 +508,19 @@ rb_gc_guarded_ptr(volatile VALUE *ptr)
 | 
			
		|||
# pragma optimize("", on)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Does anyone use it?  Just here for backwards compatibility. */
 | 
			
		||||
/**
 | 
			
		||||
 * @deprecated  This   function   was   an   implementation   detail   of   old
 | 
			
		||||
 *              #RB_ALLOCV_N().  We no longer  use it.  @shyouhei suspects that
 | 
			
		||||
 *              there are  no actual usage now.   However it was not  marked as
 | 
			
		||||
 *              private before.  We cannot delete it any longer.
 | 
			
		||||
 * @param[in]   a    Arbitrary value.
 | 
			
		||||
 * @param[in]   b    Arbitrary value.
 | 
			
		||||
 * @param[in]   max  Possible maximum value.
 | 
			
		||||
 * @param[out]  c    A pointer to return the computation result.
 | 
			
		||||
 * @retval      1    `c` is insane.
 | 
			
		||||
 * @retval      0    `c` is sane.
 | 
			
		||||
 * @post        `c` holds `a` * `b`, but could be overflowed.
 | 
			
		||||
 */
 | 
			
		||||
static inline int
 | 
			
		||||
rb_mul_size_overflow(size_t a, size_t b, size_t max, size_t *c)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -196,12 +538,30 @@ rb_mul_size_overflow(size_t a, size_t b, size_t max, size_t *c)
 | 
			
		|||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if RBIMPL_COMPILER_SINCE(GCC, 7, 0, 0)
 | 
			
		||||
#if defined(__DOXYGEN__)
 | 
			
		||||
RBIMPL_ATTR_CONSTEXPR(CXX14)
 | 
			
		||||
#elif RBIMPL_COMPILER_SINCE(GCC, 7, 0, 0)
 | 
			
		||||
RBIMPL_ATTR_CONSTEXPR(CXX14) /* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70507 */
 | 
			
		||||
#elif RBIMPL_COMPILER_SINCE(Clang, 7, 0, 0)
 | 
			
		||||
RBIMPL_ATTR_CONSTEXPR(CXX14) /* https://bugs.llvm.org/show_bug.cgi?id=37633 */
 | 
			
		||||
#endif
 | 
			
		||||
RBIMPL_ATTR_CONST()
 | 
			
		||||
/**
 | 
			
		||||
 * @private
 | 
			
		||||
 *
 | 
			
		||||
 * This is an  implementation detail of #RB_ALLOCV_N().  People  don't use this
 | 
			
		||||
 * directly.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in]  x  Arbitrary value.
 | 
			
		||||
 * @param[in]  y  Arbitrary value.
 | 
			
		||||
 * @return     `{ left, right }`,  where `left` is whether there  is an integer
 | 
			
		||||
 *             overflow or not,  and `right` is a  (possibly overflowed) result
 | 
			
		||||
 *             of `x` * `y`.
 | 
			
		||||
 *
 | 
			
		||||
 * @internal
 | 
			
		||||
 *
 | 
			
		||||
 * This is in fact also an implementation detail of ruby_xmalloc2() etc.
 | 
			
		||||
 */
 | 
			
		||||
static inline struct rbimpl_size_mul_overflow_tag
 | 
			
		||||
rbimpl_size_mul_overflow(size_t x, size_t y)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -232,6 +592,21 @@ rbimpl_size_mul_overflow(size_t x, size_t y)
 | 
			
		|||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @private
 | 
			
		||||
 *
 | 
			
		||||
 * This is an  implementation detail of #RB_ALLOCV_N().  People  don't use this
 | 
			
		||||
 * directly.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in]  x             Arbitrary value.
 | 
			
		||||
 * @param[in]  y             Arbitrary value.
 | 
			
		||||
 * @exception  rb_eArgError  Multiplication could integer overflow.
 | 
			
		||||
 * @return     `x` * `y`.
 | 
			
		||||
 *
 | 
			
		||||
 * @internal
 | 
			
		||||
 *
 | 
			
		||||
 * This is in fact also an implementation detail of ruby_xmalloc2() etc.
 | 
			
		||||
 */
 | 
			
		||||
static inline size_t
 | 
			
		||||
rbimpl_size_mul_or_raise(size_t x, size_t y)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -247,6 +622,20 @@ rbimpl_size_mul_or_raise(size_t x, size_t y)
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This is an  implementation detail of #RB_ALLOCV_N().  People  don't use this
 | 
			
		||||
 * directly.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[out]  store   Pointer to a variable.
 | 
			
		||||
 * @param[in]   count   Number of elements in an array.
 | 
			
		||||
 * @param[in]   elsize  Size of each elements.
 | 
			
		||||
 * @return      Region of `count` * `elsize` bytes.
 | 
			
		||||
 * @post        `store` holds the corresponding tmp buffer object.
 | 
			
		||||
 *
 | 
			
		||||
 * @internal
 | 
			
		||||
 *
 | 
			
		||||
 * We might want to deprecate this function and make a `rbimpl_` counterpart.
 | 
			
		||||
 */
 | 
			
		||||
static inline void *
 | 
			
		||||
rb_alloc_tmp_buffer2(volatile VALUE *store, long count, size_t elsize)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -255,7 +644,7 @@ rb_alloc_tmp_buffer2(volatile VALUE *store, long count, size_t elsize)
 | 
			
		|||
    return rb_alloc_tmp_buffer_with_count(store, total_size, cnt);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifndef __MINGW32__
 | 
			
		||||
#if ! defined(__MINGW32__) && ! defined(__DOXYGEN__)
 | 
			
		||||
RBIMPL_SYMBOL_EXPORT_BEGIN()
 | 
			
		||||
RBIMPL_ATTR_NOALIAS()
 | 
			
		||||
RBIMPL_ATTR_NONNULL((1))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue