1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

Collapse putobject, putobject, newarray

This collapses:

```
== disasm: #<ISeq:bar@bench.rb:3 (3,0)-(5,3)> (catch: FALSE)
0000 putobject                    "a"                                 (   4)[LiCa]
0002 putobject                    "b"
0004 putobject                    "c"
0006 putobject                    "d"
0008 putobject                    "e"
0010 putobject                    "f"
0012 putobject                    "g"
0014 putobject                    "h"
0016 putobject                    "i"
0018 putobject                    "j"
0020 putobject                    "k"
0022 newarray                     11
0024 leave                                                            (   5)[Re]
```

In to this:

```
== disasm: #<ISeq:bar@bench.rb:3 (3,0)-(5,3)> (catch: FALSE)
0000 duparray                     ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"](   4)[LiCa]
0002 leave                                                            (   5)[Re]
```

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66174 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
tenderlove 2018-12-03 23:53:11 +00:00
parent 7712ffc7ee
commit 3b6321083a
2 changed files with 42 additions and 8 deletions

View file

@ -3847,7 +3847,7 @@ enum compile_array_type_t {
};
static inline int
static_literal_node_p(const NODE *node)
static_literal_node_p(const NODE *node, const rb_iseq_t *iseq)
{
node = node->nd_head;
switch (nd_type(node)) {
@ -3856,13 +3856,19 @@ static_literal_node_p(const NODE *node)
case NODE_TRUE:
case NODE_FALSE:
return TRUE;
case NODE_STR:
if (ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal) {
return TRUE;
} else {
return FALSE;
}
default:
return FALSE;
}
}
static inline VALUE
static_literal_value(const NODE *node)
static_literal_value(const NODE *node, rb_iseq_t *iseq)
{
node = node->nd_head;
switch (nd_type(node)) {
@ -3872,6 +3878,17 @@ static_literal_value(const NODE *node)
return Qtrue;
case NODE_FALSE:
return Qfalse;
case NODE_STR:
if (ISEQ_COMPILE_DATA(iseq)->option->debug_frozen_string_literal || RTEST(ruby_debug)) {
VALUE lit;
VALUE debug_info = rb_ary_new_from_args(2, rb_iseq_path(iseq), INT2FIX((int)nd_line(node)));
lit = rb_str_dup(node->nd_lit);
rb_ivar_set(lit, id_debug_created_info, rb_obj_freeze(debug_info));
return rb_str_freeze(lit);
}
else {
return rb_fstring(node->nd_lit);
}
default:
return node->nd_lit;
}
@ -3921,7 +3938,7 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node_ro
}
break;
}
if (opt_p && !static_literal_node_p(node)) {
if (opt_p && !static_literal_node_p(node, iseq)) {
opt_p = 0;
}
@ -3943,15 +3960,15 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node_ro
node = start_node;
while (node != end_node) {
rb_ary_push(ary, static_literal_value(node));
rb_ary_push(ary, static_literal_value(node, iseq));
node = node->nd_next;
}
while (node && node->nd_next &&
static_literal_node_p(node) &&
static_literal_node_p(node->nd_next)) {
static_literal_node_p(node, iseq) &&
static_literal_node_p(node->nd_next, iseq)) {
VALUE elem[2];
elem[0] = static_literal_value(node);
elem[1] = static_literal_value(node->nd_next);
elem[0] = static_literal_value(node, iseq);
elem[1] = static_literal_value(node->nd_next, iseq);
rb_ary_cat(ary, elem, 2);
node = node->nd_next->nd_next;
len++;

View file

@ -177,6 +177,12 @@ class TestRubyLiteral < Test::Unit::TestCase
end
end
def test_frozen_string_in_array_literal
list = eval("# frozen-string-literal: true\n""['foo', 'bar']")
assert_equal 2, list.length
list.each { |str| assert_predicate str, :frozen? }
end
if defined?(RubyVM::InstructionSequence.compile_option) and
RubyVM::InstructionSequence.compile_option.key?(:debug_frozen_string_literal)
def test_debug_frozen_string
@ -189,6 +195,17 @@ class TestRubyLiteral < Test::Unit::TestCase
str << "x"
}
end
def test_debug_frozen_string_in_array_literal
src = '["foo"]'; f = "test.rb"; n = 1
opt = {frozen_string_literal: true, debug_frozen_string_literal: true}
ary = RubyVM::InstructionSequence.compile(src, f, f, n, opt).eval
assert_equal("foo", ary.first)
assert_predicate(ary.first, :frozen?)
assert_raise_with_message(FrozenError, /created at #{Regexp.quote(f)}:#{n}/) {
ary.first << "x"
}
end
end
def test_regexp