diff options
Diffstat (limited to 'include/ruby')
79 files changed, 2022 insertions, 2537 deletions
diff --git a/include/ruby/assert.h b/include/ruby/assert.h index 0c052363bc..c9f2c3fbef 100644 --- a/include/ruby/assert.h +++ b/include/ruby/assert.h @@ -103,7 +103,7 @@ # /* keep NDEBUG undefined */ #elif (RBIMPL_NDEBUG == 0) && (RBIMPL_RUBY_DEBUG == 0) -# /* The (*1) situation in above diagram. */ +# /* The (*1) situation in avobe diagram. */ # define RUBY_DEBUG 0 # define RUBY_NDEBUG 1 # define NDEBUG diff --git a/include/ruby/atomic.h b/include/ruby/atomic.h index eb106631f6..3eb80fbf7d 100644 --- a/include/ruby/atomic.h +++ b/include/ruby/atomic.h @@ -139,15 +139,6 @@ typedef unsigned int rb_atomic_t; rbimpl_atomic_cas(&(var), (oldval), (newval)) /** - * Atomic load. This loads `var` with an atomic intrinsic and returns - * its value. - * - * @param var A variable of ::rb_atomic_t - * @return What was stored in `var`j - */ -#define RUBY_ATOMIC_LOAD(var) rbimpl_atomic_load(&(var)) - -/** * Identical to #RUBY_ATOMIC_EXCHANGE, except for the return type. * * @param var A variable of ::rb_atomic_t. @@ -289,17 +280,6 @@ typedef unsigned int rb_atomic_t; RBIMPL_CAST(rbimpl_atomic_ptr_exchange((void **)&(var), (void *)val)) /** - * Identical to #RUBY_ATOMIC_LOAD, except it expects its arguments are `void*`. - * There are cases where ::rb_atomic_t is 32bit while `void*` is 64bit. This - * should be used for size related operations to support such platforms. - * - * @param var A variable of `void*` - * @return The value of `var` (without tearing) - */ -#define RUBY_ATOMIC_PTR_LOAD(var) \ - RBIMPL_CAST(rbimpl_atomic_ptr_load((void **)&var)) - -/** * Identical to #RUBY_ATOMIC_CAS, except it expects its arguments are `void*`. * There are cases where ::rb_atomic_t is 32bit while `void*` is 64bit. This * should be used for size related operations to support such platforms. @@ -769,21 +749,6 @@ rbimpl_atomic_value_exchange(volatile VALUE *ptr, VALUE val) RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) -static inline rb_atomic_t -rbimpl_atomic_load(volatile rb_atomic_t *ptr) -{ -#if 0 - -#elif defined(HAVE_GCC_ATOMIC_BUILTINS) - return __atomic_load_n(ptr, __ATOMIC_SEQ_CST); -#else - return rbimpl_atomic_fetch_add(ptr, 0); -#endif -} - -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) { @@ -910,22 +875,6 @@ rbimpl_atomic_ptr_cas(void **ptr, const void *oldval, const void *newval) RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) -static inline void * -rbimpl_atomic_ptr_load(void **ptr) -{ -#if 0 - -#elif defined(HAVE_GCC_ATOMIC_BUILTINS) - return __atomic_load_n(ptr, __ATOMIC_SEQ_CST); -#else - void *val = *ptr; - return rbimpl_atomic_ptr_cas(ptr, val, val); -#endif -} - -RBIMPL_ATTR_ARTIFICIAL() -RBIMPL_ATTR_NOALIAS() -RBIMPL_ATTR_NONNULL((1)) static inline VALUE rbimpl_atomic_value_cas(volatile VALUE *ptr, VALUE oldval, VALUE newval) { diff --git a/include/ruby/backward.h b/include/ruby/backward.h index f804c2c36e..e12f98ac47 100644 --- a/include/ruby/backward.h +++ b/include/ruby/backward.h @@ -13,13 +13,59 @@ #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); +/* eval.c */ +RBIMPL_ATTR_DEPRECATED_SINCE(2.2) void rb_disable_super(); +RBIMPL_ATTR_DEPRECATED_SINCE(2.2) void rb_enable_super(); + +/* hash.c */ +RBIMPL_ATTR_DEPRECATED_SINCE(2.2) void rb_hash_iter_lev(); +RBIMPL_ATTR_DEPRECATED_SINCE(2.2) void rb_hash_ifnone(); + +/* string.c */ +RBIMPL_ATTR_DEPRECATED_SINCE(2.2) void rb_str_associate(); +RBIMPL_ATTR_DEPRECATED_SINCE(2.2) void rb_str_associated(); + +/* variable.c */ +RBIMPL_ATTR_DEPRECATED_SINCE(2.5) void rb_autoload(); + +/* eval.c */ +RBIMPL_ATTR_DEPRECATED_INTERNAL(2.6) void rb_frozen_class_p(); +RBIMPL_ATTR_DEPRECATED_INTERNAL(2.7) void rb_exec_end_proc(); + +/* error.c */ +RBIMPL_ATTR_DEPRECATED_INTERNAL(2.3) void rb_compile_error(); +RBIMPL_ATTR_DEPRECATED_INTERNAL(2.3) void rb_compile_error_with_enc(); +RBIMPL_ATTR_DEPRECATED_INTERNAL(2.3) void rb_compile_error_append(); + +/* gc.c */ +RBIMPL_ATTR_DEPRECATED_INTERNAL(2.7) void rb_gc_call_finalizer_at_exit(); + +/* signal.c */ +RBIMPL_ATTR_DEPRECATED_INTERNAL(2.7) void rb_trap_exit(); + +/* struct.c */ +RBIMPL_ATTR_DEPRECATED_INTERNAL(2.4) void rb_struct_ptr(); + +/* thread.c */ +RBIMPL_ATTR_DEPRECATED_INTERNAL(2.7) void rb_clear_trace_func(); + +/* variable.c */ +RBIMPL_ATTR_DEPRECATED_INTERNAL(2.7) void rb_generic_ivar_table(); +RBIMPL_ATTR_DEPRECATED_INTERNAL(2.6) NORETURN(VALUE rb_mod_const_missing(VALUE, VALUE)); /* from version.c */ #if defined(RUBY_SHOW_COPYRIGHT_TO_DIE) && !!(RUBY_SHOW_COPYRIGHT_TO_DIE+0) -# error RUBY_SHOW_COPYRIGHT_TO_DIE is deprecated +/* for source code backward compatibility */ +RBIMPL_ATTR_DEPRECATED_SINCE(2.4) +static inline int +ruby_show_copyright_to_die(int exitcode) +{ + ruby_show_copyright(); + return exitcode; +} +#define ruby_show_copyright() /* defer EXIT_SUCCESS */ \ + (exit(ruby_show_copyright_to_die(EXIT_SUCCESS))) #endif #endif /* RUBY_RUBY_BACKWARD_H */ diff --git a/include/ruby/backward/2/assume.h b/include/ruby/backward/2/assume.h index d148710127..265421df79 100644 --- a/include/ruby/backward/2/assume.h +++ b/include/ruby/backward/2/assume.h @@ -24,6 +24,8 @@ #include "ruby/internal/assume.h" #include "ruby/internal/has/builtin.h" +#undef ASSUME /* Kill config.h definition */ +#undef UNREACHABLE /* Kill config.h definition */ #define ASSUME RBIMPL_ASSUME /**< @old{RBIMPL_ASSUME} */ #define UNREACHABLE RBIMPL_UNREACHABLE() /**< @old{RBIMPL_UNREACHABLE} */ #define UNREACHABLE_RETURN RBIMPL_UNREACHABLE_RETURN /**< @old{RBIMPL_UNREACHABLE_RETURN} */ diff --git a/include/ruby/backward/2/attributes.h b/include/ruby/backward/2/attributes.h index 916d9e9d5b..73acfc9dc0 100644 --- a/include/ruby/backward/2/attributes.h +++ b/include/ruby/backward/2/attributes.h @@ -39,7 +39,6 @@ #include "ruby/internal/attr/noinline.h" #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/attr/noreturn.h" -#include "ruby/internal/attr/packed_struct.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/attr/restrict.h" #include "ruby/internal/attr/returns_nonnull.h" @@ -81,8 +80,10 @@ #undef NOINLINE #define NOINLINE(x) RBIMPL_ATTR_NOINLINE() x -#undef ALWAYS_INLINE -#define ALWAYS_INLINE(x) RBIMPL_ATTR_FORCEINLINE() x +#ifndef MJIT_HEADER +# undef ALWAYS_INLINE +# define ALWAYS_INLINE(x) RBIMPL_ATTR_FORCEINLINE() x +#endif #undef ERRORFUNC #define ERRORFUNC(mesg, x) RBIMPL_ATTR_ERROR(mesg) x @@ -146,14 +147,17 @@ #define NORETURN(x) RBIMPL_ATTR_NORETURN() x #define NORETURN_STYLE_NEW -#undef PACKED_STRUCT -#define PACKED_STRUCT(x) \ - RBIMPL_ATTR_PACKED_STRUCT_BEGIN() x RBIMPL_ATTR_PACKED_STRUCT_END() +#ifndef PACKED_STRUCT +# define PACKED_STRUCT(x) x +#endif -#undef PACKED_STRUCT_UNALIGNED -#define PACKED_STRUCT_UNALIGNED(x) \ - RBIMPL_ATTR_PACKED_STRUCT_UNALIGNED_BEGIN() x \ - RBIMPL_ATTR_PACKED_STRUCT_UNALIGNED_END() +#ifndef PACKED_STRUCT_UNALIGNED +# if UNALIGNED_WORD_ACCESS +# define PACKED_STRUCT_UNALIGNED(x) PACKED_STRUCT(x) +# else +# define PACKED_STRUCT_UNALIGNED(x) x +# endif +#endif #undef RB_UNUSED_VAR #define RB_UNUSED_VAR(x) x RBIMPL_ATTR_MAYBE_UNUSED() diff --git a/include/ruby/debug.h b/include/ruby/debug.h index f7c8e6ca8d..c88da9c43d 100644 --- a/include/ruby/debug.h +++ b/include/ruby/debug.h @@ -10,7 +10,6 @@ * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. */ -#include "ruby/internal/attr/deprecated.h" #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/attr/returns_nonnull.h" #include "ruby/internal/dllexport.h" @@ -52,25 +51,6 @@ RBIMPL_ATTR_NONNULL((3)) int rb_profile_frames(int start, int limit, VALUE *buff, int *lines); /** - * Queries mysterious "frame"s of the given range. - * - * A per-thread version of rb_profile_frames(). - * Arguments and return values are the same with rb_profile_frames() with the - * exception of the first argument _thread_, which accepts the Thread to be - * profiled/queried. - * - * @param[in] thread The Ruby Thread to be profiled. - * @param[in] start Start position (0 means the topmost). - * @param[in] limit Number objects of `buff`. - * @param[out] buff Return buffer. - * @param[out] lines Return buffer. - * @return Number of objects filled into `buff`. - * @post `buff` is filled with backtrace pointers. - * @post `lines` is filled with `__LINE__` of each backtraces. - */ -int rb_profile_thread_frames(VALUE thread, int start, int limit, VALUE *buff, int *lines); - -/** * Queries the path of the passed backtrace. * * @param[in] frame What rb_profile_frames() returned. @@ -227,17 +207,6 @@ typedef VALUE (*rb_debug_inspector_func_t)(const rb_debug_inspector_t *dc, void VALUE rb_debug_inspector_open(rb_debug_inspector_func_t func, void *data); /** - * Queries the backtrace object of the context. This is as if you call - * `caller_locations` at the point of debugger. - * - * @param[in] dc A debug context. - * @return An array of `Thread::Backtrace::Location` which represents the - * current point of execution at `dc`. - - */ -VALUE rb_debug_inspector_backtrace_locations(const rb_debug_inspector_t *dc); - -/** * Queries the current receiver of the passed context's upper frame. * * @param[in] dc A debug context. @@ -281,27 +250,15 @@ VALUE rb_debug_inspector_frame_binding_get(const rb_debug_inspector_t *dc, long VALUE rb_debug_inspector_frame_iseq_get(const rb_debug_inspector_t *dc, long index); /** - * Queries the depth of the passed context's upper frame. - * - * Note that the depth is not same as the frame index because debug_inspector - * skips some special frames but the depth counts all frames. + * Queries the backtrace object of the context. This is as if you call + * `caller_locations` at the point of debugger. * - * @param[in] dc A debug context. - * @param[in] index Index of the frame from top to bottom. - * @exception rb_eArgError `index` out of range. - * @retval The depth at `index`-th frame in Integer. - */ -VALUE rb_debug_inspector_frame_depth(const rb_debug_inspector_t *dc, long index); - -// A macro to recognize `rb_debug_inspector_frame_depth()` is available or not -#define RB_DEBUG_INSPECTOR_FRAME_DEPTH(dc, index) rb_debug_inspector_frame_depth(dc, index) + * @param[in] dc A debug context. + * @return An array of `Thread::Backtrace::Location` which represents the + * current point of execution at `dc`. -/** - * Return current frmae depth. - * - * @retval The depth of the current frame in Integer. */ -VALUE rb_debug_inspector_current_depth(void); +VALUE rb_debug_inspector_backtrace_locations(const rb_debug_inspector_t *dc); /** @} */ @@ -616,157 +573,48 @@ VALUE rb_tracearg_object(rb_trace_arg_t *trace_arg); /* * Postponed Job API - * - * This API is designed to be called from contexts where it is not safe to run Ruby - * code (e.g. because they do not hold the GVL or because GC is in progress), and - * defer a callback to run in a context where it _is_ safe. The primary intended - * users of this API is for sampling profilers like the "stackprof" gem; these work - * by scheduling the periodic delivery of a SIGPROF signal, and inside the C-level - * signal handler, deferring a job to collect a Ruby backtrace when it is next safe - * to do so. - * - * Ruby maintains a small, fixed-size postponed job table. An extension using this - * API should first call `rb_postponed_job_preregister` to register a callback - * function in this table and obtain a handle of type `rb_postponed_job_handle_t` - * to it. Subsequently, the callback can be triggered by calling - * `rb_postponed_job_trigger` with that handle, or the `data` associated with the - * callback function can be changed by calling `rb_postponed_job_preregister` again. - * - * Because the postponed job table is quite small (it only has 32 entries on most - * common systems), extensions should generally only preregister one or two `func` - * values. - * - * Historically, this API provided two functions `rb_postponed_job_register` and - * `rb_postponed_job_register_one`, which claimed to be fully async-signal-safe and - * would call back the provided `func` and `data` at an appropriate time. However, - * these functions were subject to race conditions which could cause crashes when - * racing with Ruby's internal use of them. These two functions are still present, - * but are marked as deprecated and have slightly changed semantics: - * - * * rb_postponed_job_register now works like rb_postponed_job_register_one i.e. - * `func` will only be executed at most one time each time Ruby checks for - * interrupts, no matter how many times it is registered - * * They are also called with the last `data` to be registered, not the first - * (which is how rb_postponed_job_register_one previously worked) + * rb_postponed_job_register and rb_postponed_job_register_one are + * async-signal-safe and used via SIGPROF by the "stackprof" RubyGem */ - /** * Type of postponed jobs. * - * @param[in,out] arg What was passed to `rb_postponed_job_preregister` + * @param[in,out] arg What was passed to rb_postponed_job_register(). */ typedef void (*rb_postponed_job_func_t)(void *arg); /** - * The type of a handle returned from `rb_postponed_job_preregister` and - * passed to `rb_postponed_job_trigger` - */ -typedef unsigned int rb_postponed_job_handle_t; -#define POSTPONED_JOB_HANDLE_INVALID ((rb_postponed_job_handle_t)UINT_MAX) - -/** - * Pre-registers a func in Ruby's postponed job preregistration table, - * returning an opaque handle which can be used to trigger the job later. Generally, - * this function will be called during the initialization routine of an extension. - * - * The returned handle can be used later to call `rb_postponed_job_trigger`. This will - * cause Ruby to call back into the registered `func` with `data` at a later time, in - * a context where the GVL is held and it is safe to perform Ruby allocations. - * - * If the given `func` was already pre-registered, this function will overwrite the - * stored data with the newly passed data, and return the same handle instance as - * was previously returned. - * - * If this function is called concurrently with the same `func`, then the stored data - * could be the value from either call (but will definitely be one of them). - * - * If this function is called to update the data concurrently with a call to - * `rb_postponed_job_trigger` on the same handle, it's undefined whether `func` will - * be called with the old data or the new data. - * - * Although the current implementation of this function is in fact async-signal-safe and - * has defined semantics when called concurrently on the same `func`, a future Ruby - * version might require that this method be called under the GVL; thus, programs which - * aim to be forward-compatible should call this method whilst holding the GVL. - * - * @param[in] flags Unused and ignored - * @param[in] func The function to be pre-registered - * @param[in] data The data to be pre-registered - * @retval POSTPONED_JOB_HANDLE_INVALID The job table is full; this registration - * did not succeed and no further registration will do so for - * the lifetime of the program. - * @retval otherwise A handle which can be passed to `rb_postponed_job_trigger` - */ -rb_postponed_job_handle_t rb_postponed_job_preregister(unsigned int flags, rb_postponed_job_func_t func, void *data); - -/** - * Triggers a pre-registered job registered with rb_postponed_job_preregister, - * scheduling it for execution the next time the Ruby VM checks for interrupts. - * The context in which the job is called in holds the GVL and is safe to perform - * Ruby allocations within (i.e. it is not during GC). - * - * This method is async-signal-safe and can be called from any thread, at any - * time, including in signal handlers. + * Registers a postponed job. * - * If this method is called multiple times, Ruby will coalesce this into only - * one call to the job the next time it checks for interrupts. - * - * @params[in] h A handle returned from rb_postponed_job_preregister - */ -void rb_postponed_job_trigger(rb_postponed_job_handle_t h); - -/** - * Schedules the given `func` to be called with `data` when Ruby next checks for - * interrupts. If this function is called multiple times in between Ruby checking - * for interrupts, then `func` will be called only once with the `data` value from - * the first call to this function. + * There are situations when running a ruby program is not possible. For + * instance when a program is in a signal handler; for another instance when + * the GC is busy. On such situations however, there might be needs to do + * something. We cannot but defer such operations until we are 100% sure it is + * safe to execute them. This mechanism is called postponed jobs. This + * function registers a new one. The registered job would eventually gets + * executed. * - * Like `rb_postponed_job_trigger`, the context in which the job is called - * holds the GVL and can allocate Ruby objects. - * - * This method essentially has the same semantics as: - * - * ``` - * rb_postponed_job_trigger(rb_postponed_job_preregister(func, data)); - * ``` - * - * @note Previous versions of Ruby promised that the (`func`, `data`) pairs would - * be executed as many times as they were registered with this function; in - * reality this was always subject to race conditions and this function no - * longer provides this guarantee. Instead, multiple calls to this function - * can be coalesced into a single execution of the passed `func`, with the - * most recent `data` registered at that time passed in. - * - * @deprecated This interface implies that arbitrarily many `func`'s can be enqueued - * over the lifetime of the program, whilst in reality the registration - * slots for postponed jobs are a finite resource. This is made clearer - * by the `rb_postponed_job_preregister` and `rb_postponed_job_trigger` - * functions, and a future version of Ruby might delete this function. - * - * @param[in] flags Unused and ignored. + * @param[in] flags (Unused) reserved for future extensions. * @param[in] func Job body. * @param[in,out] data Passed as-is to `func`. - * @retval 0 Postponed job registration table is full. Failed. - * @retval 1 Registration succeeded. - * @post The passed job will run on the next interrupt check. + * @retval 0 Postponed job buffer is full. Failed. + * @retval otherwise Opaque return value. + * @post The passed job is postponed. */ - RBIMPL_ATTR_DEPRECATED(("use rb_postponed_job_preregister and rb_postponed_job_trigger")) int rb_postponed_job_register(unsigned int flags, rb_postponed_job_func_t func, void *data); /** - * Identical to `rb_postponed_job_register` - * - * @deprecated This is deprecated for the same reason as `rb_postponed_job_register` + * Identical to rb_postponed_job_register_one(), except it additionally checks + * for duplicated registration. In case the passed job is already in the + * postponed job buffer this function does nothing. * - * @param[in] flags Unused and ignored. + * @param[in] flags (Unused) reserved for future extensions. * @param[in] func Job body. * @param[in,out] data Passed as-is to `func`. - * @retval 0 Postponed job registration table is full. Failed. - * @retval 1 Registration succeeded. - * @post The passed job will run on the next interrupt check. + * @retval 0 Postponed job buffer is full. Failed. + * @retval otherwise Opaque return value. */ - RBIMPL_ATTR_DEPRECATED(("use rb_postponed_job_preregister and rb_postponed_job_trigger")) int rb_postponed_job_register_one(unsigned int flags, rb_postponed_job_func_t func, void *data); /** @} */ diff --git a/include/ruby/fiber/scheduler.h b/include/ruby/fiber/scheduler.h index 8f3d383330..3ea52beb95 100644 --- a/include/ruby/fiber/scheduler.h +++ b/include/ruby/fiber/scheduler.h @@ -23,8 +23,6 @@ RBIMPL_SYMBOL_EXPORT_BEGIN() -#define RUBY_FIBER_SCHEDULER_VERSION 2 - struct timeval; /** @@ -45,12 +43,10 @@ struct timeval; * @return A `VALUE` which contains the result and/or errno. */ static inline VALUE -rb_fiber_scheduler_io_result(ssize_t result, int error) -{ +rb_fiber_scheduler_io_result(ssize_t result, int error) { if (result == -1) { return RB_INT2NUM(-error); - } - else { + } else { return RB_SIZE2NUM(result); } } @@ -67,13 +63,11 @@ rb_fiber_scheduler_io_result(ssize_t result, int error) * @return The original result of the system call. */ static inline ssize_t -rb_fiber_scheduler_io_result_apply(VALUE result) -{ +rb_fiber_scheduler_io_result_apply(VALUE result) { if (RB_FIXNUM_P(result) && RB_NUM2INT(result) < 0) { errno = -RB_NUM2INT(result); return -1; - } - else { + } else { return RB_NUM2SIZE(result); } } @@ -97,7 +91,7 @@ VALUE rb_fiber_scheduler_get(void); * current thread will call scheduler's `#close` method on finalisation * (allowing the scheduler to properly manage all non-finished fibers). * `scheduler` can be an object of any class corresponding to - * `Fiber::Scheduler` interface. Its implementation is up to the user. + * `Fiber::SchedulerInterface`. Its implementation is up to the user. * * @param[in] scheduler The scheduler to set. * @exception rb_eArgError `scheduler` does not conform the interface. @@ -146,7 +140,7 @@ VALUE rb_fiber_scheduler_make_timeout(struct timeval *timeout); VALUE rb_fiber_scheduler_close(VALUE scheduler); /** - * Non-blocking `sleep`. Depending on scheduler implementation, this for + * Nonblocking `sleep`. Depending on scheduler implementation, this for * instance switches to another fiber etc. * * @param[in] scheduler Target scheduler. @@ -174,7 +168,7 @@ int rb_fiber_scheduler_supports_process_wait(VALUE scheduler); #endif /** - * Non-blocking `waitpid`. Depending on scheduler implementation, this for + * Nonblocking `waitpid`. Depending on scheduler implementation, this for * instance switches to another fiber etc. * * @param[in] scheduler Target scheduler. @@ -185,7 +179,7 @@ int rb_fiber_scheduler_supports_process_wait(VALUE scheduler); VALUE rb_fiber_scheduler_process_wait(VALUE scheduler, rb_pid_t pid, int flags); /** - * Non-blocking wait for the passed "blocker", which is for instance + * Nonblocking wait for the passed "blocker", which is for instance * `Thread.join` or `Mutex.lock`. Depending on scheduler implementation, this * for instance switches to another fiber etc. * @@ -207,8 +201,8 @@ VALUE rb_fiber_scheduler_block(VALUE scheduler, VALUE blocker, VALUE timeout); VALUE rb_fiber_scheduler_unblock(VALUE scheduler, VALUE blocker, VALUE fiber); /** - * Non-blocking version of rb_io_wait(). Depending on scheduler - * implementation, this for instance switches to another fiber etc. + * Nonblocking version of rb_io_wait(). Depending on scheduler implementation, + * this for instance switches to another fiber etc. * * The "events" here is a Ruby level integer, which is an OR-ed value of * `IO::READABLE`, `IO::WRITABLE`, and `IO::PRIORITY`. @@ -222,7 +216,7 @@ VALUE rb_fiber_scheduler_unblock(VALUE scheduler, VALUE blocker, VALUE fiber); VALUE rb_fiber_scheduler_io_wait(VALUE scheduler, VALUE io, VALUE events, VALUE timeout); /** - * Non-blocking wait until the passed IO is ready for reading. This is a + * Nonblocking wait until the passed IO is ready for reading. This is a * special case of rb_fiber_scheduler_io_wait(), where the interest is * `IO::READABLE` and timeout is never. * @@ -233,7 +227,7 @@ VALUE rb_fiber_scheduler_io_wait(VALUE scheduler, VALUE io, VALUE events, VALUE VALUE rb_fiber_scheduler_io_wait_readable(VALUE scheduler, VALUE io); /** - * Non-blocking wait until the passed IO is ready for writing. This is a + * Nonblocking wait until the passed IO is ready for writing. This is a * special case of rb_fiber_scheduler_io_wait(), where the interest is * `IO::WRITABLE` and timeout is never. * @@ -244,135 +238,81 @@ VALUE rb_fiber_scheduler_io_wait_readable(VALUE scheduler, VALUE io); VALUE rb_fiber_scheduler_io_wait_writable(VALUE scheduler, VALUE io); /** - * Non-blocking version of `IO.select`. - * - * It's possible that this will be emulated using a thread, so you should not - * rely on it for high performance. - * - * @param[in] scheduler Target scheduler. - * @param[in] readables An array of readable objects. - * @param[in] writables An array of writable objects. - * @param[in] exceptables An array of objects that might encounter exceptional conditions. - * @param[in] timeout Numeric timeout or nil. - * @return What `scheduler.io_select` returns, normally a 3-tuple of arrays of ready objects. - */ -VALUE rb_fiber_scheduler_io_select(VALUE scheduler, VALUE readables, VALUE writables, VALUE exceptables, VALUE timeout); - -/** - * Non-blocking version of `IO.select`, `argv` variant. - */ -VALUE rb_fiber_scheduler_io_selectv(VALUE scheduler, int argc, VALUE *argv); - -/** - * Non-blocking read from the passed IO. + * Nonblocking read from the passed IO. * * @param[in] scheduler Target scheduler. - * @param[in] io An io object to read from. - * @param[in] buffer The buffer to read to. - * @param[in] length The minimum number of bytes to read. - * @param[in] offset The offset in the buffer to read from. + * @param[out] io An io object to read from. + * @param[out] buffer Return buffer. + * @param[in] length Requested number of bytes to read. * @retval RUBY_Qundef `scheduler` doesn't have `#io_read`. * @return otherwise What `scheduler.io_read` returns `[-errno, size]`. */ -VALUE rb_fiber_scheduler_io_read(VALUE scheduler, VALUE io, VALUE buffer, size_t length, size_t offset); +VALUE rb_fiber_scheduler_io_read(VALUE scheduler, VALUE io, VALUE buffer, size_t length); /** - * Non-blocking write to the passed IO. + * Nonblocking write to the passed IO. * * @param[in] scheduler Target scheduler. - * @param[in] io An io object to write to. - * @param[in] buffer The buffer to write from. - * @param[in] length The minimum number of bytes to write. - * @param[in] offset The offset in the buffer to write from. + * @param[out] io An io object to write to. + * @param[in] buffer What to write. + * @param[in] length Number of bytes to write. * @retval RUBY_Qundef `scheduler` doesn't have `#io_write`. * @return otherwise What `scheduler.io_write` returns `[-errno, size]`. */ -VALUE rb_fiber_scheduler_io_write(VALUE scheduler, VALUE io, VALUE buffer, size_t length, size_t offset); - -/** - * Non-blocking read from the passed IO at the specified offset. - * - * @param[in] scheduler Target scheduler. - * @param[in] io An io object to read from. - * @param[in] from The offset to read from. - * @param[in] buffer The buffer to read to. - * @param[in] length The minimum number of bytes to read. - * @param[in] offset The offset in the buffer to read to. - * @retval RUBY_Qundef `scheduler` doesn't have `#io_read`. - * @return otherwise What `scheduler.io_read` returns. - */ -VALUE rb_fiber_scheduler_io_pread(VALUE scheduler, VALUE io, rb_off_t from, VALUE buffer, size_t length, size_t offset); +VALUE rb_fiber_scheduler_io_write(VALUE scheduler, VALUE io, VALUE buffer, size_t length); /** - * Non-blocking write to the passed IO at the specified offset. + * Nonblocking read from the passed IO at the specified offset. * * @param[in] scheduler Target scheduler. - * @param[in] io An io object to write to. - * @param[in] from The offset to write to. - * @param[in] buffer The buffer to write from. - * @param[in] length The minimum number of bytes to write. - * @param[in] offset The offset in the buffer to write from. - * @retval RUBY_Qundef `scheduler` doesn't have `#io_write`. - * @return otherwise What `scheduler.io_write` returns. - */ -VALUE rb_fiber_scheduler_io_pwrite(VALUE scheduler, VALUE io, rb_off_t from, VALUE buffer, size_t length, size_t offset); - -/** - * Non-blocking read from the passed IO using a native buffer. - * - * @param[in] scheduler Target scheduler. - * @param[in] io An io object to read from. - * @param[in] base The memory to read to. - * @param[in] size Size of the memory. - * @param[in] length The minimum number of bytes to read. + * @param[out] io An io object to read from. + * @param[out] buffer Return buffer. + * @param[in] length Requested number of bytes to read. + * @param[in] offset The offset in the given IO to read the data from. * @retval RUBY_Qundef `scheduler` doesn't have `#io_read`. * @return otherwise What `scheduler.io_read` returns. */ -VALUE rb_fiber_scheduler_io_read_memory(VALUE scheduler, VALUE io, void *base, size_t size, size_t length); +VALUE rb_fiber_scheduler_io_pread(VALUE scheduler, VALUE io, VALUE buffer, size_t length, off_t offset); /** - * Non-blocking write to the passed IO using a native buffer. + * Nonblocking write to the passed IO at the specified offset. * * @param[in] scheduler Target scheduler. - * @param[in] io An io object to write to. - * @param[in] base The memory to write from. - * @param[in] size Size of the memory. - * @param[in] length The minimum number of bytes to write. + * @param[out] io An io object to write to. + * @param[in] buffer What to write. + * @param[in] length Number of bytes to write. + * @param[in] offset The offset in the given IO to write the data to. * @retval RUBY_Qundef `scheduler` doesn't have `#io_write`. * @return otherwise What `scheduler.io_write` returns. */ -VALUE rb_fiber_scheduler_io_write_memory(VALUE scheduler, VALUE io, const void *base, size_t size, size_t length); +VALUE rb_fiber_scheduler_io_pwrite(VALUE scheduler, VALUE io, VALUE buffer, size_t length, off_t offset); /** - * Non-blocking pread from the passed IO using a native buffer. + * Nonblocking read from the passed IO using a native buffer. * * @param[in] scheduler Target scheduler. - * @param[in] io An io object to read from. - * @param[in] from The offset to read from. - * @param[in] base The memory to read to. - * @param[in] size Size of the memory. - * @param[in] length The minimum number of bytes to read. + * @param[out] io An io object to read from. + * @param[out] buffer Return buffer. + * @param[in] length Requested number of bytes to read. * @retval RUBY_Qundef `scheduler` doesn't have `#io_read`. * @return otherwise What `scheduler.io_read` returns. */ -VALUE rb_fiber_scheduler_io_pread_memory(VALUE scheduler, VALUE io, rb_off_t from, void *base, size_t size, size_t length); +VALUE rb_fiber_scheduler_io_read_memory(VALUE scheduler, VALUE io, void *buffer, size_t size, size_t length); /** - * Non-blocking pwrite to the passed IO using a native buffer. + * Nonblocking write to the passed IO using a native buffer. * * @param[in] scheduler Target scheduler. - * @param[in] io An io object to write to. - * @param[in] from The offset to write from. - * @param[in] base The memory to write from. - * @param[in] size Size of the memory. - * @param[in] length The minimum number of bytes to write. + * @param[out] io An io object to write to. + * @param[in] buffer What to write. + * @param[in] length Number of bytes to write. * @retval RUBY_Qundef `scheduler` doesn't have `#io_write`. * @return otherwise What `scheduler.io_write` returns. */ -VALUE rb_fiber_scheduler_io_pwrite_memory(VALUE scheduler, VALUE io, rb_off_t from, const void *base, size_t size, size_t length); +VALUE rb_fiber_scheduler_io_write_memory(VALUE scheduler, VALUE io, const void *buffer, size_t size, size_t length); /** - * Non-blocking close the given IO. + * Nonblocking close the given IO. * * @param[in] scheduler Target scheduler. * @param[in] io An io object to close. @@ -382,7 +322,7 @@ VALUE rb_fiber_scheduler_io_pwrite_memory(VALUE scheduler, VALUE io, rb_off_t fr VALUE rb_fiber_scheduler_io_close(VALUE scheduler, VALUE io); /** - * Non-blocking DNS lookup. + * Nonblocking DNS lookup. * * @param[in] scheduler Target scheduler. * @param[in] hostname A host name to query. @@ -391,12 +331,6 @@ VALUE rb_fiber_scheduler_io_close(VALUE scheduler, VALUE io); */ VALUE rb_fiber_scheduler_address_resolve(VALUE scheduler, VALUE hostname); -/** - * Create and schedule a non-blocking fiber. - * - */ -VALUE rb_fiber_scheduler_fiber(VALUE scheduler, int argc, VALUE *argv, int kw_splat); - RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_FIBER_SCHEDULER_H */ diff --git a/include/ruby/intern.h b/include/ruby/intern.h index 48e4cd546e..2480e2e703 100644 --- a/include/ruby/intern.h +++ b/include/ruby/intern.h @@ -36,6 +36,7 @@ #include "ruby/internal/intern/error.h" #include "ruby/internal/intern/eval.h" #include "ruby/internal/intern/file.h" +#include "ruby/internal/intern/gc.h" #include "ruby/internal/intern/hash.h" #include "ruby/internal/intern/io.h" #include "ruby/internal/intern/load.h" diff --git a/include/ruby/internal/abi.h b/include/ruby/internal/abi.h deleted file mode 100644 index 8e1bbf3951..0000000000 --- a/include/ruby/internal/abi.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef RUBY_ABI_H -#define RUBY_ABI_H - -#ifdef RUBY_ABI_VERSION /* should match the definition in config.h */ - -/* This number represents Ruby's ABI version. - * - * In development Ruby, it should be bumped every time an ABI incompatible - * change is introduced. This will force other developers to rebuild extension - * gems. - * - * The following cases are considered as ABI incompatible changes: - * - Changing any data structures. - * - Changing macros or inline functions causing a change in behavior. - * - Deprecating or removing function declarations. - * - * The following cases are NOT considered as ABI incompatible changes: - * - Any changes that does not involve the header files in the `include` - * directory. - * - Adding macros, inline functions, or function declarations. - * - Backwards compatible refactors. - * - Editing comments. - * - * In released versions of Ruby, this number is not defined since teeny - * versions of Ruby should guarantee ABI compatibility. - */ -#define RUBY_ABI_VERSION 0 - -/* Windows does not support weak symbols so ruby_abi_version will not exist - * in the shared library. */ -#if defined(HAVE_FUNC_WEAK) && !defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__) -# define RUBY_DLN_CHECK_ABI -#endif -#endif /* RUBY_ABI_VERSION */ - -#ifdef RUBY_DLN_CHECK_ABI - -# ifdef __cplusplus -extern "C" { -# endif - -RUBY_FUNC_EXPORTED unsigned long long __attribute__((weak)) -ruby_abi_version(void) -{ -# ifdef RUBY_ABI_VERSION - return RUBY_ABI_VERSION; -# else - return 0; -# endif -} - -# ifdef __cplusplus -} -# endif - -#endif - -#endif diff --git a/include/ruby/internal/anyargs.h b/include/ruby/internal/anyargs.h index e3e1b6166d..9d8d16fdab 100644 --- a/include/ruby/internal/anyargs.h +++ b/include/ruby/internal/anyargs.h @@ -239,16 +239,15 @@ # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_13(n) RBIMPL_ANYARGS_DISPATCH((n) == 13, rb_define_method_13, RBIMPL_ANYARGS_DISPATCH_rb_define_method_12(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_14(n) RBIMPL_ANYARGS_DISPATCH((n) == 14, rb_define_method_14, RBIMPL_ANYARGS_DISPATCH_rb_define_method_13(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_15(n) RBIMPL_ANYARGS_DISPATCH((n) == 15, rb_define_method_15, RBIMPL_ANYARGS_DISPATCH_rb_define_method_14(n)) -# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_singleton_method_notimpl, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_15(n)) -# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_protected_method_notimpl, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_15(n)) -# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_private_method_notimpl, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_15(n)) -# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_module_function_notimpl, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_15(n)) -# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_global_function_notimpl, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_15(n)) -# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_method_id_notimpl, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_15(n)) -# define RBIMPL_ANYARGS_DISPATCH_rb_define_method(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_method_notimpl, RBIMPL_ANYARGS_DISPATCH_rb_define_method_15(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_singleton_method_m3, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_15(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_protected_method_m3, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_15(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_private_method_m3, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_15(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_module_function_m3, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_15(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_global_function_m3, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_15(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_method_id_m3, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_15(n)) +# define RBIMPL_ANYARGS_DISPATCH_rb_define_method(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_method_m3, RBIMPL_ANYARGS_DISPATCH_rb_define_method_15(n)) # define RBIMPL_ANYARGS_ATTRSET(sym) RBIMPL_ATTR_MAYBE_UNUSED() RBIMPL_ATTR_NONNULL(()) RBIMPL_ATTR_WEAKREF(sym) # define RBIMPL_ANYARGS_DECL(sym, ...) \ -RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _notimpl(__VA_ARGS__, VALUE(*)(int, const VALUE *, VALUE, VALUE), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _m3(__VA_ARGS__, VALUE(*)(ANYARGS), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _m2(__VA_ARGS__, VALUE(*)(VALUE, VALUE), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _m1(__VA_ARGS__, VALUE(*)(int, union { VALUE *x; const VALUE *y; } __attribute__((__transparent_union__)), VALUE), int); \ diff --git a/include/ruby/internal/arithmetic.h b/include/ruby/internal/arithmetic.h index 7ebb4a86f1..3f7840c384 100644 --- a/include/ruby/internal/arithmetic.h +++ b/include/ruby/internal/arithmetic.h @@ -18,8 +18,7 @@ * 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 Conversion between C's arithmetic types and Ruby's numeric - * types. + * @brief Conversion between C's arithmtic types and Ruby's numeric types. */ #include "ruby/internal/arithmetic/char.h" #include "ruby/internal/arithmetic/double.h" diff --git a/include/ruby/internal/arithmetic/long.h b/include/ruby/internal/arithmetic/long.h index 6b8fd8ffc3..792f7be179 100644 --- a/include/ruby/internal/arithmetic/long.h +++ b/include/ruby/internal/arithmetic/long.h @@ -115,7 +115,7 @@ RB_INT2FIX(long i) /* :NOTE: VALUE can be wider than long. As j being unsigned, 2j+1 is fully * defined. Also it can be compiled into a single LEA instruction. */ const unsigned long j = i; - const unsigned long k = (j << 1) + RUBY_FIXNUM_FLAG; + const unsigned long k = 2 * j + RUBY_FIXNUM_FLAG; const long l = k; const SIGNED_VALUE m = l; /* Sign extend */ const VALUE n = m; diff --git a/include/ruby/internal/assume.h b/include/ruby/internal/assume.h index 4c183e8af9..65d34d4ac8 100644 --- a/include/ruby/internal/assume.h +++ b/include/ruby/internal/assume.h @@ -32,7 +32,10 @@ #include "ruby/internal/warning_push.h" /** @cond INTERNAL_MACRO */ -#if defined(HAVE___ASSUME) +#if RBIMPL_COMPILER_SINCE(MSVC, 13, 10, 0) +# define RBIMPL_HAVE___ASSUME + +#elif RBIMPL_COMPILER_SINCE(Intel, 13, 0, 0) # define RBIMPL_HAVE___ASSUME #endif /** @endcond */ diff --git a/include/ruby/internal/attr/nodiscard.h b/include/ruby/internal/attr/nodiscard.h index c3ae118942..087192a7a8 100644 --- a/include/ruby/internal/attr/nodiscard.h +++ b/include/ruby/internal/attr/nodiscard.h @@ -26,7 +26,7 @@ /** * Wraps (or simulates) `[[nodiscard]]`. In C++ (at least since C++20) a - * nodiscard attribute can have a message why the result shall not be ignored. + * nodiscard attribute can have a message why the result shall not be ignoed. * However GCC attribute and SAL annotation cannot take them. */ #if RBIMPL_HAS_CPP_ATTRIBUTE(nodiscard) diff --git a/include/ruby/internal/attr/noexcept.h b/include/ruby/internal/attr/noexcept.h index 7c3f92f1e7..ea3001df2a 100644 --- a/include/ruby/internal/attr/noexcept.h +++ b/include/ruby/internal/attr/noexcept.h @@ -54,7 +54,7 @@ * get smarter and smarter. Today they can infer if it actually throws * or not without any annotations by humans (correct me if I'm wrong). * - * - When an inline function attributed `noexcept` actually _does_ throw an + * - When an inline function attributed `noexcepr` actually _does_ throw an * exception: they have to call `std::terminate` then (C++ standard * mandates so). This means exception handling routines are actually * enforced, not omitted. This doesn't impact runtime performance (The diff --git a/include/ruby/internal/attr/packed_struct.h b/include/ruby/internal/attr/packed_struct.h deleted file mode 100644 index 0678b9acc8..0000000000 --- a/include/ruby/internal/attr/packed_struct.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef RBIMPL_ATTR_PACKED_STRUCT_H /*-*-C++-*-vi:se ft=cpp:*/ -#define RBIMPL_ATTR_PACKED_STRUCT_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 Defines #RBIMPL_ATTR_PACKED_STRUCT_BEGIN, - * #RBIMPL_ATTR_PACKED_STRUCT_END, - * #RBIMPL_ATTR_PACKED_STRUCT_UNALIGNED_BEGIN, and - * #RBIMPL_ATTR_PACKED_STRUCT_UNALIGNED_END. - */ -#include "ruby/internal/config.h" - -#ifndef RBIMPL_ATTR_PACKED_STRUCT_BEGIN -# define RBIMPL_ATTR_PACKED_STRUCT_BEGIN() /* void */ -#endif -#ifndef RBIMPL_ATTR_PACKED_STRUCT_END -# define RBIMPL_ATTR_PACKED_STRUCT_END() /* void */ -#endif - -#if UNALIGNED_WORD_ACCESS -# define RBIMPL_ATTR_PACKED_STRUCT_UNALIGNED_BEGIN() RBIMPL_ATTR_PACKED_STRUCT_BEGIN() -# define RBIMPL_ATTR_PACKED_STRUCT_UNALIGNED_END() RBIMPL_ATTR_PACKED_STRUCT_END() -#else -# define RBIMPL_ATTR_PACKED_STRUCT_UNALIGNED_BEGIN() /* void */ -# define RBIMPL_ATTR_PACKED_STRUCT_UNALIGNED_END() /* void */ -#endif - -#endif diff --git a/include/ruby/internal/config.h b/include/ruby/internal/config.h index da070f0979..51f863fc29 100644 --- a/include/ruby/internal/config.h +++ b/include/ruby/internal/config.h @@ -113,8 +113,6 @@ # define UNALIGNED_WORD_ACCESS 1 #elif defined(__powerpc64__) # define UNALIGNED_WORD_ACCESS 1 -#elif defined(__POWERPC__) // __POWERPC__ is defined for ppc and ppc64 on Darwin -# define UNALIGNED_WORD_ACCESS 1 #elif defined(__aarch64__) # define UNALIGNED_WORD_ACCESS 1 #elif defined(__mc68020__) @@ -148,4 +146,8 @@ # undef RBIMPL_TEST3 #endif /* HAVE_VA_ARGS_MACRO */ +#ifndef USE_RVARGC +# define USE_RVARGC 0 +#endif + #endif /* RBIMPL_CONFIG_H */ diff --git a/include/ruby/internal/core/rarray.h b/include/ruby/internal/core/rarray.h index 90690fe794..9f1d0509ea 100644 --- a/include/ruby/internal/core/rarray.h +++ b/include/ruby/internal/core/rarray.h @@ -29,13 +29,25 @@ #include "ruby/internal/core/rbasic.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/fl_type.h" -#include "ruby/internal/gc.h" +#include "ruby/internal/rgengc.h" #include "ruby/internal/stdbool.h" #include "ruby/internal/value.h" #include "ruby/internal/value_type.h" #include "ruby/assert.h" /** + * @private + * @warning Do not touch this macro. + * @warning It is an implementation detail. + * @warning The value of this macro must match for ruby itself and all + * extension libraries, otherwise serious memory corruption shall + * occur. + */ +#ifndef USE_TRANSIENT_HEAP +# define USE_TRANSIENT_HEAP 1 +#endif + +/** * Convenient casting macro. * * @param obj An object, which is in fact an ::RArray. @@ -47,9 +59,15 @@ #define RARRAY_EMBED_LEN_MASK RARRAY_EMBED_LEN_MASK #define RARRAY_EMBED_LEN_MAX RARRAY_EMBED_LEN_MAX #define RARRAY_EMBED_LEN_SHIFT RARRAY_EMBED_LEN_SHIFT +#if USE_TRANSIENT_HEAP +# define RARRAY_TRANSIENT_FLAG RARRAY_TRANSIENT_FLAG +#else +# define RARRAY_TRANSIENT_FLAG 0 +#endif /** @endcond */ #define RARRAY_LEN rb_array_len /**< @alias{rb_array_len} */ #define RARRAY_CONST_PTR rb_array_const_ptr /**< @alias{rb_array_const_ptr} */ +#define RARRAY_CONST_PTR_TRANSIENT rb_array_const_ptr_transient /**< @alias{rb_array_const_ptr_transient} */ /** @cond INTERNAL_MACRO */ #if defined(__fcc__) || defined(__fcc_version) || \ @@ -62,6 +80,7 @@ #define RARRAY_EMBED_LEN RARRAY_EMBED_LEN #define RARRAY_LENINT RARRAY_LENINT +#define RARRAY_TRANSIENT_P RARRAY_TRANSIENT_P #define RARRAY_ASET RARRAY_ASET #define RARRAY_PTR RARRAY_PTR /** @endcond */ @@ -111,8 +130,24 @@ enum ruby_rarray_flags { * 3rd parties must not be aware that there even is more than one way to * store array elements. It was a bad idea to expose this to them. */ - RARRAY_EMBED_LEN_MASK = RUBY_FL_USER9 | RUBY_FL_USER8 | RUBY_FL_USER7 | RUBY_FL_USER6 | - RUBY_FL_USER5 | RUBY_FL_USER4 | RUBY_FL_USER3 + RARRAY_EMBED_LEN_MASK = RUBY_FL_USER4 | RUBY_FL_USER3 +#if USE_TRANSIENT_HEAP + , + + /** + * This flag has something to do with an array's "transiency". A transient + * array is an array of young generation (of generational GC), who stores + * its elements inside of dedicated memory pages called a transient heap. + * Not every young generation share that storage scheme, but elder + * generations must no join. + * + * @internal + * + * 3rd parties must not be aware that there even is more than one way to + * store array elements. It was a bad idea to expose this to them. + */ + RARRAY_TRANSIENT_FLAG = RUBY_FL_USER13 +#endif }; /** @@ -121,7 +156,10 @@ enum ruby_rarray_flags { */ enum ruby_rarray_consts { /** Where ::RARRAY_EMBED_LEN_MASK resides. */ - RARRAY_EMBED_LEN_SHIFT = RUBY_FL_USHIFT + 3 + RARRAY_EMBED_LEN_SHIFT = RUBY_FL_USHIFT + 3, + + /** Max possible number elements that can be embedded. */ + RARRAY_EMBED_LEN_MAX = RBIMPL_EMBED_LEN_MAX_OF(VALUE) }; /** Ruby's array. */ @@ -180,12 +218,7 @@ struct RArray { * to store its elements. In this case the length is encoded into the * flags. */ - /* This is a length 1 array because: - * 1. GCC has a bug that does not optimize C flexible array members - * (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102452) - * 2. Zero length arrays are not supported by all compilers - */ - const VALUE ary[1]; + const VALUE ary[RARRAY_EMBED_LEN_MAX]; } as; }; @@ -212,6 +245,16 @@ VALUE *rb_ary_ptr_use_start(VALUE ary); */ void rb_ary_ptr_use_end(VALUE a); +#if USE_TRANSIENT_HEAP +/** + * Destructively converts an array of transient backend into ordinal one. + * + * @param[out] a An object of ::RArray. + * @pre `a` must be a transient array. + * @post `a` gets out of transient heap, destructively. + */ +void rb_ary_detransient(VALUE a); +#endif RBIMPL_SYMBOL_EXPORT_END() RBIMPL_ATTR_PURE_UNLESS_DEBUG() @@ -284,6 +327,33 @@ RARRAY_LENINT(VALUE ary) } RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +/** + * Queries if the array is a transient array. + * + * @param[in] ary Array in question. + * @retval true Yes it is. + * @retval false No it isn't. + * @pre `ary` must be an instance of ::RArray. + * + * @internal + * + * @shyouhei doesn't understand the benefit of this function called from + * extension libraries. + */ +static inline bool +RARRAY_TRANSIENT_P(VALUE ary) +{ + RBIMPL_ASSERT_TYPE(ary, RUBY_T_ARRAY); + +#if USE_TRANSIENT_HEAP + return RB_FL_ANY_RAW(ary, RARRAY_TRANSIENT_FLAG); +#else + return false; +#endif +} + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() /** * @private * @@ -294,7 +364,7 @@ RBIMPL_ATTR_PURE_UNLESS_DEBUG() * @return Its backend storage. */ static inline const VALUE * -rb_array_const_ptr(VALUE a) +rb_array_const_ptr_transient(VALUE a) { RBIMPL_ASSERT_TYPE(a, RUBY_T_ARRAY); @@ -306,21 +376,110 @@ rb_array_const_ptr(VALUE a) } } +#if ! USE_TRANSIENT_HEAP +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +#endif +/** + * @private + * + * This is an implementation detail of RARRAY_PTR(). People do not use it + * directly. + * + * @param[in] a An object of ::RArray. + * @return Its backend storage. + * @post `a` is not a transient array. + */ +static inline const VALUE * +rb_array_const_ptr(VALUE a) +{ + RBIMPL_ASSERT_TYPE(a, RUBY_T_ARRAY); + +#if USE_TRANSIENT_HEAP + if (RARRAY_TRANSIENT_P(a)) { + rb_ary_detransient(a); + } +#endif + return rb_array_const_ptr_transient(a); +} + /** * @private * * This is an implementation detail of #RARRAY_PTR_USE. People do not use it * directly. + * + * @param[in] a An object of ::RArray. + * @param[in] allow_transient Whether `a` can be transient or not. + * @return Its backend storage. + * @post `a` is not a transient array unless `allow_transient`. + */ +static inline VALUE * +rb_array_ptr_use_start(VALUE a, + RBIMPL_ATTR_MAYBE_UNUSED() + int allow_transient) +{ + RBIMPL_ASSERT_TYPE(a, RUBY_T_ARRAY); + +#if USE_TRANSIENT_HEAP + if (!allow_transient) { + if (RARRAY_TRANSIENT_P(a)) { + rb_ary_detransient(a); + } + } +#endif + + return rb_ary_ptr_use_start(a); +} + +/** + * @private + * + * This is an implementation detail of #RARRAY_PTR_USE. People do not use it + * directly. + * + * @param[in] a An object of ::RArray. + * @param[in] allow_transient Whether `a` can be transient or not. */ -#define RBIMPL_RARRAY_STMT(ary, var, expr) do { \ +static inline void +rb_array_ptr_use_end(VALUE a, + RBIMPL_ATTR_MAYBE_UNUSED() + int allow_transient) +{ + RBIMPL_ASSERT_TYPE(a, RUBY_T_ARRAY); + rb_ary_ptr_use_end(a); +} + +/** + * @private + * + * This is an implementation detail of #RARRAY_PTR_USE. People do not use it + * directly. + */ +#define RBIMPL_RARRAY_STMT(flag, ary, var, expr) do { \ RBIMPL_ASSERT_TYPE((ary), RUBY_T_ARRAY); \ const VALUE rbimpl_ary = (ary); \ - VALUE *var = rb_ary_ptr_use_start(rbimpl_ary); \ + VALUE *var = rb_array_ptr_use_start(rbimpl_ary, (flag)); \ expr; \ - rb_ary_ptr_use_end(rbimpl_ary); \ + rb_array_ptr_use_end(rbimpl_ary, (flag)); \ } while (0) /** + * @private + * + * This is an implementation detail of #RARRAY_PTR_USE. People do not use it + * directly. + */ +#define RARRAY_PTR_USE_START(a) rb_array_ptr_use_start(a, 0) + +/** + * @private + * + * This is an implementation detail of #RARRAY_PTR_USE. People do not use it + * directly. + */ +#define RARRAY_PTR_USE_END(a) rb_array_ptr_use_end(a, 0) + +/** * Declares a section of code where raw pointers are used. In case you need to * touch the raw C array instead of polite CAPIs, then that operation shall be * wrapped using this macro. @@ -346,11 +505,37 @@ rb_array_const_ptr(VALUE a) * them use it... Maybe some transition path can be implemented later. */ #define RARRAY_PTR_USE(ary, ptr_name, expr) \ - RBIMPL_RARRAY_STMT(ary, ptr_name, expr) + RBIMPL_RARRAY_STMT(0, ary, ptr_name, expr) + +/** + * @private + * + * This is an implementation detail of #RARRAY_PTR_USE_TRANSIENT. People do + * not use it directly. + */ +#define RARRAY_PTR_USE_START_TRANSIENT(a) rb_array_ptr_use_start(a, 1) + +/** + * @private + * + * This is an implementation detail of #RARRAY_PTR_USE_TRANSIENT. People do + * not use it directly. + */ +#define RARRAY_PTR_USE_END_TRANSIENT(a) rb_array_ptr_use_end(a, 1) + +/** + * Identical to #RARRAY_PTR_USE, except the pointer can be a transient one. + * + * @param ary An object of ::RArray. + * @param ptr_name A variable name which points the C array in `expr`. + * @param expr The expression that touches `ptr_name`. + */ +#define RARRAY_PTR_USE_TRANSIENT(ary, ptr_name, expr) \ + RBIMPL_RARRAY_STMT(1, ary, ptr_name, expr) /** * Wild use of a C pointer. This function accesses the backend storage - * directly. This is slower than #RARRAY_PTR_USE. It exercises + * directly. This is slower than #RARRAY_PTR_USE_TRANSIENT. It exercises * extra manoeuvres to protect our generational GC. Use of this function is * considered archaic. Use a modern way instead. * @@ -385,7 +570,7 @@ RARRAY_PTR(VALUE ary) static inline void RARRAY_ASET(VALUE ary, long i, VALUE v) { - RARRAY_PTR_USE(ary, ptr, + RARRAY_PTR_USE_TRANSIENT(ary, ptr, RB_OBJ_WRITE(ary, &ptr[i], v)); } @@ -400,6 +585,6 @@ RARRAY_ASET(VALUE ary, long i, VALUE v) * remains as it is due to that. If we could warn such usages we can set a * transition path, but currently no way is found to do so. */ -#define RARRAY_AREF(a, i) RARRAY_CONST_PTR(a)[i] +#define RARRAY_AREF(a, i) RARRAY_CONST_PTR_TRANSIENT(a)[i] #endif /* RBIMPL_RARRAY_H */ diff --git a/include/ruby/internal/core/rclass.h b/include/ruby/internal/core/rclass.h index b0b6bfc80c..13a33a28bd 100644 --- a/include/ruby/internal/core/rclass.h +++ b/include/ruby/internal/core/rclass.h @@ -26,7 +26,9 @@ #include "ruby/internal/cast.h" /** @cond INTERNAL_MACRO */ +#define RMODULE_IS_OVERLAID RMODULE_IS_OVERLAID #define RMODULE_IS_REFINEMENT RMODULE_IS_REFINEMENT +#define RMODULE_INCLUDED_INTO_REFINEMENT RMODULE_INCLUDED_INTO_REFINEMENT /** @endcond */ /** @@ -53,12 +55,57 @@ * Why is it here, given RClass itself is not? */ enum ruby_rmodule_flags { + + /** + * This flag has something to do with refinements... I guess? It is set on + * occasions for modules that are refined by refinements, but it seems + * ... nobody cares about such things? Not sure but this flag could + * perhaps be a write-only information. + */ + RMODULE_IS_OVERLAID = RUBY_FL_USER2, + /** * This flag has something to do with refinements. A module created using * 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_USER3, + + /** + * This flag has something to do with refinements. This is set when a + * (non-refinement) module is included into another module, which is a + * refinement. This amends the way `super` searches for a super method. + * + * ```ruby + * class Foo + * def foo + * "Foo" + * end + * end + * + * module Bar + * def foo + * "[#{super}]" # this + * end + * end + * + * module Baz + * refine Foo do + * include Bar + * def foo + * "<#{super}>" + * end + * end + * end + * + * using Baz + * Foo.new.foo # => "[<Foo>]" + * ``` + * + * The `super` marked with "this" comment shall look for overlaid + * `Foo#foo`, which is not the ordinal method lookup direction. + */ + RMODULE_INCLUDED_INTO_REFINEMENT = RUBY_FL_USER4 }; 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 43ab3c01e7..f6656b6546 100644 --- a/include/ruby/internal/core/rdata.h +++ b/include/ruby/internal/core/rdata.h @@ -369,6 +369,30 @@ rb_data_object_alloc(VALUE klass, void *data, RUBY_DATA_FUNC dmark, RUBY_DATA_FU return rb_data_object_wrap(klass, data, dmark, dfree); } +RBIMPL_ATTR_DEPRECATED(("by: rb_cObject. Will be removed in 3.1.")) +RBIMPL_ATTR_PURE() +/** + * @private + * + * @deprecated There once was a variable called rb_cData, which no longer + * exists today. This function is a function because we want + * warnings for the usages. + */ +static inline VALUE +rb_cData(void) +{ + return rb_cObject; +} + +/** + * @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. + */ +#define rb_cData rb_cData() + /** @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/rfile.h b/include/ruby/internal/core/rfile.h index a0eb8cb833..f8dddde9e5 100644 --- a/include/ruby/internal/core/rfile.h +++ b/include/ruby/internal/core/rfile.h @@ -25,7 +25,7 @@ /* rb_io_t is in ruby/io.h. The header file has historically not been included * into ruby/ruby.h. We follow that tradition. */ -struct rb_io; +struct rb_io_t; /** * Ruby's File and IO. Ruby's IO are not just file descriptors. They have @@ -38,7 +38,7 @@ struct RFile { struct RBasic basic; /** IO's specific fields. */ - struct rb_io *fptr; + struct rb_io_t *fptr; }; /** diff --git a/include/ruby/internal/core/rhash.h b/include/ruby/internal/core/rhash.h index 897c570794..61d2c15d87 100644 --- a/include/ruby/internal/core/rhash.h +++ b/include/ruby/internal/core/rhash.h @@ -54,6 +54,19 @@ * * @internal * + * Declaration of rb_hash_iter_lev() is at include/ruby/backward.h. + */ +#define RHASH_ITER_LEV(h) rb_hash_iter_lev(h) + +/** + * @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_hash_ifnone() is at include/ruby/backward.h. */ #define RHASH_IFNONE(h) rb_hash_ifnone(h) diff --git a/include/ruby/internal/core/rmatch.h b/include/ruby/internal/core/rmatch.h index a528c2999e..2d2fd897f5 100644 --- a/include/ruby/internal/core/rmatch.h +++ b/include/ruby/internal/core/rmatch.h @@ -68,7 +68,7 @@ struct rmatch_offset { }; /** Represents a match. */ -struct rb_matchext_struct { +struct rmatch { /** * "Registers" of a match. This is a quasi-opaque struct that holds * execution result of a match. Roughly resembles `&~`. @@ -82,8 +82,6 @@ struct rb_matchext_struct { int char_offset_num_allocated; }; -typedef struct rb_matchext_struct rb_matchext_t; - /** * Regular expression execution context. When a regular expression "matches" * to a string, it generates capture groups etc. This struct holds that info. @@ -104,13 +102,16 @@ struct RMatch { VALUE str; /** + * The result of this match. + */ + struct rmatch *rmatch; + + /** * The expression of this match. */ VALUE regexp; /* RRegexp */ }; -#define RMATCH_EXT(m) ((rb_matchext_t *)((char *)(m) + sizeof(struct RMatch))) - RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() /** @@ -138,7 +139,8 @@ static inline struct re_registers * RMATCH_REGS(VALUE match) { RBIMPL_ASSERT_TYPE(match, RUBY_T_MATCH); - return &RMATCH_EXT(match)->regs; + RBIMPL_ASSERT_OR_ASSUME(RMATCH(match)->rmatch != NULL); + return &RMATCH(match)->rmatch->regs; } #endif /* RBIMPL_RMATCH_H */ diff --git a/include/ruby/internal/core/robject.h b/include/ruby/internal/core/robject.h index c2bcae6306..f2028063a6 100644 --- a/include/ruby/internal/core/robject.h +++ b/include/ruby/internal/core/robject.h @@ -37,15 +37,16 @@ /** * Convenient casting macro. * - * @param obj An object, which is in fact an ::RObject. - * @return The passed object casted to ::RObject. + * @param obj An object, which is in fact an ::RRegexp. + * @return The passed object casted to ::RRegexp. */ #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_NUMIV ROBJECT_NUMIV #define ROBJECT_IVPTR ROBJECT_IVPTR +#define ROBJECT_IV_INDEX_TBL ROBJECT_IV_INDEX_TBL /** @endcond */ /** @@ -74,6 +75,15 @@ enum ruby_robject_flags { ROBJECT_EMBED = RUBY_FL_USER1 }; +/** + * This is an enum because GDB wants it (rather than a macro). People need not + * bother. + */ +enum ruby_robject_consts { + /** Max possible number of instance variables that can be embedded. */ + ROBJECT_EMBED_LEN_MAX = RBIMPL_EMBED_LEN_MAX_OF(VALUE) +}; + struct st_table; /** @@ -93,6 +103,13 @@ struct RObject { * this pattern. */ struct { + + /** + * Number of instance variables. This is per object; objects might + * differ in this field even if they have the identical classes. + */ + uint32_t numiv; + /** Pointer to a C array that holds instance variables. */ VALUE *ivptr; @@ -104,24 +121,42 @@ struct RObject { * * This is a shortcut for `RCLASS_IV_INDEX_TBL(rb_obj_class(obj))`. */ - struct rb_id_table *iv_index_tbl; + struct st_table *iv_index_tbl; } heap; - /* Embedded instance variables. When an object is small enough, it + /** + * Embedded instance variables. When an object is small enough, it * uses this area to store the instance variables. - * - * This is a length 1 array because: - * 1. GCC has a bug that does not optimize C flexible array members - * (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102452) - * 2. Zero length arrays are not supported by all compilers */ - VALUE ary[1]; + VALUE ary[ROBJECT_EMBED_LEN_MAX]; } as; }; RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() /** + * Queries the number of instance variables. + * + * @param[in] obj Object in question. + * @return Its number of instance variables. + * @pre `obj` must be an instance of ::RObject. + */ +static inline uint32_t +ROBJECT_NUMIV(VALUE obj) +{ + RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT); + + if (RB_FL_ANY_RAW(obj, ROBJECT_EMBED)) { + return ROBJECT_EMBED_LEN_MAX; + } + else { + return ROBJECT(obj)->as.heap.numiv; + } +} + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +/** * Queries the instance variables. * * @param[in] obj Object in question. diff --git a/include/ruby/internal/core/rstring.h b/include/ruby/internal/core/rstring.h index 0bca74e688..a682dbe22f 100644 --- a/include/ruby/internal/core/rstring.h +++ b/include/ruby/internal/core/rstring.h @@ -42,7 +42,13 @@ /** @cond INTERNAL_MACRO */ #define RSTRING_NOEMBED RSTRING_NOEMBED +#if !USE_RVARGC +#define RSTRING_EMBED_LEN_MASK RSTRING_EMBED_LEN_MASK +#define RSTRING_EMBED_LEN_SHIFT RSTRING_EMBED_LEN_SHIFT +#define RSTRING_EMBED_LEN_MAX RSTRING_EMBED_LEN_MAX +#endif #define RSTRING_FSTR RSTRING_FSTR +#define RSTRING_EMBED_LEN RSTRING_EMBED_LEN #define RSTRING_LEN RSTRING_LEN #define RSTRING_LENINT RSTRING_LENINT #define RSTRING_PTR RSTRING_PTR @@ -156,6 +162,21 @@ enum ruby_rstring_flags { */ RSTRING_NOEMBED = RUBY_FL_USER1, +#if !USE_RVARGC + /** + * When a string employs embedded strategy (see ::RSTRING_NOEMBED), these + * bits are used to store the number of bytes actually filled into + * ::RString::ary. + * + * @internal + * + * 3rd parties must not be aware that there even is more than one way to + * store a string. Might better be hidden. + */ + RSTRING_EMBED_LEN_MASK = RUBY_FL_USER2 | RUBY_FL_USER3 | RUBY_FL_USER4 | + RUBY_FL_USER5 | RUBY_FL_USER6, +#endif + /* Actually, string encodings are also encoded into the flags, using * remaining bits.*/ @@ -181,6 +202,20 @@ enum ruby_rstring_flags { RSTRING_FSTR = RUBY_FL_USER17 }; +#if !USE_RVARGC +/** + * This is an enum because GDB wants it (rather than a macro). People need not + * bother. + */ +enum ruby_rstring_consts { + /** Where ::RSTRING_EMBED_LEN_MASK resides. */ + RSTRING_EMBED_LEN_SHIFT = RUBY_FL_USHIFT + 2, + + /** Max possible number of characters that can be embedded. */ + RSTRING_EMBED_LEN_MAX = RBIMPL_EMBED_LEN_MAX_OF(char) - 1 +}; +#endif + /** * Ruby's String. A string in ruby conceptually has these information: * @@ -198,13 +233,6 @@ struct RString { /** Basic part, including flags and class. */ struct RBasic basic; - /** - * Length of the string, not including terminating NUL character. - * - * @note This is in bytes. - */ - long len; - /** String's specific fields. */ union { @@ -213,6 +241,14 @@ struct RString { * pattern. */ struct { + + /** + * Length of the string, not including terminating NUL character. + * + * @note This is in bytes. + */ + long len; + /** * Pointer to the contents of the string. In the old days each * string had dedicated memory regions. That is no longer true @@ -243,12 +279,24 @@ struct RString { /** Embedded contents. */ struct { +#if USE_RVARGC + short len; /* This is a length 1 array because: * 1. GCC has a bug that does not optimize C flexible array members * (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102452) * 2. Zero length arrays are not supported by all compilers */ char ary[1]; +#else + /** + * When a string is short enough, it uses this area to store the + * contents themselves. This was impractical in the 20th century, + * but these days 64 bit machines can typically hold 24 bytes here. + * Could be sufficiently large. In this case the length is encoded + * into the flags. + */ + char ary[RSTRING_EMBED_LEN_MAX + 1]; +#endif } embed; } as; }; @@ -361,12 +409,30 @@ RBIMPL_ATTR_ARTIFICIAL() * * @param[in] str String in question. * @return Its length, in bytes. - * @pre `str` must be an instance of ::RString. + * @pre `str` must be an instance of ::RString, and must has its + * ::RSTRING_NOEMBED flag off. + * + * @internal + * + * This was a macro before. It was inevitable to be public, since macros are + * global constructs. But should it be forever? Now that it is a function, + * @shyouhei thinks it could just be eliminated, hidden into implementation + * details. */ static inline long -RSTRING_LEN(VALUE str) +RSTRING_EMBED_LEN(VALUE str) { - return RSTRING(str)->len; + RBIMPL_ASSERT_TYPE(str, RUBY_T_STRING); + RBIMPL_ASSERT_OR_ASSUME(! RB_FL_ANY_RAW(str, RSTRING_NOEMBED)); + +#if USE_RVARGC + short f = RSTRING(str)->as.embed.len; +#else + VALUE f = RBASIC(str)->flags; + f &= RSTRING_EMBED_LEN_MASK; + f >>= RSTRING_EMBED_LEN_SHIFT; +#endif + return RBIMPL_CAST((long)f); } RBIMPL_WARNING_PUSH() @@ -396,7 +462,7 @@ rbimpl_rstring_getmem(VALUE str) else { /* Expecting compilers to optimize this on-stack struct away. */ struct RString retval; - retval.len = RSTRING_LEN(str); + retval.as.heap.len = RSTRING_EMBED_LEN(str); retval.as.heap.ptr = RSTRING(str)->as.embed.ary; return retval; } @@ -404,6 +470,21 @@ rbimpl_rstring_getmem(VALUE str) RBIMPL_WARNING_POP() +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +/** + * Queries the length of the string. + * + * @param[in] str String in question. + * @return Its length, in bytes. + * @pre `str` must be an instance of ::RString. + */ +static inline long +RSTRING_LEN(VALUE str) +{ + return rbimpl_rstring_getmem(str).as.heap.len; +} + RBIMPL_ATTR_ARTIFICIAL() /** * Queries the contents pointer of the string. @@ -417,9 +498,13 @@ RSTRING_PTR(VALUE str) { char *ptr = rbimpl_rstring_getmem(str).as.heap.ptr; - if (RUBY_DEBUG && RB_UNLIKELY(! ptr)) { + if (RB_UNLIKELY(! ptr)) { /* :BEWARE: @shyouhei thinks that currently, there are rooms for this - * function to return NULL. Better check here for maximum safety. + * function to return NULL. In the 20th century that was a pointless + * concern. However struct RString can hold fake strings nowadays. It + * seems no check against NULL are exercised around handling of them + * (one of such usages is located in marshal.c, which scares + * @shyouhei). Better check here for maximum safety. * * Also, this is not rb_warn() because RSTRING_PTR() can be called * during GC (see what obj_info() does). rb_warn() needs to allocate @@ -443,12 +528,12 @@ RSTRING_END(VALUE str) { struct RString buf = rbimpl_rstring_getmem(str); - if (RUBY_DEBUG && RB_UNLIKELY(! buf.as.heap.ptr)) { + if (RB_UNLIKELY(! buf.as.heap.ptr)) { /* Ditto. */ rb_debug_rstring_null_ptr("RSTRING_END"); } - return &buf.as.heap.ptr[buf.len]; + return &buf.as.heap.ptr[buf.as.heap.len]; } RBIMPL_ATTR_ARTIFICIAL() @@ -482,7 +567,7 @@ RSTRING_LENINT(VALUE str) __extension__ ({ \ struct RString rbimpl_str = rbimpl_rstring_getmem(str); \ (ptrvar) = rbimpl_str.as.heap.ptr; \ - (lenvar) = rbimpl_str.len; \ + (lenvar) = rbimpl_str.as.heap.len; \ }) #else # define RSTRING_GETMEM(str, ptrvar, lenvar) \ diff --git a/include/ruby/internal/core/rtypeddata.h b/include/ruby/internal/core/rtypeddata.h index 6c19576c20..bbf208867d 100644 --- a/include/ruby/internal/core/rtypeddata.h +++ b/include/ruby/internal/core/rtypeddata.h @@ -114,8 +114,6 @@ #define RUBY_TYPED_PROMOTED1 RUBY_TYPED_PROMOTED1 /** @endcond */ -#define TYPED_DATA_EMBEDDED 2 - /** * @private * @@ -139,8 +137,6 @@ rbimpl_typeddata_flags { */ RUBY_TYPED_FREE_IMMEDIATELY = 1, - RUBY_TYPED_EMBEDDABLE = 2, - /** * This flag has something to do with Ractor. Multiple Ractors run without * protecting each other. Sharing an object among Ractors is basically @@ -177,16 +173,10 @@ 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 mysterious. It seems nobody is currently using it. The + * intention of this flag is also unclear. We need further investigations. */ - RUBY_TYPED_UNUSED = RUBY_FL_UNUSED6, - - /** - * This flag determines whether marking and compaction should be carried out - * using the dmark/dcompact callback functions or whether we should mark - * declaratively using a list of references defined inside the data struct we're wrapping - */ - RUBY_TYPED_DECL_MARKING = RUBY_FL_USER2 + RUBY_TYPED_PROMOTED1 = RUBY_FL_PROMOTED1 /* THIS FLAG DEPENDS ON Ruby version */ }; /** @@ -357,14 +347,16 @@ struct RTypedData { * data. This roughly resembles a Ruby level class (apart from method * definition etc.) */ - const rb_data_type_t *const type; + const rb_data_type_t *type; /** * This has to be always 1. * * @internal + * + * Why, then, this is not a const ::VALUE? */ - const VALUE typed_flag; + VALUE typed_flag; /** Pointer to the actual C level struct that you want to wrap. */ void *data; @@ -464,7 +456,7 @@ 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 *)RTYPEDDATA_DATA(result)); \ RBIMPL_CAST(/*suppress unused variable warnings*/(void)(sval)) /** @@ -515,36 +507,6 @@ RBIMPL_SYMBOL_EXPORT_END() #define TypedData_Get_Struct(obj,type,data_type,sval) \ ((sval) = RBIMPL_CAST((type *)rb_check_typeddata((obj), (data_type)))) -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 - - return RTYPEDDATA(obj)->typed_flag & TYPED_DATA_EMBEDDED; -} - -static inline void * -RTYPEDDATA_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. 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 *); - - return RTYPEDDATA_EMBEDDED_P(obj) ? (char *)obj + embedded_typed_data_size : RTYPEDDATA(obj)->data; -} - RBIMPL_ATTR_PURE() RBIMPL_ATTR_ARTIFICIAL() /** @@ -561,8 +523,7 @@ RBIMPL_ATTR_ARTIFICIAL() static inline bool rbimpl_rtypeddata_p(VALUE obj) { - VALUE typed_flag = RTYPEDDATA(obj)->typed_flag; - return typed_flag != 0 && typed_flag <= 3; + return RTYPEDDATA(obj)->typed_flag == 1; } RBIMPL_ATTR_PURE_UNLESS_DEBUG() diff --git a/include/ruby/internal/dllexport.h b/include/ruby/internal/dllexport.h index 71026e7100..08a262209d 100644 --- a/include/ruby/internal/dllexport.h +++ b/include/ruby/internal/dllexport.h @@ -37,7 +37,9 @@ * ``` */ #undef RUBY_EXTERN -#if defined(RUBY_EXPORT) +#if defined(MJIT_HEADER) && defined(_WIN32) +# define RUBY_EXTERN extern __declspec(dllimport) +#elif defined(RUBY_EXPORT) # define RUBY_EXTERN extern #elif defined(_WIN32) # define RUBY_EXTERN extern __declspec(dllimport) @@ -57,6 +59,36 @@ # define RUBY_FUNC_EXPORTED /* void */ #endif +/** + * @cond INTERNAL_MACRO + * + * These MJIT related macros are placed here because translate_mjit_header can + * need them. Extension libraries should not touch. + */ + +/* These macros are used for functions which are exported only for MJIT + and NOT ensured to be exported in future versions. */ + +#if ! defined(MJIT_HEADER) +# define MJIT_FUNC_EXPORTED RUBY_FUNC_EXPORTED +#elif ! RBIMPL_COMPILER_IS(MSVC) +# define MJIT_FUNC_EXPORTED RUBY_FUNC_EXPORTED +#else +# define MJIT_FUNC_EXPORTED static +#endif + +#define MJIT_SYMBOL_EXPORT_BEGIN RUBY_SYMBOL_EXPORT_BEGIN +#define MJIT_SYMBOL_EXPORT_END RUBY_SYMBOL_EXPORT_END + +/* On mswin, MJIT header transformation can't be used since cl.exe can't output + preprocessed output preserving macros. So this `MJIT_STATIC` is needed + to force non-static function to static on MJIT header to avoid symbol conflict. */ +#ifdef MJIT_HEADER +# define MJIT_STATIC static +#else +# define MJIT_STATIC +#endif + /** @endcond */ /** Shortcut macro equivalent to `RUBY_SYMBOL_EXPORT_BEGIN extern "C" {`. diff --git a/include/ruby/internal/encoding/ctype.h b/include/ruby/internal/encoding/ctype.h index 05c314aeb3..64aaf0a990 100644 --- a/include/ruby/internal/encoding/ctype.h +++ b/include/ruby/internal/encoding/ctype.h @@ -36,8 +36,8 @@ RBIMPL_SYMBOL_EXPORT_BEGIN() * @param[in] p Pointer to a possibly-middle of a character. * @param[in] end End of the string. * @param[in] enc Encoding. - * @retval false It isn't. - * @retval true It is. + * @retval 0 It isn't. + * @retval otherwise It is. */ static inline bool rb_enc_is_newline(const char *p, const char *e, rb_encoding *enc) @@ -53,11 +53,11 @@ rb_enc_is_newline(const char *p, const char *e, rb_encoding *enc) * encoding. The "character type" here is a set of macros defined in onigmo.h, * like `ONIGENC_CTYPE_PUNCT`. * - * @param[in] c An `OnigCodePoint` value. - * @param[in] t An `OnigCtype` value. - * @param[in] enc A `rb_encoding*` value. - * @retval true `c` is of `t` in `enc`. - * @retval false Otherwise. + * @param[in] c An `OnigCodePoint` value. + * @param[in] t An `OnigCtype` value. + * @param[in] enc A `rb_encoding*` value. + * @retval 1 `c` is of `t` in `enc`. + * @retval 0 Otherwise. */ static inline bool rb_enc_isctype(OnigCodePoint c, OnigCtype t, rb_encoding *enc) @@ -68,10 +68,10 @@ rb_enc_isctype(OnigCodePoint c, OnigCtype t, rb_encoding *enc) /** * Identical to rb_isascii(), except it additionally takes an encoding. * - * @param[in] c A code point. - * @param[in] enc An encoding. - * @retval false `c` is out of range of ASCII character set in `enc`. - * @retval true Otherwise. + * @param[in] c A code point. + * @param[in] enc An encoding. + * @retval 0 `c` is out of range of ASCII character set in `enc`. + * @retval 1 Otherwise. * * @internal * @@ -87,10 +87,10 @@ rb_enc_isascii(OnigCodePoint c, rb_encoding *enc) /** * Identical to rb_isalpha(), except it additionally takes an encoding. * - * @param[in] c A code point. - * @param[in] enc An encoding. - * @retval true `enc` classifies `c` as "ALPHA". - * @retval false Otherwise. + * @param[in] c A code point. + * @param[in] enc An encoding. + * @retval 1 `enc` classifies `c` as "ALPHA". + * @retval 0 Otherwise. */ static inline bool rb_enc_isalpha(OnigCodePoint c, rb_encoding *enc) @@ -101,10 +101,10 @@ rb_enc_isalpha(OnigCodePoint c, rb_encoding *enc) /** * Identical to rb_islower(), except it additionally takes an encoding. * - * @param[in] c A code point. - * @param[in] enc An encoding. - * @retval true `enc` classifies `c` as "LOWER". - * @retval false Otherwise. + * @param[in] c A code point. + * @param[in] enc An encoding. + * @retval 1 `enc` classifies `c` as "LOWER". + * @retval 0 Otherwise. */ static inline bool rb_enc_islower(OnigCodePoint c, rb_encoding *enc) @@ -115,10 +115,10 @@ rb_enc_islower(OnigCodePoint c, rb_encoding *enc) /** * Identical to rb_isupper(), except it additionally takes an encoding. * - * @param[in] c A code point. - * @param[in] enc An encoding. - * @retval true `enc` classifies `c` as "UPPER". - * @retval false Otherwise. + * @param[in] c A code point. + * @param[in] enc An encoding. + * @retval 1 `enc` classifies `c` as "UPPER". + * @retval 0 Otherwise. */ static inline bool rb_enc_isupper(OnigCodePoint c, rb_encoding *enc) @@ -127,26 +127,12 @@ rb_enc_isupper(OnigCodePoint c, rb_encoding *enc) } /** - * Identical to rb_iscntrl(), except it additionally takes an encoding. - * - * @param[in] c A code point. - * @param[in] enc An encoding. - * @retval true `enc` classifies `c` as "CNTRL". - * @retval false Otherwise. - */ -static inline bool -rb_enc_iscntrl(OnigCodePoint c, rb_encoding *enc) -{ - return ONIGENC_IS_CODE_CNTRL(enc, c); -} - -/** * Identical to rb_ispunct(), except it additionally takes an encoding. * - * @param[in] c A code point. - * @param[in] enc An encoding. - * @retval true `enc` classifies `c` as "PUNCT". - * @retval false Otherwise. + * @param[in] c A code point. + * @param[in] enc An encoding. + * @retval 1 `enc` classifies `c` as "PUNCT". + * @retval 0 Otherwise. */ static inline bool rb_enc_ispunct(OnigCodePoint c, rb_encoding *enc) @@ -157,10 +143,10 @@ rb_enc_ispunct(OnigCodePoint c, rb_encoding *enc) /** * Identical to rb_isalnum(), except it additionally takes an encoding. * - * @param[in] c A code point. - * @param[in] enc An encoding. - * @retval true `enc` classifies `c` as "ANUM". - * @retval false Otherwise. + * @param[in] c A code point. + * @param[in] enc An encoding. + * @retval 1 `enc` classifies `c` as "ANUM". + * @retval 0 Otherwise. */ static inline bool rb_enc_isalnum(OnigCodePoint c, rb_encoding *enc) @@ -171,10 +157,10 @@ rb_enc_isalnum(OnigCodePoint c, rb_encoding *enc) /** * Identical to rb_isprint(), except it additionally takes an encoding. * - * @param[in] c A code point. - * @param[in] enc An encoding. - * @retval true `enc` classifies `c` as "PRINT". - * @retval false Otherwise. + * @param[in] c A code point. + * @param[in] enc An encoding. + * @retval 1 `enc` classifies `c` as "PRINT". + * @retval 0 Otherwise. */ static inline bool rb_enc_isprint(OnigCodePoint c, rb_encoding *enc) @@ -185,10 +171,10 @@ rb_enc_isprint(OnigCodePoint c, rb_encoding *enc) /** * Identical to rb_isspace(), except it additionally takes an encoding. * - * @param[in] c A code point. - * @param[in] enc An encoding. - * @retval true `enc` classifies `c` as "PRINT". - * @retval false Otherwise. + * @param[in] c A code point. + * @param[in] enc An encoding. + * @retval 1 `enc` classifies `c` as "PRINT". + * @retval 0 Otherwise. */ static inline bool rb_enc_isspace(OnigCodePoint c, rb_encoding *enc) @@ -199,10 +185,10 @@ rb_enc_isspace(OnigCodePoint c, rb_encoding *enc) /** * Identical to rb_isdigit(), except it additionally takes an encoding. * - * @param[in] c A code point. - * @param[in] enc An encoding. - * @retval true `enc` classifies `c` as "DIGIT". - * @retval false Otherwise. + * @param[in] c A code point. + * @param[in] enc An encoding. + * @retval 1 `enc` classifies `c` as "DIGIT". + * @retval 0 Otherwise. */ static inline bool rb_enc_isdigit(OnigCodePoint c, rb_encoding *enc) @@ -249,7 +235,6 @@ RBIMPL_SYMBOL_EXPORT_END() #define rb_enc_isdigit rb_enc_isdigit #define rb_enc_islower rb_enc_islower #define rb_enc_isprint rb_enc_isprint -#define rb_enc_iscntrl rb_enc_iscntrl #define rb_enc_ispunct rb_enc_ispunct #define rb_enc_isspace rb_enc_isspace #define rb_enc_isupper rb_enc_isupper diff --git a/include/ruby/internal/encoding/encoding.h b/include/ruby/internal/encoding/encoding.h index dc3e0151f0..9208d27ecf 100644 --- a/include/ruby/internal/encoding/encoding.h +++ b/include/ruby/internal/encoding/encoding.h @@ -139,6 +139,23 @@ RBIMPL_ATTR_NOALIAS() int rb_char_to_option_kcode(int c, int *option, int *kcode); /** + * Creates a new encoding, using the passed one as a template. + * + * @param[in] name Name of the creating encoding. + * @param[in] src Template. + * @exception rb_eArgError Duplicated or malformed `name`. + * @return Replicated new encoding's index. + * @post Encoding named `name` is created as a copy of `src`, whose index + * is the return value. + * + * @internal + * + * `name` can be `NULL`, but that just raises an exception. OTOH it seems no + * sanity check is done against `src`...? + */ +int rb_enc_replicate(const char *name, rb_encoding *src); + +/** * Creates a new "dummy" encoding. Roughly speaking, an encoding is dummy when * it is stateful. Notable example of dummy encoding are those defined in * ISO/IEC 2022 @@ -358,8 +375,8 @@ rb_encoding *rb_enc_check(VALUE str1,VALUE str2); VALUE rb_enc_associate_index(VALUE obj, int encindex); /** - * Identical to rb_enc_associate_index(), except it takes an encoding itself - * instead of its index. + * Identical to rb_enc_associate(), except it takes an encoding itself instead + * of its index. * * @param[out] obj Object in question. * @param[in] enc An encoding. @@ -626,12 +643,10 @@ rb_enc_code_to_mbclen(int c, rb_encoding *enc) * Identical to rb_enc_uint_chr(), except it writes back to the passed buffer * instead of allocating one. * - * @param[in] c Code point. - * @param[out] buf Return buffer. - * @param[in] enc Target encoding scheme. - * @retval <= 0 `c` is invalid in `enc`. - * @return otherwise Number of bytes written to `buf`. - * @post `c` is encoded according to `enc`, then written to `buf`. + * @param[in] c Code point. + * @param[out] buf Return buffer. + * @param[in] enc Target encoding scheme. + * @post `c` is encoded according to `enc`, then written to `buf`. * * @internal * diff --git a/include/ruby/internal/encoding/string.h b/include/ruby/internal/encoding/string.h index 2b9dfe4f31..6ed7ca1c90 100644 --- a/include/ruby/internal/encoding/string.h +++ b/include/ruby/internal/encoding/string.h @@ -30,7 +30,7 @@ RBIMPL_SYMBOL_EXPORT_BEGIN() /** - * Identical to rb_str_new(), except it additionally takes an encoding. + * Identical to rb_enc_str_new(), except it additionally takes an encoding. * * @param[in] ptr A memory region of `len` bytes length. * @param[in] len Length of `ptr`, in bytes, not including the diff --git a/include/ruby/internal/encoding/transcode.h b/include/ruby/internal/encoding/transcode.h index 7f26d2eae9..60c96a41c9 100644 --- a/include/ruby/internal/encoding/transcode.h +++ b/include/ruby/internal/encoding/transcode.h @@ -476,16 +476,16 @@ enum ruby_econv_flag_type { RUBY_ECONV_UNDEF_HEX_CHARREF = 0x00000030, /** Decorators are there. */ - RUBY_ECONV_DECORATOR_MASK = 0x0001ff00, + RUBY_ECONV_DECORATOR_MASK = 0x0000ff00, /** Newline converters are there. */ - RUBY_ECONV_NEWLINE_DECORATOR_MASK = 0x00007f00, + RUBY_ECONV_NEWLINE_DECORATOR_MASK = 0x00003f00, /** (Unclear; seems unused). */ RUBY_ECONV_NEWLINE_DECORATOR_READ_MASK = 0x00000f00, /** (Unclear; seems unused). */ - RUBY_ECONV_NEWLINE_DECORATOR_WRITE_MASK = 0x00007000, + RUBY_ECONV_NEWLINE_DECORATOR_WRITE_MASK = 0x00003000, /** Universal newline mode. */ RUBY_ECONV_UNIVERSAL_NEWLINE_DECORATOR = 0x00000100, @@ -496,14 +496,11 @@ enum ruby_econv_flag_type { /** CRLF to CR conversion shall happen. */ RUBY_ECONV_CR_NEWLINE_DECORATOR = 0x00002000, - /** CRLF to LF conversion shall happen. */ - RUBY_ECONV_LF_NEWLINE_DECORATOR = 0x00004000, - /** Texts shall be XML-escaped. */ - RUBY_ECONV_XML_TEXT_DECORATOR = 0x00008000, + RUBY_ECONV_XML_TEXT_DECORATOR = 0x00004000, /** Texts shall be AttrValue escaped */ - RUBY_ECONV_XML_ATTR_CONTENT_DECORATOR = 0x00010000, + RUBY_ECONV_XML_ATTR_CONTENT_DECORATOR = 0x00008000, /** (Unclear; seems unused). */ RUBY_ECONV_STATEFUL_DECORATOR_MASK = 0x00f00000, @@ -532,7 +529,6 @@ enum ruby_econv_flag_type { #define ECONV_UNIVERSAL_NEWLINE_DECORATOR RUBY_ECONV_UNIVERSAL_NEWLINE_DECORATOR /**< @old{RUBY_ECONV_UNIVERSAL_NEWLINE_DECORATOR} */ #define ECONV_CRLF_NEWLINE_DECORATOR RUBY_ECONV_CRLF_NEWLINE_DECORATOR /**< @old{RUBY_ECONV_CRLF_NEWLINE_DECORATOR} */ #define ECONV_CR_NEWLINE_DECORATOR RUBY_ECONV_CR_NEWLINE_DECORATOR /**< @old{RUBY_ECONV_CR_NEWLINE_DECORATOR} */ -#define ECONV_LF_NEWLINE_DECORATOR RUBY_ECONV_LF_NEWLINE_DECORATOR /**< @old{RUBY_ECONV_LF_NEWLINE_DECORATOR} */ #define ECONV_XML_TEXT_DECORATOR RUBY_ECONV_XML_TEXT_DECORATOR /**< @old{RUBY_ECONV_XML_TEXT_DECORATOR} */ #define ECONV_XML_ATTR_CONTENT_DECORATOR RUBY_ECONV_XML_ATTR_CONTENT_DECORATOR /**< @old{RUBY_ECONV_XML_ATTR_CONTENT_DECORATOR} */ #define ECONV_STATEFUL_DECORATOR_MASK RUBY_ECONV_STATEFUL_DECORATOR_MASK /**< @old{RUBY_ECONV_STATEFUL_DECORATOR_MASK} */ @@ -547,10 +543,10 @@ enum ruby_econv_flag_type { */ /** Indicates the input is a part of much larger one. */ - RUBY_ECONV_PARTIAL_INPUT = 0x00020000, + RUBY_ECONV_PARTIAL_INPUT = 0x00010000, /** Instructs the converter to stop after output. */ - RUBY_ECONV_AFTER_OUTPUT = 0x00040000, + RUBY_ECONV_AFTER_OUTPUT = 0x00020000, #define ECONV_PARTIAL_INPUT RUBY_ECONV_PARTIAL_INPUT /**< @old{RUBY_ECONV_PARTIAL_INPUT} */ #define ECONV_AFTER_OUTPUT RUBY_ECONV_AFTER_OUTPUT /**< @old{RUBY_ECONV_AFTER_OUTPUT} */ diff --git a/include/ruby/internal/error.h b/include/ruby/internal/error.h index cd37f4461a..49e2276cb9 100644 --- a/include/ruby/internal/error.h +++ b/include/ruby/internal/error.h @@ -50,19 +50,7 @@ typedef enum { /** Warning is for experimental features. */ RB_WARN_CATEGORY_EXPERIMENTAL, - /** Warning is for performance issues (not enabled by -w). */ - RB_WARN_CATEGORY_PERFORMANCE, - - RB_WARN_CATEGORY_DEFAULT_BITS = ( - (1U << RB_WARN_CATEGORY_DEPRECATED) | - (1U << RB_WARN_CATEGORY_EXPERIMENTAL) | - 0), - - RB_WARN_CATEGORY_ALL_BITS = ( - (1U << RB_WARN_CATEGORY_DEPRECATED) | - (1U << RB_WARN_CATEGORY_EXPERIMENTAL) | - (1U << RB_WARN_CATEGORY_PERFORMANCE) | - 0) + RB_WARN_CATEGORY_ALL_BITS = 0x6 /* no RB_WARN_CATEGORY_NONE bit */ } rb_warning_category_t; /** for rb_readwrite_sys_fail first argument */ @@ -481,7 +469,7 @@ VALUE *rb_ruby_debug_ptr(void); */ #define ruby_debug (*rb_ruby_debug_ptr()) -/* reports if $VERBOSE is true */ +/* reports if `-W' specified */ RBIMPL_ATTR_NONNULL((1)) RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 2) /** @@ -496,8 +484,7 @@ RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 2) * default, the method just emits its passed contents to ::rb_stderr using * rb_io_write(). * - * @note This function is affected by the value of $VERBOSE, it does - * nothing unless $VERBOSE is true. + * @note This function is affected by the `-W` flag. * @param[in] fmt Format specifier string compatible with rb_sprintf(). * * @internal @@ -522,7 +509,7 @@ RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 3, 4) * Issues a compile-time warning that happens at `__file__:__line__`. Purpose * of this function being exposed to CAPI is unclear. * - * @note This function is affected by the value of $VERBOSE. + * @note This function is affected by the `-W` flag. * @param[in] file The path corresponding to Ruby level `__FILE__`. * @param[in] line The number corresponding to Ruby level `__LINE__`. * @param[in] fmt Format specifier string compatible with rb_sprintf(). @@ -535,20 +522,19 @@ RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 2) * Identical to rb_sys_fail(), except it does not raise an exception to render * a warning instead. * - * @note This function is affected by the value of $VERBOSE. + * @note This function is affected by the `-W` flag. * @param[in] fmt Format specifier string compatible with rb_sprintf(). */ void rb_sys_warning(const char *fmt, ...); -/* reports if $VERBOSE is not nil (so if it is true or false) */ +/* reports always */ RBIMPL_ATTR_COLD() RBIMPL_ATTR_NONNULL((1)) RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 2) /** - * Identical to rb_warning(), except it reports unless $VERBOSE is nil. + * Identical to rb_warning(), except it reports always regardless of runtime + * `-W` flag. * - * @note This function is affected by the value of $VERBOSE, it does - * nothing if $VERBOSE is nil. * @param[in] fmt Format specifier string compatible with rb_sprintf(). */ void rb_warn(const char *fmt, ...); @@ -557,7 +543,8 @@ RBIMPL_ATTR_COLD() RBIMPL_ATTR_NONNULL((2)) RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 3) /** - * Identical to rb_category_warning(), except it reports unless $VERBOSE is nil. + * Identical to rb_category_warning(), except it reports always regardless of + * runtime `-W` flag. * * @param[in] cat Category e.g. deprecated. * @param[in] fmt Format specifier string compatible with rb_sprintf(). @@ -567,7 +554,8 @@ void rb_category_warn(rb_warning_category_t cat, const char *fmt, ...); RBIMPL_ATTR_NONNULL((1, 3)) RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 3, 4) /** - * Identical to rb_compile_warning(), except it reports unless $VERBOSE is nil. + * Identical to rb_compile_warning(), except it reports always regardless of + * runtime `-W` flag. * * @param[in] file The path corresponding to Ruby level `__FILE__`. * @param[in] line The number corresponding to Ruby level `__LINE__`. diff --git a/include/ruby/internal/eval.h b/include/ruby/internal/eval.h index 5bcbb97746..34a53849da 100644 --- a/include/ruby/internal/eval.h +++ b/include/ruby/internal/eval.h @@ -28,12 +28,10 @@ RBIMPL_SYMBOL_EXPORT_BEGIN() RBIMPL_ATTR_NONNULL(()) /** - * Evaluates the given string. + * Evaluates the given string in an isolated binding. * - * In case it is called from within a C-backended method, the evaluation is - * done under the current binding. However there can be no method. On such - * situation this function evaluates in an isolated binding, like `require` - * runs in a separate one. + * Here "isolated" means that the binding does not inherit any other + * bindings. This behaves same as the binding for required libraries. * * `__FILE__` will be `"(eval)"`, and `__LINE__` starts from 1 in the * evaluation. @@ -41,31 +39,6 @@ RBIMPL_ATTR_NONNULL(()) * @param[in] str Ruby code to evaluate. * @exception rb_eException Raises an exception on error. * @return The evaluated result. - * - * @internal - * - * @shyouhei's old tale about the birth and growth of this function: - * - * At the beginning, there was no rb_eval_string(). @shyouhei heard that - * @shugo, author of Apache httpd's mod_ruby module, requested @matz for this - * API. He wanted a way so that mod_ruby can evaluate ruby scripts one by one, - * separately, in each different contexts. So this function was made. It was - * designed to be a global interpreter entry point like ruby_run_node(). - * - * The way it is implemented however allows extension libraries (not just - * programs like Apache httpd) to call this function. Because its name says - * nothing about the initial design, people started to think of it as an - * orthodox way to call ruby level `eval` method from their extension - * libraries. Even our `extension.rdoc` has had a description of this function - * basically according to this understanding. - * - * The old (mod_ruby like) usage still works. But over time, usages of this - * function from extension libraries got popular, while mod_ruby faded out; is - * no longer maintained now. Devs decided to actively support both. This - * function now auto-detects how it is called, and switches how it works - * depending on it. - * - * @see https://bugs.ruby-lang.org/issues/18780 */ VALUE rb_eval_string(const char *str); diff --git a/include/ruby/internal/event.h b/include/ruby/internal/event.h index 1d194ed618..04b137a193 100644 --- a/include/ruby/internal/event.h +++ b/include/ruby/internal/event.h @@ -23,10 +23,6 @@ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" -#ifdef HAVE_STDINT_H -#include <stdint.h> -#endif - /* These macros are not enums because they are wider than int.*/ /** @@ -58,7 +54,6 @@ #define RUBY_EVENT_THREAD_END 0x0800 /**< Encountered an end of a thread. */ #define RUBY_EVENT_FIBER_SWITCH 0x1000 /**< Encountered a `Fiber#yield`. */ #define RUBY_EVENT_SCRIPT_COMPILED 0x2000 /**< Encountered an `eval`. */ -#define RUBY_EVENT_RESCUE 0x4000 /**< Encountered a `rescue` statement. */ #define RUBY_EVENT_TRACEPOINT_ALL 0xffff /**< Bitmask of extended events. */ /** @} */ diff --git a/include/ruby/internal/fl_type.h b/include/ruby/internal/fl_type.h index 44b3e8cc0f..08405d6f30 100644 --- a/include/ruby/internal/fl_type.h +++ b/include/ruby/internal/fl_type.h @@ -57,7 +57,8 @@ #define FL_SINGLETON RBIMPL_CAST((VALUE)RUBY_FL_SINGLETON) /**< @old{RUBY_FL_SINGLETON} */ #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_PROMOTED0 RBIMPL_CAST((VALUE)RUBY_FL_PROMOTED0) /**< @old{RUBY_FL_PROMOTED0} */ +#define FL_PROMOTED1 RBIMPL_CAST((VALUE)RUBY_FL_PROMOTED1) /**< @old{RUBY_FL_PROMOTED1} */ #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} */ @@ -110,6 +111,13 @@ #define RB_OBJ_FREEZE_RAW RB_OBJ_FREEZE_RAW #define RB_OBJ_FROZEN RB_OBJ_FROZEN #define RB_OBJ_FROZEN_RAW RB_OBJ_FROZEN_RAW +#define RB_OBJ_INFECT RB_OBJ_INFECT +#define RB_OBJ_INFECT_RAW RB_OBJ_INFECT_RAW +#define RB_OBJ_TAINT RB_OBJ_TAINT +#define RB_OBJ_TAINTABLE RB_OBJ_TAINTABLE +#define RB_OBJ_TAINTED RB_OBJ_TAINTED +#define RB_OBJ_TAINTED_RAW RB_OBJ_TAINTED_RAW +#define RB_OBJ_TAINT_RAW RB_OBJ_TAINT_RAW #define RB_OBJ_UNTRUST RB_OBJ_TAINT #define RB_OBJ_UNTRUSTED RB_OBJ_TAINTED /** @endcond */ @@ -199,15 +207,12 @@ ruby_fl_type { RUBY_FL_WB_PROTECTED = (1<<5), /** - * Ruby objects are "generational". There are young objects & old objects. - * Young objects are prone to die & monitored relatively extensively by the - * garbage collector. Old objects tend to live longer & are monitored less - * frequently. When an object survives a GC, its age is incremented. When - * age is equal to RVALUE_OLD_AGE, the object becomes Old. This flag is set - * when an object becomes old, and is used by the write barrier to check if - * an old object should be considered for marking more frequently - as old - * objects that have references added between major GCs need to be remarked - * to prevent the referred object being mistakenly swept. + * This flag has something to do with our garbage collector. These days + * ruby objects are "generational". There are those who are young and + * those who are old. Young objects are prone to die; monitored relatively + * extensively by the garbage collector. OTOH old objects tend to live + * longer. They are relatively rarely considered. This flag is set when a + * object experienced promotion i.e. survived a garbage collection. * * @internal * @@ -215,14 +220,41 @@ ruby_fl_type { * 3rd parties. It must be an implementation detail that they should never * know. Might better be hidden. */ - RUBY_FL_PROMOTED = (1<<5), + RUBY_FL_PROMOTED0 = (1<<5), /** - * This flag is no longer in use + * This flag has something to do with our garbage collector. These days + * ruby objects are "generational". There are those who are young and + * those who are old. Young objects are prone to die; monitored relatively + * extensively by the garbage collector. OTOH old objects tend to live + * longer. They are relatively rarely considered. This flag is set when a + * object experienced two promotions i.e. survived garbage collections + * twice. * * @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_UNUSED6 = (1<<6), + RUBY_FL_PROMOTED1 = (1<<6), + + /** + * This flag has something to do with our garbage collector. These days + * ruby objects are "generational". There are those who are young and + * those who are old. Young objects are prone to die; monitored relatively + * extensively by the garbage collector. OTOH old objects tend to live + * longer. They are relatively rarely considered. This flag is set when a + * object experienced promotions i.e. survived more than one garbage + * collections. + * + * @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_PROMOTED = RUBY_FL_PROMOTED0 | RUBY_FL_PROMOTED1, /** * This flag has something to do with finalisers. A ruby object can have @@ -251,7 +283,7 @@ ruby_fl_type { # pragma deprecated(RUBY_FL_TAINT) #endif - = 0, + = (1<<8), /** * This flag has something to do with Ractor. Multiple Ractors run without @@ -278,7 +310,7 @@ ruby_fl_type { # pragma deprecated(RUBY_FL_UNTRUSTED) #endif - = 0, + = (1<<8), /** * This flag has something to do with object IDs. Unlike in the old days, @@ -419,6 +451,12 @@ enum { RBIMPL_SYMBOL_EXPORT_BEGIN() /** + * @deprecated Does nothing. This method is deprecated and will be removed in + * Ruby 3.2. + */ +void rb_obj_infect(VALUE victim, VALUE carrier); + +/** * This is an implementation detail of #RB_OBJ_FREEZE(). People don't use it * directly. * @@ -457,7 +495,7 @@ RB_FL_ABLE(VALUE obj) RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() /** - * This is an implementation detail of RB_FL_TEST(). 3rd parties need not use + * This is an implenentation detail of RB_FL_TEST(). 3rd parties need not use * this. Just always use RB_FL_TEST(). * * @param[in] obj Object in question. @@ -505,7 +543,7 @@ RB_FL_TEST(VALUE obj, VALUE flags) RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() /** - * This is an implementation detail of RB_FL_ANY(). 3rd parties need not use + * This is an implenentation detail of RB_FL_ANY(). 3rd parties need not use * this. Just always use RB_FL_ANY(). * * @param[in] obj Object in question. @@ -539,7 +577,7 @@ RB_FL_ANY(VALUE obj, VALUE flags) RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() /** - * This is an implementation detail of RB_FL_ALL(). 3rd parties need not use + * This is an implenentation detail of RB_FL_ALL(). 3rd parties need not use * this. Just always use RB_FL_ALL(). * * @param[in] obj Object in question. @@ -575,7 +613,7 @@ RBIMPL_ATTR_ARTIFICIAL() /** * @private * - * This is an implementation detail of RB_FL_SET(). 3rd parties need not use + * This is an implenentation detail of RB_FL_SET(). 3rd parties need not use * this. Just always use RB_FL_SET(). * * @param[out] obj Object in question. @@ -595,7 +633,7 @@ rbimpl_fl_set_raw_raw(struct RBasic *obj, VALUE flags) RBIMPL_ATTR_ARTIFICIAL() /** - * This is an implementation detail of RB_FL_SET(). 3rd parties need not use + * This is an implenentation detail of RB_FL_SET(). 3rd parties need not use * this. Just always use RB_FL_SET(). * * @param[out] obj Object in question. @@ -635,7 +673,7 @@ RBIMPL_ATTR_ARTIFICIAL() /** * @private * - * This is an implementation detail of RB_FL_UNSET(). 3rd parties need not use + * This is an implenentation detail of RB_FL_UNSET(). 3rd parties need not use * this. Just always use RB_FL_UNSET(). * * @param[out] obj Object in question. @@ -655,7 +693,7 @@ rbimpl_fl_unset_raw_raw(struct RBasic *obj, VALUE flags) RBIMPL_ATTR_ARTIFICIAL() /** - * This is an implementation detail of RB_FL_UNSET(). 3rd parties need not use + * This is an implenentation detail of RB_FL_UNSET(). 3rd parties need not use * this. Just always use RB_FL_UNSET(). * * @param[out] obj Object in question. @@ -690,7 +728,7 @@ RBIMPL_ATTR_ARTIFICIAL() /** * @private * - * This is an implementation detail of RB_FL_REVERSE(). 3rd parties need not + * This is an implenentation detail of RB_FL_REVERSE(). 3rd parties need not * use this. Just always use RB_FL_REVERSE(). * * @param[out] obj Object in question. @@ -710,7 +748,7 @@ rbimpl_fl_reverse_raw_raw(struct RBasic *obj, VALUE flags) RBIMPL_ATTR_ARTIFICIAL() /** - * This is an implementation detail of RB_FL_REVERSE(). 3rd parties need not + * This is an implenentation detail of RB_FL_REVERSE(). 3rd parties need not * use this. Just always use RB_FL_REVERSE(). * * @param[out] obj Object in question. @@ -755,7 +793,6 @@ RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) static inline bool RB_OBJ_TAINTABLE(VALUE obj) { - (void)obj; return false; } @@ -773,7 +810,6 @@ RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) static inline VALUE RB_OBJ_TAINTED_RAW(VALUE obj) { - (void)obj; return false; } @@ -791,7 +827,6 @@ RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) static inline bool RB_OBJ_TAINTED(VALUE obj) { - (void)obj; return false; } @@ -807,7 +842,6 @@ RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) static inline void RB_OBJ_TAINT_RAW(VALUE obj) { - (void)obj; return; } @@ -823,7 +857,6 @@ RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) static inline void RB_OBJ_TAINT(VALUE obj) { - (void)obj; return; } @@ -840,8 +873,6 @@ RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) static inline void RB_OBJ_INFECT_RAW(VALUE dst, VALUE src) { - (void)dst; - (void)src; return; } @@ -858,15 +889,13 @@ RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) 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 + * This is an implenentation detail of RB_OBJ_FROZEN(). 3rd parties need not * use this. Just always use RB_OBJ_FROZEN(). * * @param[in] obj Object in question. @@ -907,7 +936,7 @@ RB_OBJ_FROZEN(VALUE obj) RBIMPL_ATTR_ARTIFICIAL() /** - * This is an implementation detail of RB_OBJ_FREEZE(). 3rd parties need not + * This is an implenentation detail of RB_OBJ_FREEZE(). 3rd parties need not * use this. Just always use RB_OBJ_FREEZE(). * * @param[out] obj Object in question. @@ -918,8 +947,21 @@ RB_OBJ_FREEZE_RAW(VALUE obj) RB_FL_SET_RAW(obj, RUBY_FL_FREEZE); } -RUBY_SYMBOL_EXPORT_BEGIN -void rb_obj_freeze_inline(VALUE obj); -RUBY_SYMBOL_EXPORT_END +/** + * Prevents further modifications to the given object. ::rb_eFrozenError shall + * be raised if modification is attempted. + * + * @param[out] x Object in question. + */ +static inline void +rb_obj_freeze_inline(VALUE x) +{ + if (RB_FL_ABLE(x)) { + RB_OBJ_FREEZE_RAW(x); + if (RBASIC_CLASS(x) && !(RBASIC(x)->flags & RUBY_FL_SINGLETON)) { + rb_freeze_singleton_class(x); + } + } +} #endif /* RBIMPL_FL_TYPE_H */ diff --git a/include/ruby/internal/gc.h b/include/ruby/internal/gc.h index ac9dfd8842..66fc14e511 100644 --- a/include/ruby/internal/gc.h +++ b/include/ruby/internal/gc.h @@ -20,395 +20,16 @@ * extension libraries. They could be written in C++98. * @brief Registering values to the GC. */ -#include "ruby/internal/config.h" - -#ifdef STDC_HEADERS -# include <stddef.h> /* size_t */ -#endif - -#ifdef HAVE_SYS_TYPES_H -# include <sys/types.h> /* ssize_t */ -#endif - -#include "ruby/assert.h" -#include "ruby/internal/attr/cold.h" -#include "ruby/internal/attr/nonnull.h" -#include "ruby/internal/attr/noreturn.h" -#include "ruby/internal/attr/artificial.h" -#include "ruby/internal/attr/maybe_unused.h" -#include "ruby/internal/attr/pure.h" #include "ruby/internal/dllexport.h" -#include "ruby/internal/special_consts.h" -#include "ruby/internal/stdbool.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() -#define RUBY_REF_EDGE(s, p) offsetof(s, p) -#define RUBY_REFS_LIST_PTR(l) (RUBY_DATA_FUNC)(l) -#define RUBY_REF_END SIZE_MAX -#define RUBY_REFERENCES(t) static const size_t t[] -#define RUBY_REFERENCES_START(t) RUBY_REFERENCES(t) = { -#define RUBY_REFERENCES_END RUBY_REF_END, }; - -/* gc.c */ - -RBIMPL_ATTR_COLD() -RBIMPL_ATTR_NORETURN() -/** - * Triggers out-of-memory error. If possible it raises ::rb_eNoMemError. But - * because we are running out of memory that is not always doable. This - * function tries hard to show something, but ultimately can die silently. - * - * @exception rb_eNoMemError Raises it if possible. - */ -void rb_memerror(void); - -RBIMPL_ATTR_PURE() -/** - * Queries if the GC is busy. - * - * @retval 0 It isn't. - * @retval 1 It is. - */ -int rb_during_gc(void); - -RBIMPL_ATTR_NONNULL((1)) -/** - * Marks objects between the two pointers. This is one of the GC utility - * functions that you can call when you design your own - * ::rb_data_type_struct::dmark. - * - * @pre Continuous memory region from `start` to `end` shall be fully - * addressable. - * @param[out] start Pointer to an array of objects. - * @param[out] end Pointer that terminates the array of objects. - * @post Objects from `start` (included) to `end` (excluded) are marked. - * - * @internal - * - * `end` can be NULL... But that just results in no-op. - */ -void rb_gc_mark_locations(const VALUE *start, const VALUE *end); - -/** - * Identical to rb_mark_hash(), except it marks only values of the table and - * leave their associated keys unmarked. This is one of the GC utility - * functions that you can call when you design your own - * ::rb_data_type_struct::dmark. - * - * @warning Of course it can break GC. Leave it unused if unsure. - * @param[in] tbl A table to mark. - * @post Values stored in `tbl` are marked. - */ -void rb_mark_tbl(struct st_table *tbl); - -/** - * Identical to rb_mark_tbl(), except it marks objects using - * rb_gc_mark_movable(). This is one of the GC utility functions that you can - * call when you design your own ::rb_data_type_struct::dmark. - * - * @warning Of course it can break GC. Leave it unused if unsure. - * @param[in] tbl A table to mark. - * @post Values stored in `tbl` are marked. - */ -void rb_mark_tbl_no_pin(struct st_table *tbl); - -/** - * Identical to rb_mark_hash(), except it marks only keys of the table and - * leave their associated values unmarked. This is one of the GC utility - * functions that you can call when you design your own - * ::rb_data_type_struct::dmark. - * - * @warning Of course it can break GC. Leave it unused if unsure. - * @param[in] tbl A table to mark. - * @post Keys stored in `tbl` are marked. - */ -void rb_mark_set(struct st_table *tbl); - /** - * Marks keys and values associated inside of the given table. This is one of - * the GC utility functions that you can call when you design your own - * ::rb_data_type_struct::dmark. - * - * @param[in] tbl A table to mark. - * @post Objects stored in `tbl` are marked. - */ -void rb_mark_hash(struct st_table *tbl); - -/** - * Updates references inside of tables. After you marked values using - * rb_mark_tbl_no_pin(), the objects inside of the table could of course be - * moved. This function is to fixup those references. You can call this from - * your ::rb_data_type_struct::dcompact. - * - * @param[out] ptr A table that potentially includes moved references. - * @post Moved references, if any, are corrected. - */ -void rb_gc_update_tbl_refs(st_table *ptr); - -/** - * Identical to rb_gc_mark(), except it allows the passed value be a - * non-object. For instance pointers to different type of memory regions are - * allowed here. Such values are silently ignored. This is one of the GC - * utility functions that you can call when you design your own - * ::rb_data_type_struct::dmark. - * - * @param[out] obj A possible object. - * @post `obj` is marked, if possible. - */ -void rb_gc_mark_maybe(VALUE obj); - -/** - * Marks an object. This is one of the GC utility functions that you can call - * when you design your own ::rb_data_type_struct::dmark. - * - * @param[out] obj Arbitrary Ruby object. - * @post `obj` is marked. - */ -void rb_gc_mark(VALUE obj); - -/** - * Maybe this is the only function provided for C extensions to control the - * pinning of objects, so let us describe it in detail. These days Ruby's GC - * is copying. As far as an object's physical address is guaranteed unused, it - * can move around the object space. Our GC engine rearranges these objects - * after it reclaims unreachable objects from our object space, so that the - * space is compact (improves memory locality). This is called the - * "compaction" phase, and works well most of the time... as far as there are - * no C extensions. C extensions complicate the scenario because Ruby core - * cannot detect any use of the physical address of an object inside of C - * functions. In order to prevent memory corruptions, objects observable from - * C extensions are "pinned"; they stick to where they are born until they die, - * just in case any C extensions touch their raw pointers. This variant of - * scheme is called "Mostly-Copying" garbage collector. Authors of C - * extensions, however, can extremely carefully write them to become - * compaction-aware. To do so avoid referring to a Ruby object from inside of - * your struct in the first place. But if that is not possible, use this - * function from your ::rb_data_type_struct::dmark then. This way objects - * marked using it are considered movable. If you chose this way you have to - * manually fix up locations of such moved pointers using rb_gc_location(). - * - * @see Bartlett, Joel F., "Compacting Garbage Collection with Ambiguous - * Roots", ACM SIGPLAN Lisp Pointers Volume 1 Issue 6 pp. 3-12, - * April-May-June, 1988. https://doi.org/10.1145/1317224.1317225 - * - * @param[in] obj Object that is movable. - * @post Values stored in `tbl` are marked. - */ -void rb_gc_mark_movable(VALUE obj); - -/** - * Finds a new "location" of an object. An object can be moved on compaction. - * This function projects its new abode, or just returns the passed object if - * not moved. This is one of the GC utility functions that you can call when - * you design your own ::rb_data_type_struct::dcompact. - * - * @param[in] obj An object, possibly already moved to somewhere else. - * @return An object, which holds the current contents of former `obj`. - */ -VALUE rb_gc_location(VALUE obj); - -/** - * Asserts that the passed object is no longer needed. Such objects are - * reclaimed sooner or later so this function is not mandatory. But sometimes - * you can know from your application knowledge that an object is surely dead - * at some point. Calling this as a hint can be a polite way. - * - * @param[out] obj Object, dead. - * @pre `obj` have never been passed to this function before. - * @post `obj` could be invalidated. - * @warning It is a failure to pass an object multiple times to this - * function. - * @deprecated This is now a no-op function. - */ -RBIMPL_ATTR_DEPRECATED(("this is now a no-op function")) -void rb_gc_force_recycle(VALUE obj); - -/** - * Triggers a GC process. This was the only GC entry point that we had at the - * beginning. Over time our GC evolved. Now what this function does is just a - * very simplified variation of the entire GC algorithms. A series of - * procedures kicked by this API is called a "full" GC. - * - * - It immediately scans the entire object space to sort the dead. - * - It immediately reclaims any single dead bodies to reuse later. - * - * It is worth noting that the procedures above do not include evaluations of - * finalisers. They run later. - * - * @internal - * - * Finalisers are deferred until we can handle interrupts. See - * `rb_postponed_job_flush` in vm_trace.c. - * - * Of course there are GC that are not "full". For instance this one and the - * GC which runs when we are running out of memory are different. See - * `gc_profile_record_flag` defined in gc.c for the kinds of GC. - * - * In spite of the name this is not what everything that a GC can trigger. As - * of writing it seems this function does not trigger compaction. But this - * might change in future. - */ -void rb_gc(void); - -/** - * Copy&paste an object's finaliser to another. This is one of the GC utility - * functions that you can call when you design your own `initialize_copy`, - * `initialize_dup`, `initialize_clone`. - * - * @param[out] dst Destination object. - * @param[in] src Source object. - * @post `dst` and `src` share the same finaliser. - * - * @internal - * - * But isn't it easier for you to call super, and let `Object#initialize_copy` - * call this function instead? - */ -void rb_gc_copy_finalizer(VALUE dst, VALUE src); - -/** - * (Re-) enables GC. This makes sense only after you called rb_gc_disable(). - * - * @retval RUBY_Qtrue GC was disabled before. - * @retval RUBY_Qfalse GC was enabled before. - * @post GC is enabled. - * - * @internal - * - * This is one of such exceptional functions that does not raise both Ruby - * exceptions and C++ exceptions. - */ -VALUE rb_gc_enable(void); - -/** - * Disables GC. This prevents automatic GC runs when the process is running - * out of memory. Such situations shall result in rb_memerror(). However this - * does not prevent users from manually invoking rb_gc(). That should work. - * People abused this by disabling GC at the beginning of an event loop, - * process events without GC overheads, then manually force reclaiming garbage - * at the bottom of the loop. However because our GC is now much smarter than - * just calling rb_gc(), this technique is proven to be sub-optimal these days. - * It is believed that there is currently practically no needs of this - * function. - * - * @retval RUBY_Qtrue GC was disabled before. - * @retval RUBY_Qfalse GC was enabled before. - * @post GC is disabled. - */ -VALUE rb_gc_disable(void); - -/** - * Identical to rb_gc(), except the return value. - * - * @return Always returns ::RUBY_Qnil. - */ -VALUE rb_gc_start(void); - -/** - * Assigns a finaliser for an object. Each objects can have objects (typically - * blocks) that run immediately after that object dies. They are called - * finalisers of an object. This function associates a finaliser object with a - * target object. - * - * @note Note that finalisers run _after_ the object they finalise dies. You - * cannot for instance call its methods. - * @note If your finaliser references the object it finalises that object - * loses any chance to become a garbage; effectively leaks memory until - * the end of the process. - * - * @param[in] obj Target to finalise. - * @param[in] block Something `call`able. - * @exception rb_eRuntimeError Somehow `obj` cannot have finalisers. - * @exception rb_eFrozenError `obj` is frozen. - * @exception rb_eArgError `block` doesn't respond to `call`. - * @return The passed `block`. - * @post `block` runs after `obj` dies. - */ -VALUE rb_define_finalizer(VALUE obj, VALUE block); - -/** - * Modifies the object so that it has no finalisers at all. This function is - * mainly provided for symmetry. No practical usages can be thought of. - * - * @param[out] obj Object to clear its finalisers. - * @exception rb_eFrozenError `obj` is frozen. - * @return The passed `obj`. - * @post `obj` has no finalisers. - * @note There is no way to undefine a specific part of many finalisers - * that `obj` could have. All you can do is to clear them all. - */ -VALUE rb_undefine_finalizer(VALUE obj); - -/** - * Identical to rb_gc_stat(), with "count" parameter. - * - * @return Lifetime total number of runs of GC. - */ -size_t rb_gc_count(void); - -/** - * Obtains various GC related profiles. The parameter can be either a Symbol - * or a Hash. If a Hash is passed, it is filled with everything currently - * available. If a Symbol is passed just that portion is returned. - * - * Possible variations of keys you can pass here change from version to - * version. You can get the list of known keys by passing an empty hash and - * let it be filled. - * - * @param[in,out] key_or_buf A Symbol, or a Hash. - * @exception rb_eTypeError Neither Symbol nor Hash. - * @exception rb_eFrozenError Frozen hash is passed. - * @return In case a Hash is passed it returns 0. Otherwise the - * profile value associated with the given key is returned. - * @post In case a Hash is passed it is filled with values. - */ -size_t rb_gc_stat(VALUE key_or_buf); - -/** - * Obtains various info regarding the most recent GC run. This includes for - * instance the reason of the GC. The parameter can be either a Symbol or a - * Hash. If a Hash is passed, it is filled with everything currently - * available. If a Symbol is passed just that portion is returned. - * - * Possible variations of keys you can pass here change from version to - * version. You can get the list of known keys by passing an empty hash and - * let it be filled. - * - * @param[in,out] key_or_buf A Symbol, or a Hash. - * @exception rb_eTypeError Neither Symbol nor Hash. - * @exception rb_eFrozenError Frozen hash is passed. - * @return In case a Hash is passed it returns that hash. Otherwise - * the profile value associated with the given key is returned. - * @post In case a Hash is passed it is filled with values. - */ -VALUE rb_gc_latest_gc_info(VALUE key_or_buf); - -/** - * Informs that there are external memory usages. Our GC runs when we are - * running out of memory. The amount of memory, however, can increase/decrease - * behind-the-scene. For instance DLLs can allocate memories using `mmap(2)` - * etc, which are opaque to us. Registering such external allocations using - * this function enables proper detection of how much memories an object used - * as a whole. That will trigger GCs more often than it would otherwise. You - * can also pass negative numbers here, to indicate that such external - * allocations are gone. - * - * @param[in] diff Amount of memory increased(+)/decreased(-). - */ -void rb_gc_adjust_memory_usage(ssize_t diff); - -/** - * Inform the garbage collector that the global or static variable pointed by - * `valptr` stores a live Ruby object that should not be moved. Note that - * extensions should use this API on global constants instead of assuming - * constants defined in Ruby are always alive. Ruby code can remove global - * constants. - * - * Because this registration itself has a possibility to trigger a GC, this - * function must be called before any GC-able objects is assigned to the - * address pointed by `valptr`. + * Inform the garbage collector that `valptr` points to a live Ruby object that + * should not be moved. Note that extensions should use this API on global + * constants instead of assuming constants defined in Ruby are always alive. + * Ruby code can remove global constants. */ void rb_gc_register_address(VALUE *valptr); @@ -433,410 +54,4 @@ void rb_gc_register_mark_object(VALUE object); RBIMPL_SYMBOL_EXPORT_END() -/** - * @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. - */ -#undef USE_RGENGC -#define USE_RGENGC 1 - -/** - * @deprecated This macro seems broken. Setting this to anything other than - * zero just doesn't compile. We need to KonMari. - */ -#ifndef USE_RGENGC_LOGGING_WB_UNPROTECT -# define USE_RGENGC_LOGGING_WB_UNPROTECT 0 -#endif - -/** - * @private - * - * This is a compile-time flag to enable/disable write barrier for - * struct ::RArray. It has to be set at the time ruby itself compiles. Makes - * no sense for 3rd parties. - */ -#ifndef RGENGC_WB_PROTECTED_ARRAY -# define RGENGC_WB_PROTECTED_ARRAY 1 -#endif - -/** - * @private - * - * This is a compile-time flag to enable/disable write barrier for - * struct ::RHash. It has to be set at the time ruby itself compiles. Makes - * no sense for 3rd parties. - */ -#ifndef RGENGC_WB_PROTECTED_HASH -# define RGENGC_WB_PROTECTED_HASH 1 -#endif - -/** - * @private - * - * This is a compile-time flag to enable/disable write barrier for - * struct ::RStruct. It has to be set at the time ruby itself compiles. Makes - * no sense for 3rd parties. - */ -#ifndef RGENGC_WB_PROTECTED_STRUCT -# define RGENGC_WB_PROTECTED_STRUCT 1 -#endif - -/** - * @private - * - * This is a compile-time flag to enable/disable write barrier for - * struct ::RString. It has to be set at the time ruby itself compiles. Makes - * no sense for 3rd parties. - */ -#ifndef RGENGC_WB_PROTECTED_STRING -# define RGENGC_WB_PROTECTED_STRING 1 -#endif - -/** - * @private - * - * This is a compile-time flag to enable/disable write barrier for - * struct ::RObject. It has to be set at the time ruby itself compiles. Makes - * no sense for 3rd parties. - */ -#ifndef RGENGC_WB_PROTECTED_OBJECT -# define RGENGC_WB_PROTECTED_OBJECT 1 -#endif - -/** - * @private - * - * This is a compile-time flag to enable/disable write barrier for - * struct ::RRegexp. It has to be set at the time ruby itself compiles. Makes - * no sense for 3rd parties. - */ -#ifndef RGENGC_WB_PROTECTED_REGEXP -# define RGENGC_WB_PROTECTED_REGEXP 1 -#endif - -/** - * @private - * - * This is a compile-time flag to enable/disable write barrier for - * struct ::RMatch. It has to be set at the time ruby itself compiles. Makes - * no sense for 3rd parties. - */ -#ifndef RGENGC_WB_PROTECTED_MATCH -# define RGENGC_WB_PROTECTED_MATCH 1 -#endif - -/** - * @private - * - * This is a compile-time flag to enable/disable write barrier for - * struct ::RClass. It has to be set at the time ruby itself compiles. Makes - * no sense for 3rd parties. - */ -#ifndef RGENGC_WB_PROTECTED_CLASS -# define RGENGC_WB_PROTECTED_CLASS 1 -#endif - -/** - * @private - * - * This is a compile-time flag to enable/disable write barrier for - * struct ::RFloat. It has to be set at the time ruby itself compiles. Makes - * no sense for 3rd parties. - */ -#ifndef RGENGC_WB_PROTECTED_FLOAT -# define RGENGC_WB_PROTECTED_FLOAT 1 -#endif - -/** - * @private - * - * This is a compile-time flag to enable/disable write barrier for - * struct ::RComplex. It has to be set at the time ruby itself compiles. - * Makes no sense for 3rd parties. - */ -#ifndef RGENGC_WB_PROTECTED_COMPLEX -# define RGENGC_WB_PROTECTED_COMPLEX 1 -#endif - -/** - * @private - * - * This is a compile-time flag to enable/disable write barrier for - * struct ::RRational. It has to be set at the time ruby itself compiles. - * Makes no sense for 3rd parties. - */ -#ifndef RGENGC_WB_PROTECTED_RATIONAL -# define RGENGC_WB_PROTECTED_RATIONAL 1 -#endif - -/** - * @private - * - * This is a compile-time flag to enable/disable write barrier for - * struct ::RBignum. It has to be set at the time ruby itself compiles. Makes - * no sense for 3rd parties. - */ -#ifndef RGENGC_WB_PROTECTED_BIGNUM -# define RGENGC_WB_PROTECTED_BIGNUM 1 -#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 - * - * @shyouhei doesn't think anybody uses this right now. - */ -#ifndef RGENGC_WB_PROTECTED_NODE_CREF -# define RGENGC_WB_PROTECTED_NODE_CREF 1 -#endif - -/** - * @defgroup rgengc Write barrier (WB) interfaces: - * - * @note The following core interfaces can be changed in the future. Please - * catch up if you want to insert WB into C-extensions correctly. - * - * @{ - */ - -/** - * Declaration of a "back" pointer. This is a write barrier for new reference - * from "old" generation to "young" generation. It writes `young` into - * `*slot`, which is a pointer inside of `old`. - * - * @param[in] old An old object. - * @param[in] slot A pointer inside of `old`. - * @param[out] young A young object. - */ -#define RB_OBJ_WRITE(old, slot, young) \ - RBIMPL_CAST(rb_obj_write((VALUE)(old), (VALUE *)(slot), (VALUE)(young), __FILE__, __LINE__)) - -/** - * Identical to #RB_OBJ_WRITE(), except it doesn't write any values, but only a - * WB declaration. `oldv` is replaced value with `b` (not used in current - * Ruby). - * - * @param[in] old An old object. - * @param[in] oldv An object previously stored inside of `old`. - * @param[out] young A young object. - */ -#define RB_OBJ_WRITTEN(old, oldv, young) \ - RBIMPL_CAST(rb_obj_written((VALUE)(old), (VALUE)(oldv), (VALUE)(young), __FILE__, __LINE__)) -/** @} */ - -#define OBJ_PROMOTED_RAW RB_OBJ_PROMOTED_RAW /**< @old{RB_OBJ_PROMOTED_RAW} */ -#define OBJ_PROMOTED RB_OBJ_PROMOTED /**< @old{RB_OBJ_PROMOTED} */ -#define OBJ_WB_UNPROTECT RB_OBJ_WB_UNPROTECT /**< @old{RB_OBJ_WB_UNPROTECT} */ - -/** - * Asserts that the passed object is not fenced by write barriers. Objects of - * such property do not contribute to generational GCs. They are scanned - * always. - * - * @param[out] x An object that would not be protected by the barrier. - */ -#define RB_OBJ_WB_UNPROTECT(x) rb_obj_wb_unprotect(x, __FILE__, __LINE__) - -/** - * Identical to #RB_OBJ_WB_UNPROTECT(), except it can also assert that the - * given object is of given type. - * - * @param[in] type One of `ARRAY`, `STRING`, etc. - * @param[out] obj An object of `type` that would not be protected. - * - * @internal - * - * @shyouhei doesn't understand why this has to be visible from extensions. - */ -#define RB_OBJ_WB_UNPROTECT_FOR(type, obj) \ - (RGENGC_WB_PROTECTED_##type ? OBJ_WB_UNPROTECT(obj) : obj) - -/** - * @private - * - * This is an implementation detail of rb_obj_wb_unprotect(). People don't use - * it directly. - */ -#define RGENGC_LOGGING_WB_UNPROTECT rb_gc_unprotect_logging - -/** @cond INTERNAL_MACRO */ -#define RB_OBJ_PROMOTED_RAW RB_OBJ_PROMOTED_RAW -#define RB_OBJ_PROMOTED RB_OBJ_PROMOTED -/** @endcond */ - -RBIMPL_SYMBOL_EXPORT_BEGIN() -/** - * This is the implementation of #RB_OBJ_WRITE(). People don't use it - * directly. - * - * @param[in] old An object that points to `young`. - * @param[out] young An object that is referenced from `old`. - */ -void rb_gc_writebarrier(VALUE old, VALUE young); - -/** - * This is the implementation of #RB_OBJ_WB_UNPROTECT(). People don't use it - * directly. - * - * @param[out] obj An object that does not participate in WB. - */ -void rb_gc_writebarrier_unprotect(VALUE obj); - -#if USE_RGENGC_LOGGING_WB_UNPROTECT -/** - * @private - * - * This is the implementation of #RGENGC_LOGGING_WB_UNPROTECT(). People - * don't use it directly. - * - * @param[in] objptr Don't know why this is a pointer to void but in - * reality this is a pointer to an object that is about - * to be un-protected. - * @param[in] filename Pass C's `__FILE__` here. - * @param[in] line Pass C's `__LINE__` here. - */ -void rb_gc_unprotect_logging(void *objptr, const char *filename, int line); -#endif - -RBIMPL_SYMBOL_EXPORT_END() - -RBIMPL_ATTR_PURE_UNLESS_DEBUG() -RBIMPL_ATTR_ARTIFICIAL() -/** - * This is the implementation of #RB_OBJ_PROMOTED(). People don't use it - * directly. - * - * @param[in] obj An object to query. - * @retval true The object is "promoted". - * @retval false The object is young. Have not experienced GC at all. - */ -static inline bool -RB_OBJ_PROMOTED_RAW(VALUE obj) -{ - RBIMPL_ASSERT_OR_ASSUME(RB_FL_ABLE(obj)); - return RB_FL_ANY_RAW(obj, RUBY_FL_PROMOTED); -} - -RBIMPL_ATTR_PURE_UNLESS_DEBUG() -RBIMPL_ATTR_ARTIFICIAL() -/** - * Tests if the object is "promoted" -- that is, whether the object experienced - * one or more GC marks. - * - * @param[in] obj An object to query. - * @retval true The object is "promoted". - * @retval false The object is young. Have not experienced GC at all. - * @note Hello, is anyone actively calling this function? @shyouhei have - * never seen any actual usages outside of the GC implementation - * itself. - */ -static inline bool -RB_OBJ_PROMOTED(VALUE obj) -{ - if (! RB_FL_ABLE(obj)) { - return false; - } - else { - return RB_OBJ_PROMOTED_RAW(obj); - } -} - -/** - * This is the implementation of #RB_OBJ_WB_UNPROTECT(). People don't use it - * directly. - * - * @param[out] x An object that does not participate in WB. - * @param[in] filename C's `__FILE__` of the caller function. - * @param[in] line C's `__LINE__` of the caller function. - * @return x - */ -static inline VALUE -rb_obj_wb_unprotect( - VALUE x, - RBIMPL_ATTR_MAYBE_UNUSED() - const char *filename, - RBIMPL_ATTR_MAYBE_UNUSED() - int line) -{ -#if USE_RGENGC_LOGGING_WB_UNPROTECT - RGENGC_LOGGING_WB_UNPROTECT(RBIMPL_CAST((void *)x), filename, line); -#endif - rb_gc_writebarrier_unprotect(x); - return x; -} - -/** - * @private - * - * This is the implementation of #RB_OBJ_WRITTEN(). People don't use it - * directly. - * - * @param[in] a An old object. - * @param[in] oldv An object previously stored inside of `old`. - * @param[out] b A young object. - * @param[in] filename C's `__FILE__` of the caller function. - * @param[in] line C's `__LINE__` of the caller function. - * @return a - */ -static inline VALUE -rb_obj_written( - VALUE a, - RBIMPL_ATTR_MAYBE_UNUSED() - VALUE oldv, - VALUE b, - RBIMPL_ATTR_MAYBE_UNUSED() - const char *filename, - RBIMPL_ATTR_MAYBE_UNUSED() - int line) -{ -#if USE_RGENGC_LOGGING_WB_UNPROTECT - RGENGC_LOGGING_OBJ_WRITTEN(a, oldv, b, filename, line); -#endif - - if (!RB_SPECIAL_CONST_P(b)) { - rb_gc_writebarrier(a, b); - } - - return a; -} - -/** - * @private - * - * This is the implementation of #RB_OBJ_WRITE(). People don't use it - * directly. - * - * @param[in] a An old object. - * @param[in] slot A pointer inside of `old`. - * @param[out] b A young object. - * @param[in] filename C's `__FILE__` of the caller function. - * @param[in] line C's `__LINE__` of the caller function. - * @return a - */ -static inline VALUE -rb_obj_write( - VALUE a, VALUE *slot, VALUE b, - RBIMPL_ATTR_MAYBE_UNUSED() - const char *filename, - RBIMPL_ATTR_MAYBE_UNUSED() - int line) -{ -#ifdef RGENGC_LOGGING_WRITE - RGENGC_LOGGING_WRITE(a, slot, b, filename, line); -#endif - - *slot = b; - - rb_obj_written(a, RUBY_Qundef /* ignore `oldv' now */, b, filename, line); - return a; -} - #endif /* RBIMPL_GC_H */ diff --git a/include/ruby/internal/globals.h b/include/ruby/internal/globals.h index 60d8e5309a..5a414fc472 100644 --- a/include/ruby/internal/globals.h +++ b/include/ruby/internal/globals.h @@ -94,7 +94,7 @@ RUBY_EXTERN VALUE rb_cRegexp; /**< `Regexp` class. */ RUBY_EXTERN VALUE rb_cStat; /**< `File::Stat` class. */ RUBY_EXTERN VALUE rb_cString; /**< `String` class. */ RUBY_EXTERN VALUE rb_cStruct; /**< `Struct` class. */ -RUBY_EXTERN VALUE rb_cSymbol; /**< `Symbol` class. */ +RUBY_EXTERN VALUE rb_cSymbol; /**< `Sumbol` class. */ RUBY_EXTERN VALUE rb_cThread; /**< `Thread` class. */ RUBY_EXTERN VALUE rb_cTime; /**< `Time` class. */ RUBY_EXTERN VALUE rb_cTrueClass; /**< `TrueClass` class. */ diff --git a/include/ruby/internal/has/builtin.h b/include/ruby/internal/has/builtin.h index 243ba2a34c..957aff8375 100644 --- a/include/ruby/internal/has/builtin.h +++ b/include/ruby/internal/has/builtin.h @@ -53,10 +53,8 @@ # define RBIMPL_HAS_BUILTIN___builtin_assume 0 # /* See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52624 for bswap16. */ # define RBIMPL_HAS_BUILTIN___builtin_bswap16 RBIMPL_COMPILER_SINCE(GCC, 4, 8, 0) -#ifndef __OpenBSD__ # define RBIMPL_HAS_BUILTIN___builtin_bswap32 RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0) # define RBIMPL_HAS_BUILTIN___builtin_bswap64 RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0) -#endif # define RBIMPL_HAS_BUILTIN___builtin_clz RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0) # define RBIMPL_HAS_BUILTIN___builtin_clzl RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0) # define RBIMPL_HAS_BUILTIN___builtin_clzll RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0) @@ -78,6 +76,10 @@ # define RBIMPL_HAS_BUILTIN___builtin_unreachable RBIMPL_COMPILER_SINCE(GCC, 4, 5, 0) # /* Note that "0, 0, 0" might be inaccurate. */ +#elif RBIMPL_COMPILER_IS(MSVC) +# /* MSVC has UNREACHABLE, but that is not __builtin_unreachable. */ +# define RBIMPL_HAS_BUILTIN(_) 0 + #else # /* Take config.h definition when available */ # define RBIMPL_HAS_BUILTIN(_) ((RBIMPL_HAS_BUILTIN_ ## _)+0) @@ -107,7 +109,7 @@ # define RBIMPL_HAS_BUILTIN___builtin_rotateright64 0 # define RBIMPL_HAS_BUILTIN___builtin_popcountll HAVE_BUILTIN___BUILTIN_POPCOUNTLL # define RBIMPL_HAS_BUILTIN___builtin_sub_overflow HAVE_BUILTIN___BUILTIN_SUB_OVERFLOW -# if defined(HAVE___BUILTIN_UNREACHABLE) +# if defined(UNREACHABLE) # define RBIMPL_HAS_BUILTIN___builtin_unreachable 1 # else # define RBIMPL_HAS_BUILTIN___builtin_unreachable 0 diff --git a/include/ruby/internal/has/c_attribute.h b/include/ruby/internal/has/c_attribute.h index 69b0f402cd..c5c48867bf 100644 --- a/include/ruby/internal/has/c_attribute.h +++ b/include/ruby/internal/has/c_attribute.h @@ -21,23 +21,11 @@ * @brief Defines #RBIMPL_HAS_C_ATTRIBUTE. */ -#include "ruby/internal/has/extension.h" -#include "ruby/internal/has/warning.h" - /** Wraps (or simulates) `__has_c_attribute`. */ #if defined(__cplusplus) # /* Makes no sense. */ # define RBIMPL_HAS_C_ATTRIBUTE(_) 0 -#elif RBIMPL_HAS_EXTENSION(c_attributes) -# /* Hmm. It seems Clang 17 has this macro defined even when -std=c99 mode, -# * _and_ fails to compile complaining that attributes are C2X feature. We -# * need to work around this nonsense. */ -# define RBIMPL_HAS_C_ATTRIBUTE(_) __has_c_attribute(_) - -#elif RBIMPL_HAS_WARNING("-Wc2x-extensions") -# define RBIMPL_HAS_C_ATTRIBUTE(_) 0 - #elif defined(__has_c_attribute) # define RBIMPL_HAS_C_ATTRIBUTE(_) __has_c_attribute(_) diff --git a/include/ruby/internal/intern/array.h b/include/ruby/internal/intern/array.h index 1909fdf17b..17964bf810 100644 --- a/include/ruby/internal/intern/array.h +++ b/include/ruby/internal/intern/array.h @@ -107,14 +107,14 @@ VALUE rb_ary_new_from_args(long n, ...); VALUE rb_ary_new_from_values(long n, const VALUE *elts); /** - * Allocates a hidden (no class) empty array. + * Allocates a "temporary" array. This is a hidden empty array. Handy on + * occasions. * * @param[in] capa Designed capacity of the array. * @return A hidden, empty array. * @see rb_obj_hide() */ -VALUE rb_ary_hidden_new(long capa); -#define rb_ary_tmp_new rb_ary_hidden_new +VALUE rb_ary_tmp_new(long capa); /** * Destroys the given array for no reason. @@ -187,7 +187,7 @@ VALUE rb_ary_shared_with_p(VALUE lhs, VALUE rhs); * : (int i) -> T? * | (int beg, int len) -> ::Array[T]? * | (Range[int] r) -> ::Array[T]? - * | (ArithmeticSequence as) -> ::Array[T]? # This also raises RangeError. + * | (ArithmeticSequence as) -> ::Array[T]? # This also raises RagneError. * end * ``` */ diff --git a/include/ruby/internal/intern/bignum.h b/include/ruby/internal/intern/bignum.h index c27f77a1fb..43d68018de 100644 --- a/include/ruby/internal/intern/bignum.h +++ b/include/ruby/internal/intern/bignum.h @@ -51,7 +51,7 @@ RBIMPL_SYMBOL_EXPORT_BEGIN() VALUE rb_big_new(size_t len, int sign); /** - * Queries if the passed bignum instance is a "bigzero". What is a bigzero? + * Queries if the passed bignum instance is a "bigzro". What is a bigzero? * Well, bignums are for very big integers, but can also represent tiny ones * like -1, 0, 1. Bigzero are instances of bignums whose values are zero. * Knowing if a bignum is bigzero can be handy on occasions, like for instance @@ -793,7 +793,7 @@ size_t rb_absint_size(VALUE val, int *nlz_bits_ret); * @exception rb_eTypeError `val` doesn't respond to `#to_int`. * @retval (size_t)-1 Overflowed. * @retval otherwise - * `((val_numbits * CHAR_BIT + word_numbits - 1) / word_numbits)`, + `((val_numbits * CHAR_BIT + word_numbits - 1) / word_numbits)`, * where val_numbits is the number of bits of `abs(val)`. * @post If `nlz_bits_ret` is not `NULL` and there is no overflow, * `(return_value * word_numbits - val_numbits)` is stored in diff --git a/include/ruby/internal/intern/class.h b/include/ruby/internal/intern/class.h index 0fb2d001bc..2181ab93c7 100644 --- a/include/ruby/internal/intern/class.h +++ b/include/ruby/internal/intern/class.h @@ -200,18 +200,6 @@ VALUE rb_class_descendants(VALUE klass); */ VALUE rb_class_subclasses(VALUE klass); - -/** - * Returns the attached object for a singleton class. - * If the given class is not a singleton class, raises a TypeError. - * - * @param[in] klass A class. - * @return The object which has the singleton class `klass`. - * - * @internal - */ -VALUE rb_class_attached_object(VALUE klass); - /** * Generates an array of symbols, which are the list of method names defined in * the passed class. diff --git a/include/ruby/internal/intern/cont.h b/include/ruby/internal/intern/cont.h index 32647f48aa..37493009f5 100644 --- a/include/ruby/internal/intern/cont.h +++ b/include/ruby/internal/intern/cont.h @@ -39,28 +39,6 @@ RBIMPL_SYMBOL_EXPORT_BEGIN() VALUE rb_fiber_new(rb_block_call_func_t func, VALUE callback_obj); /** - * Creates a Fiber instance from a C-backended block with the specified - * storage. - * - * If the given storage is Qundef or Qtrue, this function is equivalent to - * rb_fiber_new() which inherits storage from the current fiber. - * - * Specifying Qtrue is experimental and may be changed in the future. - * - * If the given storage is Qnil, this function will lazy initialize the - * internal storage which starts of empty (without any inheritance). - * - * Otherwise, the given storage is used as the internal storage. - * - * @param[in] func A function, to become the fiber's body. - * @param[in] callback_obj Passed as-is to `func`. - * @param[in] storage The way to set up the storage for the fiber. - * @return An allocated new instance of rb_cFiber, which is ready to be - * "resume"d. - */ -VALUE rb_fiber_new_storage(rb_block_call_func_t func, VALUE callback_obj, VALUE storage); - -/** * Queries the fiber which is calling this function. Any ruby execution * context has its fiber, either explicitly or implicitly. * diff --git a/include/ruby/internal/intern/error.h b/include/ruby/internal/intern/error.h index bf8daadd3e..37d3b8592b 100644 --- a/include/ruby/internal/intern/error.h +++ b/include/ruby/internal/intern/error.h @@ -38,6 +38,8 @@ #define rb_exc_new3 rb_exc_new_str /**< @old{rb_exc_new_str} */ /** @cond INTERNAL_MACRO */ +#define rb_check_trusted rb_check_trusted +#define rb_check_trusted_inline rb_check_trusted #define rb_check_arity rb_check_arity /** @endcond */ @@ -202,6 +204,12 @@ RBIMPL_ATTR_NORETURN() void rb_error_frozen_object(VALUE what); /** + * @deprecated Does nothing. This method is deprecated and will be removed in + * Ruby 3.2. + */ +void rb_error_untrusted(VALUE); + +/** * Queries if the passed object is frozen. * * @param[in] obj Target object to test frozen-ness. @@ -211,6 +219,12 @@ void rb_error_frozen_object(VALUE what); void rb_check_frozen(VALUE obj); /** + * @deprecated Does nothing. This method is deprecated and will be removed in + * Ruby 3.2. + */ +void rb_check_trusted(VALUE); + +/** * Ensures that the passed object can be `initialize_copy` relationship. When * you implement your own one you would better call this at the right beginning * of your implementation. @@ -235,7 +249,7 @@ RBIMPL_ATTR_NORETURN() * @param[in] max Maximum allowed `argc`. * @exception rb_eArgError Always. */ -void rb_error_arity(int argc, int min, int max); +MJIT_STATIC void rb_error_arity(int argc, int min, int max); RBIMPL_SYMBOL_EXPORT_END() diff --git a/include/ruby/internal/intern/file.h b/include/ruby/internal/intern/file.h index 79820fdc61..2dc60c7ba7 100644 --- a/include/ruby/internal/intern/file.h +++ b/include/ruby/internal/intern/file.h @@ -206,7 +206,7 @@ int rb_is_absolute_path(const char *path); * unpredictable. POSIX's `<sys/stat.h>` states that "the use of * this field is unspecified" then. */ -rb_off_t rb_file_size(VALUE file); +off_t rb_file_size(VALUE file); RBIMPL_SYMBOL_EXPORT_END() diff --git a/include/ruby/internal/intern/gc.h b/include/ruby/internal/intern/gc.h new file mode 100644 index 0000000000..e7b8008729 --- /dev/null +++ b/include/ruby/internal/intern/gc.h @@ -0,0 +1,392 @@ +#ifndef RBIMPL_INTERN_GC_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_INTERN_GC_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_mGC. + */ +#include "ruby/internal/config.h" + +#ifdef STDC_HEADERS +# include <stddef.h> /* size_t */ +#endif + +#if HAVE_SYS_TYPES_H +# include <sys/types.h> /* ssize_t */ +#endif + +#include "ruby/internal/attr/cold.h" +#include "ruby/internal/attr/noreturn.h" +#include "ruby/internal/attr/nonnull.h" +#include "ruby/internal/attr/pure.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/value.h" + +RBIMPL_SYMBOL_EXPORT_BEGIN() + +/* gc.c */ + +RBIMPL_ATTR_COLD() +RBIMPL_ATTR_NORETURN() +/** + * Triggers out-of-memory error. If possible it raises ::rb_eNoMemError. But + * because we are running out of memory that is not always doable. This + * function tries hard to show something, but ultimately can die silently. + * + * @exception rb_eNoMemError Raises it if possible. + */ +void rb_memerror(void); + +RBIMPL_ATTR_PURE() +/** + * Queries if the GC is busy. + * + * @retval 0 It isn't. + * @retval 1 It is. + */ +int rb_during_gc(void); + +RBIMPL_ATTR_NONNULL((1)) +/** + * Marks objects between the two pointers. This is one of the GC utility + * functions that you can call when you design your own + * ::rb_data_type_struct::dmark. + * + * @pre Continuous memory region from `start` to `end` shall be fully + * addressable. + * @param[out] start Pointer to an array of objects. + * @param[out] end Pointer that terminates the array of objects. + * @post Objects from `start` to `end`, both inclusive, are marked. + * + * @internal + * + * `end` can be NULL... But that just results in no-op. + */ +void rb_gc_mark_locations(const VALUE *start, const VALUE *end); + +/** + * Identical to rb_mark_hash(), except it marks only values of the table and + * leave their associated keys unmarked. This is one of the GC utility + * functions that you can call when you design your own + * ::rb_data_type_struct::dmark. + * + * @warning Of course it can break GC. Leave it unused if unsure. + * @param[in] tbl A table to mark. + * @post Values stored in `tbl` are marked. + */ +void rb_mark_tbl(struct st_table *tbl); + +/** + * Identical to rb_mark_tbl(), except it marks objects using + * rb_gc_mark_movable(). This is one of the GC utility functions that you can + * call when you design your own ::rb_data_type_struct::dmark. + * + * @warning Of course it can break GC. Leave it unused if unsure. + * @param[in] tbl A table to mark. + * @post Values stored in `tbl` are marked. + */ +void rb_mark_tbl_no_pin(struct st_table *tbl); + +/** + * Identical to rb_mark_hash(), except it marks only keys of the table and + * leave their associated values unmarked. This is one of the GC utility + * functions that you can call when you design your own + * ::rb_data_type_struct::dmark. + * + * @warning Of course it can break GC. Leave it unused if unsure. + * @param[in] tbl A table to mark. + * @post Keys stored in `tbl` are marked. + */ +void rb_mark_set(struct st_table *tbl); + +/** + * Marks keys and values associated inside of the given table. This is one of + * the GC utility functions that you can call when you design your own + * ::rb_data_type_struct::dmark. + * + * @param[in] tbl A table to mark. + * @post Objects stored in `tbl` are marked. + */ +void rb_mark_hash(struct st_table *tbl); + +/** + * Updates references inside of tables. After you marked values using + * rb_mark_tbl_no_pin(), the objects inside of the table could of course be + * moved. This function is to fixup those references. You can call this from + * your ::rb_data_type_struct::dcompact. + * + * @param[out] ptr A table that potentially includes moved references. + * @post Moved references, if any, are corrected. + */ +void rb_gc_update_tbl_refs(st_table *ptr); + +/** + * Identical to rb_gc_mark(), except it allows the passed value be a + * non-object. For instance pointers to different type of memory regions are + * allowed here. Such values are silently ignored. This is one of the GC + * utility functions that you can call when you design your own + * ::rb_data_type_struct::dmark. + * + * @param[out] obj A possible object. + * @post `obj` is marked, if possible. + */ +void rb_gc_mark_maybe(VALUE obj); + +/** + * Marks an object. This is one of the GC utility functions that you can call + * when you design your own ::rb_data_type_struct::dmark. + * + * @param[out] obj Arbitrary Ruby object. + * @post `obj` is marked. + */ +void rb_gc_mark(VALUE obj); + +/** + * Maybe this is the only function provided for C extensions to control the + * pinning of objects, so let us describe it in detail. These days Ruby's GC + * is copying. As far as an object's physical address is guaranteed unused, it + * can move around the object space. Our GC engine rearranges these objects + * after it reclaims unreachable objects from our object space, so that the + * space is compact (improves memory locality). This is called the + * "compaction" phase, and works well most of the time... as far as there are + * no C extensions. C extensions complicate the scenario because Ruby core + * cannot detect any use of the physical address of an object inside of C + * functions. In order to prevent memory corruptions, objects observable from + * C extensions are "pinned"; they stick to where they are born until they die, + * just in case any C extensions touch their raw pointers. This variant of + * scheme is called "Mostly-Copying" garbage collector. Authors of C + * extensions, however, can extremely carefully write them to become + * compaction-aware. To do so avoid referring to a Ruby object from inside of + * your struct in the first place. But if that is not possible, use this + * function from your ::rb_data_type_struct::dmark then. This way objects + * marked using it are considered movable. If you chose this way you have to + * manually fix up locations of such moved pointers using rb_gc_location(). + * + * @see Bartlett, Joel F., "Compacting Garbage Collection with Ambiguous + * Roots", ACM SIGPLAN Lisp Pointers Volume 1 Issue 6 pp. 3-12, + * April-May-June, 1988. https://doi.org/10.1145/1317224.1317225 + * + * @param[in] obj Object that is movable. + * @post Values stored in `tbl` are marked. + */ +void rb_gc_mark_movable(VALUE obj); + +/** + * Finds a new "location" of an object. An object can be moved on compaction. + * This function projects its new abode, or just returns the passed object if + * not moved. This is one of the GC utility functions that you can call when + * you design your own ::rb_data_type_struct::dcompact. + * + * @param[in] obj An object, possibly already moved to somewhere else. + * @return An object, which holds the current contents of former `obj`. + */ +VALUE rb_gc_location(VALUE obj); + +/** + * Asserts that the passed object is no longer needed. Such objects are + * reclaimed sooner or later so this function is not mandatory. But sometimes + * you can know from your application knowledge that an object is surely dead + * at some point. Calling this as a hint can be a polite way. + * + * @param[out] obj Object, dead. + * @pre `obj` have never been passed to this function before. + * @post `obj` could be invalidated. + * @warning It is a failure to pass an object multiple times to this + * function. + * @deprecated This is now a no-op function. + */ +RBIMPL_ATTR_DEPRECATED(("this is now a no-op function")) +void rb_gc_force_recycle(VALUE obj); + +/** + * Triggers a GC process. This was the only GC entry point that we had at the + * beginning. Over time our GC evolved. Now what this function does is just a + * very simplified variation of the entire GC algorithms. A series of + * procedures kicked by this API is called a "full" GC. + * + * - It immediately scans the entire object space to sort the dead. + * - It immediately reclaims any single dead bodies to reuse later. + * + * It is worth noting that the procedures above do not include evaluations of + * finalisers. They run later. + * + * @internal + * + * Finalisers are deferred until we can handle interrupts. See + * `rb_postponed_job_flush` in vm_trace.c. + * + * Of course there are GC that are not "full". For instance this one and the + * GC which runs when we are running out of memory are different. See + * `gc_profile_record_flag` defined in gc.c for the kinds of GC. + * + * In spite of the name this is not what everything that a GC can trigger. As + * of writing it seems this function does not trigger compaction. But this + * might change in future. + */ +void rb_gc(void); + +/** + * Copy&paste an object's finaliser to another. This is one of the GC utility + * functions that you can call when you design your own `initialize_copy`, + * `initialize_dup`, `initialize_clone`. + * + * @param[out] dst Destination object. + * @param[in] src Source object. + * @post `dst` and `src` share the same finaliser. + * + * @internal + * + * But isn't it easier for you to call super, and let `Object#initialize_copy` + * call this function instead? + */ +void rb_gc_copy_finalizer(VALUE dst, VALUE src); + +/** + * (Re-) enables GC. This makes sense only after you called rb_gc_disable(). + * + * @retval RUBY_Qtrue GC was disabled before. + * @retval RUBY_Qfalse GC was enabled before. + * @post GC is enabled. + * + * @internal + * + * This is one of such exceptional functions that does not raise both Ruby + * exceptions and C++ exceptions. + */ +VALUE rb_gc_enable(void); + +/** + * Disables GC. This prevents automatic GC runs when the process is running + * out of memory. Such situations shall result in rb_memerror(). However this + * does not prevent users from manually invoking rb_gc(). That should work. + * People abused this by disabling GC at the beginning of an event loop, + * process events without GC overheads, then manually force reclaiming garbage + * at the bottom of the loop. However because our GC is now much smarter than + * just calling rb_gc(), this technique is proven to be sub-optimal these days. + * It is believed that there is currently practically no needs of this + * function. + * + * @retval RUBY_Qtrue GC was disabled before. + * @retval RUBY_Qfalse GC was enabled before. + * @post GC is disabled. + */ +VALUE rb_gc_disable(void); + +/** + * Identical to rb_gc(), except the return value. + * + * @return Always returns ::RUBY_Qnil. + */ +VALUE rb_gc_start(void); + +/** + * Assigns a finaliser for an object. Each objects can have objects (typically + * blocks) that run immediately after that object dies. They are called + * finalisers of an object. This function associates a finaliser object with a + * target object. + * + * @note Note that finalisers run _after_ the object they finalise dies. You + * cannot for instance call its methods. + * @note If your finaliser references the object it finalises that object + * loses any chance to become a garbage; effectively leaks memory until + * the end of the process. + * + * @param[in] obj Target to finalise. + * @param[in] block Something `call`able. + * @exception rb_eRuntimeError Somehow `obj` cannot have finalisers. + * @exception rb_eFrozenError `obj` is frozen. + * @exception rb_eArgError `block` doesn't respond to `call`. + * @return The passed `block`. + * @post `block` runs after `obj` dies. + */ +VALUE rb_define_finalizer(VALUE obj, VALUE block); + +/** + * Modifies the object so that it has no finalisers at all. This function is + * mainly provided for symmetry. No practical usages can be thought of. + * + * @param[out] obj Object to clear its finalisers. + * @exception rb_eFrozenError `obj` is frozen. + * @return The passed `obj`. + * @post `obj` has no finalisers. + * @note There is no way to undefine a specific part of many finalisers + * that `obj` could have. All you can do is to clear them all. + */ +VALUE rb_undefine_finalizer(VALUE obj); + +/** + * Identical to rb_gc_stat(), with "count" parameter. + * + * @return Lifetime total number of runs of GC. + */ +size_t rb_gc_count(void); + +/** + * Obtains various GC related profiles. The parameter can be either a Symbol + * or a Hash. If a Hash is passed, it is filled with everything currently + * available. If a Symbol is passed just that portion is returned. + * + * Possible variations of keys you can pass here change from version to + * version. You can get the list of known keys by passing an empty hash and + * let it be filled. + * + * @param[in,out] key_or_buf A Symbol, or a Hash. + * @exception rb_eTypeError Neither Symbol nor Hash. + * @exception rb_eFrozenError Frozen hash is passed. + * @return In case a Hash is passed it returns 0. Otherwise the + * profile value associated with the given key is returned. + * @post In case a Hash is passed it is filled with values. + */ +size_t rb_gc_stat(VALUE key_or_buf); + +/** + * Obtains various info regarding the most recent GC run. This includes for + * instance the reason of the GC. The parameter can be either a Symbol or a + * Hash. If a Hash is passed, it is filled with everything currently + * available. If a Symbol is passed just that portion is returned. + * + * Possible variations of keys you can pass here change from version to + * version. You can get the list of known keys by passing an empty hash and + * let it be filled. + * + * @param[in,out] key_or_buf A Symbol, or a Hash. + * @exception rb_eTypeError Neither Symbol nor Hash. + * @exception rb_eFrozenError Frozen hash is passed. + * @return In case a Hash is passed it returns that hash. Otherwise + * the profile value associated with the given key is returned. + * @post In case a Hash is passed it is filled with values. + */ +VALUE rb_gc_latest_gc_info(VALUE key_or_buf); + +/** + * Informs that there are external memory usages. Our GC runs when we are + * running out of memory. The amount of memory, however, can increase/decrease + * behind-the-scene. For instance DLLs can allocate memories using `mmap(2)` + * etc, which are opaque to us. Registering such external allocations using + * this function enables proper detection of how much memories an object used + * as a whole. That will trigger GCs more often than it would otherwise. You + * can also pass negative numbers here, to indicate that such external + * allocations are gone. + * + * @param[in] diff Amount of memory increased(+)/decreased(-). + */ +void rb_gc_adjust_memory_usage(ssize_t diff); + +RBIMPL_SYMBOL_EXPORT_END() + +#endif /* RBIMPL_INTERN_GC_H */ diff --git a/include/ruby/internal/intern/hash.h b/include/ruby/internal/intern/hash.h index af8dfd5d8f..9d2ce8279a 100644 --- a/include/ruby/internal/intern/hash.h +++ b/include/ruby/internal/intern/hash.h @@ -107,17 +107,6 @@ VALUE rb_hash(VALUE obj); VALUE rb_hash_new(void); /** - * Identical to rb_hash_new(), except it additionally specifies how many keys - * it is expected to contain. This way you can create a hash that is large enough - * for your need. For large hashes it means it won't need to be reallocated and - * rehashed as much, improving performance. - * - * @param[in] capa Designed capacity of the hash. - * @return An empty Hash, whose capacity is `capa`. - */ -VALUE rb_hash_new_capa(long capa); - -/** * Duplicates a hash. * * @param[in] hash An instance of ::rb_cHash. @@ -299,6 +288,15 @@ int rb_path_check(const char *path); /* hash.c */ /** + * @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. + * + * @return 0 always. + */ +int rb_env_path_tainted(void); + +/** * Destructively removes every environment variables of the running process. * * @return The `ENV` object. diff --git a/include/ruby/internal/intern/load.h b/include/ruby/internal/intern/load.h index 9ceb98c2e4..288a16c2ec 100644 --- a/include/ruby/internal/intern/load.h +++ b/include/ruby/internal/intern/load.h @@ -177,43 +177,6 @@ VALUE rb_f_require(VALUE self, VALUE feature); VALUE rb_require_string(VALUE feature); /** - * Resolves and returns a symbol of a function in the native extension - * specified by the feature and symbol names. Extensions will use this function - * to access the symbols provided by other native extensions. - * - * @param[in] feature Name of a feature, e.g. `"json"`. - * @param[in] symbol Name of a symbol defined by the feature. - * @return The resolved symbol of a function, defined and externed by the - * specified feature. It may be NULL if the feature is not loaded, - * the feature is not extension, or the symbol is not found. - */ -void *rb_ext_resolve_symbol(const char *feature, const char *symbol); - -/** - * This macro is to provide backwards compatibility. It provides a way to - * define function prototypes and resolving function symbols in a safe way. - * - * ```CXX - * // prototypes - * #ifdef HAVE_RB_EXT_RESOLVE_SYMBOL - * VALUE *(*other_extension_func)(VALUE,VALUE); - * #else - * VALUE other_extension_func(VALUE); - * #endif - * - * // in Init_xxx() - * #ifdef HAVE_RB_EXT_RESOLVE_SYMBOL - * other_extension_func = \ - * (VALUE(*)(VALUE,VALUE))rb_ext_resolve_symbol(fname, sym_name); - * if (other_extension_func == NULL) { - * // raise your own error - * } - * #endif - * ``` - */ -#define HAVE_RB_EXT_RESOLVE_SYMBOL 1 - -/** * @name extension configuration * @{ */ diff --git a/include/ruby/internal/intern/object.h b/include/ruby/internal/intern/object.h index b9ffa57c06..6bb4ccb2fe 100644 --- a/include/ruby/internal/intern/object.h +++ b/include/ruby/internal/intern/object.h @@ -92,8 +92,8 @@ VALUE rb_class_new_instance_kw(int argc, const VALUE *argv, VALUE klass, int kw_ * * @param[in] lhs Comparison left hand side. * @param[in] rhs Comparison right hand side. - * @retval non-zero They are equal. - * @retval 0 Otherwise. + * @retval RUBY_Qtrue They are equal. + * @retval RUBY_Qfalse Otherwise. * @note This function actually calls `lhs.eql?(rhs)` so you cannot * implement your class' `#eql?` method using it. */ @@ -202,6 +202,74 @@ VALUE rb_obj_dup(VALUE obj); */ VALUE rb_obj_init_copy(VALUE src, VALUE dst); +RBIMPL_ATTR_DEPRECATED_EXT(("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 Verbatim `obj`. + */ +VALUE rb_obj_taint(VALUE obj); + +RBIMPL_ATTR_PURE() +RBIMPL_ATTR_DEPRECATED_EXT(("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 Always returns ::RUBY_Qfalse. + */ +VALUE rb_obj_tainted(VALUE obj); + +RBIMPL_ATTR_DEPRECATED_EXT(("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 Verbatim `obj`. + */ +VALUE rb_obj_untaint(VALUE obj); + +RBIMPL_ATTR_DEPRECATED_EXT(("trustedness 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 Verbatim `obj`. + */ +VALUE rb_obj_untrust(VALUE obj); + +RBIMPL_ATTR_PURE() +RBIMPL_ATTR_DEPRECATED_EXT(("trustedness 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 Always returns ::RUBY_Qfalse. + */ +VALUE rb_obj_untrusted(VALUE obj); + +RBIMPL_ATTR_DEPRECATED_EXT(("trustedness 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 Verbatim `obj`. + */ +VALUE rb_obj_trust(VALUE obj); + /** * Just calls rb_obj_freeze_inline() inside. Does this make any sens to * extension libraries? diff --git a/include/ruby/internal/intern/process.h b/include/ruby/internal/intern/process.h index cfa5e13162..7a7b24ed4b 100644 --- a/include/ruby/internal/intern/process.h +++ b/include/ruby/internal/intern/process.h @@ -31,15 +31,6 @@ RBIMPL_SYMBOL_EXPORT_BEGIN() /* process.c */ /** - * Wait for the specified process to terminate, reap it, and return its status. - * - * @param[in] pid The process ID to wait for. - * @param[in] flags The flags to pass to waitpid(2). - * @return VALUE An instance of Process::Status. - */ -VALUE rb_process_status_wait(rb_pid_t pid, int flags); - -/** * Sets the "last status", or the `$?`. * * @param[in] status The termination status, as defined in `waitpid(3posix)`. @@ -256,7 +247,7 @@ rb_pid_t rb_spawn_err(int argc, const VALUE *argv, char *errbuf, size_t buflen); * * @internal * - * This function might or might not exist depending on `./configure` result. + * This function might or might not exist depending on `./confiugre` result. * It must be a portability hell. Better not use. */ VALUE rb_proc_times(VALUE _); diff --git a/include/ruby/internal/intern/re.h b/include/ruby/internal/intern/re.h index 4dd58b469b..31f5593275 100644 --- a/include/ruby/internal/intern/re.h +++ b/include/ruby/internal/intern/re.h @@ -87,6 +87,11 @@ void rb_match_busy(VALUE md); * @retval RUBY_Qfalse There is a `n`-th capture and is empty. * @retval RUBY_Qtrue There is a `n`-th capture that has something. * + * @internal + * + * @shyouhei wonders: why there are both rb_reg_match_defined() and + * rb_match_nth_defined, which are largely the same things, but do not share + * their implementations at all? */ VALUE rb_reg_nth_defined(int n, VALUE md); diff --git a/include/ruby/internal/intern/select.h b/include/ruby/internal/intern/select.h index 6ba84c6e63..fabc287cd1 100644 --- a/include/ruby/internal/intern/select.h +++ b/include/ruby/internal/intern/select.h @@ -76,7 +76,7 @@ struct timeval; * * Although any file descriptors are possible here, it makes completely no * sense to pass a descriptor that is not `O_NONBLOCK`. If you want to know - * the reason for this limitation in detail, you might find this thread super + * the reason for this limitatuon in detail, you might find this thread super * interesting: https://lkml.org/lkml/2004/10/6/117 */ int rb_thread_fd_select(int nfds, rb_fdset_t *rfds, rb_fdset_t *wfds, rb_fdset_t *efds, struct timeval *timeout); diff --git a/include/ruby/internal/intern/select/largesize.h b/include/ruby/internal/intern/select/largesize.h index d65f088c06..d156f62034 100644 --- a/include/ruby/internal/intern/select/largesize.h +++ b/include/ruby/internal/intern/select/largesize.h @@ -35,6 +35,9 @@ * `select(2)` documents how to allocate fd_set dynamically. * http://www.openbsd.org/cgi-bin/man.cgi?query=select&manpath=OpenBSD+4.4 * + * - HP-UX documents how to allocate fd_set dynamically. + * http://docs.hp.com/en/B2355-60105/select.2.html + * * - Solaris 8 has `select_large_fdset` * * - Mac OS X 10.7 (Lion) diff --git a/include/ruby/internal/intern/select/posix.h b/include/ruby/internal/intern/select/posix.h index 0a9b0b2e51..5f828e66e2 100644 --- a/include/ruby/internal/intern/select/posix.h +++ b/include/ruby/internal/intern/select/posix.h @@ -136,7 +136,7 @@ rb_fd_max(const rb_fdset_t *f) } /** @cond INTERNAL_MACRO */ -/* :FIXME: What are these? They don't exist for sibling implementations. */ +/* :FIXME: What are these? They don't exist for shibling implementations. */ #define rb_fd_init_copy(d, s) (*(d) = *(s)) #define rb_fd_term(f) ((void)(f)) /** @endcond */ diff --git a/include/ruby/internal/intern/signal.h b/include/ruby/internal/intern/signal.h index e5b6d6c3d5..84f7558404 100644 --- a/include/ruby/internal/intern/signal.h +++ b/include/ruby/internal/intern/signal.h @@ -113,6 +113,12 @@ RBIMPL_ATTR_NONNULL(()) */ VALUE rb_f_kill(int argc, const VALUE *argv); +/* This must be private, @shyouhei guesses. */ +#ifdef POSIX_SIGNAL +#define posix_signal ruby_posix_signal +void (*posix_signal(int, void (*)(int)))(int); +#endif + RBIMPL_ATTR_PURE() /** * Queries the name of the signal. It returns for instance `"KILL"` for diff --git a/include/ruby/internal/intern/string.h b/include/ruby/internal/intern/string.h index 3083125e56..2ee8496256 100644 --- a/include/ruby/internal/intern/string.h +++ b/include/ruby/internal/intern/string.h @@ -123,6 +123,37 @@ VALUE rb_str_new_frozen(VALUE str); VALUE rb_str_new_with_class(VALUE obj, const char *ptr, long len); /** + * @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] ptr A C string. + * @exception rb_eNoMemError Failed to allocate memory. + * @exception rb_eArgError `ptr` is a null pointer. + * @return An instance of ::rb_cString, of "binary" encoding, whose + * contents are verbatim copy of `ptr`. + * @pre `ptr` must not be a null pointer. + */ +VALUE rb_tainted_str_new_cstr(const char *ptr); + +/** + * @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] ptr A memory region of `len` bytes length. + * @param[in] len Length of `ptr`, in bytes, not including the + * terminating NUL character. + * @exception rb_eNoMemError Failed to allocate `len+1` bytes. + * @exception rb_eArgError `len` is negative. + * @return An instance of ::rb_cString, of `len` bytes length, of + * "binary" encoding, whose contents are verbatim copy of `ptr`. + * @pre At least `len` bytes of continuous memory region shall be + * accessible via `ptr`. + */ +VALUE rb_tainted_str_new(const char *ptr, long len); + +/** * Identical to rb_str_new(), except it generates a string of "default * external" encoding. * @@ -1367,6 +1398,22 @@ rbimpl_str_new_cstr(const char *str) return rb_str_new_static(str, len); } +RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) +/** + * @private + * + * This is an implementation detail. Don't bother. + * + * @param[in] str A C string literal. + * @return Corresponding Ruby string. + */ +static inline VALUE +rbimpl_tainted_str_new_cstr(const char *str) +{ + long len = rbimpl_strlen(str); + return rb_tainted_str_new(str, len); +} + RBIMPL_ATTR_NONNULL(()) /** * @private @@ -1553,6 +1600,22 @@ rbimpl_exc_new_cstr(VALUE exc, const char *str) rb_utf8_str_new) ((str), (len))) /** + * @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. + * + * @param[in] str A C string. + * @exception rb_eNoMemError Failed to allocate memory. + * @return An instance of ::rb_cString, of "binary" encoding, whose + * contents are verbatim copy of `str`. + * @pre `str` must not be a null pointer. + */ +#define rb_tainted_str_new_cstr(str) \ + ((RBIMPL_CONSTANT_P(str) ? \ + rbimpl_tainted_str_new_cstr : \ + rb_tainted_str_new_cstr) (str)) + +/** * Identical to #rb_str_new_cstr, except it generates a string of "US ASCII" * encoding. It can also be seen as a routine Identical to * #rb_usascii_str_new, except it assumes the passed pointer is a pointer to a @@ -1676,6 +1739,7 @@ rbimpl_exc_new_cstr(VALUE exc, const char *str) #define rb_str_new3 rb_str_new_shared /**< @old{rb_str_new_shared} */ #define rb_str_new4 rb_str_new_frozen /**< @old{rb_str_new_frozen} */ #define rb_str_new5 rb_str_new_with_class /**< @old{rb_str_new_with_class} */ +#define rb_tainted_str_new2 rb_tainted_str_new_cstr /**< @old{rb_tainted_str_new_cstr} */ #define rb_str_buf_new2 rb_str_buf_new_cstr /**< @old{rb_str_buf_new_cstr} */ #define rb_usascii_str_new2 rb_usascii_str_new_cstr /**< @old{rb_usascii_str_new_cstr} */ #define rb_str_buf_cat rb_str_cat /**< @alias{rb_str_cat} */ diff --git a/include/ruby/internal/intern/struct.h b/include/ruby/internal/intern/struct.h index 4510508d77..312cf444e2 100644 --- a/include/ruby/internal/intern/struct.h +++ b/include/ruby/internal/intern/struct.h @@ -46,10 +46,10 @@ VALUE rb_struct_new(VALUE klass, ...); * * @param[in] name Name of the class. * @param[in] ... Arbitrary number of `const char*`, terminated by - * NULL. Each of which are the name of fields. + * zero. Each of which are the name of fields. * @exception rb_eNameError `name` is not a constant name. * @exception rb_eTypeError `name` is already taken. - * @exception rb_eArgError Duplicated field name. + * @exception rb_eArgError Duplicated field name. * @return The defined class. * @post Global toplevel constant `name` is defined. * @note `name` is allowed to be a null pointer. This function creates @@ -70,10 +70,10 @@ RBIMPL_ATTR_NONNULL((2)) * @param[out] space Namespace that the defining class shall reside. * @param[in] name Name of the class. * @param[in] ... Arbitrary number of `const char*`, terminated by - * NULL. Each of which are the name of fields. + * zero. Each of which are the name of fields. * @exception rb_eNameError `name` is not a constant name. * @exception rb_eTypeError `name` is already taken. - * @exception rb_eArgError Duplicated field name. + * @exception rb_eArgError Duplicated field name. * @return The defined class. * @post `name` is a constant under `space`. * @note In contrast to rb_struct_define(), it doesn't make any sense to @@ -164,10 +164,10 @@ VALUE rb_struct_alloc_noinit(VALUE klass); * @param[in] super Superclass of the defining class. * @param[in] func Must be 0 for extension libraries. * @param[in] ... Arbitrary number of `const char*`, terminated by - * NULL. Each of which are the name of fields. + * zero. Each of which are the name of fields. * @exception rb_eNameError `name` is not a constant name. * @exception rb_eTypeError `name` is already taken. - * @exception rb_eArgError Duplicated field name. + * @exception rb_eArgError Duplicated field name. * @return The defined class. * @post Global toplevel constant `name` is defined. * @note `name` is allowed to be a null pointer. This function creates @@ -187,10 +187,10 @@ RBIMPL_ATTR_NONNULL((2)) * @param[in] super Superclass of the defining class. * @param[in] alloc Must be 0 for extension libraries. * @param[in] ... Arbitrary number of `const char*`, terminated by - * NULL. Each of which are the name of fields. + * zero. Each of which are the name of fields. * @exception rb_eNameError `class_name` is not a constant name. * @exception rb_eTypeError `class_name` is already taken. - * @exception rb_eArgError Duplicated field name. + * @exception rb_eArgError Duplicated field name. * @return The defined class. * @post `class_name` is a constant under `outer`. * @note In contrast to rb_struct_define_without_accessor(), it doesn't @@ -198,20 +198,6 @@ RBIMPL_ATTR_NONNULL((2)) */ VALUE rb_struct_define_without_accessor_under(VALUE outer, const char *class_name, VALUE super, rb_alloc_func_t alloc, ...); -/** - * Defines an anonymous data class. - * - * @endinternal - * - * @param[in] super Superclass of the defining class. Must be a - * descendant of ::rb_cData, or 0 as ::rb_cData. - * @param[in] ... Arbitrary number of `const char*`, terminated by - * NULL. Each of which are the name of fields. - * @exception rb_eArgError Duplicated field name. - * @return The defined class. - */ -VALUE rb_data_define(VALUE super, ...); - RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_STRUCT_H */ diff --git a/include/ruby/internal/intern/vm.h b/include/ruby/internal/intern/vm.h index 76af796b54..562d30a6fe 100644 --- a/include/ruby/internal/intern/vm.h +++ b/include/ruby/internal/intern/vm.h @@ -247,17 +247,21 @@ void rb_undef_alloc_func(VALUE klass); * * @internal * - * Who cares? @shyouhei finds no practical usage of the return value. Maybe we + * Who cares? @shyouhei fins no practical usage of the return value. Maybe we * need KonMari. */ rb_alloc_func_t rb_get_alloc_func(VALUE klass); /** - * Clears the inline constant caches associated with a particular ID. Extension - * libraries should not bother with such things. Just forget about this API (or - * even, the presence of constant caches). + * Clears the constant cache. Extension libraries should not bother such + * things. Just forget about this API (or even, the presence of constant + * cache). + * + * @internal + * + * Completely no idea why this function is defined in vm_method.c. */ -void rb_clear_constant_cache_for_id(ID id); +void rb_clear_constant_cache(void); /** * Resembles `alias`. diff --git a/include/ruby/internal/memory.h b/include/ruby/internal/memory.h index 8f00787512..aa3464465d 100644 --- a/include/ruby/internal/memory.h +++ b/include/ruby/internal/memory.h @@ -62,7 +62,7 @@ #include "ruby/backward/2/assume.h" #include "ruby/defines.h" -/** @cond INTERNAL_MACRO */ +/** @cond INTENAL_MACRO */ /* Make alloca work the best possible way. */ #if defined(alloca) @@ -287,12 +287,12 @@ typedef uint128_t DSIZE_T; RBIMPL_CAST((type *)alloca(rbimpl_size_mul_or_raise(sizeof(type), (n)))) /** - * Identical to #RB_ALLOCV_N(), except that it allocates a number of bytes and - * returns a void* . + * Identical to #RB_ALLOCV_N(), except it implicitly assumes the type of array + * is ::VALUE. * * @param v A variable to hold the just-in-case opaque Ruby object. * @param n Size of allocation, in bytes. - * @return A void pointer to `n` bytes storage. + * @return An array of `n` bytes of ::VALUE. * @note `n` may be evaluated twice. */ #define RB_ALLOCV(v, n) \ @@ -363,7 +363,7 @@ typedef uint128_t DSIZE_T; * @return `p1`. * @post First `n` elements of `p2` are copied into `p1`. */ -#define MEMCPY(p1,p2,type,n) ruby_nonempty_memcpy((p1), (p2), rbimpl_size_mul_or_raise(sizeof(type), (n))) +#define MEMCPY(p1,p2,type,n) memcpy((p1), (p2), rbimpl_size_mul_or_raise(sizeof(type), (n))) /** * Handy macro to call memmove. @@ -644,6 +644,7 @@ rb_alloc_tmp_buffer2(volatile VALUE *store, long count, size_t elsize) return rb_alloc_tmp_buffer_with_count(store, total_size, cnt); } +#if ! defined(__MINGW32__) && ! defined(__DOXYGEN__) RBIMPL_SYMBOL_EXPORT_BEGIN() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) @@ -662,5 +663,8 @@ ruby_nonempty_memcpy(void *dest, const void *src, size_t n) } } RBIMPL_SYMBOL_EXPORT_END() +#undef memcpy +#define memcpy ruby_nonempty_memcpy +#endif #endif /* RBIMPL_MEMORY_H */ diff --git a/include/ruby/internal/newobj.h b/include/ruby/internal/newobj.h index ba1d7cbe59..a8a5557a25 100644 --- a/include/ruby/internal/newobj.h +++ b/include/ruby/internal/newobj.h @@ -172,8 +172,6 @@ RBIMPL_ATTR_DEPRECATED(("This is no longer how Object#clone works.")) static inline void rb_clone_setup(VALUE clone, VALUE obj) { - (void)clone; - (void)obj; return; } @@ -191,8 +189,6 @@ RBIMPL_ATTR_DEPRECATED(("This is no longer how Object#dup works.")) static inline void rb_dup_setup(VALUE dup, VALUE obj) { - (void)dup; - (void)obj; return; } diff --git a/include/ruby/internal/rgengc.h b/include/ruby/internal/rgengc.h new file mode 100644 index 0000000000..7ea04442f6 --- /dev/null +++ b/include/ruby/internal/rgengc.h @@ -0,0 +1,443 @@ +#ifndef RBIMPL_RGENGC_H /*-*-C++-*-vi:se ft=cpp:*/ +#define RBIMPL_RGENGC_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 RGENGC write-barrier APIs. + * @see Sasada, K., "Gradual write-barrier insertion into a Ruby + * interpreter", in proceedings of the 2019 ACM SIGPLAN + * International Symposium on Memory Management (ISMM 2019), pp + * 115-121, 2019. https://doi.org/10.1145/3315573.3329986 + */ +#include "ruby/internal/attr/artificial.h" +#include "ruby/internal/attr/maybe_unused.h" +#include "ruby/internal/attr/pure.h" +#include "ruby/internal/dllexport.h" +#include "ruby/internal/special_consts.h" +#include "ruby/internal/stdbool.h" +#include "ruby/internal/value.h" +#include "ruby/assert.h" + +/** + * @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. + */ +#undef USE_RGENGC +#define USE_RGENGC 1 + +/** + * @private + * + * This is a compile-time flag to enable/disable incremental GC feature. It + * has to be set at the time ruby itself compiles. Makes no sense for 3rd + * parties. It is safe for them to set this though; that just doesn't change + * anything. + */ +#ifndef USE_RINCGC +# define USE_RINCGC 1 +#endif + +/** + * @deprecated This macro seems broken. Setting this to anything other than + * zero just doesn't compile. We need to KonMari. + */ +#ifndef USE_RGENGC_LOGGING_WB_UNPROTECT +# define USE_RGENGC_LOGGING_WB_UNPROTECT 0 +#endif + +/** + * @private + * + * This is a compile-time flag to enable/disable write barrier for + * struct ::RArray. It has to be set at the time ruby itself compiles. Makes + * no sense for 3rd parties. + */ +#ifndef RGENGC_WB_PROTECTED_ARRAY +# define RGENGC_WB_PROTECTED_ARRAY 1 +#endif + +/** + * @private + * + * This is a compile-time flag to enable/disable write barrier for + * struct ::RHash. It has to be set at the time ruby itself compiles. Makes + * no sense for 3rd parties. + */ +#ifndef RGENGC_WB_PROTECTED_HASH +# define RGENGC_WB_PROTECTED_HASH 1 +#endif + +/** + * @private + * + * This is a compile-time flag to enable/disable write barrier for + * struct ::RStruct. It has to be set at the time ruby itself compiles. Makes + * no sense for 3rd parties. + */ +#ifndef RGENGC_WB_PROTECTED_STRUCT +# define RGENGC_WB_PROTECTED_STRUCT 1 +#endif + +/** + * @private + * + * This is a compile-time flag to enable/disable write barrier for + * struct ::RString. It has to be set at the time ruby itself compiles. Makes + * no sense for 3rd parties. + */ +#ifndef RGENGC_WB_PROTECTED_STRING +# define RGENGC_WB_PROTECTED_STRING 1 +#endif + +/** + * @private + * + * This is a compile-time flag to enable/disable write barrier for + * struct ::RObject. It has to be set at the time ruby itself compiles. Makes + * no sense for 3rd parties. + */ +#ifndef RGENGC_WB_PROTECTED_OBJECT +# define RGENGC_WB_PROTECTED_OBJECT 1 +#endif + +/** + * @private + * + * This is a compile-time flag to enable/disable write barrier for + * struct ::RRegexp. It has to be set at the time ruby itself compiles. Makes + * no sense for 3rd parties. + */ +#ifndef RGENGC_WB_PROTECTED_REGEXP +# define RGENGC_WB_PROTECTED_REGEXP 1 +#endif + +/** + * @private + * + * This is a compile-time flag to enable/disable write barrier for + * struct ::RClass. It has to be set at the time ruby itself compiles. Makes + * no sense for 3rd parties. + */ +#ifndef RGENGC_WB_PROTECTED_CLASS +# define RGENGC_WB_PROTECTED_CLASS 1 +#endif + +/** + * @private + * + * This is a compile-time flag to enable/disable write barrier for + * struct ::RFloat. It has to be set at the time ruby itself compiles. Makes + * no sense for 3rd parties. + */ +#ifndef RGENGC_WB_PROTECTED_FLOAT +# define RGENGC_WB_PROTECTED_FLOAT 1 +#endif + +/** + * @private + * + * This is a compile-time flag to enable/disable write barrier for + * struct ::RComplex. It has to be set at the time ruby itself compiles. + * Makes no sense for 3rd parties. + */ +#ifndef RGENGC_WB_PROTECTED_COMPLEX +# define RGENGC_WB_PROTECTED_COMPLEX 1 +#endif + +/** + * @private + * + * This is a compile-time flag to enable/disable write barrier for + * struct ::RRational. It has to be set at the time ruby itself compiles. + * Makes no sense for 3rd parties. + */ +#ifndef RGENGC_WB_PROTECTED_RATIONAL +# define RGENGC_WB_PROTECTED_RATIONAL 1 +#endif + +/** + * @private + * + * This is a compile-time flag to enable/disable write barrier for + * struct ::RBignum. It has to be set at the time ruby itself compiles. Makes + * no sense for 3rd parties. + */ +#ifndef RGENGC_WB_PROTECTED_BIGNUM +# define RGENGC_WB_PROTECTED_BIGNUM 1 +#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 + * + * @shyouhei doesn't think anybody uses this right now. + */ +#ifndef RGENGC_WB_PROTECTED_NODE_CREF +# define RGENGC_WB_PROTECTED_NODE_CREF 1 +#endif + +/** + * @defgroup rgengc Write barrier (WB) interfaces: + * + * @note The following core interfaces can be changed in the future. Please + * catch up if you want to insert WB into C-extensions correctly. + * + * @{ + */ + +/** + * Declaration of a "back" pointer. This is a write barrier for new reference + * from "old" generation to "young" generation. It writes `young` into + * `*slot`, which is a pointer inside of `old`. + * + * @param[in] old An old object. + * @param[in] slot A pointer inside of `old`. + * @param[out] young A young object. + */ +#define RB_OBJ_WRITE(old, slot, young) \ + RBIMPL_CAST(rb_obj_write((VALUE)(old), (VALUE *)(slot), (VALUE)(young), __FILE__, __LINE__)) + +/** + * Identical to #RB_OBJ_WRITE(), except it doesn't write any values, but only a + * WB declaration. `oldv` is replaced value with `b` (not used in current + * Ruby). + * + * @param[in] old An old object. + * @param[in] oldv An object previously stored inside of `old`. + * @param[out] young A young object. + */ +#define RB_OBJ_WRITTEN(old, oldv, young) \ + RBIMPL_CAST(rb_obj_written((VALUE)(old), (VALUE)(oldv), (VALUE)(young), __FILE__, __LINE__)) +/** @} */ + +#define OBJ_PROMOTED_RAW RB_OBJ_PROMOTED_RAW /**< @old{RB_OBJ_PROMOTED_RAW} */ +#define OBJ_PROMOTED RB_OBJ_PROMOTED /**< @old{RB_OBJ_PROMOTED} */ +#define OBJ_WB_UNPROTECT RB_OBJ_WB_UNPROTECT /**< @old{RB_OBJ_WB_UNPROTECT} */ + +/** + * Asserts that the passed object is not fenced by write barriers. Objects of + * such property do not contribute to generational GCs. They are scanned + * always. + * + * @param[out] x An object that would not be protected by the barrier. + */ +#define RB_OBJ_WB_UNPROTECT(x) rb_obj_wb_unprotect(x, __FILE__, __LINE__) + +/** + * Identical to #RB_OBJ_WB_UNPROTECT(), except it can also assert that the + * given object is of given type. + * + * @param[in] type One of `ARRAY`, `STRING`, etc. + * @param[out] obj An object of `type` that would not be protected. + * + * @internal + * + * @shyouhei doesn't understand why this has to be visible from extensions. + */ +#define RB_OBJ_WB_UNPROTECT_FOR(type, obj) \ + (RGENGC_WB_PROTECTED_##type ? OBJ_WB_UNPROTECT(obj) : obj) + +/** + * @private + * + * This is an implementation detail of rb_obj_wb_unprotect(). People don't use + * it directly. + */ +#define RGENGC_LOGGING_WB_UNPROTECT rb_gc_unprotect_logging + +/** @cond INTERNAL_MACRO */ +#define RB_OBJ_PROMOTED_RAW RB_OBJ_PROMOTED_RAW +#define RB_OBJ_PROMOTED RB_OBJ_PROMOTED +/** @endcond */ + +RBIMPL_SYMBOL_EXPORT_BEGIN() +/** + * This is the implementation of #RB_OBJ_WRITE(). People don't use it + * directly. + * + * @param[in] old An object that points to `young`. + * @param[out] young An object that is referenced from `old`. + */ +void rb_gc_writebarrier(VALUE old, VALUE young); + +/** + * This is the implementation of #RB_OBJ_WB_UNPROTECT(). People don't use it + * directly. + * + * @param[out] obj An object that does not participate in WB. + */ +void rb_gc_writebarrier_unprotect(VALUE obj); + +#if USE_RGENGC_LOGGING_WB_UNPROTECT +/** + * @private + * + * This is the implementation of #RGENGC_LOGGING_WB_UNPROTECT(). People + * don't use it directly. + * + * @param[in] objptr Don't know why this is a pointer to void but in + * reality this is a pointer to an object that is about + * to be un-protected. + * @param[in] filename Pass C's `__FILE__` here. + * @param[in] line Pass C's `__LINE__` here. + */ +void rb_gc_unprotect_logging(void *objptr, const char *filename, int line); +#endif + +RBIMPL_SYMBOL_EXPORT_END() + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +/** + * This is the implementation of #RB_OBJ_PROMOTED(). People don't use it + * directly. + * + * @param[in] obj An object to query. + * @retval true The object is "promoted". + * @retval false The object is young. Have not experienced GC at all. + */ +static inline bool +RB_OBJ_PROMOTED_RAW(VALUE obj) +{ + RBIMPL_ASSERT_OR_ASSUME(RB_FL_ABLE(obj)); + return RB_FL_ANY_RAW(obj, RUBY_FL_PROMOTED); +} + +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +/** + * Tests if the object is "promoted" -- that is, whether the object experienced + * one or more GC marks. + * + * @param[in] obj An object to query. + * @retval true The object is "promoted". + * @retval false The object is young. Have not experienced GC at all. + * @note Hello, is anyone actively calling this function? @shyouhei have + * never seen any actual usages outside of the GC implementation + * itself. + */ +static inline bool +RB_OBJ_PROMOTED(VALUE obj) +{ + if (! RB_FL_ABLE(obj)) { + return false; + } + else { + return RB_OBJ_PROMOTED_RAW(obj); + } +} + +/** + * This is the implementation of #RB_OBJ_WB_UNPROTECT(). People don't use it + * directly. + * + * @param[out] x An object that does not participate in WB. + * @param[in] filename C's `__FILE__` of the caller function. + * @param[in] line C's `__LINE__` of the caller function. + * @return x + */ +static inline VALUE +rb_obj_wb_unprotect( + VALUE x, + RBIMPL_ATTR_MAYBE_UNUSED() + const char *filename, + RBIMPL_ATTR_MAYBE_UNUSED() + int line) +{ +#if USE_RGENGC_LOGGING_WB_UNPROTECT + RGENGC_LOGGING_WB_UNPROTECT(RBIMPL_CAST((void *)x), filename, line); +#endif + rb_gc_writebarrier_unprotect(x); + return x; +} + +/** + * @private + * + * This is the implementation of #RB_OBJ_WRITTEN(). People don't use it + * directly. + * + * @param[in] a An old object. + * @param[in] oldv An object previously stored inside of `old`. + * @param[out] b A young object. + * @param[in] filename C's `__FILE__` of the caller function. + * @param[in] line C's `__LINE__` of the caller function. + * @return a + */ +static inline VALUE +rb_obj_written( + VALUE a, + RBIMPL_ATTR_MAYBE_UNUSED() + VALUE oldv, + VALUE b, + RBIMPL_ATTR_MAYBE_UNUSED() + const char *filename, + RBIMPL_ATTR_MAYBE_UNUSED() + int line) +{ +#if USE_RGENGC_LOGGING_WB_UNPROTECT + RGENGC_LOGGING_OBJ_WRITTEN(a, oldv, b, filename, line); +#endif + + if (!RB_SPECIAL_CONST_P(b)) { + rb_gc_writebarrier(a, b); + } + + return a; +} + +/** + * @private + * + * This is the implementation of #RB_OBJ_WRITE(). People don't use it + * directly. + * + * @param[in] a An old object. + * @param[in] slot A pointer inside of `old`. + * @param[out] b A young object. + * @param[in] filename C's `__FILE__` of the caller function. + * @param[in] line C's `__LINE__` of the caller function. + * @return a + */ +static inline VALUE +rb_obj_write( + VALUE a, VALUE *slot, VALUE b, + RBIMPL_ATTR_MAYBE_UNUSED() + const char *filename, + RBIMPL_ATTR_MAYBE_UNUSED() + int line) +{ +#ifdef RGENGC_LOGGING_WRITE + RGENGC_LOGGING_WRITE(a, slot, b, filename, line); +#endif + + *slot = b; + + rb_obj_written(a, RUBY_Qundef /* ignore `oldv' now */, b, filename, line); + return a; +} + +#endif /* RBIMPL_RGENGC_H */ diff --git a/include/ruby/internal/scan_args.h b/include/ruby/internal/scan_args.h index 1ed2bf6368..cf5b18f77d 100644 --- a/include/ruby/internal/scan_args.h +++ b/include/ruby/internal/scan_args.h @@ -100,7 +100,7 @@ RBIMPL_ATTR_NONNULL((2, 3)) * param-arg-spec := pre-arg-spec [post-arg-spec] / post-arg-spec / * pre-opt-post-arg-spec * pre-arg-spec := num-of-leading-mandatory-args - * [num-of-optional-args] + [num-of-optional-args] * post-arg-spec := sym-for-variable-length-args * [num-of-trailing-mandatory-args] * pre-opt-post-arg-spec := num-of-leading-mandatory-args num-of-optional-args diff --git a/include/ruby/internal/special_consts.h b/include/ruby/internal/special_consts.h index dc0a6b41d6..38934e4da3 100644 --- a/include/ruby/internal/special_consts.h +++ b/include/ruby/internal/special_consts.h @@ -76,8 +76,6 @@ #define RB_SPECIAL_CONST_P RB_SPECIAL_CONST_P #define RB_STATIC_SYM_P RB_STATIC_SYM_P #define RB_TEST RB_TEST -#define RB_UNDEF_P RB_UNDEF_P -#define RB_NIL_OR_UNDEF_P RB_NIL_OR_UNDEF_P /** @endcond */ /** special constants - i.e. non-zero and non-fixnum constants */ @@ -96,9 +94,9 @@ ruby_special_consts { RUBY_SYMBOL_FLAG, /**< Flag to denote a static symbol. */ #elif USE_FLONUM RUBY_Qfalse = 0x00, /* ...0000 0000 */ - RUBY_Qnil = 0x04, /* ...0000 0100 */ RUBY_Qtrue = 0x14, /* ...0001 0100 */ - RUBY_Qundef = 0x24, /* ...0010 0100 */ + RUBY_Qnil = 0x08, /* ...0000 1000 */ + RUBY_Qundef = 0x34, /* ...0011 0100 */ RUBY_IMMEDIATE_MASK = 0x07, /* ...0000 0111 */ RUBY_FIXNUM_FLAG = 0x01, /* ...xxxx xxx1 */ RUBY_FLONUM_MASK = 0x03, /* ...0000 0011 */ @@ -106,14 +104,14 @@ ruby_special_consts { RUBY_SYMBOL_FLAG = 0x0c, /* ...xxxx 1100 */ #else RUBY_Qfalse = 0x00, /* ...0000 0000 */ - RUBY_Qnil = 0x02, /* ...0000 0010 */ - RUBY_Qtrue = 0x06, /* ...0000 0110 */ - RUBY_Qundef = 0x0a, /* ...0000 1010 */ + RUBY_Qtrue = 0x02, /* ...0000 0010 */ + RUBY_Qnil = 0x04, /* ...0000 0100 */ + RUBY_Qundef = 0x06, /* ...0000 0110 */ RUBY_IMMEDIATE_MASK = 0x03, /* ...0000 0011 */ RUBY_FIXNUM_FLAG = 0x01, /* ...xxxx xxx1 */ RUBY_FLONUM_MASK = 0x00, /* any values ANDed with FLONUM_MASK cannot be FLONUM_FLAG */ RUBY_FLONUM_FLAG = 0x02, /* ...0000 0010 */ - RUBY_SYMBOL_FLAG = 0x0e, /* ...xxxx 1110 */ + RUBY_SYMBOL_FLAG = 0x0e, /* ...0000 1110 */ #endif RUBY_SPECIAL_SHIFT = 8 /**< Least significant 8 bits are reserved. */ @@ -138,21 +136,12 @@ static inline bool RB_TEST(VALUE obj) { /* - * if USE_FLONUM * Qfalse: ....0000 0000 - * Qnil: ....0000 0100 - * ~Qnil: ....1111 1011 + * Qnil: ....0000 1000 + * ~Qnil: ....1111 0111 * v ....xxxx xxxx * ---------------------------- - * RTEST(v) ....xxxx x0xx - * - * if ! USE_FLONUM - * Qfalse: ....0000 0000 - * Qnil: ....0000 0010 - * ~Qnil: ....1111 1101 - * v ....xxxx xxxx - * ---------------------------- - * RTEST(v) ....xxxx xx0x + * RTEST(v) ....xxxx 0xxx * * RTEST(v) can be 0 if and only if (v == Qfalse || v == Qnil). */ @@ -179,62 +168,6 @@ RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() /** - * Checks if the given object is undef. - * - * @param[in] obj An arbitrary ruby object. - * @retval true `obj` is ::RUBY_Qundef. - * @retval false Anything else. - */ -static inline bool -RB_UNDEF_P(VALUE obj) -{ - return obj == RUBY_Qundef; -} - -RBIMPL_ATTR_CONST() -RBIMPL_ATTR_CONSTEXPR(CXX14) -RBIMPL_ATTR_ARTIFICIAL() -/** - * Checks if the given object is nil or undef. Can be used to see if - * a keyword argument is not given or given `nil`. - * - * @param[in] obj An arbitrary ruby object. - * @retval true `obj` is ::RUBY_Qnil or ::RUBY_Qundef. - * @retval false Anything else. - */ -static inline bool -RB_NIL_OR_UNDEF_P(VALUE obj) -{ - /* - * if USE_FLONUM - * Qundef: ....0010 0100 - * Qnil: ....0000 0100 - * mask: ....1101 1111 - * common_bits: ....0000 0100 - * --------------------------------- - * Qnil & mask ....0000 0100 - * Qundef & mask ....0000 0100 - * - * if ! USE_FLONUM - * Qundef: ....0000 1010 - * Qnil: ....0000 0010 - * mask: ....1111 0111 - * common_bits: ....0000 0010 - * ---------------------------- - * Qnil & mask ....0000 0010 - * Qundef & mask ....0000 0010 - * - * NIL_OR_UNDEF_P(v) can be true only when v is Qundef or Qnil. - */ - const VALUE mask = ~(RUBY_Qundef ^ RUBY_Qnil); - const VALUE common_bits = RUBY_Qundef & RUBY_Qnil; - return (obj & mask) == common_bits; -} - -RBIMPL_ATTR_CONST() -RBIMPL_ATTR_CONSTEXPR(CXX11) -RBIMPL_ATTR_ARTIFICIAL() -/** * Checks if the given object is a so-called Fixnum. * * @param[in] obj An arbitrary ruby object. @@ -326,7 +259,7 @@ RBIMPL_ATTR_ARTIFICIAL() static inline bool RB_SPECIAL_CONST_P(VALUE obj) { - return RB_IMMEDIATE_P(obj) || obj == RUBY_Qfalse; + return RB_IMMEDIATE_P(obj) || ! RB_TEST(obj); } RBIMPL_ATTR_CONST() diff --git a/include/ruby/internal/stdbool.h b/include/ruby/internal/stdbool.h index 1ca61136ba..b15321cb00 100644 --- a/include/ruby/internal/stdbool.h +++ b/include/ruby/internal/stdbool.h @@ -39,7 +39,7 @@ # /* Take stdbool.h definition. */ # include <stdbool.h> -#elif !defined(HAVE__BOOL) +#else typedef unsigned char _Bool; # /* See also http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2229.htm */ # define bool _Bool diff --git a/include/ruby/internal/variable.h b/include/ruby/internal/variable.h index c017ffe3f7..1f84b92db0 100644 --- a/include/ruby/internal/variable.h +++ b/include/ruby/internal/variable.h @@ -147,7 +147,7 @@ RBIMPL_ATTR_NONNULL(()) * init_Foo(void) * { * foo = rb_eval_string("..."); - * rb_define_variable("$foo", &foo); + * rb_define_global_variable("$foo", &foo); * } * ``` * diff --git a/include/ruby/io.h b/include/ruby/io.h index e9dfeda5b1..3e035c114d 100644 --- a/include/ruby/io.h +++ b/include/ruby/io.h @@ -35,11 +35,7 @@ # undef revents # endif # define RB_WAITFD_IN POLLIN -# if defined(POLLPRI) -# define RB_WAITFD_PRI POLLPRI -# else -# define RB_WAITFD_PRI 0 -# endif +# define RB_WAITFD_PRI POLLPRI # define RB_WAITFD_OUT POLLOUT #else # define RB_WAITFD_IN 0x001 @@ -49,17 +45,11 @@ /** @endcond */ #include "ruby/internal/attr/const.h" -#include "ruby/internal/attr/packed_struct.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/attr/noreturn.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" - -// IO#wait, IO#wait_readable, IO#wait_writable, IO#wait_priority are defined by this implementation. -#define RUBY_IO_WAIT_METHODS - -// Used as the default timeout argument to `rb_io_wait` to use the `IO#timeout` value. -#define RUBY_IO_TIMEOUT_DEFAULT Qnil +#include "ruby/backward/2/attributes.h" /* PACKED_STRUCT_UNALIGNED */ RBIMPL_SYMBOL_EXPORT_BEGIN() @@ -67,31 +57,23 @@ struct stat; struct timeval; /** - * Indicates that a timeout has occurred while performing an IO operation. - */ -RUBY_EXTERN VALUE rb_eIOTimeoutError; - -/** * Type of events that an IO can wait. * * @internal * * This is visible from extension libraries because `io/wait` wants it. */ -enum rb_io_event { +typedef enum { RUBY_IO_READABLE = RB_WAITFD_IN, /**< `IO::READABLE` */ RUBY_IO_WRITABLE = RB_WAITFD_OUT, /**< `IO::WRITABLE` */ RUBY_IO_PRIORITY = RB_WAITFD_PRI, /**< `IO::PRIORITY` */ -}; - -typedef enum rb_io_event rb_io_event_t; +} rb_io_event_t; /** * IO buffers. This is an implementation detail of ::rb_io_t::wbuf and * ::rb_io_t::rbuf. People don't manipulate it directly. */ -RBIMPL_ATTR_PACKED_STRUCT_UNALIGNED_BEGIN() -struct rb_io_internal_buffer { +PACKED_STRUCT_UNALIGNED(struct rb_io_buffer_t { /** Pointer to the underlying memory region, of at least `capa` bytes. */ char *ptr; /* off + len <= capa */ @@ -104,84 +86,45 @@ struct rb_io_internal_buffer { /** Designed capacity of the buffer. */ int capa; -} RBIMPL_ATTR_PACKED_STRUCT_UNALIGNED_END(); +}); /** @alias{rb_io_buffer_t} */ -typedef struct rb_io_internal_buffer rb_io_buffer_t; - -/** Decomposed encoding flags (e.g. `"enc:enc2""`). */ -/* - * enc enc2 read action write action - * NULL NULL force_encoding(default_external) write the byte sequence of str - * e1 NULL force_encoding(e1) convert str.encoding to e1 - * e1 e2 convert from e2 to e1 convert str.encoding to e2 - */ -struct rb_io_encoding { - /** Internal encoding. */ - rb_encoding *enc; - /** External encoding. */ - rb_encoding *enc2; - /** - * Flags. - * - * @see enum ::ruby_econv_flag_type - */ - int ecflags; - /** - * Flags as Ruby hash. - * - * @internal - * - * This is set. But used from nowhere maybe? - */ - VALUE ecopts; -}; +typedef struct rb_io_buffer_t rb_io_buffer_t; -#ifndef HAVE_RB_IO_T -#define HAVE_RB_IO_T 1 /** Ruby's IO, metadata and buffers. */ -struct rb_io { +typedef struct rb_io_t { + /** The IO's Ruby level counterpart. */ - RBIMPL_ATTR_DEPRECATED(("with no replacement")) VALUE self; /** stdio ptr for read/write, if available. */ - RBIMPL_ATTR_DEPRECATED(("with no replacement")) FILE *stdio_file; /** file descriptor. */ - RBIMPL_ATTR_DEPRECATED(("rb_io_descriptor")) int fd; /** mode flags: FMODE_XXXs */ - RBIMPL_ATTR_DEPRECATED(("rb_io_mode")) int mode; /** child's pid (for pipes) */ - RBIMPL_ATTR_DEPRECATED(("with no replacement")) rb_pid_t pid; /** number of lines read */ - RBIMPL_ATTR_DEPRECATED(("with no replacement")) int lineno; /** pathname for file */ - RBIMPL_ATTR_DEPRECATED(("rb_io_path")) VALUE pathv; /** finalize proc */ - RBIMPL_ATTR_DEPRECATED(("with no replacement")) - void (*finalize)(struct rb_io*,int); + void (*finalize)(struct rb_io_t*,int); /** Write buffer. */ - RBIMPL_ATTR_DEPRECATED(("with no replacement")) rb_io_buffer_t wbuf; /** * (Byte) read buffer. Note also that there is a field called * ::rb_io_t::cbuf, which also concerns read IO. */ - RBIMPL_ATTR_DEPRECATED(("with no replacement")) rb_io_buffer_t rbuf; /** @@ -189,25 +132,49 @@ struct rb_io { * * @see rb_io_set_write_io() */ - RBIMPL_ATTR_DEPRECATED(("rb_io_get_write_io")) VALUE tied_io_for_writing; - RBIMPL_ATTR_DEPRECATED(("with no replacement")) - struct rb_io_encoding encs; /**< Decomposed encoding flags. */ + /** Decomposed encoding flags (e.g. `"enc:enc2""`). */ + /* + * enc enc2 read action write action + * NULL NULL force_encoding(default_external) write the byte sequence of str + * e1 NULL force_encoding(e1) convert str.encoding to e1 + * e1 e2 convert from e2 to e1 convert str.encoding to e2 + */ + struct rb_io_enc_t { + /** Internal encoding. */ + rb_encoding *enc; + + /** External encoding. */ + rb_encoding *enc2; + + /** + * Flags. + * + * @see enum ::ruby_econv_flag_type + */ + int ecflags; + + /** + * Flags as Ruby hash. + * + * @internal + * + * This is set. But used from nowhere maybe? + */ + VALUE ecopts; + } encs; /**< Decomposed encoding flags. */ /** Encoding converter used when reading from this IO. */ - RBIMPL_ATTR_DEPRECATED(("with no replacement")) rb_econv_t *readconv; /** * rb_io_ungetc() destination. This buffer is read before checking * ::rb_io_t::rbuf */ - RBIMPL_ATTR_DEPRECATED(("with no replacement")) rb_io_buffer_t cbuf; /** Encoding converter used when writing to this IO. */ - RBIMPL_ATTR_DEPRECATED(("with no replacement")) rb_econv_t *writeconv; /** @@ -216,25 +183,21 @@ struct rb_io { * conversion from encoding X to encoding Y does not exist, Ruby finds an * encoding Z that bridges the two, so that X to Z to Y conversion happens. */ - RBIMPL_ATTR_DEPRECATED(("with no replacement")) VALUE writeconv_asciicompat; /** Whether ::rb_io_t::writeconv is already set up. */ - RBIMPL_ATTR_DEPRECATED(("with no replacement")) int writeconv_initialized; /** * Value of ::rb_io_t::rb_io_enc_t::ecflags stored right before * initialising ::rb_io_t::writeconv. */ - RBIMPL_ATTR_DEPRECATED(("with no replacement")) int writeconv_pre_ecflags; /** * Value of ::rb_io_t::rb_io_enc_t::ecopts stored right before initialising * ::rb_io_t::writeconv. */ - RBIMPL_ATTR_DEPRECATED(("with no replacement")) VALUE writeconv_pre_ecopts; /** @@ -244,21 +207,20 @@ struct rb_io { * * This of course doesn't help inter-process IO interleaves, though. */ - RBIMPL_ATTR_DEPRECATED(("with no replacement")) VALUE write_lock; - - /** - * The timeout associated with this IO when performing blocking operations. - */ - RBIMPL_ATTR_DEPRECATED(("rb_io_timeout/rb_io_set_timeout")) - VALUE timeout; -}; -#endif - -typedef struct rb_io rb_io_t; +} rb_io_t; /** @alias{rb_io_enc_t} */ -typedef struct rb_io_encoding rb_io_enc_t; +typedef struct rb_io_enc_t rb_io_enc_t; + +/** + * @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. + */ +#define HAVE_RB_IO_T 1 /** * @name Possible flags for ::rb_io_t::mode @@ -349,16 +311,7 @@ typedef struct rb_io_encoding rb_io_enc_t; * Setting this one and #FMODE_BINMODE at the same time is a contradiction. */ #define FMODE_TEXTMODE 0x00001000 -/** - * This flag means that an IO object is wrapping an "external" file descriptor, - * which is owned by something outside the Ruby interpreter (usually a C extension). - * Ruby will not close this file when the IO object is garbage collected. - * If this flag is set, then IO#autoclose? is false, and vice-versa. - * - * This flag was previously called FMODE_PREP internally. - */ -#define FMODE_EXTERNAL 0x00010000 - +/* #define FMODE_PREP 0x00010000 */ /* #define FMODE_SIGNAL_ON_EPIPE 0x00020000 */ /** @@ -373,18 +326,6 @@ typedef struct rb_io_encoding rb_io_enc_t; /** @} */ /** - * Allocate a new IO object, with the given file descriptor. - */ -VALUE rb_io_open_descriptor(VALUE klass, int descriptor, int mode, VALUE path, VALUE timeout, struct rb_io_encoding *encoding); - -/** - * Returns whether or not the underlying IO is closed. - * - * @return Whether the underlying IO is closed. - */ -VALUE rb_io_closed_p(VALUE io); - -/** * Queries the underlying IO pointer. * * @param[in] obj An IO object. @@ -454,14 +395,14 @@ rb_io_t *rb_io_make_open_file(VALUE obj); * like this: * * ```CXX - * typedef struct rb_io { + * typedef struct rb_io_t { * FILE *f; // stdio ptr for read/write * FILE *f2; // additional ptr for rw pipes * int mode; // mode flags * int pid; // child's pid (for pipes) * int lineno; // number of lines read * char *path; // pathname for file - * void (*finalize) _((struct rb_io*,int)); // finalize proc + * void (*finalize) _((struct rb_io_t*,int)); // finalize proc * } rb_io_t; *``` * @@ -707,23 +648,10 @@ VALUE rb_io_get_write_io(VALUE io); VALUE rb_io_set_write_io(VALUE io, VALUE w); /** - * Instructs the OS to put its internal file structure into "nonblocking mode". - * This is an in-Kernel concept. Reading from/writing to that file using C - * function calls would return -1 with errno set. However when it comes to a - * ruby program, we hide that error behind our `IO#read` method. Ruby level - * `IO#read` blocks regardless of this flag. If you want to avoid blocking, - * you should consider using methods like `IO#readpartial`. - * - * ```ruby - * require 'io/nonblock' - * STDIN.nonblock = true - * STDIN.gets # blocks. - * ``` - * - * As of writing there is a room of this API in Fiber schedulers. A Fiber - * scheduler could be written in a way its behaviour depends on this property. - * You need an in-depth understanding of how schedulers work to properly - * leverage this, though. + * Sets an IO to a "nonblock mode". This amends the way an IO operates so that + * instead of waiting for rooms for read/write, it returns errors. In case of + * multiplexed IO situations it can be vital for IO operations not to block. + * This is the key API to achieve that property. * * @note Note however that nonblocking-ness propagates across process * boundaries. You must really carefully watch your step when turning @@ -743,12 +671,6 @@ VALUE rb_io_set_write_io(VALUE io, VALUE w); void rb_io_set_nonblock(rb_io_t *fptr); /** - * Returns the path for the given IO. - * - */ -VALUE rb_io_path(VALUE io); - -/** * Returns an integer representing the numeric file descriptor for * <em>io</em>. * @@ -758,12 +680,6 @@ VALUE rb_io_path(VALUE io); int rb_io_descriptor(VALUE io); /** - * Get the mode of the IO. - * - */ -int rb_io_mode(VALUE io); - -/** * This function breaks down the option hash that `IO#initialize` takes into * components. This is an implementation detail of rb_io_extract_modeenc() * today. People prefer that API instead. @@ -910,37 +826,13 @@ int rb_io_wait_writable(int fd); int rb_wait_for_single_fd(int fd, int events, struct timeval *tv); /** - * Get the timeout associated with the specified io object. - * - * @param[in] io An IO object. - * @retval RUBY_Qnil There is no associated timeout. - * @retval Otherwise The timeout value. - */ -VALUE rb_io_timeout(VALUE io); - -/** - * Set the timeout associated with the specified io object. This timeout is - * used as a best effort timeout to prevent operations from blocking forever. - * - * @param[in] io An IO object. - * @param[in] timeout A timeout value. Must respond to #to_f. - * @ - */ -VALUE rb_io_set_timeout(VALUE io, VALUE timeout); - -/** * Blocks until the passed IO is ready for the passed events. The "events" * here is a Ruby level integer, which is an OR-ed value of `IO::READABLE`, * `IO::WRITable`, and `IO::PRIORITY`. * - * If timeout is `Qnil`, it will use the default timeout as given by - * `rb_io_timeout(io)`. - * * @param[in] io An IO object to wait. * @param[in] events See above. * @param[in] timeout Time, or numeric seconds since UNIX epoch. - * If Qnil, use the default timeout. If Qfalse - * or Qundef, wait forever. * @exception rb_eIOError `io` is not open. * @exception rb_eRangeError `timeout` is out of range. * @exception rb_eSystemCallError `select(2)` failed for some reason. @@ -992,8 +884,13 @@ VALUE rb_io_maybe_wait(int error, VALUE io, VALUE events, VALUE timeout); * @exception rb_eIOError `io` is not open. * @exception rb_eRangeError `timeout` is out of range. * @exception rb_eSystemCallError `select(2)` failed for some reason. - * @retval 0 Operation timed out. - * @retval Otherwise Always returns ::RUBY_IO_READABLE. + * @exception rb_eTypeError Operation timed out. + * @return Always returns ::RUBY_IO_READABLE. + * + * @internal + * + * Because rb_io_maybe_wait() returns ::RUBY_Qfalse on timeout, this function + * fails to convert that value to `int`, and raises ::rb_eTypeError. */ int rb_io_maybe_wait_readable(int error, VALUE io, VALUE timeout); @@ -1008,8 +905,13 @@ int rb_io_maybe_wait_readable(int error, VALUE io, VALUE timeout); * @exception rb_eIOError `io` is not open. * @exception rb_eRangeError `timeout` is out of range. * @exception rb_eSystemCallError `select(2)` failed for some reason. - * @retval 0 Operation timed out. - * @retval Otherwise Always returns ::RUBY_IO_WRITABLE. + * @exception rb_eTypeError Operation timed out. + * @return Always returns ::RUBY_IO_WRITABLE. + * + * @internal + * + * Because rb_io_maybe_wait() returns ::RUBY_Qfalse on timeout, this function + * fails to convert that value to `int`, and raises ::rb_eTypeError. */ int rb_io_maybe_wait_writable(int error, VALUE io, VALUE timeout); diff --git a/include/ruby/io/buffer.h b/include/ruby/io/buffer.h index b044db0539..4763b88cce 100644 --- a/include/ruby/io/buffer.h +++ b/include/ruby/io/buffer.h @@ -1,5 +1,5 @@ -#ifndef RUBY_IO_BUFFER_H -#define RUBY_IO_BUFFER_H +#ifndef RUBY_IO_BUFFER_T +#define RUBY_IO_BUFFER_T 1 /** * @file * @author Samuel Williams @@ -21,20 +21,10 @@ RBIMPL_SYMBOL_EXPORT_BEGIN() // WARNING: This entire interface is experimental and may change in the future! #define RB_IO_BUFFER_EXPERIMENTAL 1 -#define RUBY_IO_BUFFER_VERSION 2 - -// The `IO::Buffer` class. RUBY_EXTERN VALUE rb_cIOBuffer; - -// The operating system page size. RUBY_EXTERN size_t RUBY_IO_BUFFER_PAGE_SIZE; - -// The default buffer size, usually a (small) multiple of the page size. -// Can be overridden by the RUBY_IO_BUFFER_DEFAULT_SIZE environment variable. RUBY_EXTERN size_t RUBY_IO_BUFFER_DEFAULT_SIZE; -// Represents the internal state of the buffer. -// More than one flag can be set at a time. enum rb_io_buffer_flags { // The memory in the buffer is owned by someone else. // More specifically, it means that someone else owns the buffer and we shouldn't try to resize it. @@ -45,9 +35,6 @@ enum rb_io_buffer_flags { // A non-private mapping is marked as external. RB_IO_BUFFER_MAPPED = 4, - // A mapped buffer that is also shared. - RB_IO_BUFFER_SHARED = 8, - // The buffer is locked and cannot be resized. // More specifically, it means we can't change the base address or size. // A buffer is typically locked before a system call that uses the data. @@ -57,45 +44,31 @@ enum rb_io_buffer_flags { RB_IO_BUFFER_PRIVATE = 64, // The buffer is read-only and cannot be modified. - RB_IO_BUFFER_READONLY = 128, - - // The buffer is backed by a file. - RB_IO_BUFFER_FILE = 256, + RB_IO_BUFFER_READONLY = 128 }; -// Represents the endian of the data types. enum rb_io_buffer_endian { - // The least significant units are put first. RB_IO_BUFFER_LITTLE_ENDIAN = 4, RB_IO_BUFFER_BIG_ENDIAN = 8, -#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - RB_IO_BUFFER_HOST_ENDIAN = RB_IO_BUFFER_LITTLE_ENDIAN, -#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#if defined(WORDS_BIGENDIAN) RB_IO_BUFFER_HOST_ENDIAN = RB_IO_BUFFER_BIG_ENDIAN, -#elif defined(REG_DWORD) && REG_DWORD == REG_DWORD_LITTLE_ENDIAN +#else RB_IO_BUFFER_HOST_ENDIAN = RB_IO_BUFFER_LITTLE_ENDIAN, -#elif defined(REG_DWORD) && REG_DWORD == REG_DWORD_BIG_ENDIAN - RB_IO_BUFFER_HOST_ENDIAN = RB_IO_BUFFER_BIG_ENDIAN, #endif RB_IO_BUFFER_NETWORK_ENDIAN = RB_IO_BUFFER_BIG_ENDIAN }; VALUE rb_io_buffer_new(void *base, size_t size, enum rb_io_buffer_flags flags); -VALUE rb_io_buffer_map(VALUE io, size_t size, rb_off_t offset, enum rb_io_buffer_flags flags); +VALUE rb_io_buffer_map(VALUE io, size_t size, off_t offset, enum rb_io_buffer_flags flags); VALUE rb_io_buffer_lock(VALUE self); VALUE rb_io_buffer_unlock(VALUE self); int rb_io_buffer_try_unlock(VALUE self); - VALUE rb_io_buffer_free(VALUE self); -VALUE rb_io_buffer_free_locked(VALUE self); -// Access the internal buffer and flags. Validates the pointers. -// The points may not remain valid if the source buffer is manipulated. -// Consider using rb_io_buffer_lock if needed. -enum rb_io_buffer_flags rb_io_buffer_get_bytes(VALUE self, void **base, size_t *size); +int rb_io_buffer_get_bytes(VALUE self, void **base, size_t *size); void rb_io_buffer_get_bytes_for_reading(VALUE self, const void **base, size_t *size); void rb_io_buffer_get_bytes_for_writing(VALUE self, void **base, size_t *size); @@ -104,11 +77,11 @@ void rb_io_buffer_resize(VALUE self, size_t size); void rb_io_buffer_clear(VALUE self, uint8_t value, size_t offset, size_t length); // The length is the minimum required length. -VALUE rb_io_buffer_read(VALUE self, VALUE io, size_t length, size_t offset); -VALUE rb_io_buffer_pread(VALUE self, VALUE io, rb_off_t from, size_t length, size_t offset); -VALUE rb_io_buffer_write(VALUE self, VALUE io, size_t length, size_t offset); -VALUE rb_io_buffer_pwrite(VALUE self, VALUE io, rb_off_t from, size_t length, size_t offset); +VALUE rb_io_buffer_read(VALUE self, VALUE io, size_t length); +VALUE rb_io_buffer_pread(VALUE self, VALUE io, size_t length, off_t offset); +VALUE rb_io_buffer_write(VALUE self, VALUE io, size_t length); +VALUE rb_io_buffer_pwrite(VALUE self, VALUE io, size_t length, off_t offset); RBIMPL_SYMBOL_EXPORT_END() -#endif /* RUBY_IO_BUFFER_H */ +#endif /* RUBY_IO_BUFFER_T */ diff --git a/include/ruby/memory_view.h b/include/ruby/memory_view.h index 42309d5afc..83931038a0 100644 --- a/include/ruby/memory_view.h +++ b/include/ruby/memory_view.h @@ -16,7 +16,7 @@ # include <stddef.h> /* size_t */ #endif -#ifdef HAVE_SYS_TYPES_H +#if HAVE_SYS_TYPES_H # include <sys/types.h> /* ssize_t */ #endif @@ -47,10 +47,10 @@ typedef struct { char format; /** :FIXME: what is a "native" size is unclear. */ - bool native_size_p; + unsigned native_size_p: 1; /** Endian of the component */ - bool little_endian_p; + unsigned little_endian_p: 1; /** The component's offset. */ size_t offset; diff --git a/include/ruby/missing.h b/include/ruby/missing.h index aea6c9088d..1e97e294f1 100644 --- a/include/ruby/missing.h +++ b/include/ruby/missing.h @@ -33,18 +33,6 @@ # include <sys/time.h> #endif -#ifdef HAVE_SYS_STAT_H -# include <sys/stat.h> -#endif - -#ifdef HAVE_UNISTD_H -# include <unistd.h> -#endif - -#ifdef HAVE_STDIO_H -# include <stdio.h> -#endif - #ifdef HAVE_IEEEFP_H # include <ieeefp.h> #endif @@ -236,107 +224,6 @@ RUBY_EXTERN void setproctitle(const char *fmt, ...); RUBY_EXTERN void explicit_bzero(void *b, size_t len); #endif -#ifndef HAVE_TZSET -RUBY_EXTERN void tzset(void); -#endif - -#ifndef HAVE_POSIX_MADVISE -RUBY_EXTERN int posix_madvise(void *, size_t, int); -#endif - -#ifndef HAVE_GETEUID -RUBY_EXTERN rb_uid_t geteuid(void); -#endif - -#ifndef HAVE_GETUID -RUBY_EXTERN rb_uid_t getuid(void); -#endif - -#ifndef HAVE_GETEGID -RUBY_EXTERN rb_gid_t getegid(void); -#endif - -#ifndef HAVE_GETGID -RUBY_EXTERN rb_gid_t getgid(void); -#endif - -#ifndef HAVE_GETLOGIN -RUBY_EXTERN char *getlogin(void); -#endif - -#ifndef HAVE_GETPPID -RUBY_EXTERN rb_pid_t getppid(void); -#endif - -#ifndef HAVE_UMASK -RUBY_EXTERN rb_mode_t umask(rb_mode_t); -#endif - -#ifndef HAVE_CHMOD -RUBY_EXTERN int chmod(const char *, rb_mode_t); -#endif - -#ifndef HAVE_CHOWN -RUBY_EXTERN int chown(const char *, rb_uid_t, rb_gid_t); -#endif - -#ifndef HAVE_PCLOSE -RUBY_EXTERN int pclose(FILE *); -#endif - -#ifndef HAVE_POPEN -RUBY_EXTERN FILE *popen(const char *, const char *); -#endif - -#ifndef HAVE_PIPE -RUBY_EXTERN int pipe(int [2]); -#endif - -#ifndef HAVE_DUP -RUBY_EXTERN int dup(int); -#endif - -#ifndef HAVE_DUP2 -RUBY_EXTERN int dup2(int, int); -#endif - -#ifndef HAVE_KILL -RUBY_EXTERN int kill(rb_pid_t, int); -#endif - -#ifndef HAVE_EXECL -RUBY_EXTERN int execl(const char *, const char *, ...); -#endif - -#ifndef HAVE_EXECLE -RUBY_EXTERN int execle(const char *, const char *, ...); -#endif - -#ifndef HAVE_EXECV -RUBY_EXTERN int execv(const char *, char *const []); -#endif - -#ifndef HAVE_EXECVE -RUBY_EXTERN int execve(const char *, char *const [], char *const []); -#endif - -#ifndef HAVE_SHUTDOWN -RUBY_EXTERN int shutdown(int, int); -#endif - -#ifndef HAVE_SYSTEM -RUBY_EXTERN int system(const char *); -#endif - -#ifndef WNOHANG -# define WNOHANG 0 -#endif - -#ifndef HAVE_WAITPID -# define HAVE_WAITPID 1 -RUBY_EXTERN rb_pid_t waitpid(rb_pid_t, int *, int); -#endif - RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_MISSING_H */ diff --git a/include/ruby/onigmo.h b/include/ruby/onigmo.h index d233336316..6187b37dc3 100644 --- a/include/ruby/onigmo.h +++ b/include/ruby/onigmo.h @@ -356,9 +356,9 @@ int onigenc_ascii_only_case_map(OnigCaseFoldType* flagP, const OnigUChar** pp, c #define ONIGENC_PRECISE_MBC_ENC_LEN(enc,p,e) (enc)->precise_mbc_enc_len(p,e,enc) ONIG_EXTERN -int onigenc_mbclen(const OnigUChar* p,const OnigUChar* e, const struct OnigEncodingTypeST* enc); +int onigenc_mbclen_approximate(const OnigUChar* p,const OnigUChar* e, const struct OnigEncodingTypeST* enc); -#define ONIGENC_MBC_ENC_LEN(enc,p,e) onigenc_mbclen(p,e,enc) +#define ONIGENC_MBC_ENC_LEN(enc,p,e) onigenc_mbclen_approximate(p,e,enc) #define ONIGENC_MBC_MAXLEN(enc) ((enc)->max_enc_len) #define ONIGENC_MBC_MAXLEN_DIST(enc) ONIGENC_MBC_MAXLEN(enc) #define ONIGENC_MBC_MINLEN(enc) ((enc)->min_enc_len) @@ -793,13 +793,6 @@ typedef struct re_pattern_buffer { OnigDistance dmin; /* min-distance of exact or map */ OnigDistance dmax; /* max-distance of exact or map */ - /* rb_hrtime_t from hrtime.h */ -#ifdef MY_RUBY_BUILD_MAY_TIME_TRAVEL - int128_t timelimit; -#else - uint64_t timelimit; -#endif - /* regex_t link chain */ struct re_pattern_buffer* chain; /* escape compile-conflict */ } OnigRegexType; @@ -844,8 +837,6 @@ void onig_free(OnigRegex); ONIG_EXTERN void onig_free_body(OnigRegex); ONIG_EXTERN -int onig_reg_copy(OnigRegex* reg, OnigRegex orig_reg); -ONIG_EXTERN OnigPosition onig_scan(OnigRegex reg, const OnigUChar* str, const OnigUChar* end, OnigRegion* region, OnigOptionType option, int (*scan_callback)(OnigPosition, OnigPosition, OnigRegion*, void*), void* callback_arg); ONIG_EXTERN OnigPosition onig_search(OnigRegex, const OnigUChar* str, const OnigUChar* end, const OnigUChar* start, const OnigUChar* range, OnigRegion* region, OnigOptionType option); @@ -854,8 +845,6 @@ OnigPosition onig_search_gpos(OnigRegex, const OnigUChar* str, const OnigUChar* ONIG_EXTERN OnigPosition onig_match(OnigRegex, const OnigUChar* str, const OnigUChar* end, const OnigUChar* at, OnigRegion* region, OnigOptionType option); ONIG_EXTERN -int onig_check_linear_time(OnigRegex reg); -ONIG_EXTERN OnigRegion* onig_region_new(void); ONIG_EXTERN void onig_region_init(OnigRegion* region); diff --git a/include/ruby/random.h b/include/ruby/random.h index f3df0d96fb..657b37f034 100644 --- a/include/ruby/random.h +++ b/include/ruby/random.h @@ -11,31 +11,11 @@ * * This is a set of APIs to roll your own subclass of ::rb_cRandom. An * illustrative example of such PRNG can be found at - * `ext/-test-/random/loop.c`. + * `ext/-test-/ramdom/loop.c`. */ #include "ruby/ruby.h" -/* - * version - * 0: before versioning; deprecated - * 1: added version, flags and init_32bit function - */ -#define RUBY_RANDOM_INTERFACE_VERSION_MAJOR 1 -#define RUBY_RANDOM_INTERFACE_VERSION_MINOR 0 - -#define RUBY_RANDOM_PASTE_VERSION_SUFFIX(x, y, z) x##_##y##_##z -#define RUBY_RANDOM_WITH_VERSION_SUFFIX(name, major, minor) \ - RUBY_RANDOM_PASTE_VERSION_SUFFIX(name, major, minor) -#define rb_random_data_type \ - RUBY_RANDOM_WITH_VERSION_SUFFIX(rb_random_data_type, \ - RUBY_RANDOM_INTERFACE_VERSION_MAJOR, \ - RUBY_RANDOM_INTERFACE_VERSION_MINOR) -#define RUBY_RANDOM_INTERFACE_VERSION_INITIALIZER \ - {RUBY_RANDOM_INTERFACE_VERSION_MAJOR, RUBY_RANDOM_INTERFACE_VERSION_MINOR} -#define RUBY_RANDOM_INTERFACE_VERSION_MAJOR_MAX 0xff -#define RUBY_RANDOM_INTERFACE_VERSION_MINOR_MAX 0xff - RBIMPL_SYMBOL_EXPORT_BEGIN() /** @@ -68,17 +48,6 @@ typedef void rb_random_init_func(rb_random_t *rng, const uint32_t *buf, size_t l RBIMPL_ATTR_NONNULL(()) /** - * This is the type of functions called when your random object is initialised. - * Passed data is the seed integer. - * - * @param[out] rng Your random struct to fill in. - * @param[in] data Seed, single word. - * @post `rng` is initialised using the passed seeds. - */ -typedef void rb_random_init_int32_func(rb_random_t *rng, uint32_t data); - -RBIMPL_ATTR_NONNULL(()) -/** * This is the type of functions called from your object's `#rand` method. * * @param[out] rng Your random struct to extract an integer from. @@ -115,24 +84,9 @@ typedef struct { /** Number of bits of seed numbers. */ size_t default_seed_bits; - /** - * Major/minor versions of this interface - */ - struct { - uint8_t major, minor; - } version; - - /** - * Reserved flags - */ - uint16_t flags; - - /** Function to initialize from uint32_t array. */ + /** Initialiser function. */ rb_random_init_func *init; - /** Function to initialize from single uint32_t. */ - rb_random_init_int32_func *init_int32; - /** Function to obtain a random integer. */ rb_random_get_int32_func *get_int32; @@ -176,12 +130,11 @@ typedef struct { } rb_random_interface_t; /** - * This utility macro defines 4 functions named prefix_init, prefix_init_int32, - * prefix_get_int32, prefix_get_bytes. + * This utility macro defines 3 functions named prefix_init, prefix_get_int32, + * prefix_get_bytes. */ #define RB_RANDOM_INTERFACE_DECLARE(prefix) \ static void prefix##_init(rb_random_t *, const uint32_t *, size_t); \ - static void prefix##_init_int32(rb_random_t *, uint32_t); \ static unsigned int prefix##_get_int32(rb_random_t *); \ static void prefix##_get_bytes(rb_random_t *, void *, size_t) @@ -208,9 +161,7 @@ typedef struct { * ``` */ #define RB_RANDOM_INTERFACE_DEFINE(prefix) \ - RUBY_RANDOM_INTERFACE_VERSION_INITIALIZER, 0, \ prefix##_init, \ - prefix##_init_int32, \ prefix##_get_int32, \ prefix##_get_bytes @@ -222,12 +173,6 @@ typedef struct { RB_RANDOM_INTERFACE_DEFINE(prefix), \ prefix##_get_real -#define RB_RANDOM_DEFINE_INIT_INT32_FUNC(prefix) \ - static void prefix##_init_int32(rb_random_t *rnd, uint32_t data) \ - { \ - prefix##_init(rnd, &data, 1); \ - } - #if defined _WIN32 && !defined __CYGWIN__ typedef rb_data_type_t rb_random_data_type_t; # define RB_RANDOM_PARENT 0 @@ -244,7 +189,7 @@ typedef const rb_data_type_t rb_random_data_type_t; * 0, RB_RANDOM_INTERFACE_DEFINE(your), * }; * - * static inline constexpr rb_random_data_type_t your_prng_type = { + * static inline constexpr your_prng = { * "your PRNG", * { rb_random_mark, }, * RB_RANDOM_PARENT, // <<-- HERE diff --git a/include/ruby/re.h b/include/ruby/re.h index f86d6f26cf..3892d6e7f2 100644 --- a/include/ruby/re.h +++ b/include/ruby/re.h @@ -18,7 +18,6 @@ #include <stdio.h> -#include "ruby/onigmo.h" #include "ruby/regex.h" #include "ruby/internal/core/rmatch.h" #include "ruby/internal/dllexport.h" @@ -127,30 +126,6 @@ VALUE rb_reg_quote(VALUE str); regex_t *rb_reg_prepare_re(VALUE re, VALUE str); /** - * Runs a regular expression match using function `match`. Performs preparation, - * error handling, and memory cleanup. - * - * @param[in] re Target regular expression. - * @param[in] str What `re` is about to run on. - * @param[in] match The function to run to match `str` against `re`. - * @param[in] args Pointer to arguments to pass into `match`. - * @param[out] regs Registers on a successful match. - * @exception rb_eArgError `re` does not fit for `str`. - * @exception rb_eEncCompatError `re` and `str` are incompatible. - * @exception rb_eRegexpError `re` is malformed. - * @return Match position on a successful match, `ONIG_MISMATCH` otherwise. - * - * @internal - * - * The type `regex_t *` is defined in `<ruby/onigmo.h>`, _and_ - * _conflicts_ with POSIX's `<regex.h>`. We can no longer save the situation - * at this point. Just don't mix the two. - */ -OnigPosition rb_reg_onig_match(VALUE re, VALUE str, - OnigPosition (*match)(regex_t *reg, VALUE str, struct re_registers *regs, void *args), - void *args, struct re_registers *regs); - -/** * Duplicates a match data. This is roughly the same as `onig_region_copy()`, * except it tries to GC when there is not enough memory. * diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h index 035f02c70b..f35d13685c 100644 --- a/include/ruby/ruby.h +++ b/include/ruby/ruby.h @@ -23,7 +23,6 @@ #include <stdarg.h> #include "defines.h" -#include "ruby/internal/abi.h" #include "ruby/internal/anyargs.h" #include "ruby/internal/arithmetic.h" #include "ruby/internal/core.h" @@ -43,6 +42,7 @@ #include "ruby/internal/method.h" #include "ruby/internal/module.h" #include "ruby/internal/newobj.h" +#include "ruby/internal/rgengc.h" #include "ruby/internal/scan_args.h" #include "ruby/internal/special_consts.h" #include "ruby/internal/symbol.h" @@ -97,10 +97,8 @@ VALUE rb_get_path(VALUE obj); VALUE rb_get_path_no_checksafe(VALUE); /** - * This macro actually does the same thing as #FilePathValue now. The "String" - * part indicates that this is for when a string is treated like a pathname, - * rather than the actual pathname on the file systems. For examples: - * `Dir.fnmatch?`, `File.join`, `File.basename`, etc. + * @deprecated This macro is an alias of #FilePathValue now. The part that did + * "String" was deleted. It remains here because of no harm. */ #define FilePathStringValue(v) ((v) = rb_get_path(v)) @@ -109,7 +107,7 @@ VALUE rb_get_path_no_checksafe(VALUE); # define rb_varargs_argc_check_runtime(argc, vargc) \ (((argc) <= (vargc)) ? (argc) : \ (rb_fatal("argc(%d) exceeds actual arguments(%d)", \ - argc, vargc), 0)) + argc, vargc), 0)) # define rb_varargs_argc_valid_p(argc, vargc) \ ((argc) == 0 ? (vargc) <= 1 : /* [ruby-core:85266] [Bug #14425] */ \ (argc) == (vargc)) @@ -118,16 +116,16 @@ VALUE rb_get_path_no_checksafe(VALUE); ERRORFUNC((" argument length doesn't match"), int rb_varargs_bad_length(int,int)); # else # define rb_varargs_bad_length(argc, vargc) \ - ((argc)/rb_varargs_argc_valid_p(argc, vargc)) + ((argc)/rb_varargs_argc_valid_p(argc, vargc)) # endif # define rb_varargs_argc_check(argc, vargc) \ __builtin_choose_expr(__builtin_constant_p(argc), \ - (rb_varargs_argc_valid_p(argc, vargc) ? (argc) : \ - rb_varargs_bad_length(argc, vargc)), \ - rb_varargs_argc_check_runtime(argc, vargc)) + (rb_varargs_argc_valid_p(argc, vargc) ? (argc) : \ + rb_varargs_bad_length(argc, vargc)), \ + rb_varargs_argc_check_runtime(argc, vargc)) # else # define rb_varargs_argc_check(argc, vargc) \ - rb_varargs_argc_check_runtime(argc, vargc) + rb_varargs_argc_check_runtime(argc, vargc) # endif #endif /** @endcond */ @@ -272,148 +270,30 @@ RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 3, 0) */ int ruby_vsnprintf(char *str, size_t n, char const *fmt, va_list ap); -#include <errno.h> - -/** - * @name Errno handling routines for userland threads - * @note POSIX chapter 2 section 3 states that for each thread of a process, - * the value of `errno` shall not be affected by function calls or - * assignments to `errno` by other threads. - * - * Soooo this `#define errno` below seems like a noob mistake at first sight. - * If you look at its actual implementation, the functions are just adding one - * level of indirection. It doesn't make any sense sorry? But yes! @ko1 told - * @shyouhei that this is inevitable. - * - * The ultimate reason is because Ruby now has N:M threads implemented. - * Threads of that sort change their context in user land. A function can be - * "transferred" between threads in middle of their executions. Let us for - * instance consider: - * - * ```cxx - * void foo() - * { - * auto i = errno; - * close(0); - * errno = i; - * } - * ``` - * - * This function (if ran under our Ractor) could change its running thread at - * the `close` function. But the two `errno` invocations are different! Look - * how the source code above is compiled by clang 17 with `-O3` flag @ Linux: - * - * ``` - * foo(int): # @foo(int) - * push rbp - * push r14 - * push rbx - * mov ebx, edi - * call __errno_location@PLT - * mov r14, rax - * mov ebp, dword ptr [rax] - * mov edi, ebx - * call close@PLT - * mov dword ptr [r14], ebp - * pop rbx - * pop r14 - * pop rbp - * ret - * ``` - * - * Notice how `__errno_location@PLT` is `call`-ed only once. The compiler - * assumes that the location of `errno` does not change during a function call. - * Sadly this is no longer true for us. The `close@PLT` now changes threads, - * which should also change where `errno` is stored. - * - * With the `#define errno` below the compilation result changes to this: - * - * ``` - * foo(int): # @foo(int) - * push rbp - * push rbx - * push rax - * mov ebx, edi - * call rb_errno_ptr()@PLT - * mov ebp, dword ptr [rax] - * mov edi, ebx - * call close@PLT - * call rb_errno_ptr()@PLT - * mov dword ptr [rax], ebp - * add rsp, 8 - * pop rbx - * pop rbp - * ret - * ``` - * - * Which fixes the problem. - */ - -/** - * Identical to system `errno`. - * - * @return The last set `errno` number. - */ -int rb_errno(void); - -/** - * Set the errno. - * - * @param err New `errno`. - * @post `errno` is now set to `err`. - */ -void rb_errno_set(int err); - -/** - * The location of `errno` - * - * @return The (thread-specific) location of `errno`. - */ -int *rb_errno_ptr(void); - -/** - * Not sure if it is necessary for extension libraries but this is where the - * "bare" errno is located. - * - * @return The location of `errno`. - */ -static inline int * -rb_orig_errno_ptr(void) -{ - return &errno; -} - -#define rb_orig_errno errno /**< System-provided original `errno`. */ -#undef errno -#define errno (*rb_errno_ptr()) /**< Ractor-aware version of `errno`. */ - -/** @} */ - - /** @cond INTERNAL_MACRO */ #if RBIMPL_HAS_WARNING("-Wgnu-zero-variadic-macro-arguments") # /* Skip it; clang -pedantic doesn't like the following */ #elif defined(__GNUC__) && defined(HAVE_VA_ARGS_MACRO) && defined(__OPTIMIZE__) # define rb_yield_values(argc, ...) \ __extension__({ \ - const int rb_yield_values_argc = (argc); \ - const VALUE rb_yield_values_args[] = {__VA_ARGS__}; \ - const int rb_yield_values_nargs = \ - (int)(sizeof(rb_yield_values_args) / sizeof(VALUE)); \ - rb_yield_values2( \ - rb_varargs_argc_check(rb_yield_values_argc, rb_yield_values_nargs), \ - rb_yield_values_nargs ? rb_yield_values_args : NULL); \ + const int rb_yield_values_argc = (argc); \ + const VALUE rb_yield_values_args[] = {__VA_ARGS__}; \ + const int rb_yield_values_nargs = \ + (int)(sizeof(rb_yield_values_args) / sizeof(VALUE)); \ + rb_yield_values2( \ + rb_varargs_argc_check(rb_yield_values_argc, rb_yield_values_nargs), \ + rb_yield_values_nargs ? rb_yield_values_args : NULL); \ }) # define rb_funcall(recv, mid, argc, ...) \ __extension__({ \ - const int rb_funcall_argc = (argc); \ - const VALUE rb_funcall_args[] = {__VA_ARGS__}; \ - const int rb_funcall_nargs = \ - (int)(sizeof(rb_funcall_args) / sizeof(VALUE)); \ + const int rb_funcall_argc = (argc); \ + const VALUE rb_funcall_args[] = {__VA_ARGS__}; \ + const int rb_funcall_nargs = \ + (int)(sizeof(rb_funcall_args) / sizeof(VALUE)); \ rb_funcallv(recv, mid, \ - rb_varargs_argc_check(rb_funcall_argc, rb_funcall_nargs), \ - rb_funcall_nargs ? rb_funcall_args : NULL); \ + rb_varargs_argc_check(rb_funcall_argc, rb_funcall_nargs), \ + rb_funcall_nargs ? rb_funcall_args : NULL); \ }) #endif /** @endcond */ diff --git a/include/ruby/st.h b/include/ruby/st.h index ba69c066c9..1e4bb80686 100644 --- a/include/ruby/st.h +++ b/include/ruby/st.h @@ -98,14 +98,10 @@ struct st_table { enum st_retval {ST_CONTINUE, ST_STOP, ST_DELETE, ST_CHECK, ST_REPLACE}; -size_t rb_st_table_size(const struct st_table *tbl); -#define st_table_size rb_st_table_size st_table *rb_st_init_table(const struct st_hash_type *); #define st_init_table rb_st_init_table st_table *rb_st_init_table_with_size(const struct st_hash_type *, st_index_t); #define st_init_table_with_size rb_st_init_table_with_size -st_table *rb_st_init_existing_table_with_size(st_table *tab, const struct st_hash_type *type, st_index_t size); -#define st_init_existing_table_with_size rb_st_init_existing_table_with_size st_table *rb_st_init_numtable(void); #define st_init_numtable rb_st_init_numtable st_table *rb_st_init_numtable_with_size(st_index_t); @@ -162,8 +158,6 @@ void rb_st_cleanup_safe(st_table *, st_data_t); #define st_cleanup_safe rb_st_cleanup_safe void rb_st_clear(st_table *); #define st_clear rb_st_clear -st_table *rb_st_replace(st_table *new_tab, st_table *old_tab); -#define st_replace rb_st_replace st_table *rb_st_copy(st_table *); #define st_copy rb_st_copy CONSTFUNC(int rb_st_numcmp(st_data_t, st_data_t)); diff --git a/include/ruby/thread.h b/include/ruby/thread.h index f01d276a29..18c792b386 100644 --- a/include/ruby/thread.h +++ b/include/ruby/thread.h @@ -128,7 +128,7 @@ RBIMPL_ATTR_NONNULL((1)) * your code to see if it is actually worth releasing the GVL. */ void *rb_thread_call_without_gvl(void *(*func)(void *), void *data1, - rb_unblock_function_t *ubf, void *data2); + rb_unblock_function_t *ubf, void *data2); RBIMPL_ATTR_NONNULL((1)) /** @@ -152,7 +152,7 @@ RBIMPL_ATTR_NONNULL((1)) * @return What `func` returned, or 0 in case `func` did not return. */ void *rb_thread_call_without_gvl2(void *(*func)(void *), void *data1, - rb_unblock_function_t *ubf, void *data2); + rb_unblock_function_t *ubf, void *data2); /* * XXX: unstable/unapproved - out-of-tree code should NOT not depend @@ -190,123 +190,6 @@ void *rb_nogvl(void *(*func)(void *), void *data1, */ #define RUBY_CALL_WO_GVL_FLAG_SKIP_CHECK_INTS_ -/** - * Triggered when a new thread is started. - * - * @note The callback will be called *without* the GVL held. - */ -#define RUBY_INTERNAL_THREAD_EVENT_STARTED 1 << 0 - -/** -* Triggered when a thread attempt to acquire the GVL. -* -* @note The callback will be called *without* the GVL held. -*/ -#define RUBY_INTERNAL_THREAD_EVENT_READY 1 << 1 /** acquiring GVL */ - -/** - * Triggered when a thread successfully acquired the GVL. - * - * @note The callback will be called *with* the GVL held. - */ -#define RUBY_INTERNAL_THREAD_EVENT_RESUMED 1 << 2 /** acquired GVL */ - -/** - * Triggered when a thread released the GVL. - * - * @note The callback will be called *without* the GVL held. - */ -#define RUBY_INTERNAL_THREAD_EVENT_SUSPENDED 1 << 3 /** released GVL */ - -/** - * Triggered when a thread exits. - * - * @note The callback will be called *without* the GVL held. - */ -#define RUBY_INTERNAL_THREAD_EVENT_EXITED 1 << 4 /** thread terminated */ - -#define RUBY_INTERNAL_THREAD_EVENT_MASK 0xff /** All Thread events */ - -typedef struct rb_internal_thread_event_data { - VALUE thread; -} rb_internal_thread_event_data_t; - -typedef void (*rb_internal_thread_event_callback)(rb_event_flag_t event, - const rb_internal_thread_event_data_t *event_data, - void *user_data); -typedef struct rb_internal_thread_event_hook rb_internal_thread_event_hook_t; - -/** - * Registers a thread event hook function. - * - * @param[in] func A callback. - * @param[in] events A set of events that `func` should run. - * @param[in] data Passed as-is to `func`. - * @return An opaque pointer to the hook, to unregister it later. - * @note This functionality is a noop on Windows and WebAssembly. - * @note The callback will be called without the GVL held, except for the - * RESUMED event. - * @note Callbacks are not guaranteed to be executed on the native threads - * that corresponds to the Ruby thread. To identify which Ruby thread - * the event refers to, you must use `event_data->thread`. - * @warning This function MUST not be called from a thread event callback. - */ -rb_internal_thread_event_hook_t *rb_internal_thread_add_event_hook( - rb_internal_thread_event_callback func, rb_event_flag_t events, - void *data); - - -/** - * Unregister the passed hook. - * - * @param[in] hook. The hook to unregister. - * @return Whether the hook was found and unregistered. - * @note This functionality is a noop on Windows and WebAssembly. - * @warning This function MUST not be called from a thread event callback. -*/ -bool rb_internal_thread_remove_event_hook( - rb_internal_thread_event_hook_t * hook); - - -typedef int rb_internal_thread_specific_key_t; -#define RB_INTERNAL_THREAD_SPECIFIC_KEY_MAX 8 -/** - * Create a key to store thread specific data. - * - * These APIs are designed for tools using - * rb_internal_thread_event_hook APIs. - * - * Note that only `RB_INTERNAL_THREAD_SPECIFIC_KEY_MAX` keys - * can be created. raises `ThreadError` if exceeded. - * - * Usage: - * // at initialize time: - * int tool_key; // gvar - * Init_tool() { - * tool_key = rb_internal_thread_specific_key_create(); - * } - * - * // at any timing: - * rb_internal_thread_specific_set(thread, tool_key, per_thread_data); - * ... - * per_thread_data = rb_internal_thread_specific_get(thread, tool_key); - */ -rb_internal_thread_specific_key_t rb_internal_thread_specific_key_create(void); - -/** - * Get thread and tool specific data. - * - * This function is async signal safe and thread safe. - */ -void *rb_internal_thread_specific_get(VALUE thread_val, rb_internal_thread_specific_key_t key); - -/** - * Set thread and tool specific data. - * - * This function is async signal safe and thread safe. - */ -void rb_internal_thread_specific_set(VALUE thread_val, rb_internal_thread_specific_key_t key, void *data); - RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_THREAD_H */ diff --git a/include/ruby/thread_native.h b/include/ruby/thread_native.h index 8217a67514..2945ff1e4d 100644 --- a/include/ruby/thread_native.h +++ b/include/ruby/thread_native.h @@ -28,11 +28,6 @@ typedef union rb_thread_lock_union { CRITICAL_SECTION crit; } rb_nativethread_lock_t; -struct rb_thread_cond_struct { - struct cond_event_entry *next; - struct cond_event_entry *prev; -}; - typedef struct rb_thread_cond_struct rb_nativethread_cond_t; #elif defined(HAVE_PTHREAD_H) @@ -42,12 +37,6 @@ typedef pthread_t rb_nativethread_id_t; typedef pthread_mutex_t rb_nativethread_lock_t; typedef pthread_cond_t rb_nativethread_cond_t; -#elif defined(__wasi__) // no-thread platforms - -typedef struct rb_nativethread_id_t *rb_nativethread_id_t; -typedef struct rb_nativethread_lock_t *rb_nativethread_lock_t; -typedef struct rb_nativethread_cond_t *rb_nativethread_cond_t; - #elif defined(__DOXYGEN__) /** Opaque type that holds an ID of a native thread. */ diff --git a/include/ruby/util.h b/include/ruby/util.h index 12e69c4b80..b2bc1a09f6 100644 --- a/include/ruby/util.h +++ b/include/ruby/util.h @@ -19,7 +19,7 @@ # include <stddef.h> /* size_t */ #endif -#ifdef HAVE_SYS_TYPES_H +#if HAVE_SYS_TYPES_H # include <sys/types.h> /* ssize_t */ #endif @@ -33,20 +33,9 @@ RBIMPL_SYMBOL_EXPORT_BEGIN() -/** an approximation of ceil(n * log10(2)), up to 1,048,576 (1<<20) - * without overflow within 32-bit calculation - */ +/** an approximation of ceil(n * log10(2)), up to 65536 at least */ #define DECIMAL_SIZE_OF_BITS(n) (((n) * 3010 + 9998) / 9999) -/** an approximation of decimal representation size for n-bytes */ -#define DECIMAL_SIZE_OF_BYTES(n) DECIMAL_SIZE_OF_BITS((n) * CHAR_BIT) - -/** - * An approximation of decimal representation size. `expr` may be a - * type name - */ -#define DECIMAL_SIZE_OF(expr) DECIMAL_SIZE_OF_BYTES(sizeof(expr)) - /** * Character to number mapping like `'a'` -> `10`, `'b'` -> `11` etc. For * punctuation etc., the value is -1. "36" terminology comes from the fact @@ -135,7 +124,7 @@ unsigned long ruby_scan_hex(const char *str, size_t len, size_t *ret); # define ruby_qsort qsort_r #else void ruby_qsort(void *, const size_t, const size_t, - int (*)(const void *, const void *, void *), void *); + int (*)(const void *, const void *, void *), void *); #endif RBIMPL_ATTR_NONNULL((1)) diff --git a/include/ruby/version.h b/include/ruby/version.h index 08c0aadb07..104f78a0c6 100644 --- a/include/ruby/version.h +++ b/include/ruby/version.h @@ -67,7 +67,7 @@ * 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 3 +#define RUBY_API_VERSION_MINOR 1 /** * Teeny version. This digit is kind of reserved these days. Kept 0 for the @@ -137,8 +137,7 @@ RUBY_EXTERN const int ruby_patchlevel; /** * This is what `ruby -v` prints to the standard error. Something like: - * `"ruby 2.5.9p229 (2021-04-05 revision 67829) [x86_64-linux]"`. This doesn't - * include runtime options like a JIT being enabled. + * `"ruby 2.5.9p229 (2021-04-05 revision 67829) [x86_64-linux]"` */ RUBY_EXTERN const char ruby_description[]; diff --git a/include/ruby/win32.h b/include/ruby/win32.h index dfb56f4182..c8ae599f2f 100644 --- a/include/ruby/win32.h +++ b/include/ruby/win32.h @@ -19,6 +19,11 @@ RUBY_SYMBOL_EXPORT_BEGIN */ /* + * Definitions for NT port of Perl + */ + + +/* * Ok now we can include the normal include files. */ @@ -147,19 +152,13 @@ typedef int clockid_t; #define open rb_w32_uopen #define close(h) rb_w32_close(h) #define fclose(f) rb_w32_fclose(f) -#define read(f, b, s) rb_w32_read(f, b, s) -#define write(f, b, s) rb_w32_write(f, b, s) -#define pread(f, b, s, o) rb_w32_pread(f, b, s, o) -#define pwrite(f, b, s, o) rb_w32_pwrite(f, b, s, o) +#define read(f, b, s) rb_w32_read(f, b, s) +#define write(f, b, s) rb_w32_write(f, b, s) #define getpid() rb_w32_getpid() -#undef HAVE_GETPPID -#define HAVE_GETPPID 1 #define getppid() rb_w32_getppid() #define sleep(x) rb_w32_Sleep((x)*1000) #define Sleep(msec) (void)rb_w32_Sleep(msec) -#undef HAVE_EXECV -#define HAVE_EXECV 1 #undef execv #define execv(path,argv) rb_w32_uaspawn(P_OVERLAY,path,argv) #undef isatty @@ -192,6 +191,7 @@ struct stati128 { long st_ctimensec; }; +#define off_t __int64 #define stat stati128 #undef SIZEOF_STRUCT_STAT_ST_INO #define SIZEOF_STRUCT_STAT_ST_INO sizeof(unsigned __int64) @@ -299,6 +299,7 @@ extern DWORD rb_w32_osver(void); extern int rb_w32_uchown(const char *, int, int); extern int rb_w32_ulink(const char *, const char *); extern ssize_t rb_w32_ureadlink(const char *, char *, size_t); +extern ssize_t rb_w32_wreadlink(const WCHAR *, WCHAR *, size_t); extern int rb_w32_usymlink(const char *src, const char *link); extern int gettimeofday(struct timeval *, struct timezone *); extern int clock_gettime(clockid_t, struct timespec *); @@ -308,9 +309,7 @@ extern rb_pid_t wait(int *); extern rb_pid_t rb_w32_uspawn(int, const char *, const char*); extern rb_pid_t rb_w32_uaspawn(int, const char *, char *const *); extern rb_pid_t rb_w32_uaspawn_flags(int, const char *, char *const *, DWORD); -#undef HAVE_KILL -#define HAVE_KILL 1 -extern int kill(rb_pid_t, int); +extern int kill(int, int); extern int fcntl(int, int, ...); extern int rb_w32_set_nonblock(int); extern rb_pid_t rb_w32_getpid(void); @@ -389,7 +388,6 @@ scalb(double a, long b) #endif #define S_IFLNK 0xa000 -#define S_IFSOCK 0xc000 /* * define this so we can do inplace editing @@ -397,9 +395,9 @@ scalb(double a, long b) #define SUFFIX -extern int rb_w32_ftruncate(int fd, rb_off_t length); -extern int rb_w32_truncate(const char *path, rb_off_t length); -extern int rb_w32_utruncate(const char *path, rb_off_t length); +extern int rb_w32_ftruncate(int fd, off_t length); +extern int rb_w32_truncate(const char *path, off_t length); +extern int rb_w32_utruncate(const char *path, off_t length); #undef HAVE_FTRUNCATE #define HAVE_FTRUNCATE 1 @@ -649,8 +647,6 @@ extern char *rb_w32_strerror(int); #undef setsockopt #define setsockopt(s, v, n, o, l) rb_w32_setsockopt(s, v, n, o, l) -#undef HAVE_SHUTDOWN -#define HAVE_SHUTDOWN 1 #undef shutdown #define shutdown(s, h) rb_w32_shutdown(s, h) @@ -698,10 +694,10 @@ extern char *rb_w32_strerror(int); #endif struct tms { - long tms_utime; - long tms_stime; - long tms_cutime; - long tms_cstime; + long tms_utime; + long tms_stime; + long tms_cutime; + long tms_cstime; }; int rb_w32_times(struct tms *); @@ -718,9 +714,7 @@ int rb_w32_fclose(FILE*); int rb_w32_pipe(int[2]); ssize_t rb_w32_read(int, void *, size_t); ssize_t rb_w32_write(int, const void *, size_t); -ssize_t rb_w32_pread(int, void *, size_t, rb_off_t offset); -ssize_t rb_w32_pwrite(int, const void *, size_t, rb_off_t offset); -rb_off_t rb_w32_lseek(int, rb_off_t, int); +off_t rb_w32_lseek(int, off_t, int); int rb_w32_uutime(const char *, const struct utimbuf *); int rb_w32_uutimes(const char *, const struct timeval *); int rb_w32_uutimensat(int /* must be AT_FDCWD */, const char *, const struct timespec *, int /* must be 0 */); @@ -802,25 +796,6 @@ double rb_w32_pow(double x, double y); #define pow rb_w32_pow #endif -// mmap tiny emulation -#define MAP_FAILED ((void *)-1) - -#define PROT_READ 0x01 -#define PROT_WRITE 0x02 -#define PROT_EXEC 0x04 - -#define MAP_PRIVATE 0x0002 -#define MAP_ANON 0x1000 -#define MAP_ANONYMOUS MAP_ANON - -extern void *rb_w32_mmap(void *, size_t, int, int, int, rb_off_t); -extern int rb_w32_munmap(void *, size_t); -extern int rb_w32_mprotect(void *, size_t, int); - -#define mmap(a, l, p, f, d, o) rb_w32_mmap(a, l, p, f, d, o) -#define munmap(a, l) rb_w32_munmap(a, l) -#define mprotect(a, l, prot) rb_w32_mprotect(a, l, prot) - #if defined(__cplusplus) #if 0 { /* satisfy cc-mode */ |
