Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

send-pop optimisation #2100

Open
wants to merge 20 commits into
base: master
from
Open
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file or symbol
Failed to load files and symbols.

Always

Just for now

optimise String#slice!

Looking at how `make rdoc` is working, I noticed that strings
allocated inside of String#slice! (which is called from
lib/rdoc/markup/parser.rb:313 and several other places) are becoming
garbages immediately.  These usages of String#slice! are to delete
portions of the receiver and are not interested in the return values.
Why not avoid creation of the return value in such cases.

Note however that by doing so, String#slice is inevitably made
optimised also.  These two methods are tightly connected.  Decoupling
them needs lots of copy & paste, which I think is not a good idea.
  • Loading branch information...
shyouhei committed Dec 3, 2018
commit c18332026e87d3f224bf34d40f7e386459f91100
@@ -2548,21 +2548,22 @@ rb_str_subpos(VALUE str, long beg, long *lenp)
return p;
}

static VALUE str_substr(VALUE str, long beg, long len, int empty);
static VALUE str_substr(VALUE str, long beg, long len, bool empty, bool needstr);

VALUE
rb_str_substr(VALUE str, long beg, long len)
{
return str_substr(str, beg, len, TRUE);
return str_substr(str, beg, len, TRUE, true);
}

static VALUE
str_substr(VALUE str, long beg, long len, int empty)
str_substr(VALUE str, long beg, long len, bool empty, bool needstr)
{
VALUE str2;
char *p = rb_str_subpos(str, beg, &len);

if (!p) return Qnil;
if (!needstr) return Qundef;
if (!STR_EMBEDDABLE_P(len, TERM_LEN(str)) &&
SHARABLE_SUBSTRING_P(p, len, RSTRING_END(str))) {
long ofs = p - RSTRING_PTR(str);
@@ -4427,31 +4428,42 @@ rb_str_include_range_p(VALUE beg, VALUE end, VALUE val, VALUE exclusive)
}

static VALUE
rb_str_subpat(VALUE str, VALUE re, VALUE backref)
rb_str_subpat(VALUE str, VALUE re, VALUE backref, bool needstr)
{
if (rb_reg_search(re, str, 0, 0) >= 0) {
if (rb_reg_search(re, str, 0, 0) < 0) {
return Qnil;
}
else if (! needstr) {
return Qundef;
}
else {
VALUE match = rb_backref_get();
int nth = rb_reg_backref_number(match, backref);
return rb_reg_nth_match(nth, match);
}
return Qnil;
}

static VALUE
rb_str_aref(VALUE str, VALUE indx)
rb_str_aref(VALUE str, VALUE indx, bool needstr)
{
long idx;

if (FIXNUM_P(indx)) {
idx = FIX2LONG(indx);
}
else if (RB_TYPE_P(indx, T_REGEXP)) {
return rb_str_subpat(str, indx, INT2FIX(0));
return rb_str_subpat(str, indx, INT2FIX(0), needstr);
}
else if (RB_TYPE_P(indx, T_STRING)) {
if (rb_str_index(str, indx, 0) != -1)
if (rb_str_index(str, indx, 0) == -1) {
return Qnil;
}
else if (! needstr) {
return Qundef;
}
else {
return rb_str_dup(indx);
return Qnil;
}
}
else {
/* check if indx is Range */
@@ -4462,14 +4474,32 @@ rb_str_aref(VALUE str, VALUE indx)
case Qnil:
return Qnil;
default:
return rb_str_substr(str, beg, len);
return str_substr(str, beg, len, true, needstr);
}
idx = NUM2LONG(indx);
}

return str_substr(str, idx, 1, FALSE);
return str_substr(str, idx, 1, FALSE, needstr);
}

static VALUE
rb_str_aref_m_embracing_unused_return_values(int argc, VALUE *argv, VALUE str)
{
bool needstr = rb_whether_the_return_value_is_used_p();

if (argc == 2) {
if (RB_TYPE_P(argv[0], T_REGEXP)) {
return rb_str_subpat(str, argv[0], argv[1], needstr);
}
else {
long beg = NUM2LONG(argv[0]);
long len = NUM2LONG(argv[1]);
return str_substr(str, beg, len, true, needstr);
}
}
rb_check_arity(argc, 1, 2);
return rb_str_aref(str, argv[0], needstr);
}

/*
* call-seq:
@@ -4543,18 +4573,15 @@ rb_str_aref(VALUE str, VALUE indx)
static VALUE
rb_str_aref_m(int argc, VALUE *argv, VALUE str)
{
if (argc == 2) {
if (RB_TYPE_P(argv[0], T_REGEXP)) {
return rb_str_subpat(str, argv[0], argv[1]);
}
else {
long beg = NUM2LONG(argv[0]);
long len = NUM2LONG(argv[1]);
return rb_str_substr(str, beg, len);
}
VALUE val = rb_str_aref_m_embracing_unused_return_values(argc, argv, str);

switch (val) {
case Qnil:
case Qundef:
return Qnil;
default:
return val;
}
rb_check_arity(argc, 1, 2);
return rb_str_aref(str, argv[0]);
}

VALUE
@@ -4860,8 +4887,14 @@ rb_str_slice_bang(int argc, VALUE *argv, VALUE str)
buf[i] = argv[i];
}
str_modify_keep_cr(str);
result = rb_str_aref_m(argc, buf, str);
if (!NIL_P(result)) {
result = rb_str_aref_m_embracing_unused_return_values(argc, buf, str);
switch (result) {
case Qnil:
return Qnil;
case Qundef:
result = Qnil;
/* FALLTHROUGH */
default:
buf[i] = rb_str_new(0,0);
rb_str_aset_m(argc+1, buf, str);
}
@@ -9591,7 +9624,10 @@ rb_str_partition(VALUE str, VALUE sep)
failed:
return rb_ary_new3(3, rb_str_dup(str), str_new_empty(str), str_new_empty(str));
}
sep = rb_str_subpat(str, sep, INT2FIX(0));
sep = rb_str_subpat(str, sep, INT2FIX(0), true);
assert(sep != Qnil);
assert(sep != Qundef);
assert(TYPE(sep) == T_STRING);
if (pos == 0 && RSTRING_LEN(sep) == 0) goto failed;
}
else {
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.