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

Fix hasRest to not try to load "-1" from params array. #6581

Merged
merged 1 commit into from Oct 28, 2017

Conversation

Projects
None yet
5 participants
@bmeurer
Member

bmeurer commented Oct 28, 2017

Similar in spirit to #6580, the
current implementation did

node.params[node.params.length - 1]

where node.params can also be empty, which causes it to lookup the
property "-1", which is not found on the array itself and obviously
also not in the Object.prototype and the Array.prototype. However
since "-1" is not a valid array index, but has a valid integer
representation, this is a very expensive lookup in V8 (and probably
other engines too, but that is probably less relevant, since Babel
most often runs on Node nowadays). In V8 this causes a call to
the %KeyedGetProperty runtime function for each of these "-1"
property lookups, and in addition sends the whole KeyedLoadIC
to MEGAMORPHIC state, which also penalizes other accesses
on this line.

This is a small non-breaking performance fix.

Fix hasRest to not try to load "-1" from params array.
Similar in spirit to #6580, the
current implementation did

```js
node.params[node.params.length - 1]
```

where `node.params` can also be empty, which causes it to lookup the
property `"-1"`, which is not found on the array itself and obviously
also not in the `Object.prototype` and the `Array.prototype`. However
since `"-1"` is not a valid array index, but has a valid integer
representation, this is a very expensive lookup in V8 (and probably
other engines too, but that is probably less relevant, since Babel
most often runs on Node nowadays). In V8 this causes a call to
the `%SetProperty` runtime function for each of these `"-1"`
property lookups, and in addition sends the whole `KeyedLoadIC`
to `MEGAMORPHIC` state, which also penalizes other accesses
on this line.

This is a small non-breaking performance fix.
@babel-bot

This comment has been minimized.

Show comment
Hide comment
@babel-bot

babel-bot Oct 28, 2017

Collaborator

Build successful! You can test your changes in the REPL here: https://babeljs.io/repl/build/5513/

Collaborator

babel-bot commented Oct 28, 2017

Build successful! You can test your changes in the REPL here: https://babeljs.io/repl/build/5513/

bmeurer added a commit to bmeurer/babylon that referenced this pull request Oct 28, 2017

Fix "-1" array accesses in CommentsParser.
Similar to the fixes in babel/babel#6580 and
babel/babel#6581, accesses of the form

```js
stack[stack.length - 1];
```

when `stack` can be an empty array are pretty bad for performance.
In this case it also breaks the type safety, since the function
`last<T>` is declared to only return values of type `T`, but
occasionally also returns `undefined` now, since the `stack` parameters
passed to it never contain a property `"-1"` and neither do the
`Object.prototype` or the `Array.prototype`.

This is a non-breaking performance fix, which adds proper checking
to ensure that `last` is only invoked on non-empty arrays.

bmeurer added a commit to bmeurer/babel that referenced this pull request Oct 28, 2017

Fix access to "-1" property on nodesOut array.
Similar to the fixes in babel#6580 and
babel#6581, accesses of the form

```js
nodesOut[nodesOut.length - 1]
```

where `nodesOut` can be an empty array, are bad for performance in Node.
In this particular case it's easy to restructure the code a bit to not
require the array access at all, but just track the current `tail` as we
go.

This is a non-breaking performance fix.

hzoo added a commit to babel/babylon that referenced this pull request Oct 28, 2017

Fix "-1" array accesses in CommentsParser. (#777)
Similar to the fixes in babel/babel#6580 and
babel/babel#6581, accesses of the form

```js
stack[stack.length - 1];
```

when `stack` can be an empty array are pretty bad for performance.
In this case it also breaks the type safety, since the function
`last<T>` is declared to only return values of type `T`, but
occasionally also returns `undefined` now, since the `stack` parameters
passed to it never contain a property `"-1"` and neither do the
`Object.prototype` or the `Array.prototype`.

This is a non-breaking performance fix, which adds proper checking
to ensure that `last` is only invoked on non-empty arrays.
@hzoo

hzoo approved these changes Oct 28, 2017

Yep ❤️

@hzoo hzoo merged commit df0d9d0 into babel:master Oct 28, 2017

4 checks passed

babel/repl REPL preview is available
Details
ci/circleci Your tests passed on CircleCI!
Details
codecov/project 86.96% (target 80%)
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details
@@ -155,7 +155,8 @@ const memberExpressionOptimisationVisitor = {
},
};
function hasRest(node) {
return t.isRestElement(node.params[node.params.length - 1]);
const length = node.params.length;
return length > 0 && t.isRestElement(node.params[length - 1]);

This comment has been minimized.

@johnthecat

johnthecat Oct 28, 2017

It’s better to use, i think:
length > 0 ? ... : false

@johnthecat

johnthecat Oct 28, 2017

It’s better to use, i think:
length > 0 ? ... : false

This comment has been minimized.

@baptistemanson

baptistemanson Oct 28, 2017

I prefer Ben's version. It obviously returns a boolean, is more compact. :)

@baptistemanson

baptistemanson Oct 28, 2017

I prefer Ben's version. It obviously returns a boolean, is more compact. :)

This comment has been minimized.

@johnthecat

johnthecat Oct 29, 2017

Main point of this PR is to make function more friendly to V8. Returning boolean OR undefined creates unnecessary work for engine to check and transform value into boolean in statement, that uses that func. Anyway, this code is better, than earlier.

@johnthecat

johnthecat Oct 29, 2017

Main point of this PR is to make function more friendly to V8. Returning boolean OR undefined creates unnecessary work for engine to check and transform value into boolean in statement, that uses that func. Anyway, this code is better, than earlier.

hzoo added a commit that referenced this pull request Oct 29, 2017

Fix access to "-1" property on nodesOut array. (#6582)
Similar to the fixes in #6580 and
#6581, accesses of the form

```js
nodesOut[nodesOut.length - 1]
```

where `nodesOut` can be an empty array, are bad for performance in Node.
In this particular case it's easy to restructure the code a bit to not
require the array access at all, but just track the current `tail` as we
go.

This is a non-breaking performance fix.

@lock lock bot added the outdated label May 1, 2018

@lock lock bot locked as resolved and limited conversation to collaborators May 1, 2018

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.