-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Skip outer expressions when checking for super keyword in binder #20164
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
src/compiler/binder.ts
Outdated
function isSuperOrSuperProperty(node: Node, kind: SyntaxKind) { | ||
switch (kind) { | ||
function isSuperOrSuperProperty(node: Node) { | ||
node = skipOuterExpressions(node); |
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.
@rbuckton According to the commit log, kind
was being passed in here to avoid some kind of polymorphism. If that's the case; would it make sense to continue having isSuperOrSuperProperty
take the kind
and node
directly, and move the call to skipOuterExpressions
into computeCallExpression
, or is what I have here (which is more idiomatic considering what we do elsewhere) fine?
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 was an optimization introduced after reviewing deoptimization data via IRHydra. By only digging into node
when kind
indicates a property or element access, we avoid a number of soft-deoptimization hits from looking at both node.kind
and node.expression
in the same function.
The most efficient approach which doesn't require traversing the subtree tree again would be to have a TransformFlags.ContainsSuperOrSuperProperty
. We would then add the flag for SuperKeyword
and for a property or element access whose expression
is SuperKeyword
and reset the flag for all nodes except ParenthesizedExpression
, AsExpression
, TypeAssertionExpression
, or PartiallyEmittedExpression
so that it doesn't leak out of the context where it needs to matter.
Then we only need to interrogate subtreeFlags
for the answer, which avoids polymorphism and walking the subtree.
If we are running out of TransformFlags
then it doesn't matter where we put it, since the cost of deoptimization is probably negligible compared to the cost of skipOuterExpressions
(which likely ends up deoptimized in any case since it is highly polymorphic).
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.
We have two unused bits left in TransformFlags
; 27
and 28
, so we can do it. But even as is the next new emit feature that seriously needs transform flags (like, say, proper lexical arguments
) is already in for a bad time what with there not being enough flags. But I suppose that's a future problem.
src/compiler/binder.ts
Outdated
function isSuperOrSuperProperty(node: Node, kind: SyntaxKind) { | ||
switch (kind) { | ||
function isSuperOrSuperProperty(node: Node) { | ||
node = skipOuterExpressions(node); |
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 was an optimization introduced after reviewing deoptimization data via IRHydra. By only digging into node
when kind
indicates a property or element access, we avoid a number of soft-deoptimization hits from looking at both node.kind
and node.expression
in the same function.
The most efficient approach which doesn't require traversing the subtree tree again would be to have a TransformFlags.ContainsSuperOrSuperProperty
. We would then add the flag for SuperKeyword
and for a property or element access whose expression
is SuperKeyword
and reset the flag for all nodes except ParenthesizedExpression
, AsExpression
, TypeAssertionExpression
, or PartiallyEmittedExpression
so that it doesn't leak out of the context where it needs to matter.
Then we only need to interrogate subtreeFlags
for the answer, which avoids polymorphism and walking the subtree.
If we are running out of TransformFlags
then it doesn't matter where we put it, since the cost of deoptimization is probably negligible compared to the cost of skipOuterExpressions
(which likely ends up deoptimized in any case since it is highly polymorphic).
d769ebf
to
34d4206
Compare
@rbuckton Done. This now uses transform flag aggregations for tracking subtrees that contain a |
@rbuckton any more comments? |
* origin/master: (114 commits) LEGO: check in for master to temporary branch. LEGO: check in for master to temporary branch. Enable substitution for object literal shorthand property assignments in the system transform (microsoft#21106) Skip outer expressions when checking for super keyword in binder (microsoft#20164) Group intersection code in getSimplifiedIndexedAccessType Use filter instead of unnecessary laziness Remove mapped types to never from intersections Handle jsconfig.json in fourslash tests (microsoft#16484) Add a `getFullText()` helper method to `IScriptSnapshot` (microsoft#21155) Test Diff and Omit Keep string index from intersections in base constraint of index type LEGO: check in for master to temporary branch. Fix bug: get merged symbol of symbol.parent before checking against module symbol (microsoft#21147) Do not trigger the failed lookup location invalidation for creation of program emit files Handles microsoft#20934 Add test where emit of the file results in invalidating resolution and hence invoking recompile Parse comment on @Property tag and use as documentation comment (microsoft#21119) Update baselines push/popTypeResolution for circular base constraints LEGO: check in for master to temporary branch. Test:incorrect mapped type doesn't infinitely recur ...
This adds transform flags for tracking
Super
and property accesses/element accesses which containSuper
; enabling us to not need to search the subtree while binding these expressions, but still know if the subtree contains thesuper
reference that would indicate that the call expression needs to be sent through the ES2015 transformer (#20125). Additionally, this enabled me to shift which compute function had responsibility for setting the captures lexical this flag, allowing me to correct our behavior in a few cases (#21081).Fixes #20125
Fixes #21081