Commit Graph
19463 Commits
Author SHA1 Message Date
Joe Savona b009626431 Improve DCE to handle unused loop phis
Improves DCE, using fixpoint iteration to detect values that are updated across 
loops but otherwise never read. There is still some further optimization we can 
do (the dce-loop case could optimize out `y`), but this seems like plenty for 
now. 

Actually, we probably have to add some return statements to our fixtures before 
landing this, because otherwise most of the code goes away.
2023-02-03 15:46:00 -08:00
Joe Savona 19e21b73a7 Initial pass at dead code elimination
This is a first pass at DCE without having read any literate on the subject, so 
lemme know if there's a better approach. That said the algorithm is: 

* Keep a `Set<Identifier>` of identifiers that are used (and whose constructing 
logic cannot be removed). 

* Do a first RPO iteration of all block's phis. Any phi operand that 
participates in a loop is preemptively marked as "used" even if it isn't 
strictly used somewhere. This step is necessary bc these operands may otherwise 
not be used. 

* Do a second post-order iteration of all blocks, including iterating first 
their terminals, then reverse iteration of instructions, then their phis. Mark 
the operands of each as used as we encounter them, and prune instructions whose 
lvalue is never used. 

For now I was conservative about which types of instructions can be pruned. For 
example, call instructions are never pruned, even if the result of the call is 
never used. 

However one catch is that we currently prune instructions that cause values to 
become frozen. We had planned to add runtime calls (in dev) to freeze values for 
runtime enforcement, and if we want to do that we can always add these 
instructions back (or replace them with explicit freeze calls). 

There are a few potential next steps but we should discuss whether they're worth 
it: 

* Use fixpoint iteration to find exactly which operands are actually used. This 
would allow us to to prune cases such as `let x = 0; while (...) { x += 1 }` eg 
where there's a phi but the result is never used. Such cases should be rare in 
practice though. 

* Eliminate more types of instructions, eg eliminate function calls that don't 
have any mutable arguments.
2023-02-03 14:55:49 -08:00
Joe Savona 812e0ce701 [valueblocks] Join blocks instead of replacing operands (fix edge case)
There's a bug in the HIR->ReactiveFunction conversion for certain categories of 
compound value blocks where we replace operands (which must be a Place) with a 
ReactiveValue. This approach worked in practice for lots of cases so I thought a 
type coercion was safe, but then I found a case where this assumption breaks 
(see new test). 

The updated logic fixes the bug and is simpler. When a value block gets split up 
(because there was a nested value block), instead of replacing the earlier value 
in the later instructions, we append the instructions together. This can result 
in some extra nesting (which if we wanted we could flatten away) but ensures 
that we maintain type-safety.
2023-02-03 14:16:17 -08:00
Joe Savona cc33497c44 [valueblocks] Add InstrId to SeqExperession value
A SequenceExpression currently doesn't store the InstructionId that produced its 
final `.value`. This PR adds that instruction id, which is then used in the next 
PR as we compose SequenceExpressions.
2023-02-03 14:16:17 -08:00
Joe Savona 29a95d2dea [be] Use generator in InferTypes, extract helper
Just small things I noticed when looking at InferTypes. I was thinking about how 
we'd adjust this pass to account for hooks, i'll probably pause that for now but 
putting this up in case you like the changes. If not no big deal!
2023-02-03 12:59:13 -08:00
Mofei Zhang e30a9e9258 [hir syntax] Handle TemplateLiteral syntax 2023-02-03 15:44:37 -05:00
Mofei Zhang 34595b84c8 [syntax] Followup: clean up InferReactiveIdentifiers 2023-02-03 15:44:36 -05:00
Sathya Gunasekaran 4b55399fb8 [λ] Use context identifiers in inner functions
This threads through context identifiers to inner functions and also uses them 
as dependencies if they are mutated in the inner function.
2023-02-03 17:42:07 +00:00
mofeiZ ecb084c4b8 [ReactiveHIR] Infer reactive identifiers and promote temporaries
Messed up ghstack, this is a duplicate of #1093
2023-02-03 14:52:46 -05:00
Andrew Clark 855b77c9bb publish-prereleases: Exit if CircleCI request fails (#26100)
If the publish-prereleases command fails to access CircleCI, it will now
exit with a message instead of hanging indefinitely.
2023-02-02 19:20:34 -05:00
Jan Kassens 2ef24145e4 [flow] upgrade to 0.199.0 (#26096)
`flow-remove-types` was also upgraded to the latest version.
2023-02-02 16:19:05 -05:00
Sebastian Markbåge 922dd7ba50 Revert the outer module object to an object (#26093)
This is because Webpack has a `typeof ... === 'object'` before its esm
compat test.

This is unfortunate because it means we can't have a nice error in CJS
when someone does this:

```
const fn = require('client-fn');
fn();
```

I also fixed some checks in the validator that read off the client ref.
It shouldn't do those checks against a client ref, since those now
throw.
2023-02-02 15:30:59 -05:00
Joe Savona 34a7b58334 Restrict switch case test values until they use value blocks
We currently lower switch case test values within the wrong scope: the test 
value really should be a value block rather than a `Place`. Until then, this PR 
adds a bailout for complex test values: we allow primitives and identifiers 
which should cover most real-world use-cases.
2023-02-02 09:09:25 -08:00
Sathya Gunasekaran dc65e7c5a9 [aliasing] Make InferAliasForStores use the visitor infra
No need for InferAliasForStores to know about the semantics of each instruction 
anymore. It's just a simple pass that iterates over every operand and lvalue. 

The FunctionExpression is special cased because it's slightly different but I 
have a follow up that removes this special casing.
2023-02-02 17:41:35 +00:00
Sathya Gunasekaran 40f304392e [aliasing] Alias object loads to it's lvalue as well
This doesn't change codegen as the lvalue is unused but it lets us make this 
pass be semantically the same across all instructions -- "alias lvalue and 
operands of an instr".
2023-02-02 17:41:31 +00:00
Sathya Gunasekaran 018899d778 [aliasing] Make aliasing account for MutableRange.end being exclusive 2023-02-02 17:41:27 +00:00
Sathya Gunasekaran 98f67c407b [aliasing] Alias ComputedLoad operands 2023-02-02 15:45:16 +00:00
Sathya Gunasekaran 5e1929c002 [aliasing] Alias ComputedStore operands 2023-02-02 15:45:12 +00:00
Joe Savona de929fcc40 Partial support for update expressions
Adds limited support for UpdateExpressions (`x++`). We now support the postfix 
form (`x++` ok, `++x` is a todo) and only when the argument is an identifier. We 
can relax these restrictions with more work, but this PR should be sufficient 
for the examples we've seen so far.
2023-02-02 07:53:24 -08:00
Sathya Gunasekaran 7a92b2fe5d [be] Cleanup logic that matches mutatedId and mutatedDep 2023-02-02 14:05:37 +00:00
Sathya Gunasekaran 12274f30b9 [be] Inline buildMutatedDeps 2023-02-02 14:05:36 +00:00
Sathya Gunasekaran aa2403e068 [λ] Run analyseFunctions on inner func exprs
Previously we would skip out on calling analyseFunctions on inner function  
exprs so we missed out on catching aliased mutation in a different scope.
2023-02-02 14:05:35 +00:00
Sathya Gunasekaran 0522d5233b [λ] Store and define captured bindings as context
This lets us treat global references differently from captured references.
2023-02-02 14:05:34 +00:00
Lauren Tan 8a0d3169fd Record todo bailouts in CodegenReactiveFunction
Went over this pass and converted any todos to bailouts, otherwise we continue 
to throw an invariant if there's an internal error
2023-02-01 14:49:47 -05:00
Lauren Tan 1baf22a421 [playground] Fix error wrapping for realsies
CSS is hard (jk i'm just terrible at it now)
2023-02-01 14:14:45 -05:00
Lauren Tan 8c9d1b85be Failing test from - - 2023-02-01 13:46:20 -05:00
Lauren Tan f53318d0ba [playground] Fix errors not wrapping 2023-02-01 13:17:04 -05:00
Sebastian Markbåge 9d111ffdfb Serialize Promises through Flight (#26086)
This lets you pass Promises from server components to client components
and `use()` them there.

We still don't support Promises as children on the client, so we need to
support both. This will be a lot simpler when we remove the need to
encode children as lazy since we don't need the lazy encoding anymore
then.

I noticed that this test failed because we don't synchronously resolve
instrumented Promises if they're lazy. The second fix calls `.then()`
early to ensure that this lazy initialization can happen eagerly. ~It
felt silly to do this with an empty function or something, so I just did
the attachment of ping listeners early here. It's also a little silly
since they will ping the currently running render for no reason if it's
synchronously available.~ EDIT: That didn't work because a ping might
interrupt the current render. Probably need a bigger refactor.

We could add another extension but we've already taken a lot of
liberties with the Promise protocol. At least this is one that doesn't
need extension of the protocol as much. Any sub-class of promises could
do this.
2023-02-01 12:56:53 -05:00
Joe Savona c2dda028fd Improve debugging for - errors 2023-02-01 09:42:46 -08:00
Joe Savona 2069269903 Support TypeCastExpression
Support TypeCastExpressions — `(x: TypeAnnotation)`. This is pretty 
straightforward, it's semantically identical to a raw identifier. 

One catch is that our prettier config is hard-coded to use the babel-ts parser, 
i wasn't sure how to make that dynamic based on the file extension so for now i 
just ignored .flow.js files in our pretter config.
2023-02-01 08:42:33 -08:00
Ming Ye 0ba4698c7b Fix async test in React reconciler (#26087) 2023-02-01 09:59:41 +01:00
Sebastian Markbåge 8c234c0de9 Move the Webpack manifest config to one level deeper (#26083)
This frees up the Webpack manifest to contain a `serverManifest` part
too.

@shuding
2023-01-31 23:33:31 -05:00
Joe Savona 47074a2def Support JsxSpreadAttribute
Changes the representation of JsxElement props to be an array of attributes, 
each of which can be a named attribute or spread attribute.
2023-01-31 16:43:46 -08:00
Joe Savona df07522b89 [be] Move Result into Utils/
The `Utils/` folder is meant to be a catch-all for code that doesn't have an 
obvious home in other directories.
2023-01-31 16:14:23 -08:00
Lauren Tan e8650951ea [playground] Add diff view toggle
Quick hack to show a diff view comparing previous pass to current. Default is 
the output view 

![Screenshot 2023-01-31 at 5 37 09 
PM](https://user-images.githubusercontent.com/1390709/215899637-672d578a-6fb9-4580-ae87-ae0be0878a59.png) 

![Screenshot 2023-01-31 at 5 37 12 
PM](https://user-images.githubusercontent.com/1390709/215899640-7aff3c06-fc67-476a-82f9-59d65b4f9ac4.png)
2023-01-31 17:37:22 -05:00
mofeiZ 5fbfce6d3b [test case] Failing assignment inside of nested if statement
``` 

function useBar(props) { 

let z; 

if (props.a) { 

if (props.b) { 

z = baz(); 

} 

} 

return z; 

} 

``` 

Currently fails with 

``` 

InvariantViolation: A phi cannot have two operands initialized before its 
declaration 

```
2023-01-31 16:53:06 -05:00
Joe Savona 0c5176c618 [valueblocks] Cleanup
Removes dead code related the now-unused old representation for value blocks.
2023-01-31 13:39:41 -08:00
Joe Savona fa525e0b6f [valueblocks] For.init is a value block 2023-01-31 13:39:40 -08:00
Joe Savona 894eadfa67 [valueblocks] For.update is a proper value block 2023-01-31 13:39:39 -08:00
Joe Savona 6930b5f77e [valueblocks] For.test is a proper value block 2023-01-31 13:39:39 -08:00
Joe Savona 90e1265442 [valueblocks] While.test is a proper value block
Changes ReactiveWhileTerminal’s test to use the new value block representation. 
This means logical and condition expressions will work as while test values now.
2023-01-31 13:39:38 -08:00
Joe Savona 50f300bc92 [valueblocks] Update some passes to use the new visitor
Updates some passes from ReactiveScopes/ to use the visitor added in the 
previous PR. The +124/-354 line count on this diff tells the story  — the new 
visitor avoids a lot of boilerplate and helps focus on the logic not the 
traversal. 

Note that there are a few passes which transform the function such as 
adding/removing scopes. A follow-up will extend the visitor to support that and 
convert the remaining passes.
2023-01-31 13:39:38 -08:00
Joe Savona 400bf4588c [valueblocks] More general visitor for ReactiveFunctions
This adds a truly general-purpose visitor pattern for ReactiveFunction, modeled 
on what's worked well in Relay Compiler. All types of node that have children 
get a visitFoo/traverseFoo pair of functions. By default the visitFoo() function 
delegates to the traverseFoo() function, but the visit variant is meant to be 
overridden and can delegate to the traverseFoo() variant — this gives you 
precise control so that you can save/restore state before/after traversing 
children. 

Probably the only interesting thing is that visitLValue() does not call 
visitPlace() by default though it technically could. So far that is making sense 
in the passes i converted. 

Note that once all passes are updated to use this, i'll delete the other visitor 
helpers for ReactiveFunction.
2023-01-31 13:39:37 -08:00
Joe Savona 149353badb [valueblocks] Support sequence expressions (comma operator) 2023-01-31 13:39:37 -08:00
Joe Savona d6505572cb [valueblocks] Disallow AssignmentExpression in value blocks (temporarily)
There's a bug with assignment expression in normal value blocks due to LeaveSSA. 
Until that's resolved i'm temporarily distinguishing "loop" blocks and "value" 
blocks, and disallowing assignment expressions in value blocks specifically.
2023-01-31 13:39:36 -08:00
Joe Savona 8c13c91f27 [valueblocks] ternary tests showing assignment bug
A ternary that reassigns the same variable in both branches causes some 
weirdness with LeaveSSA, this PR just adds the failing case.
2023-01-31 13:39:36 -08:00
Joe Savona acd227440e [valueblocks] Support conditional expressions (ternary)
Support conditional expressions from AST -> HIR -> ReactiveFunction -> AST. This 
also helps make the patterns for value block handling more clear, so i was able 
to extract some reusable logic in the HIR -> ReactiveFunction conversion phase.
2023-01-31 13:39:35 -08:00
Joe Savona dc7ac6fea4 [valueblocks] Scaffolding for ternary terminals
Core representation for terminals, without the lowering and conversion logic.
2023-01-31 13:39:34 -08:00
Joe Savona aca0e27012 [valueblocks] split working test and aliasing bug case 2023-01-31 13:39:34 -08:00
Joe Savona 096482e5cb print mutable ranges on every place
useful for debugging
2023-01-31 13:39:33 -08:00