[前][次][番号順一覧][スレッド一覧]

ruby-changes:39889

From: nobu <ko1@a...>
Date: Tue, 29 Sep 2015 16:39:07 +0900 (JST)
Subject: [ruby-changes:39889] nobu:r51970 (trunk): compile.c: fix performance of strconcat

nobu	2015-09-29 16:37:40 +0900 (Tue, 29 Sep 2015)

  New Revision: 51970

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=51970

  Log:
    compile.c: fix performance of strconcat
    
    * compile.c (compile_dstr_fragments): fix performance by omitting
      the first empty string only for keeping literal encoding if
      other literals are too.  [ruby-core:70930] [Bug #11556]
    * string.c (rb_str_append_literal): append but keep encoding non
      US-ASCII.

  Modified files:
    trunk/ChangeLog
    trunk/compile.c
    trunk/insns.def
    trunk/string.c
    trunk/vm.c
Index: insns.def
===================================================================
--- insns.def	(revision 51969)
+++ insns.def	(revision 51970)
@@ -370,7 +370,7 @@ concatstrings https://github.com/ruby/ruby/blob/trunk/insns.def#L370
     val = rb_str_resurrect(TOPN(i));
     while (i-- > 0) {
 	const VALUE v = TOPN(i);
-	rb_str_append(val, v);
+	rb_str_append_literal(val, v);
     }
     POPN(num);
 }
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 51969)
+++ ChangeLog	(revision 51970)
@@ -1,3 +1,12 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Tue Sep 29 16:37:29 2015  Nobuyoshi Nakada  <nobu@r...>
+
+	* compile.c (compile_dstr_fragments): fix performance by omitting
+	  the first empty string only for keeping literal encoding if
+	  other literals are too.  [ruby-core:70930] [Bug #11556]
+
+	* string.c (rb_str_append_literal): append but keep encoding non
+	  US-ASCII.
+
 Mon Sep 28 17:40:17 2015  Shugo Maeda  <shugo@r...>
 
 	* lib/net/ftp.rb (mtime): use usec instead of fractions to parse
Index: string.c
===================================================================
--- string.c	(revision 51969)
+++ string.c	(revision 51970)
@@ -2460,6 +2460,18 @@ rb_str_append(VALUE str, VALUE str2) https://github.com/ruby/ruby/blob/trunk/string.c#L2460
     return rb_str_buf_append(str, str2);
 }
 
+VALUE
+rb_str_append_literal(VALUE str, VALUE str2)
+{
+    int encidx = rb_enc_get_index(str2);
+    rb_str_buf_append(str, str2);
+    if (encidx != ENCINDEX_US_ASCII) {
+	if (rb_enc_get_index(str) == ENCINDEX_US_ASCII)
+	    rb_enc_associate_index(str, encidx);
+    }
+    return str;
+}
+
 /*
  *  call-seq:
  *     str << integer       -> str
Index: compile.c
===================================================================
--- compile.c	(revision 51969)
+++ compile.c	(revision 51970)
@@ -788,6 +788,12 @@ FIRST_ELEMENT(LINK_ANCHOR *anchor) https://github.com/ruby/ruby/blob/trunk/compile.c#L788
 }
 
 static LINK_ELEMENT *
+LAST_ELEMENT(LINK_ANCHOR *anchor)
+{
+    return anchor->last;
+}
+
+static LINK_ELEMENT *
 POP_ELEMENT(ISEQ_ARG_DECLARE LINK_ANCHOR *anchor)
 {
     LINK_ELEMENT *elem = anchor->last;
@@ -2329,6 +2335,7 @@ compile_dstr_fragments(rb_iseq_t *iseq, https://github.com/ruby/ruby/blob/trunk/compile.c#L2335
 {
     NODE *list = node->nd_next;
     VALUE lit = node->nd_lit;
+    LINK_ELEMENT *first_lit = 0;
     int cnt = 0;
 
     debugp_param("nd_lit", lit);
@@ -2337,6 +2344,7 @@ compile_dstr_fragments(rb_iseq_t *iseq, https://github.com/ruby/ruby/blob/trunk/compile.c#L2344
 	if (RB_TYPE_P(lit, T_STRING))
 	    lit = node->nd_lit = rb_fstring(node->nd_lit);
 	ADD_INSN1(ret, nd_line(node), putobject, lit);
+	if (RSTRING_LEN(lit) == 0) first_lit = LAST_ELEMENT(ret);
     }
 
     while (list) {
@@ -2344,6 +2352,7 @@ compile_dstr_fragments(rb_iseq_t *iseq, https://github.com/ruby/ruby/blob/trunk/compile.c#L2352
 	if (nd_type(node) == NODE_STR) {
 	    node->nd_lit = rb_fstring(node->nd_lit);
 	    ADD_INSN1(ret, nd_line(node), putobject, node->nd_lit);
+	    lit = Qnil;
 	}
 	else {
 	    COMPILE(ret, "each string", node);
@@ -2351,6 +2360,10 @@ compile_dstr_fragments(rb_iseq_t *iseq, https://github.com/ruby/ruby/blob/trunk/compile.c#L2360
 	cnt++;
 	list = list->nd_next;
     }
+    if (NIL_P(lit) && first_lit) {
+	REMOVE_ELEM(first_lit);
+	--cnt;
+    }
     *cntp = cnt;
 
     return COMPILE_OK;
Index: vm.c
===================================================================
--- vm.c	(revision 51969)
+++ vm.c	(revision 51970)
@@ -21,6 +21,8 @@ https://github.com/ruby/ruby/blob/trunk/vm.c#L21
 #include "probes.h"
 #include "probes_helper.h"
 
+VALUE rb_str_append_literal(VALUE str, VALUE str2);
+
 static inline VALUE *
 VM_EP_LEP(VALUE *ep)
 {

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]