-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Make source a field in Positioned nodes #9900
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
2671fe3
Make source a field in Positioned nodes
odersky 5b39279
Don't rely on tree ids when pickling
odersky 785fea9
Drop uniqueId field in Positioned
odersky bd2b184
New data structure: IntMap
odersky 2dcc362
Use IntMap in TreePickler
odersky 2249961
Drop SparseIntArray
odersky 4d044c6
Increase initial capacity of TreeAddr map
odersky 2c441d7
Mangle hashcode bits
odersky a79d848
Update compiler/src/dotty/tools/dotc/ast/Positioned.scala
odersky 0bb3107
Update compiler/src/dotty/tools/dotc/ast/Positioned.scala
odersky File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package dotty.tools.dotc.util | ||
|
||
/** A dense map from some `Key` type to `Int. Dense means: All keys and values | ||
* are stored in arrays from 0 up to the size of the map. Keys and values | ||
* can be obtained by index using `key(index)` and `value(index)`. Values | ||
* can also be stored using `setValue(index, value)`. | ||
* | ||
* ome privileged protected access to its internals | ||
* @param initialCapacity Indicates the initial number of slots in the hash table. | ||
* The actual number of slots is always a power of 2, so the | ||
* initial size of the table will be the smallest power of two | ||
* that is equal or greater than the given `initialCapacity`. | ||
* Minimum value is 4. | ||
* @param capacityMultiple The minimum multiple of capacity relative to used elements. | ||
* The hash table will be re-sized once the number of elements | ||
* multiplied by capacityMultiple exceeds the current size of the hash table. | ||
* However, a table of size up to DenseLimit will be re-sized only | ||
* once the number of elements reaches the table's size. | ||
*/ | ||
final class IntMap[Key](initialCapacity: Int = 8, capacityMultiple: Int = 2) | ||
extends PerfectHashing[Key](initialCapacity, capacityMultiple): | ||
private var values: Array[Int] = _ | ||
nicolasstucki marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
def default: Int = -1 | ||
|
||
protected override def allocate(capacity: Int) = | ||
super.allocate(capacity) | ||
values = new Array[Int](capacity) | ||
|
||
/** The value associated with key `k`, or else `default`. */ | ||
def apply(k: Key): Int = | ||
val idx = index(k) | ||
if idx < 0 then default else values(idx) | ||
|
||
/** Associate key `k` with value `v` */ | ||
def update(k: Key, v: Int): Unit = | ||
val idx = add(k) // don't merge the two statements, `add` might change `values`. | ||
values(idx) = v | ||
|
||
protected override def growTable() = | ||
val oldValues = values | ||
super.growTable() | ||
Array.copy(oldValues, 0, values, 0, oldValues.length) | ||
|
||
def valuesIterator = values.iterator.take(size) | ||
|
||
def iterator: Iterator[(Key, Int)] = keysIterator.zip(valuesIterator) | ||
|
||
/** The value stored at index `i` */ | ||
def value(i: Int) = values(i) | ||
|
||
/** Change the value stored at index `i` to `v` */ | ||
def setValue(i: Int, v: Int) = values(i) = v | ||
|
||
override def toString = | ||
iterator.map((k, v) => s"$k -> $v").mkString("IntMap(", ", ", ")") | ||
end IntMap |
136 changes: 136 additions & 0 deletions
136
compiler/src/dotty/tools/dotc/util/PerfectHashing.scala
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
package dotty.tools.dotc.util | ||
|
||
object PerfectHashing: | ||
|
||
/** The number of elements up to which dense packing is used. | ||
* If the number of elements reaches `DenseLimit` a hash table is used instead | ||
*/ | ||
inline val DenseLimit = 16 | ||
|
||
/** A map that maps keys to unique integers in a dense interval starting at 0. | ||
* @param initialCapacity Indicates the initial number of slots in the hash table. | ||
* The actual number of slots is always a power of 2, so the | ||
* initial size of the table will be the smallest power of two | ||
* that is equal or greater than the given `initialCapacity`. | ||
* Minimum value is 4. | ||
* @param capacityMultiple The minimum multiple of capacity relative to used elements. | ||
* The hash table will be re-sized once the number of elements | ||
* multiplied by capacityMultiple exceeds the current size of the hash table. | ||
* However, a table of size up to DenseLimit will be re-sized only | ||
* once the number of elements reaches the table's size. | ||
*/ | ||
class PerfectHashing[Key](initialCapacity: Int = 8, capacityMultiple: Int = 2): | ||
import PerfectHashing.DenseLimit | ||
|
||
private var used: Int = _ | ||
private var table: Array[Int] = _ | ||
private var keys: Array[AnyRef] = _ | ||
|
||
clear() | ||
|
||
protected def allocate(capacity: Int) = | ||
keys = new Array[AnyRef](capacity) | ||
if !isDense then | ||
table = new Array[Int](capacity * roundToPower(capacityMultiple)) | ||
|
||
private def roundToPower(n: Int) = | ||
if Integer.bitCount(n) == 1 then n | ||
else 1 << (32 - Integer.numberOfLeadingZeros(n)) | ||
|
||
/** Remove keys from this map and set back to initial configuration */ | ||
def clear(): Unit = | ||
used = 0 | ||
allocate(roundToPower(initialCapacity max 4)) | ||
|
||
/** The number of keys */ | ||
final def size: Int = used | ||
|
||
/** The number of keys that can be stored without growing the tables */ | ||
final def capacity: Int = keys.length | ||
|
||
private final def isDense = capacity <= DenseLimit | ||
|
||
/** Hashcode, by default a post-processed versoon of `k.hashCode`, | ||
* can be overridden | ||
*/ | ||
protected def hash(k: Key): Int = | ||
val h = k.hashCode | ||
// Part of the MurmurHash3 32 bit finalizer | ||
val i = (h ^ (h >>> 16)) * 0x85EBCA6B | ||
val j = (i ^ (i >>> 13)) & 0x7FFFFFFF | ||
if (j==0) 0x41081989 else j | ||
|
||
/** Equality test, by default `equals`, can be overridden */ | ||
protected def isEqual(x: Key, y: Key): Boolean = x.equals(y) | ||
|
||
private def matches(entry: Int, k: Key) = isEqual(key(entry), k) | ||
|
||
private def tableIndex(x: Int): Int = x & (table.length - 1) | ||
private def firstIndex(k: Key) = tableIndex(hash(k)) | ||
private def nextIndex(idx: Int) = tableIndex(idx + 1) | ||
|
||
/** The key at index `idx` */ | ||
def key(idx: Int) = keys(idx).asInstanceOf[Key] | ||
private def setKey(e: Int, k: Key) = keys(e) = k.asInstanceOf[AnyRef] | ||
|
||
private def entry(idx: Int): Int = table(idx) - 1 | ||
private def setEntry(idx: Int, entry: Int) = table(idx) = entry + 1 | ||
|
||
/** An index `idx` such that `key(idx) == k`, or -1 if no such index exists */ | ||
def index(k: Key): Int = | ||
if isDense then | ||
var e = 0 | ||
while e < used do | ||
if matches(e, k) then return e | ||
e += 1 | ||
-1 | ||
else | ||
var idx = firstIndex(k) | ||
var e = entry(idx) | ||
while e >= 0 && !matches(e, k) do | ||
idx = nextIndex(idx) | ||
e = entry(idx) | ||
e | ||
|
||
/** An index `idx` such that key(idx) == k. | ||
* If no such index exists, create an entry with an index one | ||
* larger than the previous one. | ||
*/ | ||
def add(k: Key): Int = | ||
if isDense then | ||
var e = 0 | ||
while e < used do | ||
if matches(e, k) then return e | ||
e += 1 | ||
else | ||
var idx = firstIndex(k) | ||
var e = entry(idx) | ||
while e >= 0 do | ||
if matches(e, k) then return e | ||
idx = nextIndex(idx) | ||
e = entry(idx) | ||
setEntry(idx, used) | ||
end if | ||
setKey(used, k) | ||
used = used + 1 | ||
if used == capacity then growTable() | ||
used - 1 | ||
|
||
private def rehash(): Unit = | ||
var e = 0 | ||
while e < used do | ||
var idx = firstIndex(key(e)) | ||
while entry(idx) >= 0 do idx = nextIndex(idx) | ||
setEntry(idx, e) | ||
e += 1 | ||
|
||
/** Grow backing arrays */ | ||
protected def growTable(): Unit = | ||
val oldKeys = keys | ||
allocate(capacity * 2) | ||
Array.copy(oldKeys, 0, keys, 0, oldKeys.length) | ||
if !isDense then rehash() | ||
|
||
def keysIterator: Iterator[Key] = | ||
keys.iterator.take(used).asInstanceOf[Iterator[Key]] | ||
end PerfectHashing |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.