Skip to content

Revise VecPerParamSpace to use a one Vec rather than three #15418

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 5, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/librustc/metadata/tyencode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ fn enc_vec_per_param_space<T>(w: &mut MemWriter,
op: |&mut MemWriter, &ctxt, &T|) {
for &space in subst::ParamSpace::all().iter() {
mywrite!(w, "[");
for t in v.get_vec(space).iter() {
for t in v.get_slice(space).iter() {
op(w, cx, t);
}
mywrite!(w, "]");
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/astencode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -810,7 +810,7 @@ fn encode_vec_per_param_space<T>(ebml_w: &mut Encoder,
v: &subst::VecPerParamSpace<T>,
f: |&mut Encoder, &T|) {
for &space in subst::ParamSpace::all().iter() {
ebml_w.emit_from_vec(v.get_vec(space).as_slice(),
ebml_w.emit_from_vec(v.get_slice(space),
|ebml_w, n| Ok(f(ebml_w, n))).unwrap();
}
}
Expand Down
169 changes: 135 additions & 34 deletions src/librustc/middle/subst.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ use middle::ty_fold;
use middle::ty_fold::{TypeFoldable, TypeFolder};
use util::ppaux::Repr;

use std::iter::Chain;
use std::mem;
use std::raw;
use std::slice::{Items, MutItems};
Expand Down Expand Up @@ -191,8 +190,8 @@ impl Substs {
}

pub fn with_method_from(self, substs: &Substs) -> Substs {
self.with_method((*substs.types.get_vec(FnSpace)).clone(),
(*substs.regions().get_vec(FnSpace)).clone())
self.with_method(Vec::from_slice(substs.types.get_slice(FnSpace)),
Vec::from_slice(substs.regions().get_slice(FnSpace)))
}

pub fn with_method(self,
Expand Down Expand Up @@ -261,13 +260,44 @@ impl ParamSpace {
*/
#[deriving(PartialEq, Eq, Clone, Hash, Encodable, Decodable)]
pub struct VecPerParamSpace<T> {
vecs: (Vec<T>, Vec<T>, Vec<T>)
// This was originally represented as a tuple with one Vec<T> for
// each variant of ParamSpace, and that remains the abstraction
// that it provides to its clients.
//
// Here is how the representation corresponds to the abstraction
// i.e. the "abstraction function" AF:
//
// AF(self) = (self.content.slice_to(self.type_limit),
// self.content.slice(self.type_limit, self.self_limit),
// self.content.slice_from(self.self_limit))
type_limit: uint,
self_limit: uint,
content: Vec<T>,
}

impl<T:Clone> VecPerParamSpace<T> {
pub fn push_all(&mut self, space: ParamSpace, values: &[T]) {
// FIXME (#15435): slow; O(n^2); could enhance vec to make it O(n).
for t in values.iter() {
self.push(space, t.clone());
}
}
}

impl<T> VecPerParamSpace<T> {
fn limits(&self, space: ParamSpace) -> (uint, uint) {
match space {
TypeSpace => (0, self.type_limit),
SelfSpace => (self.type_limit, self.self_limit),
FnSpace => (self.self_limit, self.content.len()),
}
}

pub fn empty() -> VecPerParamSpace<T> {
VecPerParamSpace {
vecs: (Vec::new(), Vec::new(), Vec::new())
type_limit: 0,
self_limit: 0,
content: Vec::new()
}
}

Expand All @@ -276,8 +306,15 @@ impl<T> VecPerParamSpace<T> {
}

pub fn new(t: Vec<T>, s: Vec<T>, f: Vec<T>) -> VecPerParamSpace<T> {
let type_limit = t.len();
let self_limit = t.len() + s.len();
let mut content = t;
content.push_all_move(s);
content.push_all_move(f);
VecPerParamSpace {
vecs: (t, s, f)
type_limit: type_limit,
self_limit: self_limit,
content: content,
}
}

Expand All @@ -289,55 +326,98 @@ impl<T> VecPerParamSpace<T> {
result
}

/// Appends `value` to the vector associated with `space`.
///
/// Unlike the `push` method in `Vec`, this should not be assumed
/// to be a cheap operation (even when amortized over many calls).
pub fn push(&mut self, space: ParamSpace, value: T) {
self.get_mut_vec(space).push(value);
let (_, limit) = self.limits(space);
match space {
TypeSpace => { self.type_limit += 1; self.self_limit += 1; }
SelfSpace => { self.self_limit += 1; }
FnSpace => {}
}
self.content.insert(limit, value);
}

pub fn pop(&mut self, space: ParamSpace) -> Option<T> {
let (start, limit) = self.limits(space);
if start == limit {
None
} else {
match space {
TypeSpace => { self.type_limit -= 1; self.self_limit -= 1; }
SelfSpace => { self.self_limit -= 1; }
FnSpace => {}
}
self.content.remove(limit - 1)
}
}

pub fn truncate(&mut self, space: ParamSpace, len: uint) {
// FIXME (#15435): slow; O(n^2); could enhance vec to make it O(n).
while self.len(space) > len {
self.pop(space);
}
}

pub fn replace(&mut self, space: ParamSpace, elems: Vec<T>) {
// FIXME (#15435): slow; O(n^2); could enhance vec to make it O(n).
self.truncate(space, 0);
for t in elems.move_iter() {
self.push(space, t);
}
}

pub fn get_self<'a>(&'a self) -> Option<&'a T> {
let v = self.get_vec(SelfSpace);
let v = self.get_slice(SelfSpace);
assert!(v.len() <= 1);
if v.len() == 0 { None } else { Some(v.get(0)) }
if v.len() == 0 { None } else { Some(&v[0]) }
}

pub fn len(&self, space: ParamSpace) -> uint {
self.get_vec(space).len()
self.get_slice(space).len()
}

pub fn is_empty_in(&self, space: ParamSpace) -> bool {
self.len(space) == 0
}

pub fn get_vec<'a>(&'a self, space: ParamSpace) -> &'a Vec<T> {
self.vecs.get(space as uint).unwrap()
pub fn get_slice<'a>(&'a self, space: ParamSpace) -> &'a [T] {
let (start, limit) = self.limits(space);
self.content.slice(start, limit)
}

pub fn get_mut_vec<'a>(&'a mut self, space: ParamSpace) -> &'a mut Vec<T> {
self.vecs.get_mut(space as uint).unwrap()
fn get_mut_slice<'a>(&'a mut self, space: ParamSpace) -> &'a mut [T] {
let (start, limit) = self.limits(space);
self.content.mut_slice(start, limit)
}

