diff options
Diffstat (limited to 'src/compiler')
-rw-r--r-- | src/compiler/scala/reflect/internal/Definitions.scala | 7 | ||||
-rw-r--r-- | src/compiler/scala/reflect/internal/StdNames.scala | 18 | ||||
-rw-r--r-- | src/compiler/scala/reflect/internal/Trees.scala | 11 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/CleanUp.scala | 147 |
4 files changed, 100 insertions, 83 deletions
diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala index aee3938715..d3af8e2623 100644 --- a/src/compiler/scala/reflect/internal/Definitions.scala +++ b/src/compiler/scala/reflect/internal/Definitions.scala @@ -267,10 +267,11 @@ trait Definitions extends reflect.api.StandardDefinitions { (sym.name == name) && (sym.owner == PredefModule.moduleClass) ) - lazy val ConsoleModule: Symbol = getRequiredModule("scala.Console") + lazy val ConsoleModule: Symbol = getRequiredModule("scala.Console") lazy val ScalaRunTimeModule: Symbol = getRequiredModule("scala.runtime.ScalaRunTime") - lazy val SymbolModule: Symbol = getRequiredModule("scala.Symbol") - lazy val Symbol_apply = getMember(SymbolModule, nme.apply) + lazy val SymbolModule: Symbol = getRequiredModule("scala.Symbol") + lazy val Symbol_apply = SymbolModule.info decl nme.apply + def SeqFactory = getMember(ScalaRunTimeModule, nme.Seq) def arrayApplyMethod = getMember(ScalaRunTimeModule, nme.array_apply) def arrayUpdateMethod = getMember(ScalaRunTimeModule, nme.array_update) diff --git a/src/compiler/scala/reflect/internal/StdNames.scala b/src/compiler/scala/reflect/internal/StdNames.scala index db1cf7f257..ea5565c581 100644 --- a/src/compiler/scala/reflect/internal/StdNames.scala +++ b/src/compiler/scala/reflect/internal/StdNames.scala @@ -578,6 +578,9 @@ trait StdNames extends NameManglers { self: SymbolTable => val testLessOrEqualThan: NameType = "testLessOrEqualThan" val testLessThan: NameType = "testLessThan" val testNotEqual: NameType = "testNotEqual" + + val isBoxedNumberOrBoolean: NameType = "isBoxedNumberOrBoolean" + val isBoxedNumber: NameType = "isBoxedNumber" def toUnaryName(name: TermName): TermName = name match { case raw.MINUS => UNARY_- @@ -628,6 +631,21 @@ trait StdNames extends NameManglers { self: SymbolTable => case _ => NO_NAME } + val reflPolyCacheName: NameType = "reflPoly$Cache" + val reflClassCacheName: NameType = "reflClass$Cache" + val reflParamsCacheName: NameType = "reflParams$Cache" + val reflMethodCacheName: NameType = "reflMethod$Cache" + val reflMethodName: NameType = "reflMethod$Method" + + private val reflectionCacheNames = Set[NameType]( + reflPolyCacheName, + reflClassCacheName, + reflParamsCacheName, + reflMethodCacheName, + reflMethodName + ) + def isReflectionCacheName(name: Name) = reflectionCacheNames exists (name startsWith _) + @switch def productAccessorName(j: Int): TermName = j match { case 1 => nme._1 case 2 => nme._2 diff --git a/src/compiler/scala/reflect/internal/Trees.scala b/src/compiler/scala/reflect/internal/Trees.scala index 4ca55f53ea..96f2c5cc45 100644 --- a/src/compiler/scala/reflect/internal/Trees.scala +++ b/src/compiler/scala/reflect/internal/Trees.scala @@ -248,10 +248,13 @@ trait Trees extends api.Trees { self: SymbolTable => /** Block factory that flattens directly nested blocks. */ - def Block(stats: Tree*): Block = stats match { - case Seq(b @ Block(_, _)) => b - case Seq(stat) => Block(stats.toList, Literal(Constant(()))) - case Seq(_, rest @ _*) => Block(stats.init.toList, stats.last) + def Block(stats: Tree*): Block = { + if (stats.isEmpty) Block(Nil, Literal(Constant(()))) + else stats match { + case Seq(b @ Block(_, _)) => b + case Seq(stat) => Block(stats.toList, Literal(Constant(()))) + case Seq(_, rest @ _*) => Block(stats.init.toList, stats.last) + } } // --- specific traversers and transformers diff --git a/src/compiler/scala/tools/nsc/transform/CleanUp.scala b/src/compiler/scala/tools/nsc/transform/CleanUp.scala index 575e3a9141..034628e95f 100644 --- a/src/compiler/scala/tools/nsc/transform/CleanUp.scala +++ b/src/compiler/scala/tools/nsc/transform/CleanUp.scala @@ -22,9 +22,35 @@ abstract class CleanUp extends Transform with ast.TreeDSL { new CleanUpTransformer(unit) class CleanUpTransformer(unit: CompilationUnit) extends Transformer { - private val newStaticMembers = mutable.Buffer.empty[Tree] - private val newStaticInits = mutable.Buffer.empty[Tree] + private val newStaticMembers = mutable.Buffer.empty[Tree] + private val newStaticInits = mutable.Buffer.empty[Tree] private val symbolsStoredAsStatic = mutable.Map.empty[String, Symbol] + private def clearStatics() { + newStaticMembers.clear() + newStaticInits.clear() + symbolsStoredAsStatic.clear() + } + private def savingStatics[T](body: => T): T = { + val savedNewStaticMembers : mutable.Buffer[Tree] = newStaticMembers.clone() + val savedNewStaticInits : mutable.Buffer[Tree] = newStaticInits.clone() + val savedSymbolsStoredAsStatic : mutable.Map[String, Symbol] = symbolsStoredAsStatic.clone() + val result = body + + clearStatics() + newStaticMembers ++= savedNewStaticMembers + newStaticInits ++= savedNewStaticInits + symbolsStoredAsStatic ++= savedSymbolsStoredAsStatic + + result + } + private def transformTemplate(tree: Tree) = { + val Template(parents, self, body) = tree + clearStatics() + val newBody = transformTrees(body) + val templ = treeCopy.Template(tree, parents, self, transformTrees(newStaticMembers.toList) ::: newBody) + try addStaticInits(templ) // postprocess to include static ctors + finally clearStatics() + } private def mkTerm(prefix: String): TermName = unit.freshTermName(prefix) /** Kludge to provide a safe fix for #4560: @@ -60,7 +86,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { } private def typedWithPos(pos: Position)(tree: Tree) = - localTyper typed { atPos(pos)(tree) } + localTyper.typedPos(pos)(tree) /** A value class is defined to be only Java-compatible values: unit is * not part of it, as opposed to isValueClass in definitions. scala.Int is @@ -71,7 +97,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { /** The boxed type if it's a primitive; identity otherwise. */ def toBoxedType(tp: Type) = if (isJavaValueType(tp)) boxedClass(tp.typeSymbol).tpe else tp - + override def transform(tree: Tree): Tree = tree match { /* Transforms dynamic calls (i.e. calls to methods that are undefined @@ -116,11 +142,11 @@ abstract class CleanUp extends Transform with ast.TreeDSL { /* ### CREATING THE METHOD CACHE ### */ - def addStaticVariableToClass(forName: String, forType: Type, forInit: Tree, isFinal: Boolean): Symbol = { + def addStaticVariableToClass(forName: TermName, forType: Type, forInit: Tree, isFinal: Boolean): Symbol = { val varSym = ( - currentClass.newVariable(ad.pos, mkTerm(forName)) - setFlag (PRIVATE | STATIC | SYNTHETIC) - setInfo (forType) + currentClass.newVariable(ad.pos, mkTerm("" + forName)) + setFlag PRIVATE | STATIC | SYNTHETIC + setInfo forType ) if (isFinal) varSym setFlag FINAL else varSym.addAnnotation(VolatileAttr) @@ -168,9 +194,9 @@ abstract class CleanUp extends Transform with ast.TreeDSL { */ val reflParamsCacheSym: Symbol = - addStaticVariableToClass("reflParams$Cache", theTypeClassArray, fromTypesToClassArrayLiteral(paramTypes), true) + addStaticVariableToClass(nme.reflParamsCacheName, theTypeClassArray, fromTypesToClassArrayLiteral(paramTypes), true) - addStaticMethodToClass("reflMethod$Method", List(ClassClass.tpe), MethodClass.tpe) { + addStaticMethodToClass(nme.reflMethodName, List(ClassClass.tpe), MethodClass.tpe) { case Pair(reflMethodSym, List(forReceiverSym)) => (REF(forReceiverSym) DOT Class_getMethod)(LIT(method), safeREF(reflParamsCacheSym)) } @@ -197,18 +223,18 @@ abstract class CleanUp extends Transform with ast.TreeDSL { */ val reflParamsCacheSym: Symbol = - addStaticVariableToClass("reflParams$Cache", theTypeClassArray, fromTypesToClassArrayLiteral(paramTypes), true) + addStaticVariableToClass(nme.reflParamsCacheName, theTypeClassArray, fromTypesToClassArrayLiteral(paramTypes), true) val reflMethodCacheSym: Symbol = - addStaticVariableToClass("reflMethod$Cache", MethodClass.tpe, NULL, false) + addStaticVariableToClass(nme.reflMethodCacheName, MethodClass.tpe, NULL, false) val reflClassCacheSym: Symbol = - addStaticVariableToClass("reflClass$Cache", SoftReferenceClass.tpe, NULL, false) + addStaticVariableToClass(nme.reflClassCacheName, SoftReferenceClass.tpe, NULL, false) def isCacheEmpty(receiver: Symbol): Tree = reflClassCacheSym.IS_NULL() OR (reflClassCacheSym.GET() OBJ_NE REF(receiver)) - addStaticMethodToClass("reflMethod$Method", List(ClassClass.tpe), MethodClass.tpe) { + addStaticMethodToClass(nme.reflMethodName, List(ClassClass.tpe), MethodClass.tpe) { case Pair(reflMethodSym, List(forReceiverSym)) => BLOCK( IF (isCacheEmpty(forReceiverSym)) THEN BLOCK( @@ -244,13 +270,15 @@ abstract class CleanUp extends Transform with ast.TreeDSL { */ val reflParamsCacheSym: Symbol = - addStaticVariableToClass("reflParams$Cache", theTypeClassArray, fromTypesToClassArrayLiteral(paramTypes), true) + addStaticVariableToClass(nme.reflParamsCacheName, theTypeClassArray, fromTypesToClassArrayLiteral(paramTypes), true) def mkNewPolyCache = gen.mkSoftRef(NEW(TypeTree(EmptyMethodCacheClass.tpe))) - val reflPolyCacheSym: Symbol = addStaticVariableToClass("reflPoly$Cache", SoftReferenceClass.tpe, mkNewPolyCache, false) + val reflPolyCacheSym: Symbol = ( + addStaticVariableToClass(nme.reflPolyCacheName, SoftReferenceClass.tpe, mkNewPolyCache, false) + ) def getPolyCache = gen.mkCast(fn(safeREF(reflPolyCacheSym), nme.get), MethodCacheClass.tpe) - addStaticMethodToClass("reflMethod$Method", List(ClassClass.tpe), MethodClass.tpe) + addStaticMethodToClass(nme.reflMethodName, List(ClassClass.tpe), MethodClass.tpe) { case Pair(reflMethodSym, List(forReceiverSym)) => val methodSym = reflMethodSym.newVariable(ad.pos, mkTerm("method")) setInfo MethodClass.tpe @@ -274,24 +302,13 @@ abstract class CleanUp extends Transform with ast.TreeDSL { /* ### HANDLING METHODS NORMALLY COMPILED TO OPERATORS ### */ - // Can't shortcut on BoxedNumber because BoxesRunTime - // is unforgiving of other Numbers showing up. - def testForNumber(qual1: Tree): Tree = ( - (qual1 IS_OBJ BoxedIntClass.tpe) - OR (qual1 IS_OBJ BoxedLongClass.tpe) - OR (qual1 IS_OBJ BoxedDoubleClass.tpe) - OR (qual1 IS_OBJ BoxedFloatClass.tpe) - OR (qual1 IS_OBJ BoxedByteClass.tpe) - OR (qual1 IS_OBJ BoxedShortClass.tpe) - OR (qual1 IS_OBJ BoxedCharacterClass.tpe) - ) - def testForBoolean(qual1: Tree): Tree = ( - (qual1 IS_OBJ BoxedBooleanClass.tpe) - ) - def testForName(name: Name): Tree => Tree = ( - if (nme.CommonOpNames(name)) t => testForNumber(t) OR testForBoolean(t) - else if (nme.BooleanOpNames(name)) testForBoolean - else testForNumber + def testForName(name: Name): Tree => Tree = t => ( + if (nme.CommonOpNames(name)) + gen.mkMethodCall(getMember(BoxesRunTimeClass, nme.isBoxedNumberOrBoolean), t :: Nil) + else if (nme.BooleanOpNames(name)) + t IS_OBJ BoxedBooleanClass.tpe + else + gen.mkMethodCall(getMember(BoxesRunTimeClass, nme.isBoxedNumber), t :: Nil) ) /** The Tree => Tree function in the return is necessary to prevent the original qual @@ -525,31 +542,8 @@ abstract class CleanUp extends Transform with ast.TreeDSL { * constructor. */ case Template(parents, self, body) => localTyper = typer.atOwner(tree, currentClass) - var savedNewStaticMembers : mutable.Buffer[Tree] = null - var savedNewStaticInits : mutable.Buffer[Tree] = null - var savedSymbolsStoredAsStatic : mutable.Map[String, Symbol] = null - if(forMSIL) { - savedNewStaticMembers = newStaticMembers.clone - savedNewStaticInits = newStaticInits.clone - savedSymbolsStoredAsStatic = symbolsStoredAsStatic.clone - } - newStaticMembers.clear - newStaticInits.clear - symbolsStoredAsStatic.clear - val transformedTemplate: Template = { - var newBody = transformTrees(body) - treeCopy.Template(tree, parents, self, transformTrees(newStaticMembers.toList) ::: newBody) - } - val res = addStaticInits(transformedTemplate) // postprocess to include static ctors - newStaticMembers.clear - newStaticInits.clear - symbolsStoredAsStatic.clear - if(forMSIL) { - newStaticMembers ++= savedNewStaticMembers - newStaticInits ++= savedNewStaticInits - symbolsStoredAsStatic ++= savedSymbolsStoredAsStatic - } - res + if (forMSIL) savingStatics( transformTemplate(tree) ) + else transformTemplate(tree) case Literal(c) if (c.tag == ClassTag) && !forMSIL=> val tpe = c.typeValue @@ -612,15 +606,12 @@ abstract class CleanUp extends Transform with ast.TreeDSL { * And, finally, be advised - scala symbol literal and the Symbol class of the compiler * have little in common. */ - case symapp @ Apply(Select(Select(a @ Ident(nme.scala_), b @ nme.Symbol), nme.apply), - List(Literal(Constant(symname: String)))) => + case Apply(fn, (arg @ Literal(Constant(symname: String))) :: Nil) if fn.symbol == Symbol_apply => // add the symbol name to a map if it's not there already - val rhs = gen.mkCast(Apply(gen.scalaDot(nme.Symbol), List(Literal(Constant(symname)))), symbolType) - val staticFieldSym = getSymbolStaticField(symapp.pos, symname, rhs, symapp) - + val rhs = gen.mkMethodCall(Symbol_apply, arg :: Nil) + val staticFieldSym = getSymbolStaticField(tree.pos, symname, rhs, tree) // create a reference to a static field - val ntree = typedWithPos(symapp.pos)(safeREF(staticFieldSym)) - + val ntree = typedWithPos(tree.pos)(safeREF(staticFieldSym)) super.transform(ntree) // This transform replaces Array(Predef.wrapArray(Array(...)), <manifest>) @@ -640,19 +631,21 @@ abstract class CleanUp extends Transform with ast.TreeDSL { * If it doesn't exist, i.e. the symbol is encountered the first time, * it creates a new static field definition and initialization and returns it. */ - private def getSymbolStaticField(pos: Position, symname: String, rhs: Tree, tree: Tree): Symbol = + private def getSymbolStaticField(pos: Position, symname: String, rhs: Tree, tree: Tree): Symbol = { symbolsStoredAsStatic.getOrElseUpdate(symname, { val theTyper = typer.atOwner(tree, currentClass) // create a symbol for the static field - val stfieldSym = currentClass.newVariable(pos, mkTerm("symbol$")) - .setFlag(PRIVATE | STATIC | SYNTHETIC | FINAL) - .setInfo(symbolType) + val stfieldSym = ( + currentClass.newVariable(pos, mkTerm("symbol$")) + setFlag PRIVATE | STATIC | SYNTHETIC | FINAL + setInfo SymbolClass.tpe + ) currentClass.info.decls enter stfieldSym // create field definition and initialization - val stfieldDef = theTyper.typed { atPos(pos)(VAL(stfieldSym) === rhs) } - val stfieldInit = theTyper.typed { atPos(pos)(safeREF(stfieldSym) === rhs) } + val stfieldDef = theTyper.typedPos(pos)(VAL(stfieldSym) === rhs) + val stfieldInit = theTyper.typedPos(pos)(safeREF(stfieldSym) === rhs) // add field definition to new defs newStaticMembers append stfieldDef @@ -660,6 +653,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { stfieldSym }) + } /* finds the static ctor DefDef tree within the template if it exists. */ private def findStaticCtor(template: Template): Option[Tree] = @@ -671,7 +665,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { /* changes the template for the class so that it contains a static constructor with symbol fields inits, * augments an existing static ctor if one already existed. */ - private def addStaticInits(template: Template): Template = + private def addStaticInits(template: Template): Template = { if (newStaticInits.isEmpty) template else { @@ -693,11 +687,12 @@ abstract class CleanUp extends Transform with ast.TreeDSL { // create new static ctor val staticCtorSym = currentClass.newStaticConstructor(template.pos) val rhs = Block(newStaticInits.toList, Literal(Constant())) - val staticCtorTree = DefDef(staticCtorSym, rhs) - localTyper.typed { atPos(template.pos)(staticCtorTree) } + + localTyper.typedPos(template.pos)(DefDef(staticCtorSym, rhs)) } treeCopy.Template(template, template.parents, template.self, newCtor :: template.body) } + } } // CleanUpTransformer |