diff options
author | Lukas Rytz <lukas.rytz@gmail.com> | 2014-08-13 10:30:27 +0200 |
---|---|---|
committer | Lukas Rytz <lukas.rytz@gmail.com> | 2014-08-19 17:54:22 +0200 |
commit | 22295833c33298064b40469a1ff0e491be5f80a1 (patch) | |
tree | 4da665cca0e30334aa855f20fd5799c56298aebf /src | |
parent | 53437e61305d656c115c94b25845c8f8dd7342ca (diff) | |
download | scala-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.
Diffstat (limited to 'src')
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" |