-
Notifications
You must be signed in to change notification settings - Fork 395
Add a desugaring pass between the base linker and the optimizer. #5101
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
Conversation
ae9fdc5
to
a738094
Compare
This is now in a reviewable shape, I think. The second commit might be over-engineered, though. 😅 |
I've had a look at this and the PRs on top of this. I think it fits the overall linker design reasonably nicely. Some higher level comments:
I'll likely proceed with a more detailed review when I have time, unless you feel comparing this to #5096 needs more higher level discussion. |
I can try something like that.
I don't think we can. The problem is that we don't see the shape
They don't. Those two PRs are unrelated. (I was prompted to look into that because I expected to have to write one more cache with clear after run for the desugaring phase. But it turned out it was so fast that a cache makes it worse, and so there is no relationship with the cache PRs.)
So basically making it a bare enum-like thing with an ordering, and have the checkers know the acceptable ranges? That's what I started with, but found it unwieldy. I can revert to that state to give a comparison.
No I think it's fine. It seems that this variant wins over #5096 overall. |
Maybe consider giving the enum ordering to make the range checks easier to grok. Or even expand the features on top of the checker ( IMHO the important part is that the logic of what is allowed where is in the checkers and not the phase enum. |
a738094
to
808638e
Compare
I pushed a different version of the This should make things clearer while leaving the responsibility to the checkers, as you mentioned (although factored out in |
I pushed a commit thast switches to that scheme. I'm not sure I like it better, though. It bothers me that we have fields in |
Yes, I agree, this is not nice in our design. However, I don't think this is anything new: Arguably, this is something we should fix. Ironically, one of the easiest way I know is using structural subtyping like in go (producer exposes concrete type, consumer defines an interface of what it needs). Unfortunately, that's not really available to us in Scala. Other than that, I find the alternative much cleaner :-/ Do you think it makes sense to figure out how to better decouple the fields we have for individual phases? |
Good point. The new desugaring info does not make the situation qualitatively worse. This is probably fine as is, then. We can try to improve that afterwards. |
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.
More in-depth review of check refactoring.
How big is the effort to split this into a separate PR to ease review?
linker/shared/src/main/scala/org/scalajs/linker/checker/ClassDefChecker.scala
Outdated
Show resolved
Hide resolved
hasRuntimeTypeInfo, | ||
fieldsRead, | ||
staticFieldsRead, | ||
staticDependencies, |
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.
Note to self: This will not be correct anymore when we add the NewLambda
desguaring: there will be a dependency on the class.
linker/shared/src/main/scala/org/scalajs/linker/checker/ClassDefChecker.scala
Outdated
Show resolved
Hide resolved
linker/shared/src/main/scala/org/scalajs/linker/checker/CheckingPhase.scala
Outdated
Show resolved
Hide resolved
linker/shared/src/main/scala/org/scalajs/linker/checker/FeatureSet.scala
Outdated
Show resolved
Hide resolved
linker/shared/src/main/scala/org/scalajs/linker/checker/FeatureSet.scala
Outdated
Show resolved
Hide resolved
linker/shared/src/main/scala/org/scalajs/linker/checker/FeatureSet.scala
Outdated
Show resolved
Hide resolved
linker/shared/src/main/scala/org/scalajs/linker/checker/FeatureSet.scala
Outdated
Show resolved
Hide resolved
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.
Review of the new phase (as far as possible given the current commit situation).
@@ -105,6 +107,13 @@ final class BaseLinker(config: CommonPhaseConfig, checkIR: Boolean) { | |||
|
|||
private[frontend] object BaseLinker { | |||
|
|||
/** Takes a ClassDef and DCE infos to construct a stripped down LinkedClass. | |||
*/ | |||
private[frontend] def refineClassDef(classDef: ClassDef, version: Version, |
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.
Do we still need this extra method?
newJSPropertyDef.copy()(jsPropertyDef.version)(newJSPropertyDef.pos) | ||
} | ||
|
||
override def transformTopLevelExportDef(exportDef: TopLevelExportDef): TopLevelExportDef = { |
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.
IIUC this override is (now) unnecessary?
I can do that, but probably not before Wednesday. |
No worries. I will not have time before that for sure. |
a98d50a
to
b21e091
Compare
Rebased on top of #5120. |
b21e091
to
a977798
Compare
a977798
to
2820d22
Compare
Rebased. This is now back to being standalone and re-reviewable. |
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.
Just one comment regarding the name of desugaringInfo.
@@ -89,3 +92,19 @@ final class LinkedClass( | |||
|
|||
def fullName: String = className.nameString | |||
} | |||
|
|||
object LinkedClass { | |||
final class DesugaringInfo( |
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 needs somewhere a comment at the very least what the info is. (the fact that desugaring is required).
Otherwise this IMO reads more like "information needed/useful for desugaring".
Ideally this of course goes into the names, but I realize that methodsNeedingDesugaring
is probably a bit too long :-/
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.
If only we had Latin's gérondif 😁 We could call it AbSaccharoTemperandum
😅
Perhaps DesugaringRequirements
?
linker/shared/src/test/scala/org/scalajs/linker/IRCheckerTest.scala
Outdated
Show resolved
Hide resolved
2820d22
to
4f75c5a
Compare
I went for Also I changed how we construct instances of |
Previously, the emitters and the optimizer all had to perform the same desugaring for `LinkTimeProperty` nodes. Instead, we now perform the desugaring in a dedicated phase, after the base linker. The reachability analysis records whether each method needs desugaring or not. We mark those that do so that the desugaring pass knows what to process. Methods that do not require desugaring are not processed, and so incur no additional cost. No caching is performed in `Desugarer`. It processes so few methods that caching makes it (slightly) *slower*. The machinery is heavy. It definitely outweighs the benefits in terms of duplication for `LinkTimeProperty` alone. However, the same machinery will be used to desugar `NewLambda` nodes. This commit serves as a stepping stone in that direction.
4f75c5a
to
1987d87
Compare
private def desugarClass(linkedClass: LinkedClass): LinkedClass = { | ||
import linkedClass._ | ||
|
||
if (desugaringRequirements.isEmpty) { |
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.
Nice!
Previously, the emitters and the optimizer all had to perform the same desugaring for
LinkTimeProperty
nodes. Instead, we now perform the desugaring in a dedicated phase, after the base linker.The reachability analysis records whether each method needs desugaring or not. We mark those that do so that the desugaring pass knows what to process. Methods that do not require desugaring are not processed, and so incur no additional cost.
No caching is perfored in
Desugarer
. It processes so few methods that caching makes it (slightly) slower.The machinery is heavy. It definitely outweighs the benefits in terms of duplication for
LinkTimeProperty
alone. However, the same machinery will be used to desugarNewLambda
nodes. This commit serves as a stepping stone in that direction.Alternative to #5096.