diff options
Diffstat (limited to 'src/dotty')
4 files changed, 128 insertions, 74 deletions
diff --git a/src/dotty/tools/dotc/core/pickling/PickleFormat.scala b/src/dotty/tools/dotc/core/pickling/PickleFormat.scala index 10420e723..e4bd95af2 100644 --- a/src/dotty/tools/dotc/core/pickling/PickleFormat.scala +++ b/src/dotty/tools/dotc/core/pickling/PickleFormat.scala @@ -14,7 +14,9 @@ can be dropped without changing the grammar. Micro-syntax: LongNat = Digit* StopDigit // big endian, value fits in a Long without overflow + LongInt = LongNat // big endian 2's complement, value fits in a Long without overflow Nat = LongNat // value fits in an Int without overflow + Int = LongInt // value fits in an Int without overflow Digit = 0 | ... | 127 StopDigit = 128 | ... | 255 // value = digit - 128 @@ -103,23 +105,17 @@ Standard-Section: "ASTs" Tree* Constant = UNITconst FALSEconst TRUEconst - BYTEconst Nat - BYTEneg NegNat - SHORTconst Nat - SHORTneg NegNat + BYTEconst Int + SHORTconst Int CHARconst Nat - INTconst Nat - INTneg NegNat - LONGconst LongNat - LONGneg NegLongNat - FLOATconst LongNat - DOUBLEconst LongNat + INTconst Int + LONGconst LongInt + FLOATconst Int + DOUBLEconst LongInt STRINGconst NameRef NULLconst CLASSconst Length Type ENUMconst Length Path - NegNat = Nat // negValue = -natValue - 1 - NegLongNat = LongNat // negValue = -natValue - 1 Type = Path TYPEREFdirect sym_ASTRef @@ -186,8 +182,9 @@ Note: Tree tags are grouped into 4 categories that determine what follows, and t Standard Section: "Positions" startPos_Index endPos_Index Index = Length Assoc* - Assoc = Delta ASTRef // largest tree starting/ending at offset - Delta = Nat // # chars from last offset or start of file + Assoc = offset_Delta addr_Delta // largest tree starting/ending at offset + Delta = Int // difference between consecutive offsets / tree addresses, + // First offset/address is always assumed to be 0 **************************************************************************************/ @@ -195,7 +192,7 @@ object PickleFormat { final val header = "5CA1AB1F" final val MajorVersion = 0 - final val MinorVersion = 3 + final val MinorVersion = 4 // Name tags @@ -211,38 +208,38 @@ object PickleFormat { final val EMPTYTREE = 0 final val NOTYPE = 1 - final val UNITconst = 3 - final val FALSEconst = 4 - final val TRUEconst = 5 - final val NULLconst = 6 - final val PRIVATE = 7 - final val INTERNAL = 8 - final val PROTECTED = 9 - final val ABSTRACT = 10 - final val FINAL = 11 - final val SEALED = 12 - final val CASE = 13 - final val IMPLICIT = 14 - final val LAZY = 15 - final val OVERRIDE = 16 - final val INLINE = 17 - final val ABSOVERRIDE = 18 - final val STATIC = 19 - final val MODULE = 20 - final val LOCAL = 21 - final val SYNTHETIC = 22 - final val ARTIFACT = 23 - final val MUTABLE = 24 - final val LABEL = 25 - final val FIELDaccessor = 26 - final val PARAMaccessor = 27 - final val CASEaccessor = 28 - final val COVARIANT = 29 - final val CONTRAVARIANT = 30 - final val SCALA2X = 31 - final val DEFAULTparameterized = 32 - final val DEFAULTinit = 33 - final val INSUPERCALL = 34 + final val UNITconst = 2 + final val FALSEconst = 3 + final val TRUEconst = 4 + final val NULLconst = 5 + final val PRIVATE = 6 + final val INTERNAL = 7 + final val PROTECTED = 8 + final val ABSTRACT = 9 + final val FINAL = 10 + final val SEALED = 11 + final val CASE = 12 + final val IMPLICIT = 13 + final val LAZY = 14 + final val OVERRIDE = 15 + final val INLINE = 16 + final val ABSOVERRIDE = 17 + final val STATIC = 18 + final val MODULE = 19 + final val LOCAL = 20 + final val SYNTHETIC = 21 + final val ARTIFACT = 22 + final val MUTABLE = 23 + final val LABEL = 24 + final val FIELDaccessor = 25 + final val PARAMaccessor = 26 + final val CASEaccessor = 27 + final val COVARIANT = 28 + final val CONTRAVARIANT = 29 + final val SCALA2X = 30 + final val DEFAULTparameterized = 31 + final val DEFAULTinit = 32 + final val INSUPERCALL = 33 final val SHARED = 64 final val TERMREFdirect = 65 @@ -251,17 +248,13 @@ object PickleFormat { final val TYPEREFstatic = 68 final val SKOLEMtype = 69 final val BYTEconst = 70 - final val BYTEneg = 71 - final val SHORTconst = 72 - final val SHORTneg = 73 - final val CHARconst = 74 - final val INTconst = 75 - final val INTneg = 76 - final val LONGconst = 77 - final val LONGneg = 78 - final val FLOATconst = 79 - final val DOUBLEconst = 80 - final val STRINGconst = 81 + final val SHORTconst = 71 + final val CHARconst = 72 + final val INTconst = 73 + final val LONGconst = 74 + final val FLOATconst = 75 + final val DOUBLEconst = 76 + final val STRINGconst = 77 final val IDENT = 100 final val SELECT = 101 @@ -381,14 +374,10 @@ object PickleFormat { case TYPEREFstatic => "TYPEREFstatic" case SKOLEMtype => "SKOLEMtype" case BYTEconst => "BYTEconst" - case BYTEneg => "BYTEneg" case SHORTconst => "SHORTconst" - case SHORTneg => "SHORTneg" case CHARconst => "CHARconst" case INTconst => "INTconst" - case INTneg => "INTneg" case LONGconst => "LONGconst" - case LONGneg => "LONGneg" case FLOATconst => "FLOATconst" case DOUBLEconst => "DOUBLEconst" case STRINGconst => "STRINGconst" diff --git a/src/dotty/tools/dotc/core/pickling/TastyBuffer.scala b/src/dotty/tools/dotc/core/pickling/TastyBuffer.scala index 1c0f6e24f..61dce9efb 100644 --- a/src/dotty/tools/dotc/core/pickling/TastyBuffer.scala +++ b/src/dotty/tools/dotc/core/pickling/TastyBuffer.scala @@ -60,6 +60,12 @@ class TastyBuffer(initialSize: Int) { def writeNat(x: Int): Unit = writeLongNat(x.toLong & 0x00000000FFFFFFFFL) + /** Write a natural number in 2's complement big endian format, base 128. + * All but the last digits have bit 0x80 set. + */ + def writeInt(x: Int): Unit = + writeLongInt(x) + /** * Like writeNat, but for longs. Note that the * binary representation of LongNat is identical to Nat @@ -67,15 +73,38 @@ class TastyBuffer(initialSize: Int) { * Int.MAX_VALUE. */ def writeLongNat(x: Long): Unit = { - def writeNatPrefix(x: Long): Unit = { + def writePrefix(x: Long): Unit = { val y = x >>> 7 - if (y != 0L) writeNatPrefix(y) + if (y != 0L) writePrefix(y) writeByte((x & 0x7f).toInt) } val y = x >>> 7 - if (y != 0L) writeNatPrefix(y) + if (y != 0L) writePrefix(y) writeByte(((x & 0x7f) | 0x80).toInt) } + + /** Like writeInt, but for longs */ + def writeLongInt(x: Long): Unit = { + def writePrefix(x: Long): Unit = { + val y = x >> 7 + if (y != 0L - ((x >> 6) & 1)) writePrefix(y) + writeByte((x & 0x7f).toInt) + } + val y = x >> 7 + if (y != 0L - ((x >> 6) & 1)) writePrefix(y) + writeByte(((x & 0x7f) | 0x80).toInt) + } + + /** Write an uncompressed Long stored in 8 bytes in big endian format */ + def writeUncompressedLong(x: Long): Unit = { + var y = x + val bytes = new Array[Byte](8) + for (i <- 7 to 0 by -1) { + bytes(i) = (y & 0xff).toByte + y = y >>> 8 + } + writeBytes(bytes, 8) + } // -- Address handling -------------------------------------------- @@ -140,6 +169,9 @@ class TastyBuffer(initialSize: Int) { /** Fill reserved space at address `at` with address `target` */ def fillAddr(at: Addr, target: Addr) = putNat(at, target.index, AddrWidth) + + /** Write address without leading zeroes */ + def writeAddr(addr: Addr): Unit = writeNat(addr.index) // -- Finalization -------------------------------------------- diff --git a/src/dotty/tools/dotc/core/pickling/TastyReader.scala b/src/dotty/tools/dotc/core/pickling/TastyReader.scala index 4e1acf9a9..1b3c82f79 100644 --- a/src/dotty/tools/dotc/core/pickling/TastyReader.scala +++ b/src/dotty/tools/dotc/core/pickling/TastyReader.scala @@ -65,6 +65,11 @@ class TastyReader(val bytes: Array[Byte], start: Int, end: Int, val base: Int = * All but the last digits have bit 0x80 set. */ def readNat(): Int = readLongNat.toInt + + /** Read an integer number in 2's complement big endian format, base 128. + * All but the last digits have bit 0x80 set. + */ + def readInt(): Int = readLongInt.toInt /** Read a natural number fitting in a Long in big endian format, base 128. * All but the last digits have bit 0x80 set. @@ -79,7 +84,28 @@ class TastyReader(val bytes: Array[Byte], start: Int, end: Int, val base: Int = } while ((b & 0x80) == 0) x } - + + /** Read a long integer number in 2's complement big endian format, base 128. */ + def readLongInt(): Long = { + var b = bytes(bp) + var x = (b << 1).toByte >> 1 // sign extend with bit 6. + bp += 1 + while ((b & 0x80) == 0) { + b = bytes(bp) + x = (x << 7) | (b & 0x7f) + bp += 1 + } + x + } + + /** Read an uncompressed Long stored in 8 bytes in big endian format */ + def readUncompressedLong(): Long = { + var x = 0 + for (i <- 0 to 7) + x = (x << 8) | (readByte() & 0xff) + x + } + /** Read a natural number and return as a NameRef */ def readNameRef() = NameRef(readNat()) @@ -103,6 +129,10 @@ class TastyReader(val bytes: Array[Byte], start: Int, end: Int, val base: Int = buf.toList } + /** If before given `end` address, the result of `op`, otherwise `default` */ + def ifBefore[T](end: Addr)(op: => T, default: T): T = + if (bp < index(end)) op else default + /** Perform `op` while cindition `cond` holds and collect results in a list. */ def collectWhile[T](cond: => Boolean)(op: => T): List[T] = { val buf = new mutable.ListBuffer[T] diff --git a/src/dotty/tools/dotc/core/pickling/TreePickler.scala b/src/dotty/tools/dotc/core/pickling/TreePickler.scala index 3284b1a30..cc81ae7ae 100644 --- a/src/dotty/tools/dotc/core/pickling/TreePickler.scala +++ b/src/dotty/tools/dotc/core/pickling/TreePickler.scala @@ -77,22 +77,26 @@ class TreePickler(pickler: TastyPickler, picklePositions: Boolean) { case BooleanTag => writeByte(if (c.booleanValue) TRUEconst else FALSEconst) case ByteTag => - pickleNum(BYTEconst, BYTEneg) + writeByte(BYTEconst) + writeInt(c.byteValue) case ShortTag => - pickleNum(SHORTconst, SHORTneg) + writeByte(SHORTconst) + writeInt(c.shortValue) case CharTag => writeByte(CHARconst) writeNat(c.charValue) case IntTag => - pickleNum(INTconst, INTneg) + writeByte(INTconst) + writeInt(c.intValue) case LongTag => - pickleNum(LONGconst, LONGneg) + writeByte(LONGconst) + writeLongInt(c.longValue) case FloatTag => writeByte(FLOATconst) - writeNat(java.lang.Float.floatToRawIntBits(c.floatValue)) + writeInt(java.lang.Float.floatToRawIntBits(c.floatValue)) case DoubleTag => writeByte(DOUBLEconst) - writeLongNat(java.lang.Double.doubleToRawLongBits(c.doubleValue)) + writeLongInt(java.lang.Double.doubleToRawLongBits(c.doubleValue)) case StringTag => writeByte(STRINGconst) writeNat(nameIndex(c.stringValue).index) @@ -111,8 +115,7 @@ class TreePickler(pickler: TastyPickler, picklePositions: Boolean) { val tpe = tpe0.stripTypeVar val prev = pickledTypes.get(tpe) if (prev == null) { - val addr = currentAddr - pickledTypes.put(tpe, addr) + pickledTypes.put(tpe, currentAddr) pickleNewType(tpe, richTypes) } else { |