forked from ruby/ruby
-
Notifications
You must be signed in to change notification settings - Fork 0
[pull] master from ruby:master #32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Now `$LOADED_FEATURES` list is being maintained by `setup` and `teardown` and, only libaries under the temporary directory will be removed. As `save_loaded_features` removes the rest libraries other than this test directory, ordinary libraries loaded from files under rubygems also removed, and often causes constant redefinition warnings. ruby/rubygems@9e1f92aafd
Doing it this way is simpler and it doesn't end up adding "/" to the list of folders, so it doesn't need to be removed later. ruby/fileutils@df08e124ce
I think it's debatable which is the most common usage of
`FileUtils.mkdir_p`, but even assuming the most common use case is
creating a folder when it doesn't previously exist but the parent does,
this optimization doesn't seem to have a noticiable effect there while
harming other use cases.
For benchmarks, I created this script
```ruby
require "benchmark/ips"
Benchmark.ips do |x|
x.report("old mkdir_p - exists") do
FileUtils.mkdir_p "/tmp"
end
x.report("new_mkdir_p - exists") do
FileUtils.mkdir_p_new "/tmp"
end
x.compare!
end
FileUtils.rm_rf "/tmp/foo"
Benchmark.ips do |x|
x.report("old mkdir_p - doesnt exist, parent exists") do
FileUtils.mkdir_p "/tmp/foo"
FileUtils.rm_rf "/tmp/foo"
end
x.report("new_mkdir_p - doesnt exist, parent exists") do
FileUtils.mkdir_p_new "/tmp/foo"
FileUtils.rm_rf "/tmp/foo"
end
x.compare!
end
Benchmark.ips do |x|
x.report("old mkdir_p - doesnt exist, parent either") do
FileUtils.mkdir_p "/tmp/foo/bar"
FileUtils.rm_rf "/tmp/foo"
end
x.report("new_mkdir_p - doesnt exist, parent either") do
FileUtils.mkdir_p_new "/tmp/foo/bar"
FileUtils.rm_rf "/tmp/foo"
end
x.compare!
end
Benchmark.ips do |x|
x.report("old mkdir_p - more levels") do
FileUtils.mkdir_p "/tmp/foo/bar/baz"
FileUtils.rm_rf "/tmp/foo"
end
x.report("new_mkdir_p - more levels") do
FileUtils.mkdir_p_new "/tmp/foo/bar/baz"
FileUtils.rm_rf "/tmp/foo"
end
x.compare!
end
```
and copied the method with the "optimization" removed as
`FileUtils.mkdir_p_new`. The results are as below:
```
Warming up --------------------------------------
old mkdir_p - exists 15.914k i/100ms
new_mkdir_p - exists 46.512k i/100ms
Calculating -------------------------------------
old mkdir_p - exists 161.461k (± 3.2%) i/s - 811.614k in 5.032315s
new_mkdir_p - exists 468.192k (± 2.9%) i/s - 2.372M in 5.071225s
Comparison:
new_mkdir_p - exists: 468192.1 i/s
old mkdir_p - exists: 161461.0 i/s - 2.90x (± 0.00) slower
Warming up --------------------------------------
old mkdir_p - doesnt exist, parent exists
2.142k i/100ms
new_mkdir_p - doesnt exist, parent exists
1.961k i/100ms
Calculating -------------------------------------
old mkdir_p - doesnt exist, parent exists
21.242k (± 6.7%) i/s - 107.100k in 5.069206s
new_mkdir_p - doesnt exist, parent exists
19.682k (± 4.2%) i/s - 100.011k in 5.091961s
Comparison:
old mkdir_p - doesnt exist, parent exists: 21241.7 i/s
new_mkdir_p - doesnt exist, parent exists: 19681.7 i/s - same-ish: difference falls within error
Warming up --------------------------------------
old mkdir_p - doesnt exist, parent either
945.000 i/100ms
new_mkdir_p - doesnt exist, parent either
1.002k i/100ms
Calculating -------------------------------------
old mkdir_p - doesnt exist, parent either
9.689k (± 4.4%) i/s - 49.140k in 5.084342s
new_mkdir_p - doesnt exist, parent either
10.806k (± 4.6%) i/s - 54.108k in 5.020714s
Comparison:
new_mkdir_p - doesnt exist, parent either: 10806.3 i/s
old mkdir_p - doesnt exist, parent either: 9689.3 i/s - 1.12x (± 0.00) slower
Warming up --------------------------------------
old mkdir_p - more levels
702.000 i/100ms
new_mkdir_p - more levels
775.000 i/100ms
Calculating -------------------------------------
old mkdir_p - more levels
7.046k (± 3.5%) i/s - 35.802k in 5.087548s
new_mkdir_p - more levels
7.685k (± 5.5%) i/s - 38.750k in 5.061351s
Comparison:
new_mkdir_p - more levels: 7685.1 i/s
old mkdir_p - more levels: 7046.4 i/s - same-ish: difference falls within error
```
I think it's better to keep the code simpler is the optimization is not
so clear like in this case.
ruby/fileutils@e842a0e70e
- this change get rid of a warning of mswin build. see include/ruby/internal/encoding/encoding.h(116)
See related commits: - ebc66662 for #=== - 4943d208 for #[], #[]=, #<<, and #>> ruby/rdoc@8e47f7840a
Treats Integer#% and Float#%.
Treats:
Integer#divmod
Float#divmod
Numeric#divmod
Implements [Feature #14347]
Treats Numeric#remainder and Integer#remainder.
This change fixes alias call-seq to return nil if the method's call-seq does not specify the alias. Previously, the alias's call-seq would be an empty string in this case which broke darkfish rendering. This change also backfills test coverage for 0ead786 which moved call-seq deduplication into AnyMethod. ruby/rdoc@5ce2789b6f
Commit ee037e146037 ("ssl: remove SSL::SSLContext#tmp_ecdh_callback",
2020-08-12) forgot to remove the method.
ruby/openssl@bef9ea84e4
Provide a wrapper of SSL_set0_tmp_dh_pkey()/SSL_CTX_set_tmp_dh(), which sets the DH parameters used for ephemeral DH key exchange. SSLContext#tmp_dh_callback= already exists for this purpose, as a wrapper around SSL_CTX_set_tmp_dh_callback(), but it is considered obsolete and the OpenSSL API is deprecated for future removal. There is no practical use case where an application needs to use different DH parameters nowadays. This was originally introduced to support export grade ciphers. RDoc for #tmp_dh_callback= is updated to recommend the new #tmp_dh=. Note that current versions of OpenSSL support automatic ECDHE curve selection which is enabled by default. SSLContext#tmp_dh= should only be necessary if you must allow ancient clients which don't support ECDHE. ruby/openssl@aa43da4f04
[ This is a backport to the 2.1 branch. ] Fixed misspellings reported at [Bug #16437], for default gems. (cherry picked from commit e68999c) ruby/openssl@0f43789503
Since a blocking SSLSocket#syswrite call allows context switches while waiting for the underlying socket to be ready, we must freeze the string buffer to prevent other threads from modifying it. Reference: ruby/openssl#452 ruby/openssl@aea874bc6e
Similarly to SSLSocket#syswrite, the blocking SSLSocket#sysread allows context switches. We must prevent other threads from modifying the string buffer. We can use rb_str_locktmp() and rb_str_unlocktmp() to temporarily prohibit modification of the string. ruby/openssl@d38274949f
TS_time_cb on libressl expects an long long/time_t 64 bits long instead. ruby/openssl@4c99f577b2
prevent `ossl_ts_*_free()` from calling when `d2i_TS_*_bio()` failed. ruby/openssl@b29e215786
The digest library is a default gem now, too. Therefore we can't simply use rb_require() to load it, but we should use Kernel#require instead. This change is based on the suggestion by David Rodríguez in ruby/digest@1617261#commitcomment-57778397 ruby/openssl@157f80794b
…SLSocket objects We store the reverse reference to the Ruby object in the OpenSSL struct for use from OpenSSL callback functions. To prevent the Ruby object from being relocated by GC.compact, we must "pin" it by calling rb_gc_mark(). ruby/openssl@022b7ceada
…StoreContext We store the reverse reference to the Ruby object in the OpenSSL struct for use from OpenSSL callback functions. To prevent the Ruby object from being relocated by GC.compact, we must "pin" it by calling rb_gc_mark(). ruby/openssl@a6ba9f894f
On the server side, the serialized list of protocols is stored in SSL_CTX as a String object reference. We utilize a hidden instance variable to prevent it from being GC'ed, but this is not enough because it can also be relocated by GC.compact. ruby/openssl@5eb68ba778
…es on LibreSSL LibreSSL 2.2.x has a bug in the Finished message handling with TLS 1.3. This is fixed by LibreSSL 3.3.2. ruby/openssl@0bea59d245
Drop support for Ruby 2.3, 2.4, and 2.5. As of 2021-10, Ruby 2.6 is the oldest version that still receives security fixes from the Ruby core team, so it doesn't make much sense to keep code for those ancient versions. ruby/openssl@3436bd040d
pull bot
pushed a commit
that referenced
this pull request
Sep 6, 2023
[Bug #19793]
Dummy frames are created at the top level when requiring another file.
While requiring a file, it will try to convert using encodings. Some of
these encodings will not respond to to_str. If method_missing is
redefined on Object, then it will call method_missing and attempt raise
an error. However, the iseq is invalid as it's a dummy frame so it will
write an invalid iseq to the created NoMethodError.
The following script crashes:
```
GC.stress = true
class Object
public :method_missing
end
File.write("/tmp/empty.rb", "")
require "/tmp/empty.rb"
```
With the following backtrace:
```
frame #0: 0x00000001000fa8b8 miniruby`RVALUE_MARKED(obj=4308637824) at gc.c:1638:12
frame #1: 0x00000001000fb440 miniruby`RVALUE_BLACK_P(obj=4308637824) at gc.c:1763:12
frame #2: 0x00000001000facdc miniruby`gc_writebarrier_incremental(a=4308637824, b=4308332208, objspace=0x000000010180b000) at gc.c:8822:9
frame #3: 0x00000001000faad8 miniruby`rb_gc_writebarrier(a=4308637824, b=4308332208) at gc.c:8864:17
frame #4: 0x000000010016aff0 miniruby`rb_obj_written(a=4308637824, oldv=36, b=4308332208, filename="../iseq.c", line=1279) at gc.h:804:9
frame #5: 0x0000000100162a60 miniruby`rb_obj_write(a=4308637824, slot=0x0000000100d09888, b=4308332208, filename="../iseq.c", line=1279) at gc.h:837:5
frame #6: 0x0000000100165b0c miniruby`iseqw_new(iseq=0x0000000100d09880) at iseq.c:1279:9
frame #7: 0x0000000100165a64 miniruby`rb_iseqw_new(iseq=0x0000000100d09880) at iseq.c:1289:12
frame #8: 0x00000001000d8324 miniruby`name_err_init_attr(exc=4309777920, recv=4304780496, method=827660) at error.c:1830:35
frame #9: 0x00000001000d1b80 miniruby`name_err_init(exc=4309777920, mesg=4308332496, recv=4304780496, method=827660) at error.c:1869:12
frame #10: 0x00000001000d1bd4 miniruby`rb_nomethod_err_new(mesg=4308332496, recv=4304780496, method=827660, args=4308332448, priv=0) at error.c:1957:5
frame #11: 0x000000010039049c miniruby`rb_make_no_method_exception(exc=4304914512, format=4308332496, obj=4304780496, argc=1, argv=0x000000016fdfab00, priv=0) at vm_eval.c:959:16
frame #12: 0x00000001003b3274 miniruby`raise_method_missing(ec=0x0000000100b06f40, argc=1, argv=0x000000016fdfab00, obj=4304780496, last_call_status=MISSING_NOENTRY) at vm_eval.c:999:15
frame #13: 0x00000001003945d4 miniruby`rb_method_missing(argc=1, argv=0x000000016fdfab00, obj=4304780496) at vm_eval.c:944:5
...
frame #23: 0x000000010038f5e4 miniruby`rb_vm_call_kw(ec=0x0000000100b06f40, recv=4304780496, id=2865, argc=1, argv=0x000000016fdfab00, me=0x0000000100cbfcf0, kw_splat=0) at vm_eval.c:326:12
frame #24: 0x00000001003c18e4 miniruby`call_method_entry(ec=0x0000000100b06f40, defined_class=4304927952, obj=4304780496, id=2865, cme=0x0000000100cbfcf0, argc=1, argv=0x000000016fdfab00, kw_splat=0) at vm_method.c:2720:20
frame #25: 0x00000001003c440c miniruby`check_funcall_exec(v=6171896792) at vm_eval.c:589:12
frame #26: 0x00000001000dec00 miniruby`rb_vrescue2(b_proc=(miniruby`check_funcall_exec at vm_eval.c:587), data1=6171896792, r_proc=(miniruby`check_funcall_failed at vm_eval.c:596), data2=6171896792, args="Pȗ") at eval.c:919:18
frame #27: 0x00000001000deab0 miniruby`rb_rescue2(b_proc=(miniruby`check_funcall_exec at vm_eval.c:587), data1=6171896792, r_proc=(miniruby`check_funcall_failed at vm_eval.c:596), data2=6171896792) at eval.c:900:17
frame #28: 0x000000010039008c miniruby`check_funcall_missing(ec=0x0000000100b06f40, klass=4304923536, recv=4304780496, mid=3233, argc=0, argv=0x0000000000000000, respond=-1, def=36, kw_splat=0) at vm_eval.c:666:15
frame #29: 0x000000010038fa60 miniruby`rb_check_funcall_default_kw(recv=4304780496, mid=3233, argc=0, argv=0x0000000000000000, def=36, kw_splat=0) at vm_eval.c:703:21
frame #30: 0x000000010038fb04 miniruby`rb_check_funcall(recv=4304780496, mid=3233, argc=0, argv=0x0000000000000000) at vm_eval.c:685:12
frame #31: 0x00000001001c469c miniruby`convert_type_with_id(val=4304780496, tname="String", method=3233, raise=0, index=-1) at object.c:3061:15
frame #32: 0x00000001001c4a4c miniruby`rb_check_convert_type_with_id(val=4304780496, type=5, tname="String", method=3233) at object.c:3153:9
frame #33: 0x00000001002d59f8 miniruby`rb_check_string_type(str=4304780496) at string.c:2571:11
frame #34: 0x000000010014b7b0 miniruby`io_encoding_set(fptr=0x0000000100d09ca0, v1=4304780496, v2=4, opt=4) at io.c:11655:19
frame #35: 0x0000000100139a58 miniruby`rb_io_set_encoding(argc=1, argv=0x000000016fdfb450, io=4308334032) at io.c:13497:5
frame #36: 0x00000001003c0004 miniruby`ractor_safe_call_cfunc_m1(recv=4308334032, argc=1, argv=0x000000016fdfb450, func=(miniruby`rb_io_set_encoding at io.c:13487)) at vm_insnhelper.c:3271:12
...
frame #43: 0x0000000100390b08 miniruby`rb_funcall(recv=4308334032, mid=16593, n=1) at vm_eval.c:1137:12
frame #44: 0x00000001002a43d8 miniruby`load_file_internal(argp_v=6171899936) at ruby.c:2500:5
...
```
pull bot
pushed a commit
that referenced
this pull request
Jul 29, 2025
Previously, ZJIT miscompiled the following because of native SP
interference.
def a(n1,n2,n3,n4,n5,n6,n7,n8) = [n8]
a(0,0,0,0,0,0,0, :ok)
Commented problematic disassembly:
; call rb_ary_new_capa
mov x0, #1
mov x16, #0x1278
movk x16, #0x4bc, lsl #16
movk x16, #1, lsl #32
blr x16
; call rb_ary_push
mov x1, x0
str x1, [sp, #-0x10]! ; c_push() from alloc_regs()
mov x0, x1 ; arg0, the array
ldur x1, [sp] ; meant to be arg1=n8, but sp just moved!
mov x16, #0x3968
movk x16, #0x4bc, lsl #16
movk x16, #1, lsl #32
blr x16
Since the frame pointer stays constant in the body of the function,
static offsets based on it don't run the risk of being invalidated by SP
movements.
Pass the registers to preserve through Insn::FrameSetup. This allows ARM
to use STP and waste no gaps between EC, SP, and CFP.
x86 now preserves and restores RBP since we use it as the frame pointer.
Since all arches now have a frame pointer, remove offset based SP
movement in the epilogue and restore registers using the frame pointer.
pull bot
pushed a commit
that referenced
this pull request
Jul 31, 2025
On the ruby side, this fixes a crash for methods with 39 or more
parameters. We used to miscomp those entry points due to Insn::Lea
picking ADDS which cannot reference SP:
# set method params: 40
mov x0, #0xfee8
movk x0, #0xffff, lsl #16
movk x0, #0xffff, lsl #32
movk x0, #0xffff, lsl #48
adds x0, xzr, x0
Have Lea work for all i32 displacements and avoid involving the split
pass. Previously, direct use of Insn::Lea directly from the user (as
opposed to generated by the split pass for some memory operations)
wasn't split, so being able to handle the whole range in arm64_emit()
was implicitly required. Also, not going through split reduces register
pressure.
pull bot
pushed a commit
that referenced
this pull request
Dec 17, 2025
This reverts commit 2f151e7. The SP decrement (push) before the call do not match up with the pops after the call, so registers were restored incorrectly. Code from: ./miniruby --zjit-call-threshold=1 --zjit-dump-disasm -e 'p Time.new(1992, 9, 23, 23, 0, 0, :std)' str x11, [sp, #-0x10]! str x12, [sp, #-0x10]! stur x7, [sp] # last argument mov x0, x20 mov x7, x6 mov x6, x5 mov x5, x4 mov x4, x3 mov x3, x2 mov x2, x1 ldur x1, [x29, #-0x20] mov x16, #0xccfc movk x16, #0x2e7, lsl #16 movk x16, #1, lsl #32 blr x16 ldr x12, [sp], #0x10 # supposed to match str x12, [sp, #-0x10]!, but got last argument ldr x11, [sp], #0x10
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
See Commits and Changes for more details.
Created by
pull[bot]
Can you help keep this open source service alive? 💖 Please sponsor : )