Skip to content

Commit

Permalink
Store pointer to data directly in Rc and Arc
Browse files Browse the repository at this point in the history
  • Loading branch information
EFanZh committed Nov 4, 2024
1 parent 6739555 commit d7879fa
Show file tree
Hide file tree
Showing 9 changed files with 380 additions and 284 deletions.
291 changes: 147 additions & 144 deletions library/alloc/src/rc.rs

Large diffs are not rendered by default.

253 changes: 125 additions & 128 deletions library/alloc/src/sync.rs

Large diffs are not rendered by default.

12 changes: 11 additions & 1 deletion src/etc/gdb_providers.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,12 +180,22 @@ def children(self):
def display_hint():
return "array"

BYTE_PTR_TYPE = gdb.lookup_type("u8").pointer()

class StdRcProvider(printer_base):
def __init__(self, valobj, is_atomic=False):
def inner_ptr():
data_ptr = unwrap_unique_or_non_null(valobj["ptr"])
formatter = "alloc::sync::ArcInner<{}>" if is_atomic else "alloc::rc::RcInner<{}>"
inner_type = gdb.lookup_type(formatter.format(data_ptr.type.target().name))
data_offset = inner_type.fields()[-1].bitpos // 8
inner_ptr = data_ptr.reinterpret_cast(BYTE_PTR_TYPE) - data_offset

return inner_ptr.reinterpret_cast(inner_type.pointer())

self._valobj = valobj
self._is_atomic = is_atomic
self._ptr = unwrap_unique_or_non_null(valobj["ptr"])
self._ptr = inner_ptr()
self._value = self._ptr["data" if is_atomic else "value"]
self._strong = self._ptr["strong"]["v" if is_atomic else "value"]["value"]
self._weak = self._ptr["weak"]["v" if is_atomic else "value"]["value"] - 1
Expand Down
4 changes: 2 additions & 2 deletions src/etc/lldb_batchmode.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def print_debug(s):

def normalize_whitespace(s):
"""Replace newlines, tabs, multiple spaces, etc with exactly one space"""
return re.sub("\s+", " ", s)
return re.sub("\\s+", " ", s)


def breakpoint_callback(frame, bp_loc, dict):
Expand Down Expand Up @@ -208,7 +208,7 @@ def watchdog():

