Skip to content

Commit 35bf85a

Browse files
committed
WIP serialization
1 parent aefeedf commit 35bf85a

File tree

4 files changed

+72
-3
lines changed

4 files changed

+72
-3
lines changed

src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1312,16 +1312,34 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
13121312
mt.toASMType
13131313
}
13141314

1315+
val FLAG_SERIALIZABLE = 1
1316+
val FLAG_MARKERS = 2
1317+
val flags: Int = FLAG_SERIALIZABLE | FLAG_MARKERS
1318+
val ScalaSerializable = classBTypeFromSymbol(definitions.SerializableClass).toASMType
13151319
bc.jmethod.visitInvokeDynamicInsn(methodName, desc, lambdaMetaFactoryBootstrapHandle,
13161320
// boostrap args
1317-
applyN, targetHandle, constrainedType
1321+
applyN, targetHandle, constrainedType,
1322+
flags.asInstanceOf[AnyRef], 1.asInstanceOf[AnyRef], ScalaSerializable, 0.asInstanceOf[AnyRef]
13181323
)
13191324
}
13201325
}
13211326

1327+
// CallSite altMetafactory(MethodHandles.Lookup caller,
1328+
// String invokedName,
1329+
1330+
// MethodType invokedType,
1331+
// MethodType samMethodType,
1332+
// MethodHandle implMethod,
1333+
// MethodType instantiatedMethodType,
1334+
// int flags,
1335+
// int markerInterfaceCount, // IF flags has MARKERS set
1336+
// Class... markerInterfaces, // IF flags has MARKERS set
1337+
// int bridgeCount, // IF flags has BRIDGES set
1338+
// MethodType... bridges // IF flags has BRIDGES set
1339+
// )
13221340
val lambdaMetaFactoryBootstrapHandle =
13231341
new asm.Handle(asm.Opcodes.H_INVOKESTATIC,
1324-
"java/lang/invoke/LambdaMetafactory", "metafactory",
1325-
"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;")
1342+
definitions.LambdaMetaFactory.fullName('/'), sn.AltMetafactory.toString,
1343+
"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;")
13261344

13271345
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package scala.runtime
2+
3+
import java.lang.invoke._
4+
5+
//
6+
// class C { def foo = { () => "" } }
7+
//
8+
// class C {
9+
// def foo = { LMF(anonFun$1 };
10+
// private def anonFun$1 = "";
11+
// private <static> val lambdaDeserializer$1 = new LambdaDeserializer(MethodHandles.lookup))
12+
// def $deserializeLambda$(serialized: SerializedLambda) = lambdaDeserializer$1.deserializeLambda(serialized) }
13+
// }
14+
//
15+
final class LambdaDeserializer(lookup: MethodHandles.Lookup) {
16+
def deserializeLambda(serialized: SerializedLambda): AnyRef = {
17+
val caller = lookup
18+
// serialized.getFunctionalInterfaceClass
19+
val loader = lookup.lookupClass().getClassLoader
20+
val funcInterfacesSignature = MethodType.fromMethodDescriptorString(serialized.getFunctionalInterfaceMethodSignature, loader)
21+
val methodType = funcInterfacesSignature
22+
val instantiated = MethodType.fromMethodDescriptorString(serialized.getInstantiatedMethodType, loader)
23+
// val invokedType = MethodType.methodType(loader.loadClass(serialized.getFunctionalInterfaceClass.replaceAll("/", ".")))
24+
val implMethodSig = MethodType.fromMethodDescriptorString(serialized.getImplMethodSignature, loader)
25+
val implClass =loader.loadClass(serialized.getImplClass)
26+
27+
val from = implMethodSig.parameterCount() - funcInterfacesSignature.parameterCount()
28+
val to = implMethodSig.parameterCount()
29+
val invokedType = implMethodSig.dropParameterTypes(from, to).changeReturnType(loader.loadClass(serialized.getFunctionalInterfaceClass.replaceAll("/", ".")))
30+
31+
32+
val implMethod: MethodHandle = {
33+
serialized.getImplMethodKind match {
34+
case MethodHandleInfo.REF_invokeStatic =>
35+
caller.findStatic(implClass, serialized.getImplMethodName, implMethodSig)
36+
case MethodHandleInfo.REF_invokeVirtual =>
37+
caller.findVirtual(implClass, serialized.getImplMethodName, implMethodSig)
38+
}
39+
}
40+
val site = LambdaMetafactory.metafactory(caller, serialized.getFunctionalInterfaceMethodName, invokedType, methodType, implMethod, methodType)
41+
val factory = site.getTarget
42+
val captures = (0 to serialized.getCapturedArgCount).map(serialized.getCapturedArg)
43+
val r = factory.invokeWithArguments(captures: _*)
44+
r
45+
}
46+
}
47+

src/reflect/scala/reflect/internal/Definitions.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,7 @@ trait Definitions extends api.StandardDefinitions {
514514
lazy val ScalaSignatureAnnotation = requiredClass[scala.reflect.ScalaSignature]
515515
lazy val ScalaLongSignatureAnnotation = requiredClass[scala.reflect.ScalaLongSignature]
516516

517+
lazy val LambdaMetaFactory = getClassIfDefined("java.lang.invoke.LambdaMetafactory")
517518
lazy val MethodHandle = getClassIfDefined("java.lang.invoke.MethodHandle")
518519

519520
// Option classes

src/reflect/scala/reflect/internal/StdNames.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1167,6 +1167,9 @@ trait StdNames {
11671167
final val Invoke: TermName = newTermName("invoke")
11681168
final val InvokeExact: TermName = newTermName("invokeExact")
11691169

1170+
final val Metafactory: TermName = newTermName("metafactory")
1171+
final val AltMetafactory: TermName = newTermName("altMetafactory")
1172+
11701173
val Boxed = immutable.Map[TypeName, TypeName](
11711174
tpnme.Boolean -> BoxedBoolean,
11721175
tpnme.Byte -> BoxedByte,

0 commit comments

Comments
 (0)