Reduce LambdaForm creation and use caching to improve the performance of
Considerably reduce memory footprint while preserving current
Many method-handle transforms (e.g., `MethodHandles::filterReturnValue`)
create many new LambdaForm instances for each transformed method handle.
This induces excessive memory usage in applications that make heavy use
of method handles.
The current method-handle implementation instantiates LambdaForms too
aggressively. The proposed approach is two-fold: Share LambdaForm
instances and their bytecodes for similar transformations, and cache
lambda forms for different combinators on a per-basic-type basis (see
Existing tests give good coverage of functionality. Some focused tests
(i.e., white-box tests verifying actual sharing in different cases) are
- mlvm tests
- Nashorn unit tests
- ECMA test262
- Octane benchmarks
- out-of-box: no flags
- assertions: `-ea -esa`
- interpreted vs. compiled LFs:
Risks and Assumptions
The implementation shouldn't cause any regression in peak performance.
Experiments show, however, that preserving peak performance may prevent
maximal sharing in some situations (e.g., `MethodHandles.guardWithTest`,
where profile pollution due to sharing distorts inlining decisions of JIT
compiler). We'll need to find a suitable balance between footprint
reduction and peak performance during development.
The changes are concentrated in Java portion of the method-handle
implementation (i.e., the `java.lang.invoke` and `sun.invoke` packages).
There is no impact upon those who don't use method handles. No new APIs
will be added and no existing APIs will be changed.