package opt
- Alphabetic
- Public
- All
Type Members
- class BoxUnbox [BT <: BTypes] extends AnyRef
-
class
ByteCodeRepository
[BT <: BTypes] extends AnyRef
The ByteCodeRepository provides utilities to read the bytecode of classfiles from the compilation classpath.
The ByteCodeRepository provides utilities to read the bytecode of classfiles from the compilation classpath. Parsed classes are cached in the
classes
map. - class CallGraph [BT <: BTypes] extends AnyRef
- class ClosureOptimizer [BT <: BTypes] extends AnyRef
- class CopyProp [BT <: BTypes] extends AnyRef
-
case class
InlineInfoAttribute
(inlineInfo: InlineInfo) extends Attribute with Product with Serializable
This attribute stores the InlineInfo for a ClassBType as an independent classfile attribute.
This attribute stores the InlineInfo for a ClassBType as an independent classfile attribute. The compiler does so for every class being compiled.
The reason is that a precise InlineInfo can only be obtained if the symbol for a class is available. For example, we need to know if a method is final in Scala's terms, or if it has the @inline annotation. Looking up a class symbol for a given class filename is brittle (name-mangling).
The attribute is also helpful for inlining mixin methods. The mixin phase only adds mixin method symbols to classes that are being compiled. For all other class symbols, there are no mixin members. However, the inliner requires an InlineInfo for inlining mixin members. That problem is solved by reading the InlineInfo from this attribute.
In principle we could encode the InlineInfo into a Java annotation (instead of a classfile attribute). However, an attribute allows us to save many bits. In particular, note that the strings in an InlineInfo are serialized as references to constants in the constant pool, and those strings (method names, method signatures) would exist in there anyway. So the ScalaInlineAttribute remains relatively compact.
- class Inliner [BT <: BTypes] extends AnyRef
- class InlinerHeuristics [BT <: BTypes] extends AnyRef
- case class LabelNotLive (label: LabelNode) extends RemovePairDependency with Product with Serializable
-
class
LocalOpt
[BT <: BTypes] extends AnyRef
Optimizations within a single method.
Optimizations within a single method. Certain optimizations enable others, for example removing unreachable code can render a
try
block empty and enable removeEmptyExceptionHandlers. The latter in turn enables more unreachable code to be eliminated (thecatch
block), so there is a cyclic dependency. Optimizations that depend on each other are therefore executed in a loop until reaching a fixpoint.The optimizations marked UPSTREAM enable optimizations that were already executed, so they cause another iteration in the fixpoint loop.
nullness optimizations: rewrite null-checking branches to GOTO if nullness is known + enables downstream
- unreachable code (null / non-null branch becomes unreachable)
- box-unbox elimination (may render an escaping consumer of a box unreachable)
- stale stores (aload x is replaced by aconst_null if it's known null)
- simplify jumps (replaces conditional jumps by goto, so may enable goto chains)
unreachable code / DCE (removes instructions of basic blocks to which there is no branch) + enables downstream:
- stale stores (loads may be eliminated, removing consumers of a store)
- empty handlers (try blocks may become empty)
- simplify jumps (goto l; [dead code]; l: ..) => remove goto
- stale local variable descriptors
- (not box-unbox, which is implemented using prod-cons, so it doesn't consider dead code)
note that eliminating empty handlers and stale local variable descriptors is required for correctness, see the comment in the body of
methodOptimizations
.box-unbox elimination (eliminates box-unbox pairs withing the same method) + enables UPSTREAM:
- nullness optimizations (a box extraction operation (unknown nullness) may be rewritten to a read of a non-null local. example in doc comment of box-unbox implementation)
- further box-unbox elimination (e.g. an Integer stored in a Tuple; eliminating the tuple may enable eliminating the Integer) + enables downstream:
- copy propagation (new locals are introduced, may be aliases of existing)
- stale stores (multi-value boxes where not all values are used)
- redundant casts (
("a", "b")._1
: the generic_1
method returnsObject
, a cast to String is added. The cast is redundant after eliminating the tuple.) - empty local variable descriptors (local variables that were holding the box may become unused)
copy propagation (replaces LOAD n to the LOAD m for the smallest m that is an alias of n) + enables downstrem:
- stale stores (a stored value may not be loaded anymore)
- store-load pairs (a load n may now be right after a store n) + NOTE: copy propagation is only executed once, in the first fixpoint loop iteration. none of the other optimizations enables further copy prop. we still run it as part of the loop because it requires unreachable code to be eliminated.
stale stores (replace STORE by POP) + enables downstream:
- push-pop (the new pop may be the single consumer for an instruction)
redundant casts: eliminates casts that are statically known to succeed (uses type propagation) + enables UPSTREAM:
- box-unbox elimination (a removed checkcast may be a box consumer) + enables downstream:
- push-pop for closure allocation elimination (every indyLambda is followed by a checkcast, see SI-9540)
push-pop (when a POP is the only consumer of a value, remove the POP and its producer) + enables UPSTREAM:
- stale stores (if a LOAD is removed, a corresponding STORE may become stale)
- box-unbox elimination (push-pop may eliminate a closure allocation, rendering a captured box non-escaping) + enables downstream:
- store-load pairs (a variable may become non-live)
- stale handlers (push-pop removes code)
- simplify jumps (push-pop removes code)
store-load pairs (remove
STORE x; LOAD x
if x is otherwise not used in the method) + enables downstream:- empty handlers (code is removes, a try block may become empty
- simplify jumps (code is removed, a goto may become redundant for example)
- stale local variable descriptors
empty handlers (removes exception handlers whose try block is empty) + enables UPSTREAM:
- unreachable code (catch block becomes unreachable)
- box-unbox (a box may be escape in an operation in a dead handler) + enables downstream:
- simplify jumps
simplify jumps (various, like
GOTO l; l: ...
, see doc comments of individual optimizations) + enables UPSTREAM- unreachable code (
GOTO a; a: GOTO b; b: ...
, the first jump is changed toGOTO b
, the second becomes unreachable) - store-load pairs (a
GOTO l; l: ...
is removed between store and load) - push-pop (
IFNULL l; l: ...
is replaced byPOP
)
The following cleanup optimizations don't enable any upstream optimizations, so they can be executed once at the end, when the above optimizations reach a fixpoint.
empty local variable descriptors (removes unused variables from the local variable table) + enables downstream:
- stale labels (labels that the entry points to, if not otherwise referenced)
empty line numbers (eliminates line number nodes that describe no executable instructions) + enables downstream:
- stale labels (label of the line number node, if not otherwise referenced)
stale labels (eliminate labels that are not referenced, merge sequences of label definitions)
Note on a method's maxLocals / maxStack: the backend only uses those values for running Analyzers. The values can be conservative approximations: if an optimization removes code and the maximal stack size is now smaller, the larger maxStack value will still work fine for running an Analyzer (just that frames allocate more space than required). The correct max values written to the bytecode are re-computed during classfile serialization. To keep things simpler, we don't update the max values in every optimization:
- we do it in
removeUnreachableCodeImpl
, because it's quite straightforward - maxLocals is updated in
compactLocalVariables
, which runs at the end of method optimizations
Note on updating the call graph: whenever an optimization eliminates a callsite or a closure instantiation, we eliminate the corresponding entry from the call graph.
- case class RemovePair (store: VarInsnNode, other: AbstractInsnNode, depends: List[RemovePairDependency]) extends RemovePairDependency with Product with Serializable
- trait RemovePairDependency extends AnyRef
Value Members
- object BytecodeUtils
- object ClosureOptimizer
- object InlineInfoAttribute extends Serializable
-
object
InlineInfoAttributePrototype
extends InlineInfoAttribute
In order to instruct the ASM framework to de-serialize the ScalaInlineInfo attribute, we need to pass a prototype instance when running the class reader.
- object LocalOptImpls
The Scala compiler API.
The following resources are useful for Scala plugin/compiler development: