Skip to content

Commit 86946e7

Browse files
committed
add opt_aset|aref_str [Bug ruby#9382]
1 parent c29302d commit 86946e7

File tree

4 files changed

+86
-2
lines changed

4 files changed

+86
-2
lines changed

compile.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4330,6 +4330,23 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
43304330
}
43314331
break;
43324332
}
4333+
if (node->nd_mid == idAREF &&
4334+
node->nd_recv != (NODE *)1 &&
4335+
node->nd_args &&
4336+
nd_type(node->nd_args) == NODE_ARRAY &&
4337+
node->nd_args->nd_alen == 1 &&
4338+
nd_type(node->nd_args->nd_head) == NODE_STR)
4339+
{
4340+
VALUE str = rb_fstring(node->nd_args->nd_head->nd_lit);
4341+
node->nd_args->nd_head->nd_lit = str;
4342+
COMPILE(ret, "recv", node->nd_recv);
4343+
ADD_INSN2(ret, line, opt_aref_str,
4344+
new_callinfo(iseq, idAREF, 1, 0, 0), str);
4345+
if (poped) {
4346+
ADD_INSN(ret, line, pop);
4347+
}
4348+
break;
4349+
}
43334350
case NODE_FCALL:
43344351
case NODE_VCALL:{ /* VCALL: variable or call */
43354352
/*
@@ -5300,6 +5317,25 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
53005317
VALUE flag = 0;
53015318
VALUE argc;
53025319

5320+
if (node->nd_mid == idASET &&
5321+
node->nd_recv != (NODE *)1 &&
5322+
node->nd_args &&
5323+
nd_type(node->nd_args) == NODE_ARRAY &&
5324+
node->nd_args->nd_alen == 2 &&
5325+
nd_type(node->nd_args->nd_head) == NODE_STR)
5326+
{
5327+
VALUE str = rb_fstring(node->nd_args->nd_head->nd_lit);
5328+
node->nd_args->nd_head->nd_lit = str;
5329+
COMPILE(ret, "recv", node->nd_recv);
5330+
COMPILE(ret, "value", node->nd_args->nd_next->nd_head);
5331+
ADD_INSN2(ret, line, opt_aset_str,
5332+
new_callinfo(iseq, idASET, 2, 0, 0), str);
5333+
if (poped) {
5334+
ADD_INSN(ret, line, pop);
5335+
}
5336+
break;
5337+
}
5338+
53035339
INIT_ANCHOR(recv);
53045340
INIT_ANCHOR(args);
53055341
argc = setup_args(iseq, args, node->nd_args, &flag);

hash.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2413,7 +2413,7 @@ static VALUE rb_hash_compare_by_id_p(VALUE hash);
24132413
* h1["a"] #=> 100
24142414
* h1.compare_by_identity
24152415
* h1.compare_by_identity? #=> true
2416-
* h1["a"] #=> nil # different objects.
2416+
* h1["a".dup] #=> nil # different objects.
24172417
* h1[:c] #=> "c" # same symbols are all same.
24182418
*
24192419
*/

insns.def

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1901,6 +1901,47 @@ opt_aset
19011901
}
19021902
}
19031903

1904+
/**
1905+
@c optimize
1906+
@e recv[str] = set
1907+
@j 最適化された recv[str] = set。
1908+
*/
1909+
DEFINE_INSN
1910+
opt_aset_str
1911+
(CALL_INFO ci, VALUE key)
1912+
(VALUE recv, VALUE val)
1913+
(VALUE val)
1914+
{
1915+
if (!SPECIAL_CONST_P(recv) && RBASIC_CLASS(recv) == rb_cHash && BASIC_OP_UNREDEFINED_P(BOP_ASET, HASH_REDEFINED_OP_FLAG)) {
1916+
rb_hash_aset(recv, key, val);
1917+
} else {
1918+
PUSH(recv);
1919+
PUSH(rb_str_resurrect(key));
1920+
PUSH(val);
1921+
CALL_SIMPLE_METHOD(recv);
1922+
}
1923+
}
1924+
1925+
/**
1926+
@c optimize
1927+
@e recv[str]
1928+
@j 最適化された recv[str]。
1929+
*/
1930+
DEFINE_INSN
1931+
opt_aref_str
1932+
(CALL_INFO ci, VALUE key)
1933+
(VALUE recv)
1934+
(VALUE val)
1935+
{
1936+
if (!SPECIAL_CONST_P(recv) && RBASIC_CLASS(recv) == rb_cHash && BASIC_OP_UNREDEFINED_P(BOP_AREF, HASH_REDEFINED_OP_FLAG)) {
1937+
val = rb_hash_aref(recv, key);
1938+
} else {
1939+
PUSH(recv);
1940+
PUSH(rb_str_resurrect(key));
1941+
CALL_SIMPLE_METHOD(recv);
1942+
}
1943+
}
1944+
19041945
/**
19051946
@c optimize
19061947
@e optimized length

test/ruby/test_hash.rb

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,13 @@ def test_ASET # '[]='
209209
assert_equal(256, h[z])
210210
end
211211

212+
def test_ASET_fstring_key
213+
a, b = {}, {}
214+
a["abc"] = 1
215+
b["abc"] = 1
216+
assert_same a.keys[0], b.keys[0]
217+
end
218+
212219
def test_NEWHASH_fstring_key
213220
a = {"ABC" => :t}
214221
b = {"ABC" => :t}
@@ -948,7 +955,7 @@ def test_assoc_compare_by_identity
948955
h = @cls[]
949956
h.compare_by_identity
950957
h["a"] = 1
951-
h["a"] = 2
958+
h["a".dup] = 2
952959
assert_equal(["a",1], h.assoc("a"))
953960
end
954961

0 commit comments

Comments
 (0)