aboutsummaryrefslogtreecommitdiffstats
path: root/gc.c
diff options
context:
space:
mode:
authorPeter Zhu <peter@peterzhu.ca>2022-07-27 11:26:31 -0400
committerPeter Zhu <peter@peterzhu.ca>2022-07-28 10:02:12 -0400
commit1c16645216b6db04ccb1144e6f7e085e1e0a6132 (patch)
tree79f835bb18ecbabf593bbbc52eee85efd8e7c86c /gc.c
parent2375afb8d6fd218cd9083749d87a7a59946d8938 (diff)
downloadruby-1c16645216b6db04ccb1144e6f7e085e1e0a6132.tar.gz
Make array slices views rather than copies
Before this commit, if the slice fits in VWA, it would make a copy rather than a view. This is slower as it requires a memcpy of the contents.
Diffstat (limited to 'gc.c')
-rw-r--r--gc.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/gc.c b/gc.c
index 84f9aa30f6..cd48c47a94 100644
--- a/gc.c
+++ b/gc.c
@@ -9958,7 +9958,21 @@ static void
gc_ref_update_array(rb_objspace_t * objspace, VALUE v)
{
if (ARY_SHARED_P(v)) {
+#if USE_RVARGC
+ VALUE old_root = RARRAY(v)->as.heap.aux.shared_root;
+#endif
+
UPDATE_IF_MOVED(objspace, RARRAY(v)->as.heap.aux.shared_root);
+
+#if USE_RVARGC
+ VALUE new_root = RARRAY(v)->as.heap.aux.shared_root;
+ // If the root is embedded and its location has changed
+ if (ARY_EMBED_P(new_root) && new_root != old_root) {
+ size_t offset = (size_t)(RARRAY(v)->as.heap.ptr - RARRAY(old_root)->as.ary);
+ GC_ASSERT(RARRAY(v)->as.heap.ptr >= RARRAY(old_root)->as.ary);
+ RARRAY(v)->as.heap.ptr = RARRAY(new_root)->as.ary + offset;
+ }
+#endif
}
else {
long len = RARRAY_LEN(v);