mirror of
https://github.com/ruby/ruby.git
synced 2026-10-28 16:36:20 +08:00
Define String#ascii_only? and #valid_encoding? in Ruby
Get rid of the CFUNC overhead in String#ascii_only? and #valid_encoding?. Define them as leaf Primitive.cexpr! builtins in a new string.rb, following the pattern of numeric.rb. This makes them 1.2x-1.4x faster across the interpreter, YJIT, and ZJIT. Move ZJIT's cfunc annotation for String#ascii_only? to annotate_builtin!, and add one for String#valid_encoding?. Fix CI for builtin String#ascii_only?
This commit is contained in:
1 parent
5465dca954
commit
93e977936f
9 files changed
+51
-27
Notes:
git
2026-06-24 21:21:21 +00:00
No files matched your search
@@ -0,0 +1,7 @@
|
||||
prelude: |
|
||||
ascii = "hello world"
|
||||
utf8 = "héllo wörld 晦"
|
||||
benchmark:
|
||||
ascii_only_true: ascii.ascii_only?
|
||||
ascii_only_false: utf8.ascii_only?
|
||||
loop_count: 20000000
|
||||
@@ -0,0 +1,7 @@
|
||||
prelude: |
|
||||
utf8 = "héllo wörld 晦"
|
||||
broken = "\xff\xfe".dup.force_encoding("UTF-8")
|
||||
benchmark:
|
||||
valid_enc_true: utf8.valid_encoding?
|
||||
valid_enc_false: broken.valid_encoding?
|
||||
loop_count: 20000000
|
||||
@@ -1199,6 +1199,7 @@ BUILTIN_RB_SRCS = \
|
||||
$(srcdir)/kernel.rb \
|
||||
$(srcdir)/pathname_builtin.rb \
|
||||
$(srcdir)/ractor.rb \
|
||||
$(srcdir)/string.rb \
|
||||
$(srcdir)/symbol.rb \
|
||||
$(srcdir)/timev.rb \
|
||||
$(srcdir)/thread_sync.rb \
|
||||
|
||||
@@ -17718,6 +17718,7 @@ string.$(OBJEXT): {$(VPATH)}backward/2/limits.h
|
||||
string.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
|
||||
string.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
|
||||
string.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
|
||||
string.$(OBJEXT): {$(VPATH)}builtin.h
|
||||
string.$(OBJEXT): {$(VPATH)}config.h
|
||||
string.$(OBJEXT): {$(VPATH)}constant.h
|
||||
string.$(OBJEXT): {$(VPATH)}debug_counter.h
|
||||
@@ -17896,6 +17897,7 @@ string.$(OBJEXT): {$(VPATH)}rubyparser.h
|
||||
string.$(OBJEXT): {$(VPATH)}shape.h
|
||||
string.$(OBJEXT): {$(VPATH)}st.h
|
||||
string.$(OBJEXT): {$(VPATH)}string.c
|
||||
string.$(OBJEXT): {$(VPATH)}string.rbinc
|
||||
string.$(OBJEXT): {$(VPATH)}subst.h
|
||||
string.$(OBJEXT): {$(VPATH)}thread.h
|
||||
string.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
|
||||
|
||||
@@ -105,6 +105,7 @@ rb_call_builtin_inits(void)
|
||||
BUILTIN(warning);
|
||||
BUILTIN(array);
|
||||
BUILTIN(hash);
|
||||
BUILTIN(string);
|
||||
BUILTIN(symbol);
|
||||
BUILTIN(timev);
|
||||
BUILTIN(thread_sync);
|
||||
|
||||
@@ -11736,14 +11736,6 @@ rb_str_b(VALUE str)
|
||||
return str2;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* valid_encoding? -> true or false
|
||||
*
|
||||
* :include: doc/string/valid_encoding_p.rdoc
|
||||
*
|
||||
*/
|
||||
|
||||
static VALUE
|
||||
rb_str_valid_encoding_p(VALUE str)
|
||||
{
|
||||
@@ -11752,18 +11744,6 @@ rb_str_valid_encoding_p(VALUE str)
|
||||
return RBOOL(cr != ENC_CODERANGE_BROKEN);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* ascii_only? -> true or false
|
||||
*
|
||||
* Returns whether +self+ contains only ASCII characters:
|
||||
*
|
||||
* 'abc'.ascii_only? # => true
|
||||
* "abc\u{6666}".ascii_only? # => false
|
||||
*
|
||||
* Related: see {Querying}[rdoc-ref:String@Querying].
|
||||
*/
|
||||
|
||||
static VALUE
|
||||
rb_str_is_ascii_only_p(VALUE str)
|
||||
{
|
||||
@@ -13053,8 +13033,6 @@ Init_String(void)
|
||||
rb_define_method(rb_cString, "encoding", rb_obj_encoding, 0); /* in encoding.c */
|
||||
rb_define_method(rb_cString, "force_encoding", rb_str_force_encoding, 1);
|
||||
rb_define_method(rb_cString, "b", rb_str_b, 0);
|
||||
rb_define_method(rb_cString, "valid_encoding?", rb_str_valid_encoding_p, 0);
|
||||
rb_define_method(rb_cString, "ascii_only?", rb_str_is_ascii_only_p, 0);
|
||||
|
||||
/* define UnicodeNormalize module here so that we don't have to look it up */
|
||||
mUnicodeNormalize = rb_define_module("UnicodeNormalize");
|
||||
@@ -13107,3 +13085,5 @@ Init_String(void)
|
||||
rb_define_method(rb_cSymbol, "encoding", sym_encoding, 0);
|
||||
}
|
||||
|
||||
#include "string.rbinc"
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
class String
|
||||
# call-seq:
|
||||
# valid_encoding? -> true or false
|
||||
#
|
||||
# :include: doc/string/valid_encoding_p.rdoc
|
||||
#
|
||||
def valid_encoding?
|
||||
Primitive.attr! :leaf
|
||||
Primitive.cexpr! 'rb_str_valid_encoding_p(self)'
|
||||
end
|
||||
|
||||
# call-seq:
|
||||
# ascii_only? -> true or false
|
||||
#
|
||||
# Returns whether +self+ contains only ASCII characters:
|
||||
#
|
||||
# 'abc'.ascii_only? # => true
|
||||
# "abc\u{6666}".ascii_only? # => false
|
||||
#
|
||||
# Related: see {Querying}[rdoc-ref:String@Querying].
|
||||
def ascii_only?
|
||||
Primitive.attr! :leaf
|
||||
Primitive.cexpr! 'rb_str_is_ascii_only_p(self)'
|
||||
end
|
||||
end
|
||||
@@ -222,9 +222,6 @@ pub fn init() -> Annotations {
|
||||
annotate!(rb_cString, "<<", inline_string_append);
|
||||
annotate!(rb_cString, "==", inline_string_eq);
|
||||
// Not elidable; has a side effect of setting the encoding if ENC_CODERANGE_UNKNOWN.
|
||||
// TOOD(max): Turn this into a load/compare. Will need to side-exit or do the full call if
|
||||
// ENC_CODERANGE_UNKNOWN.
|
||||
annotate!(rb_cString, "ascii_only?", types::BoolExact, no_gc, leaf);
|
||||
annotate!(rb_cModule, "name", types::StringExact.union(types::NilClass), no_gc, leaf, elidable);
|
||||
annotate!(rb_cModule, "===", inline_module_eqq, types::BoolExact, no_gc, leaf);
|
||||
annotate!(rb_cArray, "length", inline_array_length, types::Fixnum, no_gc, leaf, elidable);
|
||||
@@ -291,6 +288,10 @@ pub fn init() -> Annotations {
|
||||
annotate_builtin!(rb_mKernel, "frozen?", types::BoolExact);
|
||||
annotate_builtin!(rb_cSymbol, "name", types::StringExact);
|
||||
annotate_builtin!(rb_cSymbol, "to_s", types::StringExact);
|
||||
// TOOD(max): Turn this into a load/compare. Will need to side-exit or do the full call if
|
||||
// ENC_CODERANGE_UNKNOWN.
|
||||
annotate_builtin!(rb_cString, "ascii_only?", types::BoolExact, no_gc, leaf);
|
||||
annotate_builtin!(rb_cString, "valid_encoding?", types::BoolExact, no_gc, leaf);
|
||||
|
||||
// Array iteration builtins (used in with_jit Array#each, map, select, find)
|
||||
builtin_funcs.insert(rb_jit_fixnum_inc as *mut c_void, FnProperties { inline: inline_fixnum_inc, return_type: types::Fixnum, ..Default::default() });
|
||||
|
||||
@@ -11910,8 +11910,8 @@ mod hir_opt_tests {
|
||||
bb3(v9:BasicObject, v10:BasicObject):
|
||||
PatchPoint NoSingletonClass(String@0x1008)
|
||||
PatchPoint MethodRedefined(String@0x1008, ascii_only?@0x1010, cme:0x1018)
|
||||
v24:StringExact = GuardType v10, StringExact recompile
|
||||
v25:BoolExact = CCall v24, :String#ascii_only?@0x1040
|
||||
v23:StringExact = GuardType v10, StringExact recompile
|
||||
v25:BoolExact = InvokeBuiltin leaf <inline_expr>, v23
|
||||
CheckInterrupts
|
||||
Return v25
|
||||
");
|
||||
|
||||
Reference in new issue
Block a user