Skip to content

Commit f243654

Browse files
committed
Store pointer to data directly in Rc and Arc
1 parent 6739555 commit f243654

10 files changed

+404
-293
lines changed

library/alloc/src/rc.rs

+148-144
Large diffs are not rendered by default.

library/alloc/src/sync.rs

+126-128
Large diffs are not rendered by default.

src/etc/gdb_providers.py

+11-1
Original file line numberDiff line numberDiff line change
@@ -180,12 +180,22 @@ def children(self):
180180
def display_hint():
181181
return "array"
182182

183+
BYTE_PTR_TYPE = gdb.lookup_type("u8").pointer()
183184

184185
class StdRcProvider(printer_base):
185186
def __init__(self, valobj, is_atomic=False):
187+
def inner_ptr():
188+
data_ptr = unwrap_unique_or_non_null(valobj["ptr"])
189+
formatter = "alloc::sync::ArcInner<{}>" if is_atomic else "alloc::rc::RcInner<{}>"
190+
inner_type = gdb.lookup_type(formatter.format(data_ptr.type.target().name))
191+
data_offset = inner_type.fields()[-1].bitpos // 8
192+
inner_ptr = data_ptr.reinterpret_cast(BYTE_PTR_TYPE) - data_offset
193+
194+
return inner_ptr.reinterpret_cast(inner_type.pointer())
195+
186196
self._valobj = valobj
187197
self._is_atomic = is_atomic
188-
self._ptr = unwrap_unique_or_non_null(valobj["ptr"])
198+
self._ptr = inner_ptr()
189199
self._value = self._ptr["data" if is_atomic else "value"]
190200
self._strong = self._ptr["strong"]["v" if is_atomic else "value"]["value"]
191201
self._weak = self._ptr["weak"]["v" if is_atomic else "value"]["value"] - 1

src/etc/lldb_batchmode.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def print_debug(s):
4040

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

4545

4646
def breakpoint_callback(frame, bp_loc, dict):
@@ -208,7 +208,7 @@ def watchdog():
208208

209209
for line in script_file:
210210
command = line.strip()
211-
if command == "run" or command == "r" or re.match("^process\s+launch.*", command):
211+
if command == "run" or command == "r" or re.match("^process\\s+launch.*", command):
212212
# Before starting to run the program, let the thread sleep a bit, so all
213213
# breakpoint added events can be processed
214214
time.sleep(0.5)

src/etc/lldb_lookup.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@ def summary_lookup(valobj, dict):
4444
return SizeSummaryProvider(valobj, dict)
4545

4646
if rust_type == RustType.STD_RC:
47-
return StdRcSummaryProvider(valobj, dict)
47+
return StdRcSummaryProvider(valobj, dict, False)
4848
if rust_type == RustType.STD_ARC:
49-
return StdRcSummaryProvider(valobj, dict)
49+
return StdRcSummaryProvider(valobj, dict, True)
5050

5151
if rust_type == RustType.STD_REF:
5252
return StdRefSummaryProvider(valobj, dict)

src/etc/lldb_providers.py

+22-9
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import lldb
12
import sys
23

34
from lldb import SBData, SBError, eBasicTypeLong, eBasicTypeUnsignedLong, \
@@ -660,7 +661,16 @@ def has_children(self):
660661
return True
661662

662663

