Thomas,
Nice list of optimization proposals. I think all of those should make
it in the new compiler...lol. As for undocumented features... this is
a real good point, I'm sure there are AVM2 features Adobe has not
seen to make public to the rest of the flash community but that they
use internally. For example. If memory serves me correctly in the
AVM1 there was an int type but that type was not available as a
language type it was only in the Bytecode ( I think, though I could
be wrong about this ). I'm sure there are situations like this in the
AVM2.
Earlier you mentioned an optimization technique for method
overloading. I don't think doing something like...
myMethod_1( id:String );
myMethod_2();
will work because in the grand scheme of things. For example let's
say there is a swf ( SWF1) that is compiled with your compiler that
loads a swf (SWF2) compiled with mxmlc. If the SWF2 tries to call
myMethod() if will probably cause a runtime error because it does not
know that myMethod is overloaded and has suffixes attached to it.
Cheers,
Sam
On Sep 12, 2007, at 5:47 PM, Thomas Quester wrote:
>
>>> n = int[10]
>>>
>>> if you try to access index 11 in array n, an IndexOutOfBounds
>>> Exception is thrown. Same for C#, Objective C and obviously C. This
>>> is fundamental and basic to all professional languages and
>>> Actionscript 3 doesn't have it? Why? Who knows but it's not there.
>
> Action script has associative arrays, it is part of the language
> design,
> practally to use etc. In Visual Basic we would call this a
> collection, not
> an array.
>
> Letting the compiler know the size of the array allows
> implementation of
> bounds checks throwing exceptions if the program violates the array
> bounds.
> In real languages this is important for survival, if we have n = int
> [10] and
> write to element 11 or read from element 11 we may get a page fault
> or write
> to some data which lets our program crash 3 and a half hours
> later.... badly
> to find out what happened afterwards. In AS writing element 11 is
> at least
> save, we do not destroy memory.
>
> It may break our algorythmns if we made something wrong with array
> indexes
> like hoping with our chess figure out of the 8x8 board while we
> calculate
> the answer to a chess move may result in some days of debugging ....
>
> It seems the VM does not have any method to access real bytes,
> maybe it
> would be possible to create an n-dimensional array of bytes into a
> string
> accessing with charAt, depending what the string implementation
> does if we
> put 0 inside the string and how cost effective is converting string to
> numbers and vice versa.
>
>> a) a compiler and the resulting bytecode are two very distinct things
>> you may optimize the bytecode output, but you just can't add features
>> to this bytecode or you become incompatible
>
> We can not really add features to the bytecode, because this way we
> must
> write a new VM or extend the old one. Would be too complicated. It
> is also
> not really needed. We can maybe use undocumented features, for example
> members of a class in AVM1 are usually created by a name, but the
> flash
> player is completly happy if we use the prototype array with only
> numbers.
>
> // in AVM1
> push r:1,'fib'
> function2(r:2='n') (r:1='this')
>
> player is happy if we write
>
> push r:1,0
> function2() (r:1='this')
>
> and later use 0 in callMethod.
>
> The member function is now called 0 instead of fib but flash player
> is happy
> with this and thanks with a bit more speed and extra obfuscation.
>
> If we talk in optimizations we mean things like approving what we
> have and
> find a solution with minimal number of commands, most of them can
> be done by
> the programmer writing different the input for the compiler.
>
> First are silly optimizations
> r = 360/3
> becomes
> r = 120
> MTASC does not do this, it writes push 360,3, devide
>
> Another silly one is
> a = b+c
> d = a+e
> A is alredy on stack, no need loading it in next expression it was
> alredy
> there but deleted by varaible assignment. If a is local variable
> and never
> used, drop variable assignment.
> a = b+c
> d = b+c+e
> Avoid common sub expression b+c in second command. We may have some
> other
> code lines betwenn that both to make things more difficult. In
> languages
> that compile for real processors, common sub expressions are often
> found in
> array index calculation type conversion etc. Things we do not have
> in Flash.
>
> In a less silly example:
>
> // Decrease counter of bombs and explode
> // silly code anyway...
> for (i=0;i<game.bombs.count;i++)
> {
> if (game.bombs[i].time == 0)
> game.bombs[i].Explode()
> else
> {
> game.bombs[i].time--;
> game.bombs[i].Redraw();
> }
> }
>
> game.bombs[i] is evaluated 4 times, game.bombs is evaluated 5 times,
> registers used: 1. But we have 255 registers this makes plenty room
> for
> optimization. If you compile and disassemble, you see that
> game.bombs.count
> is evaluated time the loop is executed, the compiler can not tell
> if the
> count member will modify by some of the functions we call, so it is
> the save
> way to re-evaluate the expression until the programmer gives us
> hints or a
> very very smart compiler is examining the explode and redraw
> function and
> everything called by explode and readraw and so on....
> // harder to read in real world apps but much faster
> var temp1 = game.bombs
> var temp2 = temp1.count // for evaluates the expression
> i<bombs.count each
> time it loops, we take out that code.
> for (i=0;i<temp2;i++)
> {
> var temp3=game.bombs[i];
> if (temp3.time==0)
> temp3.Explode()
> else
> {
> temp1.bombs[i]--;
> temp3.Explode()
> }
> }
>
> game.bombs[i] is about 10 lines of assembly code, so we save a lot.
> A good
> optimizer is finding the same blocks of code automatically, prove
> if the
> variables it depends on are not modified and stores the result to a
> place
> where it can be accessed fast, if we can not prove, the expression
> must be
> re-evaluated and the effect is more locally.
>
>
> We also can add new language elements to help in optimization.
> Using them is
> optional. The "with" statement lets the programmer prove which part
> can be
> optimized.
>
> // Optimization with "with" stolen from Pascal or VB (do we have
> "with" in
> AS?)
> var temp1 = game.bombs.count
> for (i=0;i<temp1;i++) // otherwise game.bombs.count will be
> evaluated in
> each loop
> {
> with (game.bombs[i]) do // game.bombs[i] to the stack and
> store in a
> register
> {
> // compiler may save .time to a register or use the
> stack and
> save some time
> if (.time == 0) .Explode()
> else
> {
> .time--;
> .Redraw();
> }
> }
>
> "with" simply stores the result of the expression to the stack and
> into a
> register for later use. If it is possible to approve the stack top
> the stack
> is used otherwise, the regsiter. The ending block drops the element
> and the
> register is marked as free. In other word the "." before .Explode
> simple
> compiles into "dup" which is a very fast operation.
>
> In real world things are more complicated, however.... Even Visual
> Studio
> has problems with common sub expressions and sometimes creates code
> which
> crashes.
>
> All optimizations are have good theory background, but mostly the
> theory
> requires a 3 operand assembly language without stack, we have 1
> operand
> stack code.
>
> Thomas
>
>
>
> _______________________________________________
> osflash mailing list
> [email protected]
> http://osflash.org/mailman/listinfo/osflash_osflash.org
_______________________________________________
osflash mailing list
[email protected]
http://osflash.org/mailman/listinfo/osflash_osflash.org