pub fn opt_get<'a>(&'a self,
space: ParamSpace,
index: uint)
-> Option<&'a T> {
let v = self.get_vec(space);
if index < v.len() { Some(v.get(index)) } else { None }
let v = self.get_slice(space);
if index < v.len() { Some(&v[index]) } else { None }
}

pub fn get<'a>(&'a self, space: ParamSpace, index: uint) -> &'a T {
self.get_vec(space).get(index)
&self.get_slice(space)[index]
}

pub fn get_mut<'a>(&'a mut self,
space: ParamSpace,
index: uint) -> &'a mut T {
self.get_mut_vec(space).get_mut(index)
&mut self.get_mut_slice(space)[index]
}

pub fn iter<'a>(&'a self) -> Chain<Items<'a,T>,
Chain<Items<'a,T>,
Items<'a,T>>> {
let (ref r, ref s, ref f) = self.vecs;
r.iter().chain(s.iter().chain(f.iter()))
pub fn iter<'a>(&'a self) -> Items<'a,T> {
self.content.iter()
}

pub fn all_vecs(&self, pred: |&Vec<T>| -> bool) -> bool {
self.vecs.iter().all(pred)
pub fn all_vecs(&self, pred: |&[T]| -> bool) -> bool {
let spaces = [TypeSpace, SelfSpace, FnSpace];
spaces.iter().all(|&space| { pred(self.get_slice(space)) })
}

pub fn all(&self, pred: |&T| -> bool) -> bool {
Expand All @@ -353,9 +433,13 @@ impl<T> VecPerParamSpace<T> {
}

pub fn map<U>(&self, pred: |&T| -> U) -> VecPerParamSpace<U> {
VecPerParamSpace::new(self.vecs.ref0().iter().map(|p| pred(p)).collect(),
self.vecs.ref1().iter().map(|p| pred(p)).collect(),
self.vecs.ref2().iter().map(|p| pred(p)).collect())
// FIXME (#15418): this could avoid allocating the intermediate
// Vec's, but note that the values of type_limit and self_limit
// also need to be kept in sync during construction.
VecPerParamSpace::new(
self.get_slice(TypeSpace).iter().map(|p| pred(p)).collect(),
self.get_slice(SelfSpace).iter().map(|p| pred(p)).collect(),
self.get_slice(FnSpace).iter().map(|p| pred(p)).collect())
}

pub fn map_rev<U>(&self, pred: |&T| -> U) -> VecPerParamSpace<U> {
Expand All @@ -368,29 +452,46 @@ impl<T> VecPerParamSpace<T> {
* can be run to a fixed point
*/

let mut fns: Vec<U> = self.vecs.ref2().iter().rev().map(|p| pred(p)).collect();
let mut fns: Vec<U> = self.get_slice(FnSpace).iter().rev().map(|p| pred(p)).collect();

// NB: Calling foo.rev().map().rev() causes the calls to map
// to occur in the wrong order. This was somewhat surprising
// to me, though it makes total sense.
fns.reverse();

let mut selfs: Vec<U> = self.vecs.ref1().iter().rev().map(|p| pred(p)).collect();
let mut selfs: Vec<U> = self.get_slice(SelfSpace).iter().rev().map(|p| pred(p)).collect();
selfs.reverse();
let mut tys: Vec<U> = self.vecs.ref0().iter().rev().map(|p| pred(p)).collect();
let mut tys: Vec<U> = self.get_slice(TypeSpace).iter().rev().map(|p| pred(p)).collect();
tys.reverse();
VecPerParamSpace::new(tys, selfs, fns)
}

pub fn split(self) -> (Vec<T>, Vec<T>, Vec<T>) {
self.vecs
// FIXME (#15418): this does two traversals when in principle
// one would suffice. i.e. change to use `move_iter`.
let VecPerParamSpace { type_limit, self_limit, content } = self;
let mut i = 0;
let (prefix, fn_vec) = content.partition(|_| {
let on_left = i < self_limit;
i += 1;
on_left
});

let mut i = 0;
let (type_vec, self_vec) = prefix.partition(|_| {
let on_left = i < type_limit;
i += 1;
on_left
});

(type_vec, self_vec, fn_vec)
}

pub fn with_vec(mut self, space: ParamSpace, vec: Vec<T>)
-> VecPerParamSpace<T>
{
assert!(self.get_vec(space).is_empty());
*self.get_mut_vec(space) = vec;
assert!(self.is_empty_in(space));
self.replace(space, vec);
self
}
}
Expand Down
6 changes: 2 additions & 4 deletions src/librustc/middle/trans/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,10 +216,8 @@ fn resolve_default_method_vtables(bcx: &Block,
bcx.tcx(), &param_substs, &impl_res);

// Now we pull any vtables for parameters on the actual method.
param_vtables
.get_mut_vec(subst::FnSpace)
.push_all(
impl_vtables.get_vec(subst::FnSpace).as_slice());
param_vtables.push_all(subst::FnSpace,
impl_vtables.get_slice(subst::FnSpace));

param_vtables
}
Expand Down
6 changes: 3 additions & 3 deletions src/librustc/middle/trans/debuginfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -554,7 +554,7 @@ impl TypeMap {

// Maybe check that there is no self type here.

let tps = substs.types.get_vec(subst::TypeSpace);
let tps = substs.types.get_slice(subst::TypeSpace);
if tps.len() > 0 {
output.push_char('<');

Expand Down Expand Up @@ -1377,9 +1377,9 @@ pub fn create_function_debug_context(cx: &CrateContext,
}

// Handle other generic parameters
let actual_types = param_substs.substs.types.get_vec(subst::FnSpace);
let actual_types = param_substs.substs.types.get_slice(subst::FnSpace);
for (index, &ast::TyParam{ ident: ident, .. }) in generics.ty_params.iter().enumerate() {
let actual_type = *actual_types.get(index);
let actual_type = actual_types[index];
// Add actual type name to <...> clause of function name
let actual_type_name = compute_debuginfo_type_name(cx,
actual_type,
Expand Down
6 changes: 3 additions & 3 deletions src/librustc/middle/trans/type_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
// avoids creating more than one copy of the enum when one
// of the enum's variants refers to the enum itself.
let repr = adt::represent_type(cx, t);
let tps = substs.types.get_vec(subst::TypeSpace);
let tps = substs.types.get_slice(subst::TypeSpace);
let name = llvm_type_name(cx, an_enum, did, tps);
adt::incomplete_type_of(cx, &*repr, name.as_slice())
}
Expand Down Expand Up @@ -266,7 +266,7 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
// in *after* placing it into the type cache. This prevents
// infinite recursion with recursive struct types.
let repr = adt::represent_type(cx, t);
let tps = substs.types.get_vec(subst::TypeSpace);
let tps = substs.types.get_slice(subst::TypeSpace);
let name = llvm_type_name(cx, a_struct, did, tps);
adt::incomplete_type_of(cx, &*repr, name.as_slice())
}
Expand Down Expand Up @@ -305,7 +305,7 @@ pub enum named_ty { a_struct, an_enum }
pub fn llvm_type_name(cx: &CrateContext,
what: named_ty,
did: ast::DefId,
tps: &Vec<ty::t>)
tps: &[ty::t])
-> String
{
let name = match what {
Expand Down
Loading