skip to main |skip to sidebar

2008-06-15

[AS3]详解E4X的变量展开(2)——内部实现

[AS3]E4X的变量展开详解(1)——基础,下面来研究E4X变量展开的内部实现。

源文件:

var a = <a>abc{123}def</a>;

使用 abcdump 反编译后的结果:

 0        getlocal0
1 pushscope
2 findpropstrict XML
4 getproperty XML
6 pushstring "<a>abc"
8 pushbyte 123
10 esc_xelem
11 add
12 pushstring "def</a>"
14 add
15 construct (1)
17 getglobalscope
18 swap
19 setslot 1
21 returnvoid

new String() 做比较

源文件:

var a = new String("a")

使用 abcdump 反编译后的结果:

 0        getlocal0
1 pushscope
2 findpropstrict String
4 pushstring "a"
6 constructprop String (1)
9 getglobalscope
10 swap
11 setslot 1
13 returnvoid

会发现 E4X 与 new String() 很相似。

先来看压栈的部分

new String() 的为:

4        pushstring          "a"
6 constructprop String (1)

new String() 是先把 "a" 压入堆栈,再调用构造函数。

而 E4X 的为:

 6        pushstring          "<a>abc"
8 pushbyte 123
10 esc_xelem
11 add
12 pushstring "def</a>"
14 add
15 construct (1)

有点复杂,过程为:

1.把 "<a>abc" 压入堆栈(第6行)

"<a>abc"
XML

2.把 123 压入堆栈(第8行)

123
"<a>abc"
XML

3.把 栈顶(这里为 123)转换为 String。(第10行) esc_xelem 相当于 toXMLString(123) *注意 toXMLString 为内部函数,无法调用。

"123"
"<a>abc"
XML

4.把堆栈的栈顶的两项相加。(第11行)

"<a>abc123"
XML

5.把 "def</a>" 压入堆栈(第12行)

"def</a>"
"<a>abc123"
XML

6.把堆栈的栈顶的两项相加。(第14行)

"<a>abc123def</a>"
XML

7.调用构造函数。(第15行)即返回 new XML("<a>abc123def</a>")

总结

<a>abc{123}def</a>;

就相当于

new XML("<a>abc" + toXMLString(123) + "def</a>");

最后,关于AVM2的格式可以参照AVM2 Instructions,不明白的语句可以去查一查。

未完待续,下一篇详解效率与实用性

没有评论: