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

feat(ivy): add support for short-circuiting #24039

Closed
wants to merge 8 commits into from
Closed

Conversation

vicb
Copy link
Contributor

@vicb vicb commented May 21, 2018

Short-circuitable expressions (using ternary & binary operators) could not use
the regular binding mechanism as it relies on the bindings being checked every
single time - the index is incremented as part of checking the bindings.

Then for pure function kind of bindings we use a different mechanism with a
fixed index. As such short circuiting a binding check does not mess with the
expected binding index.

Note that all pure function bindings are handled the same wether or not they
actually are short-circuitable. This allows to keep the compiler and compiled
code simple - and there is no runtime perf cost anyway.

@vicb vicb requested a review from mhevery May 21, 2018 23:00
@vicb vicb added feature Issue that requests a new feature comp: ivy action: review The PR is still awaiting reviews from at least one requested reviewer target: major This PR is targeted for the next major release labels May 21, 2018
@@ -494,11 +546,12 @@ describe('compiler compliance', () => {
if (rf & 1) {
$r3$.ɵE(0, 'my-comp');
$r3$.ɵe();
i0.ɵrS(10);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

i0 -> $r3$ - everywhere updated

* Binding for pure functions are store after the LNodes in the data array but before the binding.
*
* ---------------------------------------------------------------------------
* | LNodes ... | pure function bindings | regular binding / interpolations |
Copy link
Contributor Author

Choose a reason for hiding this comment

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

reg bindingS

@mary-poppins
Copy link

You can preview e81bc71 at https://pr24039-e81bc71.ngbuilds.io/.

@vicb vicb force-pushed the 0516-shc branch 2 times, most recently from 28e7953 to f399591 Compare May 21, 2018 23:34
@mary-poppins
Copy link

You can preview 28e7953 at https://pr24039-28e7953.ngbuilds.io/.

}
if (rf & 2) {
// TODO(vicb): Shouldn't bind be the outer call ?
Copy link
Contributor Author

@vicb vicb May 21, 2018

Choose a reason for hiding this comment

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

@mhevery the code needs to be updated here, right ?

Copy link
Contributor

Choose a reason for hiding this comment

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

correct, it needs to be wrapped in bind

@mary-poppins
Copy link

You can preview f399591 at https://pr24039-f399591.ngbuilds.io/.

@mary-poppins
Copy link

You can preview 8662643 at https://pr24039-8662643.ngbuilds.io/.

i0.ɵp(0, 'ternary', i0.ɵb((ctx.cond? i0.ɵf1(2, _c0, ctx.a): _c1)));
i0.ɵp(0, 'pipe', i0.ɵb(i0.ɵpb3(6, 1, ctx.value, 1, 2)));
i0.ɵp(0, 'and', i0.ɵb((ctx.cond && i0.ɵf1(4, _c0, ctx.b))));
i0.ɵp(0, 'or', i0.ɵb((ctx.cond || i0.ɵf1(6, _c0, ctx.c))));
Copy link
Contributor

Choose a reason for hiding this comment

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

This does not look right to me. 6 is already used 2 lines above. Are we double using the slots?

Copy link
Contributor Author

@vicb vicb May 22, 2018

Choose a reason for hiding this comment

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

2 lines above is i0.ɵpb3(6, 1, ctx.value, 1, 2)

  • 6 is the pipe
  • 1 is the offset of the reserved slot <- this one compares to this 6. No error here.

However i0 should be $r3$. I'll update that part.

}
if (rf & 2) {
$r3$.ɵp(
0, 'names',
$r3$.ɵb($r3$.ɵfV($e0_ff$, ctx.n0, ctx.n1, ctx.n2, ctx.n3, ctx.n4, ctx.n5, ctx.n6, ctx.n7, ctx.n8)));
$r3$.ɵb($r3$.ɵfV(10, $e0_ff$, ctx.n0, ctx.n1, ctx.n2, ctx.n3, ctx.n4, ctx.n5, ctx.n6, ctx.n7, ctx.n8)));
Copy link
Contributor

Choose a reason for hiding this comment

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

This seems wrong. ɵfV(10, $e0_ff$, [ctx.n0, ctx.n1, ctx.n2, ctx.n3, ctx.n4, ctx.n5, ctx.n6, ctx.n7, ctx.n8])) (note that args should be in array)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think at some point Chuck used that to prevent building an array. But good catch. I'll update (compiler + test).
This error is not introduced by the current PR but was here before

@@ -64,6 +64,8 @@ export {
text as T,
textBinding as t,

reserveSlots as rS,
Copy link
Contributor

Choose a reason for hiding this comment

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

I am starting to think that maybe we should have a general instruction

function reserve(
  elementCount: number,
  bindingCount: number,
  pureFnCount?: number,
  pipeCount?: number,
): void;

This instruction would be always required as first instruction and it would allocate the data. What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Might be.
I think we discussed reserving the bindingCount part today (current issue with undefined not being detected as a change).
Should be designed/agreed, I would tend to do this in a follow up PR. WDYT ?

Copy link
Contributor

Choose a reason for hiding this comment

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

SGTM

export function pureFunctionV(pureFn: (...v: any[]) => any, exps: any[], thisArg?: any): any {
let different = false;
export function pureFunctionV(
slotOffset: number, pureFn: (...v: any[]) => any, exps: any[], thisArg?: any): any {
Copy link
Contributor

Choose a reason for hiding this comment

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

Note exps is any[] hence pureFunctionV must take args as [arg0, arg1, ...]

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed, will fix (this code was not changed by this PR).

}
if (rf & 2) {
// TODO(vicb): Shouldn't bind be the outer call ?
Copy link
Contributor

Choose a reason for hiding this comment

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

correct, it needs to be wrapped in bind

$r3$.ɵt(0, $r3$.ɵi1('', $r3$.ɵpb2(1, $r3$.ɵpb2(2, ctx.name, ctx.size), ctx.size), ''));
$r3$.ɵt(
0,
$r3$.ɵi1('', $r3$.ɵpb2(1, 6, $r3$.ɵpb2(2, 3, ctx.name, ctx.size), ctx.size), ''));
Copy link
Contributor

Choose a reason for hiding this comment

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

same here, missing bind.

Thinking more about it, I think we should just inline bind into text, property, attribute instruction. This way it will be less code to generate. Maybe follow up PR?

Copy link
Contributor Author

@vicb vicb May 22, 2018

Choose a reason for hiding this comment

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

This one is actually correct. interpolationX returns NO_CHANGE.

I don't want to change the behavior or textBinding, ... in this PR. Out of scope.

Copy link
Member

Choose a reason for hiding this comment

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

@mhevery I was thinking the same thing, but that isn't trivial for cases where interpolation is relevant. Please refer to #23881 and #23923.

@vicb
Copy link
Contributor Author

vicb commented May 22, 2018

@mhevery Thanks for the review. I'll update this PR first thing tomorrow morning.

@mary-poppins
Copy link

You can preview a973202 at https://pr24039-a973202.ngbuilds.io/.

@mary-poppins
Copy link

You can preview fd9a07a at https://pr24039-fd9a07a.ngbuilds.io/.

@vicb
Copy link
Contributor Author

vicb commented May 22, 2018

@mary-poppins
Copy link

You can preview 4adff90 at https://pr24039-4adff90.ngbuilds.io/.

vicb added 7 commits May 23, 2018 10:25
Short-circuitable expressions (using ternary & binary operators) could not use
the regular binding mechanism as it relies on the bindings being checked every
single time - the index is incremented as part of checking the bindings.

Then for pure function kind of bindings we use a different mechanism with a
fixed index. As such short circuiting a binding check does not mess with the
expected binding index.

Note that all pure function bindings are handled the same wether or not they
actually are short-circuitable. This allows to keep the compiler and compiled
code simple - and there is no runtime perf cost anyway.
@mary-poppins
Copy link

You can preview bb679b3 at https://pr24039-bb679b3.ngbuilds.io/.

@vicb vicb added action: merge The PR is ready for merge by the caretaker and removed action: review The PR is still awaiting reviews from at least one requested reviewer labels May 23, 2018
Copy link
Contributor

@kara kara left a comment

Choose a reason for hiding this comment

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

FYI found some minor typos (probably for a follow-up, since this already has a merge label).

}

/**
* Sets up the binding index before execute any `pureFunctionX` instructions.
Copy link
Contributor

Choose a reason for hiding this comment

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

before execute -> before executing

/**
* Reserves slots for pure functions (`pureFunctionX` instructions)
*
* Binding for pure functions are store after the LNodes in the data array but before the binding.
Copy link
Contributor

Choose a reason for hiding this comment

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

Binding for pure functions -> Bindings for pure functions
are store -> are stored

*/
export function reserveSlots(numSlots: number) {
// Init the slots with a unique `NO_CHANGE` value so that the first change is always detected
// whether is happens or not during the first change detection pass - pure functions checks
Copy link
Contributor

Choose a reason for hiding this comment

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

is happens -> it happens

@@ -2365,6 +2414,22 @@ function assertDataNext(index: number, arr?: any[]) {
arr.length, index, `index ${index} expected to be at the end of arr (length ${arr.length})`);
}

/**
* On the first template pass the reserved slots should be set `NO_CHANGE`.
Copy link
Contributor

Choose a reason for hiding this comment

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

On the first template pass the reserved slots -> On the first template pass, the reserved slots

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 13, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: merge The PR is ready for merge by the caretaker cla: yes feature Issue that requests a new feature target: major This PR is targeted for the next major release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants