PPT中信息组织如何实现-英雄云拓展知识分享
127
2023-11-07
【摘要】 本书摘自《自己动手写 Python 虚拟机》一书中第6章,第1节,海纳编著。
6.1.1 栈帧
在第2章讲解递归函数的时候,已经讲过在每一次函数调用时,都会有一个栈帧 与之相对应。在执行器里,还没有栈帧的概念,因此,要实现一种数据结构来对函数 的调用过程进行记录,这个数据结构就是 FrameObject 。 每一次调用一个函数,便有 一个这次调用的活动记录(也就是 FrameObject) 被创建,每次函数执行结束,它所对 应的活动记录也会被销毁。
在 Interpreter 里,有很多变量是为函数执行时的活动记录服务的。例如 pc 记 录了程序当前执行到的位置,locals 表记录了变量的值等。本质上这些变量是与函 数的执行绑定的,所以它们应该被封装到 FrameObject 里,而不是 Interpreter 中。 因此,做的第一件事情就是对 Interpreter 进行重构,将所有这些与执行状态相关的 变量移到 FrameObject 中。
先定义 FrameObject, 代码如下:
class FrameObject(
2 public:
3 FrameObject(CodeObject*codes);
4 FrameObject();
5
6 ArrayList
7 ArrayList
8
9 ArrayList
10 ArrayList
11
12 Map
13
14 CodeObject * _codes;
15 int _pc;
16
17 public:
18 void set_pc(int x) {_pc =x;}
19 int get_pc() (return_pc;)
20
21 ArrayList
22 ArrayList
23 ArrayList
24 ArrayList
25 Map
26
27 bool has_more_codes();
28 unsigned char get_op_code();
29 int get_op_arg();
30 };
上述代码已经把 Interpreter 中的相关变量都转移到 FrameObject 中来了。注
意第3行的构造方法,之前要执行一段 Code时,是直接调用Interpreter 的 run 方 法,以 CodeObject 为参数。现在,则要先创建一个 FrameObject,代码执行时,就只 会影响 FrameObject 中的 pc 和 locals 等变量。
这段代码的逻辑很简单,FrameObject 只是对一些状态变量的封装,包括27~ 29 所声明的三个方法,也不过是对一些简单逻辑的封装,具体的实现如代码清单6.2 所示。
//this constructor is used for module only.
2 FrameObject::FrameObject(CodeObject *codes)
3 _consts =codes ->_consts;
4 names =codes->_names;
5
6 locals =new Map
7
8 _stack =new ArrayList
9 _loop_stack =new ArrayList
10
11 _codes =codes;
12 _pc =0;
13 }
14
15 int FrameObject::get_op_arg()(
16 int bytel =_codes->_bytecodes->value()[_pc++]&0xff;
17 int byte2 =_codes →_bytecodes->value()[_pc++]&0xff;
18 return byte2<<8|bytel;
19 }
20
21 unsigned char FrameObject::get_op_code(){
22 return_codes>_bytecodes>value()[_pc++];
23
24
25 bool FrameObject::has_more_codes()(
26 return_pc <._codes>_bytecodes >length();
27
与之相应的,Interpreter 的 run 方法也发生了很多变化,代码如下:
1 //[runtime/interpreter.cpp]
2 //stack has been moved into FrameObject.
3 #define PUSH(x) _frame->stack()->add((x))
4 #define POP() frame->stack()>pop()
5 #define STACK_LEVEL()_frame >stack()->size()
7 void Interpreter::run(CodeObject *codes){
8 frame =new FrameObject(codes);
9 while(_frame>has_more_codes())(
10 unsigned char op_code =_frame->get_op_code()
bool has_argument =(op_code&0xFF)>=ByteCode::HAVE_ARGUMENT;
12
int op_arg =-1;
if(has_argument){
op_arg =_frame->get_op_arg();
)
17
}
19
除了上述代码所展示的修改外,run 方法里还有很多处修改,这里就不一一列出 了,读者可以通过工程提交记录自行比较代码还有哪些变化。
有了FrameObject 这个基础结构以后,终于可以把注意力转向 MAKE_FUNC- TION 和 CALL_FUNCTION 这两个字节码了。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们 18664393530@aliyun.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~