summaryrefslogtreecommitdiff
path: root/test/ruby
AgeCommit message (Collapse)Author
2024-07-17Report a TracePoint log when the TracePoint tests failYusuke Endoh
Notes: Merged: https://github.com/ruby/ruby/pull/11184
2024-07-16[PRISM] Omit two more ast tests that will not work without RubyVM::AstKevin Newton
2024-07-16Add MatchData#bytebegin and MatchData#byteendShugo Maeda
These methods return the byte-based offset of the beginning or end of the specified match. [Feature #20576]
2024-07-12Rename full_mark -> rgengc_allow_full_markMatt Valentine-House
2024-07-12Provide GC.config to disable major GC collectionsMatt Valentine-House
This feature provides a new method `GC.config` that configures internal GC configuration variables provided by an individual GC implementation. Implemented in this PR is the option `full_mark`: a boolean value that will determine whether the Ruby GC is allowed to run a major collection while the process is running. It has the following semantics This feature configures Ruby's GC to only run minor GC's. It's designed to give users relying on Out of Band GC complete control over when a major GC is run. Configuring `full_mark: false` does two main things: * Never runs a Major GC. When the heap runs out of space during a minor and when a major would traditionally be run, instead we allocate more heap pages, and mark objspace as needing a major GC. * Don't increment object ages. We don't promote objects during GC, this will cause every object to be scanned on every minor. This is an intentional trade-off between minor GC's doing more work every time, and potentially promoting objects that will then never be GC'd. The intention behind not aging objects is that users of this feature should use a preforking web server, or some other method of pre-warming the oldgen (like Nakayoshi fork)before disabling Majors. That way most objects that are going to be old will have already been promoted. This will interleave major and minor GC collections in exactly the same what that the Ruby GC runs in versions previously to this. This is the default behaviour. * This new method has the following extra semantics: - `GC.config` with no arguments returns a hash of the keys of the currently configured GC - `GC.config` with a key pair (eg. `GC.config(full_mark: true)` sets the matching config key to the corresponding value and returns the entire known config hash, including the new values. If the key does not exist, `nil` is returned * When a minor GC is run, Ruby sets an internal status flag to determine whether the next GC will be a major or a minor. When `full_mark: false` this flag is ignored and every GC will be a minor. This status flag can be accessed at `GC.latest_gc_info(:needs_major_by)`. Any value other than `nil` means that the next collection would have been a major. Thus it's possible to use this feature to check at a predetermined time, whether a major GC is necessary and run one if it is. eg. After a request has finished processing. ```ruby if GC.latest_gc_info(:needs_major_by) GC.start(full_mark: true) end ``` [Feature #20443]
2024-07-12Pend some tests because these are not working with macOS 15 beta and Xcode ↵Hiroshi SHIBATA
16 beta
2024-07-11IBM864 single-byte transcoding (#10518)Jeremy Daer
Include € euro sign from CCSID 864
2024-07-11Enumerable#all?: Stop optimizing when a given block is not optimizableYusuke Endoh
This is a follow up to 182822683f86c8f8d63b05765addf5a04d112aa2. Co-Authored-By: Aaron Patterson <[email protected]>
2024-07-10Avoid a hash allocation when keyword splatting empty hash when calling ↵Jeremy Evans
ruby2_keywords method Treat this similar to keyword splatting nil, using goto ignore. However, keep previous behavior if the method accepts a keyword splat, to avoid double hash allocation. This also can avoid an array allocation when calling a method that doesn't have any splat parameters but supports literal keyword parameters, because ignore_keyword_hash_p was not ignoring the keyword hash in that case. This change doesn't remove the empty ruby2_keywords hash from the array, which caused an assertion failure if the method being called accepted keywords in some cases. Modify the assertion to handle this case. An alternative approach would add a flag to the args struct so the args_argc calculation could handle this case and report the correct argc, but such an approach would likely be slower.
2024-07-10Eliminate array allocations for single splat followed by mutable keywordsJeremy Evans
For calls such as: m(*ary, a: 2, **h) m(*ary, **h, **h, **h) Where m does not take a positional argument splat, there was previously an array allocation (splatarray true) to dup ary, even though it was not necessary to do so. This is because the elimination of the array allocation (splatarray false) was performed in the optimizer, and the optimizer didn't handle this case, because the instructions for the keywords can be of arbitrary length. Move part of the optimization from the optimizer to the compiler, detecting parse trees of the form: ARGS_PUSH: head: SPLAT tail: HASH (without brace) And using splatarray false instead of splatarray true for them. Unfortunately, moving part of the optimization to the compiler broke the hash allocation elimination optimization for calls of the form: m(*ary, a: 2) That's because the compiler had already set splatarray false, and the optimizer code was looking for splatarray true. Split the array allocation elimination and hash allocation elimination in the optimizer so that the hash allocation elimination will still apply if the compiler performs the splatarray false optimization.
2024-07-05Fix flaky test_stat_heap_allPeter Zhu
We only collect GC.stat_heap(nil, stat_heap_all) once, outside of the loop, but assert_equal could allocate objects which can cause a GC to run and cause stat_heap_all to be out-of-sync.
2024-07-04Fix the return value of `Integer#downto` called with a blockNobuyoshi Nakada
As the document states, it should return `self`, not `nil`. Fix up of f4b313f7338f5fbe37f73aae29f70aeb474f7f5b.
2024-07-03Move Array#map to RubyAaron Patterson
Improves activerecord by about 1% on the interpreter: ``` before: ruby 3.4.0dev (2024-07-03T18:40:10Z master f88841b8f3) [arm64-darwin23] after: ruby 3.4.0dev (2024-07-03T18:41:14Z ruby-map 6c0df4eb32) [arm64-darwin23] ------------ ----------- ---------- ---------- ---------- ------------- ------------ bench before (ms) stddev (%) after (ms) stddev (%) after 1st itr before/after activerecord 235.2 0.8 233.6 0.7 1.01 1.01 ------------ ----------- ---------- ---------- ---------- ------------- ------------ Legend: - after 1st itr: ratio of before/after time for the first benchmarking iteration. - before/after: ratio of before/after time. Higher is better for after. Above 1 represents a speedup. ``` Improves YJIT by about 4%: ``` before: ruby 3.4.0dev (2024-07-03T18:40:10Z master f88841b8f3) +YJIT [arm64-darwin23] after: ruby 3.4.0dev (2024-07-03T18:41:14Z ruby-map 6c0df4eb32) +YJIT [arm64-darwin23] ------------ ----------- ---------- ---------- ---------- ------------- ------------ bench before (ms) stddev (%) after (ms) stddev (%) after 1st itr before/after activerecord 142.1 1.2 137.0 0.6 1.00 1.04 ------------ ----------- ---------- ---------- ---------- ------------- ------------ Legend: - after 1st itr: ratio of before/after time for the first benchmarking iteration. - before/after: ratio of before/after time. Higher is better for after. Above 1 represents a speedup. ```
2024-07-03array.c: Remove outdated assertionsJean Boussier
Following [Feature #20589] it can happen that we change the capacity of a frozen array, so these assertions no longer make sense. Normally we don't hit them because `Array#freeze` shrinks the array, but if somehow the Array was frozen using `Object#freeze` then we may shrink it after it was frozen.
2024-07-03[Feature #20470] Split GC into gc_impl.cPeter Zhu
This commit splits gc.c into two files: - gc.c now only contains code not specific to Ruby GC. This includes code to mark objects (which the GC implementation may choose not to use) and wrappers for internal APIs that the implementation may need to use (e.g. locking the VM). - gc_impl.c now contains the implementation of Ruby's GC. This includes marking, sweeping, compaction, and statistics. Most importantly, gc_impl.c only uses public APIs in Ruby and a limited set of functions exposed in gc.c. This allows us to build gc_impl.c independently of Ruby and plug Ruby's GC into itself.
2024-07-02Add regression test for mutating pack's format stringAaron Patterson
It doesn't look like there was a test added for this bug, so I'm adding it. Code is from here: https://web.archive.org/web/20160908192307/http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-dev/24445
2024-06-27Fix corruption of internal encoding stringPeter Zhu
[Bug #20598] Just like [Bug #20595], Encoding#name_list and Encoding#aliases can have their strings corrupted when Encoding.default_internal is set to nil. Co-authored-by: Matthew Valentine-House <[email protected]>
2024-06-27Fix corruption of encoding name stringPeter Zhu
[Bug #20595] enc_set_default_encoding will free the C string if the encoding is nil, but the C string can be used by the encoding name string. This will cause the encoding name string to be corrupted. Consider the following code: Encoding.default_internal = Encoding::ASCII_8BIT names = Encoding.default_internal.names p names Encoding.default_internal = nil p names It outputs: ["ASCII-8BIT", "BINARY", "internal"] ["ASCII-8BIT", "BINARY", "\x00\x00\x00\x00\x00\x00\x00\x00"] Co-authored-by: Matthew Valentine-House <[email protected]>
2024-06-25Move to test/.excludes-prismNobuyoshi Nakada
2024-06-25Pending `EVENT_RETURN` settracefunc tests with PrismNobuyoshi Nakada
2024-06-25[Bug #20457] Do not remove final `return` nodeNobuyoshi Nakada
This was an optimization for versions prior to 1.9 that traverse the AST at runtime.
2024-06-24Handle hash and splat nodes in defined?Jeremy Evans
This supports the nodes in both in the parse.y and prism compilers. Fixes [Bug #20043] Co-authored-by: Kevin Newton <[email protected]>
2024-06-24Fix `--debug-frozen-string-literal` to not apply ↵Jean Boussier
`--disable-frozen-string-literal` [Feature #20205] This was an undesired side effect. Now that this value is a triplet, we can't assume it's disabled by default.
2024-06-24Introduce retry to the setup of test files with TestFile#test_statYusuke Endoh
GitHub Actions macos-arm-oss is often too slow and does not timestamp as expected.
2024-06-24Extend the timeout of TestVMDump#test_darwin_invalid_call, etc.Yusuke Endoh
2024-06-21Apply EnvUtil.apply_timeout_scale for TestFile#test_statYusuke Endoh
... to respect RUBY_TEST_TIMEOUT_SCALE. This test somehow fails frequently on macos-arm-oss with --repeat-count=2 https://app.launchableinc.com/organizations/ruby/workspaces/ruby/data/test-paths/file%3Dtest%2Fruby%2Ftest_file.rb%23%23%23class%3DTestFile%23%23%23testcase%3Dtest_stat?organizationId=ruby&workspaceId=ruby&testPathId=file%3Dtest%2Fruby%2Ftest_file.rb%23%23%23class%3DTestFile%23%23%23testcase%3Dtest_stat&testSessionStatus=flake
2024-06-20[PRISM] Remove duplicated testsKevin Newton
These tests are flaky and are duplicative of other tests that are run in CI when parser=prism.
2024-06-18Fix flaky TestWeakMap#test_inspect_garbagePeter Zhu
If a GC is ran before the assert_match, then the WeakMap would be empty and would not have any objects, so the regular expression match would fail. This changes the regular expression to work even if the WeakMap is empty.
2024-06-18fix allocation assertionsAaron Patterson
2024-06-18Optimized forwarding callers and calleesAaron Patterson
This patch optimizes forwarding callers and callees. It only optimizes methods that only take `...` as their parameter, and then pass `...` to other calls. Calls it optimizes look like this: ```ruby def bar(a) = a def foo(...) = bar(...) # optimized foo(123) ``` ```ruby def bar(a) = a def foo(...) = bar(1, 2, ...) # optimized foo(123) ``` ```ruby def bar(*a) = a def foo(...) list = [1, 2] bar(*list, ...) # optimized end foo(123) ``` All variants of the above but using `super` are also optimized, including a bare super like this: ```ruby def foo(...) super end ``` This patch eliminates intermediate allocations made when calling methods that accept `...`. We can observe allocation elimination like this: ```ruby def m x = GC.stat(:total_allocated_objects) yield GC.stat(:total_allocated_objects) - x end def bar(a) = a def foo(...) = bar(...) def test m { foo(123) } end test p test # allocates 1 object on master, but 0 objects with this patch ``` ```ruby def bar(a, b:) = a + b def foo(...) = bar(...) def test m { foo(1, b: 2) } end test p test # allocates 2 objects on master, but 0 objects with this patch ``` How does it work? ----------------- This patch works by using a dynamic stack size when passing forwarded parameters to callees. The caller's info object (known as the "CI") contains the stack size of the parameters, so we pass the CI object itself as a parameter to the callee. When forwarding parameters, the forwarding ISeq uses the caller's CI to determine how much stack to copy, then copies the caller's stack before calling the callee. The CI at the forwarded call site is adjusted using information from the caller's CI. I think this description is kind of confusing, so let's walk through an example with code. ```ruby def delegatee(a, b) = a + b def delegator(...) delegatee(...) # CI2 (FORWARDING) end def caller delegator(1, 2) # CI1 (argc: 2) end ``` Before we call the delegator method, the stack looks like this: ``` Executing Line | Code | Stack ---------------+---------------------------------------+-------- 1| def delegatee(a, b) = a + b | self 2| | 1 3| def delegator(...) | 2 4| # | 5| delegatee(...) # CI2 (FORWARDING) | 6| end | 7| | 8| def caller | -> 9| delegator(1, 2) # CI1 (argc: 2) | 10| end | ``` The ISeq for `delegator` is tagged as "forwardable", so when `caller` calls in to `delegator`, it writes `CI1` on to the stack as a local variable for the `delegator` method. The `delegator` method has a special local called `...` that holds the caller's CI object. Here is the ISeq disasm fo `delegator`: ``` == disasm: #<ISeq:delegator@-e:1 (1,0)-(1,39)> local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1]) [ 1] "..."@0 0000 putself ( 1)[LiCa] 0001 getlocal_WC_0 "..."@0 0003 send <calldata!mid:delegatee, argc:0, FCALL|FORWARDING>, nil 0006 leave [Re] ``` The local called `...` will contain the caller's CI: CI1. Here is the stack when we enter `delegator`: ``` Executing Line | Code | Stack ---------------+---------------------------------------+-------- 1| def delegatee(a, b) = a + b | self 2| | 1 3| def delegator(...) | 2 -> 4| # | CI1 (argc: 2) 5| delegatee(...) # CI2 (FORWARDING) | cref_or_me 6| end | specval 7| | type 8| def caller | 9| delegator(1, 2) # CI1 (argc: 2) | 10| end | ``` The CI at `delegatee` on line 5 is tagged as "FORWARDING", so it knows to memcopy the caller's stack before calling `delegatee`. In this case, it will memcopy self, 1, and 2 to the stack before calling `delegatee`. It knows how much memory to copy from the caller because `CI1` contains stack size information (argc: 2). Before executing the `send` instruction, we push `...` on the stack. The `send` instruction pops `...`, and because it is tagged with `FORWARDING`, it knows to memcopy (using the information in the CI it just popped): ``` == disasm: #<ISeq:delegator@-e:1 (1,0)-(1,39)> local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1]) [ 1] "..."@0 0000 putself ( 1)[LiCa] 0001 getlocal_WC_0 "..."@0 0003 send <calldata!mid:delegatee, argc:0, FCALL|FORWARDING>, nil 0006 leave [Re] ``` Instruction 001 puts the caller's CI on the stack. `send` is tagged with FORWARDING, so it reads the CI and _copies_ the callers stack to this stack: ``` Executing Line | Code | Stack ---------------+---------------------------------------+-------- 1| def delegatee(a, b) = a + b | self 2| | 1 3| def delegator(...) | 2 4| # | CI1 (argc: 2) -> 5| delegatee(...) # CI2 (FORWARDING) | cref_or_me 6| end | specval 7| | type 8| def caller | self 9| delegator(1, 2) # CI1 (argc: 2) | 1 10| end | 2 ``` The "FORWARDING" call site combines information from CI1 with CI2 in order to support passing other values in addition to the `...` value, as well as perfectly forward splat args, kwargs, etc. Since we're able to copy the stack from `caller` in to `delegator`'s stack, we can avoid allocating objects. I want to do this to eliminate object allocations for delegate methods. My long term goal is to implement `Class#new` in Ruby and it uses `...`. I was able to implement `Class#new` in Ruby [here](https://github.com/ruby/ruby/pull/9289). If we adopt the technique in this patch, then we can optimize allocating objects that take keyword parameters for `initialize`. For example, this code will allocate 2 objects: one for `SomeObject`, and one for the kwargs: ```ruby SomeObject.new(foo: 1) ``` If we combine this technique, plus implement `Class#new` in Ruby, then we can reduce allocations for this common operation. Co-Authored-By: John Hawthorn <[email protected]> Co-Authored-By: Alan Wu <[email protected]>
2024-06-13clear `kw_flag` if given hash is nilKoichi Sasada
https://bugs.ruby-lang.org/issues/20570 is caused I missed to clear the `kw_flag` even if `keyword_hash` is nil.
2024-06-12Add regression test for Bug #20573Aaron Patterson
Just a regression test to ensure behavior remains the same
2024-06-12[Bug #20572] Abandon if replacing destination is the sameNobuyoshi Nakada
2024-06-11compile.c: use putspecialobject for RubyVM::FrozenCoreJean Boussier
[Bug #20569] `putobject RubyVM::FrozenCore`, is not serializable, we have to use `putspecialobject VM_SPECIAL_OBJECT_VMCORE`.
2024-06-10Don't skip test_inspect_under_gc_compact_stressPeter Zhu
Commit 1471a16 seems to have fixed this flaky test, so we don't need to skip it for YJIT or RJIT anymore.
2024-06-07Remove prism compiler warningKevin Newton
2024-06-07Don't use SEGV signal when timeout in test_gc_compactPeter Zhu
Using a SEGV signal for timeout makes it difficult to tell if it's a real SEGV or if it timed out, so we should just use the default signals.
2024-06-07TestRequire#test_loading_fifo_threading_success: Extend the timeout limitYusuke Endoh
2024-06-07TestRegexp#test_match_cache_positive_look_behind: Extend the timeout limitYusuke Endoh
2024-06-07TestRegexp#test_timeout_shorter_than_global: Extend the timeout limitYusuke Endoh
2024-06-07TestRequire#test_loading_fifo_fd_leak: Extend the timeout limitYusuke Endoh
2024-06-07TestGc#test_thrashing_for_young_objects: extend the timeout limitYusuke Endoh
2024-06-07TestRegexp#test_s_timeout: accept timeout errors more tolerantlyYusuke Endoh
This test seems flaky on macOS GitHub Actions
2024-06-07Extend timeout of TestGCCompect#test_moving_objects_between_size_poolsYusuke Endoh
It is too flaky on macOS GitHub Actions
2024-06-06Fix Module#define_method to change visibility when passed existing method bodyJeremy Evans
Fixes [Bug #19749]
2024-06-06Remove circular parameter syntax errorKevin Newton
https://bugs.ruby-lang.org/issues/20478
2024-06-05Don't add `+YJIT` to `RUBY_DESCRIPTION` until it's actually enabledJean Boussier
If you start Ruby with `--yjit-disable`, the `+YJIT` shouldn't be added until `RubyVM::YJIT.enable` is actually called. Otherwise it's confusing in crash reports etc.
2024-06-04Remove dependency on fiddle from test/rubyHiroshi SHIBATA
Co-authored-by: "Nobuyoshi Nakada" <[email protected]>
2024-05-31Make error messages clear blocks/keywords are disallowed in index assignmentJeremy Evans
Blocks and keywords are allowed in regular index. Also update NEWS to make this more clear. Co-authored-by: Nobuyoshi Nakada <[email protected]>
2024-05-30test_bignum: defined? returns String (#10880)Sorah Fukumori
didn't verify the test is working properly due to mistaken auto-merge… [Bug #20515] bug: https://bugs.ruby-lang.org/issues/20515 follow-up: 22e4eeda6561693367fc7a00b92b90f46b09cabd follow-up: https://github.com/ruby/ruby/pull/10875