diff options
Diffstat (limited to 'include/ruby')
53 files changed, 954 insertions, 791 deletions
diff --git a/include/ruby/atomic.h b/include/ruby/atomic.h index 2f5090e62f..fcc48f532c 100644 --- a/include/ruby/atomic.h +++ b/include/ruby/atomic.h @@ -34,7 +34,7 @@ # include <sys/types.h> /* ssize_t */ #endif -#if RBIMPL_COMPILER_SINCE(MSVC, 13, 0, 0) +#if RBIMPL_COMPILER_IS(MSVC) # pragma intrinsic(_InterlockedOr) #elif defined(__sun) && defined(HAVE_ATOMIC_H) # include <atomic.h> @@ -77,10 +77,35 @@ typedef unsigned int rb_atomic_t; typedef LONG rb_atomic_t; #elif defined(__sun) && defined(HAVE_ATOMIC_H) typedef unsigned int rb_atomic_t; +#elif defined(HAVE_STDATOMIC_H) +# include <stdatomic.h> +typedef unsigned int rb_atomic_t; #else # error No atomic operation found #endif +/* Memory ordering constants */ +#if defined(HAVE_GCC_ATOMIC_BUILTINS) +# define RBIMPL_ATOMIC_RELAXED __ATOMIC_RELAXED +# define RBIMPL_ATOMIC_ACQUIRE __ATOMIC_ACQUIRE +# define RBIMPL_ATOMIC_RELEASE __ATOMIC_RELEASE +# define RBIMPL_ATOMIC_ACQ_REL __ATOMIC_ACQ_REL +# define RBIMPL_ATOMIC_SEQ_CST __ATOMIC_SEQ_CST +#elif defined(HAVE_STDATOMIC_H) +# define RBIMPL_ATOMIC_RELAXED memory_order_relaxed +# define RBIMPL_ATOMIC_ACQUIRE memory_order_acquire +# define RBIMPL_ATOMIC_RELEASE memory_order_release +# define RBIMPL_ATOMIC_ACQ_REL memory_order_acq_rel +# define RBIMPL_ATOMIC_SEQ_CST memory_order_seq_cst +#else +/* Dummy values for unsupported platforms */ +# define RBIMPL_ATOMIC_RELAXED 0 +# define RBIMPL_ATOMIC_ACQUIRE 1 +# define RBIMPL_ATOMIC_RELEASE 2 +# define RBIMPL_ATOMIC_ACQ_REL 3 +# define RBIMPL_ATOMIC_SEQ_CST 4 +#endif + /** * Atomically replaces the value pointed by `var` with the result of addition * of `val` to the old value of `var`. @@ -90,7 +115,7 @@ typedef unsigned int rb_atomic_t; * @return What was stored in `var` before the addition. * @post `var` holds `var + val`. */ -#define RUBY_ATOMIC_FETCH_ADD(var, val) rbimpl_atomic_fetch_add(&(var), (val)) +#define RUBY_ATOMIC_FETCH_ADD(var, val) rbimpl_atomic_fetch_add(&(var), (val), RBIMPL_ATOMIC_SEQ_CST) /** * Atomically replaces the value pointed by `var` with the result of @@ -101,7 +126,7 @@ typedef unsigned int rb_atomic_t; * @return What was stored in `var` before the subtraction. * @post `var` holds `var - val`. */ -#define RUBY_ATOMIC_FETCH_SUB(var, val) rbimpl_atomic_fetch_sub(&(var), (val)) +#define RUBY_ATOMIC_FETCH_SUB(var, val) rbimpl_atomic_fetch_sub(&(var), (val), RBIMPL_ATOMIC_SEQ_CST) /** * Atomically replaces the value pointed by `var` with the result of @@ -113,7 +138,7 @@ typedef unsigned int rb_atomic_t; * @post `var` holds `var | val`. * @note For portability, this macro can return void. */ -#define RUBY_ATOMIC_OR(var, val) rbimpl_atomic_or(&(var), (val)) +#define RUBY_ATOMIC_OR(var, val) rbimpl_atomic_or(&(var), (val), RBIMPL_ATOMIC_SEQ_CST) /** * Atomically replaces the value pointed by `var` with `val`. This is just an @@ -124,7 +149,7 @@ typedef unsigned int rb_atomic_t; * @return What was stored in `var` before the assignment. * @post `var` holds `val`. */ -#define RUBY_ATOMIC_EXCHANGE(var, val) rbimpl_atomic_exchange(&(var), (val)) +#define RUBY_ATOMIC_EXCHANGE(var, val) rbimpl_atomic_exchange(&(var), (val), RBIMPL_ATOMIC_SEQ_CST) /** * Atomic compare-and-swap. This stores `val` to `var` if and only if the @@ -138,7 +163,7 @@ typedef unsigned int rb_atomic_t; * @retval otherwise Something else is at `var`; not updated. */ #define RUBY_ATOMIC_CAS(var, oldval, newval) \ - rbimpl_atomic_cas(&(var), (oldval), (newval)) + rbimpl_atomic_cas(&(var), (oldval), (newval), RBIMPL_ATOMIC_SEQ_CST, RBIMPL_ATOMIC_SEQ_CST) /** * Atomic load. This loads `var` with an atomic intrinsic and returns @@ -147,7 +172,7 @@ typedef unsigned int rb_atomic_t; * @param var A variable of ::rb_atomic_t * @return What was stored in `var`j */ -#define RUBY_ATOMIC_LOAD(var) rbimpl_atomic_load(&(var)) +#define RUBY_ATOMIC_LOAD(var) rbimpl_atomic_load(&(var), RBIMPL_ATOMIC_SEQ_CST) /** * Identical to #RUBY_ATOMIC_EXCHANGE, except for the return type. @@ -157,7 +182,7 @@ typedef unsigned int rb_atomic_t; * @return void * @post `var` holds `val`. */ -#define RUBY_ATOMIC_SET(var, val) rbimpl_atomic_set(&(var), (val)) +#define RUBY_ATOMIC_SET(var, val) rbimpl_atomic_store(&(var), (val), RBIMPL_ATOMIC_SEQ_CST) /** * Identical to #RUBY_ATOMIC_FETCH_ADD, except for the return type. @@ -167,7 +192,7 @@ typedef unsigned int rb_atomic_t; * @return void * @post `var` holds `var + val`. */ -#define RUBY_ATOMIC_ADD(var, val) rbimpl_atomic_add(&(var), (val)) +#define RUBY_ATOMIC_ADD(var, val) rbimpl_atomic_add(&(var), (val), RBIMPL_ATOMIC_SEQ_CST) /** * Identical to #RUBY_ATOMIC_FETCH_SUB, except for the return type. @@ -177,7 +202,7 @@ typedef unsigned int rb_atomic_t; * @return void * @post `var` holds `var - val`. */ -#define RUBY_ATOMIC_SUB(var, val) rbimpl_atomic_sub(&(var), (val)) +#define RUBY_ATOMIC_SUB(var, val) rbimpl_atomic_sub(&(var), (val), RBIMPL_ATOMIC_SEQ_CST) /** * Atomically increments the value pointed by `var`. @@ -186,7 +211,7 @@ typedef unsigned int rb_atomic_t; * @return void * @post `var` holds `var + 1`. */ -#define RUBY_ATOMIC_INC(var) rbimpl_atomic_inc(&(var)) +#define RUBY_ATOMIC_INC(var) rbimpl_atomic_inc(&(var), RBIMPL_ATOMIC_SEQ_CST) /** * Atomically decrements the value pointed by `var`. @@ -195,7 +220,19 @@ typedef unsigned int rb_atomic_t; * @return void * @post `var` holds `var - 1`. */ -#define RUBY_ATOMIC_DEC(var) rbimpl_atomic_dec(&(var)) +#define RUBY_ATOMIC_DEC(var) rbimpl_atomic_dec(&(var), RBIMPL_ATOMIC_SEQ_CST) + +/** + * Identical to #RUBY_ATOMIC_FETCH_ADD, except it expects its arguments to be `size_t`. + * There are cases where ::rb_atomic_t is 32bit while `size_t` is 64bit. This + * should be used for size related operations to support such platforms. + * + * @param var A variable of `size_t`. + * @param val Value to add. + * @return What was stored in `var` before the addition. + * @post `var` holds `var + val`. + */ +#define RUBY_ATOMIC_SIZE_FETCH_ADD(var, val) rbimpl_atomic_size_fetch_add(&(var), (val), RBIMPL_ATOMIC_SEQ_CST) /** * Identical to #RUBY_ATOMIC_INC, except it expects its argument is `size_t`. @@ -206,7 +243,7 @@ typedef unsigned int rb_atomic_t; * @return void * @post `var` holds `var + 1`. */ -#define RUBY_ATOMIC_SIZE_INC(var) rbimpl_atomic_size_inc(&(var)) +#define RUBY_ATOMIC_SIZE_INC(var) rbimpl_atomic_size_inc(&(var), RBIMPL_ATOMIC_SEQ_CST) /** * Identical to #RUBY_ATOMIC_DEC, except it expects its argument is `size_t`. @@ -217,7 +254,7 @@ typedef unsigned int rb_atomic_t; * @return void * @post `var` holds `var - 1`. */ -#define RUBY_ATOMIC_SIZE_DEC(var) rbimpl_atomic_size_dec(&(var)) +#define RUBY_ATOMIC_SIZE_DEC(var) rbimpl_atomic_size_dec(&(var), RBIMPL_ATOMIC_SEQ_CST) /** * Identical to #RUBY_ATOMIC_EXCHANGE, except it expects its arguments are @@ -231,7 +268,7 @@ typedef unsigned int rb_atomic_t; * @post `var` holds `val`. */ #define RUBY_ATOMIC_SIZE_EXCHANGE(var, val) \ - rbimpl_atomic_size_exchange(&(var), (val)) + rbimpl_atomic_size_exchange(&(var), (val), RBIMPL_ATOMIC_SEQ_CST) /** * Identical to #RUBY_ATOMIC_CAS, except it expects its arguments are `size_t`. @@ -245,7 +282,7 @@ typedef unsigned int rb_atomic_t; * @retval otherwise Something else is at `var`; not updated. */ #define RUBY_ATOMIC_SIZE_CAS(var, oldval, newval) \ - rbimpl_atomic_size_cas(&(var), (oldval), (newval)) + rbimpl_atomic_size_cas(&(var), (oldval), (newval), RBIMPL_ATOMIC_SEQ_CST, RBIMPL_ATOMIC_SEQ_CST) /** * Identical to #RUBY_ATOMIC_ADD, except it expects its arguments are `size_t`. @@ -257,7 +294,7 @@ typedef unsigned int rb_atomic_t; * @return void * @post `var` holds `var + val`. */ -#define RUBY_ATOMIC_SIZE_ADD(var, val) rbimpl_atomic_size_add(&(var), (val)) +#define RUBY_ATOMIC_SIZE_ADD(var, val) rbimpl_atomic_size_add(&(var), (val), RBIMPL_ATOMIC_SEQ_CST) /** * Identical to #RUBY_ATOMIC_SUB, except it expects its arguments are `size_t`. @@ -269,7 +306,7 @@ typedef unsigned int rb_atomic_t; * @return void * @post `var` holds `var - val`. */ -#define RUBY_ATOMIC_SIZE_SUB(var, val) rbimpl_atomic_size_sub(&(var), (val)) +#define RUBY_ATOMIC_SIZE_SUB(var, val) rbimpl_atomic_size_sub(&(var), (val), RBIMPL_ATOMIC_SEQ_CST) /** * Identical to #RUBY_ATOMIC_EXCHANGE, except it expects its arguments are @@ -288,7 +325,7 @@ typedef unsigned int rb_atomic_t; * some pointers, most notably function pointers. */ #define RUBY_ATOMIC_PTR_EXCHANGE(var, val) \ - RBIMPL_CAST(rbimpl_atomic_ptr_exchange((void **)&(var), (void *)val)) + RBIMPL_CAST(rbimpl_atomic_ptr_exchange((void **)&(var), (void *)val, RBIMPL_ATOMIC_SEQ_CST)) /** * Identical to #RUBY_ATOMIC_LOAD, except it expects its arguments are `void*`. @@ -299,7 +336,7 @@ typedef unsigned int rb_atomic_t; * @return The value of `var` (without tearing) */ #define RUBY_ATOMIC_PTR_LOAD(var) \ - RBIMPL_CAST(rbimpl_atomic_ptr_load((void **)&var)) + RBIMPL_CAST(rbimpl_atomic_ptr_load((void **)&var, RBIMPL_ATOMIC_SEQ_CST)) /** * Identical to #RUBY_ATOMIC_SET, except it expects its arguments are @@ -312,7 +349,7 @@ typedef unsigned int rb_atomic_t; * @post `var` holds `val`. */ #define RUBY_ATOMIC_PTR_SET(var, val) \ - rbimpl_atomic_ptr_set((volatile void **)&(var), (val)) + rbimpl_atomic_ptr_store((volatile void **)&(var), (val), RBIMPL_ATOMIC_SEQ_CST) /** * Identical to #RUBY_ATOMIC_CAS, except it expects its arguments are `void*`. @@ -326,7 +363,7 @@ typedef unsigned int rb_atomic_t; * @retval otherwise Something else is at `var`; not updated. */ #define RUBY_ATOMIC_PTR_CAS(var, oldval, newval) \ - RBIMPL_CAST(rbimpl_atomic_ptr_cas((void **)&(var), (void *)(oldval), (void *)(newval))) + RBIMPL_CAST(rbimpl_atomic_ptr_cas((void **)&(var), (void *)(oldval), (void *)(newval), RBIMPL_ATOMIC_SEQ_CST, RBIMPL_ATOMIC_SEQ_CST)) /** * Identical to #RUBY_ATOMIC_SET, except it expects its arguments are @@ -339,7 +376,7 @@ typedef unsigned int rb_atomic_t; * @post `var` holds `val`. */ #define RUBY_ATOMIC_VALUE_SET(var, val) \ - rbimpl_atomic_value_set(&(var), (val)) + rbimpl_atomic_value_store(&(var), (val), RBIMPL_ATOMIC_SEQ_CST) /** * Identical to #RUBY_ATOMIC_EXCHANGE, except it expects its arguments are @@ -353,7 +390,7 @@ typedef unsigned int rb_atomic_t; * @post `var` holds `val`. */ #define RUBY_ATOMIC_VALUE_EXCHANGE(var, val) \ - rbimpl_atomic_value_exchange(&(var), (val)) + rbimpl_atomic_value_exchange(&(var), (val), RBIMPL_ATOMIC_SEQ_CST) /** * Identical to #RUBY_ATOMIC_CAS, except it expects its arguments are ::VALUE. @@ -367,19 +404,20 @@ typedef unsigned int rb_atomic_t; * @retval otherwise Something else is at `var`; not updated. */ #define RUBY_ATOMIC_VALUE_CAS(var, oldval, newval) \ - rbimpl_atomic_value_cas(&(var), (oldval), (newval)) + rbimpl_atomic_value_cas(&(var), (oldval), (newval), RBIMPL_ATOMIC_SEQ_CST, RBIMPL_ATOMIC_SEQ_CST) /** @cond INTERNAL_MACRO */ RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline rb_atomic_t -rbimpl_atomic_fetch_add(volatile rb_atomic_t *ptr, rb_atomic_t val) +rbimpl_atomic_fetch_add(volatile rb_atomic_t *ptr, rb_atomic_t val, int memory_order) { + (void)memory_order; #if 0 #elif defined(HAVE_GCC_ATOMIC_BUILTINS) - return __atomic_fetch_add(ptr, val, __ATOMIC_SEQ_CST); + return __atomic_fetch_add(ptr, val, memory_order); #elif defined(HAVE_GCC_SYNC_BUILTINS) return __sync_fetch_and_add(ptr, val); @@ -396,6 +434,47 @@ rbimpl_atomic_fetch_add(volatile rb_atomic_t *ptr, rb_atomic_t val) RBIMPL_ASSERT_OR_ASSUME(val <= INT_MAX); return atomic_add_int_nv(ptr, val) - val; +#elif defined(HAVE_STDATOMIC_H) + return atomic_fetch_add_explicit((_Atomic volatile rb_atomic_t *)ptr, val, memory_order); + +#else +# error Unsupported platform. +#endif +} + +/** @cond INTERNAL_MACRO */ +RBIMPL_ATTR_ARTIFICIAL() +RBIMPL_ATTR_NOALIAS() +RBIMPL_ATTR_NONNULL((1)) +static inline size_t +rbimpl_atomic_size_fetch_add(volatile size_t *ptr, size_t val, int memory_order) +{ + (void)memory_order; +#if 0 + +#elif defined(HAVE_GCC_ATOMIC_BUILTINS) + return __atomic_fetch_add(ptr, val, memory_order); + +#elif defined(HAVE_GCC_SYNC_BUILTINS) + return __sync_fetch_and_add(ptr, val); + +#elif defined(_WIN32) + return InterlockedExchangeAdd64(ptr, val); + +#elif defined(__sun) && defined(HAVE_ATOMIC_H) && (defined(_LP64) || defined(_I32LPx)) + /* Ditto for `atomic_add_int_nv`. */ + RBIMPL_ASSERT_OR_ASSUME(val <= LONG_MAX); + atomic_add_long(ptr, val); + +#elif defined(__sun) && defined(HAVE_ATOMIC_H) + RBIMPL_STATIC_ASSERT(size_of_rb_atomic_t, sizeof *ptr == sizeof(rb_atomic_t)); + + volatile rb_atomic_t *const tmp = RBIMPL_CAST((volatile rb_atomic_t *)ptr); + rbimpl_atomic_fetch_add(tmp, val, memory_order); + +#elif defined(HAVE_STDATOMIC_H) + return atomic_fetch_add_explicit((_Atomic volatile size_t *)ptr, val, memory_order); + #else # error Unsupported platform. #endif @@ -405,8 +484,9 @@ RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline void -rbimpl_atomic_add(volatile rb_atomic_t *ptr, rb_atomic_t val) +rbimpl_atomic_add(volatile rb_atomic_t *ptr, rb_atomic_t val, int memory_order) { + (void)memory_order; #if 0 #elif defined(HAVE_GCC_ATOMIC_BUILTINS) @@ -415,7 +495,7 @@ rbimpl_atomic_add(volatile rb_atomic_t *ptr, rb_atomic_t val) * return value is not used, then compiles it into single `LOCK ADD` * instruction. */ - __atomic_add_fetch(ptr, val, __ATOMIC_SEQ_CST); + __atomic_add_fetch(ptr, val, memory_order); #elif defined(HAVE_GCC_SYNC_BUILTINS) __sync_add_and_fetch(ptr, val); @@ -433,6 +513,9 @@ rbimpl_atomic_add(volatile rb_atomic_t *ptr, rb_atomic_t val) RBIMPL_ASSERT_OR_ASSUME(val <= INT_MAX); atomic_add_int(ptr, val); +#elif defined(HAVE_STDATOMIC_H) + atomic_fetch_add_explicit((_Atomic volatile rb_atomic_t *)ptr, val, memory_order); + #else # error Unsupported platform. #endif @@ -442,12 +525,13 @@ RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline void -rbimpl_atomic_size_add(volatile size_t *ptr, size_t val) +rbimpl_atomic_size_add(volatile size_t *ptr, size_t val, int memory_order) { + (void)memory_order; #if 0 #elif defined(HAVE_GCC_ATOMIC_BUILTINS) - __atomic_add_fetch(ptr, val, __ATOMIC_SEQ_CST); + __atomic_add_fetch(ptr, val, memory_order); #elif defined(HAVE_GCC_SYNC_BUILTINS) __sync_add_and_fetch(ptr, val); @@ -461,12 +545,17 @@ rbimpl_atomic_size_add(volatile size_t *ptr, size_t val) RBIMPL_ASSERT_OR_ASSUME(val <= LONG_MAX); atomic_add_long(ptr, val); -#else +#elif defined(_WIN32) || (defined(__sun) && defined(HAVE_ATOMIC_H)) RBIMPL_STATIC_ASSERT(size_of_rb_atomic_t, sizeof *ptr == sizeof(rb_atomic_t)); volatile rb_atomic_t *const tmp = RBIMPL_CAST((volatile rb_atomic_t *)ptr); - rbimpl_atomic_add(tmp, val); + rbimpl_atomic_add(tmp, val, memory_order); +#elif defined(HAVE_STDATOMIC_H) + atomic_fetch_add_explicit((_Atomic volatile size_t *)ptr, val, memory_order); + +#else +# error Unsupported platform. #endif } @@ -474,12 +563,13 @@ RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline void -rbimpl_atomic_inc(volatile rb_atomic_t *ptr) +rbimpl_atomic_inc(volatile rb_atomic_t *ptr, int memory_order) { + (void)memory_order; #if 0 #elif defined(HAVE_GCC_ATOMIC_BUILTINS) || defined(HAVE_GCC_SYNC_BUILTINS) - rbimpl_atomic_add(ptr, 1); + rbimpl_atomic_add(ptr, 1, memory_order); #elif defined(_WIN32) InterlockedIncrement(ptr); @@ -487,9 +577,11 @@ rbimpl_atomic_inc(volatile rb_atomic_t *ptr) #elif defined(__sun) && defined(HAVE_ATOMIC_H) atomic_inc_uint(ptr); -#else - rbimpl_atomic_add(ptr, 1); +#elif defined(HAVE_STDATOMIC_H) + rbimpl_atomic_add(ptr, 1, memory_order); +#else +# error Unsupported platform. #endif } @@ -497,12 +589,13 @@ RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline void -rbimpl_atomic_size_inc(volatile size_t *ptr) +rbimpl_atomic_size_inc(volatile size_t *ptr, int memory_order) { + (void)memory_order; #if 0 #elif defined(HAVE_GCC_ATOMIC_BUILTINS) || defined(HAVE_GCC_SYNC_BUILTINS) - rbimpl_atomic_size_add(ptr, 1); + rbimpl_atomic_size_add(ptr, 1, memory_order); #elif defined(_WIN64) InterlockedIncrement64(ptr); @@ -510,11 +603,16 @@ rbimpl_atomic_size_inc(volatile size_t *ptr) #elif defined(__sun) && defined(HAVE_ATOMIC_H) && (defined(_LP64) || defined(_I32LPx)) atomic_inc_ulong(ptr); -#else +#elif defined(_WIN32) || (defined(__sun) && defined(HAVE_ATOMIC_H)) RBIMPL_STATIC_ASSERT(size_of_size_t, sizeof *ptr == sizeof(rb_atomic_t)); - rbimpl_atomic_size_add(ptr, 1); + rbimpl_atomic_size_add(ptr, 1, memory_order); + +#elif defined(HAVE_STDATOMIC_H) + rbimpl_atomic_size_add(ptr, 1, memory_order); +#else +# error Unsupported platform. #endif } @@ -522,12 +620,13 @@ RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline rb_atomic_t -rbimpl_atomic_fetch_sub(volatile rb_atomic_t *ptr, rb_atomic_t val) +rbimpl_atomic_fetch_sub(volatile rb_atomic_t *ptr, rb_atomic_t val, int memory_order) { + (void)memory_order; #if 0 #elif defined(HAVE_GCC_ATOMIC_BUILTINS) - return __atomic_fetch_sub(ptr, val, __ATOMIC_SEQ_CST); + return __atomic_fetch_sub(ptr, val, memory_order); #elif defined(HAVE_GCC_SYNC_BUILTINS) return __sync_fetch_and_sub(ptr, val); @@ -542,6 +641,9 @@ rbimpl_atomic_fetch_sub(volatile rb_atomic_t *ptr, rb_atomic_t val) RBIMPL_ASSERT_OR_ASSUME(val <= INT_MAX); return atomic_add_int_nv(ptr, neg * val) + val; +#elif defined(HAVE_STDATOMIC_H) + return atomic_fetch_sub_explicit((_Atomic volatile rb_atomic_t *)ptr, val, memory_order); + #else # error Unsupported platform. #endif @@ -551,12 +653,13 @@ RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline void -rbimpl_atomic_sub(volatile rb_atomic_t *ptr, rb_atomic_t val) +rbimpl_atomic_sub(volatile rb_atomic_t *ptr, rb_atomic_t val, int memory_order) { + (void)memory_order; #if 0 #elif defined(HAVE_GCC_ATOMIC_BUILTINS) - __atomic_sub_fetch(ptr, val, __ATOMIC_SEQ_CST); + __atomic_sub_fetch(ptr, val, memory_order); #elif defined(HAVE_GCC_SYNC_BUILTINS) __sync_sub_and_fetch(ptr, val); @@ -569,6 +672,9 @@ rbimpl_atomic_sub(volatile rb_atomic_t *ptr, rb_atomic_t val) RBIMPL_ASSERT_OR_ASSUME(val <= INT_MAX); atomic_add_int(ptr, neg * val); +#elif defined(HAVE_STDATOMIC_H) + atomic_fetch_sub_explicit((_Atomic volatile rb_atomic_t *)ptr, val, memory_order); + #else # error Unsupported platform. #endif @@ -578,12 +684,13 @@ RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline void -rbimpl_atomic_size_sub(volatile size_t *ptr, size_t val) +rbimpl_atomic_size_sub(volatile size_t *ptr, size_t val, int memory_order) { + (void)memory_order; #if 0 #elif defined(HAVE_GCC_ATOMIC_BUILTINS) - __atomic_sub_fetch(ptr, val, __ATOMIC_SEQ_CST); + __atomic_sub_fetch(ptr, val, memory_order); #elif defined(HAVE_GCC_SYNC_BUILTINS) __sync_sub_and_fetch(ptr, val); @@ -597,12 +704,17 @@ rbimpl_atomic_size_sub(volatile size_t *ptr, size_t val) RBIMPL_ASSERT_OR_ASSUME(val <= LONG_MAX); atomic_add_long(ptr, neg * val); -#else +#elif defined(_WIN32) || (defined(__sun) && defined(HAVE_ATOMIC_H)) RBIMPL_STATIC_ASSERT(size_of_rb_atomic_t, sizeof *ptr == sizeof(rb_atomic_t)); volatile rb_atomic_t *const tmp = RBIMPL_CAST((volatile rb_atomic_t *)ptr); - rbimpl_atomic_sub(tmp, val); + rbimpl_atomic_sub(tmp, val, memory_order); +#elif defined(HAVE_STDATOMIC_H) + atomic_fetch_sub_explicit((_Atomic volatile size_t *)ptr, val, memory_order); + +#else +# error Unsupported platform. #endif } @@ -610,12 +722,13 @@ RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline void -rbimpl_atomic_dec(volatile rb_atomic_t *ptr) +rbimpl_atomic_dec(volatile rb_atomic_t *ptr, int memory_order) { + (void)memory_order; #if 0 #elif defined(HAVE_GCC_ATOMIC_BUILTINS) || defined(HAVE_GCC_SYNC_BUILTINS) - rbimpl_atomic_sub(ptr, 1); + rbimpl_atomic_sub(ptr, 1, memory_order); #elif defined(_WIN32) InterlockedDecrement(ptr); @@ -623,9 +736,11 @@ rbimpl_atomic_dec(volatile rb_atomic_t *ptr) #elif defined(__sun) && defined(HAVE_ATOMIC_H) atomic_dec_uint(ptr); -#else - rbimpl_atomic_sub(ptr, 1); +#elif defined(HAVE_STDATOMIC_H) + rbimpl_atomic_sub(ptr, 1, memory_order); +#else +# error Unsupported platform. #endif } @@ -633,12 +748,13 @@ RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline void -rbimpl_atomic_size_dec(volatile size_t *ptr) +rbimpl_atomic_size_dec(volatile size_t *ptr, int memory_order) { + (void)memory_order; #if 0 #elif defined(HAVE_GCC_ATOMIC_BUILTINS) || defined(HAVE_GCC_SYNC_BUILTINS) - rbimpl_atomic_size_sub(ptr, 1); + rbimpl_atomic_size_sub(ptr, 1, memory_order); #elif defined(_WIN64) InterlockedDecrement64(ptr); @@ -646,11 +762,16 @@ rbimpl_atomic_size_dec(volatile size_t *ptr) #elif defined(__sun) && defined(HAVE_ATOMIC_H) && (defined(_LP64) || defined(_I32LPx)) atomic_dec_ulong(ptr); -#else +#elif defined(_WIN32) || (defined(__sun) && defined(HAVE_ATOMIC_H)) RBIMPL_STATIC_ASSERT(size_of_size_t, sizeof *ptr == sizeof(rb_atomic_t)); - rbimpl_atomic_size_sub(ptr, 1); + rbimpl_atomic_size_sub(ptr, 1, memory_order); +#elif defined(HAVE_STDATOMIC_H) + rbimpl_atomic_size_sub(ptr, 1, memory_order); + +#else +# error Unsupported platform. #endif } @@ -658,59 +779,42 @@ RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline void -rbimpl_atomic_or(volatile rb_atomic_t *ptr, rb_atomic_t val) +rbimpl_atomic_or(volatile rb_atomic_t *ptr, rb_atomic_t val, int memory_order) { + (void)memory_order; #if 0 #elif defined(HAVE_GCC_ATOMIC_BUILTINS) - __atomic_or_fetch(ptr, val, __ATOMIC_SEQ_CST); + __atomic_or_fetch(ptr, val, memory_order); #elif defined(HAVE_GCC_SYNC_BUILTINS) __sync_or_and_fetch(ptr, val); -#elif RBIMPL_COMPILER_SINCE(MSVC, 13, 0, 0) +#elif RBIMPL_COMPILER_IS(MSVC) _InterlockedOr(ptr, val); -#elif defined(_WIN32) && defined(__GNUC__) - /* This was for old MinGW. Maybe not needed any longer? */ - __asm__( - "lock\n\t" - "orl\t%1, %0" - : "=m"(ptr) - : "Ir"(val)); - -#elif defined(_WIN32) && defined(_M_IX86) - __asm mov eax, ptr; - __asm mov ecx, val; - __asm lock or [eax], ecx; - #elif defined(__sun) && defined(HAVE_ATOMIC_H) atomic_or_uint(ptr, val); +#elif !defined(_WIN32) && defined(HAVE_STDATOMIC_H) + atomic_fetch_or_explicit((_Atomic volatile rb_atomic_t *)ptr, val, memory_order); + #else # error Unsupported platform. #endif } -/* Nobody uses this but for theoretical backwards compatibility... */ -#if RBIMPL_COMPILER_BEFORE(MSVC, 13, 0, 0) -static inline rb_atomic_t -rb_w32_atomic_or(volatile rb_atomic_t *var, rb_atomic_t val) -{ - return rbimpl_atomic_or(var, val); -} -#endif - RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline rb_atomic_t -rbimpl_atomic_exchange(volatile rb_atomic_t *ptr, rb_atomic_t val) +rbimpl_atomic_exchange(volatile rb_atomic_t *ptr, rb_atomic_t val, int memory_order) { + (void)memory_order; #if 0 #elif defined(HAVE_GCC_ATOMIC_BUILTINS) - return __atomic_exchange_n(ptr, val, __ATOMIC_SEQ_CST); + return __atomic_exchange_n(ptr, val, memory_order); #elif defined(HAVE_GCC_SYNC_BUILTINS) return __sync_lock_test_and_set(ptr, val); @@ -721,6 +825,9 @@ rbimpl_atomic_exchange(volatile rb_atomic_t *ptr, rb_atomic_t val) #elif defined(__sun) && defined(HAVE_ATOMIC_H) return atomic_swap_uint(ptr, val); +#elif defined(HAVE_STDATOMIC_H) + return atomic_exchange_explicit((_Atomic volatile rb_atomic_t *)ptr, val, memory_order); + #else # error Unsupported platform. #endif @@ -730,12 +837,13 @@ RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline size_t -rbimpl_atomic_size_exchange(volatile size_t *ptr, size_t val) +rbimpl_atomic_size_exchange(volatile size_t *ptr, size_t val, int memory_order) { + (void)memory_order; #if 0 #elif defined(HAVE_GCC_ATOMIC_BUILTINS) - return __atomic_exchange_n(ptr, val, __ATOMIC_SEQ_CST); + return __atomic_exchange_n(ptr, val, memory_order); #elif defined(HAVE_GCC_SYNC_BUILTINS) return __sync_lock_test_and_set(ptr, val); @@ -746,13 +854,18 @@ rbimpl_atomic_size_exchange(volatile size_t *ptr, size_t val) #elif defined(__sun) && defined(HAVE_ATOMIC_H) && (defined(_LP64) || defined(_I32LPx)) return atomic_swap_ulong(ptr, val); -#else +#elif defined(_WIN32) || (defined(__sun) && defined(HAVE_ATOMIC_H)) RBIMPL_STATIC_ASSERT(size_of_size_t, sizeof *ptr == sizeof(rb_atomic_t)); volatile rb_atomic_t *const tmp = RBIMPL_CAST((volatile rb_atomic_t *)ptr); - const rb_atomic_t ret = rbimpl_atomic_exchange(tmp, val); + const rb_atomic_t ret = rbimpl_atomic_exchange(tmp, val, memory_order); return RBIMPL_CAST((size_t)ret); +#elif defined(HAVE_STDATOMIC_H) + return atomic_exchange_explicit((_Atomic volatile size_t *)ptr, val, memory_order); + +#else +# error Unsupported platform. #endif } @@ -760,15 +873,16 @@ RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline void -rbimpl_atomic_size_set(volatile size_t *ptr, size_t val) +rbimpl_atomic_size_store(volatile size_t *ptr, size_t val, int memory_order) { + (void)memory_order; #if 0 #elif defined(HAVE_GCC_ATOMIC_BUILTINS) - __atomic_store_n(ptr, val, __ATOMIC_SEQ_CST); + __atomic_store_n(ptr, val, memory_order); #else - rbimpl_atomic_size_exchange(ptr, val); + rbimpl_atomic_size_exchange(ptr, val, memory_order); #endif } @@ -777,8 +891,9 @@ RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline void * -rbimpl_atomic_ptr_exchange(void *volatile *ptr, const void *val) +rbimpl_atomic_ptr_exchange(void *volatile *ptr, const void *val, int memory_order) { + (void)memory_order; #if 0 #elif defined(InterlockedExchangePointer) @@ -795,7 +910,7 @@ rbimpl_atomic_ptr_exchange(void *volatile *ptr, const void *val) const size_t sval = RBIMPL_CAST((size_t)val); volatile size_t *const sptr = RBIMPL_CAST((volatile size_t *)ptr); - const size_t sret = rbimpl_atomic_size_exchange(sptr, sval); + const size_t sret = rbimpl_atomic_size_exchange(sptr, sval, memory_order); return RBIMPL_CAST((void *)sret); #endif @@ -805,26 +920,26 @@ RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline void -rbimpl_atomic_ptr_set(volatile void **ptr, void *val) +rbimpl_atomic_ptr_store(volatile void **ptr, void *val, int memory_order) { RBIMPL_STATIC_ASSERT(sizeof_value, sizeof *ptr == sizeof(size_t)); const size_t sval = RBIMPL_CAST((size_t)val); volatile size_t *const sptr = RBIMPL_CAST((volatile size_t *)ptr); - rbimpl_atomic_size_set(sptr, sval); + rbimpl_atomic_size_store(sptr, sval, memory_order); } RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline VALUE -rbimpl_atomic_value_exchange(volatile VALUE *ptr, VALUE val) +rbimpl_atomic_value_exchange(volatile VALUE *ptr, VALUE val, int memory_order) { RBIMPL_STATIC_ASSERT(sizeof_value, sizeof *ptr == sizeof(size_t)); const size_t sval = RBIMPL_CAST((size_t)val); volatile size_t *const sptr = RBIMPL_CAST((volatile size_t *)ptr); - const size_t sret = rbimpl_atomic_size_exchange(sptr, sval); + const size_t sret = rbimpl_atomic_size_exchange(sptr, sval, memory_order); return RBIMPL_CAST((VALUE)sret); } @@ -832,27 +947,28 @@ RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline void -rbimpl_atomic_value_set(volatile VALUE *ptr, VALUE val) +rbimpl_atomic_value_store(volatile VALUE *ptr, VALUE val, int memory_order) { RBIMPL_STATIC_ASSERT(sizeof_value, sizeof *ptr == sizeof(size_t)); const size_t sval = RBIMPL_CAST((size_t)val); volatile size_t *const sptr = RBIMPL_CAST((volatile size_t *)ptr); - rbimpl_atomic_size_set(sptr, sval); + rbimpl_atomic_size_store(sptr, sval, memory_order); } RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline rb_atomic_t -rbimpl_atomic_load(volatile rb_atomic_t *ptr) +rbimpl_atomic_load(volatile rb_atomic_t *ptr, int memory_order) { + (void)memory_order; #if 0 #elif defined(HAVE_GCC_ATOMIC_BUILTINS) - return __atomic_load_n(ptr, __ATOMIC_SEQ_CST); + return __atomic_load_n(ptr, memory_order); #else - return rbimpl_atomic_fetch_add(ptr, 0); + return rbimpl_atomic_fetch_add(ptr, 0, memory_order); #endif } @@ -860,16 +976,17 @@ RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline void -rbimpl_atomic_set(volatile rb_atomic_t *ptr, rb_atomic_t val) +rbimpl_atomic_store(volatile rb_atomic_t *ptr, rb_atomic_t val, int memory_order) { + (void)memory_order; #if 0 #elif defined(HAVE_GCC_ATOMIC_BUILTINS) - __atomic_store_n(ptr, val, __ATOMIC_SEQ_CST); + __atomic_store_n(ptr, val, memory_order); #else /* Maybe std::atomic<rb_atomic_t>::store can be faster? */ - rbimpl_atomic_exchange(ptr, val); + rbimpl_atomic_exchange(ptr, val, memory_order); #endif } @@ -878,56 +995,49 @@ RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline rb_atomic_t -rbimpl_atomic_cas(volatile rb_atomic_t *ptr, rb_atomic_t oldval, rb_atomic_t newval) +rbimpl_atomic_cas(volatile rb_atomic_t *ptr, rb_atomic_t oldval, rb_atomic_t newval, int success_memorder, int failure_memorder) { + (void)success_memorder; + (void)failure_memorder; #if 0 #elif defined(HAVE_GCC_ATOMIC_BUILTINS) __atomic_compare_exchange_n( - ptr, &oldval, newval, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); + ptr, &oldval, newval, 0, success_memorder, failure_memorder); return oldval; #elif defined(HAVE_GCC_SYNC_BUILTINS) return __sync_val_compare_and_swap(ptr, oldval, newval); -#elif RBIMPL_COMPILER_SINCE(MSVC, 13, 0, 0) +#elif RBIMPL_COMPILER_IS(MSVC) return InterlockedCompareExchange(ptr, newval, oldval); -#elif defined(_WIN32) - PVOID *pptr = RBIMPL_CAST((PVOID *)ptr); - PVOID pold = RBIMPL_CAST((PVOID)oldval); - PVOID pnew = RBIMPL_CAST((PVOID)newval); - PVOID pret = InterlockedCompareExchange(pptr, pnew, pold); - return RBIMPL_CAST((rb_atomic_t)pret); - #elif defined(__sun) && defined(HAVE_ATOMIC_H) return atomic_cas_uint(ptr, oldval, newval); +#elif defined(HAVE_STDATOMIC_H) + atomic_compare_exchange_strong_explicit( + (_Atomic volatile rb_atomic_t *)ptr, &oldval, newval, success_memorder, failure_memorder); + return oldval; + #else # error Unsupported platform. #endif } -/* Nobody uses this but for theoretical backwards compatibility... */ -#if RBIMPL_COMPILER_BEFORE(MSVC, 13, 0, 0) -static inline rb_atomic_t -rb_w32_atomic_cas(volatile rb_atomic_t *var, rb_atomic_t oldval, rb_atomic_t newval) -{ - return rbimpl_atomic_cas(var, oldval, newval); -} -#endif - RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline size_t -rbimpl_atomic_size_cas(volatile size_t *ptr, size_t oldval, size_t newval) +rbimpl_atomic_size_cas(volatile size_t *ptr, size_t oldval, size_t newval, int success_memorder, int failure_memorder) { + (void)success_memorder; + (void)failure_memorder; #if 0 #elif defined(HAVE_GCC_ATOMIC_BUILTINS) __atomic_compare_exchange_n( - ptr, &oldval, newval, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); + ptr, &oldval, newval, 0, success_memorder, failure_memorder); return oldval; #elif defined(HAVE_GCC_SYNC_BUILTINS) @@ -939,12 +1049,19 @@ rbimpl_atomic_size_cas(volatile size_t *ptr, size_t oldval, size_t newval) #elif defined(__sun) && defined(HAVE_ATOMIC_H) && (defined(_LP64) || defined(_I32LPx)) return atomic_cas_ulong(ptr, oldval, newval); -#else +#elif defined(_WIN32) || (defined(__sun) && defined(HAVE_ATOMIC_H)) RBIMPL_STATIC_ASSERT(size_of_size_t, sizeof *ptr == sizeof(rb_atomic_t)); volatile rb_atomic_t *tmp = RBIMPL_CAST((volatile rb_atomic_t *)ptr); - return rbimpl_atomic_cas(tmp, oldval, newval); + return rbimpl_atomic_cas(tmp, oldval, newval, success_memorder, failure_memorder); + +#elif defined(HAVE_STDATOMIC_H) + atomic_compare_exchange_strong_explicit( + (_Atomic volatile size_t *)ptr, &oldval, newval, success_memorder, failure_memorder); + return oldval; +#else +# error Unsupported platform. #endif } @@ -952,8 +1069,10 @@ RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline void * -rbimpl_atomic_ptr_cas(void **ptr, const void *oldval, const void *newval) +rbimpl_atomic_ptr_cas(void **ptr, const void *oldval, const void *newval, int success_memorder, int failure_memorder) { + (void)success_memorder; + (void)failure_memorder; #if 0 #elif defined(InterlockedExchangePointer) @@ -976,7 +1095,7 @@ rbimpl_atomic_ptr_cas(void **ptr, const void *oldval, const void *newval) const size_t snew = RBIMPL_CAST((size_t)newval); const size_t sold = RBIMPL_CAST((size_t)oldval); volatile size_t *const sptr = RBIMPL_CAST((volatile size_t *)ptr); - const size_t sret = rbimpl_atomic_size_cas(sptr, sold, snew); + const size_t sret = rbimpl_atomic_size_cas(sptr, sold, snew, success_memorder, failure_memorder); return RBIMPL_CAST((void *)sret); #endif @@ -986,15 +1105,16 @@ RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline void * -rbimpl_atomic_ptr_load(void **ptr) +rbimpl_atomic_ptr_load(void **ptr, int memory_order) { + (void)memory_order; #if 0 #elif defined(HAVE_GCC_ATOMIC_BUILTINS) - return __atomic_load_n(ptr, __ATOMIC_SEQ_CST); + return __atomic_load_n(ptr, memory_order); #else void *val = *ptr; - return rbimpl_atomic_ptr_cas(ptr, val, val); + return rbimpl_atomic_ptr_cas(ptr, val, val, memory_order, memory_order); #endif } @@ -1002,14 +1122,23 @@ RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline VALUE -rbimpl_atomic_value_cas(volatile VALUE *ptr, VALUE oldval, VALUE newval) +rbimpl_atomic_value_load(volatile VALUE *ptr, int memory_order) +{ + return RBIMPL_CAST((VALUE)rbimpl_atomic_ptr_load((void **)ptr, memory_order)); +} + +RBIMPL_ATTR_ARTIFICIAL() +RBIMPL_ATTR_NOALIAS() +RBIMPL_ATTR_NONNULL((1)) +static inline VALUE +rbimpl_atomic_value_cas(volatile VALUE *ptr, VALUE oldval, VALUE newval, int success_memorder, int failure_memorder) { RBIMPL_STATIC_ASSERT(sizeof_value, sizeof *ptr == sizeof(size_t)); const size_t snew = RBIMPL_CAST((size_t)newval); const size_t sold = RBIMPL_CAST((size_t)oldval); volatile size_t *const sptr = RBIMPL_CAST((volatile size_t *)ptr); - const size_t sret = rbimpl_atomic_size_cas(sptr, sold, snew); + const size_t sret = rbimpl_atomic_size_cas(sptr, sold, snew, success_memorder, failure_memorder); return RBIMPL_CAST((VALUE)sret); } /** @endcond */ diff --git a/include/ruby/backward.h b/include/ruby/backward.h index f804c2c36e..6726102158 100644 --- a/include/ruby/backward.h +++ b/include/ruby/backward.h @@ -11,12 +11,6 @@ #include "ruby/internal/interpreter.h" #include "ruby/backward/2/attributes.h" -#define RBIMPL_ATTR_DEPRECATED_SINCE(ver) RBIMPL_ATTR_DEPRECATED(("since " #ver)) -#define RBIMPL_ATTR_DEPRECATED_INTERNAL(ver) RBIMPL_ATTR_DEPRECATED(("since "#ver", also internal")) -#define RBIMPL_ATTR_DEPRECATED_INTERNAL_ONLY() RBIMPL_ATTR_DEPRECATED(("only for internal use")) - -RBIMPL_ATTR_DEPRECATED_INTERNAL_ONLY() void rb_clear_constant_cache(void); - /* from version.c */ #if defined(RUBY_SHOW_COPYRIGHT_TO_DIE) && !!(RUBY_SHOW_COPYRIGHT_TO_DIE+0) # error RUBY_SHOW_COPYRIGHT_TO_DIE is deprecated diff --git a/include/ruby/backward/2/rmodule.h b/include/ruby/backward/2/rmodule.h index 53b37831c0..76c0936462 100644 --- a/include/ruby/backward/2/rmodule.h +++ b/include/ruby/backward/2/rmodule.h @@ -23,7 +23,7 @@ * who is implementing the internals) could have used those macros for a while. * Kept public as-is here to keep some theoretical backwards compatibility. */ -#define RMODULE_IV_TBL(m) RCLASS_IV_TBL(m) +#define RMODULE_IV_TBL(m) RCLASS_FIELDS(m) #define RMODULE_CONST_TBL(m) RCLASS_CONST_TBL(m) #define RMODULE_M_TBL(m) RCLASS_M_TBL(m) #define RMODULE_SUPER(m) RCLASS_SUPER(m) diff --git a/include/ruby/backward/cxxanyargs.hpp b/include/ruby/backward/cxxanyargs.hpp index 2414b7ae6d..0ca2745c20 100644 --- a/include/ruby/backward/cxxanyargs.hpp +++ b/include/ruby/backward/cxxanyargs.hpp @@ -190,33 +190,6 @@ rb_define_hooked_variable(const char *q, VALUE *w, std::nullptr_t e, void_type * /// @name Exceptions and tag jumps /// @{ -// RUBY_CXX_DEPRECATED("by rb_block_call since 1.9") -RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") -/// @brief Old way to implement iterators. -/// @param[in] q A function that can yield. -/// @param[in] w Passed to `q`. -/// @param[in] e What is to be yielded. -/// @param[in] r Passed to `e`. -/// @return The return value of `q`. -/// @note `e` can be nullptr. -/// @deprecated This function is obsoleted since long before 2.x era. Do not -/// use it any longer. rb_block_call() is provided instead. -inline VALUE -rb_iterate(onearg_type *q, VALUE w, type *e, VALUE r) -{ - rb_block_call_func_t t = reinterpret_cast<rb_block_call_func_t>(e); - return backward::rb_iterate_deprecated(q, w, t, r); -} - -#ifdef HAVE_NULLPTR -RUBY_CXX_DEPRECATED("by rb_block_call since 1.9") -inline VALUE -rb_iterate(onearg_type *q, VALUE w, std::nullptr_t e, VALUE r) -{ - return backward::rb_iterate_deprecated(q, w, e, r); -} -#endif - RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief Call a method with a block. /// @param[in] q The self. @@ -537,9 +510,7 @@ struct driver { * this writing the version is 2.8. Let's warn this later, some time * during 3.x. Hopefully codes in old (ANYARGS-ed) format should be * less than now. */ -#if (RUBY_API_VERSION_MAJOR * 100 + RUBY_API_VERSION_MINOR) >= 301 RUBY_CXX_DEPRECATED("use of ANYARGS is deprecated") -#endif /// @copydoc define(VALUE klass, T mid, U func) /// @deprecated Pass correctly typed function instead. static inline void diff --git a/include/ruby/debug.h b/include/ruby/debug.h index 0a9f693951..547d5d94c4 100644 --- a/include/ruby/debug.h +++ b/include/ruby/debug.h @@ -297,7 +297,7 @@ VALUE rb_debug_inspector_frame_depth(const rb_debug_inspector_t *dc, long index) #define RB_DEBUG_INSPECTOR_FRAME_DEPTH(dc, index) rb_debug_inspector_frame_depth(dc, index) /** - * Return current frmae depth. + * Return current frame depth. * * @retval The depth of the current frame in Integer. */ diff --git a/include/ruby/fiber/scheduler.h b/include/ruby/fiber/scheduler.h index b678bd0d1a..4d764f68ae 100644 --- a/include/ruby/fiber/scheduler.h +++ b/include/ruby/fiber/scheduler.h @@ -23,9 +23,11 @@ RBIMPL_SYMBOL_EXPORT_BEGIN() -#define RUBY_FIBER_SCHEDULER_VERSION 2 +// Version 3: Adds support for `fiber_interrupt`. +#define RUBY_FIBER_SCHEDULER_VERSION 3 struct timeval; +struct rb_thread_struct; /** * Wrap a `ssize_t` and `int errno` into a single `VALUE`. This interface should @@ -117,7 +119,7 @@ VALUE rb_fiber_scheduler_current(void); /** * Identical to rb_fiber_scheduler_current(), except it queries for that of the - * passed thread instead of the implicit current one. + * passed thread value instead of the implicit current one. * * @param[in] thread Target thread. * @exception rb_eTypeError `thread` is not a thread. @@ -127,6 +129,17 @@ VALUE rb_fiber_scheduler_current(void); VALUE rb_fiber_scheduler_current_for_thread(VALUE thread); /** + * Identical to rb_fiber_scheduler_current_for_thread(), except it expects + * a threadptr instead of a thread value. + * + * @param[in] thread Target thread. + * @exception rb_eTypeError `thread` is not a thread. + * @retval RUBY_Qnil No scheduler is in effect in `thread`. + * @retval otherwise The scheduler that is in effect in `thread`. + */ +VALUE rb_fiber_scheduler_current_for_threadptr(struct rb_thread_struct *thread); + +/** * Converts the passed timeout to an expression that rb_fiber_scheduler_block() * etc. expects. * @@ -166,6 +179,14 @@ VALUE rb_fiber_scheduler_kernel_sleep(VALUE scheduler, VALUE duration); */ VALUE rb_fiber_scheduler_kernel_sleepv(VALUE scheduler, int argc, VALUE * argv); +/** + * Yield to the scheduler, to be resumed on the next scheduling cycle. + * + * @param[in] scheduler Target scheduler. + * @return What `scheduler.yield` returns. + */ +VALUE rb_fiber_scheduler_yield(VALUE scheduler); + /* Description TBW */ #if 0 VALUE rb_fiber_scheduler_timeout_after(VALUE scheduler, VALUE timeout, VALUE exception, VALUE message); @@ -199,6 +220,8 @@ VALUE rb_fiber_scheduler_block(VALUE scheduler, VALUE blocker, VALUE timeout); /** * Wakes up a fiber previously blocked using rb_fiber_scheduler_block(). * + * This function may be called from a different thread. + * * @param[in] scheduler Target scheduler. * @param[in] blocker What was awaited for. * @param[in] fiber What to unblock. @@ -391,11 +414,54 @@ VALUE rb_fiber_scheduler_io_close(VALUE scheduler, VALUE io); */ VALUE rb_fiber_scheduler_address_resolve(VALUE scheduler, VALUE hostname); +// The state of the blocking operation execution. struct rb_fiber_scheduler_blocking_operation_state { void *result; int saved_errno; }; +// The opaque handle for the blocking operation. +typedef struct rb_fiber_scheduler_blocking_operation rb_fiber_scheduler_blocking_operation_t; + +/** + * Extract the blocking operation handle from a BlockingOperationRuby object. + * + * This function safely extracts the opaque handle from a BlockingOperation VALUE + * while holding the GVL. The returned pointer can be passed to worker threads + * and used with rb_fiber_scheduler_blocking_operation_execute. + * + * @param[in] self The BlockingOperation VALUE to extract from + * @return The opaque struct pointer on success, NULL on error + * @note Experimental. + */ +rb_fiber_scheduler_blocking_operation_t *rb_fiber_scheduler_blocking_operation_extract(VALUE self); + +/** + * Execute blocking operation from handle (GVL not required). + * + * This function executes a blocking operation using the opaque handle + * obtained from rb_fiber_scheduler_blocking_operation_extract. + * It can be called from native threads without holding the GVL. + * + * @param[in] blocking_operation The opaque handle. + * @return 0 on success, -1 on error. + * @note Experimental. Can be called from any thread without holding the GVL + */ +int rb_fiber_scheduler_blocking_operation_execute(rb_fiber_scheduler_blocking_operation_t *blocking_operation); + +/** + * Cancel a blocking operation. + * + * This function cancels a blocking operation. If the operation is queued, + * it just marks it as cancelled. If it's executing, it marks it as cancelled + * and calls the unblock function to interrupt the operation. + * + * @param blocking_operation The opaque struct pointer + * @return 1 if unblock function was called, 0 if just marked cancelled, -1 on error + * @note Experimental. + */ +int rb_fiber_scheduler_blocking_operation_cancel(rb_fiber_scheduler_blocking_operation_t *blocking_operation); + /** * Defer the execution of the passed function to the scheduler. * @@ -412,8 +478,25 @@ struct rb_fiber_scheduler_blocking_operation_state { VALUE rb_fiber_scheduler_blocking_operation_wait(VALUE scheduler, void* (*function)(void *), void *data, rb_unblock_function_t *unblock_function, void *data2, int flags, struct rb_fiber_scheduler_blocking_operation_state *state); /** + * Interrupt a fiber by raising an exception. You can construct an exception using `rb_make_exception`. + * + * This hook may be invoked by a different thread. + * + * @param[in] scheduler Target scheduler. + * @param[in] fiber The fiber to interrupt. + * @param[in] exception The exception to raise in the fiber. + * @return What `scheduler.fiber_interrupt` returns. + */ +VALUE rb_fiber_scheduler_fiber_interrupt(VALUE scheduler, VALUE fiber, VALUE exception); + +/** * Create and schedule a non-blocking fiber. * + * @param[in] scheduler Target scheduler. + * @param[in] argc Number of arguments in argv. + * @param[in] argv Array of arguments to pass to the fiber. + * @param[in] kw_splat Whether to expand last argument as keywords. + * @return The created and scheduled fiber. */ VALUE rb_fiber_scheduler_fiber(VALUE scheduler, int argc, VALUE *argv, int kw_splat); diff --git a/include/ruby/intern.h b/include/ruby/intern.h index 48e4cd546e..8718169ce2 100644 --- a/include/ruby/intern.h +++ b/include/ruby/intern.h @@ -51,6 +51,7 @@ #include "ruby/internal/intern/re.h" #include "ruby/internal/intern/ruby.h" #include "ruby/internal/intern/select.h" +#include "ruby/internal/intern/set.h" #include "ruby/internal/intern/signal.h" #include "ruby/internal/intern/sprintf.h" #include "ruby/internal/intern/string.h" diff --git a/include/ruby/internal/abi.h b/include/ruby/internal/abi.h index e735a67564..e6d1fa7e8f 100644 --- a/include/ruby/internal/abi.h +++ b/include/ruby/internal/abi.h @@ -24,7 +24,7 @@ * In released versions of Ruby, this number is not defined since teeny * versions of Ruby should guarantee ABI compatibility. */ -#define RUBY_ABI_VERSION 0 +#define RUBY_ABI_VERSION 1 /* Windows does not support weak symbols so ruby_abi_version will not exist * in the shared library. */ diff --git a/include/ruby/internal/arithmetic/intptr_t.h b/include/ruby/internal/arithmetic/intptr_t.h index a354f4469c..70090f88e6 100644 --- a/include/ruby/internal/arithmetic/intptr_t.h +++ b/include/ruby/internal/arithmetic/intptr_t.h @@ -32,6 +32,18 @@ #define rb_int_new rb_int2inum /**< @alias{rb_int2inum} */ #define rb_uint_new rb_uint2inum /**< @alias{rb_uint2inum} */ +// These definitions are same as fiddle/conversions.h +#if SIZEOF_VOIDP <= SIZEOF_LONG +# define PTR2NUM(x) (LONG2NUM((long)(x))) +# define NUM2PTR(x) ((void*)(NUM2ULONG(x))) +#elif SIZEOF_VOIDP <= SIZEOF_LONG_LONG +# define PTR2NUM(x) (LL2NUM((LONG_LONG)(x))) +# define NUM2PTR(x) ((void*)(NUM2ULL(x))) +#else +// should have been an error in ruby/internal/value.h +# error Need integer for VALUE +#endif + RBIMPL_SYMBOL_EXPORT_BEGIN() /** diff --git a/include/ruby/internal/attr/deprecated.h b/include/ruby/internal/attr/deprecated.h index e1bbdbd15a..a374ace868 100644 --- a/include/ruby/internal/attr/deprecated.h +++ b/include/ruby/internal/attr/deprecated.h @@ -48,7 +48,7 @@ #elif RBIMPL_HAS_ATTRIBUTE(deprecated) /* but not with message. */ # define RBIMPL_ATTR_DEPRECATED(msg) __attribute__((__deprecated__)) -#elif RBIMPL_COMPILER_SINCE(MSVC, 14, 0, 0) +#elif RBIMPL_COMPILER_IS(MSVC) # define RBIMPL_ATTR_DEPRECATED(msg) __declspec(deprecated msg) #elif RBIMPL_HAS_DECLSPEC_ATTRIBUTE(deprecated) @@ -72,4 +72,11 @@ # define RBIMPL_ATTR_DEPRECATED_EXT(msg) RBIMPL_ATTR_DEPRECATED(msg) #endif +#define RBIMPL_ATTR_DEPRECATED_SINCE(ver) \ + RBIMPL_ATTR_DEPRECATED(("since " #ver)) +#define RBIMPL_ATTR_DEPRECATED_INTERNAL(ver) \ + RBIMPL_ATTR_DEPRECATED(("since "#ver", also internal")) +#define RBIMPL_ATTR_DEPRECATED_INTERNAL_ONLY() \ + RBIMPL_ATTR_DEPRECATED(("only for internal use")) + #endif /* RBIMPL_ATTR_DEPRECATED_H */ diff --git a/include/ruby/internal/attr/forceinline.h b/include/ruby/internal/attr/forceinline.h index b7daafede7..5b9ae794af 100644 --- a/include/ruby/internal/attr/forceinline.h +++ b/include/ruby/internal/attr/forceinline.h @@ -29,7 +29,7 @@ * `__forceinline` are mutually exclusive. We have to mimic that behaviour for * non-MSVC compilers. */ -#if RBIMPL_COMPILER_SINCE(MSVC, 12, 0, 0) +#if RBIMPL_COMPILER_IS(MSVC) # define RBIMPL_ATTR_FORCEINLINE() __forceinline #elif RBIMPL_HAS_ATTRIBUTE(always_inline) # define RBIMPL_ATTR_FORCEINLINE() __attribute__((__always_inline__)) inline diff --git a/include/ruby/internal/attr/noexcept.h b/include/ruby/internal/attr/noexcept.h index 7c3f92f1e7..dd4c667407 100644 --- a/include/ruby/internal/attr/noexcept.h +++ b/include/ruby/internal/attr/noexcept.h @@ -78,7 +78,7 @@ #elif defined(__INTEL_CXX11_MODE__) # define RBIMPL_ATTR_NOEXCEPT(_) noexcept(noexcept(_)) -#elif RBIMPL_COMPILER_SINCE(MSVC, 19, 0, 0) +#elif RBIMPL_COMPILER_IS(MSVC) # define RBIMPL_ATTR_NOEXCEPT(_) noexcept(noexcept(_)) #elif __cplusplus >= 201103L diff --git a/include/ruby/internal/attr/nonstring.h b/include/ruby/internal/attr/nonstring.h index 9a66180e19..5ad6ef2a86 100644 --- a/include/ruby/internal/attr/nonstring.h +++ b/include/ruby/internal/attr/nonstring.h @@ -27,6 +27,8 @@ # define RBIMPL_ATTR_NONSTRING() __attribute__((nonstring)) # if RBIMPL_COMPILER_SINCE(GCC, 15, 0, 0) # define RBIMPL_ATTR_NONSTRING_ARRAY() RBIMPL_ATTR_NONSTRING() +# elif RBIMPL_COMPILER_SINCE(Clang, 21, 0, 0) +# define RBIMPL_ATTR_NONSTRING_ARRAY() RBIMPL_ATTR_NONSTRING() # else # define RBIMPL_ATTR_NONSTRING_ARRAY() /* void */ # endif diff --git a/include/ruby/internal/attr/restrict.h b/include/ruby/internal/attr/restrict.h index e39104138c..b12fdc9dbc 100644 --- a/include/ruby/internal/attr/restrict.h +++ b/include/ruby/internal/attr/restrict.h @@ -28,7 +28,7 @@ * `__has_declspec_attribute()` which involves macro substitution. */ /** Wraps (or simulates) `__declspec(restrict)` */ -#if RBIMPL_COMPILER_SINCE(MSVC, 14, 0, 0) +#if RBIMPL_COMPILER_IS(MSVC) # define RBIMPL_ATTR_RESTRICT() __declspec(re ## strict) #elif RBIMPL_HAS_ATTRIBUTE(malloc) diff --git a/include/ruby/internal/compiler_is/msvc.h b/include/ruby/internal/compiler_is/msvc.h index 8a864ea558..824f0ecc21 100644 --- a/include/ruby/internal/compiler_is/msvc.h +++ b/include/ruby/internal/compiler_is/msvc.h @@ -38,19 +38,8 @@ # define RBIMPL_COMPILER_VERSION_MINOR (_MSC_FULL_VER % 10000000 / 100000) # define RBIMPL_COMPILER_VERSION_PATCH (_MSC_FULL_VER % 100000) -#elif defined(_MSC_FULL_VER) -# define RBIMPL_COMPILER_IS_MSVC 1 -# /* _MSC_FULL_VER = XXYYZZZZ */ -# define RBIMPL_COMPILER_VERSION_MAJOR (_MSC_FULL_VER / 1000000) -# define RBIMPL_COMPILER_VERSION_MINOR (_MSC_FULL_VER % 1000000 / 10000) -# define RBIMPL_COMPILER_VERSION_PATCH (_MSC_FULL_VER % 10000) - #else -# define RBIMPL_COMPILER_IS_MSVC 1 -# /* _MSC_VER = XXYY */ -# define RBIMPL_COMPILER_VERSION_MAJOR (_MSC_VER / 100) -# define RBIMPL_COMPILER_VERSION_MINOR (_MSC_VER % 100) -# define RBIMPL_COMPILER_VERSION_PATCH 0 +# error Unsupported MSVC version #endif #endif /* RBIMPL_COMPILER_IS_MSVC_H */ diff --git a/include/ruby/internal/config.h b/include/ruby/internal/config.h index da070f0979..34862ded6e 100644 --- a/include/ruby/internal/config.h +++ b/include/ruby/internal/config.h @@ -50,7 +50,7 @@ # define HAVE_VA_ARGS_MACRO # elif defined(__INTEL_CXX11_MODE__) # define HAVE_VA_ARGS_MACRO -# elif RBIMPL_COMPILER_SINCE(MSVC, 16, 0, 0) +# elif RBIMPL_COMPILER_IS(MSVC) # define HAVE_VA_ARGS_MACRO # else # /* NG, not known. */ diff --git a/include/ruby/internal/core/rbasic.h b/include/ruby/internal/core/rbasic.h index a1477e2600..63cdff8e09 100644 --- a/include/ruby/internal/core/rbasic.h +++ b/include/ruby/internal/core/rbasic.h @@ -55,6 +55,12 @@ enum ruby_rvalue_flags { RVALUE_EMBED_LEN_MAX = RBIMPL_RVALUE_EMBED_LEN_MAX }; +#if (SIZEOF_VALUE < SIZEOF_UINT64_T) +#define RBASIC_SHAPE_ID_FIELD 1 +#else +#define RBASIC_SHAPE_ID_FIELD 0 +#endif + /** * Ruby object's base components. All Ruby objects have them in common. */ @@ -85,6 +91,10 @@ RBasic { */ const VALUE klass; +#if RBASIC_SHAPE_ID_FIELD + VALUE shape_id; +#endif + #ifdef __cplusplus public: RBIMPL_ATTR_CONSTEXPR(CXX11) @@ -100,8 +110,14 @@ RBasic { RBasic() : flags(RBIMPL_VALUE_NULL), klass(RBIMPL_VALUE_NULL) +#if RBASIC_SHAPE_ID_FIELD + , shape_id(RBIMPL_VALUE_NULL) +#endif { } +# define RBASIC_INIT RBasic() +#else +# define RBASIC_INIT {RBIMPL_VALUE_NULL} #endif }; diff --git a/include/ruby/internal/core/rclass.h b/include/ruby/internal/core/rclass.h index b0b6bfc80c..6f78cc569b 100644 --- a/include/ruby/internal/core/rclass.h +++ b/include/ruby/internal/core/rclass.h @@ -58,7 +58,7 @@ enum ruby_rmodule_flags { * rb_mod_refine() has this flag set. This is the bit which controls * difference between normal inclusion versus refinements. */ - RMODULE_IS_REFINEMENT = RUBY_FL_USER3 + RMODULE_IS_REFINEMENT = RUBY_FL_USER1 }; struct RClass; /* Opaque, declared here for RCLASS() macro. */ diff --git a/include/ruby/internal/core/rdata.h b/include/ruby/internal/core/rdata.h index cab412af72..cee5e7b5ea 100644 --- a/include/ruby/internal/core/rdata.h +++ b/include/ruby/internal/core/rdata.h @@ -133,12 +133,6 @@ struct RData { */ RUBY_DATA_FUNC dmark; - /** Pointer to the actual C level struct that you want to wrap. - * This is in between dmark and dfree to allow DATA_PTR to continue - * to work for both RData and non-embedded RTypedData. - */ - void *data; - /** * This function is called when the object is no longer used. You need to * do whatever necessary to avoid memory leaks. @@ -147,6 +141,12 @@ struct RData { * impossible at that moment (that is why GC runs). */ RUBY_DATA_FUNC dfree; + + /** Pointer to the actual C level struct that you want to wrap. + * This is after dmark and dfree to allow DATA_PTR to continue to work for + * both RData and non-embedded RTypedData. + */ + void *data; }; RBIMPL_SYMBOL_EXPORT_BEGIN() @@ -180,11 +180,6 @@ VALUE rb_data_object_wrap(VALUE klass, void *datap, RUBY_DATA_FUNC dmark, RUBY_D */ VALUE rb_data_object_zalloc(VALUE klass, size_t size, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree); -/** - * @private - * Documented in include/ruby/internal/globals.h - */ -RUBY_EXTERN VALUE rb_cObject; RBIMPL_SYMBOL_EXPORT_END() /** @@ -351,14 +346,6 @@ rb_data_object_make(VALUE klass, RUBY_DATA_FUNC mark_func, RUBY_DATA_FUNC free_f return result; } -RBIMPL_ATTR_DEPRECATED(("by: rb_data_object_wrap")) -/** @deprecated This function was renamed to rb_data_object_wrap(). */ -static inline VALUE -rb_data_object_alloc(VALUE klass, void *data, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree) -{ - return rb_data_object_wrap(klass, data, dmark, dfree); -} - /** @cond INTERNAL_MACRO */ #define rb_data_object_wrap_0 rb_data_object_wrap #define rb_data_object_wrap_1 rb_data_object_wrap_warning diff --git a/include/ruby/internal/core/robject.h b/include/ruby/internal/core/robject.h index 1f2b7168b8..99f6470ac1 100644 --- a/include/ruby/internal/core/robject.h +++ b/include/ruby/internal/core/robject.h @@ -42,10 +42,10 @@ */ #define ROBJECT(obj) RBIMPL_CAST((struct RObject *)(obj)) /** @cond INTERNAL_MACRO */ -#define ROBJECT_EMBED_LEN_MAX ROBJECT_EMBED_LEN_MAX -#define ROBJECT_EMBED ROBJECT_EMBED -#define ROBJECT_IV_CAPACITY ROBJECT_IV_CAPACITY -#define ROBJECT_IVPTR ROBJECT_IVPTR +#define ROBJECT_EMBED_LEN_MAX ROBJECT_EMBED_LEN_MAX +#define ROBJECT_HEAP ROBJECT_HEAP +#define ROBJECT_FIELDS_CAPACITY ROBJECT_FIELDS_CAPACITY +#define ROBJECT_FIELDS ROBJECT_FIELDS /** @endcond */ /** @@ -55,10 +55,12 @@ */ enum ruby_robject_flags { /** - * This flag has something to do with memory footprint. If the object is - * "small" enough, ruby tries to be creative to abuse padding bits of - * struct ::RObject for storing instance variables. This flag denotes that - * situation. + * This flag marks that the object's instance variables are stored in an + * external heap buffer. + * Normally, instance variable references are stored inside the object slot, + * but if it overflow, Ruby may have to allocate a separate buffer and spills + * the instance variables there. + * This flag denotes that situation. * * @warning This bit has to be considered read-only. Setting/clearing * this bit without corresponding fix up must cause immediate @@ -71,7 +73,7 @@ enum ruby_robject_flags { * 3rd parties must not be aware that there even is more than one way to * store instance variables. Might better be hidden. */ - ROBJECT_EMBED = RUBY_FL_USER1 + ROBJECT_HEAP = RUBY_FL_USER4 }; struct st_table; @@ -94,7 +96,7 @@ struct RObject { */ struct { /** Pointer to a C array that holds instance variables. */ - VALUE *ivptr; + VALUE *fields; } heap; /* Embedded instance variables. When an object is small enough, it @@ -123,17 +125,17 @@ RBIMPL_ATTR_ARTIFICIAL() * @shyouhei finds no reason for this to be visible from extension libraries. */ static inline VALUE * -ROBJECT_IVPTR(VALUE obj) +ROBJECT_FIELDS(VALUE obj) { RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT); struct RObject *const ptr = ROBJECT(obj); - if (RB_FL_ANY_RAW(obj, ROBJECT_EMBED)) { - return ptr->as.ary; + if (RB_UNLIKELY(RB_FL_ANY_RAW(obj, ROBJECT_HEAP))) { + return ptr->as.heap.fields; } else { - return ptr->as.heap.ivptr; + return ptr->as.ary; } } diff --git a/include/ruby/internal/core/rstring.h b/include/ruby/internal/core/rstring.h index 0bca74e688..35175ea94a 100644 --- a/include/ruby/internal/core/rstring.h +++ b/include/ruby/internal/core/rstring.h @@ -369,41 +369,6 @@ RSTRING_LEN(VALUE str) return RSTRING(str)->len; } -RBIMPL_WARNING_PUSH() -#if RBIMPL_COMPILER_IS(Intel) -RBIMPL_WARNING_IGNORED(413) -#endif - -RBIMPL_ATTR_PURE_UNLESS_DEBUG() -RBIMPL_ATTR_ARTIFICIAL() -/** - * @private - * - * "Expands" an embedded string into an ordinal one. This is a function that - * returns aggregated type. The returned struct always has its `as.heap.len` - * an `as.heap.ptr` fields set appropriately. - * - * This is an implementation detail that 3rd parties should never bother. - */ -static inline struct RString -rbimpl_rstring_getmem(VALUE str) -{ - RBIMPL_ASSERT_TYPE(str, RUBY_T_STRING); - - if (RB_FL_ANY_RAW(str, RSTRING_NOEMBED)) { - return *RSTRING(str); - } - else { - /* Expecting compilers to optimize this on-stack struct away. */ - struct RString retval; - retval.len = RSTRING_LEN(str); - retval.as.heap.ptr = RSTRING(str)->as.embed.ary; - return retval; - } -} - -RBIMPL_WARNING_POP() - RBIMPL_ATTR_ARTIFICIAL() /** * Queries the contents pointer of the string. @@ -415,7 +380,9 @@ RBIMPL_ATTR_ARTIFICIAL() static inline char * RSTRING_PTR(VALUE str) { - char *ptr = rbimpl_rstring_getmem(str).as.heap.ptr; + char *ptr = RB_FL_TEST_RAW(str, RSTRING_NOEMBED) ? + RSTRING(str)->as.heap.ptr : + RSTRING(str)->as.embed.ary; if (RUBY_DEBUG && RB_UNLIKELY(! ptr)) { /* :BEWARE: @shyouhei thinks that currently, there are rooms for this @@ -441,14 +408,17 @@ RBIMPL_ATTR_ARTIFICIAL() static inline char * RSTRING_END(VALUE str) { - struct RString buf = rbimpl_rstring_getmem(str); + char *ptr = RB_FL_TEST_RAW(str, RSTRING_NOEMBED) ? + RSTRING(str)->as.heap.ptr : + RSTRING(str)->as.embed.ary; + long len = RSTRING_LEN(str); - if (RUBY_DEBUG && RB_UNLIKELY(! buf.as.heap.ptr)) { + if (RUBY_DEBUG && RB_UNLIKELY(!ptr)) { /* Ditto. */ rb_debug_rstring_null_ptr("RSTRING_END"); } - return &buf.as.heap.ptr[buf.len]; + return &ptr[len]; } RBIMPL_ATTR_ARTIFICIAL() @@ -477,16 +447,7 @@ RSTRING_LENINT(VALUE str) * @param ptrvar Variable where its contents is stored. * @param lenvar Variable where its length is stored. */ -#ifdef HAVE_STMT_AND_DECL_IN_EXPR -# define RSTRING_GETMEM(str, ptrvar, lenvar) \ - __extension__ ({ \ - struct RString rbimpl_str = rbimpl_rstring_getmem(str); \ - (ptrvar) = rbimpl_str.as.heap.ptr; \ - (lenvar) = rbimpl_str.len; \ - }) -#else # define RSTRING_GETMEM(str, ptrvar, lenvar) \ ((ptrvar) = RSTRING_PTR(str), \ (lenvar) = RSTRING_LEN(str)) -#endif /* HAVE_STMT_AND_DECL_IN_EXPR */ #endif /* RBIMPL_RSTRING_H */ diff --git a/include/ruby/internal/core/rstruct.h b/include/ruby/internal/core/rstruct.h index 69be487b59..0028a1bdcd 100644 --- a/include/ruby/internal/core/rstruct.h +++ b/include/ruby/internal/core/rstruct.h @@ -31,18 +31,6 @@ # include "ruby/backward.h" #endif -/** - * @private - * - * @deprecated This macro once was a thing in the old days, but makes no sense - * any longer today. Exists here for backwards compatibility - * only. You can safely forget about it. - * - * @internal - * - * Declaration of rb_struct_ptr() is at include/ruby/backward.h. - */ -#define RSTRUCT_PTR(st) rb_struct_ptr(st) /** @cond INTERNAL_MACRO */ #define RSTRUCT_LEN RSTRUCT_LEN #define RSTRUCT_SET RSTRUCT_SET diff --git a/include/ruby/internal/core/rtypeddata.h b/include/ruby/internal/core/rtypeddata.h index b576be779f..ec0794e387 100644 --- a/include/ruby/internal/core/rtypeddata.h +++ b/include/ruby/internal/core/rtypeddata.h @@ -37,6 +37,7 @@ #include "ruby/internal/dllexport.h" #include "ruby/internal/error.h" #include "ruby/internal/fl_type.h" +#include "ruby/internal/static_assert.h" #include "ruby/internal/stdbool.h" #include "ruby/internal/value_type.h" @@ -108,16 +109,17 @@ /** @cond INTERNAL_MACRO */ #define RTYPEDDATA_P RTYPEDDATA_P #define RTYPEDDATA_TYPE RTYPEDDATA_TYPE +#define TYPED_DATA_EMBEDDED ((VALUE)1) +#define TYPED_DATA_PTR_MASK (~(TYPED_DATA_EMBEDDED)) +/** @endcond */ + +/** + * Macros to see if each corresponding flag is defined. + */ #define RUBY_TYPED_FREE_IMMEDIATELY RUBY_TYPED_FREE_IMMEDIATELY #define RUBY_TYPED_FROZEN_SHAREABLE RUBY_TYPED_FROZEN_SHAREABLE #define RUBY_TYPED_WB_PROTECTED RUBY_TYPED_WB_PROTECTED #define RUBY_TYPED_PROMOTED1 RUBY_TYPED_PROMOTED1 -/** @endcond */ - -#define IS_TYPED_DATA ((VALUE)1) -#define TYPED_DATA_EMBEDDED ((VALUE)2) -#define TYPED_DATA_PTR_FLAGS ((VALUE)3) -#define TYPED_DATA_PTR_MASK (~TYPED_DATA_PTR_FLAGS) /** * @private @@ -158,6 +160,12 @@ rbimpl_typeddata_flags { */ RUBY_TYPED_FROZEN_SHAREABLE = RUBY_FL_SHAREABLE, + // experimental flag + // Similar to RUBY_TYPED_FROZEN_SHAREABLE, but doesn't make shareable + // reachable objects from this T_DATA object on the Ractor.make_shareable. + // If it refers to unshareable objects, simply raise an error. + // RUBY_TYPED_FROZEN_SHAREABLE_NO_REC = RUBY_FL_FINALIZE, + /** * This flag has something to do with our garbage collector. These days * ruby objects are "generational". There are those who are young and @@ -180,9 +188,9 @@ rbimpl_typeddata_flags { RUBY_TYPED_WB_PROTECTED = RUBY_FL_WB_PROTECTED, /* THIS FLAG DEPENDS ON Ruby version */ /** - * This flag no longer in use + * This flag is used to distinguish RTypedData from deprecated RData objects. */ - RUBY_TYPED_UNUSED = RUBY_FL_UNUSED6, + RUBY_TYPED_FL_IS_TYPED_DATA = RUBY_FL_USERPRIV0, /** * This flag determines whether marking and compaction should be carried out @@ -254,10 +262,15 @@ struct rb_data_type_struct { RUBY_DATA_FUNC dcompact; /** - * This field is reserved for future extension. For now, it must be - * filled with zeros. + * @internal */ - void *reserved[1]; /* For future extension. + void (*handle_weak_references)(void *); + + /** + * This field is reserved for future extension. For now, it must be + * filled with zeros. + */ + void *reserved[7]; /* For future extension. This array *must* be filled with ZERO. */ } function; @@ -355,11 +368,13 @@ struct RTypedData { /** The part that all ruby objects have in common. */ struct RBasic basic; + /** Direct reference to the slots that holds instance variables, if any **/ + VALUE fields_obj; + /** * This is a `const rb_data_type_t *const` value, with the low bits set: * - * 1: Always set, to differentiate RTypedData from RData. - * 2: Set if object is embedded. + * 1: Set if object is embedded. * * This field stores various information about how Ruby should handle a * data. This roughly resembles a Ruby level class (apart from method @@ -371,6 +386,10 @@ struct RTypedData { void *data; }; +#if !defined(__cplusplus) || __cplusplus >= 201103L +RBIMPL_STATIC_ASSERT(data_in_rtypeddata, offsetof(struct RData, data) == offsetof(struct RTypedData, data)); +#endif + RBIMPL_SYMBOL_EXPORT_BEGIN() RBIMPL_ATTR_NONNULL((3)) /** @@ -385,6 +404,7 @@ RBIMPL_ATTR_NONNULL((3)) */ VALUE rb_data_typed_object_wrap(VALUE klass, void *datap, const rb_data_type_t *type); +RBIMPL_ATTR_NONNULL((3)) /** * Identical to rb_data_typed_object_wrap(), except it allocates a new data * region internally instead of taking an existing one. The allocation is done @@ -400,6 +420,7 @@ VALUE rb_data_typed_object_wrap(VALUE klass, void *datap, const rb_data_type_t * */ VALUE rb_data_typed_object_zalloc(VALUE klass, size_t size, const rb_data_type_t *type); +RBIMPL_ATTR_NONNULL(()) /** * Checks for the domestic relationship between the two. * @@ -414,6 +435,7 @@ VALUE rb_data_typed_object_zalloc(VALUE klass, size_t size, const rb_data_type_t */ int rb_typeddata_inherited_p(const rb_data_type_t *child, const rb_data_type_t *parent); +RBIMPL_ATTR_NONNULL((2)) /** * Checks if the given object is of given kind. * @@ -424,6 +446,7 @@ int rb_typeddata_inherited_p(const rb_data_type_t *child, const rb_data_type_t * */ int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type); +RBIMPL_ATTR_NONNULL((2)) /** * Identical to rb_typeddata_is_kind_of(), except it raises exceptions instead * of returning false. @@ -435,8 +458,49 @@ int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type); * @post Upon successful return `obj`'s type is guaranteed `data_type`. */ void *rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type); + +RBIMPL_ATTR_NORETURN() +RBIMPL_ATTR_NONNULL((2)) +/** + * @private + * + * Fails with the given object's type incompatibility to the type. + * + * This is an implementation detail of Check_Type. People don't use it + * directly. + * + * @param[in] obj The object in question. + * @param[in] expected Name of expected data type of `obj`. + */ +void rb_unexpected_object_type(VALUE obj, const char *expected); + +RBIMPL_ATTR_NORETURN() +RBIMPL_ATTR_NONNULL(()) +/** + * @private + * + * Fails with the given object's type incompatibility to the type. + * + * This is an implementation detail of #TypedData_Make_Struct. People don't + * use it directly. + * + * @param[in] actual Actual data type. + * @param[in] expected Expected data type. + */ +void rb_unexpected_typeddata(const rb_data_type_t *actual, const rb_data_type_t *expected); RBIMPL_SYMBOL_EXPORT_END() +#if RUBY_DEBUG +# define RBIMPL_TYPEDDATA_PRECONDITION(obj, unreachable) \ + while (RB_UNLIKELY(!RB_TYPE_P(obj, RUBY_T_DATA))) { \ + rb_unexpected_object_type(obj, "Data"); \ + unreachable; \ + } +#else +# define RBIMPL_TYPEDDATA_PRECONDITION(obj, unreachable) \ + RBIMPL_ASSERT_NOTHING +#endif + /** * Converts sval, a pointer to your struct, into a Ruby object. * @@ -465,14 +529,13 @@ RBIMPL_SYMBOL_EXPORT_END() */ #define TypedData_Make_Struct0(result, klass, type, size, data_type, sval) \ VALUE result = rb_data_typed_object_zalloc(klass, size, data_type); \ - (sval) = (type *)RTYPEDDATA_GET_DATA(result); \ + (sval) = RBIMPL_CAST((type *)rbimpl_typeddata_get_data(result)); \ RBIMPL_CAST(/*suppress unused variable warnings*/(void)(sval)) /** * Identical to #TypedData_Wrap_Struct, except it allocates a new data region * internally instead of taking an existing one. The allocation is done using - * ruby_calloc(). Hence it makes no sense for `data_type->function.dfree` to - * be anything other than ::RUBY_TYPED_DEFAULT_FREE. + * ruby_calloc(). * * @param klass Ruby level class of the object. * @param type Type name of the C struct. @@ -503,47 +566,36 @@ RBIMPL_SYMBOL_EXPORT_END() sizeof(type)) #endif -/** - * Obtains a C struct from inside of a wrapper Ruby object. - * - * @param obj An instance of ::RTypedData. - * @param type Type name of the C struct. - * @param data_type The data type describing `type`. - * @param sval Variable name of obtained C struct. - * @exception rb_eTypeError `obj` is not a kind of `data_type`. - * @return Unwrapped C struct that `obj` holds. - */ -#define TypedData_Get_Struct(obj,type,data_type,sval) \ - ((sval) = RBIMPL_CAST((type *)rb_check_typeddata((obj), (data_type)))) +static inline bool +rbimpl_typeddata_embedded_p(VALUE obj) +{ + return (RTYPEDDATA(obj)->type) & TYPED_DATA_EMBEDDED; +} +RBIMPL_ATTR_DEPRECATED_INTERNAL_ONLY() static inline bool RTYPEDDATA_EMBEDDED_P(VALUE obj) { -#if RUBY_DEBUG - if (RB_UNLIKELY(!RB_TYPE_P(obj, RUBY_T_DATA))) { - Check_Type(obj, RUBY_T_DATA); - RBIMPL_UNREACHABLE_RETURN(false); - } -#endif + RBIMPL_TYPEDDATA_PRECONDITION(obj, RBIMPL_UNREACHABLE_RETURN(false)); - return (RTYPEDDATA(obj)->type) & TYPED_DATA_EMBEDDED; + return rbimpl_typeddata_embedded_p(obj); } static inline void * -RTYPEDDATA_GET_DATA(VALUE obj) +rbimpl_typeddata_get_data(VALUE obj) { -#if RUBY_DEBUG - if (RB_UNLIKELY(!RB_TYPE_P(obj, RUBY_T_DATA))) { - Check_Type(obj, RUBY_T_DATA); - RBIMPL_UNREACHABLE_RETURN(false); - } -#endif + /* We reuse the data pointer in embedded TypedData. */ + return rbimpl_typeddata_embedded_p(obj) ? + RBIMPL_CAST((void *)&RTYPEDDATA_DATA(obj)) : + RTYPEDDATA_DATA(obj); +} - /* We reuse the data pointer in embedded TypedData. We can't use offsetof - * since RTypedData a non-POD type in C++. */ - const size_t embedded_typed_data_size = sizeof(struct RTypedData) - sizeof(void *); +static inline void * +RTYPEDDATA_GET_DATA(VALUE obj) +{ + RBIMPL_TYPEDDATA_PRECONDITION(obj, RBIMPL_UNREACHABLE_RETURN(NULL)); - return RTYPEDDATA_EMBEDDED_P(obj) ? (char *)obj + embedded_typed_data_size : RTYPEDDATA(obj)->data; + return rbimpl_typeddata_get_data(obj); } RBIMPL_ATTR_PURE() @@ -562,7 +614,28 @@ RBIMPL_ATTR_ARTIFICIAL() static inline bool rbimpl_rtypeddata_p(VALUE obj) { - return RTYPEDDATA(obj)->type & IS_TYPED_DATA; + return FL_TEST_RAW(obj, RUBY_TYPED_FL_IS_TYPED_DATA); +} + +RBIMPL_ATTR_PURE() +RBIMPL_ATTR_ARTIFICIAL() +/** + * @private + * + * Identical to rbimpl_rtypeddata_p(), except it is allowed to call on non-data + * objects. + * + * This is an implementation detail of inline functions defined in this file. + * People don't use it directly. + * + * @param[in] obj Object in question + * @retval true `obj` is an instance of ::RTypedData. + * @retval false `obj` is not an instance of ::RTypedData + */ +static inline bool +rbimpl_obj_typeddata_p(VALUE obj) +{ + return RB_TYPE_P(obj, RUBY_T_DATA) && rbimpl_rtypeddata_p(obj); } RBIMPL_ATTR_PURE_UNLESS_DEBUG() @@ -578,19 +651,14 @@ RBIMPL_ATTR_ARTIFICIAL() static inline bool RTYPEDDATA_P(VALUE obj) { -#if RUBY_DEBUG - if (RB_UNLIKELY(! RB_TYPE_P(obj, RUBY_T_DATA))) { - Check_Type(obj, RUBY_T_DATA); - RBIMPL_UNREACHABLE_RETURN(false); - } -#endif + RBIMPL_TYPEDDATA_PRECONDITION(obj, RBIMPL_UNREACHABLE_RETURN(false)); return rbimpl_rtypeddata_p(obj); } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() -/* :TODO: can this function be __attribute__((returns_nonnull)) or not? */ +RBIMPL_ATTR_RETURNS_NONNULL() /** * Queries for the type of given object. * @@ -598,19 +666,77 @@ RBIMPL_ATTR_ARTIFICIAL() * @return Data type struct that corresponds to `obj`. * @pre `obj` must be an instance of ::RTypedData. */ -static inline const struct rb_data_type_struct * +static inline const rb_data_type_t * RTYPEDDATA_TYPE(VALUE obj) { -#if RUBY_DEBUG - if (RB_UNLIKELY(! RTYPEDDATA_P(obj))) { - rb_unexpected_type(obj, RUBY_T_DATA); - RBIMPL_UNREACHABLE_RETURN(NULL); + RBIMPL_TYPEDDATA_PRECONDITION(obj, RBIMPL_UNREACHABLE_RETURN(NULL)); + + VALUE type = RTYPEDDATA(obj)->type & TYPED_DATA_PTR_MASK; + const rb_data_type_t *ptr = RBIMPL_CAST((const rb_data_type_t *)type); + RBIMPL_ASSERT_OR_ASSUME(ptr); + return ptr; +} + +RBIMPL_ATTR_ARTIFICIAL() +RBIMPL_ATTR_NONNULL(()) +static inline bool +rbimpl_typeddata_inherited_p_inline(const rb_data_type_t *child, const rb_data_type_t *parent) +{ + do { + if (RB_LIKELY(child == parent)) return true; + } while ((child = child->parent) != NULL); + return false; +} +#define rb_typeddata_inherited_p rbimpl_typeddata_inherited_p_inline + +RBIMPL_ATTR_ARTIFICIAL() +RBIMPL_ATTR_NONNULL((2)) +static inline bool +rbimpl_typeddata_is_kind_of_inline(VALUE obj, const rb_data_type_t *data_type) +{ + if (RB_UNLIKELY(!rbimpl_obj_typeddata_p(obj))) return false; + return rb_typeddata_inherited_p(RTYPEDDATA_TYPE(obj), data_type); +} +#define rb_typeddata_is_kind_of rbimpl_typeddata_is_kind_of_inline + +RBIMPL_ATTR_ARTIFICIAL() +RBIMPL_ATTR_NONNULL((2)) +/** + * @private + * + * This is an implementation detail of TypedData_Get_Struct(). Don't use it + * directly. + */ +static inline void * +rbimpl_check_typeddata(VALUE obj, const rb_data_type_t *expected_type) +{ + if (RB_UNLIKELY(!rbimpl_obj_typeddata_p(obj))) { + rb_unexpected_object_type(obj, expected_type->wrap_struct_name); } -#endif - return (const struct rb_data_type_struct *)(RTYPEDDATA(obj)->type & TYPED_DATA_PTR_MASK); + const rb_data_type_t *actual_type = RTYPEDDATA_TYPE(obj); + if (RB_UNLIKELY(!rb_typeddata_inherited_p(actual_type, expected_type))){ + rb_unexpected_typeddata(actual_type, expected_type); + } + + return RTYPEDDATA_GET_DATA(obj); } + +/** + * Obtains a C struct from inside of a wrapper Ruby object. + * + * @param obj An instance of ::RTypedData. + * @param type Type name of the C struct. + * @param data_type The data type describing `type`. + * @param sval Variable name of obtained C struct. + * @exception rb_eTypeError `obj` is not a kind of `data_type`. + * @return Unwrapped C struct that `obj` holds. + */ +#define TypedData_Get_Struct(obj,type,data_type,sval) \ + ((sval) = RBIMPL_CAST((type *)rbimpl_check_typeddata((obj), (data_type)))) + +RBIMPL_ATTR_NONNULL((2)) /** * While we don't stop you from using this function, it seems to be an * implementation detail of #TypedData_Make_Struct, which is preferred over @@ -632,12 +758,4 @@ rb_data_typed_object_make(VALUE klass, const rb_data_type_t *type, void **datap, return result; } -RBIMPL_ATTR_DEPRECATED(("by: rb_data_typed_object_wrap")) -/** @deprecated This function was renamed to rb_data_typed_object_wrap(). */ -static inline VALUE -rb_data_typed_object_alloc(VALUE klass, void *datap, const rb_data_type_t *type) -{ - return rb_data_typed_object_wrap(klass, datap, type); -} - #endif /* RBIMPL_RTYPEDDATA_H */ diff --git a/include/ruby/internal/ctype.h b/include/ruby/internal/ctype.h index 0f7ca6c516..8b24026311 100644 --- a/include/ruby/internal/ctype.h +++ b/include/ruby/internal/ctype.h @@ -498,8 +498,8 @@ RBIMPL_ATTR_ARTIFICIAL() * Our own locale-insensitive version of `tolower(3)`. * * @param[in] c Byte in question to convert. - * @retval c The byte is not listed in in IEEE 1003.1 section - * 7.3.1.1 "upper". + * @retval c The byte is not listed in IEEE 1003.1 section 7.3.1.1 + * "upper". * @retval otherwise Byte converted using the map defined in IEEE 1003.1 * section 7.3.1 "tolower". * @note Not only does this function works under the POSIX Locale, but diff --git a/include/ruby/internal/error.h b/include/ruby/internal/error.h index 3ff885b2b1..5bf82bfe7d 100644 --- a/include/ruby/internal/error.h +++ b/include/ruby/internal/error.h @@ -421,11 +421,12 @@ void rb_readwrite_syserr_fail(enum rb_io_wait_readwrite waiting, int err, const RBIMPL_ATTR_COLD() RBIMPL_ATTR_NORETURN() /** + * @private + * * Fails with the given object's type incompatibility to the type. * - * It seems this function is visible from extension libraries only because - * RTYPEDDATA_TYPE() uses it on RUBY_DEBUG. So you can basically ignore it; - * use some other fine-grained method instead. + * This is an implementation detail of Check_Type. People don't use it + * directly. * * @param[in] self The object in question. * @param[in] t Expected type of the object. diff --git a/include/ruby/internal/eval.h b/include/ruby/internal/eval.h index 5bcbb97746..23aa1d9580 100644 --- a/include/ruby/internal/eval.h +++ b/include/ruby/internal/eval.h @@ -155,7 +155,8 @@ VALUE rb_funcallv(VALUE recv, ID mid, int argc, const VALUE *argv); * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @exception rb_eNoMethodError No such method. * @exception rb_eException Any exceptions happen inside. * @return What the method evaluates to. @@ -189,7 +190,8 @@ VALUE rb_funcallv_public(VALUE recv, ID mid, int argc, const VALUE *argv); * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @exception rb_eNoMethodError No such method. * @exception rb_eNoMethodError The method is private or protected. * @exception rb_eException Any exceptions happen inside. @@ -261,7 +263,8 @@ VALUE rb_funcall_passing_block(VALUE recv, ID mid, int argc, const VALUE *argv); * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @exception rb_eNoMethodError No such method. * @exception rb_eNoMethodError The method is private or protected. * @exception rb_eException Any exceptions happen inside. @@ -307,7 +310,8 @@ VALUE rb_funcall_with_block(VALUE recv, ID mid, int argc, const VALUE *argv, VAL * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @exception rb_eNoMethodError No such method. * @exception rb_eNoMethodError The method is private or protected. * @exception rb_eException Any exceptions happen inside. @@ -335,7 +339,8 @@ VALUE rb_call_super(int argc, const VALUE *argv); * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @exception rb_eNoMethodError No super method are there. * @exception rb_eException Any exceptions happen inside. * @return What the super method evaluates to. diff --git a/include/ruby/internal/fl_type.h b/include/ruby/internal/fl_type.h index f80f65ef8f..2afb3f1fa3 100644 --- a/include/ruby/internal/fl_type.h +++ b/include/ruby/internal/fl_type.h @@ -59,10 +59,8 @@ #define FL_WB_PROTECTED RBIMPL_CAST((VALUE)RUBY_FL_WB_PROTECTED) /**< @old{RUBY_FL_WB_PROTECTED} */ #define FL_PROMOTED RBIMPL_CAST((VALUE)RUBY_FL_PROMOTED) /**< @old{RUBY_FL_PROMOTED} */ #define FL_FINALIZE RBIMPL_CAST((VALUE)RUBY_FL_FINALIZE) /**< @old{RUBY_FL_FINALIZE} */ -#define FL_TAINT RBIMPL_CAST((VALUE)RUBY_FL_TAINT) /**< @old{RUBY_FL_TAINT} */ #define FL_SHAREABLE RBIMPL_CAST((VALUE)RUBY_FL_SHAREABLE) /**< @old{RUBY_FL_SHAREABLE} */ #define FL_UNTRUSTED RBIMPL_CAST((VALUE)RUBY_FL_UNTRUSTED) /**< @old{RUBY_FL_UNTRUSTED} */ -#define FL_SEEN_OBJ_ID RBIMPL_CAST((VALUE)RUBY_FL_SEEN_OBJ_ID) /**< @old{RUBY_FL_SEEN_OBJ_ID} */ #define FL_EXIVAR RBIMPL_CAST((VALUE)RUBY_FL_EXIVAR) /**< @old{RUBY_FL_EXIVAR} */ #define FL_FREEZE RBIMPL_CAST((VALUE)RUBY_FL_FREEZE) /**< @old{RUBY_FL_FREEZE} */ @@ -218,11 +216,11 @@ ruby_fl_type { RUBY_FL_PROMOTED = (1<<5), /** - * This flag is no longer in use + * This flag meaning is type dependent, currently only used by T_DATA. * * @internal */ - RUBY_FL_UNUSED6 = (1<<6), + RUBY_FL_USERPRIV0 = (1<<6), /** * This flag has something to do with finalisers. A ruby object can have @@ -239,16 +237,16 @@ ruby_fl_type { RUBY_FL_FINALIZE = (1<<7), /** - * @deprecated This flag once was a thing back in the old days, but makes - * no sense any longer today. Exists here for backwards + * @deprecated This flag was an implementation detail that should never have + * no been exposed. Exists here for backwards * compatibility only. You can safely forget about it. */ - RUBY_FL_TAINT + RUBY_FL_EXIVAR #if defined(RBIMPL_HAVE_ENUM_ATTRIBUTE) - RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) + RBIMPL_ATTR_DEPRECATED(("FL_EXIVAR is an outdated implementation detail, it should not be used.")) #elif defined(_MSC_VER) -# pragma deprecated(RUBY_FL_TAINT) +# pragma deprecated(RUBY_FL_EXIVAR) #endif = 0, @@ -265,52 +263,19 @@ ruby_fl_type { */ RUBY_FL_SHAREABLE = (1<<8), - /** - * @deprecated This flag once was a thing back in the old days, but makes - * no sense any longer today. Exists here for backwards - * compatibility only. You can safely forget about it. - */ - RUBY_FL_UNTRUSTED - -#if defined(RBIMPL_HAVE_ENUM_ATTRIBUTE) - RBIMPL_ATTR_DEPRECATED(("trustedness turned out to be a wrong idea.")) -#elif defined(_MSC_VER) -# pragma deprecated(RUBY_FL_UNTRUSTED) -#endif - - = 0, + /** + * This object weakly refers to other objects. + * + * @internal + */ + RUBY_FL_WEAK_REFERENCE = (1<<9), - /** - * This flag has something to do with object IDs. Unlike in the old days, - * an object's object ID (that a user can query using `Object#object_id`) - * is no longer its physical address represented using Ruby level integers. - * It is now a monotonic-increasing integer unrelated to the underlying - * memory arrangement. Object IDs are assigned when necessary; objects are - * born without one, and will eventually have such property when queried. - * The interpreter has to manage which one is which. This is the flag that - * helps the management. Objects with this flag set are the ones with - * object IDs assigned. - * - * @internal - * - * But honestly, @shyouhei doesn't think this flag should be visible from - * 3rd parties. It must be an implementation detail that they should never - * know. Might better be hidden. - */ - RUBY_FL_SEEN_OBJ_ID = (1<<9), - - /** - * This flag has something to do with instance variables. 3rd parties need - * not know, but there are several ways to store an object's instance - * variables. Objects with this flag use so-called "generic" backend - * storage. This distinction is purely an implementation detail. People - * need not be aware of this working behind-the-scene. - * - * @internal - * - * As of writing everything except ::RObject and RModule use this scheme. - */ - RUBY_FL_EXIVAR = (1<<10), + /** + * This flag is no longer in use + * + * @internal + */ + RUBY_FL_UNUSED10 = (1<<10), /** * This flag has something to do with data immutability. When this flag is @@ -398,23 +363,6 @@ ruby_fl_type { RUBY_FL_SINGLETON = RUBY_FL_USER1, }; -enum { - /** - * @deprecated This flag once was a thing back in the old days, but makes - * no sense any longer today. Exists here for backwards - * compatibility only. You can safely forget about it. - */ - RUBY_FL_DUPPED - -#if defined(RBIMPL_HAVE_ENUM_ATTRIBUTE) - RBIMPL_ATTR_DEPRECATED(("It seems there is no actual usage of this enum.")) -#elif defined(_MSC_VER) -# pragma deprecated(RUBY_FL_DUPPED) -#endif - - = (int)RUBY_T_MASK | (int)RUBY_FL_EXIVAR -}; - #undef RBIMPL_HAVE_ENUM_ATTRIBUTE RBIMPL_SYMBOL_EXPORT_BEGIN() @@ -446,10 +394,8 @@ RB_FL_ABLE(VALUE obj) if (RB_SPECIAL_CONST_P(obj)) { return false; } - else if (RB_TYPE_P(obj, RUBY_T_NODE)) { - return false; - } else { + RBIMPL_ASSERT_OR_ASSUME(!RB_TYPE_P(obj, RUBY_T_NODE)); return true; } } @@ -743,128 +689,6 @@ RB_FL_REVERSE(VALUE obj, VALUE flags) RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() -RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) -/** - * @deprecated This function once was a thing in the old days, but makes no - * sense any longer today. Exists here for backwards - * compatibility only. You can safely forget about it. - * - * @param[in] obj Object in question. - * @return false always. - */ -static inline bool -RB_OBJ_TAINTABLE(VALUE obj) -{ - (void)obj; - return false; -} - -RBIMPL_ATTR_PURE_UNLESS_DEBUG() -RBIMPL_ATTR_ARTIFICIAL() -RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) -/** - * @deprecated This function once was a thing in the old days, but makes no - * sense any longer today. Exists here for backwards - * compatibility only. You can safely forget about it. - * - * @param[in] obj Object in question. - * @return false always. - */ -static inline VALUE -RB_OBJ_TAINTED_RAW(VALUE obj) -{ - (void)obj; - return false; -} - -RBIMPL_ATTR_PURE_UNLESS_DEBUG() -RBIMPL_ATTR_ARTIFICIAL() -RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) -/** - * @deprecated This function once was a thing in the old days, but makes no - * sense any longer today. Exists here for backwards - * compatibility only. You can safely forget about it. - * - * @param[in] obj Object in question. - * @return false always. - */ -static inline bool -RB_OBJ_TAINTED(VALUE obj) -{ - (void)obj; - return false; -} - -RBIMPL_ATTR_ARTIFICIAL() -RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) -/** - * @deprecated This function once was a thing in the old days, but makes no - * sense any longer today. Exists here for backwards - * compatibility only. You can safely forget about it. - * - * @param[in] obj Object in question. - */ -static inline void -RB_OBJ_TAINT_RAW(VALUE obj) -{ - (void)obj; - return; -} - -RBIMPL_ATTR_ARTIFICIAL() -RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) -/** - * @deprecated This function once was a thing in the old days, but makes no - * sense any longer today. Exists here for backwards - * compatibility only. You can safely forget about it. - * - * @param[in] obj Object in question. - */ -static inline void -RB_OBJ_TAINT(VALUE obj) -{ - (void)obj; - return; -} - -RBIMPL_ATTR_ARTIFICIAL() -RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) -/** - * @deprecated This function once was a thing in the old days, but makes no - * sense any longer today. Exists here for backwards - * compatibility only. You can safely forget about it. - * - * @param[in] dst Victim object. - * @param[in] src Infectant object. - */ -static inline void -RB_OBJ_INFECT_RAW(VALUE dst, VALUE src) -{ - (void)dst; - (void)src; - return; -} - -RBIMPL_ATTR_ARTIFICIAL() -RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) -/** - * @deprecated This function once was a thing in the old days, but makes no - * sense any longer today. Exists here for backwards - * compatibility only. You can safely forget about it. - * - * @param[in] dst Victim object. - * @param[in] src Infectant object. - */ -static inline void -RB_OBJ_INFECT(VALUE dst, VALUE src) -{ - (void)dst; - (void)src; - return; -} - -RBIMPL_ATTR_PURE_UNLESS_DEBUG() -RBIMPL_ATTR_ARTIFICIAL() /** * This is an implementation detail of RB_OBJ_FROZEN(). 3rd parties need not * use this. Just always use RB_OBJ_FROZEN(). diff --git a/include/ruby/internal/gc.h b/include/ruby/internal/gc.h index 5ab3bb266e..21c2b670b3 100644 --- a/include/ruby/internal/gc.h +++ b/include/ruby/internal/gc.h @@ -823,7 +823,4 @@ rb_obj_write( return a; } -RBIMPL_ATTR_DEPRECATED(("Will be removed soon")) -static inline void rb_gc_force_recycle(VALUE obj){} - #endif /* RBIMPL_GC_H */ diff --git a/include/ruby/internal/globals.h b/include/ruby/internal/globals.h index 60d8e5309a..9beb215c0c 100644 --- a/include/ruby/internal/globals.h +++ b/include/ruby/internal/globals.h @@ -68,6 +68,7 @@ RUBY_EXTERN VALUE rb_cBasicObject; /**< `BasicObject` class. */ RUBY_EXTERN VALUE rb_cObject; /**< `Object` class. */ RUBY_EXTERN VALUE rb_cArray; /**< `Array` class. */ RUBY_EXTERN VALUE rb_cBinding; /**< `Binding` class. */ +RUBY_EXTERN VALUE rb_cBox; /**< `Ruby::Box` class. */ RUBY_EXTERN VALUE rb_cClass; /**< `Class` class. */ RUBY_EXTERN VALUE rb_cDir; /**< `Dir` class. */ RUBY_EXTERN VALUE rb_cEncoding; /**< `Encoding` class. */ @@ -91,6 +92,7 @@ RUBY_EXTERN VALUE rb_cRandom; /**< `Random` class. */ RUBY_EXTERN VALUE rb_cRange; /**< `Range` class. */ RUBY_EXTERN VALUE rb_cRational; /**< `Rational` class. */ RUBY_EXTERN VALUE rb_cRegexp; /**< `Regexp` class. */ +RUBY_EXTERN VALUE rb_cSet; /**< `Set` class. */ RUBY_EXTERN VALUE rb_cStat; /**< `File::Stat` class. */ RUBY_EXTERN VALUE rb_cString; /**< `String` class. */ RUBY_EXTERN VALUE rb_cStruct; /**< `Struct` class. */ diff --git a/include/ruby/internal/intern/complex.h b/include/ruby/internal/intern/complex.h index e111bd8ced..1efc093631 100644 --- a/include/ruby/internal/intern/complex.h +++ b/include/ruby/internal/intern/complex.h @@ -87,10 +87,6 @@ VALUE rb_complex_new(VALUE real, VALUE imag); */ VALUE rb_complex_new_polar(VALUE abs, VALUE arg); -RBIMPL_ATTR_DEPRECATED(("by: rb_complex_new_polar")) -/** @old{rb_complex_new_polar} */ -VALUE rb_complex_polar(VALUE abs, VALUE arg); - RBIMPL_ATTR_PURE() /** * Queries the real part of the passed Complex. diff --git a/include/ruby/internal/intern/cont.h b/include/ruby/internal/intern/cont.h index 32647f48aa..2d813ceb9d 100644 --- a/include/ruby/internal/intern/cont.h +++ b/include/ruby/internal/intern/cont.h @@ -148,7 +148,8 @@ VALUE rb_fiber_resume(VALUE fiber, int argc, const VALUE *argv); * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @exception rb_eFiberError `fiber` is terminated etc. * @exception rb_eException Any exceptions happen in `fiber`. * @return Either what was yielded or the last value of the fiber body. @@ -192,7 +193,8 @@ VALUE rb_fiber_yield(int argc, const VALUE *argv); * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @exception rb_eException What was raised using `Fiber#raise`. * @return (See rb_fiber_resume() for details) */ @@ -247,7 +249,8 @@ VALUE rb_fiber_transfer(VALUE fiber, int argc, const VALUE *argv); * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @exception rb_eFiberError (See above) * @exception rb_eException What was raised using `Fiber#raise`. * @return (See rb_fiber_resume() for details) @@ -275,7 +278,7 @@ VALUE rb_fiber_transfer_kw(VALUE fiber, int argc, const VALUE *argv, int kw_spla * @exception rb_eFiberError `fiber` is terminated etc. * @return (See rb_fiber_resume() for details) */ -VALUE rb_fiber_raise(VALUE fiber, int argc, const VALUE *argv); +VALUE rb_fiber_raise(VALUE fiber, int argc, VALUE *argv); RBIMPL_SYMBOL_EXPORT_END() diff --git a/include/ruby/internal/intern/enumerator.h b/include/ruby/internal/intern/enumerator.h index 20e5d7c6fc..00804d786a 100644 --- a/include/ruby/internal/intern/enumerator.h +++ b/include/ruby/internal/intern/enumerator.h @@ -100,7 +100,8 @@ VALUE rb_enumeratorize_with_size(VALUE recv, VALUE meth, int argc, const VALUE * * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @exception rb_eTypeError `meth` is not an instance of ::rb_cSymbol. * @return A new instance of ::rb_cEnumerator which, when yielded, * enumerates by calling `meth` on `recv` with `argv`. @@ -186,7 +187,8 @@ RBIMPL_SYMBOL_EXPORT_END() * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @return A new instance of ::rb_cEnumerator which, when yielded, * enumerates by calling the current method on `recv` with `argv`. */ @@ -220,7 +222,8 @@ RBIMPL_SYMBOL_EXPORT_END() * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @note This macro may return inside. */ #define RETURN_SIZED_ENUMERATOR_KW(obj, argc, argv, size_fn, kw_splat) do { \ @@ -250,7 +253,8 @@ RBIMPL_SYMBOL_EXPORT_END() * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @note This macro may return inside. */ #define RETURN_ENUMERATOR_KW(obj, argc, argv, kw_splat) \ diff --git a/include/ruby/internal/intern/file.h b/include/ruby/internal/intern/file.h index b669758d21..8508b7ab9e 100644 --- a/include/ruby/internal/intern/file.h +++ b/include/ruby/internal/intern/file.h @@ -211,22 +211,6 @@ int rb_is_absolute_path(const char *path); */ rb_off_t rb_file_size(VALUE file); -#ifdef RBIMPL_ATTR_DEPRECATED_INTERNAL_ONLY -RBIMPL_ATTR_DEPRECATED_INTERNAL_ONLY() -#endif -/** - * If the PATH_SEPARATOR-separated list of directory names contains the name of - * a world-writable directory, issue a warning for it. This may do nothing on - * some platforms. - * - * @param[in] path A local path. - * @retval 0 The "check" succeeded. - * @retval otherwise The "check" failed. - * @note This feature may be disabled by setting `ENABLE_PATH_CHECK` - * macro to zero at compilation time. - */ -int rb_path_check(const char *path); - RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_FILE_H */ diff --git a/include/ruby/internal/intern/object.h b/include/ruby/internal/intern/object.h index 9daad7d046..3897639a0a 100644 --- a/include/ruby/internal/intern/object.h +++ b/include/ruby/internal/intern/object.h @@ -80,7 +80,8 @@ VALUE rb_class_new_instance(int argc, const VALUE *argv, VALUE klass); * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @exception rb_eTypeError `klass`'s allocator is undefined. * @exception rb_eException Any exceptions can happen inside. * @return An allocated new instance of `klass`. diff --git a/include/ruby/internal/intern/proc.h b/include/ruby/internal/intern/proc.h index b8c3c5e146..2635d672eb 100644 --- a/include/ruby/internal/intern/proc.h +++ b/include/ruby/internal/intern/proc.h @@ -101,7 +101,8 @@ VALUE rb_proc_call(VALUE recv, VALUE args); * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `args`' last is not a keyword argument. * - RB_PASS_KEYWORDS `args`' last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @exception rb_eException Any exceptions happen inside. * @return What the proc evaluates to. */ @@ -141,7 +142,8 @@ VALUE rb_proc_call_with_block(VALUE recv, int argc, const VALUE *argv, VALUE pro * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `args`' last is not a keyword argument. * - RB_PASS_KEYWORDS `args`' last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @exception rb_eException Any exceptions happen inside. * @return What the proc evaluates to. */ @@ -245,7 +247,8 @@ VALUE rb_method_call(int argc, const VALUE *argv, VALUE recv); * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `args`' last is not a keyword argument. * - RB_PASS_KEYWORDS `args`' last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @exception rb_eTypeError `recv` is not a method. * @exception rb_eException Any exceptions happen inside. * @return What the method returns. @@ -279,7 +282,8 @@ VALUE rb_method_call_with_block(int argc, const VALUE *argv, VALUE recv, VALUE p * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `args`' last is not a keyword argument. * - RB_PASS_KEYWORDS `args`' last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @exception rb_eTypeError `recv` is not a method. * @exception rb_eException Any exceptions happen inside. * @return What the method returns. diff --git a/include/ruby/internal/intern/select.h b/include/ruby/internal/intern/select.h index 6ba84c6e63..ba75213618 100644 --- a/include/ruby/internal/intern/select.h +++ b/include/ruby/internal/intern/select.h @@ -72,6 +72,8 @@ struct timeval; * someone else, vastly varies among operating systems. You would better avoid * touching an fd from more than one threads. * + * NOTE: this function is used in native extensions, so change its API with care. + * * @internal * * Although any file descriptors are possible here, it makes completely no diff --git a/include/ruby/internal/intern/set.h b/include/ruby/internal/intern/set.h new file mode 100644 index 0000000000..f4ff8665e2 --- /dev/null +++ b/include/ruby/internal/intern/set.h @@ -0,0 +1,111 @@ +#ifndef RBIMPL_INTERN_SET_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_SET_H +/** + * @file + * @author Ruby developers <ruby-core@ruby-lang.org> + * @copyright This file is a part of the programming language Ruby. + * Permission is hereby granted, to either redistribute and/or + * modify this file, provided that the conditions mentioned in the + * file COPYING are met. Consult the file for details. + * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are + * implementation details. Don't take them as canon. They could + * rapidly appear then vanish. The name (path) of this header file + * is also an implementation detail. Do not expect it to persist + * at the place it is now. Developers are free to move it anywhere + * anytime at will. + * @note To ruby-core: remember that this header can be possibly + * recursively included from extension libraries written in C++. + * Do not expect for instance `__VA_ARGS__` is always available. + * We assume C99 for ruby itself but we don't assume languages of + * extension libraries. They could be written in C++98. + * @brief Public APIs related to ::rb_cSet. + */ +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/* set.c */ + +RBIMPL_ATTR_NONNULL(()) +/** + * Iterates over a set. Calls func with each element of the set and the + * argument given. func should return ST_CONTINUE, ST_STOP, or ST_DELETE. + * + * @param[in] set An instance of ::rb_cSet to iterate over. + * @param[in] func Callback function to yield. + * @param[in] arg Passed as-is to `func`. + * @exception rb_eRuntimeError `set` was tampered during iterating. + */ +void rb_set_foreach(VALUE set, int (*func)(VALUE element, VALUE arg), VALUE arg); + +/** + * Creates a new, empty set object. + * + * @return An allocated new instance of ::rb_cSet. + */ +VALUE rb_set_new(void); + +/** + * Identical to rb_set_new(), except it additionally specifies how many elements + * it is expected to contain. This way you can create a set that is large enough + * for your need. For large sets, it means it won't need to be reallocated + * much, improving performance. + * + * @param[in] capa Designed capacity of the set. + * @return An empty Set, whose capacity is `capa`. + */ +VALUE rb_set_new_capa(size_t capa); + +/** + * Whether the set contains the given element. + * + * @param[in] set Set to look into. + * @param[in] element Set element to look for. + * @return true if element is in the set, falst otherwise. + */ +bool rb_set_lookup(VALUE set, VALUE element); + +/** + * Adds element to set. + * + * @param[in] set Target set table to modify. + * @param[in] element Arbitrary Ruby object. + * @exception rb_eFrozenError `set` is frozen. + * @return true if element was not already in set, false otherwise + * @post `element` is in `set`. + */ +bool rb_set_add(VALUE set, VALUE element); + +/** + * Removes all entries from set. + * + * @param[out] set Target to clear. + * @exception rb_eFrozenError `set`is frozen. + * @return The passed `set` + * @post `set` has no elements. + */ +VALUE rb_set_clear(VALUE set); + +/** + * Removes the element from from set. + * + * @param[in] set Target set to modify. + * @param[in] element Key to delete. + * @retval true if element was already in set, false otherwise + * @post `set` does not have `element` as an element. + */ +bool rb_set_delete(VALUE set, VALUE element); + +/** + * Returns the number of elements in the set. + * + * @param[in] set A set object. + * @return The size of the set. + */ +size_t rb_set_size(VALUE set); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_INTERN_SET_H */ diff --git a/include/ruby/internal/intern/string.h b/include/ruby/internal/intern/string.h index 4573ec1262..2ec08fc81f 100644 --- a/include/ruby/internal/intern/string.h +++ b/include/ruby/internal/intern/string.h @@ -444,8 +444,8 @@ VALUE rb_str_to_interned_str(VALUE str); * terminating NUL character. * @exception rb_eArgError `len` is negative. * @return A found or created instance of ::rb_cString, of `len` bytes - * length, of "binary" encoding, whose contents are identical to - * that of `ptr`. + * length, of US-ASCII or "binary" encoding, whose contents are + * identical to that of `ptr`. * @pre At least `len` bytes of continuous memory region shall be * accessible via `ptr`. */ @@ -591,10 +591,9 @@ void rb_must_asciicompat(VALUE obj); VALUE rb_str_dup(VALUE str); /** - * I guess there is no use case of this function in extension libraries, but - * this is a routine identical to rb_str_dup(), except it always creates an - * instance of ::rb_cString regardless of the given object's class. This makes - * the most sense when the passed string is formerly hidden by rb_obj_hide(). + * Like rb_str_dup(), but always create an instance of ::rb_cString + * regardless of the given object's class. This makes the most sense + * when the passed string is formerly hidden by rb_obj_hide(). * * @param[in] str A string, possibly hidden. * @return A duplicated new instance of ::rb_cString. @@ -970,8 +969,8 @@ st_index_t rb_str_hash(VALUE str); * * @param[in] str1 A string. * @param[in] str2 Another string. - * @retval 1 They have identical contents, length, and encodings. - * @retval 0 Otherwise. + * @retval 0 They have identical contents, length, and encodings. + * @retval 1 Otherwise. * @pre Both objects must not be any arbitrary objects except * ::RString. * diff --git a/include/ruby/internal/intern/thread.h b/include/ruby/internal/intern/thread.h index 716375acd7..4d87452745 100644 --- a/include/ruby/internal/intern/thread.h +++ b/include/ruby/internal/intern/thread.h @@ -61,10 +61,10 @@ int rb_thread_wait_fd(int fd); int rb_thread_fd_writable(int fd); /** - * Notifies a closing of a file descriptor to other threads. Multiple threads - * can wait for the given file descriptor at once. If such file descriptor is - * closed, threads need to start propagating their exceptions. This is the API - * to kick that process. + * This funciton is now a no-op. It was previously used to interrupt threads + * that were using the given file descriptor and wait for them to finish. + * + * @deprecated Use IO with RUBY_IO_MODE_EXTERNAL and `rb_io_close` instead. * * @param[in] fd A file descriptor. * @note This function blocks until all the threads waiting for such fd diff --git a/include/ruby/internal/intern/vm.h b/include/ruby/internal/intern/vm.h index 29e0c7f534..f0b54c702c 100644 --- a/include/ruby/internal/intern/vm.h +++ b/include/ruby/internal/intern/vm.h @@ -89,7 +89,8 @@ VALUE rb_check_funcall(VALUE recv, ID mid, int argc, const VALUE *argv); * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @retval RUBY_Qundef `recv` doesn't respond to `mid`. * @retval otherwise What the method evaluates to. */ @@ -106,9 +107,11 @@ VALUE rb_check_funcall_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int k * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `arg`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `arg`'s last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @return What the command evaluates to. */ +RBIMPL_ATTR_DEPRECATED_INTERNAL(4.0) VALUE rb_eval_cmd_kw(VALUE cmd, VALUE arg, int kw_splat); /** diff --git a/include/ruby/internal/iterator.h b/include/ruby/internal/iterator.h index 5f706460f8..891045363e 100644 --- a/include/ruby/internal/iterator.h +++ b/include/ruby/internal/iterator.h @@ -265,48 +265,6 @@ int rb_block_given_p(void); */ void rb_need_block(void); -#ifndef __cplusplus -RBIMPL_ATTR_DEPRECATED(("by: rb_block_call since 1.9")) -#endif -/** - * Old way to iterate a block. - * - * @deprecated This is an old API. Use rb_block_call() instead. - * @warning The passed function must at least once call a ruby method - * (to handle interrupts etc.) - * @param[in] func1 A function that could yield a value. - * @param[in,out] data1 Passed to `func1` - * @param[in] proc A function acts as a block. - * @param[in,out] data2 Passed to `proc` as the data2 parameter. - * @return What `func1` returns. - */ -VALUE rb_iterate(VALUE (*func1)(VALUE), VALUE data1, rb_block_call_func_t proc, VALUE data2); - -#ifdef __cplusplus -namespace ruby { -namespace backward { -/** - * Old way to iterate a block. - * - * @deprecated This is an old API. Use rb_block_call() instead. - * @warning The passed function must at least once call a ruby method - * (to handle interrupts etc.) - * @param[in] iter A function that could yield a value. - * @param[in,out] data1 Passed to `func1` - * @param[in] bl A function acts as a block. - * @param[in,out] data2 Passed to `proc` as the data2 parameter. - * @return What `func1` returns. - */ -static inline VALUE -rb_iterate_deprecated(VALUE (*iter)(VALUE), VALUE data1, rb_block_call_func_t bl, VALUE data2) -{ - return ::rb_iterate(iter, data1, bl, data2); -}}} - -RBIMPL_ATTR_DEPRECATED(("by: rb_block_call since 1.9")) -VALUE rb_iterate(VALUE (*func1)(VALUE), VALUE data1, rb_block_call_func_t proc, VALUE data2); -#endif - /** * Identical to rb_funcallv(), except it additionally passes a function as a * block. When the method yields, `proc` is called with the yielded value as @@ -337,7 +295,8 @@ VALUE rb_block_call(VALUE obj, ID mid, int argc, const VALUE *argv, rb_block_cal * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. - * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. + * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method + * was called with keyword arguments. * @return What `obj.mid` returns. */ VALUE rb_block_call_kw(VALUE obj, ID mid, int argc, const VALUE *argv, rb_block_call_func_t proc, VALUE data2, int kw_splat); diff --git a/include/ruby/internal/memory.h b/include/ruby/internal/memory.h index 9fc6c39efc..cd099f85db 100644 --- a/include/ruby/internal/memory.h +++ b/include/ruby/internal/memory.h @@ -408,7 +408,8 @@ typedef uint128_t DSIZE_T; /** * @private * - * This is an implementation detail of rbimpl_size_mul_overflow(). + * This is an implementation detail of rbimpl_size_mul_overflow() and + * rbimpl_size_add_overflow(). * * @internal * @@ -416,9 +417,9 @@ typedef uint128_t DSIZE_T; * 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; /**< Whether overflow happened or not. */ - size_t right; /**< Multiplication result. */ +struct rbimpl_size_overflow_tag { + bool overflowed; /**< Whether overflow happened or not. */ + size_t result; /**< Calculation result. */ }; RBIMPL_SYMBOL_EXPORT_BEGIN() @@ -572,46 +573,46 @@ RBIMPL_ATTR_CONST() * * @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`. + * @return `{ overflowed, result }`, where `overflowed` is whether there is + * an integer overflow or not, and `result` 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 +static inline struct rbimpl_size_overflow_tag rbimpl_size_mul_overflow(size_t x, size_t y) { - struct rbimpl_size_mul_overflow_tag ret = { false, 0, }; + struct rbimpl_size_overflow_tag ret = { false, 0, }; #if defined(ckd_mul) - ret.left = ckd_mul(&ret.right, x, y); + ret.overflowed = ckd_mul(&ret.result, x, y); #elif RBIMPL_HAS_BUILTIN(__builtin_mul_overflow) - ret.left = __builtin_mul_overflow(x, y, &ret.right); + ret.overflowed = __builtin_mul_overflow(x, y, &ret.result); #elif defined(DSIZE_T) RB_GNUC_EXTENSION DSIZE_T dx = x; RB_GNUC_EXTENSION DSIZE_T dy = y; RB_GNUC_EXTENSION DSIZE_T dz = dx * dy; - ret.left = dz > SIZE_MAX; - ret.right = RBIMPL_CAST((size_t)dz); + ret.overflowed = dz > SIZE_MAX; + ret.result = RBIMPL_CAST((size_t)dz); #elif defined(_MSC_VER) && defined(_M_AMD64) unsigned __int64 dp = 0; unsigned __int64 dz = _umul128(x, y, &dp); - ret.left = RBIMPL_CAST((bool)dp); - ret.right = RBIMPL_CAST((size_t)dz); + ret.overflowed = RBIMPL_CAST((bool)dp); + ret.result = RBIMPL_CAST((size_t)dz); #elif defined(_MSC_VER) && defined(_M_ARM64) - ret.left = __umulh(x, y) != 0; - ret.right = x * y; + ret.overflowed = __umulh(x, y) != 0; + ret.result = x * y; #else /* https://wiki.sei.cmu.edu/confluence/display/c/INT30-C.+Ensure+that+unsigned+integer+operations+do+not+wrap */ - ret.left = (y != 0) && (x > SIZE_MAX / y); - ret.right = x * y; + ret.overflowed = (y != 0) && (x > SIZE_MAX / y); + ret.result = x * y; #endif return ret; @@ -635,11 +636,11 @@ rbimpl_size_mul_overflow(size_t x, size_t y) static inline size_t rbimpl_size_mul_or_raise(size_t x, size_t y) { - struct rbimpl_size_mul_overflow_tag size = + struct rbimpl_size_overflow_tag size = rbimpl_size_mul_overflow(x, y); - if (RB_LIKELY(! size.left)) { - return size.right; + if (RB_LIKELY(! size.overflowed)) { + return size.result; } else { ruby_malloc_size_overflow(x, y); @@ -662,33 +663,33 @@ RBIMPL_ATTR_CONST() * * @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`. + * @return `{ overflowed, result }`, where `overflowed` is whether there is + * an integer overflow or not, and `result` is a (possibly + * overflowed) result of `x` + `y`. * * @internal */ -static inline struct rbimpl_size_mul_overflow_tag +static inline struct rbimpl_size_overflow_tag rbimpl_size_add_overflow(size_t x, size_t y) { - struct rbimpl_size_mul_overflow_tag ret = { false, 0, }; + struct rbimpl_size_overflow_tag ret = { false, 0, }; #if defined(ckd_add) - ret.left = ckd_add(&ret.right, x, y); + ret.overflowed = ckd_add(&ret.result, x, y); #elif RBIMPL_HAS_BUILTIN(__builtin_add_overflow) - ret.left = __builtin_add_overflow(x, y, &ret.right); + ret.overflowed = __builtin_add_overflow(x, y, &ret.result); #elif defined(DSIZE_T) RB_GNUC_EXTENSION DSIZE_T dx = x; RB_GNUC_EXTENSION DSIZE_T dy = y; RB_GNUC_EXTENSION DSIZE_T dz = dx + dy; - ret.left = dz > SIZE_MAX; - ret.right = (size_t)dz; + ret.overflowed = dz > SIZE_MAX; + ret.result = (size_t)dz; #else - ret.right = x + y; - ret.left = ret.right < y; + ret.result = x + y; + ret.overflowed = ret.result < y; #endif @@ -710,11 +711,11 @@ rbimpl_size_add_overflow(size_t x, size_t y) static inline size_t rbimpl_size_add_or_raise(size_t x, size_t y) { - struct rbimpl_size_mul_overflow_tag size = + struct rbimpl_size_overflow_tag size = rbimpl_size_add_overflow(x, y); - if (RB_LIKELY(!size.left)) { - return size.right; + if (RB_LIKELY(!size.overflowed)) { + return size.result; } else { ruby_malloc_add_size_overflow(x, y); diff --git a/include/ruby/internal/newobj.h b/include/ruby/internal/newobj.h index 6eee2fa5fa..13030ae279 100644 --- a/include/ruby/internal/newobj.h +++ b/include/ruby/internal/newobj.h @@ -109,42 +109,4 @@ void rb_singleton_class_attached(VALUE klass, VALUE obj); void rb_copy_generic_ivar(VALUE clone, VALUE obj); RBIMPL_SYMBOL_EXPORT_END() -RBIMPL_ATTR_DEPRECATED(("This is no longer how Object#clone works.")) -/** - * @deprecated Not sure exactly when but at some time, the implementation of - * `Object#clone` stopped using this function. It remained - * untouched for a while, and then @shyouhei realised that they - * are no longer doing the same thing. It seems nobody seriously - * uses this function any longer. Let's just abandon it. - * - * @param[out] clone The destination object. - * @param[in] obj The source object. - */ -static inline void -rb_clone_setup(VALUE clone, VALUE obj) -{ - (void)clone; - (void)obj; - return; -} - -RBIMPL_ATTR_DEPRECATED(("This is no longer how Object#dup works.")) -/** - * @deprecated Not sure exactly when but at some time, the implementation of - * `Object#dup` stopped using this function. It remained - * untouched for a while, and then @shyouhei realised that they - * are no longer the same thing. It seems nobody seriously uses - * this function any longer. Let's just abandon it. - * - * @param[out] dup The destination object. - * @param[in] obj The source object. - */ -static inline void -rb_dup_setup(VALUE dup, VALUE obj) -{ - (void)dup; - (void)obj; - return; -} - #endif /* RBIMPL_NEWOBJ_H */ diff --git a/include/ruby/internal/static_assert.h b/include/ruby/internal/static_assert.h index 7f00bc21eb..30bfd3bb79 100644 --- a/include/ruby/internal/static_assert.h +++ b/include/ruby/internal/static_assert.h @@ -30,7 +30,7 @@ # /* https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations */ # define RBIMPL_STATIC_ASSERT0 static_assert -#elif defined(__cplusplus) && RBIMPL_COMPILER_SINCE(MSVC, 16, 0, 0) +#elif defined(__cplusplus) && RBIMPL_COMPILER_IS(MSVC) # define RBIMPL_STATIC_ASSERT0 static_assert #elif defined(__INTEL_CXX11_MODE__) diff --git a/include/ruby/internal/stdbool.h b/include/ruby/internal/stdbool.h index 7f3e6dcf97..5d9026434b 100644 --- a/include/ruby/internal/stdbool.h +++ b/include/ruby/internal/stdbool.h @@ -31,17 +31,9 @@ # define __bool_true_false_are_defined # endif -#elif defined(HAVE_STDBOOL_H) -# /* Take stdbool.h definition. */ +#else +# /* Take stdbool.h definition. It exists since GCC 3.0 and VS 2015. */ # include <stdbool.h> - -#elif !defined(HAVE__BOOL) -typedef unsigned char _Bool; -# /* See also http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2229.htm */ -# define bool _Bool -# define true ((_Bool)+1) -# define false ((_Bool)+0) -# define __bool_true_false_are_defined #endif #endif /* RBIMPL_STDBOOL_H */ diff --git a/include/ruby/internal/symbol.h b/include/ruby/internal/symbol.h index 569bf215a2..8bfd686fbe 100644 --- a/include/ruby/internal/symbol.h +++ b/include/ruby/internal/symbol.h @@ -101,12 +101,11 @@ ID rb_intern(const char *name); ID rb_intern2(const char *name, long len); /** - * Identical to rb_intern(), except it takes an instance of ::rb_cString. + * Identical to rb_intern(), except it takes a `T_STRING` object. * * @param[in] str The name of the id. - * @pre `str` must either be an instance of ::rb_cSymbol, or an instance - * of ::rb_cString, or responds to `#to_str` method. - * @exception rb_eTypeError Can't convert `str` into ::rb_cString. + * @pre `rb_type(str)` must be `T_STRING`. + * @exception rb_eEncodingError `str` contains invalid character(s). * @exception rb_eRuntimeError Too many symbols. * @return A (possibly new) id whose value is the given str. * @note These days Ruby internally has two kinds of symbols @@ -166,29 +165,34 @@ RBIMPL_ATTR_NONNULL(()) * of ::rb_cSymbol, or an instance of ::rb_cString, or responds * to `#to_str` method. * @exception rb_eTypeError Can't convert `*namep` into ::rb_cString. - * @exception rb_eEncodingError Given string is non-ASCII. + * @exception rb_eEncodingError Given string contains invalid character(s). * @retval 0 No such id ever existed in the history. * @retval otherwise The id that represents the given name. * @post The object that `*namep` points to is a converted result * object, which is always an instance of either ::rb_cSymbol * or ::rb_cString. + * @see rb_str_to_str * @see https://bugs.ruby-lang.org/issues/5072 - * - * @internal - * - * @shyouhei doesn't know why this has to raise rb_eEncodingError. */ ID rb_check_id(volatile VALUE *namep); /** - * @copydoc rb_intern_str() + * Identical to rb_intern_str(), except it tries to convert the parameter object + * to an instance of ::rb_cString or its subclasses. * - * @internal - * - * :FIXME: Can anyone tell us what is the difference between this one and - * rb_intern_str()? As far as @shyouhei reads the implementation it seems what - * rb_to_id() does is is just waste some CPU time, then call rb_intern_str(). - * He hopes he is wrong. + * @param[in] str The name of the id. + * @pre `str` must either be an instance of ::rb_cSymbol, or an instance + * of ::rb_cString, or responds to `#to_str` method. + * @exception rb_eTypeError Can't convert `str` into ::rb_cString. + * @exception rb_eEncodingError Given string contains invalid character(s). + * @exception rb_eRuntimeError Too many symbols. + * @return A (possibly new) id whose value is the given str. + * @note These days Ruby internally has two kinds of symbols + * (static/dynamic). Symbols created using this function would + * become static ones; i.e. would never be garbage collected. It + * is up to you to avoid memory leaks. Think twice before using + * it. + * @see rb_str_to_str */ ID rb_to_id(VALUE str); @@ -245,17 +249,14 @@ RBIMPL_ATTR_NONNULL(()) * of ::rb_cSymbol, or an instance of ::rb_cString, or responds * to `#to_str` method. * @exception rb_eTypeError Can't convert `*namep` into ::rb_cString. - * @exception rb_eEncodingError Given string is non-ASCII. + * @exception rb_eEncodingError Given string contains invalid character(s). * @retval RUBY_Qnil No such id ever existed in the history. * @retval otherwise The id that represents the given name. * @post The object that `*namep` points to is a converted result * object, which is always an instance of either ::rb_cSymbol * or ::rb_cString. * @see https://bugs.ruby-lang.org/issues/5072 - * - * @internal - * - * @shyouhei doesn't know why this has to raise rb_eEncodingError. + * @see rb_str_to_str */ VALUE rb_check_symbol(volatile VALUE *namep); RBIMPL_SYMBOL_EXPORT_END() diff --git a/include/ruby/internal/warning_push.h b/include/ruby/internal/warning_push.h index f5981633f8..91d62cb00d 100644 --- a/include/ruby/internal/warning_push.h +++ b/include/ruby/internal/warning_push.h @@ -79,7 +79,7 @@ */ #define RBIMPL_WARNING_IGNORED(flag) __pragma(warning(disable: flag)) -#elif RBIMPL_COMPILER_SINCE(MSVC, 12, 0, 0) +#elif RBIMPL_COMPILER_IS(MSVC) # /* Not sure exactly when but it seems VC++ 6.0 is a version with it.*/ # define RBIMPL_WARNING_PUSH() __pragma(warning(push)) # define RBIMPL_WARNING_POP() __pragma(warning(pop)) diff --git a/include/ruby/io.h b/include/ruby/io.h index 11d5ce5bfe..ed0967abad 100644 --- a/include/ruby/io.h +++ b/include/ruby/io.h @@ -66,6 +66,21 @@ RBIMPL_SYMBOL_EXPORT_BEGIN() struct stat; struct timeval; +#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC) +# define RUBY_USE_STATX 0 +#elif defined(HAVE_STRUCT_STATX_STX_BTIME) +# define RUBY_USE_STATX 1 +struct statx; +#else +# define RUBY_USE_STATX 0 +#endif + +#if RUBY_USE_STATX +typedef struct statx rb_io_stat_data; +#else +typedef struct stat rb_io_stat_data; +#endif + /** * Indicates that a timeout has occurred while performing an IO operation. */ @@ -1098,6 +1113,18 @@ int rb_io_read_pending(rb_io_t *fptr); */ VALUE rb_stat_new(const struct stat *st); +#if RUBY_USE_STATX +/** + * Constructs an instance of ::rb_cStat from the passed information. + * + * @param[in] st A stat. + * @return Allocated new instance of ::rb_cStat. + */ +VALUE rb_statx_new(const rb_io_stat_data *st); +#else +# define rb_statx_new rb_stat_new +#endif + /* gc.c */ RBIMPL_SYMBOL_EXPORT_END() diff --git a/include/ruby/onigmo.h b/include/ruby/onigmo.h index db290cd47a..9dcddee829 100644 --- a/include/ruby/onigmo.h +++ b/include/ruby/onigmo.h @@ -4,8 +4,8 @@ onigmo.h - Onigmo (Oniguruma-mod) (regular expression library) **********************************************************************/ /*- - * Copyright (c) 2002-2009 K.Kosako <sndgk393 AT ybb DOT ne DOT jp> - * Copyright (c) 2011-2017 K.Takata <kentkt AT csc DOT jp> + * Copyright (c) 2002-2016 K.Kosako <sndgk393 AT ybb DOT ne DOT jp> + * Copyright (c) 2011-2019 K.Takata <kentkt AT csc DOT jp> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -38,8 +38,8 @@ extern "C" { #endif #define ONIGMO_VERSION_MAJOR 6 -#define ONIGMO_VERSION_MINOR 1 -#define ONIGMO_VERSION_TEENY 3 +#define ONIGMO_VERSION_MINOR 2 +#define ONIGMO_VERSION_TEENY 0 #ifndef ONIG_EXTERN # ifdef RUBY_EXTERN @@ -789,8 +789,8 @@ typedef struct re_pattern_buffer { unsigned char *exact; unsigned char *exact_end; unsigned char map[ONIG_CHAR_TABLE_SIZE]; /* used as BM skip or char-map */ - int *int_map; /* BM skip for exact_len > 255 */ - int *int_map_backward; /* BM skip for backward search */ + int *reserved1; + int *reserved2; OnigDistance dmin; /* min-distance of exact or map */ OnigDistance dmax; /* max-distance of exact or map */ diff --git a/include/ruby/ractor.h b/include/ruby/ractor.h index 7811616f6d..8cfca21621 100644 --- a/include/ruby/ractor.h +++ b/include/ruby/ractor.h @@ -217,7 +217,7 @@ VALUE rb_ractor_make_shareable(VALUE obj); * * @param[in] obj Arbitrary ruby object to duplicate. * @exception rb_eRactorError Ractors cannot share `obj` by nature. - * @return A deep copy of `obj` which is sharable among Ractors. + * @return A deep copy of `obj` which is shareable among Ractors. */ VALUE rb_ractor_make_shareable_copy(VALUE obj); @@ -261,4 +261,18 @@ rb_ractor_shareable_p(VALUE obj) } } +// TODO: optimize on interpreter core +#ifndef RB_OBJ_SET_SHAREABLE +VALUE rb_obj_set_shareable(VALUE obj); // ractor.c +#define RB_OBJ_SET_SHAREABLE(obj) rb_obj_set_shareable(obj) +#endif + +static inline VALUE +RB_OBJ_SET_FROZEN_SHAREABLE(VALUE obj) +{ + RB_OBJ_FREEZE(obj); + RB_OBJ_SET_SHAREABLE(obj); + return obj; +} + #endif /* RUBY_RACTOR_H */ diff --git a/include/ruby/random.h b/include/ruby/random.h index f3df0d96fb..740be6bdad 100644 --- a/include/ruby/random.h +++ b/include/ruby/random.h @@ -332,7 +332,9 @@ RBIMPL_ATTR_PURE_UNLESS_DEBUG() static inline const rb_random_interface_t * rb_rand_if(VALUE obj) { + RBIMPL_ASSERT_OR_ASSUME(RB_TYPE_P(obj, T_DATA)); RBIMPL_ASSERT_OR_ASSUME(RTYPEDDATA_P(obj)); + RUBY_ASSERT(rb_typeddata_is_kind_of(obj, &rb_random_data_type)); const struct rb_data_type_struct *t = RTYPEDDATA_TYPE(obj); const void *ret = t->data; return RBIMPL_CAST((const rb_random_interface_t *)ret); diff --git a/include/ruby/version.h b/include/ruby/version.h index a521d925ed..5bb381cea2 100644 --- a/include/ruby/version.h +++ b/include/ruby/version.h @@ -61,13 +61,13 @@ * doesn't mean a total rewrite. Practically when it comes to API versioning, * major and minor version changes are equally catastrophic. */ -#define RUBY_API_VERSION_MAJOR 3 +#define RUBY_API_VERSION_MAJOR 4 /** * Minor version. As of writing this version changes annually. Greater * version doesn't mean "better"; they just mean years passed. */ -#define RUBY_API_VERSION_MINOR 5 +#define RUBY_API_VERSION_MINOR 1 /** * Teeny version. This digit is kind of reserved these days. Kept 0 for the diff --git a/include/ruby/win32.h b/include/ruby/win32.h index 27a3467606..ae11a61481 100644 --- a/include/ruby/win32.h +++ b/include/ruby/win32.h @@ -30,15 +30,10 @@ extern "C++" { /* template without extern "C++" */ #if !defined(_WIN64) && !defined(WIN32) #define WIN32 #endif -#if defined(_MSC_VER) && _MSC_VER <= 1200 -#include <windows.h> -#endif #include <winsock2.h> #include <ws2tcpip.h> #include <mswsock.h> -#if !defined(_MSC_VER) || _MSC_VER >= 1400 #include <iphlpapi.h> -#endif #if defined(__cplusplus) && defined(_MSC_VER) } #endif @@ -59,13 +54,7 @@ extern "C++" { /* template without extern "C++" */ #include <direct.h> #include <process.h> #include <time.h> -#if defined(__cplusplus) && defined(_MSC_VER) && _MSC_VER == 1200 -extern "C++" { /* template without extern "C++" */ -#endif #include <math.h> -#if defined(__cplusplus) && defined(_MSC_VER) && _MSC_VER == 1200 -} -#endif #include <signal.h> #include <sys/stat.h> #include <sys/types.h> @@ -126,8 +115,30 @@ typedef unsigned int uintptr_t; #define O_SHARE_DELETE 0x20000000 /* for rb_w32_open(), rb_w32_wopen() */ typedef int clockid_t; -#define CLOCK_REALTIME 0 -#define CLOCK_MONOTONIC 1 + +/* + * Since we use our versions in win32/win32.c, not to depend on yet + * another DLL, prefix our versions not to conflict with inline + * versions provided in time.h. + */ +#define clock_gettime rb_w32_clock_gettime +#define clock_getres rb_w32_clock_getres + +#ifndef CLOCK_REALTIME +# define CLOCK_REALTIME 0 +#endif +#ifndef CLOCK_MONOTONIC +# define CLOCK_MONOTONIC 1 +#endif +#ifndef CLOCK_PROCESS_CPUTIME_ID +# define CLOCK_PROCESS_CPUTIME_ID 2 +#endif +#ifndef CLOCK_THREAD_CPUTIME_ID +# define CLOCK_THREAD_CPUTIME_ID 3 +#endif +#ifndef CLOCK_REALTIME_COARSE +# define CLOCK_REALTIME_COARSE 4 +#endif #undef utime #undef lseek @@ -251,7 +262,6 @@ struct ifaddrs { #endif extern void rb_w32_sysinit(int *, char ***); -extern DWORD rb_w32_osid(void); extern int flock(int fd, int oper); extern int rb_w32_io_cancelable_p(int); extern int rb_w32_is_socket(int); @@ -295,7 +305,11 @@ extern void rb_w32_free_environ(char **); extern int rb_w32_map_errno(DWORD); extern const char *WSAAPI rb_w32_inet_ntop(int,const void *,char *,size_t); extern int WSAAPI rb_w32_inet_pton(int,const char *,void *); -extern DWORD rb_w32_osver(void); + +RBIMPL_ATTR_DEPRECATED(("as Windows 9x is not supported already")) +static inline DWORD rb_w32_osid(void) {return VER_PLATFORM_WIN32_NT;} +RBIMPL_ATTR_DEPRECATED(("by Windows Version Helper APIs")) +extern DWORD rb_w32_osver(void); extern int rb_w32_uchown(const char *, int, int); extern int rb_w32_ulink(const char *, const char *); @@ -331,7 +345,7 @@ extern int rb_w32_dup2(int, int); #include <float.h> -#if defined _MSC_VER && _MSC_VER >= 1800 && defined INFINITY +#if defined _MSC_VER && defined INFINITY #pragma warning(push) #pragma warning(disable:4756) static inline float @@ -414,11 +428,6 @@ extern int rb_w32_utruncate(const char *path, rb_off_t length); #define HAVE_TRUNCATE 1 #define truncate rb_w32_utruncate -#if defined(_MSC_VER) && _MSC_VER >= 1400 && _MSC_VER < 1800 -#define strtoll _strtoi64 -#define strtoull _strtoui64 -#endif - /* * stubs */ |
