summaryrefslogtreecommitdiff
path: root/compile.c
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2021-11-18 15:10:20 -0800
committerGitHub <noreply@github.com>2021-11-18 15:10:20 -0800
commitb08dacfea39ad8da3f1fd7fdd0e4538cc892ec44 (patch)
tree0e3ab7e2f068ce840aaa4e3cbb46e2561a7c153e /compile.c
parent4adb012926f8bd6011168327d8832cf19976de40 (diff)
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>
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/5002 Merged-By: jeremyevans <code@jeremyevans.net>
Diffstat (limited to 'compile.c')
-rw-r--r--compile.c21
1 files changed, 9 insertions, 12 deletions
diff --git a/compile.c b/compile.c
index 8a459b2558..2b92893d80 100644
--- a/compile.c
+++ b/compile.c
@@ -3271,13 +3271,13 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
}
}
- if (IS_INSN_ID(iobj, tostring)) {
+ if (IS_INSN_ID(iobj, anytostring)) {
LINK_ELEMENT *next = iobj->link.next;
/*
- * tostring
+ * anytostring
* concatstrings 1
* =>
- * tostring
+ * anytostring
*/
if (IS_INSN(next) && IS_INSN_ID(next, concatstrings) &&
OPERAND_AT(next, 0) == INT2FIX(1)) {
@@ -7642,17 +7642,14 @@ compile_evstr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
CHECK(COMPILE_(ret, "nd_body", node, popped));
if (!popped && !all_string_result_p(node)) {
- const int line = nd_line(node);
const NODE *line_node = node;
const unsigned int flag = VM_CALL_FCALL;
- LABEL *isstr = NEW_LABEL(line);
- ADD_INSN(ret, line_node, dup);
- ADD_INSN1(ret, line_node, checktype, INT2FIX(T_STRING));
- ADD_INSNL(ret, line_node, branchif, isstr);
- ADD_INSN(ret, line_node, dup);
- ADD_SEND_R(ret, line_node, idTo_s, INT2FIX(0), NULL, INT2FIX(flag), NULL);
- ADD_INSN(ret, line_node, tostring);
- ADD_LABEL(ret, isstr);
+
+ // Note, this dup could be removed if we are willing to change anytostring. It pops
+ // two VALUEs off the stack when it could work by replacing the top most VALUE.
+ ADD_INSN(ret, line_node, dup);
+ ADD_INSN1(ret, line_node, objtostring, new_callinfo(iseq, idTo_s, 0, flag, NULL, FALSE));
+ ADD_INSN(ret, line_node, anytostring);
}
return COMPILE_OK;
}