7

I've recently made a decompiler for AVM2/AS3, and I've noticed that Flash compiler tends to emit a lot of unneccessary code. For example, for a certain application I've removed circa 10% of the code without any impairment to functionality. It was just a certainly dead code not referenced by conditional opcodes nor by exception handling blocks.

Also, look at this snippet:

    ...
    313     setproperty         y
    315     getlocal            12
    317     returnvalue         
    318     jump                L9

    L3: 
    322     getlocal            8
    324     returnvalue         

    L9: 
    325     jump                L10 ; L10 (opcode #331) does not ever exist.
                                    ; Technically, it is a jump beyond
                                    ; the end of function. This is invalid code!

    L2: 
    329     pushnull            
    330     returnvalue         

Well, of course this is invalid code, which is also dead and hence won't cause any adverse effects (except of codebase bloating). But why does it ever emit that code? And why does verifier accepts that?

David
  • 208,112
  • 36
  • 198
  • 279
Catherine
  • 22,492
  • 3
  • 32
  • 47
  • It wasn't referenced from an exception table (as were not a lot of other, much bigger--10s of instructions--dead code blocks), and judging from the spec, you may either transfer control via a jump opcode or an exception. There are no jumps either. – Catherine Jan 12 '12 at 21:05
  • @wvxvw By the way, `finally` blocks are done in AS3 with a weird and devious hack, where compiler deliberately generates invalid opcodes to trick verifier and VM, again deliberately, ignores them. Flash is just a huge WTF. – Catherine Feb 03 '12 at 10:20
  • @wvxvw, have I understood you correctly? if you execute a certain sequence of opcodes then the VM allows the running code to examine its opcode stream somehow, presumably through pushing them to data stack? +50 if you could find the references. – Catherine Feb 04 '12 at 07:31
  • @wvxvw I already wrote a disassembler and analyzer ;) (see http://github.com/whitequark/furnace-avm2), and anyway, that bug doesn't seem to allow reading from runtime. Stacktrace is only written to user and not the code inside the VM. – Catherine Feb 04 '12 at 11:42

1 Answers1

7

ASC or compc do not optimize. This is unfortunate, but the theory is that the JIT does all the optimization work. You can come up with even worse examples like adding two constants. So the answer is: Sorry, it just does not optimize. There might be a better compiler in the future. Right now you have to rely on the AS3 JIT to do the optimization work at runtime (which it does a decent job at!) or use a different compiler.

starmole
  • 4,974
  • 1
  • 28
  • 48
  • Yes, I of course seen adding constants and such, not to mention unnecessary coercion everywhere. The worst example of it is probably how `lookupswitch` is codegen'd. Do you have any references about why is it designed that way (like [LLVM](http://blog.llvm.org/) has)? Constant folding isn't *that* hard to implement, unless you're completely braindead. – Catherine Feb 03 '12 at 10:22
  • 1
    whitequark: The theory is that the "compiler" is just a glorified parser and the JIT will take care of everything else. I personally do not think it is a good design, but that how it is. I do not know of any good references either, sorry. – starmole Feb 04 '12 at 04:53