>> 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

Reply via email to