-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
[BUGFIX beta] Extracts computed property set into a separate function #5547
Conversation
} | ||
|
||
if (watched) { propertyDidChange(obj, keyName); } | ||
ret = computedPropertySet.apply(this, arguments); |
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.
Wouldn't we also want to avoid passing arguments around?
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.
apply
is special and it's ok to use it. It doesn't get deoptimized.
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.
c
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.
So confused. Why did we stop using __nextSuper.apply(this, arguments)
then? Instead we have a two pass "optimization" there, first build a new array, then pass it to the Ember apply
function that tries to use call.
Or is it still slower even if it doesn't de-opt? Just trying to understand where it is appropriate to use Function.apply
and not.
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.
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.
The wrapper calls an internal apply function but has to jump through hoops to avoid leaking arguments only to use Function.call in the apply function.
The extra code to unwrap arguments and use call is just crazy faster than using Function.apply? I will not question the gods of v8, but at some point wrap just used Function.apply and we stopped.
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.
@mixonic I honestly don't recall __nextSuper.apply(this, arguments)
but I'm pretty new part of the code base. Generally, you want to avoid passing arguments
to the function (and in that case apply
is a function that calls either Function.call
or Function.apply
).
As I mentioned before, calling Function.apply
is safe but I'm not sure why we stopped doing that. Here's the commit where "array hack" was introduced. Maybe we should revisit and see if there's perf/functionality impact if we switch to calling __nextSuper.apply
? Calling apply
is expensive.
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.
Much research to do. We can take it offline of here though and just fold that plan into the oldSuper-is-newSuper refactor. Thanks for certifying my sanity!
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 apply hack exists because in some cases it is faster to call
a.call(this, b); and
a.call(this, b, c); then it is to call a.apply(this, arguments);
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.
in isolation this is true, but i wonder if in the context of a more complex system it is true or not.
Should this be considered a bugfix? |
nice! |
lets slide this into beta aswell |
@twokul the scope of this try/finally is much larger scope than it needs to be. The try/finally is meant only to ensure with reset Armed with that knowledge I think you should be able to improve this further. As a separate note, I think though we should make volatile a separate descriptor that just invokes .get() and .set() and doesn't do anything else, remove all the conditionals on cacheable. |
This is done to work around V8 (it cannot optimize functions with try blocks). Some comparisons from a real app: `defineProperty` Before: ![defineproperty deopt](https://cloud.githubusercontent.com/assets/1131196/4164553/ad42a504-34f6-11e4-92cc-fdf17e88cc22.png) After: ![defineproperty cp-set](https://cloud.githubusercontent.com/assets/1131196/4164559/bf012a86-34f6-11e4-9bba-e5b2dc378946.png) `watchKey` Before: ![watch - key deopt](https://cloud.githubusercontent.com/assets/1131196/4164570/e518cc88-34f6-11e4-9d66-97901a75161e.png) After: ![watch-key - cp-set](https://cloud.githubusercontent.com/assets/1131196/4164573/ec00d28e-34f6-11e4-8798-222b1ee985bf.png)
LGTM, thanks @twokul Since this doesn't change functionality and in my opinion very low risk, can we target release? /cc @rwjblue and @stefanpenner |
👍 from me for |
nice! |
[BUGFIX beta] Extracts computed property set into a separate function
This is done to work around V8 (it cannot optimize functions with
try
blocks).Comparison from a real app:
defineProperty
Before:
After: