Skip to content
Merged
Changes from 1 commit
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
857cc74
Update tests
EnzeXing Aug 25, 2021
ef43eb5
Add worklist and refactor definition for ThisRef
liufengyun Sep 4, 2021
5d1fe86
Rename Addr to Ref
liufengyun Sep 4, 2021
7279f73
Refactor: make state explicit
liufengyun Sep 5, 2021
20ff7ca
Add constructor to Warm
liufengyun Sep 5, 2021
f5651b5
Revert ThisRef to previous version
liufengyun Sep 5, 2021
6763285
Refactor constructor call
liufengyun Sep 5, 2021
ab09fd2
Make cache part of state
liufengyun Sep 5, 2021
98f9f7e
Handle cache in work list
liufengyun Sep 5, 2021
fb0c347
Don't iterate if errors found
liufengyun Sep 5, 2021
69e314e
Revert heap changes if cache has changed
liufengyun Sep 5, 2021
db11295
Restore cacheResult option for eval
liufengyun Sep 5, 2021
111ac87
Handle callConstructor
liufengyun Sep 6, 2021
29bdb5d
Reset Cache.changed after each iteration
liufengyun Sep 6, 2021
0b1b21f
Tweak log printing of errors
liufengyun Sep 6, 2021
c5daf1d
Fix context for init check
liufengyun Sep 6, 2021
4a71470
Introduce global cache which holds fixed point value
liufengyun Sep 6, 2021
375e0e5
Update tests
liufengyun Sep 7, 2021
6188e8e
Avoid asInstanceOf in logging
liufengyun Sep 7, 2021
5bdd898
Refactor cache
liufengyun Sep 8, 2021
9ea3624
Cache default value in the input cache
liufengyun Sep 8, 2021
d0e71a2
Rename global cache to stable cache
liufengyun Sep 8, 2021
fe3930d
Better encapsulate Cache.assume
liufengyun Sep 8, 2021
5bd83ae
Rename in/out to last/current
liufengyun Sep 8, 2021
2589824
Mark arguments as constructor only
liufengyun Sep 8, 2021
2849052
Add note for tempting but unsound optimization
liufengyun Sep 8, 2021
8a4fe78
Commit cache to stable on error
liufengyun Sep 8, 2021
5b00b1f
Make sure the object of a reference assumption value exists
liufengyun Sep 8, 2021
04aa72b
Add back arguments to ThisRef
liufengyun Sep 8, 2021
ad503fc
Populate parameters of Warm objects by reusing init
liufengyun Sep 8, 2021
fb3b6ca
Make sure the class parameters and outers of warm objects are populated
liufengyun Sep 8, 2021
bc98ce8
Use correct trace
liufengyun Sep 8, 2021
b27d58b
Populate class parameters for warm objects in a heap prepare step
liufengyun Sep 8, 2021
99df102
Try to check warm values immediately
liufengyun Sep 9, 2021
4163fd3
Fix crash: make sure object fresh before calling init
liufengyun Sep 9, 2021
683d537
Be more sensitive for values Warm(outer = ThisRef)
liufengyun Sep 9, 2021
ccbb355
Fix non-determinism in test
liufengyun Sep 9, 2021
fc76549
Make isPopulatingParams a flag in Warm
liufengyun Sep 15, 2021
191877a
Make heap as part of cache
liufengyun Sep 16, 2021
f5540f5
Update test
liufengyun Sep 20, 2021
a15a06c
Add more debugging information
liufengyun Sep 20, 2021
46793f1
Lazily populate warm objects
liufengyun Sep 20, 2021
8bbe384
Add comment
liufengyun Sep 20, 2021
dab8181
Fix non-termination
liufengyun Sep 21, 2021
1ab5316
Fix pickling test
liufengyun Sep 22, 2021
1e802c9
Remove unused parameters of ThisRef
liufengyun Sep 22, 2021
8088217
Fix compilation of scodec
liufengyun Sep 22, 2021
6566756
Apply suggestions from code review
liufengyun Oct 7, 2021
15a51d7
Address review comments
liufengyun Oct 7, 2021
7ee58a3
Address review: Add comment to populateParams
liufengyun Oct 7, 2021
e905cd5
Fix compilation
liufengyun Oct 7, 2021
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
Prev Previous commit
Next Next commit
Introduce global cache which holds fixed point value
  • Loading branch information
