diff options
author | Adriaan Moors <adriaan.moors@typesafe.com> | 2014-01-16 12:58:14 -0800 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@typesafe.com> | 2014-01-16 12:58:14 -0800 |
commit | fe408de32ba84a46bba026a17fe3b9311404e5c5 (patch) | |
tree | dfc0f80885caef907a8b1578174be6813161e93d /src/compiler | |
parent | b2963960820734e27d334738cfff5b5354536ec5 (diff) | |
parent | f9cbcbdaf81800b98a6774ca1e1dffcf2875fe4e (diff) | |
download | scala-fe408de32ba84a46bba026a17fe3b9311404e5c5.tar.gz scala-fe408de32ba84a46bba026a17fe3b9311404e5c5.tar.bz2 scala-fe408de32ba84a46bba026a17fe3b9311404e5c5.zip |
Merge pull request #3278 from magarciaEPFL/backendish48
improvements to GenBCode
Diffstat (limited to 'src/compiler')
7 files changed, 50 insertions, 19 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala index 4f9f4c9e31..c8845344e9 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala @@ -88,7 +88,9 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder { def genThrow(expr: Tree): BType = { val thrownKind = tpeTK(expr) - assert(exemplars.get(thrownKind).isSubtypeOf(ThrowableReference)) + // `throw null` is valid although scala.Null (as defined in src/libray-aux) isn't a subtype of Throwable. + // Similarly for scala.Nothing (again, as defined in src/libray-aux). + assert(thrownKind.isNullType || thrownKind.isNothingType || exemplars.get(thrownKind).isSubtypeOf(ThrowableReference)) genLoad(expr, thrownKind) lineNumber(expr) emit(asm.Opcodes.ATHROW) // ICode enters here into enterIgnoreMode, we'll rely instead on DCE at ClassNode level. @@ -824,7 +826,6 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder { /* Generate code that loads args into label parameters. */ def genLoadLabelArguments(args: List[Tree], lblDef: LabelDef, gotoPos: Position) { - assert(args forall { a => !a.hasSymbolField || a.hasSymbolWhich( s => !s.isLabel) }, s"SI-6089 at: $gotoPos") // SI-6089 val aps = { val params: List[Symbol] = lblDef.params.map(_.symbol) @@ -857,12 +858,11 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder { } def genLoadModule(tree: Tree): BType = { - // Working around SI-5604. Rather than failing the compile when we see a package here, check if there's a package object. val module = ( if (!tree.symbol.isPackageClass) tree.symbol else tree.symbol.info.member(nme.PACKAGE) match { - case NoSymbol => abort(s"Cannot use package as value: $tree") ; NoSymbol - case s => devWarning("Bug: found package class where package object expected. Converting.") ; s.moduleClass + case NoSymbol => abort(s"SI-5604: Cannot use package as value: $tree") + case s => abort(s"SI-5604: found package class where package object expected: $tree") } ) lineNumber(tree) @@ -871,7 +871,8 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder { } def genLoadModule(module: Symbol) { - if (claszSymbol == module.moduleClass && jMethodName != "readResolve") { + def inStaticMethod = methSymbol != null && methSymbol.isStaticMember + if (claszSymbol == module.moduleClass && jMethodName != "readResolve" && !inStaticMethod) { mnode.visitVarInsn(asm.Opcodes.ALOAD, 0) } else { val mbt = symInfoTK(module) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeGlue.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeGlue.scala index 9dcf263f4f..cc3265c5f9 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeGlue.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeGlue.scala @@ -661,6 +661,14 @@ abstract class BCodeGlue extends SubComponent { val CT_NOTHING = brefType("scala/Nothing") // TODO needed? val CT_NULL = brefType("scala/Null") // TODO needed? + val srBooleanRef = brefType("scala/runtime/BooleanRef") + val srByteRef = brefType("scala/runtime/ByteRef") + val srCharRef = brefType("scala/runtime/CharRef") + val srIntRef = brefType("scala/runtime/IntRef") + val srLongRef = brefType("scala/runtime/LongRef") + val srFloatRef = brefType("scala/runtime/FloatRef") + val srDoubleRef = brefType("scala/runtime/DoubleRef") + /* Map from type kinds to the Java reference types. * Useful when pushing class literals onto the operand stack (ldc instruction taking a class literal). * @see Predef.classOf diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala index 64ed094a47..6b1bb5b220 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala @@ -440,13 +440,11 @@ abstract class BCodeHelpers extends BCodeTypes with BytecodeWriters { if (sym0 == definitions.NullClass) return RT_NULL; if (sym0 == definitions.NothingClass) return RT_NOTHING; - // Working around SI-5604. Rather than failing the compile when we see - // a package here, check if there's a package object. val sym = ( if (!sym0.isPackageClass) sym0 else sym0.info.member(nme.PACKAGE) match { - case NoSymbol => abort(s"Cannot use package as value: ${sym0.fullName}") - case s => devWarning("Bug: found package class where package object expected. Converting.") ; s.moduleClass + case NoSymbol => abort(s"SI-5604: Cannot use package as value: ${sym0.fullName}") + case s => abort(s"SI-5604: found package class where package object expected: $s") } ) @@ -561,7 +559,9 @@ abstract class BCodeHelpers extends BCodeTypes with BytecodeWriters { memberCTK } - exemplar(csym) // side effect city + + exemplar(csym).directMemberClasses = result + result } diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala index 529295389c..c3492b79a9 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeIdiomatic.scala @@ -46,6 +46,7 @@ abstract class BCodeIdiomatic extends BCodeGlue { val ObjectReference = brefType("java/lang/Object") val AnyRefReference = ObjectReference + val objArrayReference = arrayOf(ObjectReference) val JAVA_LANG_OBJECT = ObjectReference val JAVA_LANG_STRING = brefType("java/lang/String") diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala index c921d11d00..360ce58ecc 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala @@ -460,7 +460,7 @@ abstract class BCodeSkelBuilder extends BCodeHelpers { } def lineNumber(tree: Tree) { if (!emitLines || !tree.pos.isDefined) return; - val nr = tree.pos.line + val nr = tree.pos.finalPosition.line if (nr != lastEmittedLineNr) { lastEmittedLineNr = nr lastInsn match { diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeSyncAndTry.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeSyncAndTry.scala index 27bcbb82d4..9ddb7a3ce8 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeSyncAndTry.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeSyncAndTry.scala @@ -386,10 +386,6 @@ abstract class BCodeSyncAndTry extends BCodeBodyBuilder { /* Does this tree have a try-catch block? */ def mayCleanStack(tree: Tree): Boolean = tree exists { t => t.isInstanceOf[Try] } - abstract class Cleanup(val value: AnyRef) { } - case class MonitorRelease(v: Symbol) extends Cleanup(v) { } - case class Finalizer(f: Tree) extends Cleanup (f) { } - trait EHClause case class NamelessEH(typeToDrop: BType, caseBody: Tree) extends EHClause case class BoundEH (patSymbol: Symbol, caseBody: Tree) extends EHClause diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeTypes.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeTypes.scala index dd2d63ad17..1eca69936a 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeTypes.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeTypes.scala @@ -24,11 +24,15 @@ abstract class BCodeTypes extends BCodeIdiomatic { // when compiling the Scala library, some assertions don't hold (e.g., scala.Boolean has null superClass although it's not an interface) val isCompilingStdLib = !(settings.sourcepath.isDefault) + val srBoxedUnit = brefType("scala/runtime/BoxedUnit") + // special names var StringReference : BType = null var ThrowableReference : BType = null var jlCloneableReference : BType = null // java/lang/Cloneable + var jlNPEReference : BType = null // java/lang/NullPointerException var jioSerializableReference : BType = null // java/io/Serializable + var scalaSerializableReference : BType = null // scala/Serializable var classCastExceptionReference : BType = null // java/lang/ClassCastException /* A map from scala primitive type-symbols to BTypes */ @@ -52,6 +56,8 @@ abstract class BCodeTypes extends BCodeIdiomatic { /* The Object => String overload. */ var String_valueOf: Symbol = null + var ArrayInterfaces: Set[Tracked] = null + // scala.FunctionX and scala.runtim.AbstractFunctionX val FunctionReference = new Array[Tracked](definitions.MaxFunctionArity + 1) val AbstractFunctionReference = new Array[Tracked](definitions.MaxFunctionArity + 1) @@ -128,15 +134,17 @@ abstract class BCodeTypes extends BCodeIdiomatic { ) } - exemplar(JavaCloneableClass).c - exemplar(JavaSerializableClass).c - exemplar(SerializableClass).c + exemplar(JavaCloneableClass) + exemplar(JavaSerializableClass) + exemplar(SerializableClass) StringReference = exemplar(StringClass).c StringBuilderReference = exemplar(StringBuilderClass).c ThrowableReference = exemplar(ThrowableClass).c jlCloneableReference = exemplar(JavaCloneableClass).c + jlNPEReference = exemplar(NullPointerExceptionClass).c jioSerializableReference = exemplar(JavaSerializableClass).c + scalaSerializableReference = exemplar(SerializableClass).c classCastExceptionReference = exemplar(ClassCastExceptionClass).c /* @@ -203,6 +211,23 @@ abstract class BCodeTypes extends BCodeIdiomatic { * All methods of this class can-multi-thread */ case class Tracked(c: BType, flags: Int, sc: Tracked, ifaces: Array[Tracked], innersChain: Array[InnerClassEntry]) { + + // not a case-field because we initialize it only for JVM classes we emit. + private var _directMemberClasses: List[BType] = null + + def directMemberClasses: List[BType] = { + assert(_directMemberClasses != null, s"getter directMemberClasses() invoked too early for $c") + _directMemberClasses + } + + def directMemberClasses_=(bs: List[BType]) { + if (_directMemberClasses != null) { + // TODO we enter here when both mirror class and plain class are emitted for the same ModuleClassSymbol. + assert(_directMemberClasses == bs.sortBy(_.off)) + } + _directMemberClasses = bs.sortBy(_.off) + } + /* `isCompilingStdLib` saves the day when compiling: * (1) scala.Nothing (the test `c.isNonSpecial` fails for it) * (2) scala.Boolean (it has null superClass and is not an interface) |