Skip to content
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

Merged
merged 1 commit into from
Sep 17, 2014
Merged

Conversation

twokul
Copy link
Member

@twokul twokul commented Sep 5, 2014

This is done to work around V8 (it cannot optimize functions with try blocks).

Comparison from a real app:

defineProperty

Before:
defineproperty deopt

After:
defineproperty cp-set

}

if (watched) { propertyDidChange(obj, keyName); }
ret = computedPropertySet.apply(this, arguments);
Copy link
Member

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?

Copy link
Member Author

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.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

c

Copy link
Member

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.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mixonic are you referring to this call?

Copy link
Member

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.

Copy link
Member Author

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.

Copy link
Member

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!

Copy link
Member

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

Copy link
Member

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.

@wagenet
Copy link
Member

wagenet commented Sep 12, 2014

Should this be considered a bugfix?

@stefanpenner
Copy link
Member

nice!

@stefanpenner
Copy link
Member

lets slide this into beta aswell

@krisselden
Copy link
Contributor

@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 _suspended which is only used in the didChange hook, and only needs to be set while invoking propertyDidChange(obj, keyName) and also is only needed if the CP is watched and cacheable.

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.

@twokul twokul changed the title Extracts computed property set into a separate function [BUGFIX beta] Extracts computed property set into a separate function Sep 14, 2014
@krisselden
Copy link
Contributor

LGTM, thanks @twokul

Since this doesn't change functionality and in my opinion very low risk, can we target release? /cc @rwjblue and @stefanpenner

@rwjblue
Copy link
Member

rwjblue commented Sep 15, 2014

👍 from me for [BUGFIX release].

@mmun
Copy link
Member

mmun commented Sep 15, 2014

nice!

krisselden added a commit that referenced this pull request Sep 17, 2014
[BUGFIX beta] Extracts computed property set into a separate function
@krisselden krisselden merged commit 3260c94 into emberjs:master Sep 17, 2014
@twokul twokul deleted the cp-set branch September 17, 2014 12:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants