@@ -492,6 +492,19 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
492492 * fields count as fields defined by the class itself.
493493 */
494494 private val fieldOffset = perRunCaches.newMap[Symbol , Int ]()
495+
496+ private val bitmapKindForCategory = perRunCaches.newMap[Name , ClassSymbol ]() // TODO: make it a list
497+
498+ // ByteClass, IntClass, LongClass
499+ private def bitmapKind (field : Symbol ): ClassSymbol = bitmapKindForCategory(bitmapCategory(field))
500+
501+ private def flagsPerBitmap (field : Symbol ): Int = bitmapKind(field) match {
502+ case BooleanClass => 1
503+ case ByteClass => 8
504+ case IntClass => 32
505+ case LongClass => 64
506+ }
507+
495508
496509 /** The first transform; called in a pre-order traversal at phase mixin
497510 * (that is, every node is processed before its children).
@@ -610,8 +623,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
610623 if (field.accessed hasAnnotation TransientAttr ) {
611624 if (isNormal) BITMAP_TRANSIENT
612625 else BITMAP_CHECKINIT_TRANSIENT
613- }
614- else {
626+ } else {
615627 if (isNormal) BITMAP_NORMAL
616628 else BITMAP_CHECKINIT
617629 }
@@ -696,30 +708,34 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
696708 stat
697709 }
698710
699- import lazyVals ._
700-
701711 /**
702712 * Return the bitmap field for 'offset'. Depending on the hierarchy it is possible to reuse
703713 * the bitmap of its parents. If that does not exist yet we create one.
704714 */
705715 def bitmapFor (clazz0 : Symbol , offset : Int , field : Symbol ): Symbol = {
706716 val category = bitmapCategory(field)
707- val bitmapName = nme.newBitmapName(category, offset / FLAGS_PER_WORD )
717+ val bitmapName = nme.newBitmapName(category, offset / flagsPerBitmap(field) )
708718 val sym = clazz0.info.decl(bitmapName)
709719
710720 assert(! sym.isOverloaded, sym)
711721
712722 def createBitmap : Symbol = {
713- val sym = clazz0.newVariable(bitmapName, clazz0.pos) setInfo IntClass .tpe
723+ val bitmapKind = bitmapKindForCategory(category)
724+ val sym = clazz0.newVariable(bitmapName, clazz0.pos) setInfo bitmapKind.tpe
714725 beforeTyper(sym addAnnotation VolatileAttr )
715726
716727 category match {
717728 case nme.BITMAP_TRANSIENT | nme.BITMAP_CHECKINIT_TRANSIENT => sym addAnnotation TransientAttr
718729 case _ =>
719730 }
731+ val init = bitmapKind match {
732+ case BooleanClass => VAL (sym) === FALSE
733+ case _ => VAL (sym) === ZERO
734+ }
735+
720736 sym setFlag PrivateLocal
721737 clazz0.info.decls.enter(sym)
722- addDef(clazz0.pos, VAL (sym) === ZERO )
738+ addDef(clazz0.pos, init )
723739 sym
724740 }
725741
@@ -728,23 +744,36 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
728744 else
729745 createBitmap
730746 }
747+
748+ def maskForOffset (offset : Int , sym : Symbol , kind : ClassSymbol ): Tree = {
749+ def realOffset = offset % flagsPerBitmap(sym)
750+ if (kind == LongClass ) LIT (1L << realOffset) else LIT (1 << realOffset)
751+ }
731752
732753 /** Return an (untyped) tree of the form 'Clazz.this.bmp = Clazz.this.bmp | mask'. */
733- def mkSetFlag (clazz : Symbol , offset : Int , valSym : Symbol ): Tree = {
734- val bmp = bitmapFor(clazz, offset, valSym)
735- val mask = LIT (1 << (offset % FLAGS_PER_WORD ))
736- def x = This (clazz) DOT bmp
754+ def mkSetFlag (clazz : Symbol , offset : Int , valSym : Symbol , kind : ClassSymbol ): Tree = {
755+ val bmp = bitmapFor(clazz, offset, valSym)
756+ def mask = maskForOffset(offset, valSym, kind)
757+ def x = This (clazz) DOT bmp
758+ def newValue = if (kind == BooleanClass ) TRUE else (x GEN_| (mask, kind))
737759
738- x === (x INT_| mask)
760+ x === newValue
739761 }
740762
741763 /** Return an (untyped) tree of the form 'clazz.this.bitmapSym & mask (==|!=) 0', the
742764 * precise comparison operator depending on the value of 'equalToZero'.
743765 */
744- def mkTest (clazz : Symbol , mask : Tree , bitmapSym : Symbol , equalToZero : Boolean ): Tree = {
745- def lhs = (This (clazz) DOT bitmapSym) INT_& mask
746- if (equalToZero) lhs INT_== ZERO
747- else lhs INT_!= ZERO
766+ def mkTest (clazz : Symbol , mask : Tree , bitmapSym : Symbol , equalToZero : Boolean , kind : ClassSymbol ): Tree = {
767+ val bitmapTree = (This (clazz) DOT bitmapSym)
768+ def lhs = bitmapTree GEN_& (mask, kind)
769+ kind match {
770+ case BooleanClass =>
771+ if (equalToZero) NOT (bitmapTree)
772+ else bitmapTree
773+ case _ =>
774+ if (equalToZero) lhs GEN_== (ZERO , kind)
775+ else lhs GEN_!= (ZERO , kind)
776+ }
748777 }
749778
750779 /** return a 'lazified' version of rhs. It uses double-checked locking to ensure
@@ -777,10 +806,11 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
777806 def nullify (sym : Symbol ) = Select (This (clazz), sym.accessedOrSelf) === LIT (null )
778807
779808 val bitmapSym = bitmapFor(clazz, offset, lzyVal)
780- val mask = LIT (1 << (offset % FLAGS_PER_WORD ))
781- def cond = mkTest(clazz, mask, bitmapSym, true )
809+ val kind = bitmapKind(lzyVal)
810+ val mask = maskForOffset(offset, lzyVal, kind)
811+ def cond = mkTest(clazz, mask, bitmapSym, true , kind)
782812 val nulls = lazyValNullables(lzyVal).toList sortBy (_.id) map nullify
783- def syncBody = init ::: List (mkSetFlag(clazz, offset, lzyVal), UNIT )
813+ def syncBody = init ::: List (mkSetFlag(clazz, offset, lzyVal, kind ), UNIT )
784814
785815 if (nulls.nonEmpty)
786816 log(" nulling fields inside " + lzyVal + " : " + nulls)
@@ -802,11 +832,13 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
802832 }
803833
804834 def mkCheckedAccessor (clazz : Symbol , retVal : Tree , offset : Int , pos : Position , fieldSym : Symbol ): Tree = {
805- val bitmapSym = bitmapFor(clazz, offset, fieldSym.getter(fieldSym.owner))
806- val mask = LIT (1 << (offset % FLAGS_PER_WORD ))
835+ val sym = fieldSym.getter(fieldSym.owner)
836+ val bitmapSym = bitmapFor(clazz, offset, sym)
837+ val kind = bitmapKind(sym)
838+ val mask = maskForOffset(offset, sym, kind)
807839 val msg = " Uninitialized field: " + unit.source + " : " + pos.line
808840 val result =
809- IF (mkTest(clazz, mask, bitmapSym, false )) .
841+ IF (mkTest(clazz, mask, bitmapSym, false , kind )) .
810842 THEN (retVal) .
811843 ELSE (THROW (UninitializedErrorClass , LIT (msg)))
812844
@@ -851,7 +883,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
851883 else if (settings.checkInit.value && ! clazz.isTrait && sym.isSetter) {
852884 val getter = sym.getter(clazz)
853885 if (needsInitFlag(getter) && fieldOffset.isDefinedAt(getter))
854- deriveDefDef(stat)(rhs => Block (List (rhs, localTyper.typed(mkSetFlag(clazz, fieldOffset(getter), getter))), UNIT ))
886+ deriveDefDef(stat)(rhs => Block (List (rhs, localTyper.typed(mkSetFlag(clazz, fieldOffset(getter), getter, bitmapKind(getter) ))), UNIT ))
855887 else stat
856888 }
857889 else if (sym.isModule && (! clazz.isTrait || clazz.isImplClass) && ! sym.isBridge) {
@@ -879,7 +911,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
879911 val sym = clazz.info decl lhs.symbol.getterName suchThat (_.isGetter)
880912 if (needsInitAndHasOffset(sym)) {
881913 debuglog(" adding checked getter for: " + sym + " " + lhs.symbol.flagString)
882- List (localTyper typed mkSetFlag(clazz, fieldOffset(sym), sym))
914+ List (localTyper typed mkSetFlag(clazz, fieldOffset(sym), sym, bitmapKind(sym) ))
883915 }
884916 else Nil
885917 }
@@ -917,16 +949,22 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
917949 * code generation easier later.
918950 */
919951 def buildBitmapOffsets () {
920- def fold (zero : Int , fields : List [Symbol ]) = {
921- var idx = zero
952+ def fold (fields : List [Symbol ], category : Name ) = {
953+ var idx = 0
922954 fields foreach { f =>
923955 fieldOffset(f) = idx
924956 idx += 1
925957 }
958+
959+ if (idx == 0 ) ()
960+ else if (idx == 1 ) bitmapKindForCategory(category) = BooleanClass
961+ else if (idx < 9 ) bitmapKindForCategory(category) = ByteClass
962+ else if (idx < 33 ) bitmapKindForCategory(category) = IntClass
963+ else bitmapKindForCategory(category) = LongClass
926964 }
927965 clazz.info.decls.toList groupBy bitmapCategory foreach {
928966 case (nme.NO_NAME , _) => ()
929- case (_ , fields) => fold(0 , fields )
967+ case (category , fields) => fold(fields, category )
930968 }
931969 }
932970 buildBitmapOffsets()
@@ -977,7 +1015,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
9771015 val getter = sym.getter(clazz)
9781016
9791017 if (! needsInitFlag(getter)) init
980- else Block (init, mkSetFlag(clazz, fieldOffset(getter), getter), UNIT )
1018+ else Block (init, mkSetFlag(clazz, fieldOffset(getter), getter, bitmapKind(getter) ), UNIT )
9811019 }
9821020 }
9831021 else if (needsInitFlag(sym))
0 commit comments