663-
def StdRcSummaryProvider(valobj, dict):
664+
def get_rc_inner(valobj, is_atomic):
665+
data_ptr = unwrap_unique_or_non_null(valobj.GetChildMemberWithName("ptr"))
666+
inner_type = valobj.type.fields[1].type.template_args[0]
667+
data_offset = inner_type.fields[-1].byte_offset
668+
inner_address = data_ptr.GetValueAsAddress() - data_offset
669+
670+
return data_ptr.CreateValueFromAddress("inner", inner_address, inner_type)
671+
672+
673+
def StdRcSummaryProvider(valobj, dict, is_atomic):
664674
# type: (SBValue, dict) -> str
665675
strong = valobj.GetChildMemberWithName("strong").GetValueAsUnsigned()
666676
weak = valobj.GetChildMemberWithName("weak").GetValueAsUnsigned()
@@ -670,15 +680,15 @@ def StdRcSummaryProvider(valobj, dict):
670680
class StdRcSyntheticProvider:
671681
"""Pretty-printer for alloc::rc::Rc<T> and alloc::sync::Arc<T>
672682
673-
struct Rc<T> { ptr: NonNull<RcInner<T>>, ... }
683+
struct Rc<T> { ptr: NonNull<T>, ... }
674684
rust 1.31.1: struct NonNull<T> { pointer: NonZero<*const T> }
675685
rust 1.33.0: struct NonNull<T> { pointer: *const T }
676686
struct NonZero<T>(T)
677687
struct RcInner<T> { strong: Cell<usize>, weak: Cell<usize>, value: T }
678688
struct Cell<T> { value: UnsafeCell<T> }
679689
struct UnsafeCell<T> { value: T }
680690
681-
struct Arc<T> { ptr: NonNull<ArcInner<T>>, ... }
691+
struct Arc<T> { ptr: NonNull<T>, ... }
682692
struct ArcInner<T> { strong: atomic::AtomicUsize, weak: atomic::AtomicUsize, data: T }
683693
struct AtomicUsize { v: UnsafeCell<usize> }
684694
"""
@@ -687,14 +697,17 @@ def __init__(self, valobj, dict, is_atomic=False):
687697
# type: (SBValue, dict, bool) -> StdRcSyntheticProvider
688698
self.valobj = valobj
689699

690-
self.ptr = unwrap_unique_or_non_null(self.valobj.GetChildMemberWithName("ptr"))
700+
self.inner = get_rc_inner(valobj, is_atomic)
691701

692-
self.value = self.ptr.GetChildMemberWithName("data" if is_atomic else "value")
702+
self.value = self.inner.GetChildMemberWithName("data" if is_atomic else "value")
703+
704+
if is_atomic:
705+
read_cell = lambda x: x.GetChildAtIndex(0).GetChildAtIndex(0)
706+
else:
707+
read_cell = lambda x: x.GetChildAtIndex(0)
693708

694-
self.strong = self.ptr.GetChildMemberWithName("strong").GetChildAtIndex(
695-
0).GetChildMemberWithName("value")
696-
self.weak = self.ptr.GetChildMemberWithName("weak").GetChildAtIndex(
697-
0).GetChildMemberWithName("value")
709+
self.strong = read_cell(self.inner.GetChildMemberWithName("strong"))
710+
self.weak = read_cell(self.inner.GetChildMemberWithName("weak"))
698711

699712
self.value_builder = ValueBuilder(valobj)
700713

