diff options
author | 卜部昌平 <shyouhei@ruby-lang.org> | 2020-06-10 13:42:30 +0900 |
---|---|---|
committer | 卜部昌平 <shyouhei@ruby-lang.org> | 2020-06-29 11:05:41 +0900 |
commit | 2e8d8d10f211b52f520109a8bfdd3bb3a6eab8c0 (patch) | |
tree | a7a599505dfdf3611007f295468703238b64d92d /array.c | |
parent | 09b936d89cb66e38db46dbe782aa5f22f94656bc (diff) |
rb_ary_behead: do not goto into a branch
I'm not necessarily against every goto in general, but jumping into a
branch is definitely a bad idea. Better refactor.
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/3247
Diffstat (limited to 'array.c')
-rw-r--r-- | array.c | 56 |
1 files changed, 35 insertions, 21 deletions
@@ -1524,36 +1524,50 @@ rb_ary_shift_m(int argc, VALUE *argv, VALUE ary) return result; } -MJIT_FUNC_EXPORTED VALUE -rb_ary_behead(VALUE ary, long n) +static VALUE +behead_shared(VALUE ary, long n) { - if (n<=0) return ary; - + assert(ARY_SHARED_P(ary)); rb_ary_modify_check(ary); - if (ARY_SHARED_P(ary)) { - if (ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary))) { - setup_occupied_shared: - ary_mem_clear(ary, 0, n); - } - ARY_INCREASE_PTR(ary, n); - } - else { - if (RARRAY_LEN(ary) < ARY_DEFAULT_SIZE) { - RARRAY_PTR_USE_TRANSIENT(ary, ptr, { - MEMMOVE(ptr, ptr+n, VALUE, RARRAY_LEN(ary)-n); - }); /* WB: no new reference */ - } - else { - ary_make_shared(ary); - goto setup_occupied_shared; - } + if (ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary))) { + ary_mem_clear(ary, 0, n); } + ARY_INCREASE_PTR(ary, n); ARY_INCREASE_LEN(ary, -n); + ary_verify(ary); + return ary; +} +static VALUE +behead_transient(VALUE ary, long n) +{ + rb_ary_modify_check(ary); + RARRAY_PTR_USE_TRANSIENT(ary, ptr, { + MEMMOVE(ptr, ptr+n, VALUE, RARRAY_LEN(ary)-n); + }); /* WB: no new reference */ + ARY_INCREASE_LEN(ary, -n); ary_verify(ary); return ary; } +MJIT_FUNC_EXPORTED VALUE +rb_ary_behead(VALUE ary, long n) +{ + if (n <= 0) { + return ary; + } + else if (ARY_SHARED_P(ary)) { + return behead_shared(ary, n); + } + else if (RARRAY_LEN(ary) >= ARY_DEFAULT_SIZE) { + ary_make_shared(ary); + return behead_shared(ary, n); + } + else { + return behead_transient(ary, n); + } +} + static VALUE ary_ensure_room_for_unshift(VALUE ary, int argc) { |