diff options
author | Jean Boussier <[email protected]> | 2024-08-08 14:11:37 +0200 |
---|---|---|
committer | Jean Boussier <[email protected]> | 2024-08-10 10:09:14 +0200 |
commit | 6ee9a08d32800974c596a01e9190cc8e778a6ee5 (patch) | |
tree | 33ab4c838bb9b26c6359cae978c7e11139145809 | |
parent | 7b7dde37f546b74f1dd15e482235fec139b80b70 (diff) |
rb_setup_fake_ary: use precomputed flags
Setting up the fake array is a bit more expensive than would be
expected because `rb_ary_freeze` does a lot of checks and lookup
a shape transition.
If we assume fake arrays will always be frozen, we can precompute
the flags state and just assign it.
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/11344
-rw-r--r-- | array.c | 34 | ||||
-rw-r--r-- | vm_insnhelper.c | 4 |
2 files changed, 26 insertions, 12 deletions
@@ -892,17 +892,29 @@ rb_ary_free(VALUE ary) } } +static VALUE fake_ary_flags; + +static VALUE +init_fake_ary_flags(void) +{ + struct RArray fake_ary = {0}; + fake_ary.basic.flags = T_ARRAY; + VALUE ary = (VALUE)&fake_ary; + rb_ary_freeze(ary); + return fake_ary.basic.flags; +} + VALUE -rb_setup_fake_ary(struct RArray *fake_ary, const VALUE *list, long len, bool freeze) -{ - fake_ary->basic.flags = T_ARRAY; - VALUE ary = (VALUE)fake_ary; - RBASIC_CLEAR_CLASS(ary); - ARY_SET_PTR(ary, list); - ARY_SET_HEAP_LEN(ary, len); - ARY_SET_CAPA(ary, len); - if (freeze) rb_ary_freeze(ary); - return ary; +rb_setup_fake_ary(struct RArray *fake_ary, const VALUE *list, long len) +{ + fake_ary->basic.flags = fake_ary_flags; + RBASIC_CLEAR_CLASS((VALUE)fake_ary); + + // bypass frozen checks + fake_ary->as.heap.ptr = list; + fake_ary->as.heap.len = len; + fake_ary->as.heap.aux.capa = len; + return (VALUE)fake_ary; } size_t @@ -8677,6 +8689,8 @@ rb_ary_deconstruct(VALUE ary) void Init_Array(void) { + fake_ary_flags = init_fake_ary_flags(); + rb_cArray = rb_define_class("Array", rb_cObject); rb_include_module(rb_cArray, rb_mEnumerable); diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 077d0cea21..29e6f28dec 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -6199,7 +6199,7 @@ rb_vm_opt_newarray_hash(rb_execution_context_t *ec, rb_num_t num, const VALUE *p return vm_opt_newarray_hash(ec, num, ptr); } -VALUE rb_setup_fake_ary(struct RArray *fake_ary, const VALUE *list, long len, bool freeze); +VALUE rb_setup_fake_ary(struct RArray *fake_ary, const VALUE *list, long len); VALUE rb_ec_pack_ary(rb_execution_context_t *ec, VALUE ary, VALUE fmt, VALUE buffer); static VALUE @@ -6207,7 +6207,7 @@ vm_opt_newarray_pack_buffer(rb_execution_context_t *ec, rb_num_t num, const VALU { if (BASIC_OP_UNREDEFINED_P(BOP_PACK, ARRAY_REDEFINED_OP_FLAG)) { struct RArray fake_ary; - VALUE ary = rb_setup_fake_ary(&fake_ary, ptr, num, true); + VALUE ary = rb_setup_fake_ary(&fake_ary, ptr, num); return rb_ec_pack_ary(ec, ary, fmt, (UNDEF_P(buffer) ? Qnil : buffer)); } else { |