Wulfie Reanimator Posted March 11, 2020 Share Posted March 11, 2020 (edited) A friend of mine just showed me something weird. This code, which is 1040 lines long, compiles fine. But if you add one extra element to the test list, it refuses to compile with the error "Internal server compile error." The working code reports 14628 bytes of used memory before and after touching the object, so there's no stack-heap collision or impossible memory requirements. There are 43278 characters in the code, so it's not hitting the viewer's default limit. I don't know whether this "internal server" is internal to the viewer or internal to the actual server-server (technical term). Pre-post edit: The working test list has 1023 elements (last index is 1022). 1024 elements seem to break it. If you start another list, you can keep going just fine. Appending an element to test list in the touch_start event works just fine, even though the list starts at 1023 elements. I'm posting this because 1) it started as an interesting problem and 2) it turned out to be a seemingly undocumented quirk. It's not listed in the Limits page of the wiki. Real edit: Yeah, there are no hard limits beyond that besides the memory limit itself. It's actually possible to compile a script that will run out of memory immediately on state_entry. The maximum predefined list length may vary based on the data type, obviously this code only used strings. Edited March 12, 2020 by Wulfie Reanimator 1 Link to comment Share on other sites More sharing options...
Kardargo Adamczyk Posted March 11, 2020 Share Posted March 11, 2020 (edited) what i remember is that a predefined list has a maximum number of elements, while adding elements to the list through the script only maxes out when you run out of memory, i think this is by design. looking to find it on the lsl page, will get back when i find it Dargo... *edit: this is what i found on the old lslwiki: Note: while the LSL compiler will only accept code with a maximum of 72 items in a list, lists can actually support as many items as a script's memory will allow. If a list of more than 72 predefined items is needed, just concatenate (combine) two predefined lists into a new one: longlist = firstpart + secondpart;As of 1.20.4, this no longer seems to be true. A list with at least 100 is possible, though I haven't tested to see just how many elements I can initialize a list to. - BlueJeansAndRainJune 5, 2008 - Server 1.22.1.88473 | Client 1.19.1 (4): I was able to create a global list containing 1,081 null integers and a local list containing 2,318 null integers before receiving "(0, 0) : Byte code assembly failed -- out of memory". so it seems there's still a maximum of predefined objects in a list, but it was gradually increased over time, however you found the maximum again.. you can still do a longlist = list1 + list2 Edited March 11, 2020 by Kardargo Adamczyk 1 Link to comment Share on other sites More sharing options...
Wulfie Reanimator Posted March 13, 2020 Author Share Posted March 13, 2020 (edited) On 3/12/2020 at 12:57 AM, Kardargo Adamczyk said: this is what i found on the old lslwiki: Note: while the LSL compiler will only accept code with a maximum of 72 items in a list, lists can actually support as many items as a script's memory will allow. If a list of more than 72 predefined items is needed, just concatenate (combine) two predefined lists into a new one: longlist = firstpart + secondpart; As of 1.20.4, this no longer seems to be true. A list with at least 100 is possible, though I haven't tested to see just how many elements I can initialize a list to. - BlueJeansAndRain June 5, 2008 - Server 1.22.1.88473 | Client 1.19.1 (4): I was able to create a global list containing 1,081 null integers and a local list containing 2,318 null integers before receiving "(0, 0) : Byte code assembly failed -- out of memory". I looked into this, and found more weird things. If a global list has more than 4998 elements or a local list has more than 4995 elements, you will get a syntax error before the next comma. (Of course, the script crashes long before these limits are reached, due to stack-heap collisions on or before state_entry.) Here's a reference script. If you stay within that limit, but too many for a predefined list, you'll get the internal server error. That said, I have no idea what exactly causes the internal server error. It doesn't happen when I have 4800 integers (75KB) in a single list. I can't say if it's caused by some kind of memory limit or another problem. Edited March 13, 2020 by Wulfie Reanimator Link to comment Share on other sites More sharing options...
Lucia Nightfire Posted March 14, 2020 Share Posted March 14, 2020 Said integers can't be combined into a smaller list of bitwise integers? 1 Link to comment Share on other sites More sharing options...
Lucia Nightfire Posted March 15, 2020 Share Posted March 15, 2020 (edited) You said you have a list of 4800 integers. What is the maximum number of bits actually used per integer? If each integer is only using 1 - 16 bits, you can XOR those integers, each shifted the number of bits used into a larger bit integer, thus freeing up memory. The less bits used the more integers you can "combine". Think "Endianness". Just remember when "extracting" or "expanding" that SL doesn't allow logical right shifting. 😉 Edited March 15, 2020 by Lucia Nightfire Link to comment Share on other sites More sharing options...
Wulfie Reanimator Posted March 15, 2020 Author Share Posted March 15, 2020 (edited) 34 minutes ago, Lucia Nightfire said: You said you have a list of 4800 integers. What is the maximum number of bits actually used per integer? If each integer is only using 1 - 16 bits, you can XOR those integers, each shifted the number of bits used into a larger bit integer, thus freeing up memory. The less bits used the more integers you can "combine". Think "Endianness". Just remember when "extracting" or "expanding" that SL doesn't allow logical right shifting. 😉 Firstly: SL definitely allows logical right shifting. integer i = 4; // Binary: 0100 i = (i >> 1); // Binary: 0010 llOwnerSay((string)i); // Output: 2 Secondly: You've entirely missed the point of the exercise. I'm not trying to have a practical solution -- a working script -- with any number of integers or any large lists. I'm very aware of everything you've mentioned and pretty experienced with bit-twiddling. This is a purely technical examination. I was trying to figure out "at which point does the internal server compile error happen?" The more things I try, the more convoluted the error gets. For example if I add a function call into state_entry, the internal error shows up until the predefined list length is satisfied. Otherwise it doesn't show up, except for the syntax error at the limit I originally found. Edited March 15, 2020 by Wulfie Reanimator Link to comment Share on other sites More sharing options...
Lucia Nightfire Posted March 15, 2020 Share Posted March 15, 2020 (edited) 1 hour ago, Wulfie Reanimator said: Firstly: SL definitely allows logical right shifting. Then what happens when you right shift a sign bit in SL? http://wiki.secondlife.com/wiki/LSL_Operators https://en.wikipedia.org/wiki/Arithmetic_shift Edited March 15, 2020 by Lucia Nightfire Link to comment Share on other sites More sharing options...
Wulfie Reanimator Posted March 15, 2020 Author Share Posted March 15, 2020 (edited) 58 minutes ago, Lucia Nightfire said: Then what happens when you right shift a sign bit in SL? http://wiki.secondlife.com/wiki/LSL_Operators https://en.wikipedia.org/wiki/Arithmetic_shift It does the exact same thing as regular C/C++ compilers. You can try this in any online compiler for example. If the value is signed and negative, it pads with 1s. integer i = -777; // Binary: 11111111111111111111110011110111 i = (i >> 1); // Binary: 11111111111111111111111001111011 llOwnerSay((string)i); // Output: -389 #include <stdio.h> int main() { printf("%d\n", -777); // "-777" printf("%d\n", -777 >> 1); // "-389" return 0; } If you have more questions, make a new thread (or PM me) and I'll be happy to answer them. Edited March 15, 2020 by Wulfie Reanimator Link to comment Share on other sites More sharing options...
Lucia Nightfire Posted March 15, 2020 Share Posted March 15, 2020 1 hour ago, Wulfie Reanimator said: If the value is signed and negative, it pads with 1s. That padding of 1's is specific to Arithmetic right shifting, and only optional in Logical right shifting, which typically pads with 0's. SL uses Arithmetic right shifting. You have to use other bitwise functions to emulate Logical right shifting in SL. 1 hour ago, Wulfie Reanimator said: If you have more questions, make a new thread and I'll be happy to answer them. My "question" was more rhetorical than genuine. 😉 Link to comment Share on other sites More sharing options...
ItHadToComeToThis Posted March 15, 2020 Share Posted March 15, 2020 6 minutes ago, Lucia Nightfire said: That padding of 1's is specific to Arithmetic right shifting, and only optional in Logical right shifting, which typically pads with 0's. SL uses Arithmetic right shifting. You have to use other bitwise functions to emulate Logical right shifting in SL. My "question" was more rhetorical than genuine. 😉 I am actually curious. Can you show an example of logical right shift in LSL? Link to comment Share on other sites More sharing options...
Lucia Nightfire Posted March 15, 2020 Share Posted March 15, 2020 1 hour ago, ItHadToComeToThis said: I am actually curious. Can you show an example of logical right shift in LSL? string integer2hex(integer in, integer keep_leading_zeros) { string ret; integer i = ~8; while(++i) { ret = llGetSubString("0123456789abcdef",in & 0xF,in & 0xF) + ret; in = in >> 4; } return "0x" + llList2String(llParseString2List("0x" + ret,["0x0000000","0x000000","0x00000","0x0000","0x000","0x00","0x0","0x"],[]) + [ret],!!keep_leading_zeros); //parsing eval'd left to right } default { state_entry() { llSetObjectName("Logical Left or Right Shift Test (<<<,>>>)"); llSetObjectDesc("1 <<< 0"); } on_rez(integer i) { llResetScript(); } touch_end(integer i) { if (llDetectedKey(0) == llGetOwner()) { list T = llParseString2List(llGetObjectDesc(),[" ","\n"],["<<<",">>>"]); if (llGetListLength(T) == 3) { integer a = (integer)llList2String(T,0); //hex notation is not typecasted to integer format with llList2Integer() integer b = llAbs((integer)llList2String(T,2)) % 32; //hex notation is not typecasted to integer format with llList2Integer() if (~(i = llListFindList(["<<<",">>>"],[llList2String(T,1)]))) { integer c = llList2Integer([a << b,((a & ~0x80000000) >> b) | (!!(a & 0x80000000) << (31 - b))],i); llOwnerSay((string)a + "(" + integer2hex(a,0) + ") " + llList2String(["<<<",">>>"],i) + " " + (string)b + " = " + (string)c + "(" + integer2hex(c,0) + ")"); return; } } llOwnerSay("Object description must contain two integers, separated by a logical left shift operator, '<<<' or a logical right shift operator, '>>>'. Bitwise input is accepted."); } } } I made this example years ago. IDK if I thoroughly tested it. It may or may not have redundancies. It doesn't do more than 31 bits as it's assumed greater than that will yield 0 with any input. Link to comment Share on other sites More sharing options...
Recommended Posts
Please take a moment to consider if this thread is worth bumping.
Please sign in to comment
You will be able to leave a comment after signing in
Sign In Now