User:Pedro Oval/Mono code memory usage/CIL
Jump to navigation
Jump to search
Here's the CIL code generated by the script below, which gives some insight of what's happening under the hood.
Compilation was done using the viewer's built-in compiler as suggested by User:Becky Pippen/LSL Performance. Assembly was done using ilasm from the Mono suite.
Script that gets compiled:
integer i;
u(){}
default
{
state_entry()
{
integer x;
integer y = 0;
integer z;
float f;
float g;
vector v;
list a;
;;;;;;;;;{{{{{{{{}}}}}}}}
return;
x;
(x);
(integer)x;
(float)x;
f;
(float)f;
(integer)f;
v;
v.z;
-x;
~x;
!x;
--x;
++x;
x--;
x++;
x=y;
x==y;
x=y=z;
f=x;
f=(float)x;
x!=y;
x+y;
x-y;
x+-y;
x*y;
x/y;
x%y;
x&y;
x&&y;
x|y;
x||y;
x^y;
x<<y;
x>>y;
x<y;
x>y;
x<=y;
x>=y;
x+=y;
x-=y;
x+=-y;
x*=y;
x/=y;
x%=y;
if (x) ;
if (x) ; else ;
0;
x^x;
1;
-1;
0xffffffff;
ALL_SIDES;
x|~x;
x+1;
-~x;
x-1;
x+-1;
~-x;
x*y+y-1;
(x+1)*y-1;
~(~x*y)
while (x) ;
do ; while (x);
for (;x;) ;
@label; if (x) jump label;
0.0;
f=0.0;
f=0;
<0.0, 0.0, 0.0>;
ZERO_VECTOR;
<0, 0, 0>;
<-1.0, -1.0, 0.0>;
TOUCH_INVALID_TEXCOORD;
<-1, -1, 0>;
<0xffffffff, 0xffffffff, 0>;
v+v;
v-v;
v*v;
v%v;
[];
a=[];
a+[x];
a+x;
[x]+a;
x+a;
[x];
[]+x;
(list)x;
[x,y];
[]+x+y;
(string)a;
i;
u();
}
}
Compiled and annotated result:
.assembly extern mscorlib {.ver 1:0:5000:0}
.assembly extern LslLibrary {.ver 0:1:0:0}
.assembly extern LslUserScript {.ver 0:1:0:0}
.assembly extern ScriptTypes {.ver 0:1:0:0}
.assembly 'LSL_y' {.ver 0:0:0:0}
.class public auto ansi serializable beforefieldinit LSL_y extends [LslUserScript]LindenLab.SecondLife.LslUserScript
{
.field public int32 'i'
.method public hidebysig specialname rtspecialname instance default void .ctor () cil managed
{
.maxstack 500
// Globals initialization
// integer i;
02 ldarg.0
16 ldc.i4.0
7D 01 00 00 04 stfld int32 LSL_y::'i'
02 ldarg.0
28 01 00 00 0A call instance void [LslUserScript]LindenLab.SecondLife.LslUserScript::.ctor()
2A ret
}
.method public hidebysig instance default void 'gu'() cil managed
{
.maxstack 500
2A ret
}
.method public hidebysig instance default void edefaultstate_entry() cil managed
{
.maxstack 500
.locals init (int32, int32, int32, float32, float32, class [ScriptTypes]LindenLab.SecondLife.Vector, class [mscorlib]System.Collections.ArrayList)
// integer x;
16 ldc.i4.0
13 00 stloc.s 0
// integer y = 0;
20 00 00 00 00 ldc.i4 0
13 01 stloc.s 1
// integer z;
16 ldc.i4.0
13 02 stloc.s 2
// float f;
23 00 00 00 00 ldc.r8 0
00 00 00 00
13 03 stloc.s 3
// float g;
23 00 00 00 00 ldc.r8 0
00 00 00 00
13 04 stloc.s 4
// vector v;
23 00 00 00 00 ldc.r8 0
00 00 00 00
23 00 00 00 00 ldc.r8 0
00 00 00 00
23 00 00 00 00 ldc.r8 0
00 00 00 00
28 02 00 00 0A call class [ScriptTypes]LindenLab.SecondLife.Vector class [LslUserScript]LindenLab.SecondLife.LslUserScript::'CreateVector'(float32, float32, float32)
13 05 stloc.s 5
// list a;
28 03 00 00 0A call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::CreateList()
13 06 stloc.s 6
// ;;; {{{ }}} generate no code
// return;
2A ret
// x;
11 00 ldloc.s 0
26 pop
// (x);
11 00 ldloc.s 0
26 pop
// (integer)x;
11 00 ldloc.s 0
26 pop
// (float)x;
11 00 ldloc.s 0
6C conv.r8
26 pop
// f;
11 03 ldloc.s 3
26 pop
// (float)f;
11 03 ldloc.s 3
26 pop
// (integer)f;
11 03 ldloc.s 3
28 04 00 00 0A call int32 [LslLibrary]LindenLab.SecondLife.LslRunTime::ToInteger(float32)
26 pop
// v;
11 05 ldloc.s 5
26 pop
// v.z;
12 05 ldloca.s 5
78 05 00 00 0A ldfld float32 class [ScriptTypes]LindenLab.SecondLife.Vector::z
26 pop
// -x;
11 00 ldloc.s 0
65 neg
26 pop
// ~x;
11 00 ldloc.s 0
66 not
26 pop
// !x;
11 00 ldloc.s 0
16 ldc.i4.0
FE 01 ceq
26 pop
// --x;
11 00 ldloc.s 0
17 ldc.i4.1
59 sub
25 dup
13 00 stloc.s 0
26 pop
// ++x;
11 00 ldloc.s 0
17 ldc.i4.1
58 add
25 dup
13 00 stloc.s 0
26 pop
// x--;
11 00 ldloc.s 0
11 00 ldloc.s 0
17 ldc.i4.1
59 sub
25 dup
13 00 stloc.s 0
26 pop
26 pop
// x++;
11 00 ldloc.s 0
11 00 ldloc.s 0
17 ldc.i4.1
58 add
25 dup
13 00 stloc.s 0
26 pop
26 pop
// x = y;
11 01 ldloc.s 1
25 dup
13 00 stloc.s 0
26 pop
// x == y;
11 01 ldloc.s 1
11 00 ldloc.s 0
FE 01 ceq
26 pop
// x = y = z;
11 02 ldloc.s 2
25 dup
13 01 stloc.s 1
25 dup
13 00 stloc.s 0
26 pop
// f = x;
11 00 ldloc.s 0
6C conv.r8
25 dup
13 03 stloc.s 3
26 pop
// f = (float)x;
11 00 ldloc.s 0
6C conv.r8
25 dup
13 03 stloc.s 3
26 pop
// x != y; implemented as: !(x==y)
11 01 ldloc.s 1 // this part is x == y
11 00 ldloc.s 0
FE 01 ceq
16 ldc.i4.0 // this part is 'not'
FE 01 ceq
26 pop
// x + y;
11 01 ldloc.s 1
11 00 ldloc.s 0
58 add
26 pop
// x - y;
11 01 ldloc.s 1
11 00 ldloc.s 0
28 06 00 00 0A call int32 [LslUserScript]LindenLab.SecondLife.LslUserScript::Subtract(int32, int32)
26 pop
// x + -y;
11 01 ldloc.s 1
65 neg
11 00 ldloc.s 0
58 add
26 pop
// x * y;
11 01 ldloc.s 1
11 00 ldloc.s 0
5A mul
26 pop
// x / y;
11 01 ldloc.s 1
11 00 ldloc.s 0
28 07 00 00 0A call int32 [LslUserScript]LindenLab.SecondLife.LslUserScript::Divide(int32, int32)
26 pop
// x % y;
11 01 ldloc.s 1
11 00 ldloc.s 0
28 08 00 00 0A call int32 [LslUserScript]LindenLab.SecondLife.LslUserScript::Modulo(int32, int32)
26 pop
// x & y;
11 01 ldloc.s 1
11 00 ldloc.s 0
5F and
26 pop
// x && y; implemented as: !(!x | !y)
11 01 ldloc.s 1 // !x
16 ldc.i4.0
FE 01 ceq
11 00 ldloc.s 0 // !y
16 ldc.i4.0
FE 01 ceq
60 or // !x | !y
16 ldc.i4.0 // !(!x | !y)
FE 01 ceq
26 pop
// x | y;
11 01 ldloc.s 1
11 00 ldloc.s 0
60 or
26 pop
// x || y; implemented as: !!(x | y)
11 01 ldloc.s 1 // x | y
11 00 ldloc.s 0
60 or
16 ldc.i4.0 // !(x | y)
FE 01 ceq
16 ldc.i4.0 // !!(x | y)
FE 01 ceq
26 pop
// x ^ y;
11 01 ldloc.s 1
11 00 ldloc.s 0
61 xor
26 pop
// x << y;
11 01 ldloc.s 1
11 00 ldloc.s 0
28 09 00 00 0A call int32 [LslUserScript]LindenLab.SecondLife.LslUserScript::ShiftLeft(int32, int32)
26 pop
// x >> y;
11 01 ldloc.s 1
11 00 ldloc.s 0
28 0A 00 00 0A call int32 [LslUserScript]LindenLab.SecondLife.LslUserScript::ShiftRight(int32, int32)
26 pop
// x < y; implemented as: y > x
11 01 ldloc.s 1
11 00 ldloc.s 0
FE 02 cgt
26 pop
// x > y; implemented as: y < x;
11 01 ldloc.s 1
11 00 ldloc.s 0
FE 04 clt
26 pop
// x <= y; implemented as: !(y < x)
11 01 ldloc.s 1
11 00 ldloc.s 0
FE 04 clt
16 ldc.i4.0
FE 01 ceq
26 pop
// x >= y; implemented as: !(y > x)
11 01 ldloc.s 1
11 00 ldloc.s 0
FE 02 cgt
16 ldc.i4.0
FE 01 ceq
26 pop
// x += y;
11 01 ldloc.s 1
11 00 ldloc.s 0
58 add
25 dup
13 00 stloc.s 0
26 pop
// x -= y;
11 01 ldloc.s 1
11 00 ldloc.s 0
28 06 00 00 0A call int32 [LslUserScript]LindenLab.SecondLife.LslUserScript::Subtract(int32, int32)
25 dup
13 00 stloc.s 0
26 pop
// x += -y;
11 01 ldloc.s 1
65 neg
11 00 ldloc.s 0
58 add
25 dup
13 00 stloc.s 0
26 pop
// x *= y;
11 01 ldloc.s 1
11 00 ldloc.s 0
5A mul
25 dup
13 00 stloc.s 0
26 pop
// x /= y;
11 01 ldloc.s 1
11 00 ldloc.s 0
28 07 00 00 0A call int32 [LslUserScript]LindenLab.SecondLife.LslUserScript::Divide(int32, int32)
25 dup
13 00 stloc.s 0
26 pop
// x %= y;
11 01 ldloc.s 1
11 00 ldloc.s 0
28 08 00 00 0A call int32 [LslUserScript]LindenLab.SecondLife.LslUserScript::Modulo(int32, int32)
25 dup
13 00 stloc.s 0
26 pop
// if (x) ;
11 00 ldloc.s 0
39 00 00 00 00 brfalse LabelTempJump0
// THEN branch code goes here
LabelTempJump0:
// if (x) ; else ;
11 00 ldloc.s 0
39 05 00 00 00 brfalse LabelTempJump1
// THEN branch code would go here
38 00 00 00 00 br LabelTempJump2
// ELSE branch code would go here
LabelTempJump1:
LabelTempJump2:
// 0;
20 00 00 00 00 ldc.i4 0
26 pop
// x ^ x;
11 00 ldloc.s 0
11 00 ldloc.s 0
61 xor
26 pop
// 1;
20 01 00 00 00 ldc.i4 1
26 pop
// -1; note the negative sign takes code memory
20 01 00 00 00 ldc.i4 1
65 neg
26 pop
// 0xffffffff; note it equals -1 without the sign taking memory
20 FF FF FF FF ldc.i4 -1
26 pop
// ALL_SIDES; ditto
20 FF FF FF FF ldc.i4 -1
26 pop
// x | ~x;
11 00 ldloc.s 0
66 not
11 00 ldloc.s 0
60 or
26 pop
// x + 1;
20 01 00 00 00 ldc.i4 1
11 00 ldloc.s 0
58 add
26 pop
// -~x;
11 00 ldloc.s 0
66 not
65 neg
26 pop
// x - 1;
20 01 00 00 00 ldc.i4 1
11 00 ldloc.s 0
28 06 00 00 0A call int32 [LslUserScript]LindenLab.SecondLife.LslUserScript::Subtract(int32, int32)
26 pop
// x + -1;
20 01 00 00 00 ldc.i4 1
65 neg
11 00 ldloc.s 0
58 add
26 pop
// ~-x;
11 00 ldloc.s 0
65 neg
66 not
26 pop
// x*y + y - 1;
20 01 00 00 00 ldc.i4 1
11 01 ldloc.s 1
11 01 ldloc.s 1
11 00 ldloc.s 0
5A mul
58 add
28 06 00 00 0A call int32 [LslUserScript]LindenLab.SecondLife.LslUserScript::Subtract(int32, int32)
26 pop
// (x + 1)*y - 1;
20 01 00 00 00 ldc.i4 1
11 01 ldloc.s 1
20 01 00 00 00 ldc.i4 1
11 00 ldloc.s 0
58 add
5A mul
28 06 00 00 0A call int32 [LslUserScript]LindenLab.SecondLife.LslUserScript::Subtract(int32, int32)
26 pop
// ~(~x*y);
11 01 ldloc.s 1
11 00 ldloc.s 0
66 not
5A mul
66 not
26 pop
// while (x) ;
LabelTempJump3:
11 00 ldloc.s 0
39 05 00 00 00 brfalse LabelTempJump4
// Looped code would go here
38 F4 FF FF FF br LabelTempJump3
LabelTempJump4:
// do ; while (x);
LabelTempJump5:
// Looped code would go here
11 00 ldloc.s 0
3A F9 FF FF FF brtrue LabelTempJump5
// for (; x; ) ;
LabelTempJump6:
11 00 ldloc.s 0
39 05 00 00 00 brfalse LabelTempJump7
// Looped code would go here
38 F4 FF FF FF br LabelTempJump6
LabelTempJump7:
// @label; if (x) jump label;
'label':
// Looped code would go here
11 00 ldloc.s 0
39 05 00 00 00 brfalse LabelTempJump8
38 F4 FF FF FF br 'label'
LabelTempJump8:
// 0.0;
23 00 00 00 00 ldc.r8 (00 00 00 00 00 00 00 00)
00 00 00 00
26 pop
// f = 0.0;
23 00 00 00 00 ldc.r8 (00 00 00 00 00 00 00 00)
00 00 00 00
25 dup
13 03 stloc.s 3
26 pop
// f = 0;
20 00 00 00 00 ldc.i4 0
6C conv.r8
25 dup
13 03 stloc.s 3
26 pop
// <0.0, 0.0, 0.0>;
23 00 00 00 00 ldc.r8 (00 00 00 00 00 00 00 00)
00 00 00 00
23 00 00 00 00 ldc.r8 (00 00 00 00 00 00 00 00)
00 00 00 00
23 00 00 00 00 ldc.r8 (00 00 00 00 00 00 00 00)
00 00 00 00
28 02 00 00 0A call class [ScriptTypes]LindenLab.SecondLife.Vector class [LslUserScript]LindenLab.SecondLife.LslUserScript::'CreateVector'(float32, float32, float32)
26 pop
// ZERO_VECTOR;
23 00 00 00 00 ldc.r8 (00 00 00 00 00 00 00 00)
00 00 00 00
23 00 00 00 00 ldc.r8 (00 00 00 00 00 00 00 00)
00 00 00 00
23 00 00 00 00 ldc.r8 (00 00 00 00 00 00 00 00)
00 00 00 00
28 02 00 00 0A call class [ScriptTypes]LindenLab.SecondLife.Vector class [LslUserScript]LindenLab.SecondLife.LslUserScript::'CreateVector'(float32, float32, float32)
26 pop
// <0, 0, 0>;
20 00 00 00 00 ldc.i4 0
6C conv.r8
20 00 00 00 00 ldc.i4 0
6C conv.r8
20 00 00 00 00 ldc.i4 0
6C conv.r8
28 02 00 00 0A call class [ScriptTypes]LindenLab.SecondLife.Vector class [LslUserScript]LindenLab.SecondLife.LslUserScript::'CreateVector'(float32, float32, float32)
26 pop
// <-1.0, -1.0, 0.0>;
23 00 00 00 00 ldc.r8 (00 00 00 00 00 00 f0 3f)
00 00 F0 3F
65 neg
23 00 00 00 00 ldc.r8 (00 00 00 00 00 00 f0 3f)
00 00 F0 3F
65 neg
23 00 00 00 00 ldc.r8 (00 00 00 00 00 00 00 00)
00 00 00 00
28 02 00 00 0A call class [ScriptTypes]LindenLab.SecondLife.Vector class [LslUserScript]LindenLab.SecondLife.LslUserScript::'CreateVector'(float32, float32, float32)
26 pop
// TOUCH_INVALID_TEXCOORD;
23 00 00 00 00 ldc.r8 (00 00 00 00 00 00 f0 bf)
00 00 F0 BF
23 00 00 00 00 ldc.r8 (00 00 00 00 00 00 f0 bf)
00 00 F0 BF
23 00 00 00 00 ldc.r8 (00 00 00 00 00 00 00 00)
00 00 00 00
28 02 00 00 0A call class [ScriptTypes]LindenLab.SecondLife.Vector class [LslUserScript]LindenLab.SecondLife.LslUserScript::'CreateVector'(float32, float32, float32)
26 pop
// <-1, -1, 0>;
20 01 00 00 00 ldc.i4 1
65 neg
6C conv.r8
20 01 00 00 00 ldc.i4 1
65 neg
6C conv.r8
20 00 00 00 00 ldc.i4 0
6C conv.r8
28 02 00 00 0A call class [ScriptTypes]LindenLab.SecondLife.Vector class [LslUserScript]LindenLab.SecondLife.LslUserScript::'CreateVector'(float32, float32, float32)
26 pop
// <0xffffffff, 0xffffffff, 0>;
20 FF FF FF FF ldc.i4 -1
6C conv.r8
20 FF FF FF FF ldc.i4 -1
6C conv.r8
20 00 00 00 00 ldc.i4 0
6C conv.r8
28 02 00 00 0A call class [ScriptTypes]LindenLab.SecondLife.Vector class [LslUserScript]LindenLab.SecondLife.LslUserScript::'CreateVector'(float32, float32, float32)
26 pop
// v + v;
11 05 ldloc.s 5
11 05 ldloc.s 5
28 0B 00 00 0A call class [ScriptTypes]LindenLab.SecondLife.Vector class [LslUserScript]LindenLab.SecondLife.LslUserScript::'Add'(class [ScriptTypes]LindenLab.SecondLife.Vector, class [ScriptTypes]LindenLab.SecondLife.Vector)
26 pop
// v - v;
11 05 ldloc.s 5
11 05 ldloc.s 5
28 0C 00 00 0A call class [ScriptTypes]LindenLab.SecondLife.Vector class [LslUserScript]LindenLab.SecondLife.LslUserScript::'Subtract'(class [ScriptTypes]LindenLab.SecondLife.Vector, class [ScriptTypes]LindenLab.SecondLife.Vector)
26 pop
// v * v;
11 05 ldloc.s 5
11 05 ldloc.s 5
28 0D 00 00 0A call float32 class [LslUserScript]LindenLab.SecondLife.LslUserScript::'Multiply'(class [ScriptTypes]LindenLab.SecondLife.Vector, class [ScriptTypes]LindenLab.SecondLife.Vector)
26 pop
// v % v;
11 05 ldloc.s 5
11 05 ldloc.s 5
28 0E 00 00 0A call class [ScriptTypes]LindenLab.SecondLife.Vector class [LslUserScript]LindenLab.SecondLife.LslUserScript::'Modulo'(class [ScriptTypes]LindenLab.SecondLife.Vector, class [ScriptTypes]LindenLab.SecondLife.Vector)
26 pop
// [];
28 03 00 00 0A call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::CreateList()
26 pop
// a = [];
28 03 00 00 0A call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::CreateList()
25 dup
13 06 stloc.s 6
26 pop
// a + [x];
11 00 ldloc.s 0
8C 01 00 00 1B box [mscorlib]System.Int32
28 03 00 00 0A call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::CreateList()
28 0F 00 00 0A call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::Prepend(object, class [mscorlib]System.Collections.ArrayList)
11 06 ldloc.s 6
28 10 00 00 0A call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::Append(class [mscorlib]System.Collections.ArrayList, class [mscorlib]System.Collections.ArrayList)
26 pop
// a + x;
11 00 ldloc.s 0
11 06 ldloc.s 6
28 11 00 00 0A call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::Append(int32, class [mscorlib]System.Collections.ArrayList)
26 pop
// [x] + a;
11 06 ldloc.s 6
11 00 ldloc.s 0
8C 01 00 00 1B box [mscorlib]System.Int32
28 03 00 00 0A call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::CreateList()
28 0F 00 00 0A call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::Prepend(object, class [mscorlib]System.Collections.ArrayList)
28 10 00 00 0A call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::Append(class [mscorlib]System.Collections.ArrayList, class [mscorlib]System.Collections.ArrayList)
26 pop
// x + a;
11 06 ldloc.s 6
11 00 ldloc.s 0
8C 01 00 00 1B box [mscorlib]System.Int32
28 12 00 00 0A call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::Prepend(class [mscorlib]System.Collections.ArrayList, object)
26 pop
// [x];
11 00 ldloc.s 0
8C 01 00 00 1B box [mscorlib]System.Int32
28 03 00 00 0A call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::CreateList()
28 0F 00 00 0A call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::Prepend(object, class [mscorlib]System.Collections.ArrayList)
26 pop
// []+x;
11 00 ldloc.s 0
28 03 00 00 0A call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::CreateList()
28 11 00 00 0A call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::Append(int32, class [mscorlib]System.Collections.ArrayList)
26 pop
// (list)x;
11 00 ldloc.s 0
8C 01 00 00 1B box [mscorlib]System.Int32
28 13 00 00 0A call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::CreateList(object)
26 pop
// [x, y];
11 00 ldloc.s 0
8C 01 00 00 1B box [mscorlib]System.Int32
11 01 ldloc.s 1
8C 01 00 00 1B box [mscorlib]System.Int32
28 03 00 00 0A call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::CreateList()
28 0F 00 00 0A call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::Prepend(object, class [mscorlib]System.Collections.ArrayList)
28 0F 00 00 0A call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::Prepend(object, class [mscorlib]System.Collections.ArrayList)
26 pop
// []+x+y;
11 01 ldloc.s 1
11 00 ldloc.s 0
28 03 00 00 0A call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::CreateList()
28 11 00 00 0A call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::Append(int32, class [mscorlib]System.Collections.ArrayList)
28 11 00 00 0A call class [mscorlib]System.Collections.ArrayList class [LslUserScript]LindenLab.SecondLife.LslUserScript::Append(int32, class [mscorlib]System.Collections.ArrayList)
26 pop
// (string)a;
11 06 ldloc.s 6
28 14 00 00 0A call string [LslLibrary]LindenLab.SecondLife.LslRunTime::ListToString(class [mscorlib]System.Collections.ArrayList)
26 pop
// i;
02 ldarg.0
7B 01 00 00 04 ldfld int32 LSL_y::'i'
26 pop
// u();
02 ldarg.0
28 02 00 00 06 call instance void class LSL_y::'gu'()
// end of event
2A ret
}
}
Important notes:
ldloc.s 0(opcode 11, argument 00) is probably contracted to the abbreviationldloc.0(opcode 06) at assembly time, resulting in the length of 2 obtained in the memory usage tests. Or possibly the server-side compiler added an optimization of this case (!). Either way, the evidence for this is confirmed by the fact thatx;takes 2 bytes if it's one of the first four local variables (there are 1-byte opcodes for ldloc.0 through ldloc.3), and 3 bytes otherwise. This applies to all appearances of this opcode and the similarstloc.s.- Local variable definitions seem to take a variable and big number of bytes (averaging about 47 bytes for local integers) if there is a function call anywhere in the event in which they are defined. Reason unknown.
- Backward jumps seem to take many more bytes than what the CIL result above suggests. Forward jumps, however, seem predictable enough.
- As things are now, having more than 256 local variables in a single function or event causes wraparound, making the 257th be an alias to the 1st, and so on. If they aren't the same type, the script crashes at runtime with an uncaught exception. That's a consequence of using
ldloc.s/stloc.swithout switching to the long version (ldloc/stloc) when the argument is greater than 255.
Additional memory usage notes:
- Global variable, function, and function parameter names do take code memory from the script (as part of some symbol table). Fortunately they take 1 byte per character only, as opposed to Mono strings, which take at least 2 bytes per character (they are UTF-16). That extra code is only taken once per variable, regardless of how many times it is used.
- In addition to the state code and state change command code, the state names themselves take code memory from the script, as follows:
- The state name by itself takes no code memory, but internally, each event name includes the state name. The internal name for the event is e.g.
edefaultstate_entry(for statedefault, eventstate_entry),eblahtimer(for state blah, eventtimer). These names take 1 byte per character. - If a state switch statement appears in the code, the state name takes additionally 2 bytes per character. (But these strings are reused, so multiple state switch statements don't take additional space for the strings.)
- The state name by itself takes no code memory, but internally, each event name includes the state name. The internal name for the event is e.g.
Although not mentioned above, every single-byte string needs an additional terminating zero byte, and every UTF-16 string needs an additional length prefix byte (or more if longer than 127 bytes, i.e. 63 characters if in the ASCII range) plus an additional terminating zero byte.