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

Skip to content

Commit 391bc5e

Browse files
committed
Be smarter about how we use params to initClass.
* Merge `isInterface` and `isJSType` as a single parameter `kind` that is an integer. * Use the first element of `ancestors` instead of independently passing the `internalName` (this is safe because ES 2015 guarantees the order of `getOwnPropertyNames`). * Really remove the `parentData` parameter when reachability analysis says it is not accessed.
1 parent dc3a20f commit 391bc5e

File tree

6 files changed

+56
-59
lines changed

6 files changed

+56
-59
lines changed

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

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -840,21 +840,26 @@ private[emitter] final class ClassEmitter(sjsGen: SJSGen) {
840840
val isJSType =
841841
kind.isJSType
842842

843-
val isJSTypeParam =
844-
if (isJSType) js.BooleanLiteral(true)
845-
else js.Undefined()
843+
val kindParam = {
844+
if (isJSType) js.IntLiteral(2)
845+
else if (kind == ClassKind.Interface) js.IntLiteral(1)
846+
else js.IntLiteral(0)
847+
}
846848

847-
val parentData = if (globalKnowledge.isParentDataAccessed) {
848-
superClass.fold[js.Tree] {
849+
val parentDataOpt = if (globalKnowledge.isParentDataAccessed) {
850+
val parentData = superClass.fold[js.Tree] {
849851
if (isObjectClass) js.Null()
850852
else js.Undefined()
851853
} { parent =>
852854
globalVar(VarField.d, parent.name)
853855
}
856+
parentData :: Nil
854857
} else {
855-
js.Undefined()
858+
Nil
856859
}
857860

861+
assert(ancestors.headOption.contains(className),
862+
s"The ancestors of ${className.nameString} do not start with itself: $ancestors")
858863
val ancestorsRecord = js.ObjectConstr(
859864
ancestors.withFilter(_ != ObjectClass).map(ancestor => (genAncestorIdent(ancestor), js.IntLiteral(1)))
860865
)
@@ -906,15 +911,11 @@ private[emitter] final class ClassEmitter(sjsGen: SJSGen) {
906911

907912
isInstanceFunWithGlobals.flatMap { isInstanceFun =>
908913
val allParams = List(
909-
js.ObjectConstr(List(genAncestorIdent(className) -> js.IntLiteral(0))),
910-
js.BooleanLiteral(kind == ClassKind.Interface),
914+
kindParam,
911915
js.StringLiteral(RuntimeClassNameMapperImpl.map(
912916
semantics.runtimeClassNameMapper, className.nameString)),
913-
ancestorsRecord,
914-
isJSTypeParam,
915-
parentData,
916-
isInstanceFun
917-
)
917+
ancestorsRecord
918+
) ::: parentDataOpt ::: isInstanceFun :: Nil
918919

919920
val prunedParams =
920921
allParams.reverse.dropWhile(_.isInstanceOf[js.Undefined]).reverse

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

Lines changed: 18 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,6 @@ private[emitter] object CoreJSLib {
130130
defineLinkingInfo() :::
131131
defineJSBuiltinsSnapshotsAndPolyfills() :::
132132
declareCachedL0() :::
133-
definePropertyName() :::
134133
defineCharClass() :::
135134
defineRuntimeFunctions() :::
136135
defineObjectGetClassFunctions() :::
@@ -526,23 +525,6 @@ private[emitter] object CoreJSLib {
526525
))
527526
}
528527

529-
private def definePropertyName(): List[Tree] = {
530-
/* Encodes a property name for runtime manipulation.
531-
*
532-
* Usage:
533-
* env.propertyName({someProp:0})
534-
* Returns:
535-
* "someProp"
536-
* Useful when the property is renamed by a global optimizer (like
537-
* Closure) but we must still get hold of a string of that name for
538-
* runtime reflection.
539-
*/
540-
defineFunction1(VarField.propertyName) { obj =>
541-
val prop = varRef("prop")
542-
ForIn(genEmptyImmutableLet(prop.ident), obj, Return(prop))
543-
}
544-
}
545-
546528
private def defineCharClass(): List[Tree] = {
547529
val ctor = {
548530
val c = varRef("c")
@@ -1651,23 +1633,31 @@ private[emitter] object CoreJSLib {
16511633
}
16521634

16531635
val initClass = {
1654-
val internalNameObj = varRef("internalNameObj")
1655-
val isInterface = varRef("isInterface")
1636+
// This is an int, where 1 means isInterface; 2 means isJSType; 0 otherwise
1637+
val kind = varRef("kind")
1638+
1639+
val hasParentData = globalKnowledge.isParentDataAccessed
1640+
16561641
val fullName = varRef("fullName")
16571642
val ancestors = varRef("ancestors")
1658-
val isJSType = varRef("isJSType")
16591643
val parentData = varRef("parentData")
16601644
val isInstance = varRef("isInstance")
16611645
val internalName = varRef("internalName")
16621646
val that = varRef("that")
16631647
val depth = varRef("depth")
16641648
val obj = varRef("obj")
1665-
MethodDef(static = false, Ident(cpn.initClass),
1666-
paramList(internalNameObj, isInterface, fullName, ancestors,
1667-
isJSType, parentData, isInstance), None, {
1649+
val params =
1650+
if (hasParentData) paramList(kind, fullName, ancestors, parentData, isInstance)
1651+
else paramList(kind, fullName, ancestors, isInstance)
1652+
MethodDef(static = false, Ident(cpn.initClass), params, None, {
16681653
Block(
1669-
const(internalName, genCallHelper(VarField.propertyName, internalNameObj)),
1670-
if (globalKnowledge.isParentDataAccessed)
1654+
/* Extract the internalName, which is the first property of ancestors.
1655+
* We use `getOwnPropertyNames()`, which since ES 2015 guarantees
1656+
* to return non-integer string keys in creation order.
1657+
*/
1658+
const(internalName,
1659+
BracketSelect(Apply(genIdentBracketSelect(ObjectRef, "getOwnPropertyNames"), List(ancestors)), 0)),
1660+
if (hasParentData)
16711661
privateFieldSet(cpn.parentData, parentData)
16721662
else
16731663
Skip(),
@@ -1678,9 +1668,9 @@ private[emitter] object CoreJSLib {
16781668
Return(!(!(BracketSelect(that DOT cpn.ancestors, internalName))))
16791669
})
16801670
}),
1681-
privateFieldSet(cpn.isJSType, !(!isJSType)),
1671+
privateFieldSet(cpn.isJSType, kind === 2),
16821672
publicFieldSet(cpn.name, fullName),
1683-
publicFieldSet(cpn.isInterface, isInterface),
1673+
publicFieldSet(cpn.isInterface, kind === 1),
16841674
publicFieldSet(cpn.isInstance, isInstance || {
16851675
genArrowFunction(paramList(obj), {
16861676
Return(!(!(obj && (obj DOT classData) &&

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,6 @@ private[emitter] object VarField {
175175

176176
final val valueDescription = mk("$valueDescription")
177177

178-
final val propertyName = mk("$propertyName")
179-
180178
// ID hash subsystem
181179

182180
final val systemIdentityHashCode = mk("$systemIdentityHashCode")

linker/shared/src/main/scala/org/scalajs/linker/standard/LinkedClass.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ import org.scalajs.ir.Names.{ClassName, FieldName}
2929
* P+1. The converse is not true. This guarantees that versions can be used
3030
* reliably to determine at phase P+1 whether a linked class coming from phase
3131
* P must be reprocessed.
32+
*
33+
* @param ancestors
34+
* List of all the ancestor classes and interfaces of this class. It always
35+
* contains this class name and `java.lang.Object`. This class name is
36+
* always the first element of the list.
3237
*/
3338
final class LinkedClass(
3439
// Stuff from Tree
@@ -61,6 +66,9 @@ final class LinkedClass(
6166

6267
val version: Version) {
6368

69+
require(ancestors.headOption.contains(name.name),
70+
s"ancestors for ${name.name.nameString} must start with itself: $ancestors")
71+
6472
def className: ClassName = name.name
6573

6674
val hasStaticInitializer: Boolean = {

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,9 @@ class LibrarySizeTest {
7070
)
7171

7272
testLinkedSizes(
73-
expectedFastLinkSize = 150063,
74-
expectedFullLinkSizeWithoutClosure = 89994,
75-
expectedFullLinkSizeWithClosure = 21325,
73+
expectedFastLinkSize = 148703,
74+
expectedFullLinkSizeWithoutClosure = 89321,
75+
expectedFullLinkSizeWithClosure = 21207,
7676
classDefs,
7777
moduleInitializers = MainTestModuleInitializers
7878
)

project/Build.scala

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1998,34 +1998,34 @@ object Build {
19981998
case `default212Version` =>
19991999
if (!useMinifySizes) {
20002000
Some(ExpectedSizes(
2001-
fastLink = 640000 to 641000,
2002-
fullLink = 101000 to 102000,
2003-
fastLinkGz = 77000 to 78000,
2004-
fullLinkGz = 26000 to 27000,
2001+
fastLink = 634000 to 635000,
2002+
fullLink = 100000 to 101000,
2003+
fastLinkGz = 76000 to 77000,
2004+
fullLinkGz = 25000 to 26000,
20052005
))
20062006
} else {
20072007
Some(ExpectedSizes(
2008-
fastLink = 453000 to 454000,
2009-
fullLink = 305000 to 306000,
2008+
fastLink = 450000 to 451000,
2009+
fullLink = 303000 to 304000,
20102010
fastLinkGz = 65000 to 66000,
2011-
fullLinkGz = 47000 to 48000,
2011+
fullLinkGz = 46000 to 47000,
20122012
))
20132013
}
20142014

20152015
case `default213Version` =>
20162016
if (!useMinifySizes) {
20172017
Some(ExpectedSizes(
2018-
fastLink = 462000 to 463000,
2019-
fullLink = 99000 to 100000,
2020-
fastLinkGz = 60000 to 61000,
2018+
fastLink = 457000 to 458000,
2019+
fullLink = 98000 to 99000,
2020+
fastLinkGz = 59000 to 60000,
20212021
fullLinkGz = 26000 to 27000,
20222022
))
20232023
} else {
20242024
Some(ExpectedSizes(
2025-
fastLink = 324000 to 325000,
2026-
fullLink = 284000 to 285000,
2025+
fastLink = 322000 to 323000,
2026+
fullLink = 282000 to 283000,
20272027
fastLinkGz = 51000 to 52000,
2028-
fullLinkGz = 47000 to 48000,
2028+
fullLinkGz = 46000 to 47000,
20292029
))
20302030
}
20312031

0 commit comments

Comments
 (0)