LSL Hacks

Hacks

A page dedicated to LSL Hacks, those things that make your code so much better but at the same time so much worse.

⚠️ Warning: The below comments in regards to speed is unverified on modern simulator versions, and thus cannot be assumed to be true.
Always test execution speed claims for yourself.


llMessageLinked key parameter as string

VM: LSO Discover: Unknown

Instead of passing a valid key as the forth parameter of the llMessageLinked function, a string value can be used. When the link_message event is triggered, the key can be typecast to a string (implicitly or explicitly) without any value degradation.

llMessageLinked(LINK_THIS, 10, "Hello", "World!")

Pros

Cons

llGetListLength(myList) and (myList != [])

VM: LSO Discover: Strife Onizuka

Pros

Cons

++c and c++

VM: LSO Discover: Not Applicable

In LSO LSL (as opposed to Mono LSL) ++c is faster than c++ because of how the bytecode is generated[2]. There are very few applications where ++c can't be used instead.

Pros

Cons

(c = -~c) same as ++c

VM: LSO Discover: Strife Onizuka

For the same instruction cost of (++c), (c = -~c) can be substituted giving a 4 byte savings.

Pros

Cons

Testing key validity

VM: LSO & Mono Discover: Strife Onizuka

By passing the key value to a conditional, if it is valid and not a NULL_KEY then it will execute the true branch.

integer isKey(key in) {
    if(in) return 2;
    return (in == NULL_KEY);
}

Pros

Cons

if(~c) and if(c != -1)

VM: LSO Discover: Unknown

Instead of using if(c != -1) you can use if(~c). This applies to all conditionals.

Pros

Cons

myList = (myList = []) + and myStr = (myStr = "") + Hack

VM: LSO Discover: Strife Onizuka

This hack works equally well for both strings and lists.

Instead of using myList = myList + addition you can use myList = (myList = []) + myList + addition which will in certain situations reduce memory fragmentation. Memory fragmentation can result in what appears to be a memory leak. This works because LSL execution is Right-To-Left, it frees the value stored at the variable's memory location after copying it to the stack but before storing the return back to the location; the result can be better memory compacting.

Pros

Cons

Notes

32bit hexadecimal notation instead of negative integer notation for constants (ex: 0xFFFFFFFF instead of -1)

VM: LSO, Mono Discover: Void Singer

instead of using negative integer constants in code (does not apply to global declarations) use the 32bit hexadecimal notation. Works because the compiler does not optimize out the negation sign for integer literals (LSO confirmed, Mono confirmed)

Pros

Cons

Cast negative number to itself

VM: Mono Discoverer: Pedro Oval

When using a negative integer constant, add a type cast to integer. Under Mono, a type cast of a type to itself adds no extra code, and in the case of negatives, it can parse the number as a negative integer rather than adding a negate operator, saving 1 byte and being slightly faster.

The same can be done with negative floating point constants: cast them to float.

Examples:

integer i = (integer)-1; // sets i to -1 and saves 1 byte
float f = (float)-1.0; // sets f to -1.0 and saves 1 byte

Note: Don't use (integer)(-1) or (float)(-1.0) as that destroys the magic. Put the minus sign immediately after the closing parenthesis of the type cast.

Pros

Cons

VM Detection

 

VM: Both Discoverer: Void Singer
(llToLower( "Ü" ) == "Ü"); //-- yields TRUE for LSO, and FALSE for MONO.
(llToLower( "Ü" ) != "Ü"); //-- yields TRUE for MONO, and FALSE for LSO.

Pros

Cons


VM: Both Discoverer: Strife Onizuka
(llGetListEntryType( (list)((key)"") ) & 1); //-- yields TRUE for LSO, and FALSE for MONO.
(llGetListEntryType( (list)((key)"") ) >> 2); //-- yields TRUE for MONO, and FALSE for LSO.

Pros

Cons


VM: Both Discoverer: Pedro Oval
(""!="x")  //-- yields -1 for LSO, 1 for MONO

Comments

Any non-empty string works for the right hand side. Just keep the empty string on the left. Appears to yield a strcmp of the UTF-8 strings under LSO, and a real boolean result (yielding either 0 or 1 and nothing else) under Mono.

Pros

Cons


~(""!="x")  //-- yields FALSE for LSO, -2 for MONO

Pros

if (~(""!="x")) llOwnerSay("VM is Mono"); else llOwnerSay("VM is LSO");

Cons


!~(""!="x")  //-- yields TRUE for LSO, FALSE for MONO
!~-(""!="x")  //-- yields FALSE for LSO, TRUE for MONO

Pros

Cons


llList2Key([], 0)=="" //-- yields TRUE for MONO, FALSE for LSO

Cons

(c & 0x80000000) instead of (c < 0)

VM: LSO Discover: Unknown

Instead of checking if an integer is less than 0 using the comparison operator, the bitwise AND operator can be used to check for the sign-bit. If the sign bit (0x80000000) is true, then the number is negative, and thus less than 0.

Pros

Cons

(c & power_of_two_minus_one) instead of (c % power_of_two)

VM: LSO Discover: Unknown

Instead of using the modulus operator with a power of two (such as 2^2 or 4), the bitwise AND operator can be used with the value of the power of two minus one (such as 3 instead of 4).

if(var & 3);

will work the same as

if(var % 4);

Pros

Cons

Multiplying by reciprocal instead of dividing

VM: Both Discover: Unknown

Implementations of division as a whole are more complex than implementations of multiplication. This includes the algorithmic implementation on a hardware level. Because of this, multiplication is faster than division. Many compilers will automatically 'optimize' these sort of tiny things where possible. Only 'where possible' because sometimes floating-point rounding error can make an output difference. LSL doesn't do it at all.

For example, x/2.0 will have the same output as x*0.5, but will run faster.

Pros

Cons

HTML-on-a-prim hacks

All sorts of tricks you never thought that the SL Viewer was able to do with MOAP:

User:Ama_Omega/archive/lsl_hacks

Footnotes

  1. ^ Plans for LSL3 are still being worked out, nothing has been finalized, no release date has been set, LSL3 may in-fact never happen.
  2. ^ The LSO LSL compiler does not produce optimized code.