summaryrefslogtreecommitdiff
path: root/gc.c
diff options
context:
space:
mode:
authorMatt Valentine-House <[email protected]>2021-11-15 21:28:20 +0000
committerPeter Zhu <[email protected]>2022-01-04 10:27:46 -0500
commitad007bc6ea1c75c2547be2481fba60b38dd1add1 (patch)
tree96f223208bef4d185915bfbede2f00f55d9f55b7 /gc.c
parent615e9b28658c5b44a4474e04a53b84ae83b8e3fd (diff)
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`.
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/5187
Diffstat (limited to 'gc.c')
-rw-r--r--gc.c73
1 files changed, 50 insertions, 23 deletions
diff --git a/gc.c b/gc.c
index d9ce489724..b00140bee6 100644
--- a/gc.c
+++ b/gc.c
@@ -2797,13 +2797,49 @@ rb_objspace_data_type_name(VALUE obj)
}
}
+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)
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;
}