Skip to content

Commit b42890f

Browse files
committed
perf: Use NonNull for garbage collected pointers
1 parent 044b5f7 commit b42890f

File tree

1 file changed

+28
-31
lines changed

1 file changed

+28
-31
lines changed

vm/src/gc.rs

Lines changed: 28 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
1-
use std::any::{Any, TypeId};
2-
use std::cell::Cell;
3-
use std::cmp::Ordering;
4-
use std::collections::hash_map::Entry;
5-
use std::collections::VecDeque;
6-
use std::fmt;
7-
use std::hash::{Hash, Hasher};
8-
use std::marker::PhantomData;
9-
use std::mem;
10-
use std::ops::{Deref, DerefMut};
11-
use std::ptr;
12-
use std::sync::Arc;
1+
use std::{
2+
any::{Any, TypeId},
3+
cell::Cell,
4+
cmp::Ordering,
5+
collections::hash_map::Entry,
6+
collections::VecDeque,
7+
fmt,
8+
hash::{Hash, Hasher},
9+
marker::PhantomData,
10+
mem,
11+
ops::{Deref, DerefMut},
12+
ptr::{self, NonNull},
13+
sync::Arc,
14+
};
1315

1416
use crate::base::fnv::FnvMap;
1517
use crate::interner::InternedStr;
@@ -341,10 +343,7 @@ impl GcHeader {
341343
///
342344
/// It is only safe to access data through a `GcPtr` if the value is rooted (stored in a place
343345
/// where the garbage collector will find it during the mark phase).
344-
pub struct GcPtr<T: ?Sized> {
345-
// TODO Use NonZero to allow for better optimizing
346-
ptr: *const T,
347-
}
346+
pub struct GcPtr<T: ?Sized>(NonNull<T>);
348347

349348
unsafe impl<T: ?Sized + Send + Sync> Send for GcPtr<T> {}
350349
unsafe impl<T: ?Sized + Send + Sync> Sync for GcPtr<T> {}
@@ -353,14 +352,14 @@ impl<T: ?Sized> Copy for GcPtr<T> {}
353352

354353
impl<T: ?Sized> Clone for GcPtr<T> {
355354
fn clone(&self) -> GcPtr<T> {
356-
GcPtr { ptr: self.ptr }
355+
GcPtr(self.0)
357356
}
358357
}
359358

360359
impl<T: ?Sized> Deref for GcPtr<T> {
361360
type Target = T;
362361
fn deref(&self) -> &T {
363-
unsafe { &*self.ptr }
362+
unsafe { self.0.as_ref() }
364363
}
365364
}
366365

@@ -411,12 +410,12 @@ impl<T: ?Sized> GcPtr<T> {
411410
/// Unsafe as it is up to the caller to ensure that this pointer is not referenced somewhere
412411
/// else
413412
pub unsafe fn as_mut(&mut self) -> &mut T {
414-
&mut *(self.ptr as *mut T)
413+
self.0.as_mut()
415414
}
416415

417416
/// Unsafe as `ptr` must have been allocted by this garbage collector
418417
pub unsafe fn from_raw(ptr: *const T) -> GcPtr<T> {
419-
GcPtr { ptr }
418+
GcPtr(NonNull::new_unchecked(ptr as *mut _))
420419
}
421420

422421
pub fn generation(&self) -> Generation {
@@ -444,13 +443,8 @@ impl<T: ?Sized> GcPtr<T> {
444443
}
445444

446445
fn header(&self) -> &GcHeader {
447-
// Use of transmute_copy allows us to get the pointer
448-
// to the data regardless of wether T is unsized or not
449-
// (DST is structured as (ptr, len))
450-
// This function should always be safe to call as GcPtr's should always have a header
451-
// TODO: Better way of doing this?
452446
unsafe {
453-
let p: *mut u8 = mem::transmute_copy(&self.ptr);
447+
let p = self.0.as_ptr() as *mut u8;
454448
let header = p.offset(-(GcHeader::value_offset() as isize));
455449
&*(header as *const GcHeader)
456450
}
@@ -460,8 +454,9 @@ impl<T: ?Sized> GcPtr<T> {
460454
impl<'a, T: Traverseable + Send + Sync + 'a> GcPtr<T> {
461455
/// Coerces `self` to a `Traverseable` trait object
462456
pub fn as_traverseable(self) -> GcPtr<Traverseable + Send + Sync + 'a> {
463-
GcPtr {
464-
ptr: self.ptr as *const (Traverseable + Send + Sync),
457+
unsafe {
458+
let ptr: &(Traverseable + Send + Sync) = self.0.as_ref();
459+
GcPtr(NonNull::new_unchecked(ptr as *const _ as *mut _))
465460
}
466461
}
467462
}
@@ -470,8 +465,10 @@ impl GcPtr<str> {
470465
pub fn as_traverseable_string(self) -> GcPtr<Traverseable + Send + Sync> {
471466
// As there is nothing to traverse in a str we can safely cast it to *const u8 and use
472467
// u8's Traverseable impl
473-
GcPtr {
474-
ptr: self.as_ptr() as *const (Traverseable + Send + Sync),
468+
unsafe {
469+
GcPtr(NonNull::new_unchecked(
470+
self.as_ptr() as *const (Traverseable + Send + Sync) as *mut _,
471+
))
475472
}
476473
}
477474
}
@@ -791,7 +788,7 @@ impl Gc {
791788
// that the pointer was initialized
792789
assert!(ret == p);
793790
self.values = Some(ptr);
794-
GcPtr { ptr: p }
791+
GcPtr(NonNull::new_unchecked(p))
795792
}
796793
}
797794

0 commit comments

Comments
 (0)