ActionScript 字节码 AVM2 中的 initscopedepth 是什么?为什么 getlocal_0 和 pushscope?

What is initscopedepth in ActionScript bytecode AVM2? Why getlocal_0 and pushscope?

我查看了 AVM2 Overview document(第 4.11 章,第 33 页)并发现以下关于 init_scope_depth 的内容:

init_scope_depth
The init_scope_depth field defines the minimum scope depth, relative to max_scope_depth, that may be accessed within the method.
max_scope_depth
The max_scope_depth field defines the maximum scope depth that may be accessed within the method. The difference between max_scope_depth and init_scope_depth determines the size of the local scope stack.

我还在 ActionScript 3.0 Bible book 上看到关于范围链的引用,我认为它与 init_scope_depth 有关,并说:

The scope chain, shown in figure 2-1, is an internal device that is created to manage variable scope during function execution.
When a variable is referenced, the Flash Player starts with the most recent function called and checks for variable declarations. If the value isn't found in the most local scope, it moves up one level to the parent function that called the function and checks there. This process continues until the scope chain has been checked all the way up to the global scope.

Figure2-1

如图所示,我们的范围顺序是,从上到下:

function scope -> parent function(s) scope (if any) -> instance of the class calling the function -> static instance of the class calling the function -> global scope

另请注意,根据 class 继承,作用域链可以有更多级别。

现在我的问题来了:

我一直在玩 JPEXS Free Flash Decompiler 和 RABCDAsm,我在一个名为 Data 的包中有一个名为 Global 的 class。 class 不扩展任何其他 classes,而是实现一个接口。在这个class中,有普通方法和静态方法。我注意到静态方法 initscopedepth 设置为 3,普通方法 initscopedepth 设置为 4。(注意:这些值由编译器设置,如 AVM2 Overview document 中所述, 第 4.11 章).

我的猜测是初始范围是:

method -> instance of class -> static instance of class (static variables) -> global

但我不确定,想知道是否有人可以证实这一点。

这也引出了另一个问题。所有方法 code 块,包括普通方法和静态方法,都以代码开头:

getlocal_0
pushscope

(注意:在这 2 条指令之后是方法开始的任何指令。) 可能是因为,对于普通对象,它将 this 推入作用域堆栈,而对于静态方法,它将 class 的静态实例推入作用域堆栈?如果是这样,为什么有必要这样做?

好的,我相信经过更多的研究和思考,我已经找到了答案。谜题的关键是再弄清楚两件事。

  1. 所有 classes 默认扩展 Object class,如 this book 中所述。
  2. 在方法入口处,作用域堆栈为空,并且有 max_scope_stack 个值的空间,如 AVM2 概述第 3.3.3 章中所述。

因此,初始范围深度为: global -> Object class -> MyClass class (static instance)

因此,本例中的初始作用域深度为 3。我注意到 classes 之外的函数的初始作用域深度为 1(仅限全局作用域)。非静态方法的初始作用域深度为 4(它们也有 MyClass 对象)。

因为当我们进入一个方法时作用域栈是空的,并且因为寄存器 0 保存了 this 对象(在静态方法的情况下,它是静态实例,或者 class本身,如果你愿意的话),我们必须将这个对象压入作用域栈,以便我们可以访问其作用域链上的所有变量和方法。我们当然有方法本身的范围,这使得最大范围深度为 4。