【Unity优化】我所理解的IL指令
版权声明:本文为博主原创文章,欢迎转载。请保留博主链接:http://blog.csdn.net/andrewfan
指令格式 | 英文单词全写 | 指令解释 |
---|---|---|
nop | no operation performed | 不做任何操作,留待后续版本补齐此操作码功能 |
ldc.i4 num | load const | 将操作常数数num推送到计算堆栈. 其中i4代表int32常数,栈顶结果为int32; ldc.i8,代表推送int64常数,结果为int64; ldc.i4.s,代表推送int8,结果为int32; ldc.i4.m1,代表推送-1(minus 1),结果为int32; ldc.r4,代表推送float32,结果为float32; ldc.r8,代表推送float64,结果为float64; |
ldloc n | load local | 加载第n个本地变量到计算堆栈; ldloc.n,n取0~3,代表加载n处的本地变量; ldloc.s n,短格式,针对0~255之间数值,更高效; |
ldloca index | load local | 加载第n个本地变量的地址到计算堆栈; ldloca.s 短格式 |
stloc.n | stack local | 弹出计算堆栈上的栈顶元素,存储到本地变量列表(即调用堆栈)的第n个位置,即赋值给第n个局部变量(函数参数也被编译为局部变量) |
box valTypeToken | box | 装箱,将值类型封装成valTypeToken指定的对象类型,流程是,弹出计算堆栈上的值类型参数,并使用新建立的一个引用类型对象进行并包装,将包装结果返回计算堆栈。本过程产生GC Alloc。 |
unbox valType | unbox | 拆箱,将引用类型转换成相应值类型valType,流程是,弹出计算堆栈上的引用类型参数,并执行拆箱转换,将转换完成的值类型结果推送回计算堆栈 |
unbox.any typeTok | unbox any | 拆箱,将引用类型转换成相应值类型或者引用类型typeTok,流程与unbox相同,差别是,如果typeTok是值类型,则与unbox相同;如果typeTok是引用类型,则与castclass相同,即执行类型转换 |
castclass classT | cast class | 强制类型转换,流程是,将计算堆栈上的参数弹出,并验证其是否是继承了classT指定的class,或者实现于classT指定的接口,如果不是,则引发转换异常;如果转换正常,则把转换后的结果引用返回;如果当前的参数本身是null,则也返回null |
initobj typeTok | init object | 将当前计算堆栈栈顶单元视为某个值类型对象的地址,调用值类型typeTok的初始化方法,将此地址指向的值类型单元置为0,与newobj指令不同 ,initobj不调用构造函数方法。 |
call methodDesc | call method description | 应用于早绑定的函数调用,即它不会考虑函数重载。在函数调用之前,传递的参数应该已经被压到计算堆栈上,此时执行call指令,执行完成之后,将会执行ret指令,并将返回值存储到计算堆栈。 |
callvirt method | call method | 应用于晚绑定的函数调用,即它会计算函数重载。除此之外,其运行步骤与call相同。【每个函数调用起始,都会有2句话max stack …;.locals init(…),是否是由它们弹出当前计算堆栈上的参数,并存放到当前的局部变量列表(Call Stack)中,所以在返回时,不用关心之前压入参数占据堆栈单元的问题?】 |
ret | return | 从当前函数返回,并且将返回值从当前函数的计算堆栈推送到调用者函数的计算堆栈 |
newobj ctor | new object constructor | 创建一个新引用类型或者值类型对象实例,并将创建出来的引用压入计算堆栈,并调用其后面跟随的ctor构造函数。如果当前创建的是值类型对象,那么它压入当前堆栈的是内存地址位于当前堆栈上的对象引用。当应用于引用类型时,此方法会产生GCAlloc。 |
需要注意以下几点:
- 所有的对象类型继承自System.Object类,所有的值类型继承自System.ValueType类。
- 不是所有的newobj 指令都会产生新的GC Alloc。当它应用值类型时,就会在当前计算堆栈上构建Object,而不需要存放至堆。
- 不是所有的new A() 代码,都会被翻译成IL中的newobj指令。当A是对象类型时,一定转换成newobj;当A时值类型时,就有可能转换成newobj,也有可能转换成initobj,取决于是否需要执行构造函数。
- box指令,即装箱指令,是将值类型封装成对象类型的一个过程。必然产生新的GC Alloc。