手写 Python 虚拟机
海纳
华为资深编译专家,原 Huawei JDK 团队负责人
1307 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已更新 32 讲/共 32 讲
导学|直播加餐:三小时掌握C++ (3讲)
手写 Python 虚拟机
15
15
1.0x
00:00/00:00
登录|注册

28|异常(下):处理 finally 子句和 traceback 对象

你好,我是海纳。
上一节课,我们使用 Python 源码实现了 Exception 类,从而构建起了异常对象的继承体系,同时也实现了异常对象的匹配功能。在这个基础上,我们进一步实现了用于处理异常控制流的几条字节码。
第一条重要的字节码是 SETUP_FINALLY,它的作用是创建一个 Block,指定了如果在执行 try 语句的过程中发生异常应该跳转到哪里执行。第二条是 CALL_FINALLY,它的作用是如果 try 语句正常结束了,就跳转进 finally 子句执行。这节课,我们就来实现整个异常控制流的最后一条重要的指令,就是 END_FINALLY,我们要在 END_FINALLY 中增加恢复异常的逻辑。从而让解释器可以在退出函数栈帧的时候还能正确地维护异常对象。

实现 END_FINALLY

就像之前分析的,END_FINALLY 的主要作用是结束 finally 子句的执行。根据上节课说的进入 finally 子句的三种情况,我们这里分别做了处理,你可以看一下具体实现。
void Interpreter::eval_frame() {
...
while (_frame->has_more_codes()) {
unsigned char op_code = _frame->get_op_code();
...
switch (op_code) {
...
case ByteCode::END_FINALLY: {
v = POP();
long long t = (long long)v();
if (t == 0) {
// do nothing.
}
else if (t & 0x1) {
_frame->set_pc(t >> 1);
}
else {
_exception_class = v;
_pending_exception = POP();
_trace_back = POP();
_int_status = IS_EXCEPTION;
}
break;
}
...
}
}
}
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
  • 解释
  • 总结

1. 实现异常控制流的最后一条重要的指令,即 END_FINALLY,以确保在退出函数栈帧时正确维护异常对象。 2. END_FINALLY 的实现对应了三种情况:栈顶值为0时不做处理,栈顶值为地址时修改解释器的 pc 值,发生异常时恢复异常状态进行进一步处理。 3. 补充了用于处理异常时的栈状态的字节码,如 POP_EXCEPT,用于恢复异常情况时的处理。 4. 实现了 Traceback 对象,用于记录异常栈信息,包括文件名、函数名和行号。 5. Traceback 对象的打印功能,可以将异常栈信息打印出来,方便调试和定位问题。 6. 异常处理的流程包括异常发生时的处理流程,异常状态的修改和恢复,以及异常栈信息的记录和打印。 7. 完成了异常处理的全部功能,包括异常发生时的处理流程和异常状态的恢复,以及异常栈信息的记录和打印。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《手写 Python 虚拟机》
新⼈⾸单¥59
立即购买
登录 后留言

精选留言

由作者筛选后的优质留言将会公开显示,欢迎踊跃留言。
收起评论
显示
设置
留言
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部