Skip to content

Commit e1238a1

Browse files
mametenderlove
andcommitted
Enumerable#all?: Stop optimizing when a given block is not optimizable
This is a follow up to 1828226. Co-Authored-By: Aaron Patterson <tenderlove@ruby-lang.org>
1 parent 724d95a commit e1238a1

File tree

2 files changed

+15
-4
lines changed

2 files changed

+15
-4
lines changed

enum.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1743,6 +1743,9 @@ enum_sort_by(VALUE obj)
17431743

17441744
#define ENUMFUNC(name) argc ? name##_eqq : rb_block_given_p() ? name##_iter_i : name##_i
17451745

1746+
#define ENUM_BLOCK_CALL(name) \
1747+
rb_block_call2(obj, id_each, 0, 0, ENUMFUNC(name), (VALUE)memo, rb_block_given_p() && rb_block_pair_yield_optimizable() ? RB_BLOCK_NO_USE_PACKED_ARGS : 0);
1748+
17461749
#define MEMO_ENUM_NEW(v1) (rb_check_arity(argc, 0, 1), MEMO_NEW((v1), (argc ? *argv : 0), 0))
17471750

17481751
#define DEFINE_ENUMFUNCS(name) \
@@ -1836,7 +1839,7 @@ enum_all(int argc, VALUE *argv, VALUE obj)
18361839
{
18371840
struct MEMO *memo = MEMO_ENUM_NEW(Qtrue);
18381841
WARN_UNUSED_BLOCK(argc);
1839-
rb_block_call2(obj, id_each, 0, 0, ENUMFUNC(all), (VALUE)memo, RB_BLOCK_NO_USE_PACKED_ARGS);
1842+
ENUM_BLOCK_CALL(all);
18401843
return memo->v1;
18411844
}
18421845

@@ -1898,7 +1901,7 @@ enum_any(int argc, VALUE *argv, VALUE obj)
18981901
{
18991902
struct MEMO *memo = MEMO_ENUM_NEW(Qfalse);
19001903
WARN_UNUSED_BLOCK(argc);
1901-
rb_block_call2(obj, id_each, 0, 0, ENUMFUNC(any), (VALUE)memo, RB_BLOCK_NO_USE_PACKED_ARGS);
1904+
ENUM_BLOCK_CALL(any);
19021905
return memo->v1;
19031906
}
19041907

@@ -2187,7 +2190,7 @@ enum_one(int argc, VALUE *argv, VALUE obj)
21872190
VALUE result;
21882191

21892192
WARN_UNUSED_BLOCK(argc);
2190-
rb_block_call2(obj, id_each, 0, 0, ENUMFUNC(one), (VALUE)memo, RB_BLOCK_NO_USE_PACKED_ARGS);
2193+
ENUM_BLOCK_CALL(one);
21912194
result = memo->v1;
21922195
if (UNDEF_P(result)) return Qfalse;
21932196
return result;
@@ -2248,7 +2251,7 @@ enum_none(int argc, VALUE *argv, VALUE obj)
22482251
struct MEMO *memo = MEMO_ENUM_NEW(Qtrue);
22492252

22502253
WARN_UNUSED_BLOCK(argc);
2251-
rb_block_call2(obj, id_each, 0, 0, ENUMFUNC(none), (VALUE)memo, RB_BLOCK_NO_USE_PACKED_ARGS);
2254+
ENUM_BLOCK_CALL(none);
22522255
return memo->v1;
22532256
}
22542257

test/ruby/test_enum.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1348,4 +1348,12 @@ def each
13481348
klass.new.grep(/(b.)/) { svars << $1 }
13491349
assert_equal(["ba", "ba"], svars)
13501350
end
1351+
1352+
def test_all_fast
1353+
data = { "key" => { "key2" => 1 } }
1354+
kk = vv = nil
1355+
data.all? { |(k, v)| kk, vv = k, v }
1356+
assert_equal(kk, "key")
1357+
assert_equal(vv, { "key2" => 1 })
1358+
end
13511359
end

0 commit comments

Comments
 (0)