dropModule instead of deprecated stripModuleSuffix
Level 1 of the new optimizer: intra-method optimizations

Intra-method optimizations are performed until a fixpoint is reached.
They are grouped somewhat arbitrarily into:
  - collapse a multi-jump chain to target its final destination via a single jump
  - remove unreachable code
  - remove those LabelNodes and LineNumbers that aren't in use
  - replace the last link in a chain of data accesses by a direct access to the chain-start.
  - dead-store elimination
  - remove those (producer, consumer) pairs where the consumer is a DROP and
    the producer has its value consumed only by the DROP in question.
  - nullness propagation
  - constant folding

After the fixpoint has been reached, two more intra-method optimizations are performed just once
(further applications wouldn't reduce any further):
  - eliding box/unbox pairs
  - eliding redundant local vars
Late Anonymous-Closure Classes: GenBCode dehydrates them (+ TODO)

Transform a Function node
  (x_1,...,x_n) => body
of type
  FunctionN[T_1, .., T_N, R]
into a Block expression of the form:

    {
      def hoisted(x_1: T_1, ..., x_N: T_n): R = body

      hoisted(zeroes-for-params-above).asInstanceOf[AbstractFunctionN[T_1, .., T_N, R]]
    }

GenBCode will emit either:

  (a) an anonymous closure class and its instantiation ( under -closurify:delegating )
      or
  (b) a method handle given as constructor-argument to a closure instantiation ( under -closurify:MH )

That way, the compiler has less work to do during specialize, explicitouter, erasure, and lambdalift, among others.

The resulting anon-closure-classes have smaller constant pools, which significantly shrinks output size (good for mobile devices).
Further classfile-size reductions can be obtained using -neo:o1 (ie intra-method optimizations, which lower the instruction count).

TODO
  compiling test\files\continuations-run\t3223.scala
  with options -P:continuations:enable -Xpluginsdir build\quick\misc\scala-devel\plugins -Xplugin-require:continuations
  trips an assertion in GenBCode.
squash outer pointer of Late-Closure-Classes

During UnCurry, closureConversionModern() lowers a Function node into a Block of the form:

   {
     def hoisted(x_1: T_1, ..., x_N: T_n): R = body

     hoisted(zeroes-for-params-above).asInstanceOf[AbstractFunctionN[T_1, .., T_N, R]]
   }

The "hoisted" method becomes a bytecode-level instance-method, unless the class declaring it is an implementation-class derived from a trait (in which case "hoisted" becomes a bytecode-level static method).

An instance "hoisted" method usually implies that an outer-pointer is required by the anon-closure-class (unless the class declaring the "hoisted method" is a Scala-level static module, in which case the anon-closure knows how to grab the correct instance via GETSTATIC MODULE$ thus doing without an outer-pointer)

Oftentimes an instance "hoisted method" actually does not dependen on THIS, or depends only on lifted-methods (thus not part of the public API) which themselves exhibit such property (not depend on THIS or depend only on methods that don't actually require THIS).

In class LCCOuterSquasher, method squashOuterForLCC() detects the largest subset of "hoisted methods" (aka endpoints) that can be made static, under the constraint that only lifted-methods can be made static. This constraint amounts to leaving the public API unchanged.

Once that subset has been determined, all usages of those "must-be-made-static" methods are found, and rewritten as appropriate.
Finally, each Late-Closure-Class amenable to this transformation is refactored:
  - its $outer field is removed,
  - its constructor is adapted to remove the param for the outer-pointer.

Compiler flag -Ylog:jvm informs which anon-closures have their outer-pointer squashed.
bytecode-repository for method-inlining purposes
bytecode-repository for closure-inlining purposes
making final those methods we want to be inlined
new optimizer: method inlining, closure inlining

The ICode-based inliner has a few problems:

  (a) closure elimination is implemented as repeated method inlinings.
      Upon being forced to stop with that (e.g., recursive method) none of the previous inlinings is undone, leaving both the closure class and a trail of duplicate code.

  (b) code may be inlined from third-party libraries or the JDK. In general methods not marked @inline may be inlined as discussed in thread the perils of inlining

  (c) invocation cycles (ie M1() calling M2() calling M1() etc) are "broken" only after hitting the maximum method size threshold, leaving a trail of duplicate code behind.

Instead, the new optimizer just follows a simple principle:

    only inline @inline-marked methods, and always inline them, including under separate-compilation

Thus the new inliner is deterministic, not dependent on heuristics about method sizes or similar.
The only additional requirement (if you will) is for the method to be dispatched (the one marked @inline) to be determined via the static type of the receiver.
For example, in a Range.foreach() callsite the type of the receiver must be Range or subtype (in general, not a super type of another which overrides the @inline method).
After all, inlining is a conscious decision: making that explicit via the type of the receiver is straightforward.
As a result, the @noinline annotation doesn't play a role anymore.

Under -Ylog:jvm , the new optimizer provides detailed logging about performed inlinings, as well as diagnostics when inlining proves unfeasible (down to the culprit bytecode instructions).
typo back in Level 1's BCodeType's TypeFlowInterpreter
another typo in Level 1's commit
new optimizer: GC-savvy closures

This commit adds support for singleton closures, and closure state minimization. The optimizations in question are intra-program, thus get applied at level -neo:o2 or higher.

  (1) Some anonymous closures depend only on apply() arguments, ie they capture no values.
      In such cases, code is emitted that avoids repeated closure allocations by keeping (in a static field added to that effect) a singleton-instance that is reused.

  (2) Lack of usages of a Late-Closure-Class (eg as a result of dead-code elimination) means the closure can be elided, along with its endpoint. This may lead to further tree-shaking (via UnusedPrivateDetector).

  (3) Minimization of closure-fields (in particular, outer) to those actually used.
      Field removal requires adapting both the closure allocation site, and the Late-Closure-Class itself.
      For example, removing the outer-pointer also requires turning the closure's endpoint into a static method.
      Closure allocations remain, but with smaller GC overhead.