Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.
JDT Core Programmer Guide/ECJ/Generate
Participants
- This phase is driven by
generatedCode()
methods in individual AST classes. - The result is accumulated into an instance of
org.eclipse.jdt.internal.compiler.ClassFile
per type. - The work horse for all the details of byte code is class
CodeStream
, with its subclassesStackMapFrameCodeStream
andTypeAnnotationCodeStream
, which are used es required by the target Java version.
Modes
As mentioned above subtypes of CodeStream implement different capabilities:
- stack maps are generated for 1.6 and above
- type annotations are generated for 1.8 and above
Wide mode
Additionally, byte code can be generated in one of two addressing modes: regular and wide. In regular mode, relative code offsets must be smaller than 0x8000. In regular mode, opcodes like goto
are used as opposed to goto_w
in wide mode. Code generation always starts in regular mode, but as soon as a jump requires an offset larger than 0x7FFF code generation for the current method is aborted (by throwing new AbortMethod(CodeStream.RESTART_IN_WIDE_MODE, _)
, which causes a restart in AbstractMethodDeclaration.generateCode()
or similar. The current mode is stored as CodeStream.wideMode
.
A full restart is done, because instructions like goto vs goto_w have different size in bytes. So changing a goto instruction to become goto_w will invalidated all byte code offsets after the instruction. OTOH, jump offsets are only known once the target label has been placed into the stream. As a result code generation needs to now the length of a jump before the position of the jump target is known. The easiest way to find out is thus trial and error :)
Local variable optimization
Restarting code generation for a given method may also happen for another reason as detailed in bug 329709: local variables are assigned to byte code positions inside BlockScope.computeLocalVariablePositions(..)
, but for the sake of optimization, unused locals may not get a position assigned. For certain situations, however, usedness is found out only during generateCode() itself. So if code gen started thinking a local does not require a position, and later detects this assumption was wrong, a restart is triggered with CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE
. (Details of bug 329709 may be filled in once bugzilla works again)