Skip to content

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

Merged
merged 3 commits into from
Jan 13, 2018

Conversation

weswigham
Copy link
Member

@weswigham weswigham commented Nov 20, 2017

This adds transform flags for tracking Super and property accesses/element accesses which contain Super; enabling us to not need to search the subtree while binding these expressions, but still know if the subtree contains the super 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

function isSuperOrSuperProperty(node: Node, kind: SyntaxKind) {
switch (kind) {
function isSuperOrSuperProperty(node: Node) {
node = skipOuterExpressions(node);
Copy link
Member Author

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?

Copy link
Contributor

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).

Copy link
Member Author

@weswigham weswigham Jan 9, 2018

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.

function isSuperOrSuperProperty(node: Node, kind: SyntaxKind) {
switch (kind) {
function isSuperOrSuperProperty(node: Node) {
node = skipOuterExpressions(node);
Copy link
Contributor

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).

@weswigham weswigham force-pushed the super-access-call-fix branch from d769ebf to 34d4206 Compare January 9, 2018 21:56
@weswigham
Copy link
Member Author

@rbuckton Done. This now uses transform flag aggregations for tracking subtrees that contain a super keyword or a property access/element access which uses a super keyword.

@mhegazy
Copy link
Contributor

mhegazy commented Jan 13, 2018

@rbuckton any more comments?

@weswigham weswigham merged commit 64305ed into microsoft:master Jan 13, 2018
errendir added a commit to errendir/TypeScript that referenced this pull request Jan 15, 2018
* 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
  ...
@weswigham weswigham deleted the super-access-call-fix branch April 10, 2018 23:10
@microsoft microsoft locked and limited conversation to collaborators Jul 25, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants