X

ASC2.0让AS也可以写inline函数

C/C++里一直有内联函数,很是羡慕.现在有了Flash builder4.7 beta 和 ASC2.0(Action Script Compiler是Flash builder 4.7 beta中内置的新版编译器),AS也能使用将函数内联了,真是大快人心. 内联函数 是将在函数被调用的地方使用替换成该函数实际的代码,这样就少了一次函数调用,也就少了很多地址查找,入栈出栈的操作,对于频繁调用的函数,就会有明显的性能提升.

函数成为内联函数必须同时满足的前提条件:

  • The function is final, static or the containing scope is file or package
  • 该函数是final,static的,或者该函数在在包或者文件(直接包含在文件内,而没有类)内
  • The function does not contain any activations
  • 该函数不能包含任何活动对象(Activation Object) (包括...参数和arguments对象)
  • The function does not contain any try or with statements
  • 该函数不能包含任意try catch 或 with语句
  • The function does not contain any function closures
  • 该函数不能包含任何函数闭包
  • The function body contains less than 50 expressions
  • 该函数体不超过50条语句

开启内联注意事项:

  • 需要最新的flash builder 4.7 beta的ASC2.0来支持
  • 需要-inline编译选项开启内联
  • 需要[Inline]元数据使函数成为内联函数
  • final 或 static的getter setter函数会自动成为内联函数,而不需要[Inline]元数据

内联示例

package
{
    import flash.display.Sprite;

    public class InlineTest extends Sprite
    {
        private var _m:int = 0;
        private static var _s:int = 0;

        public function InlineTest()
        {

            trace(m); // inlined
            m = 5; //inlined
            InlineTest.s = 7; //inlined
            f0(0); //inlined
            f1(0); // not-inlined, 因为f1包含一条try语句
        }

        // 自动inline作为final getter, 而不必使用Inline元数据
        final public function get m():int
        {
            return _m;
        }

        // 自动inline作为final setter, 而不必使用Inline元数据
        final public function set m(m:int):void
        {
            if (m < 0)
                _m = m;
            else
                _m = 0;
        }

        // 自动inline作为static getter, 而不必使用Inline元数据
        static public function get s():int
        {
            return _s;
        }

        // 自动inline作为static setter, 而不必使用Inline元数据
        static public function set s(s:int):void
        {
            _s = s;
        }

        // 使用Inline元数据 内联final函数
        [Inline]
        final public function f0(p:int):int
        {
            var v:int = p + _m;
            return v;
        }

        // 不能使用Inline元数据内联包含try语句的方法
        //[Inline]
        final public function f1(p:int):int
        {
            try {
                return p + _m;
            } finally
            {
                return 0;
            }
        }

    }
}

bug

类中Inline的函数在类的外部调用时也展开了而不是当做普通函数调用.有两种情况可以解决这个问题.

  1. 在类的外部调用类中定义的inline的函数时,统一当做普通函数调用
  2. 在类的外部调用类中定义的inline的函数时,仅将函数体内调用了非public的方法或属性时当做普通函数调用

第一种情况是比较容易实现的,这也是gcc编译c++时使用的方法.而第二种相对复杂些,但是会带来更高的效率.

当前ASC2.0对inline的bug示例

package
{
    import flash.display.Sprite;

    public class InlineTest2 extends Sprite
    {
        public function InlineTest2()
        {
            //编译后会变成
            //var _local1 = A;
            //A._s; 
            //这里_s是A的private变量,但是也直接访问了.
            //这里应该不使用内联.而是方法调用
            A.getS();
        }
    }
}

class A
{
    private static var _s:int = 1;

    [Inline]
    static public function getS():int { return _s; }
}

2012年12月19日更新: 在release版本里用命名空间的方法修复了这个bug,不过通过反编译发现多用inline可以提高破解难度。

This post was last modified on 2019 年 03 月 04 日 00:29

This website uses cookies.