Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8e47d09

Browse files
committed
Store $c.prototype.$classData as part of $TypeData().initClass().
This removes the largest source of uncompressible and non-removable occurrences of `$classData` identifiers. It does increase the size of the GCC output in the `LibrarySizeTest`, but it does not translate to the `reversi` checksizes, so it is probably a small codebase artifact.
1 parent 391bc5e commit 8e47d09

File tree

5 files changed

+47
-44
lines changed

5 files changed

+47
-44
lines changed

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

+4-11
Original file line numberDiff line numberDiff line change
@@ -830,7 +830,7 @@ private[emitter] final class ClassEmitter(sjsGen: SJSGen) {
830830

831831
def genTypeData(className: ClassName, kind: ClassKind,
832832
superClass: Option[ClassIdent], ancestors: List[ClassName],
833-
jsNativeLoadSpec: Option[JSNativeLoadSpec])(
833+
jsNativeLoadSpec: Option[JSNativeLoadSpec], assignClassData: Boolean)(
834834
implicit moduleContext: ModuleContext,
835835
globalKnowledge: GlobalKnowledge, pos: Position): WithGlobals[List[js.Tree]] = {
836836
import TreeDSL._
@@ -840,9 +840,10 @@ private[emitter] final class ClassEmitter(sjsGen: SJSGen) {
840840
val isJSType =
841841
kind.isJSType
842842

843-
val kindParam = {
843+
val kindOrCtorParam = {
844844
if (isJSType) js.IntLiteral(2)
845845
else if (kind == ClassKind.Interface) js.IntLiteral(1)
846+
else if (assignClassData) globalVar(VarField.c, className)
846847
else js.IntLiteral(0)
847848
}
848849

@@ -911,7 +912,7 @@ private[emitter] final class ClassEmitter(sjsGen: SJSGen) {
911912

912913
isInstanceFunWithGlobals.flatMap { isInstanceFun =>
913914
val allParams = List(
914-
kindParam,
915+
kindOrCtorParam,
915916
js.StringLiteral(RuntimeClassNameMapperImpl.map(
916917
semantics.runtimeClassNameMapper, className.nameString)),
917918
ancestorsRecord
@@ -927,14 +928,6 @@ private[emitter] final class ClassEmitter(sjsGen: SJSGen) {
927928
}
928929
}
929930

930-
def genSetTypeData(className: ClassName)(
931-
implicit moduleContext: ModuleContext,
932-
globalKnowledge: GlobalKnowledge, pos: Position): js.Tree = {
933-
import TreeDSL._
934-
935-
globalVar(VarField.c, className).prototype DOT cpn.classData := globalVar(VarField.d, className)
936-
}
937-
938931
def genModuleAccessor(className: ClassName, isJSClass: Boolean)(
939932
implicit moduleContext: ModuleContext,
940933
globalKnowledge: GlobalKnowledge, pos: Position): WithGlobals[List[js.Tree]] = {

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

+12-6
Original file line numberDiff line numberDiff line change
@@ -1633,8 +1633,11 @@ private[emitter] object CoreJSLib {
16331633
}
16341634

16351635
val initClass = {
1636-
// This is an int, where 1 means isInterface; 2 means isJSType; 0 otherwise
1637-
val kind = varRef("kind")
1636+
/* This is either:
1637+
* - an int: 1 means isInterface; 2 means isJSType; 0 otherwise
1638+
* - a Scala class constructor: means 0 + assign `kindOrCtor.prototype.$classData = this;`
1639+
*/
1640+
val kindOrCtor = varRef("kindOrCtor")
16381641

16391642
val hasParentData = globalKnowledge.isParentDataAccessed
16401643

@@ -1647,8 +1650,8 @@ private[emitter] object CoreJSLib {
16471650
val depth = varRef("depth")
16481651
val obj = varRef("obj")
16491652
val params =
1650-
if (hasParentData) paramList(kind, fullName, ancestors, parentData, isInstance)
1651-
else paramList(kind, fullName, ancestors, isInstance)
1653+
if (hasParentData) paramList(kindOrCtor, fullName, ancestors, parentData, isInstance)
1654+
else paramList(kindOrCtor, fullName, ancestors, isInstance)
16521655
MethodDef(static = false, Ident(cpn.initClass), params, None, {
16531656
Block(
16541657
/* Extract the internalName, which is the first property of ancestors.
@@ -1668,15 +1671,18 @@ private[emitter] object CoreJSLib {
16681671
Return(!(!(BracketSelect(that DOT cpn.ancestors, internalName))))
16691672
})
16701673
}),
1671-
privateFieldSet(cpn.isJSType, kind === 2),
1674+
privateFieldSet(cpn.isJSType, kindOrCtor === 2),
16721675
publicFieldSet(cpn.name, fullName),
1673-
publicFieldSet(cpn.isInterface, kind === 1),
1676+
publicFieldSet(cpn.isInterface, kindOrCtor === 1),
16741677
publicFieldSet(cpn.isInstance, isInstance || {
16751678
genArrowFunction(paramList(obj), {
16761679
Return(!(!(obj && (obj DOT classData) &&
16771680
BracketSelect(obj DOT classData DOT cpn.ancestors, internalName))))
16781681
})
16791682
}),
1683+
If(typeof(kindOrCtor) !== str("number"), {
1684+
kindOrCtor.prototype DOT cpn.classData := This()
1685+
}),
16801686
Return(This())
16811687
)
16821688
})

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

+16-12
Original file line numberDiff line numberDiff line change
@@ -432,10 +432,11 @@ final class Emitter[E >: Null <: js.Tree](
432432
x._1
433433
}
434434

435-
val classTreeCache =
436-
extractChanged(classCache.getCache(linkedClass.version))
437-
438435
val kind = linkedClass.kind
436+
val assignClassData = kind.isClass && linkedClass.hasInstances
437+
438+
val classTreeCache =
439+
extractChanged(classCache.getCache(linkedClass.version, assignClassData))
439440

440441
// Global ref management
441442

@@ -723,16 +724,10 @@ final class Emitter[E >: Null <: js.Tree](
723724
kind, // invalidated by class version
724725
linkedClass.superClass, // invalidated by class version
725726
linkedClass.ancestors, // invalidated by overall class cache (identity)
726-
linkedClass.jsNativeLoadSpec // invalidated by class version
727+
linkedClass.jsNativeLoadSpec, // invalidated by class version
728+
assignClassData // invalidated directly (it is an input of classCache.getCache)
727729
)(moduleContext, classCache, linkedClass.pos).map(postTransform(_, 0))))
728730
}
729-
730-
if (linkedClass.hasInstances && kind.isClass && linkedClass.hasRuntimeTypeInfo) {
731-
main ++= classTreeCache.setTypeData.getOrElseUpdate({
732-
val tree = classEmitter.genSetTypeData(className)(moduleContext, classCache, linkedClass.pos)
733-
postTransform(tree, 0)
734-
})
735-
}
736731
}
737732

738733
if (linkedClass.kind.hasModuleAccessor && linkedClass.hasInstances) {
@@ -889,6 +884,7 @@ final class Emitter[E >: Null <: js.Tree](
889884
private final class ClassCache extends knowledgeGuardian.KnowledgeAccessor {
890885
private[this] var _cache: DesugaredClassCache[List[E]] = null
891886
private[this] var _lastVersion: Version = Version.Unversioned
887+
private[this] var _lastAssignClassData: Boolean = false
892888
private[this] var _cacheUsed = false
893889

894890
private[this] val _methodCaches =
@@ -921,14 +917,20 @@ final class Emitter[E >: Null <: js.Tree](
921917
_fullClassChangeTracker.foreach(_.startRun())
922918
}
923919

924-
def getCache(version: Version): (DesugaredClassCache[List[E]], Boolean) = {
920+
def getCache(version: Version, assignClassData: Boolean): (DesugaredClassCache[List[E]], Boolean) = {
925921
_cacheUsed = true
926922
if (_cache == null || !_lastVersion.sameVersion(version)) {
927923
invalidate()
928924
statsClassesInvalidated += 1
929925
_lastVersion = version
926+
_lastAssignClassData = assignClassData
930927
_cache = new DesugaredClassCache[List[E]]
931928
(_cache, true)
929+
} else if (_lastAssignClassData != assignClassData) {
930+
// Keep most of the cache; only invalidate its `typeData` subcache
931+
_cache.typeData.invalidate()
932+
_lastAssignClassData = assignClassData
933+
(_cache, true)
932934
} else {
933935
statsClassesReused += 1
934936
(_cache, false)
@@ -1223,6 +1225,8 @@ object Emitter {
12231225
value = v
12241226
value
12251227
}
1228+
def invalidate(): Unit =
1229+
value = null
12261230
}
12271231

12281232
private case class ClassID(

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,9 @@ class LibrarySizeTest {
7070
)
7171

7272
testLinkedSizes(
73-
expectedFastLinkSize = 148703,
74-
expectedFullLinkSizeWithoutClosure = 89321,
75-
expectedFullLinkSizeWithClosure = 21207,
73+
expectedFastLinkSize = 147656,
74+
expectedFullLinkSizeWithoutClosure = 88696,
75+
expectedFullLinkSizeWithClosure = 21795,
7676
classDefs,
7777
moduleInitializers = MainTestModuleInitializers
7878
)

project/Build.scala

+12-12
Original file line numberDiff line numberDiff line change
@@ -1998,33 +1998,33 @@ object Build {
19981998
case `default212Version` =>
19991999
if (!useMinifySizes) {
20002000
Some(ExpectedSizes(
2001-
fastLink = 634000 to 635000,
2002-
fullLink = 100000 to 101000,
2003-
fastLinkGz = 76000 to 77000,
2001+
fastLink = 626000 to 627000,
2002+
fullLink = 98000 to 99000,
2003+
fastLinkGz = 75000 to 79000,
20042004
fullLinkGz = 25000 to 26000,
20052005
))
20062006
} else {
20072007
Some(ExpectedSizes(
2008-
fastLink = 450000 to 451000,
2009-
fullLink = 303000 to 304000,
2010-
fastLinkGz = 65000 to 66000,
2008+
fastLink = 442000 to 443000,
2009+
fullLink = 297000 to 298000,
2010+
fastLinkGz = 64000 to 65000,
20112011
fullLinkGz = 46000 to 47000,
20122012
))
20132013
}
20142014

20152015
case `default213Version` =>
20162016
if (!useMinifySizes) {
20172017
Some(ExpectedSizes(
2018-
fastLink = 457000 to 458000,
2019-
fullLink = 98000 to 99000,
2020-
fastLinkGz = 59000 to 60000,
2018+
fastLink = 451000 to 452000,
2019+
fullLink = 96000 to 97000,
2020+
fastLinkGz = 58000 to 59000,
20212021
fullLinkGz = 26000 to 27000,
20222022
))
20232023
} else {
20242024
Some(ExpectedSizes(
2025-
fastLink = 322000 to 323000,
2026-
fullLink = 282000 to 283000,
2027-
fastLinkGz = 51000 to 52000,
2025+
fastLink = 315000 to 316000,
2026+
fullLink = 276000 to 277000,
2027+
fastLinkGz = 50000 to 51000,
20282028
fullLinkGz = 46000 to 47000,
20292029
))
20302030
}

0 commit comments

Comments
 (0)