Skip to content

[Fiber] Refactor bailoutOnFinishedWork #8613

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 8 commits into from
Dec 21, 2016

Conversation

sebmarkbage
Copy link
Collaborator

@sebmarkbage sebmarkbage commented Dec 21, 2016

See individual commits.

This consolidates bailouts on finished finished work into each branch behind the tag.

@sebmarkbage sebmarkbage changed the title Always reset context before beginning new work [Fiber] Refactor bailoutOnFinishedWork Dec 21, 2016
function updateHostComponent(current, workInProgress) {
const nextProps = workInProgress.pendingProps;
pushHostContext(workInProgress);
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This wasn't always pushed before such as when props.hidden. Now it should always push.

@sebmarkbage
Copy link
Collaborator Author

sebmarkbage commented Dec 21, 2016

I'm still looking at bailoutOnLowPriority which also has inconsistent pushes. I can do that in a follow up. Want to see if we can make it avoid calling completeWork in that case.

// TODO: This call is burried a bit too deep. It would be nice to have
// a single point which happens right before any new work and
// unfortunately this is it.
resetContextStack();
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could we put the reassignment of priorityContext (line 208) inside resetContextStack? It's not quite the same as the other contexts but it serves a similar purpose.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We could but I suspect that with #8611 these will be unified to a single call to an external module which is why I grouped them inside of just inlining them.

Copy link
Contributor

@bvaughn bvaughn Dec 21, 2016

Choose a reason for hiding this comment

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

That is correct. At least in its current form, #8611 unifies these context stacks so that it is no longer possible to reset them independently. You can only reset both or unwind both to a current Fiber.

}
} else if (nextProps === null || memoizedProps === nextProps || (
// TODO: Disable this before release, since it is not part of the public API
// I use this for testing to compare the relative overhead of classes.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Will we actually do this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

¯_(ツ)_/¯

// If the state is the same as before, that's a bailout because we had
// no work matching this priority.
return bailoutOnAlreadyFinishedWork(current, workInProgress);
}
const element = state.element;
reconcileChildren(current, workInProgress, element);
workInProgress.memoizedState = state;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Shouldn't we return workInProgress.child inside this branch? I get that bailoutOnAlreadyFinishedWork does that anyway but if there's state then it's not really a bailout, is it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Ah yes. Good catch.

// Return true if the first pending update has greater or equal priority.
return comparePriority(queue.first.priorityLevel, priorityLevel) <= 0;
}
exports.hasPendingUpdate = hasPendingUpdate;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nice!

}
const element = state.element;
reconcileChildren(current, workInProgress, element);
workInProgress.memoizedState = state;
Copy link
Collaborator

Choose a reason for hiding this comment

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

GitHub suppressed my comment on an older commit so here it is again:

Shouldn't we return workInProgress.child inside this branch? I get that bailoutOnAlreadyFinishedWork does that anyway but if there's state then it's not really a bailout, is it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yea. Fixed.

This consolidates the reset of context to one single place right before
any new work is started.

This place is burried in a bit of an awkward place but findNextUnitOfWork
happens right before any new work starts. That way we're guaranteed to have
an empty stack before we start anything new.

The benefit of this is that we don't have to rely .return being null when
entering beginWork but we also don't have to check it every time in the
hot path.
This just moves things around to continue the pattern that we already
started.
The functional component branch is a bit special since it has sCU in it.

The class component branch actually already covers this in a bit convoluted
way.

I will next replicate this check in each other branch.
This doesn't need to compare props because it doesn't use props,
only state.
Now we only bail out once we've entered each branch.

This has some repetition with regard to hasContextChanged but I'm hoping
we can just get rid of all those branches at some point since they're
mostly for backwards compatibility right now.
This is no longer needed. It is effectively covered by other branches
that tries to being merging the update queue which yields the same state
object as before if there is no work. That in turn bails out.

We can shortcut in the relevant paths if needed.
Since we only call bailout from within the host component branch now, we
can just move this to the branch where we already know that this is a
host component.

As part of this I noticed that we don't always push the host context so
I moved that to the beginning of the branch.
This is the same thing as the previous commit but with class, root and portal.

I noticed host and portal now already covers this case in their branches
since pushHostContainer is always at the top.
@sebmarkbage sebmarkbage merged commit 4a05c24 into facebook:master Dec 21, 2016
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.

4 participants