diff --git a/.github/workflows/check_misc.yml b/.github/workflows/check_misc.yml
index 4b0da6a0fe9c9a..5267bd35f1c92a 100644
--- a/.github/workflows/check_misc.yml
+++ b/.github/workflows/check_misc.yml
@@ -61,14 +61,11 @@ jobs:
exit $fail
working-directory: include
- - name: Generate docs
- id: docs
+ - name: Check if to generate documents
+ id: rdoc
run: |
- $RDOC -C -x ^ext -x ^lib .
- $RDOC --op html .
- echo htmlout=ruby-html-${GITHUB_SHA:0:10} >> $GITHUB_OUTPUT
- env:
- RDOC: ruby -W0 --disable-gems tool/rdoc-srcdir -q
+ ref=$(sed 's/#.*//;/^rdoc /!d' gems/bundled_gems | awk '{print $4}')
+ echo ref=$ref >> $GITHUB_OUTPUT
# Generate only when document commit/PR
if: >-
${{false
@@ -80,6 +77,36 @@ jobs:
|| contains(github.event.pull_request.labels.*.name, 'Documentation')
}}
+ - name: Checkout rdoc
+ uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+ with:
+ repository: ruby/rdoc
+ ref: ${{ steps.rdoc.outputs.ref }}
+ path: .bundle/gems/rdoc-0
+ if: ${{ steps.rdoc.outputs.ref != '' }}
+
+ - name: Generate rdoc
+ run: |
+ set -x
+ gempath=$(ruby -e 'print Gem.user_dir, "/bin"')
+ PATH=$gempath:$PATH
+ gem install --user bundler
+ bundle config --local path vendor/bundle
+ bundle install --jobs 4
+ bundle exec rake generate
+ working-directory: .bundle/gems/rdoc-0
+ if: ${{ steps.rdoc.outputs.ref != '' }}
+
+ - name: Generate docs
+ id: docs
+ run: |
+ $RDOC -C -x ^ext -x ^lib .
+ $RDOC --op html .
+ echo htmlout=ruby-html-${GITHUB_SHA:0:10} >> $GITHUB_OUTPUT
+ env:
+ RDOC: ruby -W0 --disable-gems tool/rdoc-srcdir -q
+ if: ${{ steps.rdoc.outcome == 'success' }}
+
- name: Upload docs
uses: actions/upload-artifact@v4
with:
diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml
index fa271e5cb57c61..e17d6dc3ed0efb 100644
--- a/.github/workflows/ubuntu.yml
+++ b/.github/workflows/ubuntu.yml
@@ -24,6 +24,22 @@ jobs:
make:
strategy:
matrix:
+ test_task: [check]
+ configure: ['']
+ arch: ['']
+ os:
+ - ubuntu-24.04
+ - ubuntu-24.04-arm
+ # FIXME Comment out ppc64le due to failing tests on GitHub Actions
+ # ppc64le
+ # https://bugs.ruby-lang.org/issues/21534
+ # - ubuntu-24.04-ppc64le
+ - ubuntu-24.04-s390x
+ # The ppc64le/s390x runners work only in the registered repositories.
+ # They don't work in forked repositories.
+ # https://github.com/IBM/actionspz/blob/main/docs/FAQ.md#what-about-forked-repos
+ upstream:
+ - ${{ github.repository == 'ruby/ruby' }}
include:
- test_task: check
configure: 'cppflags=-DVM_CHECK_MODE'
@@ -36,10 +52,11 @@ jobs:
- test_task: test-bundler-parallel
timeout: 50
- test_task: test-bundled-gems
- - test_task: check
- os: ubuntu-24.04
- - test_task: check
- os: ubuntu-24.04-arm
+ exclude:
+ - os: ubuntu-24.04-ppc64le
+ upstream: false
+ - os: ubuntu-24.04-s390x
+ upstream: false
fail-fast: false
env:
@@ -72,7 +89,25 @@ jobs:
with:
ruby-version: '3.1'
bundler: none
- if: ${{ !endsWith(matrix.os, 'arm') }}
+ if: ${{ !endsWith(matrix.os, 'arm') && !endsWith(matrix.os, 'ppc64le') && !endsWith(matrix.os, 's390x') }}
+
+ # Avoid possible test failures with the zlib applying the following patch
+ # on s390x CPU architecture.
+ # https://github.com/madler/zlib/pull/410
+ - name: Disable DFLTCC
+ run: echo "DFLTCC=0" >> $GITHUB_ENV
+ working-directory:
+ if: ${{ endsWith(matrix.os, 's390x') }}
+
+ # A temporary workaround: Set HOME env to pass the step
+ # ./.github/actions/setup/directories.
+ # https://github.com/IBM/actionspz/issues/30
+ - name: Set HOME env
+ run: |
+ echo "HOME: #{HOME}"
+ echo "HOME=$(ls -d ~)" >> $GITHUB_ENV
+ working-directory:
+ if: ${{ endsWith(matrix.os, 'ppc64le') || endsWith(matrix.os, 's390x') }}
- uses: ./.github/actions/setup/directories
with:
@@ -122,6 +157,17 @@ jobs:
continue-on-error: true
timeout-minutes: 3
+ # A temporary workaround: Skip user ground id test
+ # There is a mismatch between the group IDs of "id -g" and C function
+ # getpwuid(uid_t uid) pw_gid.
+ # https://github.com/IBM/actionspz/issues/31
+ - name: Skip user group id test
+ run: |
+ sed -i.orig '/^ it "returns user group id" do/a\ skip' \
+ ../src/spec/ruby/library/etc/struct_passwd_spec.rb
+ diff -u ../src/spec/ruby/library/etc/struct_passwd_spec.rb{.orig,} || :
+ if: ${{ endsWith(matrix.os, 'ppc64le') || endsWith(matrix.os, 's390x') }}
+
- name: make ${{ matrix.test_task }}
run: |
test -n "${LAUNCHABLE_STDOUT}" && exec 1> >(tee "${LAUNCHABLE_STDOUT}")
diff --git a/doc/globals.md b/doc/globals.md
index db23831a102265..b9315f5ff975e4 100644
--- a/doc/globals.md
+++ b/doc/globals.md
@@ -6,7 +6,7 @@ For each of those, the \English synonym is given.
To use the module:
-```
+```ruby
require 'English'
```
@@ -14,70 +14,70 @@ require 'English'
### Exceptions
-| Variable | English | Contains |
-|-------------|--------------------------|----------------------------------------------------|
-| $! | $ERROR_INFO | Exception object; set by Kernel#raise. |
-| $@ | $ERROR_POSITION | Array of backtrace positions; set by Kernel#raise. |
+| Variable | English | Contains |
+|-------------|-------------------|----------------------------------------------------|
+| `$!` | `$ERROR_INFO` | Exception object; set by Kernel#raise. |
+| `$@` | `$ERROR_POSITION` | Array of backtrace positions; set by Kernel#raise. |
### Pattern Matching
-| Variable | English | Contains |
-|-------------|----------------------------|--------------------------------------------------|
-| $~ | $LAST_MATCH_INFO | MatchData object; set by matcher method. |
-| $& | $MATCH | Matched substring; set by matcher method. |
-| $` | $PRE_MATCH | Substring left of match; set by matcher method. |
-| $' | $POST_MATCH | Substring right of match; set by matcher method. |
-| $+ | $LAST_PAREN_MATCH | Last group matched; set by matcher method. |
-| $1 | | First group matched; set by matcher method. |
-| $2 | | Second group matched; set by matcher method. |
-| $n | | nth group matched; set by matcher method. |
+| Variable | English | Contains |
+|---------------|---------------------|--------------------------------------------------|
+| `$~` | `$LAST_MATCH_INFO` | MatchData object; set by matcher method. |
+| `$&` | `$MATCH` | Matched substring; set by matcher method. |
+| `` $` `` | `$PRE_MATCH` | Substring left of match; set by matcher method. |
+| `$'` | `$POST_MATCH` | Substring right of match; set by matcher method. |
+| `$+` | `$LAST_PAREN_MATCH` | Last group matched; set by matcher method. |
+| `$1` | | First group matched; set by matcher method. |
+| `$2` | | Second group matched; set by matcher method. |
+| $_n_ | | nth group matched; set by matcher method. |
### Separators
-| Variable | English | Contains |
-|----------------------|-----------------------------------|--------------------------------------------------|
-| $/ | $INPUT_RECORD_SEPARATOR | Input record separator; initially newline. |
-| $\\\\\\\\ | $OUTPUT_RECORD_SEPARATOR | Output record separator; initially nil. |
+| Variable | English | Contains |
+|----------|----------------------------|--------------------------------------------|
+| `$/` | `$INPUT_RECORD_SEPARATOR` | Input record separator; initially newline. |
+| `$\` | `$OUTPUT_RECORD_SEPARATOR` | Output record separator; initially `nil`. |
### Streams
-| Variable | English | Contains |
-|------------------|-------------------------------------------|-----------------------------------------------------------|
-| $stdin | | Standard input stream; initially STDIN. |
-| $stdout | | Standard input stream; initially STDIOUT. |
-| $stderr | | Standard input stream; initially STDERR. |
-| $< | $DEFAULT_INPUT | Default standard input; ARGF or $stdin. |
-| $> | $DEFAULT_OUTPUT | Default standard output; initially $stdout. |
-| $. | $INPUT_LINE_NUMBER, $NR | Input position of most recently read stream. |
-| $_ | $LAST_READ_LINE | String from most recently read stream. |
+| Variable | English | Contains |
+|-----------|-----------------------------|-----------------------------------------------|
+| `$stdin` | | Standard input stream; initially `STDIN`. |
+| `$stdout` | | Standard input stream; initially `STDIOUT`. |
+| `$stderr` | | Standard input stream; initially `STDERR`. |
+| `$<` | `$DEFAULT_INPUT` | Default standard input; `ARGF` or `$stdin`. |
+| `$>` | `$DEFAULT_OUTPUT` | Default standard output; initially `$stdout`. |
+| `$.` | `$INPUT_LINE_NUMBER`, `$NR` | Input position of most recently read stream. |
+| `$_` | `$LAST_READ_LINE` | String from most recently read stream. |
### Processes
-| Variable | English | Contains |
-|------------------------------------------------|-------------------------------------|--------------------------------------------------------|
-| $0 | | Initially, the name of the executing program. |
-| $* | $ARGV | Points to the ARGV array. |
-| $$ | $PROCESS_ID, $PID | Process ID of the current process. |
-| $? | $CHILD_STATUS | Process::Status of most recently exited child process. |
-| $LOAD_PATH, $:, $-I | | Array of paths to be searched. |
-| $LOADED_FEATURES, $" | | Array of paths to loaded files. |
+| Variable | English | Contains |
+|---------------------------|-----------------------|--------------------------------------------------------|
+| `$0` | | Initially, the name of the executing program. |
+| `$*` | `$ARGV` | Points to the `ARGV` array. |
+| `$$` | `$PROCESS_ID`, `$PID` | Process ID of the current process. |
+| `$?` | `$CHILD_STATUS` | Process::Status of most recently exited child process. |
+| `$LOAD_PATH`, `$:`, `$-I` | | Array of paths to be searched. |
+| `$LOADED_FEATURES`, `$"` | | Array of paths to loaded files. |
### Debugging
-| Variable | English | Contains |
-|--------------------|---------|----------------------------------------------------------------------|
-| $FILENAME | | The value returned by method ARGF.filename. |
-| $DEBUG | | Initially, whether option -d or --debug was given. |
-| $VERBOSE | | Initially, whether option -V or -W was given. |
+| Variable | English | Contains |
+|-------------|---------|--------------------------------------------------------|
+| `$FILENAME` | | The value returned by method ARGF.filename. |
+| `$DEBUG` | | Initially, whether option `-d` or `--debug` was given. |
+| `$VERBOSE` | | Initially, whether option `-V` or `-W` was given. |
### Other Variables
-| Variable | English | Contains |
-|--------------|---------|-------------------------------------------------------|
-| $-a | | Whether option -a was given. |
-| $-i | | Extension given with command-line option -i. |
-| $-l | | Whether option -l was given. |
-| $-p | | Whether option -p was given. |
+| Variable | English | Contains |
+|----------|---------|------------------------------------------------|
+| `$-a` | | Whether option `-a` was given. |
+| `$-i` | | Extension given with command-line option `-i`. |
+| `$-l` | | Whether option `-l` was given. |
+| `$-p` | | Whether option `-p` was given. |
## Exceptions
@@ -85,7 +85,7 @@ require 'English'
Contains the Exception object set by Kernel#raise:
-```
+```ruby
begin
raise RuntimeError.new('Boo!')
rescue RuntimeError
@@ -106,7 +106,7 @@ English - `$ERROR_INFO`
Same as `$!.backtrace`;
returns an array of backtrace positions:
-```
+```ruby
begin
raise RuntimeError.new('Boo!')
rescue RuntimeError
@@ -165,7 +165,7 @@ English - `$LAST_PAREN_MATCH`.
### `$1`, `$2`, \Etc. (Matched Group)
-For `$_n_` the _nth_ group of the match.
+For $_n_ the nth group of the match.
No \English.
@@ -179,9 +179,9 @@ English - `$INPUT_RECORD_SEPARATOR`, `$RS`.
Aliased as `$-0`.
-### `$\\` (Output Record Separator)
+### `$\` (Output Record Separator)
-An output record separator, initially +nil+.
+An output record separator, initially `nil`.
English - `$OUTPUT_RECORD_SEPARATOR`, `$ORS`.
@@ -191,7 +191,7 @@ English - `$OUTPUT_RECORD_SEPARATOR`, `$ORS`.
The current standard input stream; initially:
-```
+```ruby
$stdin # => #>
```
@@ -199,7 +199,7 @@ $stdin # => #>
The current standard output stream; initially:
-```
+```ruby
$stdout # => #>
```
@@ -207,7 +207,7 @@ $stdout # => #>
The current standard error stream; initially:
-```
+```ruby
$stderr # => #>
```
@@ -256,7 +256,7 @@ English - `$PROCESS_ID`, `$PID`.
### `$?` (Child Status)
-Initially +nil+, otherwise the Process::Status object
+Initially `nil`, otherwise the Process::Status object
created for the most-recently exited child process;
thread-local.
@@ -270,15 +270,15 @@ by Kernel#load and Kernel#require.
Singleton method `$LOAD_PATH.resolve_feature_path(feature)`
returns:
-- `[:rb, _path_]`, where +path+ is the path to the Ruby file
- to be loaded for the given +feature+.
-- `[:so+ _path_]`, where +path+ is the path to the shared object file
- to be loaded for the given +feature+.
-- +nil+ if there is no such +feature+ and +path+.
+- [:rb, _path_], where `path` is the path to the Ruby file to be
+ loaded for the given `feature`.
+- [:so, _path_], where `path` is the path to the shared object file
+ to be loaded for the given `feature`.
+- `nil` if there is no such `feature` and `path`.
Examples:
-```
+```ruby
$LOAD_PATH.resolve_feature_path('timeout')
# => [:rb, "/snap/ruby/317/lib/ruby/3.2.0/timeout.rb"]
$LOAD_PATH.resolve_feature_path('date_core')
@@ -293,7 +293,7 @@ Aliased as `$:` and `$-I`.
Contains an array of the paths to the loaded files:
-```
+```ruby
$LOADED_FEATURES.take(10)
# =>
["enumerator.so",
@@ -318,23 +318,23 @@ The value returned by method ARGF.filename.
### `$DEBUG`
-Initially +true+ if command-line option `-d` or `--debug` is given,
-otherwise initially +false+;
+Initially `true` if command-line option `-d` or `--debug` is given,
+otherwise initially `false`;
may be set to either value in the running program.
-When +true+, prints each raised exception to `$stderr`.
+When `true`, prints each raised exception to `$stderr`.
Aliased as `$-d`.
### `$VERBOSE`
-Initially +true+ if command-line option `-v` or `-w` is given,
-otherwise initially +false+;
-may be set to either value, or to +nil+, in the running program.
+Initially `true` if command-line option `-v` or `-w` is given,
+otherwise initially `false`;
+may be set to either value, or to `nil`, in the running program.
-When +true+, enables Ruby warnings.
+When `true`, enables Ruby warnings.
-When +nil+, disables warnings, including those from Kernel#warn.
+When `nil`, disables warnings, including those from Kernel#warn.
Aliased as `$-v` and `$-w`.
@@ -347,7 +347,7 @@ Whether command-line option `-a` was given; read-only.
### `$-i`
Contains the extension given with command-line option `-i`,
-or +nil+ if none.
+or `nil` if none.
An alias of ARGF.inplace_mode.
@@ -373,35 +373,35 @@ Whether command-line option `-p` was given; read-only.
### Streams
-| Constant | Contains |
-|-----------------|-------------------------|
-| STDIN | Standard input stream. |
-| STDOUT | Standard output stream. |
-| STDERR | Standard error stream. |
+| Constant | Contains |
+|----------|-------------------------|
+| `STDIN` | Standard input stream. |
+| `STDOUT` | Standard output stream. |
+| `STDERR` | Standard error stream. |
### Environment
-| Constant | Contains |
-|------------------------------|--------------------------------------------------------------------------------------|
-| ENV | Hash of current environment variable names and values. |
-| ARGF | String concatenation of files given on the command line, or $stdin if none. |
-| ARGV | Array of the given command-line arguments. |
-| TOPLEVEL_BINDING | Binding of the top level scope. |
-| RUBY_VERSION | String Ruby version. |
-| RUBY_RELEASE_DATE | String Ruby release date. |
-| RUBY_PLATFORM | String Ruby platform. |
-| RUBY_PATCH_LEVEL | String Ruby patch level. |
-| RUBY_REVISION | String Ruby revision. |
-| RUBY_COPYRIGHT | String Ruby copyright. |
-| RUBY_ENGINE | String Ruby engine. |
-| RUBY_ENGINE_VERSION | String Ruby engine version. |
-| RUBY_DESCRIPTION | String Ruby description. |
+| Constant | Contains |
+|-----------------------|-------------------------------------------------------------------------------|
+| `ENV` | Hash of current environment variable names and values. |
+| `ARGF` | String concatenation of files given on the command line, or `$stdin` if none. |
+| `ARGV` | Array of the given command-line arguments. |
+| `TOPLEVEL_BINDING` | Binding of the top level scope. |
+| `RUBY_VERSION` | String Ruby version. |
+| `RUBY_RELEASE_DATE` | String Ruby release date. |
+| `RUBY_PLATFORM` | String Ruby platform. |
+| `RUBY_PATCH_LEVEL` | String Ruby patch level. |
+| `RUBY_REVISION` | String Ruby revision. |
+| `RUBY_COPYRIGHT` | String Ruby copyright. |
+| `RUBY_ENGINE` | String Ruby engine. |
+| `RUBY_ENGINE_VERSION` | String Ruby engine version. |
+| `RUBY_DESCRIPTION` | String Ruby description. |
### Embedded Data
-| Constant | Contains |
-|---------------|---------------------------------------------------------------------------|
-| DATA | File containing embedded data (lines following __END__, if any). |
+| Constant | Contains |
+|----------|--------------------------------------------------------------------|
+| `DATA` | File containing embedded data (lines following `__END__`, if any). |
## Streams
@@ -409,7 +409,7 @@ Whether command-line option `-p` was given; read-only.
The standard input stream (the default value for `$stdin`):
-```
+```ruby
STDIN # => #>
```
@@ -417,7 +417,7 @@ STDIN # => #>
The standard output stream (the default value for `$stdout`):
-```
+```ruby
STDOUT # => #>
```
@@ -425,17 +425,17 @@ STDOUT # => #>
The standard error stream (the default value for `$stderr`):
-```
+```ruby
STDERR # => #>
```
## Environment
-### ENV
+### `ENV`
A hash of the contains current environment variables names and values:
-```
+```ruby
ENV.take(5)
# =>
[["COLORTERM", "truecolor"],
@@ -445,7 +445,7 @@ ENV.take(5)
["GDMSESSION", "ubuntu"]]
```
-### ARGF
+### `ARGF`
The virtual concatenation of the files given on the command line, or from
`$stdin` if no files were given, `"-"` is given, or after
@@ -459,7 +459,7 @@ An array of the given command-line arguments.
The Binding of the top level scope:
-```
+```ruby
TOPLEVEL_BINDING # => #
```
@@ -467,7 +467,7 @@ TOPLEVEL_BINDING # => #
The Ruby version:
-```
+```ruby
RUBY_VERSION # => "3.2.2"
```
@@ -475,7 +475,7 @@ RUBY_VERSION # => "3.2.2"
The release date string:
-```
+```ruby
RUBY_RELEASE_DATE # => "2023-03-30"
```
@@ -483,7 +483,7 @@ RUBY_RELEASE_DATE # => "2023-03-30"
The platform identifier:
-```
+```ruby
RUBY_PLATFORM # => "x86_64-linux"
```
@@ -491,7 +491,7 @@ RUBY_PLATFORM # => "x86_64-linux"
The integer patch level for this Ruby:
-```
+```ruby
RUBY_PATCHLEVEL # => 53
```
@@ -501,7 +501,7 @@ For a development build the patch level will be -1.
The git commit hash for this Ruby:
-```
+```ruby
RUBY_REVISION # => "e51014f9c05aa65cbf203442d37fef7c12390015"
```
@@ -509,7 +509,7 @@ RUBY_REVISION # => "e51014f9c05aa65cbf203442d37fef7c12390015"
The copyright string:
-```
+```ruby
RUBY_COPYRIGHT
# => "ruby - Copyright (C) 1993-2023 Yukihiro Matsumoto"
```
@@ -518,7 +518,7 @@ RUBY_COPYRIGHT
The name of the Ruby implementation:
-```
+```ruby
RUBY_ENGINE # => "ruby"
```
@@ -526,7 +526,7 @@ RUBY_ENGINE # => "ruby"
The version of the Ruby implementation:
-```
+```ruby
RUBY_ENGINE_VERSION # => "3.2.2"
```
@@ -534,7 +534,7 @@ RUBY_ENGINE_VERSION # => "3.2.2"
The description of the Ruby implementation:
-```
+```ruby
RUBY_DESCRIPTION
# => "ruby 3.2.2 (2023-03-30 revision e51014f9c0) [x86_64-linux]"
```
@@ -545,7 +545,7 @@ RUBY_DESCRIPTION
Defined if and only if the program has this line:
-```
+```ruby
__END__
```
@@ -553,7 +553,7 @@ When defined, `DATA` is a File object
containing the lines following the `__END__`,
positioned at the first of those lines:
-```
+```ruby
p DATA
DATA.each_line { |line| p line }
__END__
diff --git a/enumerator.c b/enumerator.c
index 8d02c836e960e0..0d54058215f088 100644
--- a/enumerator.c
+++ b/enumerator.c
@@ -3073,7 +3073,7 @@ static const rb_data_type_t enum_chain_data_type = {
enum_chain_memsize,
enum_chain_mark_and_move,
},
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
};
static struct enum_chain *
@@ -3123,7 +3123,7 @@ enum_chain_initialize(VALUE obj, VALUE enums)
if (!ptr) rb_raise(rb_eArgError, "unallocated chain");
- ptr->enums = rb_ary_freeze(enums);
+ RB_OBJ_WRITE(obj, &ptr->enums, rb_ary_freeze(enums));
ptr->pos = -1;
return obj;
@@ -3157,7 +3157,7 @@ enum_chain_init_copy(VALUE obj, VALUE orig)
if (!ptr1) rb_raise(rb_eArgError, "unallocated chain");
- ptr1->enums = ptr0->enums;
+ RB_OBJ_WRITE(obj, &ptr1->enums, ptr0->enums);
ptr1->pos = ptr0->pos;
return obj;
@@ -3388,7 +3388,7 @@ static const rb_data_type_t enum_product_data_type = {
enum_product_memsize,
enum_product_mark_and_move,
},
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
};
static struct enum_product *
@@ -3444,7 +3444,7 @@ enum_product_initialize(int argc, VALUE *argv, VALUE obj)
if (!ptr) rb_raise(rb_eArgError, "unallocated product");
- ptr->enums = rb_ary_freeze(enums);
+ RB_OBJ_WRITE(obj, &ptr->enums, rb_ary_freeze(enums));
return obj;
}
@@ -3462,7 +3462,7 @@ enum_product_init_copy(VALUE obj, VALUE orig)
if (!ptr1) rb_raise(rb_eArgError, "unallocated product");
- ptr1->enums = ptr0->enums;
+ RB_OBJ_WRITE(obj, &ptr1->enums, ptr0->enums);
return obj;
}
diff --git a/gems/bundled_gems b/gems/bundled_gems
index 4fed6a994d8766..4c59614011428c 100644
--- a/gems/bundled_gems
+++ b/gems/bundled_gems
@@ -39,7 +39,7 @@ ostruct 0.6.3 https://github.com/ruby/ostruct
pstore 0.2.0 https://github.com/ruby/pstore
benchmark 0.4.1 https://github.com/ruby/benchmark
logger 1.7.0 https://github.com/ruby/logger
-rdoc 6.14.2 https://github.com/ruby/rdoc
+rdoc 6.14.2 https://github.com/ruby/rdoc f4a90c6010b2346cb5426d4496f5a37a136a82fb # for markdown
win32ole 1.9.2 https://github.com/ruby/win32ole
irb 1.15.2 https://github.com/ruby/irb 331c4e851296b115db766c291e8cf54a2492fb36
reline 0.6.2 https://github.com/ruby/reline
diff --git a/include/ruby/atomic.h b/include/ruby/atomic.h
index b778276f62d887..c7043b047692a6 100644
--- a/include/ruby/atomic.h
+++ b/include/ruby/atomic.h
@@ -84,6 +84,28 @@ typedef unsigned int rb_atomic_t;
# error No atomic operation found
#endif
+/* Memory ordering constants */
+#if defined(HAVE_GCC_ATOMIC_BUILTINS)
+# define RBIMPL_ATOMIC_RELAXED __ATOMIC_RELAXED
+# define RBIMPL_ATOMIC_ACQUIRE __ATOMIC_ACQUIRE
+# define RBIMPL_ATOMIC_RELEASE __ATOMIC_RELEASE
+# define RBIMPL_ATOMIC_ACQ_REL __ATOMIC_ACQ_REL
+# define RBIMPL_ATOMIC_SEQ_CST __ATOMIC_SEQ_CST
+#elif defined(HAVE_STDATOMIC_H)
+# define RBIMPL_ATOMIC_RELAXED memory_order_relaxed
+# define RBIMPL_ATOMIC_ACQUIRE memory_order_acquire
+# define RBIMPL_ATOMIC_RELEASE memory_order_release
+# define RBIMPL_ATOMIC_ACQ_REL memory_order_acq_rel
+# define RBIMPL_ATOMIC_SEQ_CST memory_order_seq_cst
+#else
+/* Dummy values for unsupported platforms */
+# define RBIMPL_ATOMIC_RELAXED 0
+# define RBIMPL_ATOMIC_ACQUIRE 1
+# define RBIMPL_ATOMIC_RELEASE 2
+# define RBIMPL_ATOMIC_ACQ_REL 3
+# define RBIMPL_ATOMIC_SEQ_CST 4
+#endif
+
/**
* Atomically replaces the value pointed by `var` with the result of addition
* of `val` to the old value of `var`.
@@ -93,7 +115,7 @@ typedef unsigned int rb_atomic_t;
* @return What was stored in `var` before the addition.
* @post `var` holds `var + val`.
*/
-#define RUBY_ATOMIC_FETCH_ADD(var, val) rbimpl_atomic_fetch_add(&(var), (val))
+#define RUBY_ATOMIC_FETCH_ADD(var, val) rbimpl_atomic_fetch_add(&(var), (val), RBIMPL_ATOMIC_SEQ_CST)
/**
* Atomically replaces the value pointed by `var` with the result of
@@ -104,7 +126,7 @@ typedef unsigned int rb_atomic_t;
* @return What was stored in `var` before the subtraction.
* @post `var` holds `var - val`.
*/
-#define RUBY_ATOMIC_FETCH_SUB(var, val) rbimpl_atomic_fetch_sub(&(var), (val))
+#define RUBY_ATOMIC_FETCH_SUB(var, val) rbimpl_atomic_fetch_sub(&(var), (val), RBIMPL_ATOMIC_SEQ_CST)
/**
* Atomically replaces the value pointed by `var` with the result of
@@ -116,7 +138,7 @@ typedef unsigned int rb_atomic_t;
* @post `var` holds `var | val`.
* @note For portability, this macro can return void.
*/
-#define RUBY_ATOMIC_OR(var, val) rbimpl_atomic_or(&(var), (val))
+#define RUBY_ATOMIC_OR(var, val) rbimpl_atomic_or(&(var), (val), RBIMPL_ATOMIC_SEQ_CST)
/**
* Atomically replaces the value pointed by `var` with `val`. This is just an
@@ -127,7 +149,7 @@ typedef unsigned int rb_atomic_t;
* @return What was stored in `var` before the assignment.
* @post `var` holds `val`.
*/
-#define RUBY_ATOMIC_EXCHANGE(var, val) rbimpl_atomic_exchange(&(var), (val))
+#define RUBY_ATOMIC_EXCHANGE(var, val) rbimpl_atomic_exchange(&(var), (val), RBIMPL_ATOMIC_SEQ_CST)
/**
* Atomic compare-and-swap. This stores `val` to `var` if and only if the
@@ -141,7 +163,7 @@ typedef unsigned int rb_atomic_t;
* @retval otherwise Something else is at `var`; not updated.
*/
#define RUBY_ATOMIC_CAS(var, oldval, newval) \
- rbimpl_atomic_cas(&(var), (oldval), (newval))
+ rbimpl_atomic_cas(&(var), (oldval), (newval), RBIMPL_ATOMIC_SEQ_CST, RBIMPL_ATOMIC_SEQ_CST)
/**
* Atomic load. This loads `var` with an atomic intrinsic and returns
@@ -150,7 +172,7 @@ typedef unsigned int rb_atomic_t;
* @param var A variable of ::rb_atomic_t
* @return What was stored in `var`j
*/
-#define RUBY_ATOMIC_LOAD(var) rbimpl_atomic_load(&(var))
+#define RUBY_ATOMIC_LOAD(var) rbimpl_atomic_load(&(var), RBIMPL_ATOMIC_SEQ_CST)
/**
* Identical to #RUBY_ATOMIC_EXCHANGE, except for the return type.
@@ -160,7 +182,7 @@ typedef unsigned int rb_atomic_t;
* @return void
* @post `var` holds `val`.
*/
-#define RUBY_ATOMIC_SET(var, val) rbimpl_atomic_set(&(var), (val))
+#define RUBY_ATOMIC_SET(var, val) rbimpl_atomic_store(&(var), (val), RBIMPL_ATOMIC_SEQ_CST)
/**
* Identical to #RUBY_ATOMIC_FETCH_ADD, except for the return type.
@@ -170,7 +192,7 @@ typedef unsigned int rb_atomic_t;
* @return void
* @post `var` holds `var + val`.
*/
-#define RUBY_ATOMIC_ADD(var, val) rbimpl_atomic_add(&(var), (val))
+#define RUBY_ATOMIC_ADD(var, val) rbimpl_atomic_add(&(var), (val), RBIMPL_ATOMIC_SEQ_CST)
/**
* Identical to #RUBY_ATOMIC_FETCH_SUB, except for the return type.
@@ -180,7 +202,7 @@ typedef unsigned int rb_atomic_t;
* @return void
* @post `var` holds `var - val`.
*/
-#define RUBY_ATOMIC_SUB(var, val) rbimpl_atomic_sub(&(var), (val))
+#define RUBY_ATOMIC_SUB(var, val) rbimpl_atomic_sub(&(var), (val), RBIMPL_ATOMIC_SEQ_CST)
/**
* Atomically increments the value pointed by `var`.
@@ -189,7 +211,7 @@ typedef unsigned int rb_atomic_t;
* @return void
* @post `var` holds `var + 1`.
*/
-#define RUBY_ATOMIC_INC(var) rbimpl_atomic_inc(&(var))
+#define RUBY_ATOMIC_INC(var) rbimpl_atomic_inc(&(var), RBIMPL_ATOMIC_SEQ_CST)
/**
* Atomically decrements the value pointed by `var`.
@@ -198,7 +220,7 @@ typedef unsigned int rb_atomic_t;
* @return void
* @post `var` holds `var - 1`.
*/
-#define RUBY_ATOMIC_DEC(var) rbimpl_atomic_dec(&(var))
+#define RUBY_ATOMIC_DEC(var) rbimpl_atomic_dec(&(var), RBIMPL_ATOMIC_SEQ_CST)
/**
* Identical to #RUBY_ATOMIC_FETCH_ADD, except it expects its arguments to be `size_t`.
@@ -210,7 +232,7 @@ typedef unsigned int rb_atomic_t;
* @return What was stored in `var` before the addition.
* @post `var` holds `var + val`.
*/
-#define RUBY_ATOMIC_SIZE_FETCH_ADD(var, val) rbimpl_atomic_size_fetch_add(&(var), (val))
+#define RUBY_ATOMIC_SIZE_FETCH_ADD(var, val) rbimpl_atomic_size_fetch_add(&(var), (val), RBIMPL_ATOMIC_SEQ_CST)
/**
* Identical to #RUBY_ATOMIC_INC, except it expects its argument is `size_t`.
@@ -221,7 +243,7 @@ typedef unsigned int rb_atomic_t;
* @return void
* @post `var` holds `var + 1`.
*/
-#define RUBY_ATOMIC_SIZE_INC(var) rbimpl_atomic_size_inc(&(var))
+#define RUBY_ATOMIC_SIZE_INC(var) rbimpl_atomic_size_inc(&(var), RBIMPL_ATOMIC_SEQ_CST)
/**
* Identical to #RUBY_ATOMIC_DEC, except it expects its argument is `size_t`.
@@ -232,7 +254,7 @@ typedef unsigned int rb_atomic_t;
* @return void
* @post `var` holds `var - 1`.
*/
-#define RUBY_ATOMIC_SIZE_DEC(var) rbimpl_atomic_size_dec(&(var))
+#define RUBY_ATOMIC_SIZE_DEC(var) rbimpl_atomic_size_dec(&(var), RBIMPL_ATOMIC_SEQ_CST)
/**
* Identical to #RUBY_ATOMIC_EXCHANGE, except it expects its arguments are
@@ -246,7 +268,7 @@ typedef unsigned int rb_atomic_t;
* @post `var` holds `val`.
*/
#define RUBY_ATOMIC_SIZE_EXCHANGE(var, val) \
- rbimpl_atomic_size_exchange(&(var), (val))
+ rbimpl_atomic_size_exchange(&(var), (val), RBIMPL_ATOMIC_SEQ_CST)
/**
* Identical to #RUBY_ATOMIC_CAS, except it expects its arguments are `size_t`.
@@ -260,7 +282,7 @@ typedef unsigned int rb_atomic_t;
* @retval otherwise Something else is at `var`; not updated.
*/
#define RUBY_ATOMIC_SIZE_CAS(var, oldval, newval) \
- rbimpl_atomic_size_cas(&(var), (oldval), (newval))
+ rbimpl_atomic_size_cas(&(var), (oldval), (newval), RBIMPL_ATOMIC_SEQ_CST, RBIMPL_ATOMIC_SEQ_CST)
/**
* Identical to #RUBY_ATOMIC_ADD, except it expects its arguments are `size_t`.
@@ -272,7 +294,7 @@ typedef unsigned int rb_atomic_t;
* @return void
* @post `var` holds `var + val`.
*/
-#define RUBY_ATOMIC_SIZE_ADD(var, val) rbimpl_atomic_size_add(&(var), (val))
+#define RUBY_ATOMIC_SIZE_ADD(var, val) rbimpl_atomic_size_add(&(var), (val), RBIMPL_ATOMIC_SEQ_CST)
/**
* Identical to #RUBY_ATOMIC_SUB, except it expects its arguments are `size_t`.
@@ -284,7 +306,7 @@ typedef unsigned int rb_atomic_t;
* @return void
* @post `var` holds `var - val`.
*/
-#define RUBY_ATOMIC_SIZE_SUB(var, val) rbimpl_atomic_size_sub(&(var), (val))
+#define RUBY_ATOMIC_SIZE_SUB(var, val) rbimpl_atomic_size_sub(&(var), (val), RBIMPL_ATOMIC_SEQ_CST)
/**
* Identical to #RUBY_ATOMIC_EXCHANGE, except it expects its arguments are
@@ -303,7 +325,7 @@ typedef unsigned int rb_atomic_t;
* some pointers, most notably function pointers.
*/
#define RUBY_ATOMIC_PTR_EXCHANGE(var, val) \
- RBIMPL_CAST(rbimpl_atomic_ptr_exchange((void **)&(var), (void *)val))
+ RBIMPL_CAST(rbimpl_atomic_ptr_exchange((void **)&(var), (void *)val, RBIMPL_ATOMIC_SEQ_CST))
/**
* Identical to #RUBY_ATOMIC_LOAD, except it expects its arguments are `void*`.
@@ -314,7 +336,7 @@ typedef unsigned int rb_atomic_t;
* @return The value of `var` (without tearing)
*/
#define RUBY_ATOMIC_PTR_LOAD(var) \
- RBIMPL_CAST(rbimpl_atomic_ptr_load((void **)&var))
+ RBIMPL_CAST(rbimpl_atomic_ptr_load((void **)&var, RBIMPL_ATOMIC_SEQ_CST))
/**
* Identical to #RUBY_ATOMIC_SET, except it expects its arguments are
@@ -327,7 +349,7 @@ typedef unsigned int rb_atomic_t;
* @post `var` holds `val`.
*/
#define RUBY_ATOMIC_PTR_SET(var, val) \
- rbimpl_atomic_ptr_set((volatile void **)&(var), (val))
+ rbimpl_atomic_ptr_store((volatile void **)&(var), (val), RBIMPL_ATOMIC_SEQ_CST)
/**
* Identical to #RUBY_ATOMIC_CAS, except it expects its arguments are `void*`.
@@ -341,7 +363,7 @@ typedef unsigned int rb_atomic_t;
* @retval otherwise Something else is at `var`; not updated.
*/
#define RUBY_ATOMIC_PTR_CAS(var, oldval, newval) \
- RBIMPL_CAST(rbimpl_atomic_ptr_cas((void **)&(var), (void *)(oldval), (void *)(newval)))
+ RBIMPL_CAST(rbimpl_atomic_ptr_cas((void **)&(var), (void *)(oldval), (void *)(newval), RBIMPL_ATOMIC_SEQ_CST, RBIMPL_ATOMIC_SEQ_CST))
/**
* Identical to #RUBY_ATOMIC_SET, except it expects its arguments are
@@ -354,7 +376,7 @@ typedef unsigned int rb_atomic_t;
* @post `var` holds `val`.
*/
#define RUBY_ATOMIC_VALUE_SET(var, val) \
- rbimpl_atomic_value_set(&(var), (val))
+ rbimpl_atomic_value_store(&(var), (val), RBIMPL_ATOMIC_SEQ_CST)
/**
* Identical to #RUBY_ATOMIC_EXCHANGE, except it expects its arguments are
@@ -368,7 +390,7 @@ typedef unsigned int rb_atomic_t;
* @post `var` holds `val`.
*/
#define RUBY_ATOMIC_VALUE_EXCHANGE(var, val) \
- rbimpl_atomic_value_exchange(&(var), (val))
+ rbimpl_atomic_value_exchange(&(var), (val), RBIMPL_ATOMIC_SEQ_CST)
/**
* Identical to #RUBY_ATOMIC_CAS, except it expects its arguments are ::VALUE.
@@ -382,19 +404,20 @@ typedef unsigned int rb_atomic_t;
* @retval otherwise Something else is at `var`; not updated.
*/
#define RUBY_ATOMIC_VALUE_CAS(var, oldval, newval) \
- rbimpl_atomic_value_cas(&(var), (oldval), (newval))
+ rbimpl_atomic_value_cas(&(var), (oldval), (newval), RBIMPL_ATOMIC_SEQ_CST, RBIMPL_ATOMIC_SEQ_CST)
/** @cond INTERNAL_MACRO */
RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL((1))
static inline rb_atomic_t
-rbimpl_atomic_fetch_add(volatile rb_atomic_t *ptr, rb_atomic_t val)
+rbimpl_atomic_fetch_add(volatile rb_atomic_t *ptr, rb_atomic_t val, int memory_order)
{
+ (void)memory_order;
#if 0
#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
- return __atomic_fetch_add(ptr, val, __ATOMIC_SEQ_CST);
+ return __atomic_fetch_add(ptr, val, memory_order);
#elif defined(HAVE_GCC_SYNC_BUILTINS)
return __sync_fetch_and_add(ptr, val);
@@ -412,7 +435,7 @@ rbimpl_atomic_fetch_add(volatile rb_atomic_t *ptr, rb_atomic_t val)
return atomic_add_int_nv(ptr, val) - val;
#elif defined(HAVE_STDATOMIC_H)
- return atomic_fetch_add((_Atomic volatile rb_atomic_t *)ptr, val);
+ return atomic_fetch_add_explicit((_Atomic volatile rb_atomic_t *)ptr, val, memory_order);
#else
# error Unsupported platform.
@@ -424,12 +447,13 @@ RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL((1))
static inline size_t
-rbimpl_atomic_size_fetch_add(volatile size_t *ptr, size_t val)
+rbimpl_atomic_size_fetch_add(volatile size_t *ptr, size_t val, int memory_order)
{
+ (void)memory_order;
#if 0
#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
- return __atomic_fetch_add(ptr, val, __ATOMIC_SEQ_CST);
+ return __atomic_fetch_add(ptr, val, memory_order);
#elif defined(HAVE_GCC_SYNC_BUILTINS)
return __sync_fetch_and_add(ptr, val);
@@ -446,10 +470,10 @@ rbimpl_atomic_size_fetch_add(volatile size_t *ptr, size_t val)
RBIMPL_STATIC_ASSERT(size_of_rb_atomic_t, sizeof *ptr == sizeof(rb_atomic_t));
volatile rb_atomic_t *const tmp = RBIMPL_CAST((volatile rb_atomic_t *)ptr);
- rbimpl_atomic_fetch_add(tmp, val);
+ rbimpl_atomic_fetch_add(tmp, val, memory_order);
#elif defined(HAVE_STDATOMIC_H)
- return atomic_fetch_add((_Atomic volatile size_t *)ptr, val);
+ return atomic_fetch_add_explicit((_Atomic volatile size_t *)ptr, val, memory_order);
#else
# error Unsupported platform.
@@ -460,8 +484,9 @@ RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL((1))
static inline void
-rbimpl_atomic_add(volatile rb_atomic_t *ptr, rb_atomic_t val)
+rbimpl_atomic_add(volatile rb_atomic_t *ptr, rb_atomic_t val, int memory_order)
{
+ (void)memory_order;
#if 0
#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
@@ -470,7 +495,7 @@ rbimpl_atomic_add(volatile rb_atomic_t *ptr, rb_atomic_t val)
* return value is not used, then compiles it into single `LOCK ADD`
* instruction.
*/
- __atomic_add_fetch(ptr, val, __ATOMIC_SEQ_CST);
+ __atomic_add_fetch(ptr, val, memory_order);
#elif defined(HAVE_GCC_SYNC_BUILTINS)
__sync_add_and_fetch(ptr, val);
@@ -489,7 +514,7 @@ rbimpl_atomic_add(volatile rb_atomic_t *ptr, rb_atomic_t val)
atomic_add_int(ptr, val);
#elif defined(HAVE_STDATOMIC_H)
- *(_Atomic volatile rb_atomic_t *)ptr += val;
+ atomic_fetch_add_explicit((_Atomic volatile rb_atomic_t *)ptr, val, memory_order);
#else
# error Unsupported platform.
@@ -500,12 +525,13 @@ RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL((1))
static inline void
-rbimpl_atomic_size_add(volatile size_t *ptr, size_t val)
+rbimpl_atomic_size_add(volatile size_t *ptr, size_t val, int memory_order)
{
+ (void)memory_order;
#if 0
#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
- __atomic_add_fetch(ptr, val, __ATOMIC_SEQ_CST);
+ __atomic_add_fetch(ptr, val, memory_order);
#elif defined(HAVE_GCC_SYNC_BUILTINS)
__sync_add_and_fetch(ptr, val);
@@ -523,10 +549,10 @@ rbimpl_atomic_size_add(volatile size_t *ptr, size_t val)
RBIMPL_STATIC_ASSERT(size_of_rb_atomic_t, sizeof *ptr == sizeof(rb_atomic_t));
volatile rb_atomic_t *const tmp = RBIMPL_CAST((volatile rb_atomic_t *)ptr);
- rbimpl_atomic_add(tmp, val);
+ rbimpl_atomic_add(tmp, val, memory_order);
#elif defined(HAVE_STDATOMIC_H)
- *(_Atomic volatile size_t *)ptr += val;
+ atomic_fetch_add_explicit((_Atomic volatile size_t *)ptr, val, memory_order);
#else
# error Unsupported platform.
@@ -537,12 +563,13 @@ RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL((1))
static inline void
-rbimpl_atomic_inc(volatile rb_atomic_t *ptr)
+rbimpl_atomic_inc(volatile rb_atomic_t *ptr, int memory_order)
{
+ (void)memory_order;
#if 0
#elif defined(HAVE_GCC_ATOMIC_BUILTINS) || defined(HAVE_GCC_SYNC_BUILTINS)
- rbimpl_atomic_add(ptr, 1);
+ rbimpl_atomic_add(ptr, 1, memory_order);
#elif defined(_WIN32)
InterlockedIncrement(ptr);
@@ -551,7 +578,7 @@ rbimpl_atomic_inc(volatile rb_atomic_t *ptr)
atomic_inc_uint(ptr);
#elif defined(HAVE_STDATOMIC_H)
- rbimpl_atomic_add(ptr, 1);
+ rbimpl_atomic_add(ptr, 1, memory_order);
#else
# error Unsupported platform.
@@ -562,12 +589,13 @@ RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL((1))
static inline void
-rbimpl_atomic_size_inc(volatile size_t *ptr)
+rbimpl_atomic_size_inc(volatile size_t *ptr, int memory_order)
{
+ (void)memory_order;
#if 0
#elif defined(HAVE_GCC_ATOMIC_BUILTINS) || defined(HAVE_GCC_SYNC_BUILTINS)
- rbimpl_atomic_size_add(ptr, 1);
+ rbimpl_atomic_size_add(ptr, 1, memory_order);
#elif defined(_WIN64)
InterlockedIncrement64(ptr);
@@ -578,10 +606,10 @@ rbimpl_atomic_size_inc(volatile size_t *ptr)
#elif defined(_WIN32) || (defined(__sun) && defined(HAVE_ATOMIC_H))
RBIMPL_STATIC_ASSERT(size_of_size_t, sizeof *ptr == sizeof(rb_atomic_t));
- rbimpl_atomic_size_add(ptr, 1);
+ rbimpl_atomic_size_add(ptr, 1, memory_order);
#elif defined(HAVE_STDATOMIC_H)
- rbimpl_atomic_size_add(ptr, 1);
+ rbimpl_atomic_size_add(ptr, 1, memory_order);
#else
# error Unsupported platform.
@@ -592,12 +620,13 @@ RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL((1))
static inline rb_atomic_t
-rbimpl_atomic_fetch_sub(volatile rb_atomic_t *ptr, rb_atomic_t val)
+rbimpl_atomic_fetch_sub(volatile rb_atomic_t *ptr, rb_atomic_t val, int memory_order)
{
+ (void)memory_order;
#if 0
#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
- return __atomic_fetch_sub(ptr, val, __ATOMIC_SEQ_CST);
+ return __atomic_fetch_sub(ptr, val, memory_order);
#elif defined(HAVE_GCC_SYNC_BUILTINS)
return __sync_fetch_and_sub(ptr, val);
@@ -613,7 +642,7 @@ rbimpl_atomic_fetch_sub(volatile rb_atomic_t *ptr, rb_atomic_t val)
return atomic_add_int_nv(ptr, neg * val) + val;
#elif defined(HAVE_STDATOMIC_H)
- return atomic_fetch_sub((_Atomic volatile rb_atomic_t *)ptr, val);
+ return atomic_fetch_sub_explicit((_Atomic volatile rb_atomic_t *)ptr, val, memory_order);
#else
# error Unsupported platform.
@@ -624,12 +653,13 @@ RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL((1))
static inline void
-rbimpl_atomic_sub(volatile rb_atomic_t *ptr, rb_atomic_t val)
+rbimpl_atomic_sub(volatile rb_atomic_t *ptr, rb_atomic_t val, int memory_order)
{
+ (void)memory_order;
#if 0
#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
- __atomic_sub_fetch(ptr, val, __ATOMIC_SEQ_CST);
+ __atomic_sub_fetch(ptr, val, memory_order);
#elif defined(HAVE_GCC_SYNC_BUILTINS)
__sync_sub_and_fetch(ptr, val);
@@ -643,7 +673,7 @@ rbimpl_atomic_sub(volatile rb_atomic_t *ptr, rb_atomic_t val)
atomic_add_int(ptr, neg * val);
#elif defined(HAVE_STDATOMIC_H)
- *(_Atomic volatile rb_atomic_t *)ptr -= val;
+ atomic_fetch_sub_explicit((_Atomic volatile rb_atomic_t *)ptr, val, memory_order);
#else
# error Unsupported platform.
@@ -654,12 +684,13 @@ RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL((1))
static inline void
-rbimpl_atomic_size_sub(volatile size_t *ptr, size_t val)
+rbimpl_atomic_size_sub(volatile size_t *ptr, size_t val, int memory_order)
{
+ (void)memory_order;
#if 0
#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
- __atomic_sub_fetch(ptr, val, __ATOMIC_SEQ_CST);
+ __atomic_sub_fetch(ptr, val, memory_order);
#elif defined(HAVE_GCC_SYNC_BUILTINS)
__sync_sub_and_fetch(ptr, val);
@@ -677,10 +708,10 @@ rbimpl_atomic_size_sub(volatile size_t *ptr, size_t val)
RBIMPL_STATIC_ASSERT(size_of_rb_atomic_t, sizeof *ptr == sizeof(rb_atomic_t));
volatile rb_atomic_t *const tmp = RBIMPL_CAST((volatile rb_atomic_t *)ptr);
- rbimpl_atomic_sub(tmp, val);
+ rbimpl_atomic_sub(tmp, val, memory_order);
#elif defined(HAVE_STDATOMIC_H)
- *(_Atomic volatile size_t *)ptr -= val;
+ atomic_fetch_sub_explicit((_Atomic volatile size_t *)ptr, val, memory_order);
#else
# error Unsupported platform.
@@ -691,12 +722,13 @@ RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL((1))
static inline void
-rbimpl_atomic_dec(volatile rb_atomic_t *ptr)
+rbimpl_atomic_dec(volatile rb_atomic_t *ptr, int memory_order)
{
+ (void)memory_order;
#if 0
#elif defined(HAVE_GCC_ATOMIC_BUILTINS) || defined(HAVE_GCC_SYNC_BUILTINS)
- rbimpl_atomic_sub(ptr, 1);
+ rbimpl_atomic_sub(ptr, 1, memory_order);
#elif defined(_WIN32)
InterlockedDecrement(ptr);
@@ -705,7 +737,7 @@ rbimpl_atomic_dec(volatile rb_atomic_t *ptr)
atomic_dec_uint(ptr);
#elif defined(HAVE_STDATOMIC_H)
- rbimpl_atomic_sub(ptr, 1);
+ rbimpl_atomic_sub(ptr, 1, memory_order);
#else
# error Unsupported platform.
@@ -716,12 +748,13 @@ RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL((1))
static inline void
-rbimpl_atomic_size_dec(volatile size_t *ptr)
+rbimpl_atomic_size_dec(volatile size_t *ptr, int memory_order)
{
+ (void)memory_order;
#if 0
#elif defined(HAVE_GCC_ATOMIC_BUILTINS) || defined(HAVE_GCC_SYNC_BUILTINS)
- rbimpl_atomic_size_sub(ptr, 1);
+ rbimpl_atomic_size_sub(ptr, 1, memory_order);
#elif defined(_WIN64)
InterlockedDecrement64(ptr);
@@ -732,10 +765,10 @@ rbimpl_atomic_size_dec(volatile size_t *ptr)
#elif defined(_WIN32) || (defined(__sun) && defined(HAVE_ATOMIC_H))
RBIMPL_STATIC_ASSERT(size_of_size_t, sizeof *ptr == sizeof(rb_atomic_t));
- rbimpl_atomic_size_sub(ptr, 1);
+ rbimpl_atomic_size_sub(ptr, 1, memory_order);
#elif defined(HAVE_STDATOMIC_H)
- rbimpl_atomic_size_sub(ptr, 1);
+ rbimpl_atomic_size_sub(ptr, 1, memory_order);
#else
# error Unsupported platform.
@@ -746,12 +779,13 @@ RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL((1))
static inline void
-rbimpl_atomic_or(volatile rb_atomic_t *ptr, rb_atomic_t val)
+rbimpl_atomic_or(volatile rb_atomic_t *ptr, rb_atomic_t val, int memory_order)
{
+ (void)memory_order;
#if 0
#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
- __atomic_or_fetch(ptr, val, __ATOMIC_SEQ_CST);
+ __atomic_or_fetch(ptr, val, memory_order);
#elif defined(HAVE_GCC_SYNC_BUILTINS)
__sync_or_and_fetch(ptr, val);
@@ -776,7 +810,7 @@ rbimpl_atomic_or(volatile rb_atomic_t *ptr, rb_atomic_t val)
atomic_or_uint(ptr, val);
#elif !defined(_WIN32) && defined(HAVE_STDATOMIC_H)
- *(_Atomic volatile rb_atomic_t *)ptr |= val;
+ atomic_fetch_or_explicit((_Atomic volatile rb_atomic_t *)ptr, val, memory_order);
#else
# error Unsupported platform.
@@ -796,12 +830,13 @@ RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL((1))
static inline rb_atomic_t
-rbimpl_atomic_exchange(volatile rb_atomic_t *ptr, rb_atomic_t val)
+rbimpl_atomic_exchange(volatile rb_atomic_t *ptr, rb_atomic_t val, int memory_order)
{
+ (void)memory_order;
#if 0
#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
- return __atomic_exchange_n(ptr, val, __ATOMIC_SEQ_CST);
+ return __atomic_exchange_n(ptr, val, memory_order);
#elif defined(HAVE_GCC_SYNC_BUILTINS)
return __sync_lock_test_and_set(ptr, val);
@@ -813,7 +848,7 @@ rbimpl_atomic_exchange(volatile rb_atomic_t *ptr, rb_atomic_t val)
return atomic_swap_uint(ptr, val);
#elif defined(HAVE_STDATOMIC_H)
- return atomic_exchange((_Atomic volatile rb_atomic_t *)ptr, val);
+ return atomic_exchange_explicit((_Atomic volatile rb_atomic_t *)ptr, val, memory_order);
#else
# error Unsupported platform.
@@ -824,12 +859,13 @@ RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL((1))
static inline size_t
-rbimpl_atomic_size_exchange(volatile size_t *ptr, size_t val)
+rbimpl_atomic_size_exchange(volatile size_t *ptr, size_t val, int memory_order)
{
+ (void)memory_order;
#if 0
#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
- return __atomic_exchange_n(ptr, val, __ATOMIC_SEQ_CST);
+ return __atomic_exchange_n(ptr, val, memory_order);
#elif defined(HAVE_GCC_SYNC_BUILTINS)
return __sync_lock_test_and_set(ptr, val);
@@ -844,11 +880,11 @@ rbimpl_atomic_size_exchange(volatile size_t *ptr, size_t val)
RBIMPL_STATIC_ASSERT(size_of_size_t, sizeof *ptr == sizeof(rb_atomic_t));
volatile rb_atomic_t *const tmp = RBIMPL_CAST((volatile rb_atomic_t *)ptr);
- const rb_atomic_t ret = rbimpl_atomic_exchange(tmp, val);
+ const rb_atomic_t ret = rbimpl_atomic_exchange(tmp, val, memory_order);
return RBIMPL_CAST((size_t)ret);
#elif defined(HAVE_STDATOMIC_H)
- return atomic_exchange((_Atomic volatile size_t *)ptr, val);
+ return atomic_exchange_explicit((_Atomic volatile size_t *)ptr, val, memory_order);
#else
# error Unsupported platform.
@@ -859,15 +895,16 @@ RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL((1))
static inline void
-rbimpl_atomic_size_set(volatile size_t *ptr, size_t val)
+rbimpl_atomic_size_store(volatile size_t *ptr, size_t val, int memory_order)
{
+ (void)memory_order;
#if 0
#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
- __atomic_store_n(ptr, val, __ATOMIC_SEQ_CST);
+ __atomic_store_n(ptr, val, memory_order);
#else
- rbimpl_atomic_size_exchange(ptr, val);
+ rbimpl_atomic_size_exchange(ptr, val, memory_order);
#endif
}
@@ -876,8 +913,9 @@ RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL((1))
static inline void *
-rbimpl_atomic_ptr_exchange(void *volatile *ptr, const void *val)
+rbimpl_atomic_ptr_exchange(void *volatile *ptr, const void *val, int memory_order)
{
+ (void)memory_order;
#if 0
#elif defined(InterlockedExchangePointer)
@@ -894,7 +932,7 @@ rbimpl_atomic_ptr_exchange(void *volatile *ptr, const void *val)
const size_t sval = RBIMPL_CAST((size_t)val);
volatile size_t *const sptr = RBIMPL_CAST((volatile size_t *)ptr);
- const size_t sret = rbimpl_atomic_size_exchange(sptr, sval);
+ const size_t sret = rbimpl_atomic_size_exchange(sptr, sval, memory_order);
return RBIMPL_CAST((void *)sret);
#endif
@@ -904,26 +942,26 @@ RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL((1))
static inline void
-rbimpl_atomic_ptr_set(volatile void **ptr, void *val)
+rbimpl_atomic_ptr_store(volatile void **ptr, void *val, int memory_order)
{
RBIMPL_STATIC_ASSERT(sizeof_value, sizeof *ptr == sizeof(size_t));
const size_t sval = RBIMPL_CAST((size_t)val);
volatile size_t *const sptr = RBIMPL_CAST((volatile size_t *)ptr);
- rbimpl_atomic_size_set(sptr, sval);
+ rbimpl_atomic_size_store(sptr, sval, memory_order);
}
RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL((1))
static inline VALUE
-rbimpl_atomic_value_exchange(volatile VALUE *ptr, VALUE val)
+rbimpl_atomic_value_exchange(volatile VALUE *ptr, VALUE val, int memory_order)
{
RBIMPL_STATIC_ASSERT(sizeof_value, sizeof *ptr == sizeof(size_t));
const size_t sval = RBIMPL_CAST((size_t)val);
volatile size_t *const sptr = RBIMPL_CAST((volatile size_t *)ptr);
- const size_t sret = rbimpl_atomic_size_exchange(sptr, sval);
+ const size_t sret = rbimpl_atomic_size_exchange(sptr, sval, memory_order);
return RBIMPL_CAST((VALUE)sret);
}
@@ -931,27 +969,28 @@ RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL((1))
static inline void
-rbimpl_atomic_value_set(volatile VALUE *ptr, VALUE val)
+rbimpl_atomic_value_store(volatile VALUE *ptr, VALUE val, int memory_order)
{
RBIMPL_STATIC_ASSERT(sizeof_value, sizeof *ptr == sizeof(size_t));
const size_t sval = RBIMPL_CAST((size_t)val);
volatile size_t *const sptr = RBIMPL_CAST((volatile size_t *)ptr);
- rbimpl_atomic_size_set(sptr, sval);
+ rbimpl_atomic_size_store(sptr, sval, memory_order);
}
RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL((1))
static inline rb_atomic_t
-rbimpl_atomic_load(volatile rb_atomic_t *ptr)
+rbimpl_atomic_load(volatile rb_atomic_t *ptr, int memory_order)
{
+ (void)memory_order;
#if 0
#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
- return __atomic_load_n(ptr, __ATOMIC_SEQ_CST);
+ return __atomic_load_n(ptr, memory_order);
#else
- return rbimpl_atomic_fetch_add(ptr, 0);
+ return rbimpl_atomic_fetch_add(ptr, 0, memory_order);
#endif
}
@@ -959,16 +998,17 @@ RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL((1))
static inline void
-rbimpl_atomic_set(volatile rb_atomic_t *ptr, rb_atomic_t val)
+rbimpl_atomic_store(volatile rb_atomic_t *ptr, rb_atomic_t val, int memory_order)
{
+ (void)memory_order;
#if 0
#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
- __atomic_store_n(ptr, val, __ATOMIC_SEQ_CST);
+ __atomic_store_n(ptr, val, memory_order);
#else
/* Maybe std::atomic::store can be faster? */
- rbimpl_atomic_exchange(ptr, val);
+ rbimpl_atomic_exchange(ptr, val, memory_order);
#endif
}
@@ -977,13 +1017,15 @@ RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL((1))
static inline rb_atomic_t
-rbimpl_atomic_cas(volatile rb_atomic_t *ptr, rb_atomic_t oldval, rb_atomic_t newval)
+rbimpl_atomic_cas(volatile rb_atomic_t *ptr, rb_atomic_t oldval, rb_atomic_t newval, int success_memorder, int failure_memorder)
{
+ (void)success_memorder;
+ (void)failure_memorder;
#if 0
#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
__atomic_compare_exchange_n(
- ptr, &oldval, newval, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+ ptr, &oldval, newval, 0, success_memorder, failure_memorder);
return oldval;
#elif defined(HAVE_GCC_SYNC_BUILTINS)
@@ -1003,8 +1045,8 @@ rbimpl_atomic_cas(volatile rb_atomic_t *ptr, rb_atomic_t oldval, rb_atomic_t new
return atomic_cas_uint(ptr, oldval, newval);
#elif defined(HAVE_STDATOMIC_H)
- atomic_compare_exchange_strong(
- (_Atomic volatile rb_atomic_t *)ptr, &oldval, newval);
+ atomic_compare_exchange_strong_explicit(
+ (_Atomic volatile rb_atomic_t *)ptr, &oldval, newval, success_memorder, failure_memorder);
return oldval;
#else
@@ -1025,13 +1067,15 @@ RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL((1))
static inline size_t
-rbimpl_atomic_size_cas(volatile size_t *ptr, size_t oldval, size_t newval)
+rbimpl_atomic_size_cas(volatile size_t *ptr, size_t oldval, size_t newval, int success_memorder, int failure_memorder)
{
+ (void)success_memorder;
+ (void)failure_memorder;
#if 0
#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
__atomic_compare_exchange_n(
- ptr, &oldval, newval, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+ ptr, &oldval, newval, 0, success_memorder, failure_memorder);
return oldval;
#elif defined(HAVE_GCC_SYNC_BUILTINS)
@@ -1047,11 +1091,11 @@ rbimpl_atomic_size_cas(volatile size_t *ptr, size_t oldval, size_t newval)
RBIMPL_STATIC_ASSERT(size_of_size_t, sizeof *ptr == sizeof(rb_atomic_t));
volatile rb_atomic_t *tmp = RBIMPL_CAST((volatile rb_atomic_t *)ptr);
- return rbimpl_atomic_cas(tmp, oldval, newval);
+ return rbimpl_atomic_cas(tmp, oldval, newval, success_memorder, failure_memorder);
#elif defined(HAVE_STDATOMIC_H)
- atomic_compare_exchange_strong(
- (_Atomic volatile size_t *)ptr, &oldval, newval);
+ atomic_compare_exchange_strong_explicit(
+ (_Atomic volatile size_t *)ptr, &oldval, newval, success_memorder, failure_memorder);
return oldval;
#else
@@ -1063,8 +1107,10 @@ RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL((1))
static inline void *
-rbimpl_atomic_ptr_cas(void **ptr, const void *oldval, const void *newval)
+rbimpl_atomic_ptr_cas(void **ptr, const void *oldval, const void *newval, int success_memorder, int failure_memorder)
{
+ (void)success_memorder;
+ (void)failure_memorder;
#if 0
#elif defined(InterlockedExchangePointer)
@@ -1087,7 +1133,7 @@ rbimpl_atomic_ptr_cas(void **ptr, const void *oldval, const void *newval)
const size_t snew = RBIMPL_CAST((size_t)newval);
const size_t sold = RBIMPL_CAST((size_t)oldval);
volatile size_t *const sptr = RBIMPL_CAST((volatile size_t *)ptr);
- const size_t sret = rbimpl_atomic_size_cas(sptr, sold, snew);
+ const size_t sret = rbimpl_atomic_size_cas(sptr, sold, snew, success_memorder, failure_memorder);
return RBIMPL_CAST((void *)sret);
#endif
@@ -1097,15 +1143,16 @@ RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL((1))
static inline void *
-rbimpl_atomic_ptr_load(void **ptr)
+rbimpl_atomic_ptr_load(void **ptr, int memory_order)
{
+ (void)memory_order;
#if 0
#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
- return __atomic_load_n(ptr, __ATOMIC_SEQ_CST);
+ return __atomic_load_n(ptr, memory_order);
#else
void *val = *ptr;
- return rbimpl_atomic_ptr_cas(ptr, val, val);
+ return rbimpl_atomic_ptr_cas(ptr, val, val, memory_order, memory_order);
#endif
}
@@ -1113,14 +1160,23 @@ RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL((1))
static inline VALUE
-rbimpl_atomic_value_cas(volatile VALUE *ptr, VALUE oldval, VALUE newval)
+rbimpl_atomic_value_load(volatile VALUE *ptr, int memory_order)
+{
+ return RBIMPL_CAST((VALUE)rbimpl_atomic_ptr_load((void **)ptr, memory_order));
+}
+
+RBIMPL_ATTR_ARTIFICIAL()
+RBIMPL_ATTR_NOALIAS()
+RBIMPL_ATTR_NONNULL((1))
+static inline VALUE
+rbimpl_atomic_value_cas(volatile VALUE *ptr, VALUE oldval, VALUE newval, int success_memorder, int failure_memorder)
{
RBIMPL_STATIC_ASSERT(sizeof_value, sizeof *ptr == sizeof(size_t));
const size_t snew = RBIMPL_CAST((size_t)newval);
const size_t sold = RBIMPL_CAST((size_t)oldval);
volatile size_t *const sptr = RBIMPL_CAST((volatile size_t *)ptr);
- const size_t sret = rbimpl_atomic_size_cas(sptr, sold, snew);
+ const size_t sret = rbimpl_atomic_size_cas(sptr, sold, snew, success_memorder, failure_memorder);
return RBIMPL_CAST((VALUE)sret);
}
/** @endcond */
diff --git a/ruby_atomic.h b/ruby_atomic.h
index 1ccabcbdf6ba6a..ad53356f069ce2 100644
--- a/ruby_atomic.h
+++ b/ruby_atomic.h
@@ -3,7 +3,7 @@
#include "ruby/atomic.h"
-#define RUBY_ATOMIC_VALUE_LOAD(x) (VALUE)(RUBY_ATOMIC_PTR_LOAD(x))
+#define RUBY_ATOMIC_VALUE_LOAD(x) rbimpl_atomic_value_load(&(x), RBIMPL_ATOMIC_SEQ_CST)
/* shim macros only */
#define ATOMIC_ADD(var, val) RUBY_ATOMIC_ADD(var, val)
@@ -27,16 +27,7 @@
#define ATOMIC_VALUE_CAS(var, oldval, val) RUBY_ATOMIC_VALUE_CAS(var, oldval, val)
#define ATOMIC_VALUE_EXCHANGE(var, val) RUBY_ATOMIC_VALUE_EXCHANGE(var, val)
-static inline rb_atomic_t
-rbimpl_atomic_load_relaxed(volatile rb_atomic_t *ptr)
-{
-#if defined(HAVE_GCC_ATOMIC_BUILTINS)
- return __atomic_load_n(ptr, __ATOMIC_RELAXED);
-#else
- return *ptr;
-#endif
-}
-#define ATOMIC_LOAD_RELAXED(var) rbimpl_atomic_load_relaxed(&(var))
+#define ATOMIC_LOAD_RELAXED(var) rbimpl_atomic_load(&(var), RBIMPL_ATOMIC_RELAXED)
typedef RBIMPL_ALIGNAS(8) uint64_t rbimpl_atomic_uint64_t;
diff --git a/test/openssl/test_pkey_dh.rb b/test/openssl/test_pkey_dh.rb
index c82f642c016338..f0c42866ea5df7 100644
--- a/test/openssl/test_pkey_dh.rb
+++ b/test/openssl/test_pkey_dh.rb
@@ -103,6 +103,8 @@ def test_generate_key
end if !openssl?(3, 0, 0)
def test_params_ok?
+ omit_on_fips
+
# Skip the tests in old OpenSSL version 1.1.1c or early versions before
# applying the following commits in OpenSSL 1.1.1d to make `DH_check`
# function pass the RFC 7919 FFDHE group texts.
diff --git a/test/openssl/test_pkey_ec.rb b/test/openssl/test_pkey_ec.rb
index 1953b4c2dae6b8..e569397c0a874c 100644
--- a/test/openssl/test_pkey_ec.rb
+++ b/test/openssl/test_pkey_ec.rb
@@ -72,6 +72,8 @@ def test_marshal
end
def test_check_key
+ omit_on_fips
+
key0 = Fixtures.pkey("p256")
assert_equal(true, key0.check_key)
assert_equal(true, key0.private?)
diff --git a/tool/zjit_bisect.rb b/tool/zjit_bisect.rb
index a4280a4ec2b8ab..47d6071d3b92f3 100755
--- a/tool/zjit_bisect.rb
+++ b/tool/zjit_bisect.rb
@@ -118,6 +118,11 @@ def run_with_jit_list(ruby, options, jit_list)
jit_list = File.readlines(temp_file.path).map(&:strip).reject(&:empty?)
end
LOGGER.info("Starting with JIT list of #{jit_list.length} items.")
+# Try running without the optimizer
+_, stderr, exitcode = run_with_jit_list(RUBY, ["--zjit-disable-hir-opt", *OPTIONS], jit_list)
+if exitcode == 0
+ LOGGER.warn "*** Command suceeded with HIR optimizer disabled. HIR optimizer is probably at fault. ***"
+end
# Now narrow it down
command = lambda do |items|
_, _, exitcode = run_with_jit_list(RUBY, OPTIONS, items)
diff --git a/variable.c b/variable.c
index 76b16b04cb3968..e0a85b8f483ef1 100644
--- a/variable.c
+++ b/variable.c
@@ -2734,21 +2734,12 @@ struct autoload_data {
};
static void
-autoload_data_compact(void *ptr)
+autoload_data_mark_and_move(void *ptr)
{
struct autoload_data *p = ptr;
- p->feature = rb_gc_location(p->feature);
- p->mutex = rb_gc_location(p->mutex);
-}
-
-static void
-autoload_data_mark(void *ptr)
-{
- struct autoload_data *p = ptr;
-
- rb_gc_mark_movable(p->feature);
- rb_gc_mark_movable(p->mutex);
+ rb_gc_mark_and_move(&p->feature);
+ rb_gc_mark_and_move(&p->mutex);
}
static void
@@ -2772,32 +2763,20 @@ autoload_data_memsize(const void *ptr)
static const rb_data_type_t autoload_data_type = {
"autoload_data",
- {autoload_data_mark, autoload_data_free, autoload_data_memsize, autoload_data_compact},
+ {autoload_data_mark_and_move, autoload_data_free, autoload_data_memsize, autoload_data_mark_and_move},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
};
static void
-autoload_const_compact(void *ptr)
-{
- struct autoload_const *ac = ptr;
-
- ac->module = rb_gc_location(ac->module);
- ac->autoload_data_value = rb_gc_location(ac->autoload_data_value);
- ac->value = rb_gc_location(ac->value);
- ac->file = rb_gc_location(ac->file);
- ac->namespace = rb_gc_location(ac->namespace);
-}
-
-static void
-autoload_const_mark(void *ptr)
+autoload_const_mark_and_move(void *ptr)
{
struct autoload_const *ac = ptr;
- rb_gc_mark_movable(ac->module);
- rb_gc_mark_movable(ac->autoload_data_value);
- rb_gc_mark_movable(ac->value);
- rb_gc_mark_movable(ac->file);
- rb_gc_mark_movable(ac->namespace);
+ rb_gc_mark_and_move(&ac->module);
+ rb_gc_mark_and_move(&ac->autoload_data_value);
+ rb_gc_mark_and_move(&ac->value);
+ rb_gc_mark_and_move(&ac->file);
+ rb_gc_mark_and_move(&ac->namespace);
}
static size_t
@@ -2817,7 +2796,7 @@ autoload_const_free(void *ptr)
static const rb_data_type_t autoload_const_type = {
"autoload_const",
- {autoload_const_mark, autoload_const_free, autoload_const_memsize, autoload_const_compact,},
+ {autoload_const_mark_and_move, autoload_const_free, autoload_const_memsize, autoload_const_mark_and_move,},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
};
diff --git a/zjit/src/backend/lir.rs b/zjit/src/backend/lir.rs
index 86bea62fcd34f0..7d3afab7a951c1 100644
--- a/zjit/src/backend/lir.rs
+++ b/zjit/src/backend/lir.rs
@@ -1889,9 +1889,9 @@ impl Assembler {
out
}
- pub fn add_into(&mut self, left: Opnd, right: Opnd) -> Opnd {
+ pub fn add_into(&mut self, left: Opnd, right: Opnd) {
+ assert!(matches!(left, Opnd::Reg(_)), "Destination of add_into must be Opnd::Reg, but got: {left:?}");
self.push_insn(Insn::Add { left, right, out: left });
- left
}
#[must_use]
@@ -2233,10 +2233,9 @@ impl Assembler {
out
}
- pub fn sub_into(&mut self, left: Opnd, right: Opnd) -> Opnd {
- let out = self.sub(left, right);
- self.mov(left, out);
- out
+ pub fn sub_into(&mut self, left: Opnd, right: Opnd) {
+ assert!(matches!(left, Opnd::Reg(_)), "Destination of sub_into must be Opnd::Reg, but got: {left:?}");
+ self.push_insn(Insn::Sub { left, right, out: left });
}
#[must_use]
diff --git a/zjit/src/backend/x86_64/mod.rs b/zjit/src/backend/x86_64/mod.rs
index 8027c74b182e66..718f76837b4069 100644
--- a/zjit/src/backend/x86_64/mod.rs
+++ b/zjit/src/backend/x86_64/mod.rs
@@ -197,9 +197,15 @@ impl Assembler
}
},
// We have to load memory operands to avoid corrupting them
- (Opnd::Mem(_) | Opnd::Reg(_), _) => {
+ (Opnd::Mem(_), _) => {
*left = asm.load(*left);
},
+ // We have to load register operands to avoid corrupting them
+ (Opnd::Reg(_), _) => {
+ if *left != *out {
+ *left = asm.load(*left);
+ }
+ },
// The first operand can't be an immediate value
(Opnd::UImm(_), _) => {
*left = asm.load(*left);
@@ -1164,7 +1170,21 @@ mod tests {
asm.mov(CFP, sp); // should be merged to add
asm.compile_with_num_regs(&mut cb, 1);
- assert_eq!(format!("{:x}", cb), "4983c540");
+ assert_disasm!(cb, "4983c540", {"
+ 0x0: add r13, 0x40
+ "});
+ }
+
+ #[test]
+ fn test_add_into() {
+ let (mut asm, mut cb) = setup_asm();
+
+ asm.add_into(CFP, Opnd::UImm(0x40));
+ asm.compile_with_num_regs(&mut cb, 1);
+
+ assert_disasm!(cb, "4983c540", {"
+ 0x0: add r13, 0x40
+ "});
}
#[test]
@@ -1175,7 +1195,21 @@ mod tests {
asm.mov(CFP, sp); // should be merged to add
asm.compile_with_num_regs(&mut cb, 1);
- assert_eq!(format!("{:x}", cb), "4983ed40");
+ assert_disasm!(cb, "4983ed40", {"
+ 0x0: sub r13, 0x40
+ "});
+ }
+
+ #[test]
+ fn test_sub_into() {
+ let (mut asm, mut cb) = setup_asm();
+
+ asm.sub_into(CFP, Opnd::UImm(0x40));
+ asm.compile_with_num_regs(&mut cb, 1);
+
+ assert_disasm!(cb, "4983ed40", {"
+ 0x0: sub r13, 0x40
+ "});
}
#[test]
diff --git a/zjit/src/codegen.rs b/zjit/src/codegen.rs
index b1b43abbe6dc03..9fc3b643b7bb5f 100644
--- a/zjit/src/codegen.rs
+++ b/zjit/src/codegen.rs
@@ -1275,7 +1275,9 @@ fn compile_iseq(iseq: IseqPtr) -> Option {
return None;
}
};
- function.optimize();
+ if !get_option!(disable_hir_opt) {
+ function.optimize();
+ }
if let Err(err) = function.validate() {
debug!("ZJIT: compile_iseq: {err:?}");
return None;
diff --git a/zjit/src/options.rs b/zjit/src/options.rs
index 07584c9b99d380..94a6988a4fddc5 100644
--- a/zjit/src/options.rs
+++ b/zjit/src/options.rs
@@ -35,6 +35,9 @@ pub struct Options {
/// Enable debug logging
pub debug: bool,
+ /// Turn off the HIR optimizer
+ pub disable_hir_opt: bool,
+
/// Dump initial High-level IR before optimization
pub dump_hir_init: Option,
@@ -66,6 +69,7 @@ impl Default for Options {
num_profiles: 1,
stats: false,
debug: false,
+ disable_hir_opt: false,
dump_hir_init: None,
dump_hir_opt: None,
dump_hir_graphviz: false,
@@ -210,6 +214,8 @@ fn parse_option(str_ptr: *const std::os::raw::c_char) -> Option<()> {
("debug", "") => options.debug = true,
+ ("disable-hir-opt", "") => options.disable_hir_opt = true,
+
// --zjit-dump-hir dumps the actual input to the codegen, which is currently the same as --zjit-dump-hir-opt.
("dump-hir" | "dump-hir-opt", "") => options.dump_hir_opt = Some(DumpHIR::WithoutSnapshot),
("dump-hir" | "dump-hir-opt", "all") => options.dump_hir_opt = Some(DumpHIR::All),