基于栈的运行时环境

在《Compiler Construction Principles and Practice》一书中讲了两种语言运行时环境:完全静态运行时环境和基于栈的运行时环境。

完全静态运行时环境是最简单的运行时环境类别,其所有的数据都是静态的,且在程序执行期间内存中的数据都是固定的,这种运行时环境没有指针和动态内存分配,并且也不支持函数递归调用,这类语言的一个标准例子就是FORTRAN77。在完全静态运行时环境中,所有的变量,不论全局和局部的变量,都是静态分配的,我们可以通过固定的地址来直接访问到这些变量。

基于栈的运行时环境是我们常见的语言运行时环境,如C,C++等语言就是基于栈的运行时环境。允许递归调用并且在递归调用过程中要重新分配局部变量,不能静态分配活动记录(Activation Record)。一般在内存中,数据的组织如下:

在内存中数据组织图

代码区域是程序的执行指令,是不允许修改的,接下来就是全局和静态数据区,然后就是栈和堆。栈是向下生长的(向地址空间减少的方向),而堆是向上生长的(向地址空间增加的方向)。在内存分配中的一个重要单元为过程活动记录(procedure activation record),它包含了过程或函数被调用时内存分配的局部数据,一个活动记录一般包含下面几个部分:

活动记录

其实活动记录就是函数调用时被压入栈的数据总称,首先被压入栈的是函数或过程的参数,接着是返回地址,然后在函数执行过程中分配的局部数据等等。涉及函数调用还有一个指向当前活动记录的指针,称为框架指针(frame pointer)或fp,通常fp保存在寄存器中,而每个活动记录中,在bookkeeping information区域(薄记信息),都会有一个值(称为Control Link)指向上一个活动记录,即调用当前函数的函数活动记录,使整个执行流程中的活动记录呈现链状形式。

控制链在活动记录中的参数和局部数据可以通过相对于fp的偏移值来获取。

对于左边的C程序,右边显示其在第2次对g调用时的运行时栈状态:

cexample

cruntime

以上是没有允许定义局部函数的运行时栈的状态,如果在语言编译时允许定义局部的函数,前面的组织方式就没有办法做到了,因为没有提供非局部(nonlocal)和非全局的(nonglobal)的引用,支持这类运行时环境中的语言有Python、Pascal等支持在函数或者过程中再定义函数和过程的语言。解决这个问题的方法可以在bookkeeping information的区域添加添加一个叫访问链(Assess Link)的值,用于指向定义环境(Control Link是指向调用环境的)。在下面左边的Pascal程序中,右边为添加了访问链后的栈运行时状态:

pascalpascalruntime

可以看到,在q调用过程中,对变量n的搜索,是直接从定义 q的过程p中搜索,而没有从r的参数中获取。如果在过程中函数多层嵌套定义的过程,需要越过多个作用域去寻找变量,重复地取出访问链来实现。对于这样的访问链工作,编译程序必须能够在局部访问之前判定出要链接多少个嵌套层。这就要求编译程序预先为每个声明计算出嵌套层属性,当进入一个过程或者函数时,嵌套层+1,离开时则-1。

在某些语言中,特别是函数语言如Haskell之类的,不仅允许有局部过程或函数定义,而且还可以将过程和函数作为参数进行传递。在这样的语言中,当调用一个作为参数传递的过程时,编译程序就不可能像上面所说的访问链进行操作了。当将过程作为参数传递时,必须预先计算出被传递过程的访问链并与过程代码的指针一同传递,这时候,被传递的过程就拥有了代码指针和访问链,即指令指针和环境指针,可以让传递进行的过程访问其定义环境中的数据,而指令指针和环境指针就通称为闭包,以<ip, ep>表示,ip表示过程的指令指针,ep表示过程的环境指针。下面左边的表示了一个含有过程参数的例子,右边为被传递过程参数执行时的运行时栈状态:

pascalfuncpascalfuncruntime

可以看到过程r被当作过程参数传递给p的时候,在p中被调用时,访问链指向的为定义r的过程p。

以上内容是对《Compiler Construction Principles and Practice》书中讲到基于栈的运行时环境的总结。

This entry was posted in Compiler. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>