Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
d22b7ca3
R
Rust
项目概览
int
/
Rust
大约 1 年 前同步成功
通知
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,发现更多精彩内容 >>
提交
d22b7ca3
编写于
9月 06, 2012
作者:
E
Elliott Slaughter
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
gc: Documentation.
上级
8d17308e
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
52 addition
and
0 deletion
+52
-0
src/libcore/gc.rs
src/libcore/gc.rs
+52
-0
未找到文件。
src/libcore/gc.rs
浏览文件 @
d22b7ca3
/*! Precise Garbage Collector
The precise GC exposes two functions, gc and
cleanup_stack_for_failure. The gc function is the entry point to the
garbage collector itself. The cleanup_stack_for_failure is the entry
point for GC-based cleanup.
Precise GC depends on changes to LLVM's GC which add support for
automatic rooting and addrspace-based metadata marking. Rather than
explicitly rooting pointers with LLVM's gcroot intrinsic, the GC
merely creates allocas for pointers, and allows an LLVM pass to
automatically infer roots based on the allocas present in a function
(and live at a given location). The compiler communicates the type of
the pointer to LLVM by setting the addrspace of the pointer type. The
compiler then emits a map from addrspace to tydesc, which LLVM then
uses to match pointers with their tydesc. The GC reads the metadata
table produced by LLVM, and uses it to determine which glue functions
to call to free objects on their respective heaps.
GC-based cleanup is a replacement for landing pads which relies on the
GC infrastructure to find pointers on the stack to cleanup. Whereas
the normal GC needs to walk task-local heap allocations, the cleanup
code needs to walk exchange heap allocations and stack-allocations
with destructors.
*/
import
stackwalk
::
Word
;
import
libc
::
size_t
;
import
libc
::
uintptr_t
;
...
...
@@ -27,6 +54,7 @@ struct StackSegment {
fn
rust_get_stack_segment
()
->
*
StackSegment
;
}
// Is fp contained in segment?
unsafe
fn
is_frame_in_segment
(
fp
:
*
Word
,
segment
:
*
StackSegment
)
->
bool
{
let
begin
:
Word
=
unsafe
::
reinterpret_cast
(
&
segment
);
let
end
:
Word
=
unsafe
::
reinterpret_cast
(
&
(
*
segment
)
.end
);
...
...
@@ -37,6 +65,8 @@ unsafe fn is_frame_in_segment(fp: *Word, segment: *StackSegment) -> bool {
type
SafePoint
=
{
sp_meta
:
*
Word
,
fn_meta
:
*
Word
};
// Returns the safe point metadata for the given program counter, if
// any.
unsafe
fn
is_safe_point
(
pc
:
*
Word
)
->
Option
<
SafePoint
>
{
let
module_meta
=
rustrt
::
rust_gc_metadata
();
let
num_safe_points_ptr
:
*
u32
=
unsafe
::
reinterpret_cast
(
&
module_meta
);
...
...
@@ -48,6 +78,7 @@ unsafe fn is_safe_point(pc: *Word) -> Option<SafePoint> {
return
None
;
}
// FIXME (#2997): Use binary rather than linear search.
let
mut
sp
=
0
as
Word
;
while
sp
<
num_safe_points
{
let
sp_loc
=
*
ptr
::
offset
(
safe_points
,
sp
*
3
)
as
*
Word
;
...
...
@@ -74,6 +105,8 @@ unsafe fn align_to_pointer<T>(ptr: *T) -> *T {
return
unsafe
::
reinterpret_cast
(
&
ptr
);
}
// Walks the list of roots for the given safe point, and calls visitor
// on each root.
unsafe
fn
walk_safe_point
(
fp
:
*
Word
,
sp
:
SafePoint
,
visitor
:
Visitor
)
{
let
fp_bytes
:
*
u8
=
unsafe
::
reinterpret_cast
(
&
fp
);
let
sp_meta_u32s
:
*
u32
=
unsafe
::
reinterpret_cast
(
&
sp
.sp_meta
);
...
...
@@ -127,6 +160,10 @@ unsafe fn walk_safe_point(fp: *Word, sp: SafePoint, visitor: Visitor) {
const
need_cleanup
:
Memory
=
exchange_heap
|
stack
;
// Find and return the segment containing the given frame pointer. At
// stack segment boundaries, returns true for boundary, so that the
// caller can do any special handling to identify where the correct
// return address is in the stack frame.
unsafe
fn
find_segment_for_frame
(
fp
:
*
Word
,
segment
:
*
StackSegment
)
->
{
segment
:
*
StackSegment
,
boundary
:
bool
}
{
// Check if frame is in either current frame or previous frame.
...
...
@@ -154,6 +191,8 @@ unsafe fn find_segment_for_frame(fp: *Word, segment: *StackSegment)
return
{
segment
:
segment
,
boundary
:
false
};
}
// Walks stack, searching for roots of the requested type, and passes
// each root to the visitor.
unsafe
fn
walk_gc_roots
(
mem
:
Memory
,
sentinel
:
**
Word
,
visitor
:
Visitor
)
{
let
mut
segment
=
rustrt
::
rust_get_stack_segment
();
let
mut
last_ret
:
*
Word
=
ptr
::
null
();
...
...
@@ -168,6 +207,15 @@ unsafe fn walk_gc_roots(mem: Memory, sentinel: **Word, visitor: Visitor) {
let
{
segment
:
next_segment
,
boundary
:
boundary
}
=
find_segment_for_frame
(
frame
.fp
,
segment
);
segment
=
next_segment
;
// Each stack segment is bounded by a morestack frame. The
// morestack frame includes two return addresses, one for
// morestack itself, at the normal offset from the frame
// pointer, and then a second return address for the
// function prologue (which called morestack after
// determining that it had hit the end of the stack).
// Since morestack itself takes two parameters, the offset
// for this second return address is 3 greater than the
// return address for morestack.
let
ret_offset
=
if
boundary
{
4
}
else
{
1
};
last_ret
=
*
ptr
::
offset
(
frame
.fp
,
ret_offset
)
as
*
Word
;
...
...
@@ -238,6 +286,10 @@ fn expect_sentinel() -> bool { true }
#[cfg(nogc)]
fn
expect_sentinel
()
->
bool
{
false
}
// Entry point for GC-based cleanup. Walks stack looking for exchange
// heap and stack allocations requiring drop, and runs all
// destructors.
//
// This should only be called from fail, as it will drop the roots
// which are *live* on the stack, rather than dropping those that are
// dead.
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录