-
Notifications
You must be signed in to change notification settings - Fork 425
Enable and constrain optimized array operator support for InstantRender #2547
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NTillmann has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. Please make sure that the internal test produces reasonable results before landing.
src/realm.js
Outdated
number of unsupported scenarios. We group all associated compiler diagnostics here. */ | ||
|
||
instantRenderBailout(message: string, loc: ?BabelNodeSourceLocation) { | ||
let error = new CompilerDiagnostic(message, loc, "PP0039", "RecoverableError"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need an actual Wiki page for this. I am not thrilled by this, however. It may be more specific than PP0001, but it is still vague and not actionable. Each call to this routine should instead have its own error code along with a wiki page that gives concrete advice about it.
src/utils/leak.js
Outdated
// user upgrades the warning to an error. | ||
handleMaterialization = o => { | ||
let diagnosticCode = "PP0044"; | ||
if (realm.userChangedDiagnosticToError(diagnosticCode)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is far too subtle to change the semantics of the abstract interpreter based on whether or not a warning was upgraded to an error and then subsequently ignored.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I'll find another way to do this.
src/utils/leak.js
Outdated
diagnosticCode, | ||
"Warning" | ||
); | ||
realm.handleError(error); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Never ignore the result of handleError and then carry on. You may only ignore it if you throw a FatalError immediately afterwards.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This I've fixed.
Dropped the approach that opened a path to adding policies in Prepack.
Looks fine to me; except that I expect to run into issues when the everything including the module table is getting marked as final. But we can deal with it when we get there. |
@NTillmann Note that accessing such objects lead to recoverable errors for Instant Render. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sb98052 has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.
informative and recoverable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sb98052 is landing this pull request. If you are a Facebook employee, you can view this diff on Phabricator.
); | ||
} else { | ||
let error = new CompilerDiagnostic( | ||
"Mutating a final object, or an object with unknown properties, after some of those " + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not your doing, but I hate it when terms related to internal implementation details of Prepack leak out via error messages. Moreover, the text of this message is very obscure and may mislead a programmer who has to make sense of it.
Even worse than that, the wiki page for this error gives an outdated example. Prepack already snapshots and does the right thing for the example. I'm none too sure if there are other cases. If there are none, the whole concept of final objects should be deleted. Otherwise, the wiki page should be updated with examples that cover ALL of the other cases.
Is there an issue for this?
number of unsupported scenarios. We group all associated compiler diagnostics here. */ | ||
instantRenderBailout(message: string, loc: ?BabelNodeSourceLocation) { | ||
if (loc === undefined) loc = this.currentLocation; | ||
let error = new CompilerDiagnostic(message, loc, "PP0039", "RecoverableError"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I've said before, we should not use the same error code for different error messages. At best we can parameterize a single message. Given that, this abstraction is a trap and should be removed.
// We can't continue because this object is already in its final state | ||
if (realm.instantRender.enabled) { | ||
realm.instantRenderBailout( | ||
"Object mutations that require materialization are currently not supported by InstantRender", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Materialization is an internal concept and should not leak into error messages. The message is also very obscure. If you can't explain why this is not allowed in clear terms along with a wiki page that has a clarifying example, you are not quite done thinking about this problem.
@@ -1348,14 +1348,10 @@ export class ResidualHeapSerializer { | |||
to the __empty built-in */ | |||
if (instantRenderMode) { | |||
if (this.emitter.getReasonToWaitForDependencies(elemVal)) { | |||
let error = new CompilerDiagnostic( | |||
this.realm.instantRenderBailout( | |||
"InstantRender does not yet support cyclical arrays or objects", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This error is totally unrelated to the previous call to instantRenderBailout and a perfect example of the trap that I want to remove.
@@ -43,6 +43,11 @@ function evaluatePossibleNestedOptimizedFunctionsAndStoreEffects( | |||
thisValue = func.$BoundThis; | |||
} | |||
invariant(funcToModel instanceof ECMAScriptSourceFunctionValue); | |||
|
|||
if (realm.instantRender.enabled && realm.collectedNestedOptimizedFunctionEffects.has(funcToModel)) { | |||
realm.instantRenderBailout("Array operators may only be optimized once", funcToModel.expressionLocation); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does this mean? Give an example in a wiki page.
@@ -59,6 +64,12 @@ function evaluatePossibleNestedOptimizedFunctionsAndStoreEffects( | |||
// the default behaviour and leaked the nested functions so any bindings | |||
// within the function properly leak and materialize. | |||
if (e instanceof NestedOptimizedFunctionSideEffect) { | |||
if (realm.instantRender.enabled) { | |||
realm.instantRenderBailout( | |||
"InstantRender does not support impure array operators", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is an impure array operator? Give a motivating example in a wiki page.
"PP0039", | ||
"FatalError" | ||
this.realm.instantRenderBailout( | ||
"InstantRender does not yet support cyclical arrays or objects", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this no longer a fatal error? Is it likely that the code generated in this case will do the right thing? If so, I want to see a regression test that does the right thing in this case.
Summary: In support of #2547. Sometimes, it is more desirable (less costly, better for debugging) to flag a warning for a possibly anomalous condition, than to assume that it is anomalous and enforce it as an error. This change exposes warnings that a user upgrades to errors, so that they can then be enforced as such. Pull Request resolved: #2548 Differential Revision: D9884632 Pulled By: sb98052 fbshipit-source-id: c47b57a21aa047b0f3fa2672508f8fb23c04942a
This change ensures that the code generated via optimized array loop operators is correct in the InstantRender setting. It enables the optimization of such functions when the
--instantRender
option is set. Materialization is prevented by ensuring that post-optimization, objects that are reachable from the function are not mutated. Recoverable errors are issued. We also degrade all InstantRender bailouts to recoverable errors, to facilitate debugging. We add a constraint that optimized functions may not be reused.Resolves #2451 #2448