liufengyun committed Oct 7, 2021
commit 4a71470e0177545687b0f15f51470e78cd26a9df
58 changes: 46 additions & 12 deletions compiler/src/dotty/tools/dotc/transform/init/Semantic.scala
Original file line number Diff line number Diff line change
Expand Up @@ -272,12 +272,46 @@ object Semantic {
*/

object Cache {
opaque type CacheIn = mutable.Map[Value, EqHashMap[Tree, Value]]
opaque type CacheOut = mutable.Map[Value, EqHashMap[Tree, Value]]
opaque type CacheStore = mutable.Map[Value, EqHashMap[Tree, Value]]

class Cache(val in: CacheIn, var out: CacheOut) {
class Cache {
private val in: CacheStore = mutable.Map.empty
private var out: CacheStore = mutable.Map.empty
private val global: CacheStore = mutable.Map.empty
var changed: Boolean = false

def contains(value: Value, expr: Tree) =
out.contains(value, expr) || global.contains(value, expr)

def apply(value: Value, expr: Tree) =
if out.contains(value, expr) then out(value)(expr)
else global(value)(expr)

def assume(value: Value, expr: Tree) =
val assumeValue = if (in.contains(value, expr)) in.get(value, expr) else Hot
out.put(value, expr, assumeValue)
assumeValue

def update(value: Value, expr: Tree, result: Value) =
out.put(value, expr, result)

def remove(value: Value, expr: Tree) =
out.remove(value, expr)

/** Commit out cache to global cache.
*
* Precondition: the out cache reaches fixed point.
*/
def commit() = {
out.foreach { (v, m) =>
m.iterator.foreach { (e, res) =>
global.put(v, e, res)
}
}

out = mutable.Map.empty
}

/** Copy out to in and reset out to empty */
def update() = {
out.foreach { (v, m) =>
Expand All @@ -290,10 +324,10 @@ object Semantic {
}
}

val empty: Cache = new Cache(mutable.Map.empty, mutable.Map.empty)
val empty: Cache = new Cache()

extension (cache: CacheIn | CacheOut)
def contains(value: Value, expr: Tree): Boolean = cache.contains(value) && cache(value).contains(expr)
extension (cache: CacheStore)
def contains(value: Value, expr: Tree) = cache.contains(value) && cache(value).contains(expr)
def get(value: Value, expr: Tree): Value = cache(value)(expr)
def remove(value: Value, expr: Tree) = cache(value).remove(expr)
def put(value: Value, expr: Tree, result: Value): Unit = {
Expand Down Expand Up @@ -793,6 +827,7 @@ object Semantic {

if res.errors.nonEmpty || !cache.changed then
pendingTasks = rest
cache.commit()
else
// discard heap changes and copy cache.out to cache.in
cache.update()
Expand All @@ -808,7 +843,7 @@ object Semantic {
*
* This method should only be called from the work list scheduler.
*/
private def doTask(task: Task)(using State, Context): Result = {
private def doTask(task: Task)(using State, Context): Result = log("checking " + task) {
val thisRef = task
val tpl = thisRef.klass.defTree.asInstanceOf[TypeDef].rhs.asInstanceOf[Template]

Expand Down Expand Up @@ -870,17 +905,16 @@ object Semantic {
* This method only handles cache logic and delegates the work to `cases`.
*/
def eval(expr: Tree, thisV: Ref, klass: ClassSymbol, cacheResult: Boolean = false): Contextual[Result] = log("evaluating " + expr.show + ", this = " + thisV.show, printer, (_: Result).show) {
if (cache.out.contains(thisV, expr)) Result(cache.out.get(thisV, expr), Errors.empty)
if (cache.contains(thisV, expr)) Result(cache(thisV, expr), Errors.empty)
else {
val assumeValue = if (cache.in.contains(thisV, expr)) cache.in.get(thisV, expr) else Hot
cache.out.put(thisV, expr, assumeValue)
val assumeValue = cache.assume(thisV, expr)
val res = cases(expr, thisV, klass)
if res.value != assumeValue then
// println("changed: old = " + assumeValue + ", res = " + res.value)
cache.changed = true
cache.out.put(thisV, expr, res.value) // must put in cache for termination
cache.update(thisV, expr, res.value) // must put in cache for termination
else
if !cacheResult then cache.out.remove(thisV, expr)
if !cacheResult then cache.remove(thisV, expr)
res
}
}
Expand Down