[前][次][番号順一覧][スレッド一覧]

ruby-changes:70729

From: Matt <ko1@a...>
Date: Wed, 5 Jan 2022 00:28:01 +0900 (JST)
Subject: [ruby-changes:70729] ad007bc6ea (master): Switch `is_pointer_to_heap` to use library bsearch

https://git.ruby-lang.org/ruby.git/commit/?id=ad007bc6ea

From ad007bc6ea1c75c2547be2481fba60b38dd1add1 Mon Sep 17 00:00:00 2001
From: Matt Valentine-House <matt@e...>
Date: Mon, 15 Nov 2021 21:28:20 +0000
Subject: Switch `is_pointer_to_heap` to use library bsearch

This commit switches from a custom implemented bsearch algorithm to
use the one provided by the C standard library.

Because `is_pointer_to_heap` will only return true if the pointer
being searched for is a valid slot starting address within the heap
page body, we've extracted the bsearch call site into a more general
function so we can use it elsewhere.

The new function `heap_page_for_ptr` returns the heap page for any heap
page pointer, regardless of whether that is at the start of a slot or
in the middle of one.

We then use this function as the basis of `is_pointer_to_heap`.
---
 gc.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++----------------------
 1 file changed, 50 insertions(+), 23 deletions(-)

diff --git a/gc.c b/gc.c
index d9ce489724b..b00140bee67 100644
--- a/gc.c
+++ b/gc.c
@@ -2797,13 +2797,49 @@ rb_objspace_data_type_name(VALUE obj) https://github.com/ruby/ruby/blob/trunk/gc.c#L2797
     }
 }
 
+static int
+ptr_in_page_body_p(const void *ptr, const void *memb)
+{
+    struct heap_page *page = *(struct heap_page **)memb;
+    uintptr_t p_body = (uintptr_t)GET_PAGE_BODY(page->start);
+
+    if ((uintptr_t)ptr >= p_body) {
+        return (uintptr_t)ptr < (p_body + HEAP_PAGE_SIZE) ? 0 : 1;
+    }
+    else {
+        return -1;
+    }
+}
+
+PUREFUNC(static inline struct heap_page * heap_page_for_ptr(rb_objspace_t *objspace, uintptr_t ptr);)
+static inline struct heap_page *
+heap_page_for_ptr(rb_objspace_t *objspace, uintptr_t ptr)
+{
+    struct heap_page **res;
+
+    if (ptr < (uintptr_t)heap_pages_lomem ||
+            ptr > (uintptr_t)heap_pages_himem) {
+        return NULL;
+    }
+
+    res = bsearch((void *)ptr, heap_pages_sorted,
+                  (size_t)heap_allocated_pages, sizeof(struct heap_page *),
+                  ptr_in_page_body_p);
+
+    if (res) {
+        return *res;
+    }
+    else {
+        return NULL;
+    }
+}
+
 PUREFUNC(static inline int is_pointer_to_heap(rb_objspace_t *objspace, void *ptr);)
 static inline int
 is_pointer_to_heap(rb_objspace_t *objspace, void *ptr)
 {
     register RVALUE *p = RANY(ptr);
     register struct heap_page *page;
-    register size_t hi, lo, mid;
 
     RB_DEBUG_COUNTER_INC(gc_isptr_trial);
 
@@ -2813,30 +2849,21 @@ is_pointer_to_heap(rb_objspace_t *objspace, void *ptr) https://github.com/ruby/ruby/blob/trunk/gc.c#L2849
     if ((VALUE)p % sizeof(RVALUE) != 0) return FALSE;
     RB_DEBUG_COUNTER_INC(gc_isptr_align);
 
-    /* check if p looks like a pointer using bsearch*/
-    lo = 0;
-    hi = heap_allocated_pages;
-    while (lo < hi) {
-	mid = (lo + hi) / 2;
-	page = heap_pages_sorted[mid];
-	if (page->start <= p) {
-            if ((uintptr_t)p < ((uintptr_t)page->start + (page->total_slots * page->slot_size))) {
-                RB_DEBUG_COUNTER_INC(gc_isptr_maybe);
+    page = heap_page_for_ptr(objspace, (uintptr_t)ptr);
+    if (page) {
+        GC_ASSERT(page == GET_HEAP_PAGE(ptr));
 
-                if (page->flags.in_tomb) {
-                    return FALSE;
-                }
-                else {
-                    if ((NUM_IN_PAGE(p) * sizeof(RVALUE)) % page->slot_size != 0) return FALSE;
+        RB_DEBUG_COUNTER_INC(gc_isptr_maybe);
+        if (page->flags.in_tomb) {
+            return FALSE;
+        }
+        else {
+            if ((uintptr_t)p < ((uintptr_t)page->start)) return FALSE;
+            if ((uintptr_t)p >= ((uintptr_t)page->start + (page->total_slots * page->slot_size))) return FALSE;
+            if ((NUM_IN_PAGE(p) * sizeof(RVALUE)) % page->slot_size != 0) return FALSE;
 
-                    return TRUE;
-                }
-	    }
-	    lo = mid + 1;
-	}
-	else {
-	    hi = mid;
-	}
+            return TRUE;
+        }
     }
     return FALSE;
 }
-- 
cgit v1.2.1


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]