Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
c2e8f3b4
R
Rust
项目概览
int
/
Rust
12 个月 前同步成功
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
Rust
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
c2e8f3b4
编写于
10月 12, 2014
作者:
J
Jakub Wieczorek
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add a memoize! macro and use it throughout rustc
上级
5201bf17
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
125 addition
and
113 deletion
+125
-113
src/librustc/lib.rs
src/librustc/lib.rs
+1
-0
src/librustc/middle/macros.rs
src/librustc/middle/macros.rs
+71
-0
src/librustc/middle/ty.rs
src/librustc/middle/ty.rs
+53
-113
未找到文件。
src/librustc/lib.rs
浏览文件 @
c2e8f3b4
...
...
@@ -97,6 +97,7 @@ pub mod middle {
pub
mod
intrinsicck
;
pub
mod
lang_items
;
pub
mod
liveness
;
pub
mod
macros
;
pub
mod
mem_categorization
;
pub
mod
pat_util
;
pub
mod
privacy
;
...
...
src/librustc/middle/macros.rs
0 → 100644
浏览文件 @
c2e8f3b4
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![macro_escape]
macro_rules!
memoize_expand_block
(
(
$cache_map:expr
,
$cache_key:expr
,
$
(
$param_name:ident
:
$param_ty:ty
),
*
)
=>
{
{
match
(
$cache_map
)
.borrow
()
.find
(
&
$cache_key
)
{
Some
(
ref
result
)
=>
return
(
*
result
)
.clone
(),
None
=>
{}
}
let
result
=
inner
(
$
(
$param_name
),
*
);
(
$cache_map
)
.borrow_mut
()
.insert
(
$cache_key
,
result
.clone
());
result
}
}
)
/// Memoizes a function using a cache that is available by evaluating the
/// `$cache_map` exression in the context of the function's arguments.
/// `$cache_key` is the expression that will be used to compute the cache key
/// for each function invocation.
///
/// The macro assumes the cache to be a RefCell containing a HashMap,
/// which is in practice how most caching in rustc is currently carried out.
///
/// # Example
///
/// ```
/// struct Context {
/// fibonacci_cache: RefCell<HashMap<uint, uint>>
/// }
///
/// memoize!(context.fibonacci_cache, n,
/// fn fibonacci(context: &Context, n: uint) -> uint {
/// match n {
/// 0 | 1 => n,
/// _ => fibonacci(n - 2) + fibonacci(n - 1)
/// }
/// }
/// )
/// ```
macro_rules!
memoize
(
(
$cache_map:expr
,
$cache_key:expr
,
fn
$name:ident
(
$
(
$param_name:ident
:
$param_ty:ty
),
*
)
->
$output_ty:ty
$block:block
)
=>
{
fn
$name
(
$
(
$param_name
:
$param_ty
),
*
)
->
$output_ty
{
fn
inner
(
$
(
$param_name
:
$param_ty
),
*
)
->
$output_ty
$block
memoize_expand_block!
(
$cache_map
,
$cache_key
,
$
(
$param_name
:
$param_ty
),
*
)
}
};
(
$cache_map:expr
,
$cache_key:expr
,
pub
fn
$name:ident
(
$
(
$param_name:ident
:
$param_ty:ty
),
*
)
->
$output_ty:ty
$block:block
)
=>
{
pub
fn
$name
(
$
(
$param_name
:
$param_ty
),
*
)
->
$output_ty
{
fn
inner
(
$
(
$param_name
:
$param_ty
),
*
)
->
$output_ty
$block
memoize_expand_block!
(
$cache_map
,
$cache_key
,
$
(
$param_name
:
$param_ty
),
*
)
}
}
)
src/librustc/middle/ty.rs
浏览文件 @
c2e8f3b4
...
...
@@ -2117,22 +2117,8 @@ pub fn type_needs_drop(cx: &ctxt, ty: t) -> bool {
// task can free them all at once later. Currently only things
// that only contain scalars and shared boxes can avoid unwind
// cleanups.
pub
fn
type_needs_unwind_cleanup
(
cx
:
&
ctxt
,
ty
:
t
)
->
bool
{
match
cx
.needs_unwind_cleanup_cache
.borrow
()
.find
(
&
ty
)
{
Some
(
&
result
)
=>
return
result
,
None
=>
()
}
let
mut
tycache
=
HashSet
::
new
();
let
needs_unwind_cleanup
=
type_needs_unwind_cleanup_
(
cx
,
ty
,
&
mut
tycache
);
cx
.needs_unwind_cleanup_cache
.borrow_mut
()
.insert
(
ty
,
needs_unwind_cleanup
);
needs_unwind_cleanup
}
fn
type_needs_unwind_cleanup_
(
cx
:
&
ctxt
,
ty
:
t
,
tycache
:
&
mut
HashSet
<
t
>
)
->
bool
{
memoize!
(
cx
.needs_unwind_cleanup_cache
,
ty
,
fn
type_needs_unwind_cleanup_
(
cx
:
&
ctxt
,
ty
:
t
,
tycache
:
&
mut
HashSet
<
t
>
)
->
bool
{
// Prevent infinite recursion
if
!
tycache
.insert
(
ty
)
{
return
false
;
...
...
@@ -2140,32 +2126,29 @@ fn type_needs_unwind_cleanup_(cx: &ctxt, ty: t,
let
mut
needs_unwind_cleanup
=
false
;
maybe_walk_ty
(
ty
,
|
ty
|
{
let
result
=
match
get
(
ty
)
.sty
{
ty_nil
|
ty_bot
|
ty_bool
|
ty_int
(
_
)
|
ty_uint
(
_
)
|
ty_float
(
_
)
|
ty_tup
(
_
)
|
ty_ptr
(
_
)
=>
{
true
}
ty_enum
(
did
,
ref
substs
)
=>
{
for
v
in
(
*
enum_variants
(
cx
,
did
))
.iter
()
{
for
aty
in
v
.args
.iter
()
{
let
t
=
aty
.subst
(
cx
,
substs
);
needs_unwind_cleanup
|
=
type_needs_unwind_cleanup_
(
cx
,
t
,
tycache
);
}
}
!
needs_unwind_cleanup
}
_
=>
{
needs_unwind_cleanup
=
true
;
false
}
};
needs_unwind_cleanup
|
=
match
get
(
ty
)
.sty
{
ty_nil
|
ty_bot
|
ty_bool
|
ty_int
(
_
)
|
ty_uint
(
_
)
|
ty_float
(
_
)
|
ty_tup
(
_
)
|
ty_ptr
(
_
)
=>
false
,
ty_enum
(
did
,
ref
substs
)
=>
enum_variants
(
cx
,
did
)
.iter
()
.any
(|
v
|
v
.args
.iter
()
.any
(|
aty
|
{
let
t
=
aty
.subst
(
cx
,
substs
);
type_needs_unwind_cleanup_
(
cx
,
t
,
tycache
)
})
),
result
_
=>
true
};
!
needs_unwind_cleanup
});
needs_unwind_cleanup
}
)
pub
fn
type_needs_unwind_cleanup
(
cx
:
&
ctxt
,
ty
:
t
)
->
bool
{
type_needs_unwind_cleanup_
(
cx
,
ty
,
&
mut
HashSet
::
new
())
}
/**
* Type contents is how the type checker reasons about kinds.
...
...
@@ -2179,6 +2162,7 @@ fn type_needs_unwind_cleanup_(cx: &ctxt, ty: t,
* easier for me (nmatsakis) to think about what is contained within
* a type than to think about what is *not* contained within a type.
*/
#[deriving(Clone)]
pub
struct
TypeContents
{
pub
bits
:
u64
}
...
...
@@ -2358,19 +2342,9 @@ pub fn type_interior_is_unsafe(cx: &ctxt, t: ty::t) -> bool {
type_contents
(
cx
,
t
)
.interior_unsafe
()
}
memoize!
(
cx
.tc_cache
,
type_id
(
ty
),
pub
fn
type_contents
(
cx
:
&
ctxt
,
ty
:
t
)
->
TypeContents
{
let
ty_id
=
type_id
(
ty
);
match
cx
.tc_cache
.borrow
()
.find
(
&
ty_id
)
{
Some
(
tc
)
=>
{
return
*
tc
;
}
None
=>
{}
}
let
mut
cache
=
HashMap
::
new
();
let
result
=
tc_ty
(
cx
,
ty
,
&
mut
cache
);
cx
.tc_cache
.borrow_mut
()
.insert
(
ty_id
,
result
);
return
result
;
return
tc_ty
(
cx
,
ty
,
&
mut
HashMap
::
new
());
fn
tc_ty
(
cx
:
&
ctxt
,
ty
:
t
,
...
...
@@ -2685,6 +2659,7 @@ fn each_inherited_builtin_bound(cx: &ctxt,
}
}
}
)
pub
fn
type_moves_by_default
(
cx
:
&
ctxt
,
ty
:
t
)
->
bool
{
type_contents
(
cx
,
ty
)
.moves_by_default
(
cx
)
...
...
@@ -4033,28 +4008,23 @@ pub fn impl_or_trait_item(cx: &ctxt, id: ast::DefId) -> ImplOrTraitItem {
/// Returns true if the given ID refers to an associated type and false if it
/// refers to anything else.
memoize!
(
cx
.associated_types
,
id
,
pub
fn
is_associated_type
(
cx
:
&
ctxt
,
id
:
ast
::
DefId
)
->
bool
{
let
result
=
match
cx
.associated_types
.borrow_mut
()
.find
(
&
id
)
{
Some
(
result
)
=>
return
*
result
,
None
if
id
.krate
==
ast
::
LOCAL_CRATE
=>
{
match
cx
.impl_or_trait_items
.borrow
()
.find
(
&
id
)
{
Some
(
ref
item
)
=>
{
match
**
item
{
TypeTraitItem
(
_
)
=>
true
,
MethodTraitItem
(
_
)
=>
false
,
}
if
id
.krate
==
ast
::
LOCAL_CRATE
{
match
cx
.impl_or_trait_items
.borrow
()
.find
(
&
id
)
{
Some
(
ref
item
)
=>
{
match
**
item
{
TypeTraitItem
(
_
)
=>
true
,
MethodTraitItem
(
_
)
=>
false
,
}
None
=>
false
,
}
None
=>
false
,
}
None
=>
{
csearch
::
is_associated_type
(
&
cx
.sess.cstore
,
id
)
}
};
cx
.associated_types
.borrow_mut
()
.insert
(
id
,
result
);
result
}
else
{
csearch
::
is_associated_type
(
&
cx
.sess.cstore
,
id
)
}
}
)
/// Returns the parameter index that the given associated type corresponds to.
pub
fn
associated_type_parameter_index
(
cx
:
&
ctxt
,
...
...
@@ -4110,13 +4080,9 @@ pub fn trait_item_def_ids(cx: &ctxt, id: ast::DefId)
})
}
memoize!
(
cx
.impl_trait_cache
,
id
,
pub
fn
impl_trait_ref
(
cx
:
&
ctxt
,
id
:
ast
::
DefId
)
->
Option
<
Rc
<
TraitRef
>>
{
match
cx
.impl_trait_cache
.borrow
()
.find
(
&
id
)
{
Some
(
ret
)
=>
{
return
ret
.clone
();
}
None
=>
{}
}
let
ret
=
if
id
.krate
==
ast
::
LOCAL_CRATE
{
if
id
.krate
==
ast
::
LOCAL_CRATE
{
debug!
(
"(impl_trait_ref) searching for trait impl {:?}"
,
id
);
match
cx
.map
.find
(
id
.node
)
{
Some
(
ast_map
::
NodeItem
(
item
))
=>
{
...
...
@@ -4136,11 +4102,9 @@ pub fn impl_trait_ref(cx: &ctxt, id: ast::DefId) -> Option<Rc<TraitRef>> {
}
}
else
{
csearch
::
get_impl_trait
(
cx
,
id
)
};
cx
.impl_trait_cache
.borrow_mut
()
.insert
(
id
,
ret
.clone
());
ret
}
}
)
pub
fn
trait_ref_to_def_id
(
tcx
:
&
ctxt
,
tr
:
&
ast
::
TraitRef
)
->
ast
::
DefId
{
let
def
=
*
tcx
.def_map
.borrow
()
...
...
@@ -4324,13 +4288,9 @@ pub fn type_is_empty(cx: &ctxt, t: t) -> bool {
}
}
memoize!
(
cx
.enum_var_cache
,
id
,
pub
fn
enum_variants
(
cx
:
&
ctxt
,
id
:
ast
::
DefId
)
->
Rc
<
Vec
<
Rc
<
VariantInfo
>>>
{
match
cx
.enum_var_cache
.borrow
()
.find
(
&
id
)
{
Some
(
variants
)
=>
return
variants
.clone
(),
_
=>
{
/* fallthrough */
}
}
let
result
=
if
ast
::
LOCAL_CRATE
!=
id
.krate
{
if
ast
::
LOCAL_CRATE
!=
id
.krate
{
Rc
::
new
(
csearch
::
get_enum_variants
(
cx
,
id
))
}
else
{
/*
...
...
@@ -4385,12 +4345,9 @@ pub fn enum_variants(cx: &ctxt, id: ast::DefId) -> Rc<Vec<Rc<VariantInfo>>> {
}
_
=>
cx
.sess
.bug
(
"enum_variants: id not bound to an enum"
)
}
};
cx
.enum_var_cache
.borrow_mut
()
.insert
(
id
,
result
.clone
());
result
}
}
)
// Returns information about the enum variant with the given ID:
pub
fn
enum_variant_with_id
(
cx
:
&
ctxt
,
...
...
@@ -4415,22 +4372,12 @@ pub fn lookup_item_type(cx: &ctxt,
}
/// Given the did of a trait, returns its canonical trait ref.
memoize!
(
cx
.trait_defs
,
did
,
pub
fn
lookup_trait_def
(
cx
:
&
ctxt
,
did
:
ast
::
DefId
)
->
Rc
<
ty
::
TraitDef
>
{
let
mut
trait_defs
=
cx
.trait_defs
.borrow_mut
();
match
trait_defs
.find_copy
(
&
did
)
{
Some
(
trait_def
)
=>
{
// The item is in this crate. The caller should have added it to the
// type cache already
trait_def
}
None
=>
{
assert
!
(
did
.krate
!=
ast
::
LOCAL_CRATE
);
let
trait_def
=
Rc
::
new
(
csearch
::
get_trait_def
(
cx
,
did
));
trait_defs
.insert
(
did
,
trait_def
.clone
());
trait_def
}
}
assert!
(
did
.krate
!=
ast
::
LOCAL_CRATE
);
Rc
::
new
(
csearch
::
get_trait_def
(
cx
,
did
))
}
)
/// Given a reference to a trait, returns the bounds declared on the
/// trait, with appropriate substitutions applied.
...
...
@@ -4489,13 +4436,9 @@ pub fn lookup_simd(tcx: &ctxt, did: DefId) -> bool {
}
/// Obtain the representation annotation for a struct definition.
memoize!
(
tcx
.repr_hint_cache
,
did
,
pub
fn
lookup_repr_hints
(
tcx
:
&
ctxt
,
did
:
DefId
)
->
Rc
<
Vec
<
attr
::
ReprAttr
>>
{
match
tcx
.repr_hint_cache
.borrow
()
.find
(
&
did
)
{
None
=>
{}
Some
(
ref
hints
)
=>
return
(
*
hints
)
.clone
(),
}
let
acc
=
if
did
.krate
==
LOCAL_CRATE
{
Rc
::
new
(
if
did
.krate
==
LOCAL_CRATE
{
let
mut
acc
=
Vec
::
new
();
ty
::
each_attr
(
tcx
,
did
,
|
meta
|
{
acc
.extend
(
attr
::
find_repr_attrs
(
tcx
.sess
.diagnostic
(),
...
...
@@ -4505,12 +4448,9 @@ pub fn lookup_repr_hints(tcx: &ctxt, did: DefId) -> Rc<Vec<attr::ReprAttr>> {
acc
}
else
{
csearch
::
get_repr_attrs
(
&
tcx
.sess.cstore
,
did
)
};
let
acc
=
Rc
::
new
(
acc
);
tcx
.repr_hint_cache
.borrow_mut
()
.insert
(
did
,
acc
.clone
());
acc
})
}
)
// Look up a field ID, whether or not it's local
// Takes a list of type substs in case the struct is generic
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录