From 554fb11b0cd2f76d7990a0de935c8deef30f95dc Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Tue, 9 Aug 2011 14:50:21 +0000 Subject: Big cleanups in the tracing utility and its usa... Big cleanups in the tracing utility and its usage for signature tracing. To assist in my current java signature thrill-o-rama. No review. --- .../scala/tools/nsc/backend/jvm/GenJVM.scala | 5 +- .../scala/tools/nsc/transform/Erasure.scala | 46 +++++++++--------- src/compiler/scala/tools/nsc/util/Tracer.scala | 56 ++++++++++++---------- 3 files changed, 57 insertions(+), 50 deletions(-) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala index baee596f5f..be98b314a4 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala @@ -661,9 +661,10 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with } } val index = jmember.getConstantPool.addUtf8(sig).toShort - if (opt.verboseDebug) + if (opt.verboseDebug || erasure.traceSignatures) atPhase(currentRun.erasurePhase) { - println("add generic sig "+sym+":"+sym.info+" ==> "+sig+" @ "+index) + log("new signature for " + sym+":"+sym.info) + log(" " + sig) } val buf = ByteBuffer.allocate(2) buf putShort index diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index b53baf45eb..fc3aae9046 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -72,7 +72,6 @@ abstract class Erasure extends AddInterfaces atPos(tree.pos)(Apply(Select(tree, conversion), Nil)) } - private object NeedsSigCollector extends TypeCollector(false) { def traverse(tp: Type) { if (!result) { @@ -99,6 +98,10 @@ abstract class Erasure extends AddInterfaces } } + // for debugging signatures: traces logic given system property + // performance: get the value here + val traceSignatures = (sys.BooleanProp keyExists "scalac.sigs.trace").value + override protected def verifyJavaErasure = settings.Xverify.value || settings.debug.value private def needsJavaSig(tp: Type) = !settings.Ynogenericsig.value && NeedsSigCollector.collect(tp) @@ -110,9 +113,7 @@ abstract class Erasure extends AddInterfaces !sym.isHigherOrderTypeParameter && sym.isTypeParameterOrSkolem && ( (initialSymbol.enclClassChain.exists(sym isNestedIn _)) || - traceSig("isMethod", (initialSymbol, initialSymbol.typeParams)) { - (initialSymbol.isMethod && initialSymbol.typeParams.contains(sym)) - } + (initialSymbol.isMethod && initialSymbol.typeParams.contains(sym)) ) ) @@ -129,9 +130,7 @@ abstract class Erasure extends AddInterfaces case ch => last = ch ; ch } } - // for debugging signatures: traces logic given system property - private val traceProp = (sys.BooleanProp keyExists "scalac.sigs.trace").value // performance: get the value here - private val traceSig = util.Tracer(traceProp) + private val traceSig = util.Tracer(traceSignatures) /** This object is only used for sanity testing when -check:genjvm is set. * In that case we make sure that the erasure of the `normalized` type @@ -234,7 +233,7 @@ abstract class Erasure extends AddInterfaces boxedSig(tp) } - // If args isEmpty, Array is being used as a higher-kinded type + // If args isEmpty, Array is being used as a type constructor if (sym == ArrayClass && args.nonEmpty) { if (unboundedGenericArrayLevel(tp) == 1) jsig(ObjectClass.tpe) else ARRAY_TAG.toString+(args map (jsig(_))).mkString @@ -258,23 +257,21 @@ abstract class Erasure extends AddInterfaces } else if (sym.isClass) { val preRebound = pre.baseType(sym.owner) // #2585 - traceSig("sym.isClass", (sym.ownerChain, preRebound, sym0.enclClassChain)) { - dotCleanup( - ( - if (needsJavaSig(preRebound)) { - val s = jsig(preRebound, existentiallyBound) - if (s.charAt(0) == 'L') s.substring(0, s.length - 1) + "." + sym.javaSimpleName - else fullNameInSig(sym) - } + dotCleanup( + ( + if (needsJavaSig(preRebound)) { + val s = jsig(preRebound, existentiallyBound) + if (s.charAt(0) == 'L') s.substring(0, s.length - 1) + "." + sym.javaSimpleName else fullNameInSig(sym) - ) + ( - if (args.isEmpty) "" else - "<"+(args map argSig).mkString+">" - ) + ( - ";" - ) + } + else fullNameInSig(sym) + ) + ( + if (args.isEmpty) "" else + "<"+(args map argSig).mkString+">" + ) + ( + ";" ) - } + ) } else jsig(erasure(sym0, tp), existentiallyBound, toplevel, primitiveOK) case PolyType(tparams, restpe) => @@ -291,10 +288,11 @@ abstract class Erasure extends AddInterfaces def paramSig(tsym: Symbol) = tsym.name + boundSig(hiBounds(tsym.info.bounds)) val paramString = if (toplevel) tparams map paramSig mkString ("<", "", ">") else "" - traceSig("PolyType", (tparams, restpe))(paramString + jsig(restpe)) + paramString + jsig(restpe) case MethodType(params, restpe) => "("+(params map (_.tpe) map (jsig(_))).mkString+")"+ (if (restpe.typeSymbol == UnitClass || sym0.isConstructor) VOID_TAG.toString else jsig(restpe)) + case RefinedType(parent :: _, decls) => boxedSig(parent) case ClassInfoType(parents, _, _) => diff --git a/src/compiler/scala/tools/nsc/util/Tracer.scala b/src/compiler/scala/tools/nsc/util/Tracer.scala index 1dd21b26c2..ec1eaa13ea 100644 --- a/src/compiler/scala/tools/nsc/util/Tracer.scala +++ b/src/compiler/scala/tools/nsc/util/Tracer.scala @@ -7,21 +7,36 @@ package scala.tools.nsc package util import java.io.PrintStream +import scala.runtime.ScalaRunTime class Tracer(enabled: () => Boolean) { def out: PrintStream = System.out def intoString(x: Any): String = "" + x - def stringify(x: Any): String = x match { - case null => "null" - case x: TraversableOnce[_] => x map stringify mkString ", " - case x: Product => stringify(x.productIterator) - case x: AnyRef => intoString(x) + + def stringify(x: Any) = ScalaRunTime stringOf x + + // So can pass tuples, lists, whatever as arguments and don't + // get a lot of extra parens or noisy prefixes. + def stringifyArgs(x: Any) = { + x match { + case x: TraversableOnce[_] => x map stringify mkString ", " + case x: Product => x.productIterator map stringify mkString ", " + case _ => stringify(x) + } } private val LBRACE = "{" private val RBRACE = "}" private var indentLevel = 0 - private def ind(s: String) = (" " * (indentLevel * 2)) + s + private def spaces = " " * (indentLevel * 2) + private def pblock(result: Any) = { + p(LBRACE + "\n") + indented(p(spaces + stringify(result) + "\n")) + p(spaces + RBRACE + "\n") + } + private def passign(name: String, args: String) = + p(spaces + name + "(" + args + ") = ") + private def indented[T](body: => T): T = { indentLevel += 1 try body @@ -31,30 +46,23 @@ class Tracer(enabled: () => Boolean) { out.print(s) out.flush() } - private def pin[T](x: T): T = { - p(ind("" + x)) - x - } + def apply[T](name: String, args: => Any)(body: => T): T = { val result = body + if (enabled()) { + passign(name, stringifyArgs(args)) // concise output optimization - val boolResult = result match { - case x: Boolean => Some(x) - case _ => None + val isOneliner = result match { + case _: Boolean | _: None.type => true + case s: String => s.length < 40 + case _ => false } - p(ind("%s(%s) = %s\n".format( - name, - stringify(args), - boolResult getOrElse LBRACE)) - ) - if (boolResult.isEmpty) { - indented(pin(result)) - p("\n" + ind(RBRACE)) - } - result + if (isOneliner) p(stringify(result) + "\n") + else pblock(result) } - else result + + result } } -- cgit v1.2.3