[英]Can someone explain CALL_FUNCTION and RETURN_VALUE from python bytecode
I'm trying to understand python bytecode and I'm caught on CALL_FUNCTION and RETURN_VALUE.我正在尝试理解 python 字节码,但遇到了 CALL_FUNCTION 和 RETURN_VALUE。
Does a function have its own stack?函数是否有自己的堆栈? If not, what does the documentation mean by "Returns TOS to the caller of the function"?
如果不是,文档中“将 TOS 返回给函数调用者”是什么意思?
Sorry for the vagueness抱歉含糊不清
In CPython every function gets its own stack, it's called a frame in CPython and it's an implementation-specific detail(very old one) and other implementation of Python like IronPython 1 and Jython doesn't have this functionality or implement it differently.在 CPython 中,每个函数都有自己的堆栈,在 CPython 中称为框架,它是特定于实现的细节(非常旧的),而其他 Python 实现(如 IronPython 1和 Jython)没有此功能或以不同方式实现。
To clarify when we say stack there are multiple stacks involved:为了澄清当我们说堆栈时涉及多个堆栈:
When a function is called a new frame object is created first and placed on the Python stack
.当一个函数被调用时,一个新的框架对象首先被创建并放置在
Python stack
。 This frame object contains the code object of the function, global variables the function has access to, and also the local variables defined in the function get stored in the frame object.这个框架对象包含函数的代码对象、函数可以访问的全局变量以及函数中定义的局部变量存储在框架对象中。
You can get the current frames in Python stack and current frame using the utilities provided in the inspect module.您可以使用检查模块中提供的实用程序获取Python 堆栈中的当前帧和当前帧。
The issue with this is that it is a Python object, it has its own type PyFrame_Type
, it gets reference count(gets all headers from PyVarObject
) and consumes some memory and if we have a chain of function calls, each time we will be creating these frame objects in memory all over the heap.问题在于它是一个 Python 对象,它有自己的类型
PyFrame_Type
,它获取引用计数(从PyVarObject
获取所有标头)并消耗一些内存,如果我们有一系列函数调用,每次我们都会创建这些帧对象在内存中遍布整个堆。
In Python 3.11, the frame object will be replaced by an array of structs that won't have an object header.在 Python 3.11 中,框架对象将被一个没有对象头的结构数组替换。 The frame objects will still be available, but only if we request for it using
inspect.currentframe()
or sys._get_frame()
.框架对象仍然可用,但
inspect.currentframe()
是我们使用inspect.currentframe()
或sys._get_frame()
请求它。
2 Function values stack 2函数值栈
We can check stacksize of a function by accessing co_stacksize
attribute of function's code object, this value is determined during the compilation time:我们可以通过访问函数代码对象的
co_stacksize
属性来检查函数的堆栈大小,该值是在编译期间确定的:
>>> def func():
... a = 1
... b = 2
... c = 3
... d = a + b + c
...
>>> func.__code__.co_stacksize
2
Here the value is 2 because to sum a + b + c
, it first loads a
and b
on the stack( LOAD_FAST
) and performs the sum( BINARY_ADD
) and puts the result back on top of stack, now c
is loaded and it's summed with the result of the sum of a
and b
.这里的值是 2,因为要对
a + b + c
求和,它首先在堆栈上加载a
和b
( LOAD_FAST
)并执行求和( BINARY_ADD
)并将结果放回堆栈顶部,现在c
已加载并求和与a
和b
之和的结果。 Hence, a maximum size of 2 is required for the stack specific to this function.因此,特定于该函数的堆栈需要的最大大小为 2。
1: The flag X:Frames
can be used in IronPython to enable CPython like frame objects. 1:可以在 IronPython 中使用标志
X:Frames
来启用 CPython 之类的框架对象。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.