8000 Collapse putobject, putobject, newarray · github/ruby@e878315 · GitHub
[go: up one dir, main page]

Skip to content

Commit e878315

Browse files
committed
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] ```
1 parent 5d3aa0a commit e878315

File tree

2 files changed

+42
-8
lines changed

2 files changed

+42
-8
lines changed

compile.c

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3847,7 +3847,7 @@ enum compile_array_type_t {
38473847
};
38483848

38493849
static inline int
3850-
static_literal_node_p(const NODE *node)
3850+
static_literal_node_p(const NODE *node, const rb_iseq_t *iseq)
38513851
{
38523852
node = node->nd_head;
38533853
switch (nd_type(node)) {
@@ -3856,13 +3856,19 @@ static_literal_node_p(const NODE *node)
38563856
case NODE_TRUE:
38573857
case NODE_FALSE:
38583858
return TRUE;
3859+
case NODE_STR:
3860+
if (ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal) {
3861+
return TRUE;
3862+
} else {
3863+
return FALSE;
3864+
}
38593865
default:
38603866
return FALSE;
38613867
}
38623868
}
38633869

38643870
static inline VALUE
3865-
static_literal_value(const NODE *node)
3871+
static_literal_value(const NODE *node, rb_iseq_t *iseq)
38663872
{
38673873
node = node->nd_head;
38683874
switch (nd_type(node)) {
@@ -3872,6 +3878,17 @@ static_literal_value(const NODE *node)
38723878
return Qtrue;
38733879
case NODE_FALSE:
38743880
return Qfalse;
3881+
case NODE_STR:
3882+
if (ISEQ_COMPILE_DATA(iseq)->option->debug_frozen_string_literal || RTEST(ruby_debug)) {
3883+
VALUE lit;
3884+
VALUE debug_info = rb_ary_new_from_args(2, rb_iseq_path(iseq), INT2FIX((int)nd_line(node)));
3885+
lit = rb_str_dup(node->nd_lit);
3886+
rb_ivar_set(lit, id_debug_created_info, rb_obj_freeze(debug_info));
3887+
return rb_str_freeze(lit);
3888+
}
3889+
else {
3890+
return rb_fstring(node->nd_lit);
3891+
}
38753892
default:
38763893
return node->nd_lit;
38773894
}
@@ -3921,7 +3938,7 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node_ro
39213938
}
39223939
break;
39233940
}
3924-
if (opt_p && !static_literal_node_p(node)) {
3941+
if (opt_p && !static_literal_node_p(node, iseq)) {
39253942
opt_p = 0;
39263943
}
39273944

@@ -3943,15 +3960,15 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node_ro
39433960
node = start_node;
39443961

39453962
while (node != end_node) {
3946-
rb_ary_push(ary, static_literal_value(node));
3963+
rb_ary_push(ary, static_literal_value(node, iseq));
39473964
node = node->nd_next;
39483965
}
39493966
while (node && node->nd_next &&
3950-
static_literal_node_p(node) &&
3951-
static_literal_node_p(node->nd_next)) {
3967+
static_literal_node_p(node, iseq) &&
3968+
static_literal_node_p(node->nd_next, iseq)) {
39523969
VALUE elem[2];
3953-
elem[0] = static_literal_value(node);
3954-
elem[1] = static_literal_value(node->nd_next);
3970+
elem[0] = static_literal_value(node, iseq);
3971+
elem[1] = static_literal_value(node->nd_next, iseq);
39553972
rb_ary_cat(ary, elem, 2);
39563973
node = node->nd_next->nd_next;
39573974
len++;

test/ruby/test_literal.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,12 @@ def test_frozen_string
177177
end
178178
end
179179

180+
def test_frozen_string_in_array_literal
181+
list = eval("# frozen-string-literal: true\n""['foo', 'bar']")
182+
assert_equal 2, list.length
183+
list.each { |str| assert_predicate str, :frozen? }
184+
end
185+
180186
if defined?(RubyVM::InstructionSequence.compile_option) and
181187
RubyVM::InstructionSequence.compile_option.key?(:debug_frozen_string_literal)
182188
def test_debug_frozen_string
@@ -189,6 +195,17 @@ def test_debug_frozen_string
189195
str << "x"
190196
}
191197
end
198+
199+
def test_debug_frozen_string_in_array_literal
200+
src = '["foo"]'; f = "test.rb"; n = 1
201+
opt = {frozen_string_literal: true, debug_frozen_string_literal: true}
202+
ary = RubyVM::InstructionSequence.compile(src, f, f, n, opt).eval
203+
assert_equal("foo", ary.first)
204+
assert_predicate(ary.first, :frozen?)
205+
assert_raise_with_message(FrozenError, /created at #{Regexp.quote(f)}:#{n}/) {
206+
ary.first << "x"
207+
}
208+
end
192209
end
193210

194211
def test_regexp

0 commit comments

Comments
 (0)
0