summaryrefslogtreecommitdiff
path: root/string.c
AgeCommit message (Collapse)Author
2024-11-06Store precomputed hash when there's capacityÉtienne Barrié
Co-authored-by: Jean Boussier <byroot@ruby-lang.org> Notes: Merged: https://github.com/ruby/ruby/pull/11990
2024-11-04Precompute hash only once when interning string literalsÉtienne Barrié
When a fake string is interned, use the capa field to store the string hash. This lets us compute it once for hash lookup and embedding the hash in the interned string. Co-authored-by: Jean Boussier <byroot@ruby-lang.org> Notes: Merged: https://github.com/ruby/ruby/pull/11989
2024-10-21Fix an off-by-one error of own memrchr implementationYusuke Endoh
and make it support `search_len == 0`, just for the case Ref [Bug #20796] Notes: Merged: https://github.com/ruby/ruby/pull/11923
2024-10-21Show where mutated chilled strings were allocatedÉtienne Barrié
[Feature #20205] The warning now suggests running with --debug-frozen-string-literal: ``` test.rb:3: warning: literal string will be frozen in the future (run with --debug-frozen-string-literal for more information) ``` When using --debug-frozen-string-literal, the location where the string was created is shown: ``` test.rb:3: warning: literal string will be frozen in the future test.rb:1: info: the string was created here ``` When resurrecting strings and debug mode is not enabled, the overhead is a simple FL_TEST_RAW. When mutating chilled strings and deprecation warnings are not enabled, the overhead is a simple warning category enabled check. Co-authored-by: Jean Boussier <byroot@ruby-lang.org> Co-authored-by: Nobuyoshi Nakada <nobu@ruby-lang.org> Co-authored-by: Jean Boussier <byroot@ruby-lang.org> Notes: Merged: https://github.com/ruby/ruby/pull/11893
2024-10-07[DOC] String#sub! and String#gsub! return nil if no replacement occuredHolger Just
Notes: Merged: https://github.com/ruby/ruby/pull/11700 Merged-By: nobu <nobu@ruby-lang.org>
2024-09-24Use rb_bug instead of UNREACHABLE for assertionsPeter Zhu
UNREACHABLE uses __builtin_unreachable which is not intended to be used as an assertion. Notes: Merged: https://github.com/ruby/ruby/pull/11678
2024-09-24Fix undefined behavior in String#append_as_bytesPeter Zhu
The UNREACHABLE macro calls __builtin_unreachable, which according to the [GCC docs](https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html#index-_005f_005fbuiltin_005funreachable): > If control flow reaches the point of the __builtin_unreachable, the > program is undefined. But it can reach this point with the following script: "123".append_as_bytes("123") This can crash on some platforms with a `Trace/BPT trap: 5`. Notes: Merged: https://github.com/ruby/ruby/pull/11678
2024-09-18Update exception message in string_for_symbolJeremy Evans
This is a static function only called in two places (rb_to_id and rb_to_symbol), and in both places, both symbols and strings are allowed. This makes the error message consistent with rb_check_id and rb_check_symbol. Fixes [Bug #20607] Notes: Merged: https://github.com/ruby/ruby/pull/11097
2024-09-09Implement String#append_as_bytes(String | Integer, ...)Jean Boussier
[Feature #20594] A handy method to construct a string out of multiple chunks. Contrary to `String#concat`, it doesn't do any encoding negociation, and simply append the content as bytes regardless of whether this result in a broken string or not. It's the caller responsibility to check for `String#valid_encoding?` in cases where it's needed. When passed integers, only the lower byte is considered, like in `String#setbyte`. Notes: Merged: https://github.com/ruby/ruby/pull/11552
2024-09-04Fix documentation for String#index and String#byterindexJean Boussier
Notes: Merged: https://github.com/ruby/ruby/pull/11540
2024-09-04Adjust indents [ci skip]Nobuyoshi Nakada
2024-09-03rb_enc_str_asciionly_p: avoid always fetching the encodingJean Boussier
Profiling of `JSON.dump` shows a significant amount of time spent in `rb_enc_str_asciionly_p`, in large part because it fetches the encoding. It can be made twice as fast in this scenario by first checking the coderange and only falling back to fetching the encoding if the coderange is unknown. Additionally we can skip fetching the encoding for the common popular encodings. Notes: Merged: https://github.com/ruby/ruby/pull/11533
2024-09-03Improve String#rindex performance on OSXZack Deveau
On OSX, String#rindex is slow due to the lack of `memrchr`. The fallback implementation finds a match by instead doing a `memcmp` on every single character in the search string looking for a substring match. For OSX hosts, this changeset introduces a simple `memrchr` implementation, `rb_memrchr`, that can be used instead. An example benchmark below demonstrates an 8000 char long search string with a 10 char substring near the end. ``` ruby-master | substring near the end | osx UTF-8 user system total real index 0.000111 0.000000 0.000111 ( 0.000110) rindex 0.000446 0.000005 0.000451 ( 0.000454) ``` ``` ruby-patched | substring near the end | osx UTF-8 user system total real index 0.000112 0.000000 0.000112 ( 0.000111) rindex 0.000057 0.000001 0.000058 ( 0.000057) ``` Notes: Merged: https://github.com/ruby/ruby/pull/11519
2024-08-09rb_str_bytesplice: skip encoding check if encodings are the sameJean Boussier
If both strings have the same encoding, all this work is useless. Notes: Merged: https://github.com/ruby/ruby/pull/11353
2024-08-09string.c: add fastpath in str_ensure_byte_posJean Boussier
If the string only contain single byte characters we can skips all the costly checks. Notes: Merged: https://github.com/ruby/ruby/pull/11353
2024-08-09string.c: Add fastpath to single_byte_optimizableJean Boussier
`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. Notes: Merged: https://github.com/ruby/ruby/pull/11353
2024-08-09string.c: str_capacity don't check for immediatesJean Boussier
`STR_EMBED_P` uses `FL_TEST_RAW` meaning we already assume `str` isn't an immediate, so we can use `FL_TEST_RAW` here too. Notes: Merged: https://github.com/ruby/ruby/pull/11350
2024-08-09str_independent: add a fastpath with a single flag checkJean Boussier
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. Notes: Merged: https://github.com/ruby/ruby/pull/11350
2024-08-02YJIT: Enhance the `String#<<` method substitution to handle integer ↵Kevin Menard
codepoint values. (#11032) * Document why we need to explicitly spill registers. * Simplify passing a byte value to `str_buf_cat`. * YJIT: Enhance the `String#<<` method substitution to handle integer codepoint values. * YJIT: Move runtime type check into YJIT. Performing the check in YJIT means we can make assumptions about the type. It also improves correctness of stack traces in cases where the codepoint argument is not a String or a Fixnum. Notes: Merged-By: maximecb <maximecb@ruby-lang.org>
2024-06-19String.new(capacity:) don't substract termlenJean Boussier
[Bug #20585] This was changed in 36a06efdd9f0604093dccbaf96d4e2cb17874dc8 because `String.new(1024)` would end up allocating `1025` bytes, but the problem with this change is that the caller may be trying to right size a String. So instead, we should just better document the behavior of `capacity:`.
2024-06-17Add a fast path implementation for appending single byte values to US-ASCII ↵Kevin Menard
strings.
2024-06-17Add a fast path implementation for appending single byte values to binary ↵Kevin Menard
strings. Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org>
2024-06-13Simplify unaligned write for pre-computed string hashAlan Wu
2024-06-13rb_str_hash(): Avoid UB with making misaligned pointerAlan Wu
Previously, on common platforms, this code made a pointer to a union of 8 byte alignment out of a char pointer that is not guaranteed to satisfy the alignment requirement. That is undefined behavior according to [C99 6.3.2.3p7](https://port70.net/~nsz/c/c99/n1256.html#6.3.2.3p7). Use memcpy() to do the unaligned read instead.
2024-06-13Simplify rb_str_resize clear range conditiontompng
2024-06-13Clear coderange when rb_str_resize change sizetompng
In some encoding like utf-16 utf-32, expanding the string with null bytes can change coderange to either broken or valid.
2024-06-09[Bug #20566] Mention out-of-range argument cases in `String#<<`Nobuyoshi Nakada
Also [Bug #18973].
2024-06-02Stop exposing `rb_str_chilled_p`Jean Boussier
[Feature #20205] Now that chilled strings no longer appear as frozen, there is no need to offer an API to check for chilled strings. We however need to change `rb_check_frozen_internal` to no longer be a macro, as it needs to check for chilled strings.
2024-05-28[Bug #20512] Set coderange in `Range#each` of stringsNobuyoshi Nakada
2024-05-28Set empty strings to ASCII-onlyNobuyoshi Nakada
2024-05-28Precompute embedded string literals hash codeJean Boussier
With embedded strings we often have some space left in the slot, which we can use to store the string Hash code. It's probably only worth it for string literals, as they are the ones likely to be used as hash keys. We chose to store the Hash code right after the string terminator as to make it easy/fast to compute, and not require one more union in RString. ``` compare-ruby: ruby 3.4.0dev (2024-04-22T06:32:21Z main f77618c1fa) [arm64-darwin23] built-ruby: ruby 3.4.0dev (2024-04-22T10:13:03Z interned-string-ha.. 8a1a32331b) [arm64-darwin23] last_commit=Precompute embedded string literals hash code | |compare-ruby|built-ruby| |:-----------|-----------:|---------:| |symbol | 39.275M| 39.753M| | | -| 1.01x| |dyn_symbol | 37.348M| 37.704M| | | -| 1.01x| |small_lit | 29.514M| 33.948M| | | -| 1.15x| |frozen_lit | 27.180M| 33.056M| | | -| 1.22x| |iseq_lit | 27.391M| 32.242M| | | -| 1.18x| ``` Co-Authored-By: Étienne Barrié <etienne.barrie@gmail.com>
2024-05-28Stop marking chilled strings as frozenÉtienne Barrié
They were initially made frozen to avoid false positives for cases such as: str = str.dup if str.frozen? But this may cause bugs and is generally confusing for users. [Feature #20205] Co-authored-by: Jean Boussier <byroot@ruby-lang.org>
2024-04-18Add a hint of `ASCII-8BIT` being `BINARY`Jean Boussier
[Feature #18576] Since outright renaming `ASCII-8BIT` is deemed to backward incompatible, the next best thing would be to only change its `#inspect`, particularly in exception messages.
2024-04-16Eliminate usage of OBJ_FREEZE_RAWJean Boussier
Previously it would bypass the `FL_ABLE` check, but since shapes introduction, it started having a different behavior than `OBJ_FREEZE`, as it would onyl set the `FL_FREEZE` flag, but not update the shape. I have no indication of this causing a bug yet, but it seems like a trap waiting to happen.
2024-04-08Document STR_CHILLED flag on RStringÉtienne Barrié
[Feature #20205]
2024-04-08Add builtin type assertionNobuyoshi Nakada
2024-04-05Assert that Symbol#inspect returns a T_STRINGPeter Zhu
2024-03-31Add missing RB_GC_GUARDs related to DATA_PTRKJ Tsanaktsidis
I discovered the problem in `compile.c` from a failing TestIseqLoad#test_stressful_roundtrip test with ASAN enabled. The other two changes in array.c and string.c I found by auditing similar usages of DATA_PTR in the codebase. [Bug #20402]
2024-03-26Expose rb_str_chilled_pÉtienne Barrié
Some extensions (like stringio) may need to differentiate between chilled strings and frozen strings. They can now use rb_str_chilled_p but must check for its presence since the function will be removed when chilled strings are removed. [Bug #20389] [Feature #20205] Co-authored-by: Jean Boussier <byroot@ruby-lang.org>
2024-03-25[Bug #20389] Chilled string cannot be a shared rootNobuyoshi Nakada
2024-03-19Implement chilled stringsÉtienne Barrié
[Feature #20205] As a path toward enabling frozen string literals by default in the future, this commit introduce "chilled strings". From a user perspective chilled strings pretend to be frozen, but on the first attempt to mutate them, they lose their frozen status and emit a warning rather than to raise a `FrozenError`. Implementation wise, `rb_compile_option_struct.frozen_string_literal` is no longer a boolean but a tri-state of `enabled/disabled/unset`. When code is compiled with frozen string literals neither explictly enabled or disabled, string literals are compiled with a new `putchilledstring` instruction. This instruction is identical to `putstring` except it marks the String with the `STR_CHILLED (FL_USER3)` and `FL_FREEZE` flags. Chilled strings have the `FL_FREEZE` flag as to minimize the need to check for chilled strings across the codebase, and to improve compatibility with C extensions. Notes: - `String#freeze`: clears the chilled flag. - `String#-@`: acts as if the string was mutable. - `String#+@`: acts as if the string was mutable. - `String#clone`: copies the chilled flag. Co-authored-by: Jean Boussier <byroot@ruby-lang.org>
2024-03-03[Bug #20322] Fix rb_enc_interned_str_cstr null encodingThomas Marshall
The documentation for `rb_enc_interned_str_cstr` notes that `enc` can be a null pointer, but this currently causes a segmentation fault when trying to autoload the encoding. This commit fixes the issue by checking for NULL before calling `rb_enc_autoload`.
2024-02-23Stop using rb_str_locktmp_ensure publiclyPeter Zhu
rb_str_locktmp_ensure is a private API.
2024-02-23YJIT: Lazily push a frame for specialized C funcs (#10080)Takashi Kokubun
* YJIT: Lazily push a frame for specialized C funcs Co-authored-by: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@shopify.com> * Fix a comment on pc_to_cfunc * Rename rb_yjit_check_pc to rb_yjit_lazy_push_frame * Rename it to jit_prepare_lazy_frame_call * Fix a typo * Optimize String#getbyte as well * Optimize String#byteslice as well --------- Co-authored-by: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@shopify.com>
2024-02-23Stop using rb_fstring publiclyPeter Zhu
rb_fstring is a private API, so we should use rb_str_to_interned_str instead, which is a public API.
2024-02-23Remove unneeded RUBY_FUNC_EXPORTEDPeter Zhu
2024-02-22Fix -Wsign-compare on String#initializeTakashi Kokubun
../string.c:1886:57: warning: comparison of integer expressions of different signedness: ‘size_t’ {aka ‘long unsigned int’} and ‘long int’ [-Wsign-compare] 1886 | if (STR_EMBED_P(str)) RUBY_ASSERT(osize <= str_embed_capa(str)); | ^~
2024-02-22[Bug #20292] Truncate embedded string to new capacityNobuyoshi Nakada
2024-02-19[Bug #20280] Check by `rb_parser_enc_str_coderange`Nobuyoshi Nakada
Co-authored-by: Yuichiro Kaneko <spiketeika@gmail.com>
2024-02-19[Bug #20280] Raise SyntaxError on invalid encoding symbolNobuyoshi Nakada