I just want to share with you how Taas can actually optimize code and what happens behind the scenes. So in my last post I talked about stackless code and optimizations that are possible but how does it work at all?
Imagine you have got this ActionScript code:
var x: Number = 1.0;
var y: Number;
if(true)
{
y = 3.0;
}
else
{
y = 2.0;
}
x += y;
return x;
For the sake of simplicity I will not use local variables in the bytecode. But it will be easier to figure out what happens in the bytecode.
PushDouble 1.0
PushTrue
IfTrue L0
PushDouble 2.0
Jump L1
L0: PushDouble 3.0
L1: Add
ReturnValue
This bytecode is nearly the same as the method but without local variables. This should be fairly simple to understand.
When converting bytecode to Taas, its corresponding control flow graph is converted into a control flow graph of Taas expressions. I do not want to go into much detail how the stack based code is converted but here is the graph before and after the transformation from bytecode to Taas. It looks quite similar but there is a major difference. All those constant values in the Taas graph are not values pushed on a stack but assignments to virtual variables which exist only in theory. You can see also that the Add in the bytecode has known operands and type in the Taas version. Since it is currently not know if 2.0 or 3.0 has been used there is a Φ function that says “This value is either 2.0 or 3.0 depending on the path taken at runtime”.
So as I said this code can be optimized much better than stack based code. This graph is very redundant. There are three utilities to compact and simplify the current graph of Taas expressions. The algorithm has been developed for Java bytecode but works with ActionScript very well tool. The concept is quite simple. Perform copy propagation, constant folding and dead code elimination until the graph stops changing. Applying these techniques to the Taas graph yields the following results.
Copy propagation:
Most of the theoretical variables have been eliminated using copy propagation.
Constant folding:
Known constants have been replaced. Even the if condition is no longer needed and the false branch has been removed. The dead code elimination will clean up this code afterwards.
Dead code elimination:
Dead code elimination has removed the dead Jump statement and also the value 2.0 from the Φ expression. Afterwards constant folding replaced the Φ expression with its one constant value. Then another iteration of constant folding replaced the Add expression with the constant value 4.0. Afterwards copy propagation has put the result into the Return statement and voilá.
This result may have seemed quite obvious from the beginning and you may ask who writes such code. Probably nobody. But once you start inlining methods this makes a lot of sense. A lot of preconditions are known in that case and unnecessary branches can be removed. Since inlining methods bloats up the code it is very important to compact it afterwards as much as possible. I hope you see now how interesting all of this might be in the future.




You know, I thought I was a pretty good flash programmer, but reading this just makes me feel like the biggest idiot on the block. Excuse me while I go try and push my liquified brains back in through my nose.
I take it this all comes in really handy if you want to do some serious optimisations? If so – and I really wouldn’t be all that suprised if it was something different alltogether and that I’ve missed the point completely – could you give us a real world example of what this technique can accomplish?
It is all about optimizations but still a long way to go before I am able to show this. Most of the algorithms are not easy to implement and I have to finish a lot before I can start writing an Abc/Swf generator for the Taas representation but I will show some more examples along the way.