for line in script_file:
command = line.strip()
if command == "run" or command == "r" or re.match("^process\s+launch.*", command):
if command == "run" or command == "r" or re.match("^process\\s+launch.*", command):
# Before starting to run the program, let the thread sleep a bit, so all
# breakpoint added events can be processed
time.sleep(0.5)
Expand Down
4 changes: 2 additions & 2 deletions src/etc/lldb_providers.py
Original file line number Diff line number Diff line change
Expand Up @@ -670,15 +670,15 @@ def StdRcSummaryProvider(valobj, dict):
class StdRcSyntheticProvider:
"""Pretty-printer for alloc::rc::Rc<T> and alloc::sync::Arc<T>
struct Rc<T> { ptr: NonNull<RcInner<T>>, ... }
struct Rc<T> { ptr: NonNull<T>, ... }
rust 1.31.1: struct NonNull<T> { pointer: NonZero<*const T> }
rust 1.33.0: struct NonNull<T> { pointer: *const T }
struct NonZero<T>(T)
struct RcInner<T> { strong: Cell<usize>, weak: Cell<usize>, value: T }
struct Cell<T> { value: UnsafeCell<T> }
struct UnsafeCell<T> { value: T }
struct Arc<T> { ptr: NonNull<ArcInner<T>>, ... }
struct Arc<T> { ptr: NonNull<T>, ... }
struct ArcInner<T> { strong: atomic::AtomicUsize, weak: atomic::AtomicUsize, data: T }
struct AtomicUsize { v: UnsafeCell<usize> }
"""
Expand Down
12 changes: 8 additions & 4 deletions tests/codegen/placement-new.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,22 @@ pub fn box_default_inplace() -> Box<(String, String)> {
#[no_mangle]
pub fn rc_default_inplace() -> Rc<(String, String)> {
// CHECK-NOT: alloca
// CHECK: [[RC:%.*]] = {{.*}}call {{.*}}__rust_alloc(
// CHECK: [[RC:%.*]] = {{.*}}call {{.*}}__rust_alloc(i[[#BITS:]]
// CHECK-NOT: call void @llvm.memcpy
// CHECK: ret ptr [[RC]]
// CHECK: [[DATA:%.*]] = getelementptr inbounds i8, ptr [[RC]], i[[#BITS]] [[#div(BITS,4)]]
// CHECK-NOT: call void @llvm.memcpy
// CHECK: ret ptr [[DATA]]
Rc::default()
}

// CHECK-LABEL: @arc_default_inplace
#[no_mangle]
pub fn arc_default_inplace() -> Arc<(String, String)> {
// CHECK-NOT: alloca
// CHECK: [[ARC:%.*]] = {{.*}}call {{.*}}__rust_alloc(
// CHECK: [[RC:%.*]] = {{.*}}call {{.*}}__rust_alloc(i[[#BITS:]]
// CHECK-NOT: call void @llvm.memcpy
// CHECK: [[DATA:%.*]] = getelementptr inbounds i8, ptr [[RC]], i[[#BITS]] [[#div(BITS,4)]]
// CHECK-NOT: call void @llvm.memcpy
// CHECK: ret ptr [[ARC]]
// CHECK: ret ptr [[DATA]]
Arc::default()
}
82 changes: 82 additions & 0 deletions tests/codegen/zero-cost-rc-arc-deref.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
//@ compile-flags: -O -Z merge-functions=disabled

#![crate_type = "lib"]

use std::rc::Rc;
use std::sync::Arc;

// CHECK-LABEL: @deref_rc_sized(
// CHECK-NOT: getelementptr
// CHECK: ret
#[no_mangle]
pub fn deref_rc_sized(rc: &Rc<u32>) -> &u32 {
&rc
}

// CHECK-LABEL: @deref_rc_unsized(
// CHECK-COUNT-1: getelementptr
// CHECK: ret
#[no_mangle]
pub fn deref_rc_unsized(rc: &Rc<str>) -> &str {
&rc
}

// CHECK-LABEL: @deref_arc_sized(
// CHECK-NOT: getelementptr
// CHECK: ret
#[no_mangle]
pub fn deref_arc_sized(arc: &Arc<u32>) -> &u32 {
&arc
}

// CHECK-LABEL: @deref_arc_unsized(
// CHECK-COUNT-1: getelementptr
// CHECK: ret
#[no_mangle]
pub fn deref_arc_unsized(arc: &Arc<str>) -> &str {
&arc
}

// CHECK-LABEL: @rc_slice_to_ref_slice_sized(
// CHECK-NOT: getelementptr
// CHECK: tail call void @llvm.memcpy
// CHECK-COUNT-1: getelementptr
// CHECK: ret
#[no_mangle]
pub fn rc_slice_to_ref_slice_sized(s: &[Rc<u32>]) -> Box<[&u32]> {
s.iter().map(|x| &**x).collect()
}

// This test doesn’t work yet.
//
// COM: CHECK-LABEL: @rc_slice_to_ref_slice_unsized(
// COM: CHECK-NOT: getelementptr
// COM: CHECK: tail call void @llvm.memcpy
// COM: CHECK-NOT: getelementptr
// COM: CHECK: ret
// #[no_mangle]
// pub fn rc_slice_to_ref_slice_unsized(s: &[Rc<str>]) -> Box<[&str]> {
// s.iter().map(|x| &**x).collect()
// }

// CHECK-LABEL: @arc_slice_to_ref_slice_sized(
// CHECK-NOT: getelementptr
// CHECK: tail call void @llvm.memcpy
// CHECK-COUNT-1: getelementptr
// CHECK: ret
#[no_mangle]
pub fn arc_slice_to_ref_slice_sized(s: &[Arc<u32>]) -> Box<[&u32]> {
s.iter().map(|x| &**x).collect()
}

// This test doesn’t work yet.
//
// COM: CHECK-LABEL: @arc_slice_to_ref_slice_unsized(
// COM: CHECK-NOT: getelementptr
// COM: CHECK: tail call void @llvm.memcpy
// COM: CHECK-NOT: getelementptr
// COM: CHECK: ret
// #[no_mangle]
// pub fn arc_slice_to_ref_slice_unsized(s: &[Arc<str>]) -> Box<[&str]> {
// s.iter().map(|x| &**x).collect()
// }
2 changes: 1 addition & 1 deletion tests/debuginfo/strings-and-strs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
// gdb-check:$4 = ("Hello", "World")

// gdb-command:print str_in_rc
// gdb-check:$5 = alloc::rc::Rc<&str, alloc::alloc::Global> {ptr: core::ptr::non_null::NonNull<alloc::rc::RcInner<&str>> {pointer: 0x[...]}, phantom: core::marker::PhantomData<alloc::rc::RcInner<&str>>, alloc: alloc::alloc::Global}
// gdb-check:$5 = alloc::rc::Rc<&str, alloc::alloc::Global> {ptr: core::ptr::non_null::NonNull<&str> {pointer: 0x[...]}, phantom: core::marker::PhantomData<alloc::rc::RcInner<&str>>, alloc: alloc::alloc::Global}

// === LLDB TESTS ==================================================================================
// lldb-command:run
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/abi/compatibility.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ mod prelude {
value: T,
}
pub struct Rc<T: ?Sized, A = Global> {
ptr: NonNull<RcInner<T>>,
ptr: NonNull<T>,
phantom: PhantomData<RcInner<T>>,
alloc: A,
}
Expand All @@ -140,7 +140,7 @@ mod prelude {
data: T,
}
pub struct Arc<T: ?Sized, A = Global> {
ptr: NonNull<ArcInner<T>>,
ptr: NonNull<T>,
phantom: PhantomData<ArcInner<T>>,
alloc: A,
}
Expand Down

0 comments on commit d7879fa

Please sign in to comment.