Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
263f4c58
R
Rust
项目概览
int
/
Rust
11 个月 前同步成功
通知
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,发现更多精彩内容 >>
提交
263f4c58
编写于
1月 12, 2012
作者:
N
Niko Matsakis
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
add tydescs into shape, rewrite walk_fn_contents()
上级
e55aa6e5
变更
9
显示空白变更内容
内联
并排
Showing
9 changed file
with
108 addition
and
86 deletion
+108
-86
src/comp/middle/trans.rs
src/comp/middle/trans.rs
+4
-5
src/comp/middle/trans_closure.rs
src/comp/middle/trans_closure.rs
+1
-9
src/rt/rust_cc.cpp
src/rt/rust_cc.cpp
+9
-10
src/rt/rust_shape.cpp
src/rt/rust_shape.cpp
+5
-9
src/rt/rust_shape.h
src/rt/rust_shape.h
+32
-23
src/rt/rust_upcall.cpp
src/rt/rust_upcall.cpp
+7
-5
src/test/run-pass/uniq-cc-generic.rs
src/test/run-pass/uniq-cc-generic.rs
+26
-0
src/test/run-pass/uniq-cc.rs
src/test/run-pass/uniq-cc.rs
+24
-0
src/test/run-pass/uniq-fn-leak.rs
src/test/run-pass/uniq-fn-leak.rs
+0
-25
未找到文件。
src/comp/middle/trans.rs
浏览文件 @
263f4c58
...
...
@@ -959,9 +959,9 @@ fn trans_stack_local_derived_tydesc(cx: @block_ctxt, llsz: ValueRef,
ret
llmyroottydesc
;
}
// Objects
and closures store their type parameters differently (in the object
//
or closure itself
rather than in the type descriptor).
tag
ty_param_storage
{
tps_normal
;
tps_obj
(
uint
);
tps_fn
(
uint
);
}
// Objects
store their type parameters differently (in the object itself
// rather than in the type descriptor).
tag
ty_param_storage
{
tps_normal
;
tps_obj
(
uint
);
}
fn
get_derived_tydesc
(
cx
:
@
block_ctxt
,
t
:
ty
::
t
,
escapes
:
bool
,
storage
:
ty_param_storage
,
...
...
@@ -980,7 +980,7 @@ fn get_derived_tydesc(cx: @block_ctxt, t: ty::t, escapes: bool,
let
is_obj_body
;
alt
storage
{
tps_normal
.
{
is_obj_body
=
false
;
}
tps_obj
(
_
)
|
tps_fn
(
_
)
{
is_obj_body
=
true
;
}
tps_obj
(
_
)
{
is_obj_body
=
true
;
}
}
bcx_ccx
(
cx
)
.stats.n_derived_tydescs
+=
1u
;
...
...
@@ -1028,7 +1028,6 @@ fn get_derived_tydesc(cx: @block_ctxt, t: ty::t, escapes: bool,
alt
storage
{
tps_normal
.
{
obj_params
=
0u
;
}
tps_obj
(
np
)
{
obj_params
=
np
;
}
tps_fn
(
np
)
{
obj_params
=
0x80000000u
|
np
;
}
}
let
v
;
...
...
src/comp/middle/trans_closure.rs
浏览文件 @
263f4c58
...
...
@@ -314,16 +314,8 @@ fn maybe_clone_tydesc(bcx: @block_ctxt,
let
bound_tydesc
=
GEPi
(
bcx
,
llbox
,
[
0
,
abi
::
cbox_elt_tydesc
]);
let
ti
=
none
;
// NDM I believe this is the correct value,
// but using it exposes bugs and limitations
// in the shape code. Therefore, I am using
// tps_normal, which is what we used before.
//
// let tps = tps_fn(vec::len(lltyparams));
let
tps
=
tps_normal
;
let
{
result
:
closure_td
,
_
}
=
trans
::
get_tydesc
(
bcx
,
cbox_ty
,
true
,
tps
,
ti
);
trans
::
get_tydesc
(
bcx
,
cbox_ty
,
true
,
tps
_normal
,
ti
);
trans
::
lazily_emit_tydesc_glue
(
bcx
,
abi
::
tydesc_field_take_glue
,
ti
);
trans
::
lazily_emit_tydesc_glue
(
bcx
,
abi
::
tydesc_field_drop_glue
,
ti
);
trans
::
lazily_emit_tydesc_glue
(
bcx
,
abi
::
tydesc_field_free_glue
,
ti
);
...
...
src/rt/rust_cc.cpp
浏览文件 @
263f4c58
...
...
@@ -357,7 +357,7 @@ class mark : public shape::data<mark,shape::ptr> {
case
shape
::
SHAPE_BOX_FN
:
{
// Record an irc for the environment box, but don't descend
// into it since it will be walked via the box's allocation
shape
::
data
<
mark
,
shape
::
ptr
>::
walk_fn_contents1
(
dp
);
shape
::
data
<
mark
,
shape
::
ptr
>::
walk_fn_contents1
(
dp
,
false
);
break
;
}
case
shape
::
SHAPE_BARE_FN
:
// Does not close over data.
...
...
@@ -552,15 +552,14 @@ class sweep : public shape::data<sweep,shape::ptr> {
fn_env_pair
pair
=
*
(
fn_env_pair
*
)
dp
;
// free closed over data:
shape
::
data
<
sweep
,
shape
::
ptr
>::
walk_fn_contents1
(
dp
,
true
);
// now free the embedded type descr:
//
// FIXME--this is a bit sketchy, since there is an
// embedded tydesc that we will be using to walk the
// data, but it will be freed as we walk. In the
// generated code we pull this desc out and free it
// later. We may well want to do the same. However,
// since all we use from the descr. is the "shape", I
// think we're ok.
shape
::
data
<
sweep
,
shape
::
ptr
>::
walk_fn_contents1
(
dp
);
// see comment in walk_fn_contents1() concerning null_td
// to understand why this does not occur during the normal
// walk.
upcall_s_free_shared_type_desc
((
type_desc
*
)
pair
.
env
->
td
);
// now free the ptr:
task
->
kernel
->
free
(
pair
.
env
);
...
...
src/rt/rust_shape.cpp
浏览文件 @
263f4c58
...
...
@@ -44,15 +44,7 @@ type_param::make(const type_desc **tydescs, unsigned n_tydescs,
return
ptrs
;
}
// Constructs type parameters from a function shape. This is a bit messy,
// because it requires that the function shape have a specific format.
type_param
*
type_param
::
from_fn_shape
(
rust_opaque_closure
*
env
,
arena
&
arena
)
{
unsigned
n_tydescs
=
env
->
td
->
n_obj_params
&
0x7fffffff
;
return
make
(
env
->
captured_tds
,
n_tydescs
,
arena
);
}
// Constructs type parameters from an object shape. This is also a bit messy,
// Constructs type parameters from an object shape. This is a bit messy,
// because it requires that the object shape have a specific format.
type_param
*
type_param
::
from_obj_shape
(
const
uint8_t
*
sp
,
ptr
dp
,
arena
&
arena
)
{
...
...
@@ -354,6 +346,10 @@ public:
data
<
cmp
,
ptr_pair
>::
walk_box_contents1
();
}
void
walk_tydesc2
(
char
)
{
cmp_pointer
();
}
void
walk_fn2
(
char
)
{
return
cmp_two_pointers
();
}
void
walk_obj2
()
{
return
cmp_two_pointers
();
}
...
...
src/rt/rust_shape.h
浏览文件 @
263f4c58
...
...
@@ -306,8 +306,6 @@ public:
const
rust_shape_tables
*
tables
;
const
type_param
*
params
;
// subparameters
// Constructs type parameters from a function shape.
static
type_param
*
from_fn_shape
(
rust_opaque_closure
*
env
,
arena
&
arena
);
// Creates type parameters from an object shape description.
static
type_param
*
from_obj_shape
(
const
uint8_t
*
sp
,
ptr
dp
,
arena
&
arena
);
...
...
@@ -326,8 +324,8 @@ public:
// have to actually have the data pointer, since we don't statically
// know from the type of an object or function which type parameters
// it closes over.
assert
(
!
tydesc
->
n_obj_params
&&
"Type-parametric objects
and
"
"
functions
must go through from_tydesc_and_data() instead!"
);
assert
(
!
tydesc
->
n_obj_params
&&
"Type-parametric objects "
"must go through from_tydesc_and_data() instead!"
);
return
make
(
tydesc
->
first_param
,
tydesc
->
n_params
,
arena
);
}
...
...
@@ -337,20 +335,11 @@ public:
if
(
tydesc
->
n_obj_params
)
{
uintptr_t
n_obj_params
=
tydesc
->
n_obj_params
;
const
type_desc
**
first_param
;
if
(
n_obj_params
&
0x80000000
)
{
// Function closure.
DPRINT
(
"n_obj_params FN %lu, tydesc %p, starting at %p
\n
"
,
(
unsigned
long
)
n_obj_params
,
tydesc
,
dp
+
sizeof
(
uintptr_t
)
+
tydesc
->
size
);
n_obj_params
&=
0x7fffffff
;
first_param
=
(
const
type_desc
**
)(
dp
+
sizeof
(
uintptr_t
));
}
else
{
// Object closure.
DPRINT
(
"n_obj_params OBJ %lu, tydesc %p, starting at %p
\n
"
,
(
unsigned
long
)
n_obj_params
,
tydesc
,
dp
+
sizeof
(
uintptr_t
)
*
2
);
first_param
=
(
const
type_desc
**
)(
dp
+
sizeof
(
uintptr_t
)
*
2
);
}
return
make
(
first_param
,
n_obj_params
,
arena
);
}
...
...
@@ -852,7 +841,7 @@ protected:
void
walk_box_contents1
();
void
walk_uniq_contents1
();
void
walk_fn_contents1
(
ptr
&
dp
);
void
walk_fn_contents1
(
ptr
&
dp
,
bool
null_td
);
void
walk_obj_contents1
(
ptr
&
dp
);
void
walk_iface_contents1
(
ptr
&
dp
);
void
walk_variant1
(
tag_info
&
tinfo
,
tag_variant_t
variant
);
...
...
@@ -1008,20 +997,40 @@ data<T,U>::walk_tag1(tag_info &tinfo) {
template
<
typename
T
,
typename
U
>
void
data
<
T
,
U
>::
walk_fn_contents1
(
ptr
&
dp
)
{
data
<
T
,
U
>::
walk_fn_contents1
(
ptr
&
dp
,
bool
null_td
)
{
fn_env_pair
pair
=
bump_dp
<
fn_env_pair
>
(
dp
);
if
(
!
pair
.
env
)
return
;
arena
arena
;
type_param
*
params
=
type_param
::
from_fn_shape
(
pair
.
env
,
arena
);
const
type_desc
*
closure_td
=
pair
.
env
->
td
;
type_param
*
params
=
type_param
::
from_tydesc
(
closure_td
,
arena
);
ptr
closure_dp
((
uintptr_t
)
pair
.
env
);
T
sub
(
*
static_cast
<
T
*>
(
this
),
closure_td
->
shape
,
params
,
closure_td
->
shape_tables
,
closure_dp
);
sub
.
align
=
true
;
if
(
null_td
)
{
// if null_td flag is true, null out the type descr from
// the data structure while we walk. This is used in cycle
// collector when we are sweeping up data. The idea is that
// we are using the information in the embedded type desc to
// walk the contents, so we do not want to free it during that
// walk. This is not *strictly* necessary today because
// type_param::from_tydesc() actually pulls out the "shape"
// string and other information and copies it into a new
// location that is unaffected by the free. But it seems
// safer, particularly as this pulling out of information will
// not cope with nested, derived type descriptors.
pair
.
env
->
td
=
NULL
;
}
sub
.
walk
();
if
(
null_td
)
{
pair
.
env
->
td
=
closure_td
;
}
}
template
<
typename
T
,
typename
U
>
...
...
@@ -1138,7 +1147,7 @@ private:
void
walk_fn2
(
char
kind
)
{
out
<<
prefix
<<
"fn"
;
prefix
=
""
;
data
<
log
,
ptr
>::
walk_fn_contents1
(
dp
);
data
<
log
,
ptr
>::
walk_fn_contents1
(
dp
,
false
);
}
void
walk_obj2
()
{
...
...
src/rt/rust_upcall.cpp
浏览文件 @
263f4c58
...
...
@@ -283,12 +283,14 @@ void upcall_s_free_shared_type_desc(type_desc *td)
rust_task
*
task
=
rust_scheduler
::
get_task
();
LOG_UPCALL_ENTRY
(
task
);
if
(
td
)
{
// Recursively free any referenced descriptors:
for
(
unsigned
i
=
0
;
i
<
td
->
n_params
;
i
++
)
{
upcall_s_free_shared_type_desc
((
type_desc
*
)
td
->
first_param
[
i
]);
}
task
->
kernel
->
free
(
td
);
}
}
extern
"C"
CDECL
void
...
...
src/test/run-pass/uniq-cc-generic.rs
0 → 100644
浏览文件 @
263f4c58
tag
maybe_pointy
{
none
;
p
(
@
pointy
);
}
type
pointy
=
{
mutable
a
:
maybe_pointy
,
d
:
sendfn
()
->
uint
,
};
fn
make_uniq_closure
<
A
:
send
>
(
a
:
A
)
->
sendfn
()
->
uint
{
sendfn
()
->
uint
{
ptr
::
addr_of
(
a
)
as
uint
}
}
fn
empty_pointy
()
->
@
pointy
{
ret
@
{
mutable
a
:
none
,
d
:
make_uniq_closure
(
"hi"
)
}
}
fn
main
()
{
let
v
=
empty_pointy
();
v
.a
=
p
(
v
);
}
src/test/run-pass/uniq-cc.rs
0 → 100644
浏览文件 @
263f4c58
tag
maybe_pointy
{
none
;
p
(
@
pointy
);
}
type
pointy
=
{
mutable
a
:
maybe_pointy
,
c
:
~
int
,
d
:
sendfn
()
->
(),
};
fn
empty_pointy
()
->
@
pointy
{
ret
@
{
mutable
a
:
none
,
c
:
~
22
,
d
:
sendfn
()
->
(){},
}
}
fn
main
()
{
let
v
=
empty_pointy
();
v
.a
=
p
(
v
);
}
src/test/run-pass/uniq-fn-leak.rs
已删除
100644 → 0
浏览文件 @
e55aa6e5
// xfail-test
tag
maybe_pointy
{
none
;
p
(
@
pointy
);
}
type
pointy
=
{
mutable
a
:
maybe_pointy
,
c
:
~
int
,
d
:
sendfn
()
->
(),
};
fn
empty_pointy
()
->
@
pointy
{
ret
@
{
mutable
a
:
none
,
c
:
~
22
,
d
:
sendfn
()
->
(){},
}
}
fn
main
()
{
let
v
=
empty_pointy
();
v
.a
=
p
(
v
);
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录