aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/pickling/TreeBuffer.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2015-02-08 10:06:43 +0100
committerDmitry Petrashko <dmitry.petrashko@gmail.com>2015-03-18 11:09:43 +0100
commit340dc52a567de022c56acb1533c5772d21405f2a (patch)
treeae5dc41d2de3879d27abffc6413c18b25019e61b /src/dotty/tools/dotc/core/pickling/TreeBuffer.scala
parent61cb51acaedbe603add8c4af9e390a27f8b33f09 (diff)
downloaddotty-340dc52a567de022c56acb1533c5772d21405f2a.tar.gz
dotty-340dc52a567de022c56acb1533c5772d21405f2a.tar.bz2
dotty-340dc52a567de022c56acb1533c5772d21405f2a.zip
First prototype of pickler.
Diffstat (limited to 'src/dotty/tools/dotc/core/pickling/TreeBuffer.scala')
-rw-r--r--src/dotty/tools/dotc/core/pickling/TreeBuffer.scala133
1 files changed, 133 insertions, 0 deletions
diff --git a/src/dotty/tools/dotc/core/pickling/TreeBuffer.scala b/src/dotty/tools/dotc/core/pickling/TreeBuffer.scala
new file mode 100644
index 000000000..5a445124d
--- /dev/null
+++ b/src/dotty/tools/dotc/core/pickling/TreeBuffer.scala
@@ -0,0 +1,133 @@
+package dotty.tools
+package dotc
+package core
+package pickling
+
+import util.Util.{bestFit, dble}
+import TastyBuffer.{Addr, AddrWidth}
+
+class TreeBuffer extends TastyBuffer(1000000) {
+
+ private final val ItemsOverOffsets = 2
+
+ private val initialOffsetSize = bytes.length / (AddrWidth * ItemsOverOffsets)
+ private var offsets = new Array[Int](initialOffsetSize)
+ private var isRelative = new Array[Boolean](initialOffsetSize)
+ private var delta: Array[Int] = _
+ private var numOffsets = 0
+
+ private def offset(i: Int): Addr = new Addr(offsets(i))
+
+ private def keepOffset(relative: Boolean): Unit = {
+ if (numOffsets == offsets.length) {
+ offsets = dble(offsets)
+ isRelative = dble(isRelative)
+ }
+ offsets(numOffsets) = length
+ isRelative(numOffsets) = relative
+ numOffsets += 1
+ }
+
+ def reserveRef(relative: Boolean): Addr = {
+ val addr = currentAddr
+ keepOffset(relative)
+ reserveAddr()
+ addr
+ }
+
+ def writeRef(target: Addr) = {
+ keepOffset(relative = false)
+ writeNat(target.index)
+ }
+
+ def fillRef(at: Addr, target: Addr, relative: Boolean) = {
+ val addr = if (relative) target.relativeTo(at) else target
+ fillAddr(at, addr)
+ }
+
+ def adjusted(x: Addr): Addr = {
+ val idx = bestFit(offsets, x.index - 1)
+ if (idx < 0) x else x - delta(idx)
+ }
+
+ private def computeDeltas() = {
+ delta = new Array[Int](numOffsets)
+ var lastDelta = 0
+ var i = 0
+ while (i < numOffsets) {
+ val off = offset(i)
+ val skippedOff = skipZeroes(off)
+ val skippedCount = skippedOff.index - off.index
+ assert(skippedCount < AddrWidth, s"unset field at position $off")
+ lastDelta += skippedCount
+ delta(i) = lastDelta
+ i += 1
+ }
+ }
+
+ private def adjustedOffset(at: Addr, isRelative: Boolean): Addr = {
+ val original = getAddr(at)
+ if (isRelative) {
+ val start = skipNat(at).index
+ adjusted(original + start) - start
+ } else adjusted(original)
+ }
+
+ private def adjustOffsets(): Unit = {
+ for (i <- 0 until numOffsets) {
+ val off = offset(i)
+ val original = getAddr(off)
+ val corrected = adjustedOffset(off, isRelative(i))
+ fillAddr(off, corrected)
+ }
+ }
+
+ private def adjustDeltas(): Int = {
+ val delta1 = new Array[Int](delta.length)
+ var lastDelta = 0
+ var i = 0
+ while (i < numOffsets) {
+ val corrected = adjustedOffset(offset(i), isRelative(i))
+ lastDelta += AddrWidth - TastyBuffer.natSize(corrected.index)
+ delta1(i) = lastDelta
+ i += 1
+ }
+ val saved =
+ if (numOffsets == 0) 0
+ else delta1(numOffsets - 1) - delta(numOffsets - 1)
+ delta = delta1
+ saved
+ }
+
+ private def compress(): Int = {
+ var lastDelta = 0
+ var start = 0
+ var i = 0
+ var wasted = 0
+ while (i < numOffsets) {
+ val next = offsets(i)
+ Array.copy(bytes, start, bytes, start - lastDelta, next - start)
+ start = next + delta(i) - lastDelta
+ val pastZeroes = skipZeroes(new Addr(next)).index
+ assert(pastZeroes >= start, s"something's wrong: eliminated non-zero")
+ wasted += (pastZeroes - start)
+ lastDelta = delta(i)
+ i += 1
+ }
+ length -= lastDelta
+ wasted
+ }
+
+ override def assemble(): Unit = {
+ val origLength = length
+ computeDeltas()
+ adjustOffsets()
+ if (false) {
+ var saved = 0
+ do saved = adjustDeltas()
+ while (saved > 0 && length / saved < 100)
+ }
+ val wasted = compress()
+ println(s"original length: $origLength, compressed to: $length, wasted: $wasted")
+ }
+}