1 / 26

第九章 运行时的存储空间

第九章 运行时的存储空间. 运行时存储空间的结构和分配 过程活动记录 AR 运行时变量的访问. 运行时的存储空间结构. 要保存的信息: 目标代码;数据;库函数代码; 过程活动的控制信息等 运行时的存储空间结构:. 最大地址. 堆区空间 栈区空间. 最小地址. 库代码空间. 静态区空间. 目标代码空间. 目标程序运行时的活动. 活动: 过程的一次执行。如果 a 和 b 是两个活动,则它们的生存期或者是不重叠的,或者是嵌套的。 活动树: 由活动构成的一个树,其中 1 )树中的每个节点代表一个活动。 2 )树的根节点是程序的主过程(函数)的活动。

caelan
Download Presentation

第九章 运行时的存储空间

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第九章 运行时的存储空间 • 运行时存储空间的结构和分配 • 过程活动记录AR • 运行时变量的访问

  2. 运行时的存储空间结构 • 要保存的信息: 目标代码;数据;库函数代码; 过程活动的控制信息等 • 运行时的存储空间结构: 最大地址 堆区空间 栈区空间 最小地址 库代码空间 静态区空间 目标代码空间

  3. 目标程序运行时的活动 • 活动:过程的一次执行。如果a和b是两个活动,则它们的生存期或者是不重叠的,或者是嵌套的。 • 活动树:由活动构成的一个树,其中 1)树中的每个节点代表一个活动。 2)树的根节点是程序的主过程(函数)的活动。 3)在树中若b为a的儿子节点,则必有a活动调用了b活动。 4)在树中若a为b的左兄弟节点,则必有a活动先于b活动执行。

  4. 名字的作用域和邦定 • 作用域:一个声明起作用的程序部分称为该声明的作用域。一个名字在程序中只声明一次,该名字在程序运行时也可能代表不同的数据对象。 • 环境和状态:环境表示将名字映射到存储单元的函数,状态表示将存储单元映射到它所保存的值的函数 。 • 绑定:如果环境将名字x映射到存储单元s,我们就说x被绑定(binding)到s 。

  5. 过程活动记录 • 过程活动记录(AR):过程的一个现场记录 • 记录内容: 过程控制信息:先行活动记录的动态链指针、返回地址、层数和长度等 机器状态信息:寄存器状态等 全局变量信息:非局部变量的信息 局部变量值:形参变量、局部变量和临时变量

  6. 临时变量区 局部变量区 AR的结构: 本层变量和返回值 形参变量区 返回值 变量访问信息 变量访问环境 机器状态信息 机器状态 过程层数 控制状态信息 返回地址 动态链指针 sp

  7. 抽象地址分配 I. (ℓ,off)LabelDec(ℓ,off) (ℓ,off)ConstDec(ℓ,off) (ℓ,off)TypeDec(ℓ,off) (ℓ,off)Var id:T(ℓ,off+n) (ℓ,off)ProcDec(ℓ,off) (ℓ,off)FuncDec(ℓ,off) II.(ℓ,off)Proc p()(ℓ+1,off1+ℓ+2) (ℓ,off)Func f():T(ℓ+1,off1+ℓ+2) (ℓ,off)Proc P()(ℓ,off+2) (ℓ,off)Func F():T (ℓ,off+2) III. (ℓ,off)Var ID:T(ℓ,off+1) (ℓ,off)ID:T(ℓ,off+n) IV. (ℓ,off)Proc p((ℓ+1,off0) (ℓ,off)Func f((ℓ+1,off0) (ℓ,off)Proc P((ℓ+1,off0) (ℓ,off)Fucn F((ℓ+1,off0)

  8. 抽象地址分配例子 (ℓ,10)Label 100,200; (ℓ,10)Const pai=3.14; (ℓ,10)Type arr=array[1..10]of integer; (ℓ,10)Var x:integer; (ℓ,11) a:array[1..5]of integer; (ℓ,16)Function f( (ℓ+1,4)Var x:real; (ℓ+1,5) a:arr; (ℓ+1,15)Var c:arr; (ℓ+1,16)Procedure G(); (ℓ+1,18)Function F():real (ℓ+1,20) ):real; (ℓ+1,20+ℓ+2 Begin ……end; (ℓ,16)

  9. 目标程序运行时的动作(1) 调用一个过/函时,建立新的活动记录;退出一个过/函时,删除它的当前活动记录。这些工作由目标程序来完成,分别分散在过程调用语句、过程入口和过程出口部分的目标代码中。 • 过/函调用语句所完成的工作 1)在新建立的活动记录里保存现役活动记录的始地址:0[top]:=sp; 2)在新建立的活动记录里记入先行Display表的始地址: • 实在过程语句情形:3[top]:=sp+ Noff。 • 形式过程语句情形:3[top]:=(第二形参单元)。其中第二形参单元是给形参过程名分配的第二个单元。 3)把实参信息传送到新活动记录区的形参单元中; 4)转向相应过程的目标程序。 5)如果是函数调用,则把函数值读到某寄存器中。

  10. 目标程序运行时的动作(2) • 过/函入口完成的工作 1)在新建立的活动记录里保存返回地址:1[top]:=返回地址 2)在要建立的新活动记录里生成DISPLAY表:从3[top]所指的先行DISPLAY表自底向上抄录ℓ个单元的内容(ℓ是被调用过程的层数),再添上新的sp值。 3)使新建的活动记录成为现役活动记录: sp:=top;top:=top+Moff • 过/函出口完成的工作 1)删除本层活动记录,使动态外层的活动记录成为现役活动记录: top:=sp;sp:=0[sp] 2)按1[top]中的返回地址返回。

  11. 参数传递(1) • 值调用 1)把形参当作所在过程的局部名看待,形参的存储单元在该过程的活动记录中。 2)调用过程计算实参,并把右值放入形参的存储单元中。 • 引用调用 1)如果实参是有左值的名字或表达式,则把该左值放入形参的存储单元。如果实参是a + b或2这样没有左值的表达式,则把它的值计算到新的存储单元,然后传递这个单元的地址。 2)在被调用过程的目标代码中,任何对形参的引用都是通过传给该过程的指针来间接引用实参的。

  12. 参数传递(2) • 值-结果调用 1)在控制流到被调用过程之前,由调用过程计算实参,然后将实参的右值和左值同时传给被调用过程。 2)在被调用过程中,像值调用那样使用实参的右值。 3)在被调用过程中,当控制返回调用过程时,根据传递来的实参的左值,将形参当前的值复写到实参存储单元。 • 换名调用 1)把过程当作宏来对待,也就是在调用点,用被调用过程的体来替换调用者的调用,但是形参用对应的实参文字来代替。这种文字替换方式称为宏展开或内联展开。 2)被调用过程的局部名与调用过程的名字保持区别。可以认为在宏展开前,被调用过程的每个局部名字系统地被重新命名成可区别的名字。 3)为保持实参的完整性,实参可以由括号包围

  13. 静态存储分配 • 存储对象的存储位置在程序的整个生命 周期是固定的。 • 分配对象: 全程变量 常量 信息表 • 分配方法: 块地址法:(DataArea,Offset) 变址模式:(Register,Offset)

  14. 栈式存储分配 • 存在递归调用 • 存储对象: 过程中被声明的形参、局部变量 临时变量 • 分配方法: 对每个被调用过程分配一段存储空间,sp存放当前 过程空间的开始地址;对变量X:(Level,off), 则其存放地址为off[sp]。 过程结束时自动释放空间; • 不能存储: 值的生命周期长于过程的变量; 动态申请空间的变量;

  15. 过程层数 假定主程序的层数为0,称为第0层过程。如果过程 Q是在层数为i的过程P内定义,并且P是包围Q的最小过程,那么,Q的层数就为i+1。 • 调用链 :过程名序列 若M是主程序名,则(M)是一个调用链; 若(M,…,R)是调用链,且在R中有S的调用,则(M, …, R, S)也是调用链。记为 CallChain(S)= (M, …,R, S) • 动态链: 如果有调用链CallChain(S)=(M,…,R, S), 则它对应的动态链为: DynamicChain=[AR(M),…,AR(R),AR(S)]

  16. 声明链 (M)是过程声明链;若(M,…,P)是声明链,且P中有过程Q的声明,则(M,…,P,Q)也是过程声明链。记作 DeclaChain(Q)= (M,…,P,Q) • 活跃活动记录 过程S在动态链中可有多个AR,但只有最新的AR(S)是可访问的,称其为S活跃活动记录,记为LAR(S)。 • 变量访问环境 Q的声明链中的每个过程的活跃活动记录构成的链称为Q的当前变量访问环境,记为: VarVisitEnv(LAR(Q))=[LAR(M),…, LAR(P), LAR(Q)]

  17. 变量访问环境的实现方法 • Display表方法 全局表法 局部表法 • 静态链方法 • 寄存器方法

  18. 局部Display表方法 • 对于每个AR求出其变量访问环境,并把它以 地址表的形式(Display表)保存在AR中。因 为每个AR都自带Display表,称这种方法为局 部化Display表方法。 • 如果层数为N的过程P的变量访问环境为: VarVisitEnv(AR(P))=[ARi1,…,ARi,n+1], arij表示ARij的始地址,则 [ari1,…,ari,n+1]是AR(P)的Display表.

  19. …… [ar0,ar1,…,arN-1,newsp] Display表 …… newsp 动态链指针 …… Display表 [ar0,ar1,…,arN-1,…] …… 动态链指针 sp Display表的求法 • NewAR.Display= CurrentAR.Display的前N项newsp

  20. AR(S) X单元 AR(M) AR(Q) AR(R) Z单元 Y单元 newsp Display 表 ar1 ar0 ar1 ar2 ar0 Off- Display sp 例:有过程M,Q,R,S,其中level(M)=0;level(Q)=1;level(R)=1;level(S)=2,各AR的Display表分别如下:

  21. 局部Display表时变量的访问 • 对一个变量X(L, off),地址为: 当L= CurrentAR.level时: addr(X)=[sp+D]+off 否则: addr(X)=CurrentAR.Display[L]+ off 即[sp+D+L]+off

  22. 静态链方法 • 原Display表部分变成一个单元,称为静态链 单元,存放静态链指针。 • 静态链指针的确定: 若NewAR.level= CurrentAR.level+1-k,则 NewAR.StaticChainPointer=Indir(sp,k) 其中Indir(sp,k)表示sp的k次间接内容。 AR(M) CurrentAR NewAR AR2 AR1 ar2 ar0 ar3 ar4 ar1 sp

  23. 使用静态链时变量的访问 • 变量X(L,off)的地址: 若L= CurrentAR.Level,则addr(X)= [sp+D]+ off 若L= CurrentAR.Level-k,则 addr(X)= Indir(sp,k)+D+ off

  24. 全局Display表和寄存器方法 • 设置一个总的Display表,其长度为最大嵌 套层数(系统确定),其中Display[i]存放 第i层最新AR的指针。D[i]表示。 • 当层数为j的过程Q被调用时: 将旧的D[j]的内容保存到NewAR(Q)中: NewAR(Q).RessumeAddr = D[j]; 改写D[j]的内容:D[j]=NewAR(Q)的地址; 当退出Q时:恢复原来D[j]的内容: D[j] = CurrentAR.ResumeAddr • 变量X(L,off)的地址:addr(X)= D[L]+off

  25. 全局Display表方法的实现 sp proc P; proc Q; begin R end proc R; proc S; begin T end proc T; begin end begin S end begin Q end 全局Display表

  26. 堆区的存储分配 • 可随时分配和释放空间 • 存储对象: 动态申请空间的变量的值 • 释放空间方法: 显式释放: 隐式释放:单指针释放 计数释放法 标记释放法 • 分配空间方法: 最佳符合法;首次优先法;循环首次优先法

More Related