Skip to content

Commit a05d12b

Browse files
committed
syntax: try ref-counting the AST.
1 parent f47ec2a commit a05d12b

File tree

2 files changed

+46
-27
lines changed

2 files changed

+46
-27
lines changed

src/libsyntax/attr/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -735,7 +735,7 @@ impl HasAttrs for ThinVec<Attribute> {
735735
}
736736
}
737737

738-
impl<T: HasAttrs + 'static> HasAttrs for P<T> {
738+
impl<T: Clone + HasAttrs + 'static> HasAttrs for P<T> {
739739
fn attrs(&self) -> &[Attribute] {
740740
(**self).attrs()
741741
}

src/libsyntax/ptr.rs

+45-26
Original file line numberDiff line numberDiff line change
@@ -33,40 +33,42 @@ use std::{mem, ptr, slice, vec};
3333

3434
use serialize::{Encodable, Decodable, Encoder, Decoder};
3535

36+
use rustc_data_structures::sync::Lrc;
3637
use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
3738
HashStable};
3839
/// An owned smart pointer.
3940
#[derive(Hash, PartialEq, Eq)]
4041
pub struct P<T: ?Sized> {
41-
ptr: Box<T>
42+
ptr: Lrc<T>
4243
}
4344

4445
#[allow(non_snake_case)]
4546
/// Construct a `P<T>` from a `T` value.
4647
pub fn P<T: 'static>(value: T) -> P<T> {
4748
P {
48-
ptr: Box::new(value)
49+
ptr: Lrc::new(value)
4950
}
5051
}
5152

52-
impl<T: 'static> P<T> {
53+
impl<T: 'static + Clone> P<T> {
5354
/// Move out of the pointer.
5455
/// Intended for chaining transformations not covered by `map`.
5556
pub fn and_then<U, F>(self, f: F) -> U where
5657
F: FnOnce(T) -> U,
5758
{
58-
f(*self.ptr)
59+
f(self.into_inner())
5960
}
6061
/// Equivalent to and_then(|x| x)
6162
pub fn into_inner(self) -> T {
62-
*self.ptr
63+
Lrc::try_unwrap(self.ptr).unwrap_or_else(|ptr| (*ptr).clone())
6364
}
6465

6566
/// Produce a new `P<T>` from `self` without reallocating.
6667
pub fn map<F>(mut self, f: F) -> P<T> where
6768
F: FnOnce(T) -> T,
6869
{
69-
let p: *mut T = &mut *self.ptr;
70+
// FIXME(eddyb) How can we reuse the original if unchanged?
71+
let p: *mut T = Lrc::make_mut(&mut self.ptr);
7072

7173
// Leak self in case of panic.
7274
// FIXME(eddyb) Use some sort of "free guard" that
@@ -78,15 +80,16 @@ impl<T: 'static> P<T> {
7880
ptr::write(p, f(ptr::read(p)));
7981

8082
// Recreate self from the raw pointer.
81-
P { ptr: Box::from_raw(p) }
83+
P { ptr: Lrc::from_raw(p) }
8284
}
8385
}
8486

8587
/// Optionally produce a new `P<T>` from `self` without reallocating.
8688
pub fn filter_map<F>(mut self, f: F) -> Option<P<T>> where
8789
F: FnOnce(T) -> Option<T>,
8890
{
89-
let p: *mut T = &mut *self.ptr;
91+
// FIXME(eddyb) How can we reuse the original if unchanged?
92+
let p: *mut T = Lrc::make_mut(&mut self.ptr);
9093

9194
// Leak self in case of panic.
9295
// FIXME(eddyb) Use some sort of "free guard" that
@@ -99,9 +102,9 @@ impl<T: 'static> P<T> {
99102
ptr::write(p, v);
100103

101104
// Recreate self from the raw pointer.
102-
Some(P { ptr: Box::from_raw(p) })
105+
Some(P { ptr: Lrc::from_raw(p) })
103106
} else {
104-
drop(Box::from_raw(p));
107+
drop(Lrc::from_raw(p));
105108
None
106109
}
107110
}
@@ -116,15 +119,17 @@ impl<T: ?Sized> Deref for P<T> {
116119
}
117120
}
118121

