Skip to content

Commit 6707372

Browse files
committed
[GR-19220] Adding rb_hash_new_capa to CEXT api (#3103)
PullRequest: truffleruby/3902
2 parents 7e5e57d + 023561f commit 6707372

File tree

8 files changed

+44
-1
lines changed

8 files changed

+44
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ Compatibility:
2828
* Handle `long long` and aliases in `Fiddle` (#3128, @eregon).
2929
* Add `Module#refinements` (#3039, @itarato).
3030
* Add `Refinement#refined_class` (#3039, @itarato).
31+
* Add `rb_hash_new_capa` function (#3039, @itarato).
3132

3233
Performance:
3334

lib/cext/ABI_version.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
8
1+
9

lib/cext/include/ruby/internal/intern/hash.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,17 @@ VALUE rb_hash(VALUE obj);
106106
*/
107107
VALUE rb_hash_new(void);
108108

109+
/**
110+
* Identical to rb_hash_new(), except it additionally specifies how many keys
111+
* it is expected to contain. This way you can create a hash that is large enough
112+
* for your need. For large hashes it means it won't need to be reallocated and
113+
* rehashed as much, improving performance.
114+
*
115+
* @param[in] capacity Designed capacity of the hash.
116+
* @return An empty Hash, whose capacity is `capacity`.
117+
*/
118+
VALUE rb_hash_new_capa(long capacity);
119+
109120
/**
110121
* Duplicates a hash.
111122
*

lib/truffle/truffle/cext.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -972,6 +972,11 @@ def rb_hash_new
972972
{}
973973
end
974974

975+
def rb_hash_new_capa(capacity)
976+
raise RuntimeError, 'st_table too big' if capacity < 0
977+
{}
978+
end
979+
975980
def rb_ident_hash_new
976981
{}.compare_by_identity
977982
end

spec/ruby/optional/capi/ext/hash_spec.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,10 @@ VALUE hash_spec_rb_hash_new(VALUE self) {
105105
return rb_hash_new();
106106
}
107107

108+
VALUE hash_spec_rb_hash_new_capa(VALUE self, VALUE capacity) {
109+
return rb_hash_new_capa(NUM2LONG(capacity));
110+
}
111+
108112
VALUE rb_ident_hash_new(void); /* internal.h, used in ripper */
109113

110114
VALUE hash_spec_rb_ident_hash_new(VALUE self) {
@@ -149,6 +153,7 @@ void Init_hash_spec(void) {
149153
rb_define_method(cls, "rb_hash_lookup2", hash_spec_rb_hash_lookup2, 3);
150154
rb_define_method(cls, "rb_hash_lookup2_default_undef", hash_spec_rb_hash_lookup2_default_undef, 2);
151155
rb_define_method(cls, "rb_hash_new", hash_spec_rb_hash_new, 0);
156+
rb_define_method(cls, "rb_hash_new_capa", hash_spec_rb_hash_new_capa, 1);
152157
rb_define_method(cls, "rb_ident_hash_new", hash_spec_rb_ident_hash_new, 0);
153158
rb_define_method(cls, "rb_hash_size", hash_spec_rb_hash_size, 1);
154159
rb_define_method(cls, "rb_hash_set_ifnone", hash_spec_rb_hash_set_ifnone, 2);

spec/ruby/optional/capi/hash_spec.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,22 @@
5050
end
5151
end
5252

53+
ruby_version_is '3.2' do
54+
describe "rb_hash_new_capa" do
55+
it "returns a new hash" do
56+
@s.rb_hash_new_capa(3).should == {}
57+
end
58+
59+
it "creates a hash with no default proc" do
60+
@s.rb_hash_new_capa(3) {}.default_proc.should be_nil
61+
end
62+
63+
it "raises RuntimeError when negative index is provided" do
64+
-> { @s.rb_hash_new_capa(-1) }.should raise_error(RuntimeError, "st_table too big")
65+
end
66+
end
67+
end
68+
5369
describe "rb_ident_hash_new" do
5470
it "returns a new compare by identity hash" do
5571
result = @s.rb_ident_hash_new

spec/truffleruby.next-specs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,4 @@ spec/ruby/core/sizedqueue/shift_spec.rb
3333
spec/ruby/core/module/refinements_spec.rb
3434
spec/ruby/core/refinement/refined_class_spec.rb
3535
spec/ruby/core/module/used_refinements_spec.rb
36+
spec/ruby/optional/capi/hash_spec.rb

src/main/c/cext/hash.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ VALUE rb_hash_new() {
2424
return RUBY_CEXT_INVOKE("rb_hash_new");
2525
}
2626

27+
VALUE rb_hash_new_capa(long capacity) {
28+
return rb_tr_wrap(polyglot_invoke(RUBY_CEXT, "rb_hash_new_capa", capacity));
29+
}
30+
2731
VALUE rb_ident_hash_new() {
2832
return RUBY_CEXT_INVOKE("rb_ident_hash_new");
2933
}

0 commit comments

Comments
 (0)