In more details:
- add a Constants interface to avoid some magic constants in the code
- remove the INSTRUCTION_TYPES indirection in ClassReader, and use (table)switch statements on raw opcode values instead
- remove unnecessary flags BASIC_BLOCK_CHANGED, VISITED and VISITED2 in Label (replaced with a simpler algorithm using an EMPTY_LIST sentinel), as well as the redundant STORE flag
- add an otherLineNumbers field in Label to store line numbers in a cleaner way than with nextChangedBlock
- remove the inputStackTop field in Label, which was used to store different values depending on the compute options or basic block types. Replace it with new inputStackSize and outputStackSize fields in Label, and a new (private) outputStackStart field in Frame.
- use 'short' fields when possible in Frame and Label. Object size in memory with OpenJDK 1.8.0, measured with https://www.javaworld.com/article/2077496/testing-debugging/java-tip-130--do-you-know-your-data-size-.html, decreased from 64 to 56 bytes for Label (despite the added fields), and stayed unchanged (48 bytes) for Frame (despite the added field outputStackStart).
- split the large visitMaxs method in two smaller methods.
- performance is unchanged or improved: 1.02-1.04 speedup for ClassReader, no change for ClassReader+ClassWriter, 1.11 speedup for CR+CW with compute maxs, 1.05 speedup for CR+CW with compute frames.