diff options
author | Hubert Plociniczak <hubert.plociniczak@epfl.ch> | 2011-01-07 14:42:45 +0000 |
---|---|---|
committer | Hubert Plociniczak <hubert.plociniczak@epfl.ch> | 2011-01-07 14:42:45 +0000 |
commit | 5cefd81ee9f99535e3e2ce8a23016206da65a92d (patch) | |
tree | d04db0731101cd23430747766e3cbbbfd34cd018 | |
parent | 33b35dfbfdaaeaafa8783008c964e96b7b705972 (diff) | |
download | scala-5cefd81ee9f99535e3e2ce8a23016206da65a92d.tar.gz scala-5cefd81ee9f99535e3e2ce8a23016206da65a92d.tar.bz2 scala-5cefd81ee9f99535e3e2ce8a23016206da65a92d.zip |
Closes #4072.
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/StdNames.scala | 8 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/Mixin.scala | 60 | ||||
-rw-r--r-- | test/files/run/t3038b.check | 6 | ||||
-rw-r--r-- | test/files/run/t3038b.scala | 14 |
4 files changed, 62 insertions, 26 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/StdNames.scala b/src/compiler/scala/tools/nsc/symtab/StdNames.scala index 30c1db9de1..0e28ac54e1 100644 --- a/src/compiler/scala/tools/nsc/symtab/StdNames.scala +++ b/src/compiler/scala/tools/nsc/symtab/StdNames.scala @@ -328,11 +328,17 @@ trait StdNames extends reflect.generic.StdNames with NameManglers { def bitmapName(n: Int): TermName = bitmapName(n, "") /** The name of bitmaps for initialized transient lazy vals. */ - def bitmapNameForTransitive(n: Int): TermName = bitmapName(n, "trans$") + def bitmapNameForTransient(n: Int): TermName = bitmapName(n, "trans$") /** The name of bitmaps for initialized private lazy vals. */ def bitmapNameForPrivate(n: Int): TermName = bitmapName(n, "priv$") + /** The name of bitmaps for checkinit values */ + def bitmapNameForCheckinit(n: Int): TermName = bitmapName(n, "init$") + + /** The name of bitmaps for checkinit values that have transient flag*/ + def bitmapNameForCheckinitTransient(n: Int): TermName = bitmapName(n, "inittrans$") + /** Base strings from which synthetic names are derived. */ val BITMAP_PREFIX = "bitmap$" val CHECK_IF_REFUTABLE_STRING = "check$ifrefutable$" diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index 6ed1a8f7b5..8d3c76e176 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -657,36 +657,45 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { /** * Private or transient lazy vals use bitmaps that are private for the class context, * unlike public or protected vals, which can use inherited bitmaps. + * Similarly fields in the checkinit mode use private bitmaps. */ def localBitmapField(field: Symbol) = - field.accessed.hasAnnotation(TransientAttr) || field.hasFlag(PRIVATE) + field.accessed.hasAnnotation(TransientAttr) || field.hasFlag(PRIVATE) || checkinitField(field) /** * 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, field: Symbol, searchParents:Boolean = true): Symbol = { - def bitmapName: Name = - bitmapOperation(field, nme.bitmapNameForTransitive(offset / FLAGS_PER_WORD), + def bitmapLazyName: Name = + bitmapOperation(field, nme.bitmapNameForTransient(offset / FLAGS_PER_WORD), nme.bitmapNameForPrivate(offset / FLAGS_PER_WORD), nme.bitmapName(offset / FLAGS_PER_WORD)) + def bitmapCheckinitName: Name = + bitmapOperation(field, nme.bitmapNameForCheckinitTransient(offset / FLAGS_PER_WORD), + nme.bitmapNameForCheckinit(offset / FLAGS_PER_WORD), + nme.bitmapNameForCheckinit(offset / FLAGS_PER_WORD)) + val checkinitField = !field.isLazy + val bitmapName = if (checkinitField) bitmapCheckinitName else bitmapLazyName + def createBitmap: Symbol = { - val sym = clazz0.newVariable(clazz0.pos, bitmapName) - .setInfo(IntClass.tpe) + + val sym = clazz0.newVariable(clazz0.pos, bitmapName).setInfo(IntClass.tpe) atPhase(currentRun.typerPhase) { sym addAnnotation AnnotationInfo(VolatileAttr.tpe, Nil, Nil) } bitmapOperation(field, {sym.addAnnotation(AnnotationInfo(TransientAttr.tpe, Nil, Nil)); sym.setFlag(PRIVATE | LOCAL)}, - sym.setFlag(PRIVATE | LOCAL), sym.setFlag(PROTECTED)) + sym.setFlag(PRIVATE | LOCAL), + sym.setFlag(if (checkinitField) (PRIVATE | LOCAL) else PROTECTED)) clazz0.info.decls.enter(sym) if (clazz0 == clazz) addDef(clazz.pos, VAL(sym) === ZERO) else { //FIXME: the assertion below will not work because of the way bitmaps are added. - // They should be added during inforTransform, so that in separate compilation, bitmap + // They should be added during infoTransform, so that in separate compilation, bitmap // is a member of clazz and doesn't fail the condition couple lines below. // This works, as long as we assume that the previous classes were compiled correctly. //assert(clazz0.sourceFile != null) @@ -718,7 +727,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { // filter private and transient - // on what else should we filter? + // since we do not inherit normal values (in checkinit mode) also filter them out for (cl <- clazz0.info.baseClasses.tail.filter(c => !c.isTrait && !c.hasFlag(JAVA)) if res == None) { val fields0 = usedBits(cl) @@ -860,7 +869,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { val res = (settings.checkInit.value && sym.isGetter && !sym.isInitializedToDefault - && !sym.hasFlag(PARAMACCESSOR | SPECIALIZED) + && !sym.hasFlag(PARAMACCESSOR | SPECIALIZED | LAZY) && !sym.accessed.hasFlag(PRESUPER) && !sym.isOuterAccessor && !(sym.owner isSubClass DelayedInitClass)) @@ -907,12 +916,15 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { } def fieldWithBitmap(field: Symbol) = { - field.info // ensure that nested objects are tranformed + field.info // ensure that nested objects are transformed // For checkinit consider normal value getters // but for lazy values only take into account lazy getters - (needsInitFlag(field) || field.isLazy && field.isMethod) && !field.isDeferred + field.isLazy && field.isMethod && !field.isDeferred } + def checkinitField(field: Symbol) = + needsInitFlag(field) && !field.isDeferred + /** * Return the number of bits used by superclass fields. */ @@ -937,14 +949,26 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { var fields = usedBits(clazz0) var fieldsPrivate = 0 var fieldsTransient = 0 - for (f <- clazz0.info.decls.iterator if fieldWithBitmap(f)) { + var fieldsCheckinit = 0 + var fieldsCheckinitTransient = 0 + + for (f <- clazz0.info.decls.iterator) { if (settings.debug.value) log(f.fullName + " -> " + fields) - val (idx, _) = + if (fieldWithBitmap(f)) { + val (idx, _) = bitmapOperation(f, (fieldsTransient, fieldsTransient += 1), - (fieldsPrivate, fieldsPrivate += 1), - (fields, fields += 1)) - fieldOffset(f) = idx + (fieldsPrivate, fieldsPrivate += 1), + (fields, fields += 1)) + fieldOffset(f) = idx + } else if (checkinitField(f)) { + // bitmaps for checkinit fields are not inherited + val (idx, _) = + bitmapOperation(f, (fieldsCheckinitTransient, fieldsCheckinitTransient += 1), + (fieldsCheckinit, fieldsCheckinit += 1), + (fieldsCheckinit, fieldsCheckinit += 1)) + fieldOffset(f) = idx + } } } @@ -1009,12 +1033,12 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { case _ => val init = Assign(accessedRef, Ident(vparams.head)) val getter = sym.getter(clazz) - if (settings.checkInit.value && needsInitFlag(getter)) + if (needsInitFlag(getter)) Block(List(init, mkSetFlag(clazz, fieldOffset(getter), getter)), UNIT) else init } - } else if (!sym.isLazy && needsInitFlag(sym)) { + } else if (needsInitFlag(sym)) { mkCheckedAccessor(clazz, accessedRef, fieldOffset(sym), sym.pos, sym) } else gen.mkCheckInit(accessedRef) diff --git a/test/files/run/t3038b.check b/test/files/run/t3038b.check new file mode 100644 index 0000000000..cf0389a5af --- /dev/null +++ b/test/files/run/t3038b.check @@ -0,0 +1,6 @@ +1 +2 +3 +4 +5 +6
\ No newline at end of file diff --git a/test/files/run/t3038b.scala b/test/files/run/t3038b.scala index 5237ee941e..0b9731f52a 100644 --- a/test/files/run/t3038b.scala +++ b/test/files/run/t3038b.scala @@ -6,15 +6,15 @@ class A { @transient val c1 = 5 @transient val c2 = 6 def run = { - a1 - a2 - b1 - b2 - c1 - c2 + println(a1) + println(a2) + println(b1) + println(b2) + println(c1) + println(c2) } } object Test extends Application { new A().run -}
\ No newline at end of file +} |