scala.tools.nsc.backend

# opt

#### package opt

Visibility

1. Public
2. All

### Type Members

1. #### abstract class ClosureElimination extends SubComponent

2. #### abstract class ConstantOptimization extends SubComponent

   ConstantOptimization uses abstract interpretation to approximate for each instruction what constants a variable or stack slot might hold or cannot hold.

   ConstantOptimization uses abstract interpretation to approximate for each instruction what constants a variable or stack slot might hold or cannot hold. From this it will eliminate unreachable conditionals where only one branch is reachable, e.g. to eliminate unnecessary null checks.

   With some more work it could be extended to - cache stable values (final fields, modules) in locals - replace the copy propagation in ClosureElilmination - fold constants - eliminate unnecessary stores and loads - propagate knowledge gathered from conditionals for further optimization

3. #### abstract class DeadCodeElimination extends SubComponent

4. #### abstract class InlineExceptionHandlers extends SubComponent

   This optimization phase inlines the exception handlers so that further phases can optimize the code better

   This optimization phase inlines the exception handlers so that further phases can optimize the code better

       try {
         ...
         if (condition)
           throw IllegalArgumentException("sth")
       } catch {
         case e: IllegalArgumentException => <handler code>
         case e: ... => ...
       }

   will inline the exception handler code to:

       try {
         ...
         if (condition)
           <handler code> // + jump to the end of the catch statement
       } catch {
         case e: IllegalArgumentException => <handler code>
         case e: ... => ...
       }

   Q: How does the inlining work, ICode level? A: if a block contains a THROW(A) instruction AND there is a handler that takes A or a superclass of A we do:

   1. We duplicate the handler code such that we can transform THROW into a JUMP 2. We analyze the handler to see what local it expects the exception to be placed in 3. We place the exception that is thrown in the correct "local variable" slot and clean up the stack 4. We finally JUMP to the duplicate handler All the above logic is implemented in InlineExceptionHandlersPhase.apply(bblock: BasicBlock)

   Q: Why do we need to duplicate the handler? A: An exception might be thrown in a method that we invoke in the function and we cannot see that THROW command directly. In order to catch such exceptions, we keep the exception handler in place and duplicate it in order to inline its code.

5. #### abstract class Inliners extends SubComponent

   Inliner balances two competing goals: (a) aggressive inlining of: (a.1) the apply methods of anonymous closures, so that their anon-classes can be eliminated; (a.2) higher-order-methods defined in an external library, e.g.

   Inliner balances two competing goals: (a) aggressive inlining of: (a.1) the apply methods of anonymous closures, so that their anon-classes can be eliminated; (a.2) higher-order-methods defined in an external library, e.g. `Range.foreach()` among many others. (b) circumventing the barrier to inter-library inlining that private accesses in the callee impose.

   Summing up the discussion in SI-5442 and SI-5891, the current implementation achieves to a large degree both goals above, and overcomes a problem exhibited by previous versions:

   (1) Problem: Attempting to access a private member `p` at runtime resulting in an `IllegalAccessError`, where `p` is defined in a library L, and is accessed from a library C (for Client), where C was compiled against L', an optimized version of L where the inliner made `p` public at the bytecode level. The only such members are fields, either synthetic or isParamAccessor, and thus having a dollar sign in their name (the accessibility of methods and constructors isn't touched by the inliner).

   Thus we add one more goal to our list: (c) Compile C (either optimized or not) against any of L or L', so that it runs with either L or L' (in particular, compile against L' and run with L).

   The chosen strategy is described in some detail in the comments for `accessRequirements()` and `potentiallyPublicized()`. Documentation at http://lamp.epfl.ch/~magarcia/ScalaCompilerCornerReloaded/2011Q4/Inliner.pdf

### Ungrouped