8000 Do not cache overall class · scala-js/scala-js@0885927 · GitHub
[go: up one dir, main page]

Skip to content

Commit 0885927

Browse files
committed
Do not cache overall class
This reduces some memory overhead for negligible performance cost. Residual (post link memory) benchmarks for the test suite: Baseline: 1.13 GB, new 1.01 GB
1 parent d2b7322 commit 0885927

File tree

2 files changed

+34
-29
lines changed

2 files changed

+34
-29
lines changed

linker/shared/src/main/scala/org/scalajs/linker/backend/emitter/Emitter.scala

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -620,9 +620,9 @@ final class Emitter[E >: Null <: js.Tree](
620620
}
621621

622622
val fullClass = extractChanged {
623-
val fullClassCache = classCache.getFullClassCache()
623+
val fullClassChangeTracker = classCache.getFullClassChangeTracker()
624624

625-
fullClassCache.getOrElseUpdate(linkedClass.version, ctorWithGlobals,
625+
fullClassChangeTracker.trackChanged(linkedClass.version, ctorWithGlobals,
626626
memberMethodsWithGlobals, exportedMembersWithGlobals, {
627627
for {
628628
ctor <- ctorWithGlobals
@@ -637,8 +637,8 @@ final class Emitter[E >: Null <: js.Tree](
637637
linkedClass.superClass, // invalidated by class version
638638
storeJSSuperClass, // invalidated by class version
639639
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
640+
membersAsTrees // invalidated directly
641+
)(moduleContext, fullClassChangeTracker, linkedClass.pos) // pos invalidated by class version
642642
} yield {
643643
// Avoid a nested post transform if we just got the original members back.
644644
if (clazz eq allMembers) {
@@ -862,7 +862,7 @@ final class Emitter[E >: Null <: js.Tree](
862862
private[this] val _exportedMembersCache =
863863
mutable.Map.empty[Int, MethodCache[List[E]]]
864864

865-
private[this] var _fullClassCache: Option[FullClassCache] = None
865+
private[this] var _fullClassChangeTracker: Option[FullClassChangeTracker] = None
866866

867867
override def invalidate(): Unit = {
868868
/* Do not invalidate contained methods, as they have their own
@@ -878,7 +878,7 @@ final class Emitter[E >: Null <: js.Tree](
878878
_methodCaches.foreach(_.valuesIterator.foreach(_.startRun()))
879879
_memberMethodCache.valuesIterator.foreach(_.startRun())
880880
_constructorCache.foreach(_.startRun())
881-
_fullClassCache.foreach(_.startRun())
881+
_fullClassChangeTracker.foreach(_.startRun())
882882
}
883883

884884
def getCache(version: Version): (DesugaredClassCache[List[E]], Boolean) = {
@@ -917,10 +917,10 @@ final class Emitter[E >: Null <: js.Tree](
917917
def getExportedMemberCache(idx: Int): MethodCache[List[E]] =
918918
_exportedMembersCache.getOrElseUpdate(idx, new MethodCache)
919919

920-
def getFullClassCache(): FullClassCache = {
921-
_fullClassCache.getOrElse {
922-
val cache = new FullClassCache
923-
_fullClassCache = Some(cache)
920+
def getFullClassChangeTracker(): FullClassChangeTracker = {
921+
_fullClassChangeTracker.getOrElse {
922+
val cache = new FullClassChangeTracker
923+
_fullClassChangeTracker = Some(cache)
924924
cache
925925
}
926926
}
@@ -934,8 +934,8 @@ final class Emitter[E >: Null <: js.Tree](
934934

935935
_exportedMembersCache.filterInPlace((_, c) => c.cleanAfterRun())
936936

937-
if (_fullClassCache.exists(!_.cleanAfterRun()))
938-
_fullClassCache = None
937+
if (_fullClassChangeTracker.exists(!_.cleanAfterRun()))
938+
_fullClassChangeTracker = None
939939

940940
if (!_cacheUsed)
941941
invalidate()
@@ -980,26 +980,24 @@ final class Emitter[E >: Null <: js.Tree](
980980
}
981981
}
982982

983-
private class FullClassCache extends knowledgeGuardian.KnowledgeAccessor {
984-
private[this] var _tree: WithGlobals[List[E]] = null
983+
private class FullClassChangeTracker extends knowledgeGuardian.KnowledgeAccessor {
985984
private[this] var 8000 _lastVersion: Version = Version.Unversioned
986985
private[this] var _lastCtor: WithGlobals[List[E]] = null
987986
private[this] var _lastMemberMethods: List[WithGlobals[List[E]]] = null
988987
private[this] var _lastExportedMembers: List[WithGlobals[List[E]]] = null
989-
private[this] var _cacheUsed = false
988+
private[this] var _trackerUsed = false
990989

991990
override def invalidate(): Unit = {
992991
super.invalidate()
993-
_tree = null
994992
_lastVersion = Version.Unversioned
995993
_lastCtor = null
996994
_lastMemberMethods = null
997995
_lastExportedMembers = null
998996
}
999997

1000-
def startRun(): Unit = _cacheUsed = false
998+
def startRun(): Unit = _trackerUsed = false
1001999

1002-
def getOrElseUpdate(version: Version, ctor: WithGlobals[List[E]],
1000+
def trackChanged(version: Version, ctor: WithGlobals[List[E]],
10031001
memberMethods: List[WithGlobals[List[E]]], exportedMembers: List[WithGlobals[List[E]]],
10041002
compute: => WithGlobals[List[E]]): (WithGlobals[List[E]], Boolean) = {
10051003

@@ -1011,28 +1009,32 @@ final class Emitter[E >: Null <: js.Tree](
10111009
}
10121010
}
10131011

1014-
_cacheUsed = true
1012+
_trackerUsed = true
10151013

1016-
if (_tree == null || !version.sameVersion(_lastVersion) || (_lastCtor ne ctor) ||
1014+
if (!version.sameVersion(_lastVersion) || (_lastCtor ne ctor) ||
10171015
!allSame(_lastMemberMethods, memberMethods) ||
10181016
!allSame(_lastExportedMembers, exportedMembers)) {
1017+
// Input has changed or we were invalidated.
1018+
// Clean knowledge tracking and re-track dependencies.
10191019
invalidate()
1020-
_tree = compute
10211020
_lastVersion = version
10221021
_lastCtor = ctor
10231022
_lastMemberMethods = memberMethods
10241023
_lastExportedMembers = exportedMembers
1025-
(_tree, true)
1024+
1025+
(compute, true)
10261026
} else {
1027-
(_tree, false)
1027+
// Input has not changed and we were not invalidated.
1028+
// --> nothing has changed (we recompute to save memory).
1029+
(compute, false)
10281030
}
10291031
}
10301032

10311033
def cleanAfterRun(): Boolean = {
1032-
if (!_cacheUsed)
1034+
if (!_trackerUsed)
10331035
invalidate()
10341036

1035-
_cacheUsed
1037+
_trackerUsed
10361038
}
10371039
}
10381040

linker/shared/src/test/scala/org/scalajs/linker/EmitterTest.scala

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -208,18 +208,21 @@ class EmitterTest {
208208

209209
// Post transforms
210210

211-
val Seq(postTransforms1, _, _) =
211+
val Seq(postTransforms1, nestedPostTransforms1, _) =
212212
lines1.assertContainsMatch(EmitterPostTransformStatsMessage).map(_.toInt)
213213

214-
val Seq(postTransforms2, _, _) =
214+
val Seq(postTransforms2, nestedPostTransforms2, _) =
215215
lines2.assertContainsMatch(EmitterPostTransformStatsMessage).map(_.toInt)
216216

217-
// At the time of writing this test, postTransformsTotal1 reports 216
217+
// At the time of writing this test, postTransforms1 reports 216
218218
assertTrue(
219219
s"Not enough post transforms (got $postTransforms1); extraction must have gone wrong",
220220
postTransforms1 > 200)
221221

222-
assertEquals("Second run must not have any post transforms", 0, postTransforms2)
222+
assertEquals("Second run must only have nested post transforms",
223+
nestedPostTransforms2, postTransforms2)
224+
assertEquals("Both runs must have the same number of nested post transforms",
225+
nestedPostTransforms1, nestedPostTransforms2)
223226
}
224227
}
225228
}

0 commit comments

Comments
 (0)
0