From a9b85dbaad568b5c709a5eb6ab23907cdf4ee29e Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 11 Jul 2012 19:03:35 +0200 Subject: Pickled flag reorg Cleaned up and optimized code that maps between raw and pickled flags. Avoids mystery constants. Makes a whole bunch of new flags be pickled which were not pickled before (more precisely: Everything in InitialFlags with value greater than 1 << 31 which is not in FlagsNotPickled now gets pickled whereas before it wasn't. Among these: VARARGS, IMPLCLASS, SPECIALZED, DEFAULTINIT, SYNCHRONIZED. I am curious how many tickets will get fixed by this change. The first one I noted is t5504, which previously enforced the buggy behavior through a neg check! There are also some build manager check file changes that have to do with the fact that flags now print in a different order for performance reasons. --- .../scala/tools/nsc/symtab/classfile/Pickler.scala | 4 +- src/reflect/scala/reflect/internal/Flags.scala | 81 +++++++++++----------- test/files/buildmanager/t2651_3/t2651_3.check | 2 +- test/files/buildmanager/t2651_4/t2651_4.check | 4 +- test/files/buildmanager/t2657/t2657.check | 4 +- test/files/buildmanager/t2789/t2789.check | 4 +- test/files/neg/t5504.check | 4 -- test/files/neg/t5504/s_1.scala | 4 -- test/files/neg/t5504/s_2.scala | 8 --- test/files/pos/t5504/s_1.scala | 4 ++ test/files/pos/t5504/s_2.scala | 8 +++ 11 files changed, 61 insertions(+), 66 deletions(-) delete mode 100644 test/files/neg/t5504.check delete mode 100644 test/files/neg/t5504/s_1.scala delete mode 100644 test/files/neg/t5504/s_2.scala create mode 100644 test/files/pos/t5504/s_1.scala create mode 100644 test/files/pos/t5504/s_2.scala diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala index 192cc94b90..cc5ed0f129 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala @@ -503,7 +503,7 @@ abstract class Pickler extends SubComponent { private def writeSymInfo(sym: Symbol) { writeRef(sym.name) writeRef(localizedOwner(sym)) - writeLongNat((rawFlagsToPickled(sym.flags & PickledFlags))) + writeLongNat((rawToPickledFlags(sym.flags & PickledFlags))) if (sym.hasAccessBoundary) writeRef(sym.privateWithin) writeRef(sym.info) } @@ -966,7 +966,7 @@ abstract class Pickler extends SubComponent { TREE case Modifiers(flags, privateWithin, _) => - val pflags = rawFlagsToPickled(flags) + val pflags = rawToPickledFlags(flags) writeNat((pflags >> 32).toInt) writeNat((pflags & 0xFFFFFFFF).toInt) writeRef(privateWithin) diff --git a/src/reflect/scala/reflect/internal/Flags.scala b/src/reflect/scala/reflect/internal/Flags.scala index 37e5a23819..c17600ec41 100644 --- a/src/reflect/scala/reflect/internal/Flags.scala +++ b/src/reflect/scala/reflect/internal/Flags.scala @@ -165,6 +165,7 @@ class Flags extends ModifierFlags { // A Java method's type is ``cooked'' by transforming raw types to existentials final val SYNCHRONIZED = 1L << 45 // symbol is a method which should be marked ACC_SYNCHRONIZED + // ------- shift definitions ------------------------------------------------------- final val InitialFlags = 0x0001FFFFFFFFFFFFL // flags that are enabled from phase 1. @@ -211,7 +212,7 @@ class Flags extends ModifierFlags { /** To be a little clearer to people who aren't habitual bit twiddlers. */ final val AllFlags = -1L - + /** These flags can be set when class or module symbol is first created. * They are the only flags to survive a call to resetFlags(). */ @@ -279,6 +280,12 @@ class Flags extends ModifierFlags { /** Module flags inherited by their module-class */ final val ModuleToClassFlags = AccessFlags | TopLevelCreationFlags | CASE | SYNTHETIC + /** These flags are not pickled */ + final val FlagsNotPickled = IS_ERROR | OVERLOADED | LIFTED | TRANS_FLAG | LOCKED | TRIEDCOOKING + + /** These flags are pickled */ + final val PickledFlags = InitialFlags & ~FlagsNotPickled + def getterFlags(fieldFlags: Long): Long = ACCESSOR + ( if ((fieldFlags & MUTABLE) != 0) fieldFlags & ~MUTABLE & ~PRESUPER else fieldFlags & ~PRESUPER | STABLE @@ -307,47 +314,45 @@ class Flags extends ModifierFlags { private final val PKL_MASK = 0x00000FFF - final val PickledFlags = 0xFFFFFFFFL - - private def rawPickledCorrespondence = Array( - (IMPLICIT, IMPLICIT_PKL), - (FINAL, FINAL_PKL), + /** Pickler correspondence, ordered roughly by frequency of occurrence */ + private def rawPickledCorrespondence = Array[(Long, Long)]( + (METHOD, METHOD_PKL), (PRIVATE, PRIVATE_PKL), + (FINAL, FINAL_PKL), (PROTECTED, PROTECTED_PKL), - (SEALED, SEALED_PKL), - (OVERRIDE, OVERRIDE_PKL), (CASE, CASE_PKL), - (ABSTRACT, ABSTRACT_PKL), (DEFERRED, DEFERRED_PKL), - (METHOD, METHOD_PKL), (MODULE, MODULE_PKL), - (INTERFACE, INTERFACE_PKL) + (OVERRIDE, OVERRIDE_PKL), + (INTERFACE, INTERFACE_PKL), + (IMPLICIT, IMPLICIT_PKL), + (SEALED, SEALED_PKL), + (ABSTRACT, ABSTRACT_PKL) ) - private val rawFlags: Array[Int] = rawPickledCorrespondence map (_._1) - private val pickledFlags: Array[Int] = rawPickledCorrespondence map (_._2) - - private def r2p(flags: Int): Int = { - var result = 0 - var i = 0 - while (i < rawFlags.length) { - if ((flags & rawFlags(i)) != 0) - result |= pickledFlags(i) - - i += 1 - } - result - } - private def p2r(flags: Int): Int = { - var result = 0 - var i = 0 - while (i < rawFlags.length) { - if ((flags & pickledFlags(i)) != 0) - result |= rawFlags(i) - - i += 1 + + private val mappedRawFlags = rawPickledCorrespondence map (_._1) + private val mappedPickledFlags = rawPickledCorrespondence map (_._2) + + private class MapFlags(from: Array[Long], to: Array[Long]) extends (Long => Long) { + val fromSet = (0L /: from) (_ | _) + + def apply(flags: Long): Long = { + var result = flags & ~fromSet + var tobeMapped = flags & fromSet + var i = 0 + while (tobeMapped != 0) { + if ((tobeMapped & from(i)) != 0) { + result |= to(i) + tobeMapped &= ~from(i) + } + i += 1 + } + result } - result } + + val rawToPickledFlags: Long => Long = new MapFlags(mappedRawFlags, mappedPickledFlags) + val pickledToRawFlags: Long => Long = new MapFlags(mappedPickledFlags, mappedRawFlags) // ------ displaying flags -------------------------------------------------------- @@ -462,18 +467,12 @@ class Flags extends ModifierFlags { } } - def rawFlagsToPickled(flags: Long): Long = - (flags & ~PKL_MASK) | r2p(flags.toInt & PKL_MASK) - - def pickledToRawFlags(pflags: Long): Long = - (pflags & ~PKL_MASK) | p2r(pflags.toInt & PKL_MASK) - // List of the raw flags, in pickled order final val MaxBitPosition = 62 final val pickledListOrder: List[Long] = { val all = 0 to MaxBitPosition map (1L << _) - val front = rawFlags map (_.toLong) + val front = mappedRawFlags map (_.toLong) front.toList ++ (all filterNot (front contains _)) } diff --git a/test/files/buildmanager/t2651_3/t2651_3.check b/test/files/buildmanager/t2651_3/t2651_3.check index d4bac196e9..2a60e3d806 100644 --- a/test/files/buildmanager/t2651_3/t2651_3.check +++ b/test/files/buildmanager/t2651_3/t2651_3.check @@ -3,4 +3,4 @@ compiling Set(A.scala) Changes: Map() builder > A.scala compiling Set(A.scala) -Changes: Map(trait A -> List(Changed(Definition(A.x))[method x changed from ()T to ()S flags: ])) +Changes: Map(trait A -> List(Changed(Definition(A.x))[method x changed from ()T to ()S flags: ])) diff --git a/test/files/buildmanager/t2651_4/t2651_4.check b/test/files/buildmanager/t2651_4/t2651_4.check index b182f31c09..74e5d8f99b 100644 --- a/test/files/buildmanager/t2651_4/t2651_4.check +++ b/test/files/buildmanager/t2651_4/t2651_4.check @@ -3,8 +3,8 @@ compiling Set(A.scala, B.scala) Changes: Map() builder > A.scala compiling Set(A.scala) -Changes: Map(trait A -> List(Changed(Definition(A.x))[method x changed from ()T to ()T flags: ], Changed(Definition(A.y))[method y changed from (a: T)Unit to (a: T)Unit flags: ], Changed(Definition(A.z))[method z changed from [B <: T]()Unit to [B <: T]()Unit flags: ])) -invalidate B.scala because inherited method changed [Changed(Definition(A.x))[method x changed from ()T to ()T flags: ]] +Changes: Map(trait A -> List(Changed(Definition(A.x))[method x changed from ()T to ()T flags: ], Changed(Definition(A.y))[method y changed from (a: T)Unit to (a: T)Unit flags: ], Changed(Definition(A.z))[method z changed from [B <: T]()Unit to [B <: T]()Unit flags: ])) +invalidate B.scala because inherited method changed [Changed(Definition(A.x))[method x changed from ()T to ()T flags: ]] compiling Set(B.scala) B.scala:2: error: type mismatch; found : Int(3) diff --git a/test/files/buildmanager/t2657/t2657.check b/test/files/buildmanager/t2657/t2657.check index cd0357599c..0d6709e58b 100644 --- a/test/files/buildmanager/t2657/t2657.check +++ b/test/files/buildmanager/t2657/t2657.check @@ -4,8 +4,8 @@ warning: there were 1 feature warnings; re-run with -feature for details Changes: Map() builder > A.scala compiling Set(A.scala) -Changes: Map(class A -> List(Changed(Definition(A.y))[method y changed from (i: Int)String to (i: Int)String flags: implicit ])) -invalidate B.scala because inherited method changed [Changed(Definition(A.y))[method y changed from (i: Int)String to (i: Int)String flags: implicit ]] +Changes: Map(class A -> List(Changed(Definition(A.y))[method y changed from (i: Int)String to (i: Int)String flags: implicit ])) +invalidate B.scala because inherited method changed [Changed(Definition(A.y))[method y changed from (i: Int)String to (i: Int)String flags: implicit ]] compiling Set(B.scala) B.scala:2: error: type mismatch; found : Int(3) diff --git a/test/files/buildmanager/t2789/t2789.check b/test/files/buildmanager/t2789/t2789.check index a7c767cc45..066561ac44 100644 --- a/test/files/buildmanager/t2789/t2789.check +++ b/test/files/buildmanager/t2789/t2789.check @@ -3,8 +3,8 @@ compiling Set(A.scala, B.scala) Changes: Map() builder > A.scala compiling Set(A.scala) -Changes: Map(class A -> List(Changed(Definition(A.e))[method e changed from ()E to ()E flags: implicit ]), class E -> List()) -invalidate B.scala because inherited method changed [Changed(Definition(A.e))[method e changed from ()E to ()E flags: implicit ]] +Changes: Map(class A -> List(Changed(Definition(A.e))[method e changed from ()E to ()E flags: implicit ]), class E -> List()) +invalidate B.scala because inherited method changed [Changed(Definition(A.e))[method e changed from ()E to ()E flags: implicit ]] compiling Set(B.scala) B.scala:2: error: could not find implicit value for parameter y: E val y = x(3) diff --git a/test/files/neg/t5504.check b/test/files/neg/t5504.check deleted file mode 100644 index 2827c02d10..0000000000 --- a/test/files/neg/t5504.check +++ /dev/null @@ -1,4 +0,0 @@ -error: type _$1 is defined twice - conflicting symbols both originated in file 't5504/s_1.scala' - Note: this may be due to a bug in the compiler involving wildcards in package objects -one error found diff --git a/test/files/neg/t5504/s_1.scala b/test/files/neg/t5504/s_1.scala deleted file mode 100644 index 35cb2c8bae..0000000000 --- a/test/files/neg/t5504/s_1.scala +++ /dev/null @@ -1,4 +0,0 @@ -// a.scala -package object foo { - val m: List[_] = Nil -} diff --git a/test/files/neg/t5504/s_2.scala b/test/files/neg/t5504/s_2.scala deleted file mode 100644 index 03eecf6e19..0000000000 --- a/test/files/neg/t5504/s_2.scala +++ /dev/null @@ -1,8 +0,0 @@ -// b.scala -package foo - -object Test { - def main(args: Array[String]): Unit = { - println(foo.m) - } -} diff --git a/test/files/pos/t5504/s_1.scala b/test/files/pos/t5504/s_1.scala new file mode 100644 index 0000000000..35cb2c8bae --- /dev/null +++ b/test/files/pos/t5504/s_1.scala @@ -0,0 +1,4 @@ +// a.scala +package object foo { + val m: List[_] = Nil +} diff --git a/test/files/pos/t5504/s_2.scala b/test/files/pos/t5504/s_2.scala new file mode 100644 index 0000000000..03eecf6e19 --- /dev/null +++ b/test/files/pos/t5504/s_2.scala @@ -0,0 +1,8 @@ +// b.scala +package foo + +object Test { + def main(args: Array[String]): Unit = { + println(foo.m) + } +} -- cgit v1.2.3