Seriously, you would think that SWITCH statements would just get compiled into a giant if then else tree. Good guess. That’s what I thought, but you need to support case fall through. So you would think that they would have an If, then else tree where you test each case, and jump to a area of code, where at the end of each block you can Jump to the end of the switch statement (ie.e they end that case with a "break") or simply fall through to the next cases code block. Make sense. An If/then/else tree to test cases and a layer of indirection to the code blocks to allow for fall through. Only Adobe makes add yet another level on indirection. They have the if/then/else tree, they test each case statement for a value, then push a special value on the stack, then jump to a dispatcher, which jumps to different code block based on the magical stack value, which then jumps you to the code blocks so you can fall through. Are you freaking kidding me? Behold, this is the source code.
trace("before");
switch(x) {
case 1:
trace("case 1");
break;
case 2:
trace("case 2");
break;
default:
trace("default");
break;
}
trace("after");
Becomes because the following Flash pseudo-assembly code.
Push "before" onto stack
Call trace()
Push x onto stack
If(x == 1) {
Push 0 onto stack
Jump to DISPATCHER
}
If(x == 2) {
Push 1 onto stack
Jump to DISPATCHER
}
Push 2 onto stack
Jump to DISPATCHER
.
. //unimportant crap
.
BLOCK1:
Push "case 1" onto stack
Call trace()
Jump to POSTSWTICH:
BLOCK2:
Push "case 2" onto stack
Call trace()
Jump to POSTSWTICH:
BLOCK3:
Push "default" onto stack
Call trace()
Jump to POSTSWTICH:
.
. //unimportant crap
.
DISPATCHER:
//lookupswitch is an op code (yes, they have a freaking opcode for this)
//that reads the byte on the top of the stack and uses that as
//an index into a list of locations to jump to and then jumps to that
//corresponding label. So if say, 0, is on the stack, it will jump to
//BLOCK1, etc
Lookupswitch BLOCK1, BLOCK2, BLOCK3
POSTSWITCH:
Push "after" onto stack
Call trace()
I'm going to punch someone in the head. It's took me a solid 2 hours to trace this stuff and try to find a pattern (With default, without, swtiching on diff datatypes, etc). I too way long to figure out how to actually recognize this crap mixed into a giant mess of other nested if/else clauses, ternary ops, while loops, etc. Oh, and I didn't even include the dead code. Yeah. That’s right, DEAD CODE! For each case the silly compiler actually generates dead code containing extra JUMPs that are impossible to get to. Just to make the jump/branch tables even more complex. As if 3 freaking levels of indirection were not enough, they have to throw in crap that will not even get executed! And god help you if you nest switches. Holy crap. grrrr And then there the bloody scope stack... Thats it Adobe, you are on the list! ;-) |