summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@gmail.com>2015-09-23 13:53:35 +0200
committerLukas Rytz <lukas.rytz@gmail.com>2015-09-23 13:53:35 +0200
commitf9dbade4dbc3a888f927983c164b83ef5d500af9 (patch)
treed241abb3de557a60ad283d3926f4ff68ed9f13d3
parent708868227d43b3f0c0a6037b27c15faa9b2110e3 (diff)
downloadscala-f9dbade4dbc3a888f927983c164b83ef5d500af9.tar.gz
scala-f9dbade4dbc3a888f927983c164b83ef5d500af9.tar.bz2
scala-f9dbade4dbc3a888f927983c164b83ef5d500af9.zip
Move addLambdaDeserialize into the BTypes assembly
This allows accessing the method from the inliner, which doesn't have access to the Global instance.
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala54
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala14
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala57
4 files changed, 65 insertions, 62 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala
index 0f381a4325..bc3bdfc6ba 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala
@@ -683,60 +683,6 @@ abstract class BCodeHelpers extends BCodeIdiomatic with BytecodeWriters {
new java.lang.Long(id)
).visitEnd()
}
-
- /**
- * Add:
- * private static java.util.Map $deserializeLambdaCache$ = null
- * private static Object $deserializeLambda$(SerializedLambda l) {
- * var cache = $deserializeLambdaCache$
- * if (cache eq null) {
- * cache = new java.util.HashMap()
- * $deserializeLambdaCache$ = cache
- * }
- * return scala.runtime.LambdaDeserializer.deserializeLambda(MethodHandles.lookup(), cache, l);
- * }
- */
- def addLambdaDeserialize(clazz: Symbol, jclass: asm.ClassVisitor): Unit = {
- val cw = jclass
- import scala.tools.asm.Opcodes._
-
- // Need to force creation of BTypes for these as `getCommonSuperClass` is called on
- // automatically computing the max stack size (`visitMaxs`) during method writing.
- javaUtilHashMapReference
- javaUtilMapReference
-
- cw.visitInnerClass("java/lang/invoke/MethodHandles$Lookup", "java/lang/invoke/MethodHandles", "Lookup", ACC_PUBLIC + ACC_FINAL + ACC_STATIC)
-
- {
- val fv = cw.visitField(ACC_PRIVATE + ACC_STATIC + ACC_SYNTHETIC, "$deserializeLambdaCache$", "Ljava/util/Map;", null, null)
- fv.visitEnd()
- }
-
- {
- val mv = cw.visitMethod(ACC_PRIVATE + ACC_STATIC + ACC_SYNTHETIC, "$deserializeLambda$", "(Ljava/lang/invoke/SerializedLambda;)Ljava/lang/Object;", null, null)
- mv.visitCode()
- // javaBinaryName returns the internal name of a class. Also used in BTypesFromsymbols.classBTypeFromSymbol.
- mv.visitFieldInsn(GETSTATIC, clazz.javaBinaryName.toString, "$deserializeLambdaCache$", "Ljava/util/Map;")
- mv.visitVarInsn(ASTORE, 1)
- mv.visitVarInsn(ALOAD, 1)
- val l0 = new asm.Label()
- mv.visitJumpInsn(IFNONNULL, l0)
- mv.visitTypeInsn(NEW, "java/util/HashMap")
- mv.visitInsn(DUP)
- mv.visitMethodInsn(INVOKESPECIAL, "java/util/HashMap", "<init>", "()V", false)
- mv.visitVarInsn(ASTORE, 1)
- mv.visitVarInsn(ALOAD, 1)
- mv.visitFieldInsn(PUTSTATIC, clazz.javaBinaryName.toString, "$deserializeLambdaCache$", "Ljava/util/Map;")
- mv.visitLabel(l0)
- mv.visitFieldInsn(GETSTATIC, "scala/runtime/LambdaDeserializer$", "MODULE$", "Lscala/runtime/LambdaDeserializer$;")
- mv.visitMethodInsn(INVOKESTATIC, "java/lang/invoke/MethodHandles", "lookup", "()Ljava/lang/invoke/MethodHandles$Lookup;", false)
- mv.visitVarInsn(ALOAD, 1)
- mv.visitVarInsn(ALOAD, 0)
- mv.visitMethodInsn(INVOKEVIRTUAL, "scala/runtime/LambdaDeserializer$", "deserializeLambda", "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/util/Map;Ljava/lang/invoke/SerializedLambda;)Ljava/lang/Object;", false)
- mv.visitInsn(ARETURN)
- mv.visitEnd()
- }
- }
} // end of trait BCClassGen
/* functionality for building plain and mirror classes */
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala
index 9875ade113..8d8ffe31d2 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala
@@ -130,7 +130,7 @@ abstract class BCodeSkelBuilder extends BCodeHelpers {
&& indyLambdaHosts.contains(claszSymbol))
if (shouldAddLambdaDeserialize)
- addLambdaDeserialize(claszSymbol, cnode)
+ backendUtils.addLambdaDeserialize(cnode)
addInnerClassesASM(cnode, innerClassBufferASM.toList)
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala b/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala
index 00ca096e59..48e43c74f4 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala
@@ -206,12 +206,14 @@ trait CoreBTypesProxyGlobalIndependent[BTS <: BTypes] {
def boxedClasses: Set[ClassBType]
- def RT_NOTHING : ClassBType
- def RT_NULL : ClassBType
-
- def ObjectReference : ClassBType
- def jlCloneableReference : ClassBType
- def jioSerializableReference : ClassBType
+ def RT_NOTHING: ClassBType
+ def RT_NULL : ClassBType
+
+ def ObjectReference : ClassBType
+ def jlCloneableReference : ClassBType
+ def jioSerializableReference: ClassBType
+ def javaUtilHashMapReference: ClassBType
+ def javaUtilMapReference : ClassBType
}
/**
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala b/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala
index f4badd8383..4e0d7a4c44 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala
@@ -2,7 +2,8 @@ package scala.tools.nsc
package backend.jvm
package analysis
-import scala.tools.asm.tree.{AbstractInsnNode, MethodNode}
+import scala.tools.asm.Label
+import scala.tools.asm.tree.{ClassNode, AbstractInsnNode, MethodNode}
import scala.tools.asm.tree.analysis.{Frame, BasicInterpreter, Analyzer, Value}
import scala.tools.nsc.backend.jvm.BTypes._
import scala.tools.nsc.backend.jvm.opt.BytecodeUtils._
@@ -47,4 +48,58 @@ class BackendUtils[BT <: BTypes](val btypes: BT) {
}
class ProdConsAnalyzer(val methodNode: MethodNode, classInternalName: InternalName) extends AsmAnalyzer(methodNode, classInternalName, new Analyzer(new InitialProducerSourceInterpreter)) with ProdConsAnalyzerImpl
+
+ /**
+ * Add:
+ * private static java.util.Map $deserializeLambdaCache$ = null
+ * private static Object $deserializeLambda$(SerializedLambda l) {
+ * var cache = $deserializeLambdaCache$
+ * if (cache eq null) {
+ * cache = new java.util.HashMap()
+ * $deserializeLambdaCache$ = cache
+ * }
+ * return scala.runtime.LambdaDeserializer.deserializeLambda(MethodHandles.lookup(), cache, l);
+ * }
+ */
+ def addLambdaDeserialize(classNode: ClassNode): Unit = {
+ val cw = classNode
+ import scala.tools.asm.Opcodes._
+
+ // Need to force creation of BTypes for these as `getCommonSuperClass` is called on
+ // automatically computing the max stack size (`visitMaxs`) during method writing.
+ btypes.coreBTypes.javaUtilHashMapReference
+ btypes.coreBTypes.javaUtilMapReference
+
+ cw.visitInnerClass("java/lang/invoke/MethodHandles$Lookup", "java/lang/invoke/MethodHandles", "Lookup", ACC_PUBLIC + ACC_FINAL + ACC_STATIC)
+
+ {
+ val fv = cw.visitField(ACC_PRIVATE + ACC_STATIC + ACC_SYNTHETIC, "$deserializeLambdaCache$", "Ljava/util/Map;", null, null)
+ fv.visitEnd()
+ }
+
+ {
+ val mv = cw.visitMethod(ACC_PRIVATE + ACC_STATIC + ACC_SYNTHETIC, "$deserializeLambda$", "(Ljava/lang/invoke/SerializedLambda;)Ljava/lang/Object;", null, null)
+ mv.visitCode()
+ // javaBinaryName returns the internal name of a class. Also used in BTypesFromsymbols.classBTypeFromSymbol.
+ mv.visitFieldInsn(GETSTATIC, classNode.name, "$deserializeLambdaCache$", "Ljava/util/Map;")
+ mv.visitVarInsn(ASTORE, 1)
+ mv.visitVarInsn(ALOAD, 1)
+ val l0 = new Label()
+ mv.visitJumpInsn(IFNONNULL, l0)
+ mv.visitTypeInsn(NEW, "java/util/HashMap")
+ mv.visitInsn(DUP)
+ mv.visitMethodInsn(INVOKESPECIAL, "java/util/HashMap", "<init>", "()V", false)
+ mv.visitVarInsn(ASTORE, 1)
+ mv.visitVarInsn(ALOAD, 1)
+ mv.visitFieldInsn(PUTSTATIC, classNode.name, "$deserializeLambdaCache$", "Ljava/util/Map;")
+ mv.visitLabel(l0)
+ mv.visitFieldInsn(GETSTATIC, "scala/runtime/LambdaDeserializer$", "MODULE$", "Lscala/runtime/LambdaDeserializer$;")
+ mv.visitMethodInsn(INVOKESTATIC, "java/lang/invoke/MethodHandles", "lookup", "()Ljava/lang/invoke/MethodHandles$Lookup;", false)
+ mv.visitVarInsn(ALOAD, 1)
+ mv.visitVarInsn(ALOAD, 0)
+ mv.visitMethodInsn(INVOKEVIRTUAL, "scala/runtime/LambdaDeserializer$", "deserializeLambda", "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/util/Map;Ljava/lang/invoke/SerializedLambda;)Ljava/lang/Object;", false)
+ mv.visitInsn(ARETURN)
+ mv.visitEnd()
+ }
+ }
}