summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHubert Plociniczak <hubert.plociniczak@epfl.ch>2010-10-15 08:25:42 +0000
committerHubert Plociniczak <hubert.plociniczak@epfl.ch>2010-10-15 08:25:42 +0000
commit264e7c95f1f25102aee5492aef4ba3146863f6fd (patch)
tree2579d64b848c707575d031210414b23ab1befaed /src
parent3332d2052666f868092deea2b34f0b7b1b7fb932 (diff)
downloadscala-264e7c95f1f25102aee5492aef4ba3146863f6fd.tar.gz
scala-264e7c95f1f25102aee5492aef4ba3146863f6fd.tar.bz2
scala-264e7c95f1f25102aee5492aef4ba3146863f6fd.zip
Reverting r23232. No review.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/transform/LazyVals.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/Mixin.scala129
2 files changed, 42 insertions, 89 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/LazyVals.scala b/src/compiler/scala/tools/nsc/transform/LazyVals.scala
index e6bc44ad80..98b98b06ac 100644
--- a/src/compiler/scala/tools/nsc/transform/LazyVals.scala
+++ b/src/compiler/scala/tools/nsc/transform/LazyVals.scala
@@ -12,7 +12,6 @@ abstract class LazyVals extends Transform with TypingTransformers with ast.TreeD
import CODE._
val phaseName: String = "lazyvals"
- val FLAGS_PER_WORD: Int
def newTransformer(unit: CompilationUnit): Transformer =
new LazyValues(unit)
@@ -152,6 +151,7 @@ abstract class LazyVals extends Transform with TypingTransformers with ast.TreeD
private def mkSetFlag(bmp: Symbol, mask: Tree): Tree =
Ident(bmp) === (Ident(bmp) INT_| mask)
+ final val FLAGS_PER_WORD = 32
val bitmaps = new mutable.HashMap[Symbol, List[Symbol]] {
override def default(meth: Symbol) = Nil
}
diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala
index 5b561890b2..71472e1fcf 100644
--- a/src/compiler/scala/tools/nsc/transform/Mixin.scala
+++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala
@@ -206,9 +206,6 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
/** Map a lazy, mixedin field accessor to it's trait member accessor */
val initializer = new mutable.HashMap[Symbol, Symbol]
- /** Deferred bitmaps that will be added during the transformation of a class */
- val deferredBitmaps: collection.mutable.Map[Symbol, List[Tree]] = new collection.mutable.HashMap[Symbol, List[Tree]]
-
/** Add all members to be mixed in into a (non-trait-) class
* These are:
* for every mixin trait T that is not also inherited by the superclass:
@@ -617,11 +614,6 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
else newDefs ::: stats.filter(isNotDuplicate)
}
- def addDeferredBitmap(clazz: Symbol, tree: Tree) {
- // Append the set of deffered defs
- deferredBitmaps(clazz) = typedPos(clazz.pos)(tree)::deferredBitmaps.getOrElse(clazz, List())
- }
-
/** If `stat' is a superaccessor, complete it by adding a right-hand side.
* Note: superaccessors are always abstract until this point.
* The method to call in a superaccessor is stored in the accessor symbol's alias field.
@@ -646,62 +638,23 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
import lazyVals._
- /**
- * Return the bitmap field for 'offset'. Depending on the hierarchy it is possible to reuse
- * the bitmap of its parents. If that does not exist yet we create one.
- */
- def bitmapFor(clazz0: Symbol, offset: Int, searchParents:Boolean = true): Symbol = {
- def createBitmap: Symbol = {
- val sym = clazz0.newVariable(clazz0.pos, nme.bitmapName(offset / FLAGS_PER_WORD))
+ /** Return the bitmap field for 'offset', create one if not inheriting it already. */
+ def bitmapFor(clazz: Symbol, offset: Int): Symbol = {
+ var sym = clazz.info.member(nme.bitmapName(offset / FLAGS_PER_WORD))
+ assert(!sym.hasFlag(OVERLOADED))
+ if (sym == NoSymbol) {
+ sym = clazz.newVariable(clazz.pos, nme.bitmapName(offset / FLAGS_PER_WORD))
.setInfo(IntClass.tpe)
.setFlag(PROTECTED)
atPhase(currentRun.typerPhase) {
sym addAnnotation AnnotationInfo(VolatileAttr.tpe, Nil, Nil)
}
- clazz0.info.decls.enter(sym)
- if (clazz0 == clazz)
- addDef(clazz.pos, VAL(sym) === ZERO)
- else
- addDeferredBitmap(clazz0, VAL(sym) === ZERO)
- sym
- }
- var sym = clazz0.info.member(nme.bitmapName(offset / FLAGS_PER_WORD))
- assert(!sym.hasFlag(OVERLOADED))
- if (sym == NoSymbol) {
- if (searchParents)
- bitmapForParents(clazz0, offset) match {
- case Some(bitmap) =>
- sym = bitmap
- case None =>
- sym = createBitmap
- }
- else
- sym = createBitmap
+ clazz.info.decls.enter(sym)
+ addDef(clazz.pos, VAL(sym) === ZERO)
}
- //assert(sym != NoSymbol)
sym
}
- def bitmapForParents(clazz0: Symbol, offset: Int): Option[Symbol] = {
- def requiredBitmaps(fs: Int): Int = if (fs == 0) -1 else (fs - 1) / FLAGS_PER_WORD
-
- var res:Option[Symbol] = None
- val bitmapNum = offset / FLAGS_PER_WORD
-
- // on what else should we filter?
- for (cl <- clazz0.info.baseClasses.tail.filter(c => !c.isTrait && !c.hasFlag(JAVA))
- if res == None) {
- val fields0 = usedBits(cl)
-
- if (requiredBitmaps(fields0) < bitmapNum) {
- val fields1 = cl.info.decls.filter(fieldWithBitmap).size
- if (requiredBitmaps(fields0 + fields1) >= bitmapNum)
- res = Some(bitmapFor(cl, offset, false))
- }
- }
- res
- }
-
/** Return an (untyped) tree of the form 'Clazz.this.bmp = Clazz.this.bmp | mask'. */
def mkSetFlag(clazz: Symbol, offset: Int): Tree = {
val bmp = bitmapFor(clazz, offset)
@@ -752,6 +705,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
Select(This(clazz), sym1) === LIT(null)
}
+
val bitmapSym = bitmapFor(clazz, offset)
val mask = LIT(1 << (offset % FLAGS_PER_WORD))
def cond = mkTest(clazz, mask, bitmapSym, true)
@@ -780,6 +734,10 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
* the class constructor is changed to set the initialized bits.
*/
def addCheckedGetters(clazz: Symbol, stats: List[Tree]): List[Tree] = {
+ // TODO: not used?
+ def findLazyAssignment(stats: List[Tree]): Tree = (
+ for (s @ Assign(lhs, _) <- stats ; if lhs.symbol hasFlag LAZY) yield s
+ ) head // if there's no assignment then it's a bug and we crash
val stats1 = for (stat <- stats; sym = stat.symbol) yield stat match {
case DefDef(mods, name, tp, vp, tpt, rhs)
@@ -860,55 +818,50 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
}.transform(rhs)
}
- def fieldWithBitmap(field: Symbol) = {
- // For checkinit consider normal value getters
- // but for lazy values only take into account lazy getters
- (needsInitFlag(field) || field.hasFlag(LAZY) && field.isMethod) && !field.isDeferred
- }
-
-
- /**
- * Return the number of bits used by superclass fields.
+ /** Return the number of bits used by superclass fields.
+ * This number is a conservative approximation of what is actually used:
+ * - fields initialized to the default value don't get a checked initializer
+ * but there is no way to recover this information from types alone.
*/
- def usedBits(clazz0: Symbol): Int = {
- def needsBitmap(field: Symbol) =
- field.owner != clazz0 &&
- fieldWithBitmap(field)
-
- val fs = for {
- sc <- clazz0.info.baseClasses.tail
- field <- sc.info.decls.iterator.toList
- if !sc.isTrait && needsBitmap(field)
- } yield field
-
- fs.length
+ def usedBits(clazz: Symbol): Int = {
+ def isField(sym: Symbol) =
+ sym.hasFlag(PRIVATE) && sym.isTerm && !sym.isMethod
+
+ def needsBitmapField(sc: Type, field: Symbol) =
+ !sc.typeSymbol.isTrait &&
+ field.owner != clazz &&
+ (settings.checkInit.value && isField(field) ||
+ field.hasFlag(LAZY))
+
+ // parents != baseClasses.map(_.tpe): bug #1535
+ val fields = for {
+ sc <- clazz.info.baseClasses.map(_.tpe)
+ field <- sc.decls.iterator.toList
+ if needsBitmapField(sc, field)
+ } yield field
+
+ if (settings.debug.value) log("Found inherited fields in " + clazz + " : " + fields)
+ fields.length
}
+
/** Fill the map from fields to offset numbers.
* Instead of field symbols, the map keeps their getter symbols. This makes
* code generation easier later.
*/
- def buildFieldPositions(clazz0: Symbol) {
- var fields = usedBits(clazz0)
- for (f <- clazz0.info.decls.iterator if fieldWithBitmap(f)) {
+ def buildFieldPositions(clazz: Symbol) {
+ var fields = usedBits(clazz)
+ for (f <- clazz.info.decls.iterator if needsInitFlag(f) || f.hasFlag(LAZY)) {
if (settings.debug.value) log(f.fullName + " -> " + fields)
-
fieldOffset(f) = fields
fields += 1
}
}
- // begin addNewDefs
buildFieldPositions(clazz)
+ // begin addNewDefs
var stats1 = addCheckedGetters(clazz, stats)
- // add deffered bitmaps
- deferredBitmaps.remove(clazz) match {
- case Some(deferred) =>
- stats1 = add(stats1, deferred)
- case None =>
- }
-
// for all symbols `sym' in the class definition, which are mixed in:
for (sym <- clazz.info.decls.toList) {
if (sym hasFlag MIXEDIN) {