"unused" TS arguments being optimised out
by Ian Omroth Hardingham · in Torque 3D Professional · 05/13/2014 (4:44 am) · 20 replies
Morning.
TS optimises out %db here so it can't be accessed in %perk.eval. Best way to stop that?
Thanks,
Ian
function applyPerkToDB(%perk, %db)
{
eval(%perk.eval);
}TS optimises out %db here so it can't be accessed in %perk.eval. Best way to stop that?
Thanks,
Ian
About the author
Designer and lead programmer on Frozen Synapse, Frozen Endzone, and Determinance. Co-owner of Mode 7 Games.
#2
I was also a bit surprised, but maybe loooooads of the time class::method(%this) never references %this and it's actually a significant time saving? Dunno.
Ian
05/13/2014 (6:05 am)
Thanks Lukas - bit ugly but never mind.I was also a bit surprised, but maybe loooooads of the time class::method(%this) never references %this and it's actually a significant time saving? Dunno.
Ian
#3
05/13/2014 (6:10 am)
Out of interest, where in the code does that optimisation happen? I'm fascinated.
#4
05/13/2014 (6:12 am)
Hey Daniel - no idea myself, just seen the result of it.
#5
05/13/2014 (8:58 am)
Could be that the parser is optimizing it out. AFAIK it doesn't optimize any of this stuff out on a bytecode level.
#6
And this one was just for fun:
Everything seems to be in order.
05/13/2014 (1:25 pm)
I think there's something else going on. I ran some tests:function testfunc(%arg1, %arg2)
{
eval("echo(%arg1 @ \"and\" @ %arg2);");
}
testfunc("hello", "goodbye");This outputs: "hello and goodbye"function testfunc(%arg1, %arg2)
{
eval(%arg1);
}
testfunc("echo(%arg2);", "goodbye");This outputs: "goodbye"And this one was just for fun:
function testfunc(%arg1, %arg2)
{
eval(%arg1);
}
testfunc("echo(%arg1 @ \" and \" @ %arg2);", "goodbye");This outputs: "echo(%arg1 @ " and " @ %arg2); and goodbye".Everything seems to be in order.
#7
It must be something else.
05/13/2014 (5:30 pm)
I was gonna say, I haven't found out where the parser does optimization yet too it :PIt must be something else.
#8
Lies! Lies I say!
Lies, damn lies ... and statistics!
;P
05/13/2014 (6:45 pm)
Torquescript optimizes something!? Lies! Lies I say!
Lies, damn lies ... and statistics!
;P
#9
I'm not sure what else could explain what I'm seeing here - I've seen it multiple times.
Ian
05/14/2014 (1:38 am)
Very weird... Andrew, does it still function correctly if you don't have the call in the file with the function - ie if you just have the function then paste that into the console?I'm not sure what else could explain what I'm seeing here - I've seen it multiple times.
Ian
#10
Ian
05/14/2014 (1:42 am)
What engine version are you using Andrew? I do not get any output from your second testFunc here - my code is based on T3D 1.1.Ian
#11
05/14/2014 (6:04 am)
Ian, are you working with James U's improved TorqueScript performance stuff? Maybe that's causing some discrepancies.
#12
05/14/2014 (6:05 am)
I am - I guess that's what it is.
#13
05/14/2014 (4:13 pm)
Unit tests ahoy! I actually ran this using vanilla T3D and using a version with James's pull request merged, and saw identical behaviour between both of them. So maybe that's not it, but see if James has been doing any other TS-related work.
#14
The TS stuff is not merged into Ian's code.
It seems %db is being passed in. However the compiler isn't assigning a name to the value unless "%buffer = %db;" is added in - thus why %db appears not to exist. When the function is parsed into the ast tree however %db is present with the correct name.
Likely something very strange is happening in the compiler string table.
05/19/2014 (4:34 pm)
Just an update on this...The TS stuff is not merged into Ian's code.
It seems %db is being passed in. However the compiler isn't assigning a name to the value unless "%buffer = %db;" is added in - thus why %db appears not to exist. When the function is parsed into the ast tree however %db is present with the correct name.
Likely something very strange is happening in the compiler string table.
#15
- Turn off TORQUE_NO_DSO_GENERATION
- Stick Omroth's code paste at the end of your core/main.cs
- Start either the Empty or Full project
- Put a breakpoint in CodeBlock::exec on line 1642 (should be "ret = nsEntry->mCode->exec(nsEntry->mFunctionOffset, fnName, nsEntry->mNamespace, callArgc, callArgv, false, nsEntry->mPackage);")
- Type "applyPerkToDB("One", "Two");" into the windows console
- Step into the exec call, and step through the code at the top which grabs the function parameter names (i.e. StringTableEntry var = U32toSTE(code[ip + i + 6]);)
According to my debugger the first param ends up being %perk while the second parameter ends up being "". Thus %db never exists.
05/19/2014 (5:02 pm)
This occurs with T3D MIT. Steps to reproduce:- Turn off TORQUE_NO_DSO_GENERATION
- Stick Omroth's code paste at the end of your core/main.cs
- Start either the Empty or Full project
- Put a breakpoint in CodeBlock::exec on line 1642 (should be "ret = nsEntry->mCode->exec(nsEntry->mFunctionOffset, fnName, nsEntry->mNamespace, callArgc, callArgv, false, nsEntry->mPackage);")
- Type "applyPerkToDB("One", "Two");" into the windows console
- Step into the exec call, and step through the code at the top which grabs the function parameter names (i.e. StringTableEntry var = U32toSTE(code[ip + i + 6]);)
According to my debugger the first param ends up being %perk while the second parameter ends up being "". Thus %db never exists.
#16
) , it is not adding the parameter names to the ident table, whereas in the compile pass it does ( https://github.com/GarageGames/Torque3D/blob/master/Engine/source/console/astNodes.cpp#L1869 ).
Since only the strings added during the precompile step are added to the string table which gets written ( https://github.com/GarageGames/Torque3D/blob/aa090daf03640705f5f759ce6abbc6987e7e8e0d/Engine/source/console/codeBlock.cpp#L513 ), any function parameters you do not reference in the function end up being placed at the end of the string table, which does not exist. Thus "junk" parameters are created.
When loading a codeblock from disk, the code checks to see if a string is within the string table. If it is not, it replaces it with a blank string.
IMO this should be fixed as it creates confusing behaviour if you decide to reference unused parameters in an eval call.
05/20/2014 (3:52 pm)
Figured out the problem. What is happening is when the compiler goes through its precompile step ( https://github.com/GarageGames/Torque3D/blob/master/Engine/source/console/astNodes.cpp#L1834) , it is not adding the parameter names to the ident table, whereas in the compile pass it does ( https://github.com/GarageGames/Torque3D/blob/master/Engine/source/console/astNodes.cpp#L1869 ).
Since only the strings added during the precompile step are added to the string table which gets written ( https://github.com/GarageGames/Torque3D/blob/aa090daf03640705f5f759ce6abbc6987e7e8e0d/Engine/source/console/codeBlock.cpp#L513 ), any function parameters you do not reference in the function end up being placed at the end of the string table, which does not exist. Thus "junk" parameters are created.
When loading a codeblock from disk, the code checks to see if a string is within the string table. If it is not, it replaces it with a blank string.
IMO this should be fixed as it creates confusing behaviour if you decide to reference unused parameters in an eval call.
#17
Nice catch, Ian.
05/20/2014 (4:45 pm)
Hey, has anyone noticed this happening in T2D as well? Because I'm pretty sure this is the behavior there, too. I recall quite some time ago having "odd" things happen when using eval() to handle some tasks in the Tower Defense Template's wave editor. It could be that this is comes from TGE and wasn't caught because eval() is rarely used....Nice catch, Ian.
#19
05/21/2014 (2:38 am)
Nice diagnosis James!
#20
05/21/2014 (4:43 am)
Pushed a fix, enjoy!
Torque Owner Lukas Joergensen
WinterLeaf Entertainment
One solution is to:
function applyPerkToDB(%perk, %db) { %buffer = %db; eval(%perk.eval); }Then it prolly wont get optimized.
It's the same kind of hack that you have to do in HLSL from time to time.