问题描述
function main(arg1,arg2) {
do_foo(arg1,arg2)
}
function do_foo(a,b) {
let x = a + b
let y = x * a
let z = x * b
let p = y + z
let q = x + z
let r = do_bar(&p)
let s = do_bar(&q)
}
function do_bar(&p,&q) {
*p += 1
*q += 3
let r = &p * &q
let s = &p + &q
let v = do_baz(&r,&s)
return &v
}
function do_baz(&a,&b) {
return *a + *b
}
通常如何确定变量的活跃度,以及在哪里可以插入指令以进行引用计数?
这是我的尝试...
从顶部的功能main
开始。它以2个参数开头。假设没有没有复制。它将实际的可变值传递给do_foo
。
然后我们有x
。 X拥有a和b。然后我们看到y
。 y
设置为x
,因此将前一个x链接到此x
。到r
,我们再也看不到x
了,所以也许可以释放它了……。单独看do_bar
,我们基本上知道p
和{ {1}}无法在此范围内进行垃圾收集。
基本上,我不知道如何开始实施用于实现ARC的算法(理想情况下是编译时间参考计数,但是现在也可以开始运行)。
q
我如何开始实施这种算法。我搜索了有关该主题的每篇论文,但没有找到算法。
解决方法
以下规则应适合您的语言。
- 声明变量后,增加其引用计数
- 当变量超出范围时,减少其引用计数
- 将变量引用分配给变量后,请调整变量的引用计数:
- 增加引用已分配的变量的引用计数
- 减少之前已在变量中为其分配引用的变量的引用计数(如果不为空)
- 当包含非空对变量的引用的变量超出范围时,请减小其所引用变量的引用计数。
注意:
- 如果您的语言允许在数据结构,“静态”变量等中使用对变量的引用类型,则需要以明显的方式扩展上述规则。
- 优化的编译器也许可以消除refcount的一些增量和减量。
编译时间参考计数:
- 实际上没有任何事情。引用计数在运行时完成。在编译时这样做没有任何意义。
- 您可能正在谈论分析代码以确定是否可以优化或完全消除运行时引用计数。
-
我在上面提到了前者。这实际上是一种窥孔优化。
- 后者需要检查变量引用是否可以转义;即在变量超出范围后是否可以使用 。 (尝试使用Googling进行“转义分析”。这类似于“转义分析”,编译器可以用来确定对象是否可以分配在堆栈上而不是堆中。)