summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--compile.c13
-rw-r--r--insns.def2
-rw-r--r--string.c12
-rw-r--r--vm.c2
5 files changed, 37 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index 47bc210..be8d0d1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+Tue Sep 29 16:37:29 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * 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@ruby-lang.org>
* lib/net/ftp.rb (mtime): use usec instead of fractions to parse
diff --git a/compile.c b/compile.c
index 9928aaa..9c59b59 100644
--- a/compile.c
+++ b/compile.c
@@ -788,6 +788,12 @@ FIRST_ELEMENT(LINK_ANCHOR *anchor)
}
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, LINK_ANCHOR *ret, NODE *node, int *cntp)
{
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, LINK_ANCHOR *ret, NODE *node, int *cntp)
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, LINK_ANCHOR *ret, NODE *node, int *cntp)
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, LINK_ANCHOR *ret, NODE *node, int *cntp)
cnt++;
list = list->nd_next;
}
+ if (NIL_P(lit) && first_lit) {
+ REMOVE_ELEM(first_lit);
+ --cnt;
+ }
*cntp = cnt;
return COMPILE_OK;
diff --git a/insns.def b/insns.def
index 7eb3221..a923d3a 100644
--- a/insns.def
+++ b/insns.def
@@ -370,7 +370,7 @@ concatstrings
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);
}
diff --git a/string.c b/string.c
index e93af5c..728676c 100644
--- a/string.c
+++ b/string.c
@@ -2460,6 +2460,18 @@ rb_str_append(VALUE str, VALUE str2)
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
diff --git a/vm.c b/vm.c
index 92b33f3..ee9f407 100644
--- a/vm.c
+++ b/vm.c
@@ -21,6 +21,8 @@
#include "probes.h"
#include "probes_helper.h"
+VALUE rb_str_append_literal(VALUE str, VALUE str2);
+
static inline VALUE *
VM_EP_LEP(VALUE *ep)
{