1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
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")
}
}
|