From 22295833c33298064b40469a1ff0e491be5f80a1 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Wed, 13 Aug 2014 10:30:27 +0200 Subject: 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. --- .../tools/nsc/backend/jvm/BCodeBodyBuilder.scala | 1 + .../scala/tools/nsc/backend/jvm/BCodeHelpers.scala | 1 + .../tools/nsc/backend/jvm/BCodeIdiomatic.scala | 1 + .../tools/nsc/backend/jvm/BCodeSkelBuilder.scala | 1 + .../tools/nsc/backend/jvm/BCodeSyncAndTry.scala | 2 +- .../scala/tools/nsc/backend/jvm/BTypes.scala | 18 +- .../tools/nsc/backend/jvm/BTypesFromSymbols.scala | 10 +- .../scala/tools/nsc/backend/jvm/CoreBTypes.scala | 420 +++++++++++---------- .../scala/tools/nsc/backend/jvm/GenBCode.scala | 1 + 9 files changed, 253 insertions(+), 202 deletions(-) (limited to 'src/compiler/scala/tools/nsc') 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" -- cgit v1.2.3