From 455526f52c0d7a98f2b0bef8f29e7fb542bfe600 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Thu, 16 Aug 2012 15:03:33 -0700 Subject: Large logging cleanup effort. Quieted down many logging statements which contribute disproportionate noise. Made others emit something more sensible. Spent lots of time on the inliner trying to find a regular format to make the logs more readable. Long way to go here but it'd be so worth it to have readable logs instead of mind-numbing indiscriminate text dumps. --- src/compiler/scala/tools/nsc/Global.scala | 5 +- .../scala/tools/nsc/backend/icode/GenICode.scala | 56 ++--- .../backend/icode/analysis/CopyPropagation.scala | 8 +- .../scala/tools/nsc/backend/jvm/GenASM.scala | 4 +- .../scala/tools/nsc/backend/jvm/GenJVM.scala | 4 +- .../tools/nsc/backend/opt/ClosureElimination.scala | 27 ++- .../nsc/backend/opt/DeadCodeElimination.scala | 21 +- .../nsc/backend/opt/InlineExceptionHandlers.scala | 5 +- .../scala/tools/nsc/backend/opt/Inliners.scala | 229 +++++++++++---------- .../scala/tools/nsc/interpreter/IMain.scala | 3 +- .../tools/nsc/symtab/classfile/ICodeReader.scala | 13 +- .../scala/tools/nsc/transform/AddInterfaces.scala | 20 +- .../scala/tools/nsc/transform/Erasure.scala | 8 +- .../scala/tools/nsc/transform/Flatten.scala | 16 +- .../scala/tools/nsc/transform/UnCurry.scala | 6 +- .../scala/tools/nsc/typechecker/Typers.scala | 2 +- .../scala/reflect/internal/SymbolTable.scala | 2 + src/reflect/scala/reflect/internal/Symbols.scala | 2 +- test/files/run/compiler-asSeenFrom.check | 12 +- 19 files changed, 226 insertions(+), 217 deletions(-) diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 80e9ede271..fd05229088 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -271,9 +271,8 @@ class Global(var currentSettings: Settings, var reporter: Reporter) log("Running operation '%s' after every phase.\n".format(msg) + describeAfterEveryPhase(op)) } - def shouldLogAtThisPhase = ( - (settings.log.isSetByUser) - && ((settings.log containsPhase globalPhase) || (settings.log containsPhase phase)) + override def shouldLogAtThisPhase = settings.log.isSetByUser && ( + (settings.log containsPhase globalPhase) || (settings.log containsPhase phase) ) // Over 200 closure objects are eliminated by inlining this. @inline final def log(msg: => AnyRef) { diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala index 431802d185..d3a5975a2a 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala @@ -125,7 +125,7 @@ abstract class GenICode extends SubComponent { // in companion object accessors to @static fields, we access the static field directly val hostClass = m.symbol.owner.companionClass val staticfield = hostClass.info.findMember(m.symbol.accessed.name, NoFlags, NoFlags, false) - + if (m.symbol.isGetter) { ctx1.bb.emit(LOAD_FIELD(staticfield, true) setHostClass hostClass, tree.pos) ctx1.bb.closeWith(RETURN(m.returnType)) @@ -659,16 +659,16 @@ abstract class GenICode extends SubComponent { } else { val sym = tree.symbol val local = ctx.method.addLocal(new Local(sym, toTypeKind(sym.info), false)) - + if (rhs == EmptyTree) { debuglog("Uninitialized variable " + tree + " at: " + (tree.pos)); ctx.bb.emit(getZeroOf(local.kind)) } - + var ctx1 = ctx if (rhs != EmptyTree) ctx1 = genLoad(rhs, ctx, local.kind); - + ctx1.bb.emit(STORE_LOCAL(local), tree.pos) ctx1.scope.add(local) ctx1.bb.emit(SCOPE_ENTER(local)) @@ -727,10 +727,10 @@ abstract class GenICode extends SubComponent { ctx1.bb.enterIgnoreMode generatedType = expectedType ctx1 - } + } genLoadReturn - case t @ Try(_, _, _) => + case t @ Try(_, _, _) => genLoadTry(t, ctx, generatedType = _) case Throw(expr) => @@ -750,7 +750,7 @@ abstract class GenICode extends SubComponent { case Object_asInstanceOf => true case _ => abort("Unexpected type application " + fun + "[sym: " + sym.fullName + "]" + " in: " + tree) } - + val Select(obj, _) = fun val l = toTypeKind(obj.tpe) val r = toTypeKind(targs.head.tpe) @@ -794,7 +794,7 @@ abstract class GenICode extends SubComponent { ctx.bb.emit(THIS(ctx.clazz.symbol), tree.pos) val ctx1 = genLoadArguments(args, fun.symbol.info.paramTypes, ctx) - + ctx1.bb.emit(CALL_METHOD(fun.symbol, invokeStyle), tree.pos) generatedType = if (fun.symbol.isConstructor) UNIT @@ -812,7 +812,7 @@ abstract class GenICode extends SubComponent { val ctor = fun.symbol debugassert(ctor.isClassConstructor, "'new' call to non-constructor: " + ctor.name) - + generatedType = toTypeKind(tpt.tpe) debugassert(generatedType.isReferenceType || generatedType.isArrayType, "Non reference type cannot be instantiated: " + generatedType) @@ -858,7 +858,7 @@ abstract class GenICode extends SubComponent { ctx1 } ctx2 - + case _ => abort("Cannot instantiate " + tpt + " of kind: " + generatedType) } @@ -899,7 +899,7 @@ abstract class GenICode extends SubComponent { ctx1 case app @ Apply(fun @ Select(qual, _), args) - if !ctx.method.symbol.isStaticConstructor + if !ctx.method.symbol.isStaticConstructor && fun.symbol.isAccessor && fun.symbol.accessed.hasStaticAnnotation && qual.tpe.typeSymbol.orElse(fun.symbol.owner).companionClass != NoSymbol => // bypass the accessor to the companion object and load the static field directly @@ -938,11 +938,11 @@ abstract class GenICode extends SubComponent { } } genLoadApply5 - + case app @ Apply(fun, args) => def genLoadApply6 = { val sym = fun.symbol - + if (sym.isLabel) { // jump to a label val label = ctx.labels.getOrElse(sym, { // it is a forward jump, scan for labels @@ -979,7 +979,7 @@ abstract class GenICode extends SubComponent { Static(true) else Dynamic - + var ctx1 = if (invokeStyle.hasInstance) { if (forMSIL && !(invokeStyle.isInstanceOf[SuperCall]) && msil_IsValuetypeInstMethod(sym)) @@ -987,24 +987,26 @@ abstract class GenICode extends SubComponent { else genLoadQualifier(fun, ctx) } else ctx - + ctx1 = genLoadArguments(args, sym.info.paramTypes, ctx1) val cm = CALL_METHOD(sym, invokeStyle) - + /** In a couple cases, squirrel away a little extra information in the * CALL_METHOD for use by GenJVM. */ fun match { case Select(qual, _) => val qualSym = findHostClass(qual.tpe, sym) - - if (qualSym == ArrayClass) cm setTargetTypeKind toTypeKind(qual.tpe) - else cm setHostClass qualSym - - log( - if (qualSym == ArrayClass) "Stored target type kind " + toTypeKind(qual.tpe) + " for " + sym.fullName - else s"Set more precise host class for ${sym.fullName} hostClass: $qualSym" - ) + if (qualSym == ArrayClass) { + val kind = toTypeKind(qual.tpe) + cm setTargetTypeKind kind + log(s"Stored target type kind for {$sym.fullName} as $kind") + } + else { + cm setHostClass qualSym + if (qual.tpe.typeSymbol != qualSym) + log(s"Precisified host class for $sym from ${qual.tpe.typeSymbol.fullName} to ${qualSym.fullName}") + } case _ => } ctx1.bb.emit(cm, tree.pos) @@ -1140,7 +1142,7 @@ abstract class GenICode extends SubComponent { val elmKind = toTypeKind(tpt.tpe) generatedType = ARRAY(elmKind) val elems = _elems.toIndexedSeq - + ctx1.bb.emit(CONSTANT(new Constant(elems.length)), tree.pos) ctx1.bb.emit(CREATE_ARRAY(elmKind, 1)) // inline array literals @@ -1163,7 +1165,7 @@ abstract class GenICode extends SubComponent { val afterCtx = ctx1.newBlock var caseCtx: Context = null generatedType = toTypeKind(tree.tpe) - + var targets: List[BasicBlock] = Nil var tags: List[Int] = Nil var default: BasicBlock = afterCtx.bb @@ -1190,7 +1192,7 @@ abstract class GenICode extends SubComponent { abort("Invalid case statement in switch-like pattern match: " + tree + " at: " + (tree.pos)) } - + caseCtx = genLoad(body, tmpCtx, generatedType) // close the block unless it's already been closed by the body, which closes the block if it ends in a jump (which is emitted to have alternatives share their body) caseCtx.bb.closeWith(JUMP(afterCtx.bb) setPos caze.pos) diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala index d1d8e4a385..df158a29ea 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala @@ -200,7 +200,7 @@ abstract class CopyPropagation { in(b) = lattice.bottom out(b) = lattice.bottom assert(out.contains(b), out) - log("Added point: " + b) + debuglog("CopyAnalysis added point: " + b) } m.exh foreach { e => in(e.startBlock) = new copyLattice.State(copyLattice.emptyBinding, copyLattice.exceptionHandlerStack); @@ -531,11 +531,11 @@ abstract class CopyPropagation { case 0 => () case 1 if ctor.tpe.paramTypes.head == ctor.owner.rawowner.tpe => // it's an unused outer - log("considering unused outer at position 0 in " + ctor.tpe.paramTypes) + debuglog("considering unused outer at position 0 in " + ctor.tpe.paramTypes) paramTypes = paramTypes.tail values = values.tail case _ => - log("giving up on " + ctor + "(diff: " + diff + ")") + debuglog("giving up on " + ctor + "(diff: " + diff + ")") return bindings } @@ -566,7 +566,7 @@ abstract class CopyPropagation { method.blocks map { b => "\nIN(%s):\t Bindings: %s".format(b.label, in(b).bindings) + "\nIN(%s):\t Stack: %s".format(b.label, in(b).stack) - } + } ).mkString } /* class CopyAnalysis */ diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala index b57f5e86a3..ea0a0148e4 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala @@ -154,8 +154,10 @@ abstract class GenASM extends SubComponent with BytecodeWriters { inform("[running phase " + name + " on icode]") if (settings.Xdce.value) - for ((sym, cls) <- icodes.classes if inliner.isClosureClass(sym) && !deadCode.liveClosures(sym)) + for ((sym, cls) <- icodes.classes if inliner.isClosureClass(sym) && !deadCode.liveClosures(sym)) { + log(s"Optimizer eliminated ${sym.fullNameString}") icodes.classes -= sym + } // For predictably ordered error messages. var sortedClasses = classes.values.toList sortBy ("" + _.symbol.fullName) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala index 930791d88d..0f64a55d70 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala @@ -122,8 +122,10 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with inform("[running phase " + name + " on icode]") if (settings.Xdce.value) - for ((sym, cls) <- icodes.classes if inliner.isClosureClass(sym) && !deadCode.liveClosures(sym)) + for ((sym, cls) <- icodes.classes if inliner.isClosureClass(sym) && !deadCode.liveClosures(sym)) { + log(s"Optimizer eliminated ${sym.fullNameString}") icodes.classes -= sym + } // For predictably ordered error messages. val sortedClasses = classes.values.toList sortBy ("" + _.symbol.fullName) diff --git a/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala b/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala index 7772ccbdd5..eb2da72401 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala @@ -35,7 +35,7 @@ abstract class ClosureElimination extends SubComponent { case (STORE_LOCAL(x), LOAD_LOCAL(y)) if (x == y) => var liveOut = liveness.out(bb) if (!liveOut(x)) { - log("store/load to a dead local? " + x) + debuglog("store/load to a dead local? " + x) val instrs = bb.getArray var idx = instrs.length - 1 while (idx > 0 && (instrs(idx) ne i2)) { @@ -43,7 +43,7 @@ abstract class ClosureElimination extends SubComponent { idx -= 1 } if (!liveOut(x)) { - log("removing dead store/load " + x) + log("Removing dead store/load of " + x.sym.initialize.defString) Some(Nil) } else None } else @@ -84,6 +84,7 @@ abstract class ClosureElimination extends SubComponent { */ class ClosureElim { def analyzeClass(cls: IClass): Unit = if (settings.Xcloselim.value) { + log(s"Analyzing ${cls.methods.size} methods in $cls.") cls.methods foreach { m => analyzeMethod(m) peephole(m) @@ -95,7 +96,6 @@ abstract class ClosureElimination extends SubComponent { /* Some embryonic copy propagation. */ def analyzeMethod(m: IMethod): Unit = try {if (m.hasCode) { - log("Analyzing " + m) cpp.init(m) cpp.run @@ -110,23 +110,20 @@ abstract class ClosureElimination extends SubComponent { t match { case Deref(This) | Const(_) => bb.replaceInstruction(i, valueToInstruction(t)); - log("replaced " + i + " with " + t) + debuglog(s"replaced $i with $t") case _ => - bb.replaceInstruction(i, LOAD_LOCAL(info.getAlias(l))) - log("replaced " + i + " with " + info.getAlias(l)) - + val t = info.getAlias(l) + bb.replaceInstruction(i, LOAD_LOCAL(t)) + debuglog(s"replaced $i with $t") } case LOAD_FIELD(f, false) /* if accessible(f, m.symbol) */ => def replaceFieldAccess(r: Record) { val Record(cls, bindings) = r - info.getFieldNonRecordValue(r, f) match { - case Some(v) => - bb.replaceInstruction(i, - DROP(REFERENCE(cls)) :: valueToInstruction(v) :: Nil); - log("Replaced " + i + " with " + info.getFieldNonRecordValue(r, f)); - case None => + info.getFieldNonRecordValue(r, f) foreach { v => + bb.replaceInstruction(i, DROP(REFERENCE(cls)) :: valueToInstruction(v) :: Nil) + debuglog(s"replaced $i with $v") } } @@ -157,14 +154,14 @@ abstract class ClosureElimination extends SubComponent { value match { case Boxed(LocalVar(loc2)) => bb.replaceInstruction(i, DROP(icodes.ObjectReference) :: valueToInstruction(info.getBinding(loc2)) :: Nil) - log("replaced " + i + " with " + info.getBinding(loc2)) + debuglog("replaced " + i + " with " + info.getBinding(loc2)) case _ => () } case Boxed(LocalVar(loc1)) :: _ => val loc2 = info.getAlias(loc1) bb.replaceInstruction(i, DROP(icodes.ObjectReference) :: valueToInstruction(Deref(LocalVar(loc2))) :: Nil) - log("replaced " + i + " with " + LocalVar(loc2)) + debuglog("replaced " + i + " with " + LocalVar(loc2)) case _ => } diff --git a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala index fd949576e1..36a5d61cfb 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala @@ -44,6 +44,7 @@ abstract class DeadCodeElimination extends SubComponent { class DeadCode { def analyzeClass(cls: IClass) { + log(s"Analyzing ${cls.methods.size} methods in $cls.") cls.methods.foreach { m => this.method = m dieCodeDie(m) @@ -73,7 +74,7 @@ abstract class DeadCodeElimination extends SubComponent { def dieCodeDie(m: IMethod) { if (m.hasCode) { - log("dead code elimination on " + m); + debuglog("dead code elimination on " + m); dropOf.clear() m.code.blocks.clear() accessedLocals = m.params.reverse @@ -82,8 +83,10 @@ abstract class DeadCodeElimination extends SubComponent { mark sweep(m) accessedLocals = accessedLocals.distinct - if ((m.locals diff accessedLocals).nonEmpty) { - log("Removed dead locals: " + (m.locals diff accessedLocals)) + val diff = m.locals diff accessedLocals + if (diff.nonEmpty) { + val msg = diff.map(_.sym.name)mkString(", ") + log(s"Removed ${diff.size} dead locals: $msg") m.locals = accessedLocals.reverse } } @@ -126,7 +129,7 @@ abstract class DeadCodeElimination extends SubComponent { case RETURN(_) | JUMP(_) | CJUMP(_, _, _, _) | CZJUMP(_, _, _, _) | STORE_FIELD(_, _) | THROW(_) | LOAD_ARRAY_ITEM(_) | STORE_ARRAY_ITEM(_) | SCOPE_ENTER(_) | SCOPE_EXIT(_) | STORE_THIS(_) | LOAD_EXCEPTION(_) | SWITCH(_, _) | MONITOR_ENTER() | MONITOR_EXIT() => worklist += ((bb, idx)) - case CALL_METHOD(m1, _) if isSideEffecting(m1) => worklist += ((bb, idx)); log("marking " + m1) + case CALL_METHOD(m1, _) if isSideEffecting(m1) => worklist += ((bb, idx)); debuglog("marking " + m1) case CALL_METHOD(m1, SuperCall(_)) => worklist += ((bb, idx)) // super calls to constructor case DROP(_) => @@ -173,7 +176,7 @@ abstract class DeadCodeElimination extends SubComponent { instr match { case LOAD_LOCAL(l1) => for ((l2, bb1, idx1) <- defs((bb, idx)) if l1 == l2; if !useful(bb1)(idx1)) { - log("\tAdding " + bb1(idx1)) + debuglog("\tAdding " + bb1(idx1)) worklist += ((bb1, idx1)) } @@ -197,7 +200,7 @@ abstract class DeadCodeElimination extends SubComponent { case _ => for ((bb1, idx1) <- rdef.findDefs(bb, idx, instr.consumed) if !useful(bb1)(idx1)) { - log("\tAdding " + bb1(idx1)) + debuglog("\tAdding " + bb1(idx1)) worklist += ((bb1, idx1)) } } @@ -232,7 +235,7 @@ abstract class DeadCodeElimination extends SubComponent { } else { i match { case NEW(REFERENCE(sym)) => - log("skipped object creation: " + sym + "inside " + m) + log(s"Eliminated instantation of $sym inside $m") case _ => () } debuglog("Skipped: bb_" + bb + ": " + idx + "( " + i + ")") @@ -240,7 +243,7 @@ abstract class DeadCodeElimination extends SubComponent { } if (bb.nonEmpty) bb.close - else log("empty block encountered") + else log(s"empty block encountered in $m") } } @@ -252,7 +255,7 @@ abstract class DeadCodeElimination extends SubComponent { foreachWithIndex(bb.toList) { (i, idx) => if (!useful(bb)(idx)) { foreachWithIndex(i.consumedTypes.reverse) { (consumedType, depth) => - log("Finding definitions of: " + i + "\n\t" + consumedType + " at depth: " + depth) + debuglog("Finding definitions of: " + i + "\n\t" + consumedType + " at depth: " + depth) val defs = rdef.findDefs(bb, idx, 1, depth) for (d <- defs) { val (bb, idx) = d diff --git a/src/compiler/scala/tools/nsc/backend/opt/InlineExceptionHandlers.scala b/src/compiler/scala/tools/nsc/backend/opt/InlineExceptionHandlers.scala index f1f597322e..98120f0614 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/InlineExceptionHandlers.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/InlineExceptionHandlers.scala @@ -93,10 +93,9 @@ abstract class InlineExceptionHandlers extends SubComponent { val startTime = System.currentTimeMillis currentClass = c - log("Starting " + c) + debuglog("Starting InlineExceptionHandlers on " + c) c.methods foreach applyMethod - - log("Finished " + c + "... " + (System.currentTimeMillis - startTime) + "ms") + debuglog("Finished InlineExceptionHandlers on " + c + "... " + (System.currentTimeMillis - startTime) + "ms") currentClass = null } diff --git a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala index 82d44a0e62..62bb23c3a7 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala @@ -44,7 +44,7 @@ abstract class Inliners extends SubComponent { import definitions.{ NullClass, NothingClass, ObjectClass, PredefModule, RuntimePackage, ScalaInlineClass, ScalaNoInlineClass, - isFunctionType + isFunctionType, isByNameParamType } val phaseName = "inliner" @@ -143,7 +143,6 @@ abstract class Inliners extends SubComponent { } def isBottomType(sym: Symbol) = sym == NullClass || sym == NothingClass - def posToStr(pos: scala.reflect.internal.util.Position) = if (pos.isDefined) pos.point.toString else "" /** Is the given class a closure? */ def isClosureClass(cls: Symbol): Boolean = @@ -194,6 +193,27 @@ abstract class Inliners extends SubComponent { private var currentIClazz: IClass = _ private def warn(pos: Position, msg: String) = currentIClazz.cunit.inlinerWarning(pos, msg) + private def ownedName(sym: Symbol): String = afterUncurry { + val count = ( + if (!sym.isMethod) 1 + else if (sym.owner.isAnonymousFunction) 3 + else 2 + ) + (sym.ownerChain take count filterNot (_.isPackageClass)).reverseMap(_.nameString).mkString(".") + } + private def inlineLog(what: String, main: => String, comment: => String) { + def cstr = comment match { + case "" => "" + case str => " // " + str + } + val width = if (currentIClazz eq null) 40 else currentIClazz.symbol.enclosingPackage.fullName.length + 25 + val fmt = "%8s %-" + width + "s" + cstr + log(fmt.format(what, main)) + } + private def inlineLog(what: String, main: Symbol, comment: => String) { + inlineLog(what, ownedName(main), comment) + } + val recentTFAs = mutable.Map.empty[Symbol, Tuple2[Boolean, analysis.MethodTFA]] private def getRecentTFA(incm: IMethod, forceable: Boolean): (Boolean, analysis.MethodTFA) = { @@ -244,14 +264,15 @@ abstract class Inliners extends SubComponent { def analyzeClass(cls: IClass): Unit = if (settings.inline.value) { - debuglog("Analyzing " + cls) + inlineLog("class", s"${cls.symbol.decodedName}", s"analyzing ${cls.methods.size} methods in $cls") this.currentIClazz = cls val ms = cls.methods sorted imethodOrdering ms foreach { im => - if(hasInline(im.symbol)) { - log("Not inlining into " + im.symbol.originalName.decode + " because it is marked @inline.") - } else if(im.hasCode && !im.symbol.isBridge) { + if (hasInline(im.symbol)) { + inlineLog("skip", im.symbol, "no inlining into @inline methods") + } + else if(im.hasCode && !im.symbol.isBridge) { analyzeMethod(im) } } @@ -296,6 +317,8 @@ abstract class Inliners extends SubComponent { * */ def analyzeMethod(m: IMethod): Unit = { // m.normalize + if (settings.debug.value) + inlineLog("caller", ownedName(m.symbol), "in " + m.symbol.owner.fullName) var sizeBeforeInlining = m.code.blockCount var instrBeforeInlining = m.code.instructionCount @@ -306,8 +329,8 @@ abstract class Inliners extends SubComponent { val fresh = mutable.HashMap.empty[String, Int] withDefaultValue 0 // how many times have we already inlined this method here? val inlinedMethodCount = mutable.HashMap.empty[Symbol, Int] withDefaultValue 0 - val caller = new IMethodInfo(m) + def analyzeMessage = s"Analyzing ${caller.length} blocks of $m for inlining sites." def preInline(isFirstRound: Boolean): Int = { val inputBlocks = caller.m.linearizedBlocks() @@ -354,15 +377,17 @@ abstract class Inliners extends SubComponent { */ def analyzeInc(i: CALL_METHOD, bb: BasicBlock, receiver: Symbol, stackLength: Int, concreteMethod: Symbol): Boolean = { assert(bb.toList contains i, "Candidate callsite does not belong to BasicBlock.") - - var inlined = false val shouldWarn = hasInline(i.method) - def warnNoInline(reason: String) = { - if (shouldWarn) { - warn(i.pos, "Could not inline required method %s because %s.".format(i.method.originalName.decode, reason)) - } - } + def warnNoInline(reason: String): Boolean = { + def msg = "Could not inline required method %s because %s.".format(i.method.originalName.decode, reason) + if (settings.debug.value) + inlineLog("fail", i.method.fullName, reason) + if (shouldWarn) + warn(i.pos, msg) + + false + } var isAvailable = icodes available concreteMethod.enclClass @@ -378,92 +403,69 @@ abstract class Inliners extends SubComponent { isAvailable = icodes.load(concreteMethod.enclClass) } - def isCandidate = ( - isClosureClass(receiver) - || concreteMethod.isEffectivelyFinal - || receiver.isEffectivelyFinal - ) + def isCandidate = ( + isClosureClass(receiver) + || concreteMethod.isEffectivelyFinal + || receiver.isEffectivelyFinal + ) - def isApply = concreteMethod.name == nme.apply + def isApply = concreteMethod.name == nme.apply - def isCountable = !( - isClosureClass(receiver) - || isApply - || isMonadicMethod(concreteMethod) - || receiver.enclosingPackage == definitions.RuntimePackage - ) // only count non-closures + def isCountable = !( + isClosureClass(receiver) + || isApply + || isMonadicMethod(concreteMethod) + || receiver.enclosingPackage == definitions.RuntimePackage + ) // only count non-closures debuglog("Treating " + i + "\n\treceiver: " + receiver + "\n\ticodes.available: " + isAvailable + "\n\tconcreteMethod.isEffectivelyFinal: " + concreteMethod.isEffectivelyFinal) - if (isAvailable && isCandidate) { - lookupIMethod(concreteMethod, receiver) match { - - case Some(callee) if callee.hasCode => - val inc = new IMethodInfo(callee) - val pair = new CallerCalleeInfo(caller, inc, fresh, inlinedMethodCount) - - if(inc.hasHandlers && (stackLength == -1)) { - // no inlining is done, yet don't warn about it, stackLength == -1 indicates we're trying to inlineWithoutTFA. - // Shortly, a TFA will be computed and an error message reported if indeed inlining not possible. - return false - } - - (pair isStampedForInlining stackLength) match { - - case inlInfo if inlInfo.isSafe => - - (inlInfo: @unchecked) match { - - case FeasibleInline(accessNeeded, toBecomePublic) => - for(f <- toBecomePublic) { - debuglog("Making public (synthetic) field-symbol: " + f) - f setFlag Flags.notPRIVATE - f setFlag Flags.notPROTECTED - } - // only add to `knownSafe` after all `toBecomePublic` fields actually made public. - if(accessNeeded == NonPublicRefs.Public) { tfa.knownSafe += inc.sym } - - case InlineableAtThisCaller => () - - } + if (!isCandidate) warnNoInline("it can be overridden") + else if (!isAvailable) warnNoInline("bytecode unavailable") + else lookupIMethod(concreteMethod, receiver) filter (callee => callee.hasCode || warnNoInline("callee has no code")) exists { callee => + val inc = new IMethodInfo(callee) + val pair = new CallerCalleeInfo(caller, inc, fresh, inlinedMethodCount) - retry = true - inlined = true - if (isCountable) { count += 1 }; - - pair.doInline(bb, i) - if (!pair.isInlineForced || inc.isMonadic) { caller.inlinedCalls += 1 }; - inlinedMethodCount(inc.sym) += 1 - - // Remove the caller from the cache (this inlining might have changed its calls-private relation). - usesNonPublics -= m - recentTFAs -= m.symbol - - - case DontInlineHere(msg) => - debuglog("inline failed, reason: " + msg) - warnNoInline(msg) - - case NeverSafeToInline => () - } - - case Some(callee) => - assert(!callee.hasCode, "The case clause right before this one should have handled this case.") - warnNoInline("callee (" + callee + ") has no code") - () + if (inc.hasHandlers && (stackLength == -1)) { + // no inlining is done, yet don't warn about it, stackLength == -1 indicates we're trying to inlineWithoutTFA. + // Shortly, a TFA will be computed and an error message reported if indeed inlining not possible. + false + } + else { + val isSafe = pair isStampedForInlining stackLength match { + case DontInlineHere(msg) => warnNoInline(msg) + case NeverSafeToInline => false + case InlineableAtThisCaller => true + case inl @ FeasibleInline(_, _) if !inl.isSafe => false + case FeasibleInline(required, toPublicize) => + for (f <- toPublicize) { + inlineLog("access", f, "making public") + f setFlag Flags.notPRIVATE + f setFlag Flags.notPROTECTED + } + // only add to `knownSafe` after all `toPublicize` fields actually made public. + if (required == NonPublicRefs.Public) + tfa.knownSafe += inc.sym - case None => - warnNoInline("bytecode was not available") - debuglog("could not find icode\n\treceiver: " + receiver + "\n\tmethod: " + concreteMethod) + true + } + isSafe && { + retry = true + if (isCountable) count += 1 + pair.doInline(bb, i) + if (!pair.isInlineForced || inc.isMonadic) caller.inlinedCalls += 1 + inlinedMethodCount(inc.sym) += 1 + + // Remove the caller from the cache (this inlining might have changed its calls-private relation). + usesNonPublics -= m + recentTFAs -= m.symbol + true + } } - } else { - warnNoInline(if(!isAvailable) "bytecode was not available" else "it can be overridden") } - - inlined } /* Pre-inlining consists in invoking the usual inlining subroutine with (receiver class, concrete method) pairs as input @@ -485,7 +487,7 @@ abstract class Inliners extends SubComponent { do { retry = false - log("Analyzing " + m + " count " + count + " with " + caller.length + " blocks") + debuglog(analyzeMessage) /* it's important not to inline in unreachable basic blocks. linearizedBlocks() returns only reachable ones. */ tfa.callerLin = caller.m.linearizedBlocks() @@ -567,9 +569,16 @@ abstract class Inliners extends SubComponent { m.normalize if (sizeBeforeInlining > 0) { val instrAfterInlining = m.code.instructionCount - val prefix = if ((instrAfterInlining > 2 * instrBeforeInlining) && (instrAfterInlining > 200)) " !! " else "" - log(prefix + " %s blocks before inlining: %d (%d) after: %d (%d)".format( - m.symbol.fullName, sizeBeforeInlining, instrBeforeInlining, m.code.blockCount, instrAfterInlining)) + val prefix = if ((instrAfterInlining > 2 * instrBeforeInlining) && (instrAfterInlining > 200)) "!!" else "" + val inlinings = caller.inlinedCalls + if (inlinings > 0) { + val s1 = s"instructions $instrBeforeInlining -> $instrAfterInlining" + val s2 = if (sizeBeforeInlining == m.code.blockCount) "" else s", blocks $sizeBeforeInlining -> ${m.code.blockCount}" + val callees = inlinedMethodCount.toList map { case (k, v) => k.fullNameString + ( if (v == 1) "" else "/" + v ) } + + inlineLog("inlined", m.symbol.fullName, callees.sorted.mkString(inlinings + " inlined: ", ", ", "")) + inlineLog("<>", m.symbol.fullName, s"${m.symbol.nameString}: $s1$s2") + } } } @@ -589,6 +598,8 @@ abstract class Inliners extends SubComponent { } class IMethodInfo(val m: IMethod) { + override def toString = m.toString + val sym = m.symbol val name = sym.name def owner = sym.owner @@ -688,7 +699,7 @@ abstract class Inliners extends SubComponent { val i = iter.next() getAccess(i) match { case Private => - log("instruction " + i + " requires private access.") + inlineLog("access", s"instruction $i requires private access", "pos=" + i.pos) toBecomePublic = Nil seen = Private case Protected => seen = Protected @@ -765,11 +776,10 @@ abstract class Inliners extends SubComponent { tfa.warnIfInlineFails.remove(instr) val targetPos = instr.pos - log("Inlining " + inc.m + " in " + caller.m + " at pos: " + posToStr(targetPos)) def blockEmit(i: Instruction) = block.emit(i, targetPos) def newLocal(baseName: String, kind: TypeKind) = - new Local(caller.sym.newVariable(freshName(baseName), targetPos), kind, false) + new Local(caller.sym.newVariable(freshName(baseName), targetPos) setInfo kind.toType, kind, false) val (hasRETURN, a) = getRecentTFA(inc.m, isInlineForced) @@ -956,6 +966,7 @@ abstract class Inliners extends SubComponent { if(reasonWhyNever != null) { tfa.knownNever += inc.sym + inlineLog("never", inc.sym, reasonWhyNever) // next time around NeverSafeToInline is returned, thus skipping (duplicate) msg, this is intended. return DontInlineHere(inc.m + " " + reasonWhyNever) } @@ -978,10 +989,15 @@ abstract class Inliners extends SubComponent { * As a result of (b), some synthetic private members can be chosen to become public. */ - if(!isInlineForced && !isScoreOK) { + val score = inlinerScore + val scoreStr = if (score > 0) "+" + score else "" + score + val what = if (score > 0) "ok to" else "don't" + inlineLog(scoreStr, inc.m.symbol, s"$what inline into ${ownedName(caller.m.symbol)}") + + if (!isInlineForced && score <= 0) { // During inlining retry, a previous caller-callee pair that scored low may pass. // Thus, adding the callee to tfa.knownUnsafe isn't warranted. - return DontInlineHere("too low score (heuristics)") + return DontInlineHere(s"inliner heuristic") } if(inc.hasHandlers && (stackLength > inc.minimumStack)) { @@ -1000,7 +1016,9 @@ abstract class Inliners extends SubComponent { val accReq = inc.accessRequirements if(!canAccess(accReq.accessNeeded)) { tfa.knownUnsafe += inc.sym - return DontInlineHere("access level required by callee not matched by caller") + val msg = "access level required by callee not matched by caller" + inlineLog("fail", inc.sym, msg) + return DontInlineHere(msg) } FeasibleInline(accReq.accessNeeded, accReq.toBecomePublic) @@ -1022,9 +1040,7 @@ abstract class Inliners extends SubComponent { * - it's good to inline closures functions. * - it's bad (useless) to inline inside bridge methods */ - def isScoreOK: Boolean = { - debuglog(s"shouldInline: ${caller.m} , callee: ${inc.m}") - + def inlinerScore: Int = { var score = 0 // better not inline inside closures, but hope that the closure itself is repeatedly inlined @@ -1036,18 +1052,15 @@ abstract class Inliners extends SubComponent { if (inc.isLarge) score -= 1; if (caller.isSmall && isLargeSum) { score -= 1 - debuglog(s"shouldInline: score decreased to $score because small $caller would become large") + debuglog(s"inliner score decreased to $score because small caller $caller would become large") } if (inc.isMonadic) score += 3 else if (inc.isHigherOrder) score += 1 - if (inc.isInClosure) score += 2; - if (inlinedMethodCount(inc.sym) > 2) score -= 2; - - log(s"shouldInline(${inc.m}) score: $score") - - score > 0 + if (inc.isInClosure) score += 2 + if (inlinedMethodCount(inc.sym) > 2) score -= 2 + score } } diff --git a/src/compiler/scala/tools/nsc/interpreter/IMain.scala b/src/compiler/scala/tools/nsc/interpreter/IMain.scala index 96d7dadbd7..a2df1494ef 100644 --- a/src/compiler/scala/tools/nsc/interpreter/IMain.scala +++ b/src/compiler/scala/tools/nsc/interpreter/IMain.scala @@ -387,8 +387,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends newSym <- req.definedSymbols get name oldSym <- oldReq.definedSymbols get name.companionName } { - replwarn("warning: previously defined %s is not a companion to %s.".format( - stripString("" + oldSym), stripString("" + newSym))) + afterTyper(replwarn(s"warning: previously defined $oldSym is not a companion to $newSym.")) replwarn("Companions must be defined together; you may wish to use :paste mode for this.") } diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala index 437a5e1434..175c322786 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala @@ -37,7 +37,7 @@ abstract class ICodeReader extends ClassfileParser { cls.info // ensure accurate type information isScalaModule = cls.isModule && !cls.isJavaDefined - log("Reading class: " + cls + " isScalaModule?: " + isScalaModule) + log("ICodeReader reading " + cls) val name = cls.javaClassName classPath.findSourceFile(name) match { @@ -99,11 +99,9 @@ abstract class ICodeReader extends ClassfileParser { if (sym == NoSymbol) sym = owner.info.findMember(newTermName(name + nme.LOCAL_SUFFIX_STRING), 0, 0, false).suchThat(_.tpe =:= tpe) if (sym == NoSymbol) { - log("Could not find symbol for " + name + ": " + tpe) - log(owner.info.member(name).tpe + " : " + tpe) sym = if (field) owner.newValue(name, owner.pos, toScalaFieldFlags(jflags)) else dummySym sym setInfoAndEnter tpe - log("added " + sym + ": " + sym.tpe) + log(s"ICodeReader could not locate ${name.decode} in $owner. Created ${sym.defString}.") } (jflags, sym) } @@ -172,10 +170,7 @@ abstract class ICodeReader extends ClassfileParser { } else if (nme.isModuleName(name)) { val strippedName = nme.stripModuleSuffix(name) - val sym = forceMangledName(newTermName(strippedName.decode), true) - - if (sym == NoSymbol) rootMirror.getModule(strippedName) - else sym + forceMangledName(newTermName(strippedName.decode), true) orElse rootMirror.getModule(strippedName) } else { forceMangledName(name, false) @@ -956,7 +951,7 @@ abstract class ICodeReader extends ClassfileParser { case None => checkValidIndex val l = freshLocal(idx, kind, false) - log("Added new local for idx " + idx + ": " + kind) + debuglog("Added new local for idx " + idx + ": " + kind) locals += (idx -> List((l, kind))) l } diff --git a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala index a8cdee7154..4a668d4c61 100644 --- a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala +++ b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala @@ -79,12 +79,11 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure => // -optimise and not otherwise, but the classpath can use arbitrary // logic so the classpath must be queried. if (classPath.context.isValidName(implName + ".class")) { - log("unlinking impl class " + implSym) iface.owner.info.decls unlink implSym NoSymbol } else { - log("not unlinking existing " + implSym + " as the impl class is not visible on the classpath.") + log(s"not unlinking $iface's existing implClass ${implSym.name} because it is not on the classpath.") implSym } } @@ -113,9 +112,10 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure => iface.info implClassMap.getOrElse(iface, atPhase(implClassPhase) { - log("Creating implClass for " + iface) - if (iface.implClass ne NoSymbol) - log("%s.implClass already exists: %s".format(iface, iface.implClass)) + if (iface.implClass eq NoSymbol) + debuglog(s"${iface.fullLocationString} has no implClass yet, creating it now.") + else + log(s"${iface.fullLocationString} impl class is ${iface.implClass.nameString}") newImplClass(iface) }) @@ -137,7 +137,7 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure => * given the decls ifaceDecls of its interface. */ private def implDecls(implClass: Symbol, ifaceDecls: Scope): Scope = { - log("LazyImplClassType calculating decls for " + implClass) + debuglog("LazyImplClassType calculating decls for " + implClass) val decls = newScope if ((ifaceDecls lookup nme.MIXIN_CONSTRUCTOR) == NoSymbol) { @@ -152,16 +152,16 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure => for (sym <- ifaceDecls) { if (isInterfaceMember(sym)) { if (needsImplMethod(sym)) { - log("Cloning " + sym + " for implementation method in " + implClass) val clone = sym.cloneSymbol(implClass).resetFlag(lateDEFERRED) if (currentRun.compiles(implClass)) implMethodMap(sym) = clone decls enter clone sym setFlag lateDEFERRED + if (!sym.isSpecialized) + log(s"Cloned ${sym.name} from ${sym.owner} into implClass ${implClass.fullName}") } - else log(sym + " needs no implementation method in " + implClass) } else { - log("Destructively modifying owner of %s from %s to %s".format(sym, sym.owner, implClass)) + log(s"Destructively modifying owner of $sym from ${sym.owner} to $implClass") sym.owner = implClass // note: OK to destructively modify the owner here, // because symbol will not be accessible from outside the sourcefile. @@ -174,7 +174,7 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure => } override def complete(implSym: Symbol) { - log("LazyImplClassType completing " + implSym) + debuglog("LazyImplClassType completing " + implSym) /** If `tp` refers to a non-interface trait, return a * reference to its implementation class. Otherwise return `tp`. diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index d97fbf5daa..8af9fd6eb8 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -490,7 +490,7 @@ abstract class Erasure extends AddInterfaces @inline private def box(tree: Tree, target: => String): Tree = { val result = box1(tree) - log("boxing "+tree+":"+tree.tpe+" to "+target+" = "+result+":"+result.tpe) + log(s"boxing ${tree.summaryString}: ${tree.tpe} into $target: ${result.tpe}") result } @@ -525,7 +525,7 @@ abstract class Erasure extends AddInterfaces * fields (see TupleX). (ID) */ case Apply(boxFun, List(arg)) if isUnbox(tree.symbol) && safeToRemoveUnbox(arg.tpe.typeSymbol) => - log("boxing an unbox: " + tree + "/" + tree.symbol + " and replying with " + arg + " of type " + arg.tpe) + log(s"boxing an unbox: ${tree.symbol} -> ${arg.tpe}") arg case _ => (REF(boxMethod(x)) APPLY tree) setPos (tree.pos) setType ObjectClass.tpe @@ -537,7 +537,7 @@ abstract class Erasure extends AddInterfaces private def unbox(tree: Tree, pt: Type): Tree = { val result = unbox1(tree, pt) - log("unboxing "+tree+":"+tree.tpe+" to "+pt+" = "+result+":"+result.tpe) + log(s"unboxing ${tree.summaryString}: ${tree.tpe} with pt=$pt as type ${result.tpe}") result } @@ -614,7 +614,7 @@ abstract class Erasure extends AddInterfaces * @return the adapted tree */ private def adaptToType(tree: Tree, pt: Type): Tree = { - //if (settings.debug.value && pt != WildcardType) + if (settings.debug.value && pt != WildcardType) log("adapting " + tree + ":" + tree.tpe + " : " + tree.tpe.parents + " to " + pt)//debug if (tree.tpe <:< pt) tree diff --git a/src/compiler/scala/tools/nsc/transform/Flatten.scala b/src/compiler/scala/tools/nsc/transform/Flatten.scala index 94eaba67d7..3bbf429fc2 100644 --- a/src/compiler/scala/tools/nsc/transform/Flatten.scala +++ b/src/compiler/scala/tools/nsc/transform/Flatten.scala @@ -22,12 +22,14 @@ abstract class Flatten extends InfoTransform { */ private def replaceSymbolInCurrentScope(sym: Symbol): Symbol = afterFlatten { val scope = sym.owner.info.decls - val old = scope lookup sym.name - if (old ne NoSymbol) - scope unlink old - + val old = scope lookup sym.name andAlso scope.unlink scope enter sym - log("lifted " + sym.fullLocationString) + + if (old eq NoSymbol) + log(s"lifted ${sym.fullLocationString}") + else + log(s"lifted ${sym.fullLocationString} after unlinking existing $old from scope.") + old } @@ -35,9 +37,7 @@ abstract class Flatten extends InfoTransform { if (!sym.isLifted) { sym setFlag LIFTED debuglog("re-enter " + sym.fullLocationString) - val old = replaceSymbolInCurrentScope(sym) - if (old ne NoSymbol) - log("unlinked " + old.fullLocationString + " after lifting " + sym) + replaceSymbolInCurrentScope(sym) } } private def liftSymbol(sym: Symbol) { diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala index 181463657b..5bff653499 100644 --- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala +++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala @@ -484,11 +484,7 @@ abstract class UnCurry extends InfoTransform arg setType functionType(Nil, arg.tpe) } else { - log("byname | %s | %s | %s".format( - arg.pos.source.path + ":" + arg.pos.line, fun.fullName, - if (fun.isPrivate) "private" else "") - ) - + log(s"Argument '$arg' at line ${arg.pos.safeLine} is $formal from ${fun.fullName}") arg match { // don't add a thunk for by-name argument if argument already is an application of // a Function0. We can then remove the application and use the existing Function0. diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 4eea8461d3..a9c31cfe1f 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1870,7 +1870,7 @@ trait Typers extends Modes with Adaptations with Tags { * @param rhs ... */ def computeParamAliases(clazz: Symbol, vparamss: List[List[ValDef]], rhs: Tree) { - log("computing param aliases for "+clazz+":"+clazz.primaryConstructor.tpe+":"+rhs)//debug + debuglog(s"computing param aliases for $clazz:${clazz.primaryConstructor.tpe}:$rhs") def decompose(call: Tree): (Tree, List[Tree]) = call match { case Apply(fn, args) => val (superConstr, args1) = decompose(fn) diff --git a/src/reflect/scala/reflect/internal/SymbolTable.scala b/src/reflect/scala/reflect/internal/SymbolTable.scala index 4100e97cdd..2424e75949 100644 --- a/src/reflect/scala/reflect/internal/SymbolTable.scala +++ b/src/reflect/scala/reflect/internal/SymbolTable.scala @@ -47,6 +47,8 @@ abstract class SymbolTable extends macros.Universe def globalError(msg: String): Unit = abort(msg) def abort(msg: String): Nothing = throw new FatalError(supplementErrorMessage(msg)) + def shouldLogAtThisPhase = false + @deprecated("Give us a reason", "2.10.0") def abort(): Nothing = abort("unknown error") diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index aab41a0b29..c0e6a66767 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -943,7 +943,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => /** If this symbol has an expanded name, its original name, otherwise its name itself. * @see expandName */ - def originalName: Name = nme.originalName(name) + def originalName: Name = nme.originalName(nme.dropLocalSuffix(name)) /** The name of the symbol before decoding, e.g. `\$eq\$eq` instead of `==`. */ diff --git a/test/files/run/compiler-asSeenFrom.check b/test/files/run/compiler-asSeenFrom.check index 96e257d303..47d40b0331 100644 --- a/test/files/run/compiler-asSeenFrom.check +++ b/test/files/run/compiler-asSeenFrom.check @@ -269,8 +269,8 @@ value jZ { // after parser value jZ { // after explicitouter protected val $outer: D.this.type - val ll$D$J$$$outer(): D.this.type - val ll$C$I$$$outer(): C.this.type + val $outer(): D.this.type + val $outer(): C.this.type def thisI(): I.this.type def thisC(): C.this.type def t2(): T2 @@ -279,9 +279,9 @@ value jZ { // after explicitouter value jZ { // after erasure protected val $outer: ll.D - val ll$D$J$$$outer(): ll.D + val $outer(): ll.D protected val $outer: ll.C - val ll$C$I$$$outer(): ll.C + val $outer(): ll.C def thisI(): ll.C#I def thisC(): ll.C def t2(): Object @@ -290,9 +290,9 @@ value jZ { // after erasure value jZ { // after flatten protected val $outer: ll.D - val ll$D$J$$$outer(): ll.D + val $outer(): ll.D protected val $outer: ll.C - val ll$C$I$$$outer(): ll.C + val $outer(): ll.C def thisI(): ll.C#C$I def thisC(): ll.C def t2(): Object -- cgit v1.2.3