@@ -619,37 +619,41 @@ final class Emitter[E >: Null <: js.Tree](
619
619
}
620
620
}
621
621
622
- val fullClass = extractChanged {
623
- val fullClassCache = classCache.getFullClassCache()
624
-
625
- fullClassCache.getOrElseUpdate(linkedClass.version, ctorWithGlobals,
626
- memberMethodsWithGlobals, exportedMembersWithGlobals, {
627
- for {
628
- ctor <- ctorWithGlobals
629
- memberMethods <- WithGlobals .flatten(memberMethodsWithGlobals)
630
- exportedMembers <- WithGlobals .flatten(exportedMembersWithGlobals)
631
- allMembers = ctor ::: memberMethods ::: exportedMembers
632
- clazz <- classEmitter.buildClass(
633
- className, // invalidated by overall class cache (part of ancestors)
634
- isJSClass, // invalidated by class version
635
- linkedClass.jsClassCaptures, // invalidated by class version
636
- hasClassInitializer, // invalidated by class version (optimizer cannot remove it)
637
- linkedClass.superClass, // invalidated by class version
638
- storeJSSuperClass, // invalidated by class version
639
- useESClass, // invalidated by class version (depends on kind, config and ancestry only)
640
- allMembers // invalidated directly
641
- )(moduleContext, fullClassCache, linkedClass.pos) // pos invalidated by class version
642
- } yield {
643
- // Avoid a nested post transform if we just got the original members back.
644
- if (clazz eq allMembers) {
645
- statsNestedPostTransformsAvoided += 1
646
- allMembers
647
- } else {
648
- statsNestedPostTransforms += 1
649
- postTransform(clazz, 0 )
650
- }
622
+ val fullClass = {
623
+ val fullClassChangeTracker = classCache.getFullClassChangeTracker()
624
+
625
+ // Put changed state into a val to avoid short circuiting behavior of ||.
626
+ val classChanged = fullClassChangeTracker.trackChanged(
627
+ linkedClass.version, ctorWithGlobals,
628
+ memberMethodsWithGlobals, exportedMembersWithGlobals)
629
+
630
+ changed ||= classChanged
631
+
632
+ for {
633
+ ctor <- ctorWithGlobals
634
+ memberMethods <- WithGlobals .flatten(memberMethodsWithGlobals)
635
+ exportedMembers <- WithGlobals .flatten(exportedMembersWithGlobals)
636
+ allMembers = ctor ::: memberMethods ::: exportedMembers
637
+ clazz <- classEmitter.buildClass(
638
+ className, // invalidated by overall class cache (part of ancestors)
639
+ isJSClass, // invalidated by class version
640
+ linkedClass.jsClassCaptures, // invalidated by class version
641
+ hasClassInitializer, // invalidated by class version (optimizer cannot remove it)
642
+ linkedClass.superClass, // invalidated by class version
643
+ storeJSSuperClass, // invalidated by class version
644
+ useESClass, // invalidated by class version (depends on kind, config and ancestry only)
645
+ allMembers // invalidated directly
646
+ )(moduleContext, fullClassChangeTracker, linkedClass.pos) // pos invalidated by class version
647
+ } yield {
648
+ // Avoid a nested post transform if we just got the original members back.
649
+ if (clazz eq allMembers) {
650
+ statsNestedPostTransformsAvoided += 1
651
+ allMembers
652
+ } else {
653
+ statsNestedPostTransforms += 1
654
+ postTransform(clazz, 0 )
651
655
}
652
- })
656
+ }
653
657
}
654
658
655
659
main ++= extractWithGlobals(fullClass)
@@ -862,7 +866,7 @@ final class Emitter[E >: Null <: js.Tree](
862
866
private [this ] val _exportedMembersCache =
863
867
mutable.Map .empty[Int , MethodCache [List [E ]]]
864
868
865
- private [this ] var _fullClassCache : Option [FullClassCache ] = None
869
+ private [this ] var _fullClassChangeTracker : Option [FullClassChangeTracker ] = None
866
870
867
871
override def invalidate (): Unit = {
868
872
/* Do not invalidate contained methods, as they have their own
@@ -878,7 +882,7 @@ final class Emitter[E >: Null <: js.Tree](
878
882
_methodCaches.foreach(_.valuesIterator.foreach(_.startRun()))
879
883
_memberMethodCache.valuesIterator.foreach(_.startRun())
880
884
_constructorCache.foreach(_.startRun())
881
- _fullClassCache .foreach(_.startRun())
885
+ _fullClassChangeTracker .foreach(_.startRun())
882
886
}
883
887
884
888
def getCache (version : Version ): (DesugaredClassCache [List [E ]], Boolean ) = {
@@ -917,10 +921,10 @@ final class Emitter[E >: Null <: js.Tree](
917
921
def getExportedMemberCache (idx : Int ): MethodCache [List [E ]] =
918
922
_exportedMembersCache.getOrElseUpdate(idx, new MethodCache )
919
923
920
- def getFullClassCache (): FullClassCache = {
921
- _fullClassCache .getOrElse {
922
- val cache = new FullClassCache
923
- _fullClassCache = Some (cache)
924
+ def getFullClassChangeTracker (): FullClassChangeTracker = {
925
+ _fullClassChangeTracker .getOrElse {
926
+ val cache = new FullClassChangeTracker
927
+ _fullClassChangeTracker = Some (cache)
924
928
cache
925
929
}
926
930
}
@@ -934,8 +938,8 @@ final class Emitter[E >: Null <: js.Tree](
934
938
935
939
_exportedMembersCache.filterInPlace((_, c) => c.cleanAfterRun())
936
940
937
- if (_fullClassCache .exists(! _.cleanAfterRun()))
938
- _fullClassCache = None
941
+ if (_fullClassChangeTracker .exists(! _.cleanAfterRun()))
942
+ _fullClassChangeTracker = None
939
943
940
944
if (! _cacheUsed)
941
945
invalidate()
@@ -980,28 +984,26 @@ final class Emitter[E >: Null <: js.Tree](
980
984
}
981
985
}
982
986
983
- private class FullClassCache extends knowledgeGuardian.KnowledgeAccessor {
984
- private [this ] var _tree : WithGlobals [List [E ]] = null
987
+ private class FullClassChangeTracker extends knowledgeGuardian.KnowledgeAccessor {
985
988
private [this ] var _lastVersion : Version = Version .Unversioned
986
989
private [this ] var _lastCtor : WithGlobals [List [E ]] = null
987
990
private [this ] var _lastMemberMethods : List [WithGlobals [List [E ]]] = null
988
991
private [this ] var _lastExportedMembers : List [WithGlobals [List [E ]]] = null
989
- private [this ] var _cacheUsed = false
992
+ private [this ] var _trackerUsed = false
990
993
991
994
override def invalidate (): Unit = {
992
995
super .invalidate()
993
- _tree = null
994
996
_lastVersion = Version .Unversioned
995
997
_lastCtor = null
996
998
_lastMemberMethods = null
997
999
_lastExportedMembers = null
998
1000
}
999
1001
1000
- def startRun (): Unit = _cacheUsed = false
1002
+ def startRun (): Unit = _trackerUsed = false
1001
1003
1002
- def getOrElseUpdate (version : Version , ctor : WithGlobals [List [E ]],
1003
- memberMethods : List [WithGlobals [List [E ]]], exportedMembers : List [ WithGlobals [ List [ E ]]],
1004
- compute : => WithGlobals [List [E ]]): ( WithGlobals [ List [ E ]], Boolean ) = {
1004
+ def trackChanged (version : Version , ctor : WithGlobals [List [E ]],
1005
+ memberMethods : List [WithGlobals [List [E ]]],
1006
+ exportedMembers : List [ WithGlobals [List [E ]]] ): Boolean = {
1005
1007
1006
1008
@ tailrec
1007
1009
def allSame [A <: AnyRef ](xs : List [A ], ys : List [A ]): Boolean = {
@@ -1011,28 +1013,33 @@ final class Emitter[E >: Null <: js.Tree](
1011
1013
}
1012
1014
}
1013
1015
1014
- _cacheUsed = true
1016
+ _trackerUsed = true
1015
1017
1016
- if (_tree == null || ! version.sameVersion(_lastVersion) || (_lastCtor ne ctor) ||
1017
- ! allSame(_lastMemberMethods, memberMethods) ||
1018
- ! allSame(_lastExportedMembers, exportedMembers)) {
1018
+ val changed = {
1019
+ ! version.sameVersion(_lastVersion) ||
1020
+ (_lastCtor ne ctor) ||
1021
+ ! allSame(_lastMemberMethods, memberMethods) ||
1022
+ ! allSame(_lastExportedMembers, exportedMembers)
1023
+ }
1024
+
1025
+ if (changed) {
1026
+ // Input has changed or we were invalidated.
1027
+ // Clean knowledge tracking and re-track dependencies.
1019
1028
invalidate()
1020
- _tree = compute
1021
1029
_lastVersion = version
1022
1030
_lastCtor = ctor
1023
1031
_lastMemberMethods = memberMethods
1024
1032
_lastExportedMembers = exportedMembers
1025
- (_tree, true )
1026
- } else {
1027
- (_tree, false )
1028
1033
}
1034
+
1035
+ changed
1029
1036
}
1030
1037
1031
1038
def cleanAfterRun (): Boolean = {
1032
- if (! _cacheUsed )
1039
+ if (! _trackerUsed )
1033
1040
invalidate()
1034
1041
1035
- _cacheUsed
1042
+ _trackerUsed
1036
1043
}
1037
1044
}
1038
1045
0 commit comments