`Prism.lex` and `Prism.lex_file` return `ParseLexResult` instead of `Array`.
`Prism::parse_lex` and `Prism::parse_lex_file` return `ParseLexResult` instead of `ParseResult`.
This PR updates the documentation to reflect these return values.
https://github.com/ruby/prism/commit/ee331941c0
Setting up the fake array is a bit more expensive than would be
expected because `rb_ary_freeze` does a lot of checks and lookup
a shape transition.
If we assume fake arrays will always be frozen, we can precompute
the flags state and just assign it.
When an exception is raised, it can leak memory in `head`. There are two
places that can leak memory:
1. `Check_Type(tuple, T_ARRAY)` can leak memory if `tuple` is not an
array.
2. `StringValue(name)` and `StringValue(value)` if they are not strings
and the call to `to_str` does not return a string.
This commit fixes these memory leaks by wrapping the code around a
rb_ensure so that the memory is freed in all cases.
The following code demonstrates the memory leak:
emitter = Psych::Emitter.new(StringIO.new)
nil_to_string_tags = [[nil, "tag:TALOS"]] + ([1] * 1000)
expected_array_tags = [1] * 1000
10.times do
1_000.times do
# Raises `no implicit conversion of nil into String`
emitter.start_document([], nil_to_string_tags, 0)
rescue TypeError
end
1_000.times do
# Raises `wrong argument type Integer (expected Array)`
emitter.start_document([], expected_array_tags, 0)
rescue TypeError
end
puts `ps -o rss= -p #{$$}`
end
Before:
47248
79728
111968
144224
176480
208896
241104
273280
305472
337664
After:
14832
15088
15344
15344
15360
15632
15632
15632
15648
15648
https://github.com/ruby/psych/commit/053af73818
`rb_enc_from_index` is a costly operation so it is worth avoiding
to call it for the common encodings.
Also in the case of UTF-8, it's more efficient to scan the
coderange if it is unknown that to fallback to the slower
algorithms.
If we assume that most strings we modify are not frozen and
are independent, then we can optimize this case by replacing
multiple flag checks by a single mask check.
YJIT currently uses the YJIT root object to mark objects during GC and
update references during compaction. This object otherwise serves no
purpose.
This commit changes it YJIT to be step when marking the GC root. This
saves some memory from being allocated from the system and the GC.
We're seeing a crash during shutdown in rb_gc_impl_objspace_free because
it's running lazy sweeping during shutdown. It appears that it's due to
`finalizing` being set, which causes GC to not be aborted and not
disabled which causes it to be in lazy sweeping at shutdown.
The full stack trace is:
#6 rb_bug (fmt=fmt@entry=0x5643b8ebde78 "lazy sweeping underway when freeing object space") at error.c:1095
#7 0x00005643b8a3c697 in rb_gc_impl_objspace_free (objspace_ptr=<optimized out>) at gc/default.c:9507
#8 0x00005643b8c269eb in ruby_vm_destruct (vm=0x7e2fdc84d000) at vm.c:3141
#9 0x00005643b8a5147b in rb_ec_cleanup (ec=<optimized out>, ex=<optimized out>) at eval.c:263
#10 0x00005643b8a51c93 in ruby_run_node (n=<optimized out>) at eval.c:319
#11 0x00005643b8a4c7c7 in rb_main (argv=0x7fffef15e7f8, argc=18) at ./main.c:43
#12 main (argc=<optimized out>, argv=<optimized out>) at ./main.c:62
Like the following scenario with bootsnap, that frames are same or smaller than frame_to_skip(=3).
---
"/Users/hsbt/.local/share/rbenv/versions/3.3-dev/lib/ruby/3.3.0/bundled_gems.rb:69:in `block (2 levels) in replace_require'"
"/Users/hsbt/.local/share/gem/gems/bootsnap-1.18.4/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'"
"test_warn_bootsnap.rb:11:in `<main>'"
---
The `2` skipped frames went out of sync and now it should be `3`.
Rather than just update the offset, we can implement a way that
is adaptative as long as all require decorators are also called require.
Also we should compute the corresponding `uplevel` otherwise the
warning will still point decorators.
Co-authored-by: "Hiroshi SHIBATA" <hsbt@ruby-lang.org>
Unlike in older revisions in the year, GCC 11 isn't inlining the call
to vm_push_frame() inside invoke_iseq_block_from_c() anymore. We do
want it to be inlined since rb_yield() speed is fairly important.
Logs from -fopt-info-optimized-inline reveal that GCC was blowing its
code size budget inlining invoke_block_from_c_bh() into its various
callers, leaving suboptimal code for its body.
Take away some uses of the `inline` keyword and merge a common tail
call to vm_exec() for overall better code.
This tweak gives about 18% on a micro benchmark and 1% on the
chunky-png benchmark from yjit-bench. I tested on a Skylake server.
```
$ cat c-to-ruby-call.yml
benchmark:
- 0.upto(10_000_000) {}
$ benchmark-driver --chruby '+patch;master' c-to-ruby-call.yml
Warming up --------------------------------------
0.upto(10_000_000) {} 2.299 i/s - 3.000 times in 1.304689s (434.90ms/i)
Calculating -------------------------------------
+patch master
0.upto(10_000_000) {} 2.299 1.943 i/s - 6.000 times in 2.609393s 3.088353s
Comparison:
0.upto(10_000_000) {}
+patch: 2.3 i/s
master: 1.9 i/s - 1.18x slower
$ ruby run_benchmarks.rb --chruby 'master;+patch' chunky-png
<snip>
---------- ----------- ---------- ----------- ---------- -------------- -------------
bench master (ms) stddev (%) +patch (ms) stddev (%) +patch 1st itr master/+patch
chunky-png 1156.1 0.1 1142.2 0.2 1.01 1.01
---------- ----------- ---------- ----------- ---------- -------------- -------------
```
When building with the `--shared` option, most functionality is kept in
`libruby.so`. Therefore also run annocheck for `libruby.so`.
Use `ARG IN_DIR` to propagate multiple files into the container instead of
`ARG FILES` in the `Dockerfile-copy`. Because the `COPY` syntax in Dockerfile
doesn't support copying the multiple files.
https://stackoverflow.com/questions/61599384/specify-multiple-files-in-arg-to-copy-in-dockerfile
Co-authored-by: Vít Ondruch <vondruch@redhat.com>