Closed
Description
Java 8 allows interfaces to contain default implementations of methods. This is done by
removing a restriction in the bytecode, interface methods may now have a code attribute.
Current trait encoding
- typically, a concrete method in a Scala trait results in:
- in the interface: an deferred method in the interface
- in the impl class: an impl method containing the body of the method, taking
$this
as an extra parameter - in each subclass: a forwarder method that implements the interface method and forwards to the implementation class
Proposed encoding
- Do away with the impl methods, instead leaving the code in a default method of the interface method
- Optional: omit forwarder methods in subclasses if the JVM would link an invokeinterface
to the same method as the forwarder would target. - when forwarders are still used, or when we encode
super[Trait].method
, we can useinvokespecial
to call the default implementation of interface method.
Benefits
- making it easier to extends traits from Java, including with Java lambdas
- which will obviate the layer of
JFunctionN
interfaces initially used to back Scala 2.12 lambdas
- which will obviate the layer of
- adding a concrete method to a trait can be a binary compatible without requiring subclasses to recompile
- (if we omit forwarders) reduced bytecode size
- (if we omit forwarders) avoid the JIT-hostile code shapes of the artificially megamorphic calls, where all implementations of the methods are just forwarders to the same implementation method.
Non Benefits
- fields in traits still require "intimate" recompilation of trait and subclass.
Steps
- Update GenBCode to enable emission of default methods #38 Enable emission of defaults
- Bridge or omit troublesome additional abstract methods in specialized traits #36 Handle interaction with specialization
- Remove
AddInterfaces
, impl classes, and redirect references to impl methods to default methods #37 Do away with impl classes