summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@gmail.com>2014-08-13 10:30:27 +0200
committerLukas Rytz <lukas.rytz@gmail.com>2014-08-19 17:54:22 +0200
commit22295833c33298064b40469a1ff0e491be5f80a1 (patch)
tree4da665cca0e30334aa855f20fd5799c56298aebf
parent53437e61305d656c115c94b25845c8f8dd7342ca (diff)
downloadscala-22295833c33298064b40469a1ff0e491be5f80a1.tar.gz
scala-22295833c33298064b40469a1ff0e491be5f80a1.tar.bz2
scala-22295833c33298064b40469a1ff0e491be5f80a1.zip
Integrate CoreBTypes by composition (not inheritance), non-var fields
Make the fields of CoreBTypes non-variable. Instead, replace the CoreBTypes instance on each compiler run. That results in fewer variables, and the initialization code is directly where the fields are declared, instead of an init method.
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala1
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala1
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala1
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala1
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BCodeSyncAndTry.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala18
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala10
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala420
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala1
9 files changed, 253 insertions, 202 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala
index 05a2867a3a..2e629485a0 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala
@@ -25,6 +25,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
import definitions._
import bCodeICodeCommon._
import bTypes._
+ import coreBTypes._
/*
* Functionality to build the body of ASM MethodNode, except for `synchronized` and `try` expressions.
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala
index c14997628f..18a9bad1b7 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala
@@ -21,6 +21,7 @@ import scala.tools.nsc.io.AbstractFile
abstract class BCodeHelpers extends BCodeIdiomatic with BytecodeWriters {
import global._
import bTypes._
+ import coreBTypes._
/*
* must-single-thread
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala
index 290e899ba4..5d187168db 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala
@@ -25,6 +25,7 @@ abstract class BCodeIdiomatic extends SubComponent {
import global._
import bTypes._
+ import coreBTypes._
val classfileVersion: Int = settings.target.value match {
case "jvm-1.5" => asm.Opcodes.V1_5
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala
index 35a9962620..3f3c0d0620 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala
@@ -26,6 +26,7 @@ import java.io.PrintWriter
abstract class BCodeSkelBuilder extends BCodeHelpers {
import global._
import bTypes._
+ import coreBTypes._
/*
* There's a dedicated PlainClassBuilder for each CompilationUnit,
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeSyncAndTry.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeSyncAndTry.scala
index c271e7b129..7c95b7fc3b 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeSyncAndTry.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeSyncAndTry.scala
@@ -21,7 +21,7 @@ import scala.tools.asm
abstract class BCodeSyncAndTry extends BCodeBodyBuilder {
import global._
import bTypes._
-
+ import coreBTypes._
/*
* Functionality to lower `synchronized` and `try` expressions.
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala b/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala
index 390de5fae1..389dbe43eb 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala
@@ -42,6 +42,12 @@ abstract class BTypes {
*/
def classBTypeFromInternalName(internalName: String) = classBTypeFromInternalNameMap(internalName)
+ // Some core BTypes are required here, in class BType, where no Global instance is available.
+ // The Global is only available in the subclass BTypesFromSymbols. We cannot depend on the actual
+ // implementation (CoreBTypesProxy) here because it has members that refer to global.Symbol.
+ val coreBTypes: CoreBTypesProxyGlobalIndependent[this.type]
+ import coreBTypes._
+
/**
* A BType is either a primitve type, a ClassBType, an ArrayBType of one of these, or a MethodType
* referring to BTypes.
@@ -834,14 +840,10 @@ abstract class BTypes {
* They are defs (not vals) because they are implemented using vars (see comment on CoreBTypes).
*/
- def boxedClasses: Set[ClassBType]
-
- def RT_NOTHING : ClassBType
- def RT_NULL : ClassBType
-
- def ObjectReference : ClassBType
- def jlCloneableReference : ClassBType
- def jioSerializableReference : ClassBType
+ /**
+ * Just a named pair, used in CoreBTypes.asmBoxTo/asmUnboxTo.
+ */
+ final case class MethodNameAndType(name: String, methodType: MethodBType)
/**
* True if the current compilation unit is of a primitive class (scala.Boolean et al).
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala
index 3b11a484bb..da3244ba23 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala
@@ -20,10 +20,18 @@ import scala.tools.asm
* of the core btypes. They are declared in BTypes as abstract members. Note that BTypes does
* not have access to the compiler instance.
*/
-class BTypesFromSymbols[G <: Global](val global: G) extends BTypes with CoreBTypes[G] {
+class BTypesFromSymbols[G <: Global](val global: G) extends BTypes {
import global._
import definitions._
+ // Why the proxy, see documentation of class [[CoreBTypes]].
+ val coreBTypes = new CoreBTypesProxy[this.type](this)
+ import coreBTypes._
+
+ final def intializeCoreBTypes(): Unit = {
+ coreBTypes.setBTypes(new CoreBTypes[this.type](this))
+ }
+
def internalNameString(offset: Int, length: Int) = new String(global.chrs, offset, length)
protected val classBTypeFromInternalNameMap = {
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala b/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala
index d92e775185..fac3c93be2 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala
@@ -7,16 +7,27 @@ import scala.annotation.switch
* Core BTypes and some other definitions. The initialization of these definitions requies access
* to symbols / types (global).
*
- * There is a reason for using vars instead of lazy vals. The symbols used to initialize the
- * ClassBTypes may change from one compiler run to the next. To make sure the definitions are
- * consistent with the symbols in the current run, the `intializeCoreBTypes` (which assigns the
- * vars) is executed once for every compiler run.
+ * The symbols used to initialize the ClassBTypes may change from one compiler run to the next. To
+ * make sure the definitions are consistent with the symbols in the current run, the
+ * `intializeCoreBTypes` method in BTypesFromSymbols creates a new instance of CoreBTypes in each
+ * compiler run.
*
- * Note: if they were lazy vals, BType.classBTypeFromInternalNameMap could not be a perRunCache
- * anymore: the classes defeined here need to be in that map, they are added when the ClassBTypes
- * are created. The per run cache removes them, so they would be missing in the second run.
+ * The class BTypesFromSymbols does not directly reference CoreBTypes, but CoreBTypesProxy. The
+ * reason is that having a `var bTypes: CoreBTypes` would not allow `import bTypes._`. Instead, the
+ * proxy class holds a `CoreBTypes` in a variable field and forwards to this instance.
+ *
+ * The definitions in `CoreBTypes` need to be lazy vals to break an initialization cycle. When
+ * creating a new instance to assign to the proxy, the `classBTypeFromSymbol` invoked in the
+ * constructor will actucally go through the proxy. The lazy vals make sure the instance is assigned
+ * in the proxy before the fields are initialized.
+ *
+ * Note: if we did not re-create the core BTypes on each compiler run, BType.classBTypeFromInternalNameMap
+ * could not be a perRunCache anymore: the classes defeined here need to be in that map, they are
+ * added when the ClassBTypes are created. The per run cache removes them, so they would be missing
+ * in the second run.
*/
-trait CoreBTypes[G <: Global] { self: BTypesFromSymbols[G] =>
+class CoreBTypes[BTFS <: BTypesFromSymbols[_ <: Global]](val bTypes: BTFS) {
+ import bTypes._
import global._
import rootMirror.{requiredClass, getClassIfDefined}
import definitions._
@@ -25,36 +36,62 @@ trait CoreBTypes[G <: Global] { self: BTypesFromSymbols[G] =>
* Maps primitive types to their corresponding PrimitiveBType. The map is defined lexically above
* the first use of `classBTypeFromSymbol` because that method looks at the map.
*/
- var primitiveTypeMap: Map[Symbol, PrimitiveBType] = _
-
- var BOXED_UNIT : ClassBType = _
- var BOXED_BOOLEAN : ClassBType = _
- var BOXED_BYTE : ClassBType = _
- var BOXED_SHORT : ClassBType = _
- var BOXED_CHAR : ClassBType = _
- var BOXED_INT : ClassBType = _
- var BOXED_LONG : ClassBType = _
- var BOXED_FLOAT : ClassBType = _
- var BOXED_DOUBLE : ClassBType = _
-
- var boxedClasses: Set[ClassBType] = _
+ lazy val primitiveTypeMap: Map[Symbol, PrimitiveBType] = Map(
+ UnitClass -> UNIT,
+ BooleanClass -> BOOL,
+ CharClass -> CHAR,
+ ByteClass -> BYTE,
+ ShortClass -> SHORT,
+ IntClass -> INT,
+ LongClass -> LONG,
+ FloatClass -> FLOAT,
+ DoubleClass -> DOUBLE
+ )
+
+ lazy val BOXED_UNIT : ClassBType = classBTypeFromSymbol(requiredClass[java.lang.Void])
+ lazy val BOXED_BOOLEAN : ClassBType = classBTypeFromSymbol(BoxedBooleanClass)
+ lazy val BOXED_BYTE : ClassBType = classBTypeFromSymbol(BoxedByteClass)
+ lazy val BOXED_SHORT : ClassBType = classBTypeFromSymbol(BoxedShortClass)
+ lazy val BOXED_CHAR : ClassBType = classBTypeFromSymbol(BoxedCharacterClass)
+ lazy val BOXED_INT : ClassBType = classBTypeFromSymbol(BoxedIntClass)
+ lazy val BOXED_LONG : ClassBType = classBTypeFromSymbol(BoxedLongClass)
+ lazy val BOXED_FLOAT : ClassBType = classBTypeFromSymbol(BoxedFloatClass)
+ lazy val BOXED_DOUBLE : ClassBType = classBTypeFromSymbol(BoxedDoubleClass)
/**
* Map from primitive types to their boxed class type. Useful when pushing class literals onto the
* operand stack (ldc instruction taking a class literal), see genConstant.
*/
- var boxedClassOfPrimitive: Map[PrimitiveBType, ClassBType] = _
+ lazy val boxedClassOfPrimitive: Map[PrimitiveBType, ClassBType] = Map(
+ UNIT -> BOXED_UNIT,
+ BOOL -> BOXED_BOOLEAN,
+ BYTE -> BOXED_BYTE,
+ SHORT -> BOXED_SHORT,
+ CHAR -> BOXED_CHAR,
+ INT -> BOXED_INT,
+ LONG -> BOXED_LONG,
+ FLOAT -> BOXED_FLOAT,
+ DOUBLE -> BOXED_DOUBLE
+ )
+
+ lazy val boxedClasses: Set[ClassBType] = boxedClassOfPrimitive.values.toSet
/**
* Maps the method symbol for a box method to the boxed type of the result. For example, the
* method symbol for `Byte.box()` is mapped to the ClassBType `java/lang/Byte`.
*/
- var boxResultType: Map[Symbol, ClassBType] = _
+ lazy val boxResultType: Map[Symbol, ClassBType] = {
+ for ((valueClassSym, boxMethodSym) <- currentRun.runDefinitions.boxMethod)
+ yield boxMethodSym -> boxedClassOfPrimitive(primitiveTypeMap(valueClassSym))
+ }
/**
* Maps the method symbol for an unbox method to the primitive type of the result.
* For example, the method symbol for `Byte.unbox()`) is mapped to the PrimitiveBType BYTE. */
- var unboxResultType: Map[Symbol, PrimitiveBType] = _
+ lazy val unboxResultType: Map[Symbol, PrimitiveBType] = {
+ for ((valueClassSym, unboxMethodSym) <- currentRun.runDefinitions.unboxMethod)
+ yield unboxMethodSym -> primitiveTypeMap(valueClassSym)
+ }
/*
* RT_NOTHING and RT_NULL exist at run-time only. They are the bytecode-level manifestation (in
@@ -62,196 +99,195 @@ trait CoreBTypes[G <: Global] { self: BTypesFromSymbols[G] =>
*
* Therefore, when RT_NOTHING or RT_NULL are to be emitted, a mapping is needed: the internal
* names of NothingClass and NullClass can't be emitted as-is.
+ * TODO @lry Once there's a 2.11.3 starr, use the commented argument list. The current starr crashes on the type literal `scala.runtime.Nothing$`
*/
- var RT_NOTHING : ClassBType = _
- var RT_NULL : ClassBType = _
+ lazy val RT_NOTHING : ClassBType = classBTypeFromSymbol(rootMirror.getRequiredClass("scala.runtime.Nothing$")) // (requiredClass[scala.runtime.Nothing$])
+ lazy val RT_NULL : ClassBType = classBTypeFromSymbol(rootMirror.getRequiredClass("scala.runtime.Null$")) // (requiredClass[scala.runtime.Null$])
- var ObjectReference : ClassBType = _
- var objArrayReference : ArrayBType = _
+ lazy val ObjectReference : ClassBType = classBTypeFromSymbol(ObjectClass)
+ lazy val objArrayReference : ArrayBType = ArrayBType(ObjectReference)
- var StringReference : ClassBType = _
- var StringBuilderReference : ClassBType = _
- var ThrowableReference : ClassBType = _
- var jlCloneableReference : ClassBType = _
- var jlNPEReference : ClassBType = _
- var jioSerializableReference : ClassBType = _
- var scalaSerializableReference : ClassBType = _
- var classCastExceptionReference : ClassBType = _
+ lazy val StringReference : ClassBType = classBTypeFromSymbol(StringClass)
+ lazy val StringBuilderReference : ClassBType = classBTypeFromSymbol(StringBuilderClass)
+ lazy val ThrowableReference : ClassBType = classBTypeFromSymbol(ThrowableClass)
+ lazy val jlCloneableReference : ClassBType = classBTypeFromSymbol(JavaCloneableClass) // java/lang/Cloneable
+ lazy val jlNPEReference : ClassBType = classBTypeFromSymbol(NullPointerExceptionClass) // java/lang/NullPointerException
+ lazy val jioSerializableReference : ClassBType = classBTypeFromSymbol(JavaSerializableClass) // java/io/Serializable
+ lazy val scalaSerializableReference : ClassBType = classBTypeFromSymbol(SerializableClass) // scala/Serializable
+ lazy val classCastExceptionReference : ClassBType = classBTypeFromSymbol(ClassCastExceptionClass) // java/lang/ClassCastException
- var srBooleanRef : ClassBType = _
- var srByteRef : ClassBType = _
- var srCharRef : ClassBType = _
- var srIntRef : ClassBType = _
- var srLongRef : ClassBType = _
- var srFloatRef : ClassBType = _
- var srDoubleRef : ClassBType = _
+ lazy val srBooleanRef : ClassBType = classBTypeFromSymbol(requiredClass[scala.runtime.BooleanRef])
+ lazy val srByteRef : ClassBType = classBTypeFromSymbol(requiredClass[scala.runtime.ByteRef])
+ lazy val srCharRef : ClassBType = classBTypeFromSymbol(requiredClass[scala.runtime.CharRef])
+ lazy val srIntRef : ClassBType = classBTypeFromSymbol(requiredClass[scala.runtime.IntRef])
+ lazy val srLongRef : ClassBType = classBTypeFromSymbol(requiredClass[scala.runtime.LongRef])
+ lazy val srFloatRef : ClassBType = classBTypeFromSymbol(requiredClass[scala.runtime.FloatRef])
+ lazy val srDoubleRef : ClassBType = classBTypeFromSymbol(requiredClass[scala.runtime.DoubleRef])
- var hashMethodSym: Symbol = _
+ lazy val hashMethodSym: Symbol = getMember(ScalaRunTimeModule, nme.hash_)
- var AndroidParcelableInterface : Symbol = _
- var AndroidCreatorClass : Symbol = _
+ // TODO @lry avoiding going through through missingHook for every line in the REPL: https://github.com/scala/scala/commit/8d962ed4ddd310cc784121c426a2e3f56a112540
+ lazy val AndroidParcelableInterface : Symbol = getClassIfDefined("android.os.Parcelable")
+ lazy val AndroidCreatorClass : Symbol = getClassIfDefined("android.os.Parcelable$Creator")
- var BeanInfoAttr: Symbol = _
+ lazy val BeanInfoAttr: Symbol = requiredClass[scala.beans.BeanInfo]
/* The Object => String overload. */
- var String_valueOf: Symbol = _
+ lazy val String_valueOf: Symbol = {
+ getMember(StringModule, nme.valueOf) filter (sym => sym.info.paramTypes match {
+ case List(pt) => pt.typeSymbol == ObjectClass
+ case _ => false
+ })
+ }
// scala.FunctionX and scala.runtim.AbstractFunctionX
- var FunctionReference : Vector[ClassBType] = _
- var AbstractFunctionReference : Vector[ClassBType] = _
- var AbstractFunctionArityMap : Map[ClassBType, Int] = _
-
- var PartialFunctionReference : ClassBType = _
- var AbstractPartialFunctionReference : ClassBType = _
+ lazy val FunctionReference : Vector[ClassBType] = (0 to MaxFunctionArity).map(i => classBTypeFromSymbol(FunctionClass(i)))(collection.breakOut)
+ lazy val AbstractFunctionReference : Vector[ClassBType] = (0 to MaxFunctionArity).map(i => classBTypeFromSymbol(AbstractFunctionClass(i)))(collection.breakOut)
+ lazy val AbstractFunctionArityMap : Map[ClassBType, Int] = AbstractFunctionReference.zipWithIndex.toMap
- var BoxesRunTime: ClassBType = _
+ lazy val PartialFunctionReference : ClassBType = classBTypeFromSymbol(PartialFunctionClass)
+ lazy val AbstractPartialFunctionReference : ClassBType = classBTypeFromSymbol(AbstractPartialFunctionClass)
- case class MethodNameAndType(name: String, methodType: MethodBType)
+ lazy val BoxesRunTime: ClassBType = classBTypeFromSymbol(requiredClass[scala.runtime.BoxesRunTime])
/**
* Methods in scala.runtime.BoxesRuntime
*/
- var asmBoxTo : Map[BType, MethodNameAndType] = _
- var asmUnboxTo: Map[BType, MethodNameAndType] = _
+ lazy val asmBoxTo : Map[BType, MethodNameAndType] = Map(
+ BOOL -> MethodNameAndType("boxToBoolean", MethodBType(List(BOOL), BOXED_BOOLEAN)),
+ BYTE -> MethodNameAndType("boxToByte", MethodBType(List(BYTE), BOXED_BYTE)),
+ CHAR -> MethodNameAndType("boxToCharacter", MethodBType(List(CHAR), BOXED_CHAR)),
+ SHORT -> MethodNameAndType("boxToShort", MethodBType(List(SHORT), BOXED_SHORT)),
+ INT -> MethodNameAndType("boxToInteger", MethodBType(List(INT), BOXED_INT)),
+ LONG -> MethodNameAndType("boxToLong", MethodBType(List(LONG), BOXED_LONG)),
+ FLOAT -> MethodNameAndType("boxToFloat", MethodBType(List(FLOAT), BOXED_FLOAT)),
+ DOUBLE -> MethodNameAndType("boxToDouble", MethodBType(List(DOUBLE), BOXED_DOUBLE))
+ )
+
+ lazy val asmUnboxTo: Map[BType, MethodNameAndType] = Map(
+ BOOL -> MethodNameAndType("unboxToBoolean", MethodBType(List(ObjectReference), BOOL)),
+ BYTE -> MethodNameAndType("unboxToByte", MethodBType(List(ObjectReference), BYTE)),
+ CHAR -> MethodNameAndType("unboxToChar", MethodBType(List(ObjectReference), CHAR)),
+ SHORT -> MethodNameAndType("unboxToShort", MethodBType(List(ObjectReference), SHORT)),
+ INT -> MethodNameAndType("unboxToInt", MethodBType(List(ObjectReference), INT)),
+ LONG -> MethodNameAndType("unboxToLong", MethodBType(List(ObjectReference), LONG)),
+ FLOAT -> MethodNameAndType("unboxToFloat", MethodBType(List(ObjectReference), FLOAT)),
+ DOUBLE -> MethodNameAndType("unboxToDouble", MethodBType(List(ObjectReference), DOUBLE))
+ )
+
+ lazy val typeOfArrayOp: Map[Int, BType] = {
+ import scalaPrimitives._
+ Map(
+ (List(ZARRAY_LENGTH, ZARRAY_GET, ZARRAY_SET) map (_ -> BOOL)) ++
+ (List(BARRAY_LENGTH, BARRAY_GET, BARRAY_SET) map (_ -> BYTE)) ++
+ (List(SARRAY_LENGTH, SARRAY_GET, SARRAY_SET) map (_ -> SHORT)) ++
+ (List(CARRAY_LENGTH, CARRAY_GET, CARRAY_SET) map (_ -> CHAR)) ++
+ (List(IARRAY_LENGTH, IARRAY_GET, IARRAY_SET) map (_ -> INT)) ++
+ (List(LARRAY_LENGTH, LARRAY_GET, LARRAY_SET) map (_ -> LONG)) ++
+ (List(FARRAY_LENGTH, FARRAY_GET, FARRAY_SET) map (_ -> FLOAT)) ++
+ (List(DARRAY_LENGTH, DARRAY_GET, DARRAY_SET) map (_ -> DOUBLE)) ++
+ (List(OARRAY_LENGTH, OARRAY_GET, OARRAY_SET) map (_ -> ObjectReference)) : _*
+ )
+ }
+}
- var typeOfArrayOp: Map[Int, BType] = _
+/**
+ * This trait make some core BTypes availalbe that don't depend on a Global instance. Some core
+ * BTypes are required to be accessible in the BTypes trait, which does not have access to Global.
+ *
+ * BTypes cannot refer to CoreBTypesProxy because some of its members depend on global, for example
+ * the type Symbol in
+ * def primitiveTypeMap: Map[Symbol, PrimitiveBType]
+ */
+trait CoreBTypesProxyGlobalIndependent[BTS <: BTypes] {
+ val bTypes: BTS
+ import bTypes._
- /**
- * Initialize core ClassBTypes computed from symbols. Invoked once for each compiler run.
- */
- def intializeCoreBTypes(): Unit = {
- primitiveTypeMap = Map(
- UnitClass -> UNIT,
- BooleanClass -> BOOL,
- CharClass -> CHAR,
- ByteClass -> BYTE,
- ShortClass -> SHORT,
- IntClass -> INT,
- LongClass -> LONG,
- FloatClass -> FLOAT,
- DoubleClass -> DOUBLE
- )
+ def boxedClasses: Set[ClassBType]
- BOXED_UNIT = classBTypeFromSymbol(requiredClass[java.lang.Void])
- BOXED_BOOLEAN = classBTypeFromSymbol(BoxedBooleanClass)
- BOXED_BYTE = classBTypeFromSymbol(BoxedByteClass)
- BOXED_SHORT = classBTypeFromSymbol(BoxedShortClass)
- BOXED_CHAR = classBTypeFromSymbol(BoxedCharacterClass)
- BOXED_INT = classBTypeFromSymbol(BoxedIntClass)
- BOXED_LONG = classBTypeFromSymbol(BoxedLongClass)
- BOXED_FLOAT = classBTypeFromSymbol(BoxedFloatClass)
- BOXED_DOUBLE = classBTypeFromSymbol(BoxedDoubleClass)
-
- boxedClassOfPrimitive = Map(
- UNIT -> BOXED_UNIT,
- BOOL -> BOXED_BOOLEAN,
- BYTE -> BOXED_BYTE,
- SHORT -> BOXED_SHORT,
- CHAR -> BOXED_CHAR,
- INT -> BOXED_INT,
- LONG -> BOXED_LONG,
- FLOAT -> BOXED_FLOAT,
- DOUBLE -> BOXED_DOUBLE
- )
+ def RT_NOTHING : ClassBType
+ def RT_NULL : ClassBType
- boxedClasses = boxedClassOfPrimitive.values.toSet
-
- boxResultType = {
- for ((valueClassSym, boxMethodSym) <- currentRun.runDefinitions.boxMethod)
- yield boxMethodSym -> boxedClassOfPrimitive(primitiveTypeMap(valueClassSym))
- }
-
- unboxResultType = {
- for ((valueClassSym, unboxMethodSym) <- currentRun.runDefinitions.unboxMethod)
- yield unboxMethodSym -> primitiveTypeMap(valueClassSym)
- }
-
- // TODO @lry Once there's a 2.11.2 starr, use the commented argument list. The current starr crashes on the type literal `scala.runtime.Nothing$`
- RT_NOTHING = classBTypeFromSymbol(rootMirror.getRequiredClass("scala.runtime.Nothing$")) // (requiredClass[scala.runtime.Nothing$])
- RT_NULL = classBTypeFromSymbol(rootMirror.getRequiredClass("scala.runtime.Null$")) // (requiredClass[scala.runtime.Null$])
-
- ObjectReference = classBTypeFromSymbol(ObjectClass)
- objArrayReference = ArrayBType(ObjectReference)
-
- StringReference = classBTypeFromSymbol(StringClass)
- StringBuilderReference = classBTypeFromSymbol(StringBuilderClass)
- ThrowableReference = classBTypeFromSymbol(ThrowableClass)
- jlCloneableReference = classBTypeFromSymbol(JavaCloneableClass) // java/lang/Cloneable
- jlNPEReference = classBTypeFromSymbol(NullPointerExceptionClass) // java/lang/NullPointerException
- jioSerializableReference = classBTypeFromSymbol(JavaSerializableClass) // java/io/Serializable
- scalaSerializableReference = classBTypeFromSymbol(SerializableClass) // scala/Serializable
- classCastExceptionReference = classBTypeFromSymbol(ClassCastExceptionClass) // java/lang/ClassCastException
-
- srBooleanRef = classBTypeFromSymbol(requiredClass[scala.runtime.BooleanRef])
- srByteRef = classBTypeFromSymbol(requiredClass[scala.runtime.ByteRef])
- srCharRef = classBTypeFromSymbol(requiredClass[scala.runtime.CharRef])
- srIntRef = classBTypeFromSymbol(requiredClass[scala.runtime.IntRef])
- srLongRef = classBTypeFromSymbol(requiredClass[scala.runtime.LongRef])
- srFloatRef = classBTypeFromSymbol(requiredClass[scala.runtime.FloatRef])
- srDoubleRef = classBTypeFromSymbol(requiredClass[scala.runtime.DoubleRef])
-
- hashMethodSym = getMember(ScalaRunTimeModule, nme.hash_)
-
- // TODO @lry avoiding going through through missingHook for every line in the REPL: https://github.com/scala/scala/commit/8d962ed4ddd310cc784121c426a2e3f56a112540
- AndroidParcelableInterface = getClassIfDefined("android.os.Parcelable")
- AndroidCreatorClass = getClassIfDefined("android.os.Parcelable$Creator")
-
- BeanInfoAttr = requiredClass[scala.beans.BeanInfo]
-
- String_valueOf = {
- getMember(StringModule, nme.valueOf) filter (sym => sym.info.paramTypes match {
- case List(pt) => pt.typeSymbol == ObjectClass
- case _ => false
- })
- }
-
- // scala.FunctionX and scala.runtim.AbstractFunctionX
- FunctionReference = (0 to MaxFunctionArity).map(i => classBTypeFromSymbol(FunctionClass(i)))(collection.breakOut)
-
- AbstractFunctionReference = (0 to MaxFunctionArity).map(i => classBTypeFromSymbol(AbstractFunctionClass(i)))(collection.breakOut)
-
- AbstractFunctionArityMap = AbstractFunctionReference.zipWithIndex.toMap
-
- PartialFunctionReference = classBTypeFromSymbol(PartialFunctionClass)
- AbstractPartialFunctionReference = classBTypeFromSymbol(AbstractPartialFunctionClass)
-
- BoxesRunTime = classBTypeFromSymbol(requiredClass[scala.runtime.BoxesRunTime])
-
- asmBoxTo = Map(
- BOOL -> MethodNameAndType("boxToBoolean", MethodBType(List(BOOL), BOXED_BOOLEAN)),
- BYTE -> MethodNameAndType("boxToByte", MethodBType(List(BYTE), BOXED_BYTE)),
- CHAR -> MethodNameAndType("boxToCharacter", MethodBType(List(CHAR), BOXED_CHAR)),
- SHORT -> MethodNameAndType("boxToShort", MethodBType(List(SHORT), BOXED_SHORT)),
- INT -> MethodNameAndType("boxToInteger", MethodBType(List(INT), BOXED_INT)),
- LONG -> MethodNameAndType("boxToLong", MethodBType(List(LONG), BOXED_LONG)),
- FLOAT -> MethodNameAndType("boxToFloat", MethodBType(List(FLOAT), BOXED_FLOAT)),
- DOUBLE -> MethodNameAndType("boxToDouble", MethodBType(List(DOUBLE), BOXED_DOUBLE))
- )
+ def ObjectReference : ClassBType
+ def jlCloneableReference : ClassBType
+ def jioSerializableReference : ClassBType
+}
- asmUnboxTo = Map(
- BOOL -> MethodNameAndType("unboxToBoolean", MethodBType(List(ObjectReference), BOOL)),
- BYTE -> MethodNameAndType("unboxToByte", MethodBType(List(ObjectReference), BYTE)),
- CHAR -> MethodNameAndType("unboxToChar", MethodBType(List(ObjectReference), CHAR)),
- SHORT -> MethodNameAndType("unboxToShort", MethodBType(List(ObjectReference), SHORT)),
- INT -> MethodNameAndType("unboxToInt", MethodBType(List(ObjectReference), INT)),
- LONG -> MethodNameAndType("unboxToLong", MethodBType(List(ObjectReference), LONG)),
- FLOAT -> MethodNameAndType("unboxToFloat", MethodBType(List(ObjectReference), FLOAT)),
- DOUBLE -> MethodNameAndType("unboxToDouble", MethodBType(List(ObjectReference), DOUBLE))
- )
+/**
+ * See comment in class [[CoreBTypes]].
+ */
+final class CoreBTypesProxy[BTFS <: BTypesFromSymbols[_ <: Global]](val bTypes: BTFS) extends CoreBTypesProxyGlobalIndependent[BTFS] {
+ import bTypes._
+ import global._
- typeOfArrayOp = {
- import scalaPrimitives._
- Map(
- (List(ZARRAY_LENGTH, ZARRAY_GET, ZARRAY_SET) map (_ -> BOOL)) ++
- (List(BARRAY_LENGTH, BARRAY_GET, BARRAY_SET) map (_ -> BYTE)) ++
- (List(SARRAY_LENGTH, SARRAY_GET, SARRAY_SET) map (_ -> SHORT)) ++
- (List(CARRAY_LENGTH, CARRAY_GET, CARRAY_SET) map (_ -> CHAR)) ++
- (List(IARRAY_LENGTH, IARRAY_GET, IARRAY_SET) map (_ -> INT)) ++
- (List(LARRAY_LENGTH, LARRAY_GET, LARRAY_SET) map (_ -> LONG)) ++
- (List(FARRAY_LENGTH, FARRAY_GET, FARRAY_SET) map (_ -> FLOAT)) ++
- (List(DARRAY_LENGTH, DARRAY_GET, DARRAY_SET) map (_ -> DOUBLE)) ++
- (List(OARRAY_LENGTH, OARRAY_GET, OARRAY_SET) map (_ -> ObjectReference)) : _*
- )
- }
+ private[this] var _coreBTypes: CoreBTypes[bTypes.type] = _
+ def setBTypes(coreBTypes: CoreBTypes[BTFS]): Unit = {
+ _coreBTypes = coreBTypes.asInstanceOf[CoreBTypes[bTypes.type]]
}
+
+ def primitiveTypeMap: Map[Symbol, PrimitiveBType] = _coreBTypes.primitiveTypeMap
+
+ def BOXED_UNIT : ClassBType = _coreBTypes.BOXED_UNIT
+ def BOXED_BOOLEAN : ClassBType = _coreBTypes.BOXED_BOOLEAN
+ def BOXED_BYTE : ClassBType = _coreBTypes.BOXED_BYTE
+ def BOXED_SHORT : ClassBType = _coreBTypes.BOXED_SHORT
+ def BOXED_CHAR : ClassBType = _coreBTypes.BOXED_CHAR
+ def BOXED_INT : ClassBType = _coreBTypes.BOXED_INT
+ def BOXED_LONG : ClassBType = _coreBTypes.BOXED_LONG
+ def BOXED_FLOAT : ClassBType = _coreBTypes.BOXED_FLOAT
+ def BOXED_DOUBLE : ClassBType = _coreBTypes.BOXED_DOUBLE
+
+ def boxedClasses: Set[ClassBType] = _coreBTypes.boxedClasses
+
+ def boxedClassOfPrimitive: Map[PrimitiveBType, ClassBType] = _coreBTypes.boxedClassOfPrimitive
+
+ def boxResultType: Map[Symbol, ClassBType] = _coreBTypes.boxResultType
+
+ def unboxResultType: Map[Symbol, PrimitiveBType] = _coreBTypes.unboxResultType
+
+ def RT_NOTHING : ClassBType = _coreBTypes.RT_NOTHING
+ def RT_NULL : ClassBType = _coreBTypes.RT_NULL
+
+ def ObjectReference : ClassBType = _coreBTypes.ObjectReference
+ def objArrayReference : ArrayBType = _coreBTypes.objArrayReference
+
+ def StringReference : ClassBType = _coreBTypes.StringReference
+ def StringBuilderReference : ClassBType = _coreBTypes.StringBuilderReference
+ def ThrowableReference : ClassBType = _coreBTypes.ThrowableReference
+ def jlCloneableReference : ClassBType = _coreBTypes.jlCloneableReference
+ def jlNPEReference : ClassBType = _coreBTypes.jlNPEReference
+ def jioSerializableReference : ClassBType = _coreBTypes.jioSerializableReference
+ def scalaSerializableReference : ClassBType = _coreBTypes.scalaSerializableReference
+ def classCastExceptionReference : ClassBType = _coreBTypes.classCastExceptionReference
+
+ def srBooleanRef : ClassBType = _coreBTypes.srBooleanRef
+ def srByteRef : ClassBType = _coreBTypes.srByteRef
+ def srCharRef : ClassBType = _coreBTypes.srCharRef
+ def srIntRef : ClassBType = _coreBTypes.srIntRef
+ def srLongRef : ClassBType = _coreBTypes.srLongRef
+ def srFloatRef : ClassBType = _coreBTypes.srFloatRef
+ def srDoubleRef : ClassBType = _coreBTypes.srDoubleRef
+
+ def hashMethodSym: Symbol = _coreBTypes.hashMethodSym
+
+ def AndroidParcelableInterface : Symbol = _coreBTypes.AndroidParcelableInterface
+ def AndroidCreatorClass : Symbol = _coreBTypes.AndroidCreatorClass
+
+ def BeanInfoAttr: Symbol = _coreBTypes.BeanInfoAttr
+
+ def String_valueOf: Symbol = _coreBTypes.String_valueOf
+
+ def FunctionReference : Vector[ClassBType] = _coreBTypes.FunctionReference
+ def AbstractFunctionReference : Vector[ClassBType] = _coreBTypes.AbstractFunctionReference
+ def AbstractFunctionArityMap : Map[ClassBType, Int] = _coreBTypes.AbstractFunctionArityMap
+
+ def PartialFunctionReference : ClassBType = _coreBTypes.PartialFunctionReference
+ def AbstractPartialFunctionReference : ClassBType = _coreBTypes.AbstractPartialFunctionReference
+
+ def BoxesRunTime: ClassBType = _coreBTypes.BoxesRunTime
+
+ def asmBoxTo : Map[BType, MethodNameAndType] = _coreBTypes.asmBoxTo
+ def asmUnboxTo: Map[BType, MethodNameAndType] = _coreBTypes.asmUnboxTo
+
+ def typeOfArrayOp: Map[Int, BType] = _coreBTypes.typeOfArrayOp
}
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala
index 480767f407..0a7c894a69 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala
@@ -47,6 +47,7 @@ abstract class GenBCode extends BCodeSyncAndTry {
import global._
import bTypes._
+ import coreBTypes._
val phaseName = "jvm"