summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean Boussier <[email protected]>2024-08-08 12:14:50 +0200
committerJean Boussier <[email protected]>2024-08-09 15:20:58 +0200
commitaf44af238befeed20cc2606ea2b440e16d341213 (patch)
treecfcc77efd3dfe6da305a8588b0cea1ee0d4ae708
parentf57167d3380b6351a915e3e4e0c04c799bd151bd (diff)
str_independent: add a fastpath with a single flag check
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
Notes: Merged: https://github.com/ruby/ruby/pull/11350
-rw-r--r--string.c27
1 files changed, 19 insertions, 8 deletions
diff --git a/string.c b/string.c
index 26c3aa43d6..10023d26a3 100644
--- a/string.c
+++ b/string.c
@@ -2500,32 +2500,43 @@ rb_check_lockedtmp(VALUE str)
}
}
+// If none of these flags are set, we know we have an modifiable string.
+// If any is set, we need to do more detailed checks.
+#define STR_UNMODIFIABLE_MASK (FL_FREEZE | STR_TMPLOCK | STR_CHILLED)
static inline void
str_modifiable(VALUE str)
{
- if (CHILLED_STRING_P(str)) {
- CHILLED_STRING_MUTATED(str);
+ if (RB_UNLIKELY(FL_ANY_RAW(str, STR_UNMODIFIABLE_MASK))) {
+ if (CHILLED_STRING_P(str)) {
+ CHILLED_STRING_MUTATED(str);
+ }
+ rb_check_lockedtmp(str);
+ rb_check_frozen(str);
}
- rb_check_lockedtmp(str);
- rb_check_frozen(str);
}
static inline int
str_dependent_p(VALUE str)
{
if (STR_EMBED_P(str) || !FL_TEST(str, STR_SHARED|STR_NOFREE)) {
- return 0;
+ return FALSE;
}
else {
- return 1;
+ return TRUE;
}
}
+// If none of these flags are set, we know we have an independent string.
+// If any is set, we need to do more detailed checks.
+#define STR_DEPENDANT_MASK (STR_UNMODIFIABLE_MASK | STR_SHARED | STR_NOFREE)
static inline int
str_independent(VALUE str)
{
- str_modifiable(str);
- return !str_dependent_p(str);
+ if (RB_UNLIKELY(FL_ANY_RAW(str, STR_DEPENDANT_MASK))) {
+ str_modifiable(str);
+ return !str_dependent_p(str);
+ }
+ return TRUE;
}
static void