- Joined
- Feb 6, 2014
- Messages
- 2,466
All About Inlining:
Inlining is replacing the call site of a function or the lookup of a constant variable by its content making the code run faster since no function call or variable lookup actually takes place. It happens upon compiling the script (Function Inlining) or optimizing the map script (Constant Inlining).Contents
Function inlining is one of the features of vJASS Optimization allowing readable yet efficient code. However functions that get inlined still remain in the map script (even thought it is unused) so it still takes up space in the map script (unless Wc3 optimizer is used).
JassHelper Manual said:Function inlining will look for function calls that can be inlined and then just convert their calls to a direct usage of the function's contents.
Here are some rules regarding function inlining (as of JassHelper 0.A.2.B included in Jass New Gen Pack 2.0):
- The function must be a one-liner
JASS:function Inline1 takes integer i1, integer i2 returns integer return i1 + i2 endfunction function Inline2 takes integer i1, integer i2 returns integer local integer answer = 42 return i1 + i2 endfunction function I takes nothing returns nothing local integer i = Inline1(1, 2) local integer j = Inline2(1, 2) endfunction
JASS:function Inline1 takes integer i1,integer i2 returns integer return i1 + i2 endfunction function Inline2 takes integer i1,integer i2 returns integer local integer answer= 42 return i1 + i2 endfunction function I takes nothing returns nothing local integer i= ((1 ) + ( 2)) // INLINED!! local integer j= Inline2(1 , 2) endfunction
- BJ Functions don't get inlined, but custom functions that do the same thing get inlined
JASS:function UnitDamageTargetCustom takes unit whichUnit, unit target, real amount, attacktype whichAttack, damagetype whichDamage returns boolean return UnitDamageTarget(whichUnit, target, amount, true, false, whichAttack, whichDamage, WEAPON_TYPE_WHOKNOWS) endfunction function CosDeg takes real r returns real return Cos(r*bj_RADTODEG) endfunction function F takes nothing returns nothing local unit u1 local unit u2 local real r1 = CosBJ(42) local real r2 = CosDeg(42) call UnitDamageTargetBJ(u1, u2, 0, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL) call UnitDamageTargetCustom(u1, u2, 0, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL) endfunction
JASS:function UnitDamageTargetCustom takes unit whichUnit,unit target,real amount,attacktype whichAttack,damagetype whichDamage returns boolean return UnitDamageTarget(whichUnit, target, amount, true, false, whichAttack, whichDamage, WEAPON_TYPE_WHOKNOWS) endfunction function CosDeg takes real r returns real return Cos(r * bj_RADTODEG) endfunction function F takes nothing returns nothing local unit u1 local unit u2 local real r1= CosBJ(42) local real r2= (Cos(((42)*1.0) * bj_RADTODEG)) // INLINED!! call UnitDamageTargetBJ(u1, u2, 0, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL) call UnitDamageTarget((u1 ), ( u2 ), (( 0 )*1.0), true, false, ( ATTACK_TYPE_NORMAL ), ( DAMAGE_TYPE_NORMAL), WEAPON_TYPE_WHOKNOWS) // INLINED!! endfunction
(BJs are still not inlined but unused functions (UnitDamageTargetCustom and CosDeg) are removed
JASS:function F takes nothing returns nothing local unit u1 local unit u2 local real r1=CosBJ(42) local real r2=(Cos(((42)*1.)*bj_RADTODEG)) call UnitDamageTargetBJ(u1,u2,0,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL) call UnitDamageTarget((u1),(u2),((0)*1.),true,false,(ATTACK_TYPE_NORMAL),(DAMAGE_TYPE_NORMAL),WEAPON_TYPE_WHOKNOWS) endfunction
- The order of the input arguments must match how they appear in the custom function
JASS://Correct order function Inline1 takes integer i1, integer i2 returns integer return i1 + i2 endfunction //Incorrect order function Inline2 takes integer i1, integer i2 returns integer return i2 + i1 endfunction function I takes nothing returns nothing local integer i = Inline1(1, 2) local integer j = Inline2(1, 2) endfunction
JASS://Correct order function Inline1 takes integer i1,integer i2 returns integer return i1 + i2 endfunction //Incorrect order function Inline2 takes integer i1,integer i2 returns integer return i2 + i1 endfunction function I takes nothing returns nothing local integer i= ((1 ) + ( 2)) // INLINED!! local integer j= Inline2(1 , 2) endfunction
- Each argument must only appear once in the function.
JASS://Correct way function Inline1 takes integer i1, integer i2 returns real return 3*i1 + 5.0*i2 endfunction //Incorrect way function Inline2 takes integer i1, integer i2 returns real return i1 + 2*i1 + 5.0*i2 endfunction function I takes nothing returns nothing local real r1 = Inline1(1, 2) local real r2 = Inline2(1, 2) endfunction
JASS://Correct way function Inline1 takes integer i1,integer i2 returns real return 3 * i1 + 5.0 * i2 endfunction //Incorrect way function Inline2 takes integer i1,integer i2 returns real return i1 + 2 * i1 + 5.0 * i2 endfunction function I takes nothing returns nothing local real r1= (3 * (1 ) + 5.0 * ( 2)) // INLINED!! local real r2= Inline2(1 , 2) endfunction
- Directly setting a variable also gets inlined, but it must not take any input argument nor it must not assign one of its argument
JASS://Inlining setting a variable with unused input argument //Won't get inlined function Inline1 takes integer i returns nothing set global = 42 //a global variable endfunction //Inlining setting a variable with no input argument //Will get inlined function Inline2 takes nothing returns nothing set global = 42 //a global variable endfunction function F takes nothing returns nothing call Inline1(1) call Inline2() endfunction
JASS://Inlining setting a variable with unused input argument //Won't get inlined function Inline1 takes integer i returns nothing set global=42 //a global variable endfunction //Inlining setting a variable with no input argument //Will get inlined function Inline2 takes nothing returns nothing set global=42 //a global variable endfunction function F takes nothing returns nothing call Inline1(1) set global=42 // INLINED!! endfunction
- Directly calling another function also gets inlined
JASS://Directly calling a function with no input argument //Will get inlined function Inline1 takes real r returns nothing call SetWidgetLife(globalUnit, r) endfunction //Directly calling a function with no input argument //Will get inlined function Inline2 takes nothing returns nothing call SetWidgetLife(globalUnit, 42) endfunction //Directly calling a function with unused input argument //Will not get inlined function Inline3 takes real r returns nothing call SetWidgetLife(globalUnit, 42) endfunction //Calling an inlining function //Will get inlined function Inline4 takes nothing returns nothing call Inline2() endfunction function F takes nothing returns nothing call Inline1(1) call Inline2() call Inline3(1) call Inline4() endfunction
JASS://Directly calling a function with no input argument //Will get inlined function Inline1 takes real r returns nothing call SetWidgetLife(globalUnit, r) endfunction //Directly calling a function with no input argument //Will get inlined function Inline2 takes nothing returns nothing call SetWidgetLife(globalUnit, 42) endfunction //Directly calling a function with unused input argument //Will not get inlined function Inline3 takes real r returns nothing call SetWidgetLife(globalUnit, 42) endfunction //Calling an inlining function //Will get inlined function Inline4 takes nothing returns nothing call SetWidgetLife(globalUnit, 42) // INLINED!! endfunction function F takes nothing returns nothing call SetWidgetLife(globalUnit, ((1)*1.0)) // INLINED!! call SetWidgetLife(globalUnit, 42) // INLINED!! call Inline3(1) call SetWidgetLife(globalUnit, 42) // INLINED!! endfunction
- Functions which contains other function calls must have all its input argument evaluated first before the function call.
JASS://Function call after input arguments function Inline1 takes unit u, real x returns nothing call SetUnitPosition(u, x, Sin(42)) endfunction //Function call before input arguments function Inline2 takes real x, real y returns nothing call SetUnitPosition(GetTriggerUnit(), x, y) endfunction function F takes nothing returns nothing local unit u1 call Inline1(u1, 1) call Inline2(1, 2) endfunction
JASS://Function call after input arguments function Inline1 takes unit u,real x returns nothing call SetUnitPosition(u, x, Sin(42)) endfunction //Function call before input arguments function Inline2 takes real x,real y returns nothing call SetUnitPosition(GetTriggerUnit(), x, y) endfunction function F takes nothing returns nothing local unit u1 call SetUnitPosition((u1 ), (( 1)*1.0), Sin(42)) // INLINED!! call Inline2(1 , 2) endfunction
Part 2: Constants Variables
Constant variables are different from normal variables because they can be inlined when the script is optimized by Wc3mapoptimizer 5.0 therefore it does not take any RAM because no variable exists and it is faster than normal variables because no variable lookup takes place. The speed gain may not be noticeable, however the optimized map script will have significantly lesser file size. As the name suggest, it holds a constant value so you cannot change its value (it will throw an error in an attempt to change its value).
Wc3 Map Optimizer Read Me said:Constant inlining: This method inlines constant variables and some of the constant functions in order to save size (most of the times) but the bigger impact is an improvement in performance, although this method will not have any impact unless you use some advanced Jass spells or systems.
Inlining constant variables has a simple rule:
- Constants that needs to be evaluated doesn't get inlined.
JASS:library L initializer F globals constant integer INT1 = 42 constant integer INT2 = 42 + 73 constant real REAL1 = 2.718281828 constant real REAL2 = 1/32 constant real REAL3 = 1*2*3*4 constant real REAL4 = Sin(bj_PI/2) constant string STRING1 = "A constant string" constant string STRING2 = SubString("12345", 0, 3) constant boolean BOOL1 = true constant boolean BOOL2 = (42 == 72) constant boolean BOOL3 = true or false //static if will not work because of 'or' operation constant boolean BOOL4 = false and false endglobals function F takes nothing returns nothing local integer i1 = INT1 local integer i2 = INT2 local real r1 = REAL1 local real r2 = REAL2 local real r3 = REAL3 local real r4 = REAL4 local string s1 = STRING1 local string s2 = STRING2 local boolean b1 = BOOL1 local boolean b2 = BOOL2 local boolean b3 = BOOL3 //However BOOL2 and BOOL4 still works with static ifs static if not BOOL2 then call BJDebugMsg("BOOL2 static if works correctly") endif static if BOOL3 then call BJDebugMsg("BOOL3 static if works correctly") endif static if not BOOL4 then call BJDebugMsg("BOOL4 static if works correctly") endif endfunction endlibrary
JASS:globals constant integer e=42+73 constant real x=1/ 32 constant real o=1*2*3*4 constant real i=Sin(bj_PI/ 2) constant string a=SubString("12345",0,3) constant boolean n=42==72 constant boolean V=true or false trigger E=null real R=.0 real I=.0 boolexpr b=null endglobals //... function F takes nothing returns nothing local integer i1=42 local integer i2=e local real r1=2.718281828 local real r2=x local real r3=o local real r4=i local string s1="A constant string" local string s2=a local boolean b1=true local boolean b2=n local boolean b3=V call BJDebugMsg("BOOL2 static if works correctly") call BJDebugMsg("BOOL4 static if works correctly") endfunction
The Wc3 map optimizer generated script shows that constants containing arithmetic operation, boolean expression, comparison or functions calls doesn't get inlined. Since other variables types (e.g. widgets, players, trigger) cannot be initialized without a function call, they cannot be inlined. Thecode
variable cannot also be used as a constant (constant variables must be initialized with a value) because it will throw an undefined function error since theglobals endglobals
block is placed at the top most part of the script.
To inline constant variables, the 'Optimized Script' option must be checked (enabled) and the constant inlining script optimization feature must unchecked (enabled).
Script Optimization Tweaks
Attachments
Last edited by a moderator: