I have... significant reservations with the way object enumeration happens in AVM2. For comparison, AVM1 enumeration works like this: You enumerate the entire object at once, producing a list of property names, which are then pushed onto the stack after a sentinel value. This is a properly abstract way to handle property enumeration.
In AVM2, they completely replaced this with index-based enumeration. What this means is that you hand the object an index and it gives you back a name or value. There's also an instruction that will give you the next index in the object.
The only advantage I can think of is that it results in less stack manipulation if you want to bail out of iteration early. You just jump out of your loop and kill the registers you don't care about. The disadvantage is that it locks the object representation down pretty hard. They also screwed up the definition of `hasnext`, and thus the VM is stuck enumerating properties from 1. This is because `hasnext` and `hasnext2` increment the index value before checking the object. Code generated by Animate 2020 (which I suspect to be the final version of that software that generates AVM2 code) initializes the index at hero, and then does `hasnext2`, hence we have to start from one.
I actually cheated a little and added a separate `Vec` for storing enumerant names. I strongly suspect that Adobe's implementation has objects be inherently slot-oriented, and named properties are just hashmap lookups to slots. This would allow enumerating the slots to get names out of the object.
All constant pools in an ABC file are actually numbered starting from one; there's an implicit 0 entry not stored in the file that the runtime is expected to retrieve when pulling constants from the pool.
The AVM2/ABC spec only mentions this in passing.