New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Consolidate Info Loading #4824
Consolidate Info Loading #4824
Conversation
Note that this currently fails |
|
||
private object ClassDefAndInfoCache { | ||
final class Update( | ||
val classDef: ClassDef, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems we currently cache the entire ClassDef, even though the global IRCache already does that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That seems appropriate. It's overall a nice simplification, I think. The added caching probably won't do any good, but it also should not hurt. It might become beneficial with an incremental Analyzer?
@@ -233,27 +233,16 @@ private[emitter] final class KnowledgeGuardian(config: Emitter.Config) { | |||
|
|||
private var isAlive: Boolean = true | |||
|
|||
private var isInterface = computeIsInterface(initClass) | |||
private var linkedClass = initClass |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo in the commit message? "Doesn't require use to compare"
superClassAskers += invalidatable | ||
superClass | ||
rawClassInfoAskers += invalidatable | ||
linkedClass.superClass.fold[ClassName](null.asInstanceOf[ClassName])(_.name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is asInstanceOf
necessary, here?
linkedClass.superClass.fold[ClassName](null.asInstanceOf[ClassName])(_.name) | |
linkedClass.superClass.fold[ClassName](null)(_.name) |
rawClassInfoAskers += invalidatable | ||
linkedClass.fields |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this valid? Can't fields
evolve independently of linkedClass.version
because of reachability analysis?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Uh, oh. Indeed :-/
val tree = ir.Serializers.deserialize(ByteBuffer.wrap(content)) | ||
|
||
new IRFileImpl(path, stableVersion) { | ||
def entryPointsInfo(implicit ec: ExecutionContext): Future[ir.EntryPointsInfo] = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CI says: missing import for ExecutionContext
and Future
.
) | ||
val path = "org/scalajs/linker/runtime/" + name | ||
val content = Base64.getDecoder().decode(contentBase64) | ||
val tree = ir.Serializers.deserialize(ByteBuffer.wrap(content)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why don't we do the same thing in linker/jvm/.../PrivateLibHolder
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because I forgot :-/
case object InternalIRCheck extends IRCheckMode | ||
} | ||
|
||
private class ClassInfoCache(className: ClassName, irLoader: IRLoader, irCheckMode: InfoLoader.IRCheckMode) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider putting all these private classes inside object InfoLoader
. We usually do that.
case FieldDef(flags, FieldIdent(name), _, ftpe) => | ||
if (!flags.namespace.isStatic) | ||
builder.maybeAddReferencedFieldClass(name, ftpe) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indentation issue.
private val methodSynthesizer = new MethodSynthesizer(irLoader) | ||
private val infoLoader = new InfoLoader(irLoader, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like this right hand side deserves a block.
@@ -107,11 +115,11 @@ final class BaseLinker(config: CommonPhaseConfig, checkIR: Boolean) { | |||
private def assemble(moduleInitializers: Seq[ModuleInitializer], | |||
analysis: Analysis)(implicit ec: ExecutionContext): Future[LinkingUnit] = { | |||
def assembleClass(info: ClassInfo) = { | |||
val classAndVersion = irLoader.loadClassDefAndVersion(info.className) | |||
val version = irLoader.irFileVersion(info.className) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This split between the version and the tree does not seem warranted. It results in looking up the class name twice in a hash map instead of once. Why is this done?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To avoid triggering a load if the version stays the same (in other parts of the codebase):
Alternatives:
- (re)-add an additional method
loadClassDefAndVersion
toIRLoader
. Con: More complicated interface. - Return
IRFile
s fromIRLoader
(orOption[IRFile]
). Con: Needs wrapping in the Refiner (OTOH, we could replace the tuples returned by the Optimizer by anIRFile
subclass).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes, I see. I wouldn't go as far as returning IRFile
from IRLoader
. I think I would find that confusing. Either re-add loadClassDefAndVersion
or leave it as is seem equally good.
|
||
/** Does a dead code elimination pass on a [[LinkingUnit]]. */ | ||
final class Refiner(config: CommonPhaseConfig, checkIR: Boolean) { | ||
import Refiner._ | ||
|
||
private val inputProvider = new InputProvider(checkIR) | ||
private val irLoader = new ClassDefIRLoader | ||
private val infoLoader = new InfoLoader(irLoader, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as the other one. This deserves a block.
Rebased onto main and addressed comments. TBC: Not necessary for 1.13.1. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM module the suggested Squash.
Instead of individual loaders for BaseLinker and Refiner, we consolidate into a single loader.
Instead of individual loaders for BaseLinker and Refiner, we
consolidate into a single loader.