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

Fix timing of expression evaluation in blocks #337

Merged
merged 5 commits into from
Oct 26, 2016
Merged

Conversation

chancancode
Copy link
Contributor

This commit fixes a compiler bug where certain built-in syntaxes would re-evaluate its arguments when the block's assertion causes a re-entry into the append VM, instead of reusing the argument references that were created the first time.

In practice, this is observable when a "stateful helper" is used as an argument to a syntax with an assertion (currently #if, #unless, #with, #each, partial, InElementSyntax and dynamic components).

Because the argument references are created every time, any state stored on the original instance of the helper will be observably wiped away when used as an argument to an asserting block helper. Of course, it is also observable by comparing the JavaScript identity of the helper in question over time.

This commit fixes the compiler bug by moving the evaluation of the expressions passed as arguments to the block syntaxes in question above the Try block, and capturing the relevant registers (args and operand, which store the results of evaluating the arguments) so they can be restored when the append VM is re-entered for the same block.

Fixes #336

@chancancode
Copy link
Contributor Author

chancancode commented Oct 25, 2016

TODOs:

  • Investigate ember failure
  • Move Test opcode outside of the Enter block?

Godhuda added 5 commits October 25, 2016 16:09
This commit fixes a compiler bug where certain built-in syntaxes would
re-evaluate its arguments when the block's assertion causes a re-entry
into the append VM, instead of reusing the argument references that were
created the first time.

In practice, this is observable when a "stateful helper" is used as an
argument to a syntax with an assertion (currently `#if`, `#unless`,
`#with`, `#each`, `partial`, `InElementSyntax` and dynamic components).

Because the argument references are created every time, any state stored
on the original instance of the helper will be observably wiped away
when used as an argument to an asserting block helper. Of course, it is
also observable by comparing the JavaScript identity of the helper in
question over time.

This commit fixes the compiler bug by moving the evaluation of the
expressions passed as arguments to the block syntaxes in question above
the `Try` block, and capturing the relevant registers (args and operand,
which store the results of evaluating the arguments) so they can be
restored when the append VM is re-entered for the same block.
The `condition` register is now saved and restored, like the operand
and args registers.
This commit:

Switched partials to use the new opcode building style.

Moved the evaluation of the test opcode, and the production of the
condition register, outside of the block that could be re-entered. This
means that when the expression passed to a {{partial expr}} becomes
invalidated, we no longer generate a brand new reference for the
to-boolean operation on the operand (which produces the condition).
Previously, the code that captured and restored VM state manually
captured a few registers and manually restored them.

This commit puts the Frame in charge of capturing and restoring, which
means that if we want to capture more registers in the future, it will
be easy to remember to update the restoring code at the same time.
Now that we capture the conditional register, we have to also simulate
that effect when we lazily deopt (since we are essentially doing an OSR)
@chancancode chancancode merged commit 95986ee into master Oct 26, 2016
@chancancode chancancode deleted the fix-assert branch October 26, 2016 19:32
tilde-engineering pushed a commit to tildeio/ember.js that referenced this pull request Oct 26, 2016
This commit fixes a bug where `OutletComponentReference`
inadvertently relied on broken behavior: it returned `null`, assuming
that that would cause the reference to be rebuilt. But
glimmerjs/glimmer-vm#337 fixed the underlying bug, causing the reference to
be properly cached. As a result, we need to remember that we rendered a
`null` component, so that swapping back to the original component
replaces the empty component with the rendered component.
chancancode added a commit to emberjs/ember.js that referenced this pull request Oct 26, 2016
This commit fixes a bug where `OutletComponentReference`
inadvertently relied on broken behavior: it returned `null`, assuming
that that would cause the reference to be rebuilt. But
glimmerjs/glimmer-vm#337 fixed the underlying bug, causing the reference to
be properly cached. As a result, we need to remember that we rendered a
`null` component, so that swapping back to the original component
replaces the empty component with the rendered component.
(cherry picked from commit 8cc93b6)
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.

stateful helper bug
1 participant