diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2018-04-17 13:20:09 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2018-04-17 17:21:45 +0900 |
| commit | 0e76faed8cfc55b743b1eac36ea92e772d9f2da6 (patch) | |
| tree | 77adf127c35dc1af070d2f1ae01f922a4264a4ed | |
| parent | 5c15aa2f3b7bca49b49384951fc5aba1e36bfd79 (diff) | |
| download | mruby-0e76faed8cfc55b743b1eac36ea92e772d9f2da6.tar.gz mruby-0e76faed8cfc55b743b1eac36ea92e772d9f2da6.zip | |
Make `ary_replace()` to share entry buffers if possible.
| -rw-r--r-- | src/array.c | 29 |
1 files changed, 28 insertions, 1 deletions
diff --git a/src/array.c b/src/array.c index 09de566f8..043cd7325 100644 --- a/src/array.c +++ b/src/array.c @@ -349,12 +349,39 @@ mrb_ary_plus(mrb_state *mrb, mrb_value self) return mrb_obj_value(a2); } +#define ARY_REPLACE_SHARED_MIN 20 + static void ary_replace(mrb_state *mrb, struct RArray *a, struct RArray *b) { mrb_int len = ARY_LEN(b); - ary_modify(mrb, a); + ary_modify_check(mrb, a); + if (a == b) return; + if (ARY_SHARED_P(a)) { + mrb_ary_decref(mrb, a->as.heap.aux.shared); + a->as.heap.aux.capa = 0; + a->as.heap.len = 0; + a->as.heap.ptr = NULL; + ARY_UNSET_SHARED_FLAG(a); + } + if (ARY_SHARED_P(b)) { + shared_b: + if (ARY_EMBED_P(a)) { + ARY_UNSET_EMBED_FLAG(a); + } + a->as.heap.ptr = b->as.heap.ptr; + a->as.heap.len = len; + a->as.heap.aux.shared = b->as.heap.aux.shared; + a->as.heap.aux.shared->refcnt++; + ARY_SET_SHARED_FLAG(a); + mrb_write_barrier(mrb, (struct RBasic*)a); + return; + } + if (!MRB_FROZEN_P(b) && len > ARY_REPLACE_SHARED_MIN) { + ary_make_shared(mrb, b); + goto shared_b; + } if (ARY_CAPA(a) < len) ary_expand_capa(mrb, a, len); array_copy(ARY_PTR(a), ARY_PTR(b), len); |
