diff options
author | Paul Phillips <paulp@improving.org> | 2012-01-10 07:10:05 -0800 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2012-01-11 16:21:38 -0800 |
commit | 5f5029d2ac6348ecb07fc11f6656621c662ced92 (patch) | |
tree | 59f3946d2c5e2612cd2c36ca008c016b0c69b0d5 /src/compiler/scala/tools/nsc/transform/CleanUp.scala | |
parent | b00002f9049c034510438881b4a4449d73fe2f54 (diff) | |
download | scala-5f5029d2ac6348ecb07fc11f6656621c662ced92.tar.gz scala-5f5029d2ac6348ecb07fc11f6656621c662ced92.tar.bz2 scala-5f5029d2ac6348ecb07fc11f6656621c662ced92.zip |
Optimizing TypeRef, starting with Symbols.
There are too many potential optimizations unavailable to us due to the
lack of bright lines among different kinds of symbols. For instance the
difference between a TypeSymbol which represents a type alias and one
which represents an abstract type is only whether the DEFERRED flag
is set. This creates issues.
1) There are many (many) places where tests are performed on every symbol
which could be done more efficiently and (especially) more verifiably
correctly with polymorphism.
2) TypeRefs based on those symbols are also checking that flag
constantly, in perpetuity. A symbol created as an alias is never (to the
best of my knowledge) going to intentionally morph into one representing
an abstract type, nor vice versa.
3) One has no guarantees, because anyone can set or reset the DEFERRED
flag at any time.
So tackling more than one problem at once herein:
1) I created canonical symbol creation points which take the flags as
an argument, so that there can be a difference between initializing a
symbol's flags and setting/resetting them at arbitrary times.
2) I structured all the symbol creators to take arguments in the
same order, which is:
def newXXX(name: Name, ..., pos: Position = NoPosition, flags: Long = 0L)
(Where "..." is for those symbols which require something
beyond the name to create, such as a TypeSkolem's origin.)
The name is first because it's the only always required argument.
I left but deprecated the variations which take (pos, name).
3) I created subclasses of TypeRef based on the information which
should be stable from creation time onward:
- args or no args?
- abstract type, type alias, or class?
2x3 == 6 and that's how many subclasses of TypeRef there are now. So
now, for example, every TypeRef doesn't have to carry null symInfoCache
and thisInfoCache fields for the benefit of the minority which use them.
I still intend to realize the gain possible once we can evade the fields
for pre and args without losing pattern matcher efficiency.
Diffstat (limited to 'src/compiler/scala/tools/nsc/transform/CleanUp.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/CleanUp.scala | 19 |
1 files changed, 9 insertions, 10 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/CleanUp.scala b/src/compiler/scala/tools/nsc/transform/CleanUp.scala index 034628e95f..0bc137f3e8 100644 --- a/src/compiler/scala/tools/nsc/transform/CleanUp.scala +++ b/src/compiler/scala/tools/nsc/transform/CleanUp.scala @@ -143,13 +143,13 @@ abstract class CleanUp extends Transform with ast.TreeDSL { /* ### CREATING THE METHOD CACHE ### */ 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 + val flags = PRIVATE | STATIC | SYNTHETIC | ( + if (isFinal) FINAL else 0 ) - if (isFinal) varSym setFlag FINAL - else varSym.addAnnotation(VolatileAttr) + + val varSym = currentClass.newVariable(mkTerm("" + forName), ad.pos, flags) setInfo forType + if (!isFinal) + varSym.addAnnotation(VolatileAttr) currentClass.info.decls enter varSym val varDef = typedPos( VAL(varSym) === forInit ) @@ -280,7 +280,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { addStaticMethodToClass(nme.reflMethodName, List(ClassClass.tpe), MethodClass.tpe) { case Pair(reflMethodSym, List(forReceiverSym)) => - val methodSym = reflMethodSym.newVariable(ad.pos, mkTerm("method")) setInfo MethodClass.tpe + val methodSym = reflMethodSym.newVariable(mkTerm("method"), ad.pos) setInfo MethodClass.tpe BLOCK( IF (getPolyCache OBJ_EQ NULL) THEN (safeREF(reflPolyCacheSym) === mkNewPolyCache) ENDIF, @@ -565,7 +565,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { case theTry @ Try(block, catches, finalizer) if theTry.tpe.typeSymbol != definitions.UnitClass && theTry.tpe.typeSymbol != definitions.NothingClass => val tpe = theTry.tpe.widen - val tempVar = currentOwner.newVariable(theTry.pos, mkTerm(nme.EXCEPTION_RESULT_PREFIX)).setInfo(tpe) + val tempVar = currentOwner.newVariable(mkTerm(nme.EXCEPTION_RESULT_PREFIX), theTry.pos).setInfo(tpe) def assignBlock(rhs: Tree) = super.transform(BLOCK(Ident(tempVar) === transform(rhs))) val newBlock = assignBlock(block) @@ -637,8 +637,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { // create a symbol for the static field val stfieldSym = ( - currentClass.newVariable(pos, mkTerm("symbol$")) - setFlag PRIVATE | STATIC | SYNTHETIC | FINAL + currentClass.newVariable(mkTerm("symbol$"), pos, PRIVATE | STATIC | SYNTHETIC | FINAL) setInfo SymbolClass.tpe ) currentClass.info.decls enter stfieldSym |