diff options
author | Koichi Sasada <ko1@cookpad.com> | 2019-01-16 10:48:30 +0000 |
---|---|---|
committer | Koichi Sasada <ko1@atdot.net> | 2019-07-31 09:44:23 +0900 |
commit | ebd398ac5a4147a1e652d6943c39a29a62f12e66 (patch) | |
tree | 79dba6622c591db987f0a9c065fe37cd09a58e98 /test/ruby/test_hash.rb | |
parent | 4afd8975242917d319cfb20c7ed635b979ad48d5 (diff) |
remove RHash::iter_lev.
iter_lev is used to detect the hash is iterating or not.
Usually, iter_lev should be very small number (1 or 2) so
`int` is overkill.
This patch introduce iter_lev in flags (7 bits, FL13 to FL19)
and if iter_lev exceeds this range, save it in hidden attribute.
We can get 1 word in RHash.
We can't modify frozen objects. Therefore I added new internal API
`rb_ivar_set_internal()` which allows us to set an attribute
even if the target object is frozen
if the name is hidden ivar (the name without `@` prefix).
Diffstat (limited to 'test/ruby/test_hash.rb')
-rw-r--r-- | test/ruby/test_hash.rb | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/test/ruby/test_hash.rb b/test/ruby/test_hash.rb index 243cad8d43..d973b1f763 100644 --- a/test/ruby/test_hash.rb +++ b/test/ruby/test_hash.rb @@ -1720,6 +1720,31 @@ class TestHash < Test::Unit::TestCase assert_equal(keys, h.keys.map(&:hash), msg) end + def hrec h, n, &b + if n > 0 + h.each{hrec(h, n-1, &b)} + else + yield + end + end + + def test_huge_iter_level + h = @cls[a: 1] + assert_raise(RuntimeError){ + hrec(h, 1000){ h[:c] = 3 } + } + + h = @cls[a: 1] + hrec(h, 1000){} + h[:c] = 3 + assert_equal(3, h[:c]) + + h = @cls[a: 1] + h.freeze # set hidden attribute for a frozen object + hrec(h, 1000){} + assert_equal(1, h.size) + end + class TestSubHash < TestHash class SubHash < Hash def reject(*) |