tests/codegen/placement-new.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,22 @@ pub fn box_default_inplace() -> Box<(String, String)> {
2222
#[no_mangle]
2323
pub fn rc_default_inplace() -> Rc<(String, String)> {
2424
// CHECK-NOT: alloca
25-
// CHECK: [[RC:%.*]] = {{.*}}call {{.*}}__rust_alloc(
25+
// CHECK: [[RC:%.*]] = {{.*}}call {{.*}}__rust_alloc(i[[#BITS:]]
2626
// CHECK-NOT: call void @llvm.memcpy
27-
// CHECK: ret ptr [[RC]]
27+
// CHECK: [[DATA:%.*]] = getelementptr inbounds i8, ptr [[RC]], i[[#BITS]] [[#div(BITS,4)]]
28+
// CHECK-NOT: call void @llvm.memcpy
29+
// CHECK: ret ptr [[DATA]]
2830
Rc::default()
2931
}
3032

3133
// CHECK-LABEL: @arc_default_inplace
3234
#[no_mangle]
3335
pub fn arc_default_inplace() -> Arc<(String, String)> {
3436
// CHECK-NOT: alloca
35-
// CHECK: [[ARC:%.*]] = {{.*}}call {{.*}}__rust_alloc(
37+
// CHECK: [[RC:%.*]] = {{.*}}call {{.*}}__rust_alloc(i[[#BITS:]]
38+
// CHECK-NOT: call void @llvm.memcpy
39+
// CHECK: [[DATA:%.*]] = getelementptr inbounds i8, ptr [[RC]], i[[#BITS]] [[#div(BITS,4)]]
3640
// CHECK-NOT: call void @llvm.memcpy
37-
// CHECK: ret ptr [[ARC]]
41+
// CHECK: ret ptr [[DATA]]
3842
Arc::default()
3943
}
+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
//@ compile-flags: -O -Z merge-functions=disabled
2+
3+
#![crate_type = "lib"]
4+
5+
use std::rc::Rc;
6+
use std::sync::Arc;
7+
8+
// CHECK-LABEL: @deref_rc_sized(
9+
// CHECK-NOT: getelementptr
10+
// CHECK: ret
11+
#[no_mangle]
12+
pub fn deref_rc_sized(rc: &Rc<u32>) -> &u32 {
13+
&rc
14+
}
15+
16+
// CHECK-LABEL: @deref_rc_unsized(
17+
// CHECK-COUNT-1: getelementptr
18+
// CHECK: ret
19+
#[no_mangle]
20+
pub fn deref_rc_unsized(rc: &Rc<str>) -> &str {
21+
&rc
22+
}
23+
24+
// CHECK-LABEL: @deref_arc_sized(
25+
// CHECK-NOT: getelementptr
26+
// CHECK: ret
27+
#[no_mangle]
28+
pub fn deref_arc_sized(arc: &Arc<u32>) -> &u32 {
29+
&arc
30+
}
31+
32+
// CHECK-LABEL: @deref_arc_unsized(
33+
// CHECK-COUNT-1: getelementptr
34+
// CHECK: ret
35+
#[no_mangle]
36+
pub fn deref_arc_unsized(arc: &Arc<str>) -> &str {
37+
&arc
38+
}
39+
40+
// CHECK-LABEL: @rc_slice_to_ref_slice_sized(
41+
// CHECK-NOT: getelementptr
42+
// CHECK: tail call void @llvm.memcpy
43+
// CHECK-COUNT-1: getelementptr
44+
// CHECK: ret
45+
#[no_mangle]
46+
pub fn rc_slice_to_ref_slice_sized(s: &[Rc<u32>]) -> Box<[&u32]> {
47+
s.iter().map(|x| &**x).collect()
48+
}
49+
50+
// This test doesn’t work yet.
51+
//
52+
// COM: CHECK-LABEL: @rc_slice_to_ref_slice_unsized(
53+
// COM: CHECK-NOT: getelementptr
54+
// COM: CHECK: tail call void @llvm.memcpy
55+
// COM: CHECK-NOT: getelementptr
56+
// COM: CHECK: ret
57+
// #[no_mangle]
58+
// pub fn rc_slice_to_ref_slice_unsized(s: &[Rc<str>]) -> Box<[&str]> {
59+
// s.iter().map(|x| &**x).collect()
60+
// }
61+
62+
// CHECK-LABEL: @arc_slice_to_ref_slice_sized(
63+
// CHECK-NOT: getelementptr
64+
// CHECK: tail call void @llvm.memcpy
65+
// CHECK-COUNT-1: getelementptr
66+
// CHECK: ret
67+
#[no_mangle]
68+
pub fn arc_slice_to_ref_slice_sized(s: &[Arc<u32>]) -> Box<[&u32]> {
69+
s.iter().map(|x| &**x).collect()
70+
}
71+
72+
// This test doesn’t work yet.
73+
//
74+
// COM: CHECK-LABEL: @arc_slice_to_ref_slice_unsized(
75+
// COM: CHECK-NOT: getelementptr
76+
// COM: CHECK: tail call void @llvm.memcpy
77+
// COM: CHECK-NOT: getelementptr
78+
// COM: CHECK: ret
79+
// #[no_mangle]
80+
// pub fn arc_slice_to_ref_slice_unsized(s: &[Arc<str>]) -> Box<[&str]> {
81+
// s.iter().map(|x| &**x).collect()
82+
// }

tests/debuginfo/strings-and-strs.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
// gdb-check:$4 = ("Hello", "World")
2020

2121
// gdb-command:print str_in_rc
22-
// 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}
22+
// 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}
2323

2424
// === LLDB TESTS ==================================================================================
2525
// lldb-command:run

tests/ui/abi/compatibility.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ mod prelude {
126126
value: T,
127127
}
128128
pub struct Rc<T: ?Sized, A = Global> {
129-
ptr: NonNull<RcInner<T>>,
129+
ptr: NonNull<T>,
130130
phantom: PhantomData<RcInner<T>>,
131131
alloc: A,
132132
}
@@ -140,7 +140,7 @@ mod prelude {
140140
data: T,
141141
}
142142
pub struct Arc<T: ?Sized, A = Global> {
143-
ptr: NonNull<ArcInner<T>>,
143+
ptr: NonNull<T>,
144144
phantom: PhantomData<ArcInner<T>>,
145145
alloc: A,
146146
}

0 commit comments

Comments
 (0)