diff options
author | Jeremy Evans <code@jeremyevans.net> | 2021-11-18 15:10:20 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-18 15:10:20 -0800 |
commit | b08dacfea39ad8da3f1fd7fdd0e4538cc892ec44 (patch) | |
tree | 0e3ab7e2f068ce840aaa4e3cbb46e2561a7c153e /object.c | |
parent | 4adb012926f8bd6011168327d8832cf19976de40 (diff) | |
download | ruby-b08dacfea39ad8da3f1fd7fdd0e4538cc892ec44.tar.gz |
Optimize dynamic string interpolation for symbol/true/false/nil/0-9
This provides a significant speedup for symbol, true, false,
nil, and 0-9, class/module, and a small speedup in most other cases.
Speedups (using included benchmarks):
:symbol :: 60%
0-9 :: 50%
Class/Module :: 50%
nil/true/false :: 20%
integer :: 10%
[] :: 10%
"" :: 3%
One reason this approach is faster is it reduces the number of
VM instructions for each interpolated value.
Initial idea, approach, and benchmarks from Eric Wong. I applied
the same approach against the master branch, updating it to handle
the significant internal changes since this was first proposed 4
years ago (such as CALL_INFO/CALL_CACHE -> CALL_DATA). I also
expanded it to optimize true/false/nil/0-9/class/module, and added
handling of missing methods, refined methods, and RUBY_DEBUG.
This renames the tostring insn to anytostring, and adds an
objtostring insn that implements the optimization. This requires
making a few functions non-static, and adding some non-static
functions.
This disables 4 YJIT tests. Those tests should be reenabled after
YJIT optimizes the new objtostring insn.
Implements [Feature #13715]
Co-authored-by: Eric Wong <e@80x24.org>
Co-authored-by: Alan Wu <XrXr@users.noreply.github.com>
Co-authored-by: Yusuke Endoh <mame@ruby-lang.org>
Co-authored-by: Koichi Sasada <ko1@atdot.net>
Diffstat (limited to 'object.c')
-rw-r--r-- | object.c | 20 |
1 files changed, 10 insertions, 10 deletions
@@ -1248,8 +1248,8 @@ rb_obj_frozen_p(VALUE obj) * Always returns the empty string. */ -static VALUE -nil_to_s(VALUE obj) +MJIT_FUNC_EXPORTED VALUE +rb_nil_to_s(VALUE obj) { return rb_cNilClass_to_s; } @@ -1331,8 +1331,8 @@ nil_match(VALUE obj1, VALUE obj2) * The string representation of <code>true</code> is "true". */ -static VALUE -true_to_s(VALUE obj) +MJIT_FUNC_EXPORTED VALUE +rb_true_to_s(VALUE obj) { return rb_cTrueClass_to_s; } @@ -1408,8 +1408,8 @@ true_xor(VALUE obj, VALUE obj2) * The string representation of <code>false</code> is "false". */ -static VALUE -false_to_s(VALUE obj) +MJIT_FUNC_EXPORTED VALUE +rb_false_to_s(VALUE obj) { return rb_cFalseClass_to_s; } @@ -1585,7 +1585,7 @@ rb_obj_cmp(VALUE obj1, VALUE obj2) * show information on the thing we're attached to as well. */ -static VALUE +MJIT_FUNC_EXPORTED VALUE rb_mod_to_s(VALUE klass) { ID id_defined_at; @@ -4586,7 +4586,7 @@ InitVM_Object(void) rb_cNilClass = rb_define_class("NilClass", rb_cObject); rb_cNilClass_to_s = rb_fstring_enc_lit("", rb_usascii_encoding()); rb_gc_register_mark_object(rb_cNilClass_to_s); - rb_define_method(rb_cNilClass, "to_s", nil_to_s, 0); + rb_define_method(rb_cNilClass, "to_s", rb_nil_to_s, 0); rb_define_method(rb_cNilClass, "to_a", nil_to_a, 0); rb_define_method(rb_cNilClass, "to_h", nil_to_h, 0); rb_define_method(rb_cNilClass, "inspect", nil_inspect, 0); @@ -4668,7 +4668,7 @@ InitVM_Object(void) rb_cTrueClass = rb_define_class("TrueClass", rb_cObject); rb_cTrueClass_to_s = rb_fstring_enc_lit("true", rb_usascii_encoding()); rb_gc_register_mark_object(rb_cTrueClass_to_s); - rb_define_method(rb_cTrueClass, "to_s", true_to_s, 0); + rb_define_method(rb_cTrueClass, "to_s", rb_true_to_s, 0); rb_define_alias(rb_cTrueClass, "inspect", "to_s"); rb_define_method(rb_cTrueClass, "&", true_and, 1); rb_define_method(rb_cTrueClass, "|", true_or, 1); @@ -4680,7 +4680,7 @@ InitVM_Object(void) rb_cFalseClass = rb_define_class("FalseClass", rb_cObject); rb_cFalseClass_to_s = rb_fstring_enc_lit("false", rb_usascii_encoding()); rb_gc_register_mark_object(rb_cFalseClass_to_s); - rb_define_method(rb_cFalseClass, "to_s", false_to_s, 0); + rb_define_method(rb_cFalseClass, "to_s", rb_false_to_s, 0); rb_define_alias(rb_cFalseClass, "inspect", "to_s"); rb_define_method(rb_cFalseClass, "&", false_and, 1); rb_define_method(rb_cFalseClass, "|", false_or, 1); |