rustc: middle: ty: replace unsafe pointers with references in Ty.
This commit is contained in:
parent
9706d8f602
commit
92ae0c6c25
1 changed files with 56 additions and 73 deletions
|
@ -61,6 +61,7 @@ use util::ppaux::{Repr, UserString};
|
||||||
use util::common::{indenter, memoized};
|
use util::common::{indenter, memoized};
|
||||||
use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet};
|
use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet};
|
||||||
use util::nodemap::{FnvHashMap, FnvHashSet};
|
use util::nodemap::{FnvHashMap, FnvHashSet};
|
||||||
|
use std::borrow::BorrowFrom;
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::fmt::{mod, Show};
|
use std::fmt::{mod, Show};
|
||||||
|
@ -252,32 +253,6 @@ pub struct creader_cache_key {
|
||||||
pub len: uint
|
pub len: uint
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct intern_key {
|
|
||||||
sty: *const sty,
|
|
||||||
}
|
|
||||||
|
|
||||||
// NB: Do not replace this with #[deriving(PartialEq)]. The automatically-derived
|
|
||||||
// implementation will not recurse through sty and you will get stack
|
|
||||||
// exhaustion.
|
|
||||||
impl cmp::PartialEq for intern_key {
|
|
||||||
fn eq(&self, other: &intern_key) -> bool {
|
|
||||||
unsafe {
|
|
||||||
*self.sty == *other.sty
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn ne(&self, other: &intern_key) -> bool {
|
|
||||||
!self.eq(other)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Eq for intern_key {}
|
|
||||||
|
|
||||||
impl<W:Writer> Hash<W> for intern_key {
|
|
||||||
fn hash(&self, s: &mut W) {
|
|
||||||
unsafe { (*self.sty).hash(s) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum ast_ty_to_ty_cache_entry {
|
pub enum ast_ty_to_ty_cache_entry {
|
||||||
atttce_unresolved, /* not resolved yet */
|
atttce_unresolved, /* not resolved yet */
|
||||||
atttce_resolved(Ty) /* resolved to a type, irrespective of region */
|
atttce_resolved(Ty) /* resolved to a type, irrespective of region */
|
||||||
|
@ -456,11 +431,13 @@ pub struct TransmuteRestriction {
|
||||||
/// later on.
|
/// later on.
|
||||||
pub struct ctxt<'tcx> {
|
pub struct ctxt<'tcx> {
|
||||||
/// The arena that types are allocated from.
|
/// The arena that types are allocated from.
|
||||||
type_arena: &'tcx TypedArena<t_box_>,
|
type_arena: &'tcx TypedArena<TyS>,
|
||||||
|
|
||||||
/// Specifically use a speedy hash algorithm for this hash map, it's used
|
/// Specifically use a speedy hash algorithm for this hash map, it's used
|
||||||
/// quite often.
|
/// quite often.
|
||||||
interner: RefCell<FnvHashMap<intern_key, &'tcx t_box_>>,
|
// TODO(eddyb) use a FnvHashSet<InternedTy<'tcx>> when equivalent keys can
|
||||||
|
// queried from a HashSet.
|
||||||
|
interner: RefCell<FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>>,
|
||||||
pub sess: Session,
|
pub sess: Session,
|
||||||
pub def_map: resolve::DefMap,
|
pub def_map: resolve::DefMap,
|
||||||
|
|
||||||
|
@ -621,10 +598,8 @@ bitflags! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type t_box = &'static t_box_;
|
|
||||||
|
|
||||||
#[deriving(Show)]
|
#[deriving(Show)]
|
||||||
pub struct t_box_ {
|
pub struct TyS {
|
||||||
pub sty: sty,
|
pub sty: sty,
|
||||||
pub flags: TypeFlags,
|
pub flags: TypeFlags,
|
||||||
|
|
||||||
|
@ -638,32 +613,52 @@ impl fmt::Show for TypeFlags {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// To reduce refcounting cost, we're representing types as unsafe pointers
|
impl PartialEq for TyS {
|
||||||
// throughout the compiler. These are simply casted t_box values. Use ty::get
|
fn eq(&self, other: &TyS) -> bool {
|
||||||
// to cast them back to a box. (Without the cast, compiler performance suffers
|
(self as *const _) == (other as *const _)
|
||||||
// ~15%.) This does mean that a Ty value relies on the ctxt to keep its box
|
}
|
||||||
// alive, and using ty::get is unsafe when the ctxt is no longer alive.
|
}
|
||||||
enum t_opaque {}
|
impl Eq for TyS {}
|
||||||
|
|
||||||
#[allow(raw_pointer_deriving)]
|
impl<S: Writer> Hash<S> for TyS {
|
||||||
#[deriving(Clone, PartialEq, Eq, Hash)]
|
fn hash(&self, s: &mut S) {
|
||||||
pub struct Ty { inner: *const t_opaque }
|
(self as *const _).hash(s)
|
||||||
|
|
||||||
impl fmt::Show for Ty {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
write!(f, "{}", get(*self))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(ty: Ty) -> t_box {
|
pub type Ty<'tcx> = &'tcx TyS;
|
||||||
unsafe {
|
|
||||||
let t2: t_box = mem::transmute(ty);
|
/// An entry in the type interner.
|
||||||
t2
|
struct InternedTy<'tcx> {
|
||||||
|
ty: Ty<'tcx>
|
||||||
|
}
|
||||||
|
|
||||||
|
// NB: An InternedTy compares and hashes as a sty.
|
||||||
|
impl<'tcx> PartialEq for InternedTy<'tcx> {
|
||||||
|
fn eq(&self, other: &InternedTy<'tcx>) -> bool {
|
||||||
|
self.ty.sty == other.ty.sty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'tcx> Eq for InternedTy<'tcx> {}
|
||||||
|
|
||||||
|
impl<'tcx, S: Writer> Hash<S> for InternedTy<'tcx> {
|
||||||
|
fn hash(&self, s: &mut S) {
|
||||||
|
self.ty.sty.hash(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tbox_has_flag(tb: t_box, flag: TypeFlags) -> bool {
|
impl<'tcx> BorrowFrom<InternedTy<'tcx>> for sty<'tcx> {
|
||||||
tb.flags.intersects(flag)
|
fn borrow_from<'a>(ty: &'a InternedTy<'tcx>) -> &'a sty<'tcx> {
|
||||||
|
&ty.ty.sty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(ty: Ty) -> Ty {
|
||||||
|
ty
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tbox_has_flag(ty: Ty, flag: TypeFlags) -> bool {
|
||||||
|
ty.flags.intersects(flag)
|
||||||
}
|
}
|
||||||
pub fn type_has_params(ty: Ty) -> bool {
|
pub fn type_has_params(ty: Ty) -> bool {
|
||||||
tbox_has_flag(get(ty), HAS_PARAMS)
|
tbox_has_flag(get(ty), HAS_PARAMS)
|
||||||
|
@ -1024,13 +1019,13 @@ pub enum BoundRegion {
|
||||||
}
|
}
|
||||||
|
|
||||||
mod primitives {
|
mod primitives {
|
||||||
use super::t_box_;
|
use super::TyS;
|
||||||
|
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
|
|
||||||
macro_rules! def_prim_ty(
|
macro_rules! def_prim_ty(
|
||||||
($name:ident, $sty:expr) => (
|
($name:ident, $sty:expr) => (
|
||||||
pub static $name: t_box_ = t_box_ {
|
pub static $name: TyS = TyS {
|
||||||
sty: $sty,
|
sty: $sty,
|
||||||
flags: super::NO_TYPE_FLAGS,
|
flags: super::NO_TYPE_FLAGS,
|
||||||
region_depth: 0,
|
region_depth: 0,
|
||||||
|
@ -1053,7 +1048,7 @@ mod primitives {
|
||||||
def_prim_ty!(TY_F32, super::ty_float(ast::TyF32))
|
def_prim_ty!(TY_F32, super::ty_float(ast::TyF32))
|
||||||
def_prim_ty!(TY_F64, super::ty_float(ast::TyF64))
|
def_prim_ty!(TY_F64, super::ty_float(ast::TyF64))
|
||||||
|
|
||||||
pub static TY_ERR: t_box_ = t_box_ {
|
pub static TY_ERR: TyS = TyS {
|
||||||
sty: super::ty_err,
|
sty: super::ty_err,
|
||||||
flags: super::HAS_TY_ERR,
|
flags: super::HAS_TY_ERR,
|
||||||
region_depth: 0,
|
region_depth: 0,
|
||||||
|
@ -1701,7 +1696,7 @@ impl UnboxedClosureKind {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mk_ctxt<'tcx>(s: Session,
|
pub fn mk_ctxt<'tcx>(s: Session,
|
||||||
type_arena: &'tcx TypedArena<t_box_>,
|
type_arena: &'tcx TypedArena<TyS>,
|
||||||
dm: resolve::DefMap,
|
dm: resolve::DefMap,
|
||||||
named_region_map: resolve_lifetime::NamedRegionMap,
|
named_region_map: resolve_lifetime::NamedRegionMap,
|
||||||
map: ast_map::Map<'tcx>,
|
map: ast_map::Map<'tcx>,
|
||||||
|
@ -1785,32 +1780,22 @@ pub fn mk_t(cx: &ctxt, st: sty) -> Ty {
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
|
|
||||||
let key = intern_key { sty: &st };
|
match cx.interner.borrow().get(&st) {
|
||||||
|
Some(ty) => return ty,
|
||||||
match cx.interner.borrow().get(&key) {
|
|
||||||
Some(ty) => unsafe { return mem::transmute(&ty.sty); },
|
|
||||||
_ => ()
|
_ => ()
|
||||||
}
|
}
|
||||||
|
|
||||||
let flags = FlagComputation::for_sty(&st);
|
let flags = FlagComputation::for_sty(&st);
|
||||||
|
|
||||||
let ty = cx.type_arena.alloc(t_box_ {
|
let ty = cx.type_arena.alloc(TyS {
|
||||||
sty: st,
|
sty: st,
|
||||||
flags: flags.flags,
|
flags: flags.flags,
|
||||||
region_depth: flags.depth,
|
region_depth: flags.depth,
|
||||||
});
|
});
|
||||||
|
|
||||||
let sty_ptr = &ty.sty as *const sty;
|
cx.interner.borrow_mut().insert(InternedTy { ty: ty }, ty);
|
||||||
|
|
||||||
let key = intern_key {
|
Ty { inner: ty }
|
||||||
sty: sty_ptr,
|
|
||||||
};
|
|
||||||
|
|
||||||
cx.interner.borrow_mut().insert(key, ty);
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
mem::transmute::<*const sty, Ty>(sty_ptr)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FlagComputation {
|
struct FlagComputation {
|
||||||
|
@ -1996,10 +1981,8 @@ impl FlagComputation {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn mk_prim_t(primitive: &'static t_box_) -> Ty {
|
pub fn mk_prim_t(primitive: &'static TyS) -> Ty {
|
||||||
unsafe {
|
Ty { inner: primitive }
|
||||||
mem::transmute::<&'static t_box_, Ty>(primitive)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue