diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2015-04-17 14:55:04 +1000 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2015-04-17 15:39:37 +1000 |
commit | 1aa97cb81b96cbf1e7b7b2cd42dd5bd3d8e5c6dd (patch) | |
tree | c8cbc6e20a8c453080a54ab583efb233cf0f8b5f /lib | |
parent | b730937493f8f25c985b1a4cf5fcfb7fc16092a4 (diff) | |
download | scala-1aa97cb81b96cbf1e7b7b2cd42dd5bd3d8e5c6dd.tar.gz scala-1aa97cb81b96cbf1e7b7b2cd42dd5bd3d8e5c6dd.tar.bz2 scala-1aa97cb81b96cbf1e7b7b2cd42dd5bd3d8e5c6dd.zip |
Make lambda body public rather than using static accessor
Under -Ydelambdafy:method (the basis of the upcoming "indylambda"
translation for -target:jvm-1.8), an anonymous function is currently
encoded as:
1. a private method containing the lambda's code
2. a public, static accessor method that allows access to 1 from
other classes, namely:
3. an anonymous class capturing free variables and implementing
the suitable FunctionN interface.
In our prototypes of indylambda, we do away with 3, instead deferring
creating of this class to JDK8's LambdaMetafactory by way of an
invokedynamic instruction at the point of lambda capture. This
facility can use a private method as the lambda target; access is
mediated by the runtime-provided instance of
`java.lang.invoke.MethodHandles.Lookup` that confers the privelages
of the lambda capture call site to the generated implementation class.
Indeed, The java compiler uses this to emit private lambda body
methods.
However, there are two Scala specific factors that make this
a little troublesome.
First, Scala's optimizer may want to inline the lambda capture
call site into a new enclosing class. In general, this isn't a
safe optimization, as `invokedynamic` instructions have call-site
specific semantics. But we will rely the ability to inline like
this in order to eliminate closures altogether where possible.
Second, to support lambda deserialization, the Java compiler creates
a synthetic method `$dersializeLamda$` in each class that captures
them, just to be able to get the suitable access to spin up an
anoymous class with access to the private method. It only needs
to do this for functional interfaces that extends Serializable,
which is the exception rather than the rule. But in Scala, *every*
function must support serialization, so blindly copying the Java
approach will lead to some code bloat.
I have prototyped a hybrid approach to these challenges: use the
private method directly where it is allowed, but fall back to
using the accessor method in a generic lambda deserializer or
in call sites that have been inlined into a new enclosing class.
However, the most straight forward approach is to simply emit the
lambda bodies as public (with an mangled name and with the SYHTNETIC
flag) and use them in all cases. That is what is done in this commit.
This does moves us one step backwards from the goals of SI-7085,
but it doesn't seem sensible to incur the inconvenience from locking
down one small part of our house when we don't have a plan or the
budget to complete that job.
The REPL has some fancy logic to decompile the bodys of lambdas
(`:javap -fun C#m`) which needed tweaking to accomodate this change.
I haven't tried to make this backwards compatible with the old
encoding as `-Ydelambdafy:method` is still experimental.
Diffstat (limited to 'lib')
0 files changed, 0 insertions, 0 deletions