Say you have these calls (JavaScript, just making this up for the article):
(假设您有以下调用(JavaScript,仅弥补本文的不足):)
function start() {
let a = 10
let x = doX(a)
let b = 20
doY(a, b + x)
b = 30
x--
return doZ(a + (b * x))
}
function doX(x) {
let a = x * 2
let b = doZ(x) + 2
return doZ(a + b)
}
function doY(x, y) {
fs.writeFileSync(`${x + y}.txt`, 'hello world')
}
function doZ(x) {
return Math.pow(2, x)
}
So not to get too into the weeds about the exact representation a compiler would make of this, I am just mainly interested in demonstrating some nested variables and how they are used in between function calls.
(因此,为了避免过于迷惑编译器将如何实现这种精确表示,我只是主要感兴趣于演示一些嵌套变量以及它们在函数调用之间的用法。)
So essentially we have this at each "frame" (a term which I just mean to be all of the variables defined before the upcoming function call):
(因此,从本质上讲,我们在每个“框架”处都有这个(我只是想将其作为即将到来的函数调用之前定义的所有变量):)
1. a = 10 [call doX(a)]
1. a = x * 2 [call doZ(x)]
2. a = x * 2, b = doZ(x) + 2 [call doZ(a + b)]
2. x = ?1, a = 10, b = 20 [call doY(a, b + x)]
1. ... ignored, just something outside of our scope
3. x = ?2, a = 10, b = 30 [call doZ(a + (b * x))]
1. just a return
So at the top level, both x
and b
change their values.
(因此,在顶层, x
和b
更改其值。)
Otherwise all the other variable are just declared once.(否则,所有其他变量仅声明一次。)
But in reality function calls could be 20 deep, with 20 variables each, some of them being assigned 10 times+.(但是实际上,函数调用的深度可能为20,每个变量有20个变量,其中一些被分配了10倍以上。)
So there would be this situation times 10 let's say, if not more.(因此,这种情况将乘以10,如果不是更多的话。)
Basically, I am wondering what the call stack would look like in each of these frames.
(基本上,我想知道每个帧中的调用堆栈是什么样的。)
Particularly how the local variables are stored/restored after certain points.(特别是在某些点之后如何存储/恢复局部变量。)
For example, what happens between points (2) and (3)?
(例如,在点(2)和(3)之间会发生什么?)
The x
and b
variables are both redefined.(x
和b
变量都被重新定义。)
What goes into the call stack before the function called at (2)?(在(2)处调用的函数之前,什么进入调用堆栈?)
What goes into the call stack inside of (2)?((2)里面的调用堆栈中有什么?)
And what goes into the call stack after (2)?((2)之后,什么进入调用堆栈?)
Say we had a much more complicated situation:
(假设我们遇到的情况要复杂得多:)
let a = 10
let b = 20
draw(a++, b)
draw(a++, b)
draw(a++, b)
draw(a++, b)
...x100
What happens then?
(那会发生什么呢?)
Is b
pushed and popped every call to draw
?Or is it somehow optimized so it doesn't have to be stored on the stack every time?(是在每次draw
调用时都推入并弹出b
吗?还是以某种方式对其进行了优化,因此不必每次都将其存储在堆栈中?)
This sort of stuff...(这种东西...)
Pretty much I am just trying to get a sense of how to build a call stack from scratch, and am confused as to what you actually put onto the call stack, and when/how/what you actually pop when a function returns.
(我几乎只是想了解如何从头开始构建调用堆栈,并对您实际放入调用堆栈中的内容以及函数返回时实际弹出的时间/方式/内容感到困惑。)
Because to me, in my head, when you do let b = 10
, it just "stays around in the function scope" until the function is done, but that's not realistic.(因为对我来说,当我let b = 10
,它只是“停留在函数范围内”,直到函数完成为止,但这是不现实的。)
I am not paying attention to the call stack, mainly because higher-level languages don't require you too, and so I don't have any sense of it.WHat I would like to gain is an intuition for what the call stack looks like at these points/frames.(我没有注意调用堆栈,主要是因为高级语言也不需要您,所以我对此没有任何感觉。我想了解的是调用堆栈的外观就像在这些点/帧。)
I have seen the wikipedia (and other) diagrams of the rectangle drawing of a stack, but they aren't very helpful.(我已经看到了堆栈的矩形图的Wikipedia(和其他)图,但是它们并不是很有用。)
What I would really think was useful is some pseudocode so I could see, perhaps in an array of "frames", what each "step" or "frame" would look like in terms of JavaScript objects or structs (sort of thing), something like:(我真正认为有用的是一些伪代码,因此我可以在一个“框架”数组中看到每个“步骤”或“框架”在JavaScript对象或结构(某种事物)方面的外观,喜欢:)
var callStackAtEachFrame = [
{
a: 10
},
[
{
a: 10
},
{
a: x * 2
}
],
[
{
a: 10
},
{
a: x * 2,
b: doZ(x) + 2
},
{
something: Math.pow(2, x)
}
]
]
I don't really know, but it seems that visualizing in a more code way like this, how things push and pop from the callstack, would be helpful in knowing how to build one.
(我真的不知道,但是似乎以这种更多的代码方式可视化事物如何从调用堆栈中弹出和弹出,将有助于了解如何构建一个。)
Does it look something like this in reality?
(在现实中看起来像这样吗?)
function start() {
let a = 10
PUSH(a)
let x = doX(a)
POP(a, x)
let b = 20
PUSH(a, x, b)
doY(a, b + x)
POP(a, x, b)
b = 30
x--
PUSH(a, x, b)
return doZ(a + (b * x))
}
function doX(x) {
let a = x * 2
PUSH(a)
let b = doZ(x) + 2
POP(a, b)
return doZ(a + b)
}
...
Also, I am not really to interested how JavaScript itself does it, I am interested in a language-agnostic way.
(另外,我对JavaScript本身的工作方式并不感兴趣,而是对语言不可知的方式感兴趣。)
ask by Lance Pollard translate from so