119-
impl<T: ?Sized> DerefMut for P<T> {
122+
impl<T: Clone> DerefMut for P<T> {
120123
fn deref_mut(&mut self) -> &mut T {
121-
&mut self.ptr
124+
Lrc::make_mut(&mut self.ptr)
122125
}
123126
}
124127

125-
impl<T: 'static + Clone> Clone for P<T> {
128+
impl<T: ?Sized> Clone for P<T> {
126129
fn clone(&self) -> P<T> {
127-
P((**self).clone())
130+
P {
131+
ptr: self.ptr.clone(),
132+
}
128133
}
129134
}
130135

@@ -160,17 +165,21 @@ impl<T: Encodable> Encodable for P<T> {
160165

161166
impl<T> P<[T]> {
162167
pub fn new() -> P<[T]> {
163-
P { ptr: Default::default() }
168+
P { ptr: Lrc::new([]) }
164169
}
165170

171+
// FIXME(eddyb) this is inefficient because it needs to
172+
// move all the elements to accomodate `Lrc`'s allocation.
166173
#[inline(never)]
167174
pub fn from_vec(v: Vec<T>) -> P<[T]> {
168-
P { ptr: v.into_boxed_slice() }
175+
P { ptr: v.into() }
169176
}
170177

178+
// FIXME(eddyb) this is inefficient because it needs to
179+
// clone all the elements out of the `Lrc<[T]>`.
171180
#[inline(never)]
172-
pub fn into_vec(self) -> Vec<T> {
173-
self.ptr.into_vec()
181+
pub fn into_vec(self) -> Vec<T> where T: Clone {
182+
self.ptr.to_vec()
174183
}
175184
}
176185

@@ -181,31 +190,41 @@ impl<T> Default for P<[T]> {
181190
}
182191
}
183192

184-
impl<T: Clone> Clone for P<[T]> {
185-
fn clone(&self) -> P<[T]> {
186-
P::from_vec(self.to_vec())
187-
}
188-
}
189-
190193
impl<T> From<Vec<T>> for P<[T]> {
191194
fn from(v: Vec<T>) -> Self {
192195
P::from_vec(v)
193196
}
194197
}
195198

196-
impl<T> Into<Vec<T>> for P<[T]> {
199+
// FIXME(eddyb) this is inefficient because it needs to
200+
// clone all the elements out of the `Lrc<[T]>`.
201+
impl<T: Clone> Into<Vec<T>> for P<[T]> {
197202
fn into(self) -> Vec<T> {
198203
self.into_vec()
199204
}
200205
}
201206

207+
// FIXME(eddyb) this is inefficient because it needs to
208+
// clone all the elements out of the `Lrc<[T]>`.
209+
impl<T: Clone> DerefMut for P<[T]> {
210+
fn deref_mut(&mut self) -> &mut [T] {
211+
// HACK(eddyb) this emulates `make_mut` for `Lrc<[T]>`.
212+
if Lrc::get_mut(&mut self.ptr).is_none() {
213+
self.ptr = self.ptr.to_vec().into();
214+
}
215+
Lrc::get_mut(&mut self.ptr).unwrap()
216+
}
217+
}
218+
202219
impl<T> FromIterator<T> for P<[T]> {
203220
fn from_iter<I: IntoIterator<Item=T>>(iter: I) -> P<[T]> {
204221
P::from_vec(iter.into_iter().collect())
205222
}
206223
}
207224

208-
impl<T> IntoIterator for P<[T]> {
225+
// FIXME(eddyb) this is inefficient because it needs to
226+
// clone all the elements out of the `Lrc<[T]>`.
227+
impl<T: Clone> IntoIterator for P<[T]> {
209228
type Item = T;
210229
type IntoIter = vec::IntoIter<T>;
211230

0 commit comments

Comments
 (0)