Skip to content
This repository has been archived by the owner on Feb 12, 2022. It is now read-only.

Effects contain NormalCompletion not Value #2110

Closed
wants to merge 13 commits into from
Closed

Conversation

cblappert
Copy link
Contributor

Release Notes: None

In an effort to unify Completions and Effects (many completions are tied to effects whose result should be the completion), I change evaluateForEffects to return a NormalCompletion whereever it would otherwise return a Value. Now all EvaluationResults are Completions or References.

Fairly mechanical refactor (except slightly tricky because PossiblyNormalCompletions are NormalCompletions, so instead of checking instanceof Value you should check instanceof NormalCompletion && ! instanceof PossiblyNormalCompletion).

@gaearon
Copy link
Contributor

gaearon commented Jun 11, 2018

NestedThrowEffects runs into an invariant it seems.

test/serializer/additional-functions/NestedThrowEffects.js {"delayInitializations":false,"inlineExpressions":false,"residual":false}
{ Invariant Violation: undefined
This is likely a bug in Prepack, not your code. Feel free to open an issue on GitHub.
    at invariant (/home/circleci/project/lib/invariant.js:10:136)
    at JoinImplementation.joinOrForkResults (/home/circleci/project/lib/methods/join.js:9:41726)
    at JoinImplementation.joinForkOrChoose (/home/circleci/project/lib/methods/join.js:9:30226)
    at composeNestedThrowEffectsWithHandler (/home/circleci/project/lib/evaluators/TryStatement.js:9:8204)
    at exports.default (/home/circleci/project/lib/evaluators/TryStatement.js:9:2306)
    at LexicalEnvironment.evaluateAbstract (/home/circleci/project/lib/environment.js:9:55282)
    at LexicalEnvironment.evaluate (/home/circleci/project/lib/environment.js:9:54439)
    at LexicalEnvironment.evaluateCompletion (/home/circleci/project/lib/environment.js:9:39246)
    at LexicalEnvironment.evaluateCompletionDeref (/home/circleci/project/lib/environment.js:9:38706)
    at FunctionImplementation.EvaluateStatements (/home/circleci/project/lib/methods/function.js:9:47736) name: 'Invariant Violation' }

@@ -230,6 +230,8 @@ export function computeBinary(
}
// return or throw completion
if (completion instanceof AbruptCompletion) throw completion;
if (completion instanceof NormalCompletion && !(completion instanceof PossiblyNormalCompletion))
Copy link
Contributor

Choose a reason for hiding this comment

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

At this point (at least in master) completion is guaranteed be an instance of Value.

@cblappert cblappert added the WIP This pull request is a work in progress and not ready for merging. label Jun 11, 2018
}

// Normal completions are returned just like spec completions
export class NormalCompletion extends Completion {}
export class NormalCompletion extends Completion {
toValue(): Value {
Copy link
Contributor

Choose a reason for hiding this comment

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

Probably not needed.

@@ -290,6 +290,8 @@ function tryToEvaluateCallOrLeaveAsAbstract(
}
// return or throw completion
if (completion instanceof AbruptCompletion) throw completion;
if (completion instanceof NormalCompletion && !(completion instanceof PossiblyNormalCompletion))
Copy link
Contributor

Choose a reason for hiding this comment

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

completion cannot be an instance of PossiblyNormalCompletion at this point.

@@ -73,6 +73,7 @@ export default function(
// so instead try to compute a fixpoint for it
let iteration = () => {
let bodyResult = env.evaluateCompletion(body, strictCode);
if (bodyResult instanceof Value) bodyResult = new NormalCompletion(bodyResult);
Copy link
Contributor

Choose a reason for hiding this comment

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

I would have expected that evaluateCompletion will never return a Value and that this can be part of its type annotation.

@@ -142,7 +142,13 @@ function emitResidualLoopIfSafe(
strictCode,
blockEnv
);
if (result instanceof Value && gen.empty() && modifiedBindings.size === 0 && modifiedProperties.size === 1) {
if (
result instanceof NormalCompletion &&
Copy link
Contributor

Choose a reason for hiding this comment

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

Come to think of it, why not introduce a new subtype of NormalCompletion called "SimpleNormalCompletion"?

@@ -1122,6 +1122,7 @@ export class FunctionImplementation {
// If c is undefined, the result is just realm.savedCompletion.
// Call this only when a join point has been reached.
incorporateSavedCompletion(realm: Realm, c: void | AbruptCompletion | Value): void | Completion | Value {
Copy link
Contributor

Choose a reason for hiding this comment

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

You probably want to remove "| Value" from the type of c.

@@ -117,6 +123,8 @@ export default function(

// return or throw completion
if (completion instanceof AbruptCompletion) throw completion;
if (completion instanceof SimpleNormalCompletion) completion = completion.value;
if (result2 instanceof SimpleNormalCompletion) result2 = result2.value;
invariant(completion instanceof Value); // references do not survive join
Copy link
Contributor

Choose a reason for hiding this comment

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

The comment is now out of date. Just delete it.

@@ -1122,6 +1128,7 @@ export class FunctionImplementation {
// If c is undefined, the result is just realm.savedCompletion.
// Call this only when a join point has been reached.
incorporateSavedCompletion(realm: Realm, c: void | AbruptCompletion | Value): void | Completion | Value {
invariant(!(c instanceof SimpleNormalCompletion), "TODO: This function doesn't accept NormalCompletions");
Copy link
Contributor

Choose a reason for hiding this comment

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

The type annotation already precludes c from being a normal completion. There is no need for it and there is no todo here either.

@@ -129,13 +130,13 @@ export class JoinImplementation {
): PossiblyNormalCompletion | Value {
if (leftCompletion instanceof PossiblyNormalCompletion) {
if (rightCompletion instanceof PossiblyNormalCompletion) {
this.updatePossiblyNormalCompletionWithValue(realm, rightCompletion, resultValue);
this.updatePossiblyNormalCompletionWithValue(realm, rightCompletion, new SimpleNormalCompletion(resultValue));
Copy link
Contributor

Choose a reason for hiding this comment

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

Given the name of the method, it would be more appropriate to do the wrapping inside the method.

@@ -341,27 +352,42 @@ export class JoinImplementation {
realm: Realm,
joinCondition: AbstractValue,
pnc: PossiblyNormalCompletion,
v: Value
nc: SimpleNormalCompletion
Copy link
Contributor

Choose a reason for hiding this comment

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

Given the name of the method, do the wrapping inside it rather than at the point of call.

invariant(rv instanceof Value);
a.value = rv;
return new PossiblyNormalCompletion(rv, joinCondition, fc, ce, a, ae, []);
let rv = this.collapseResults(realm, joinCondition, this._getNormalCompletion(c), this._getNormalCompletion(a));
Copy link
Contributor

Choose a reason for hiding this comment

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

Rather join just join the values.

if (result1 instanceof AbruptCompletion) {
let value = result2;
let savedEffects;
let savedPathConditions = [];
if (result2 instanceof PossiblyNormalCompletion) {
value = result2.value;
value = this._getNormalCompletion(result2);
Copy link
Contributor

Choose a reason for hiding this comment

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

You probably want to rename value to completion.

@@ -341,6 +341,8 @@ export class PropertiesImplementation {

// return or throw completion
if (completion instanceof AbruptCompletion) throw completion;
if (completion instanceof SimpleNormalCompletion && !(completion instanceof PossiblyNormalCompletion))
Copy link
Contributor

Choose a reason for hiding this comment

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

At this stage completion cannot be a PossiblyNormalCompletion.

if (result1 instanceof PossiblyNormalCompletion || result2 instanceof PossiblyNormalCompletion) {
//todo: #1174 figure out how to deal with loops that have embedded conditional exits
// widen join pathConditions
// widen normal result and Effects
// use abrupt part of result2, depend stability to make this safe. See below.
throw new FatalError();
}
if (result1 instanceof SimpleNormalCompletion && result2 instanceof SimpleNormalCompletion) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Moving the code around like this makes blame less effective.

src/realm.js Outdated
invariant(completion instanceof Value);
//TODO: fix
Copy link
Contributor

Choose a reason for hiding this comment

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

fix what?

src/realm.js Outdated
@@ -1627,7 +1642,7 @@ export class Realm {
return f();
} finally {
for (let priorEffect of priorEffects) {
invariant(!priorEffect.canBeApplied);
invariant(!priorEffect.canBeApplied, "Prior effects not applied");
Copy link
Contributor

Choose a reason for hiding this comment

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

The message seem to imply that canBeApplied is true.

@cblappert cblappert removed the WIP This pull request is a work in progress and not ready for merging. label Jun 13, 2018
invariant(rv instanceof SimpleNormalCompletion);
a.value = rv.value;
return new PossiblyNormalCompletion(rv.value, joinCondition, fc, ce, a, ae, []);
//let rv = this.collapseResults(realm, joinCondition, this._getNormalCompletion(c), this._getNormalCompletion(a));
Copy link
Contributor

Choose a reason for hiding this comment

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

Did you mean to leave this in?

@@ -377,6 +396,7 @@ export class JoinImplementation {
}

_getNormalCompletion(pnc: PossiblyNormalCompletion): SimpleNormalCompletion {
// TODO: unify with getNormalCompletion in PossiblyNormalCompletion
Copy link
Contributor

Choose a reason for hiding this comment

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

issue number

@@ -264,6 +261,9 @@ export class ModuleTracer extends Tracer {
realm.handleError(warning);
result = result.value;
realm.applyEffects(effects, `initialization of module ${moduleIdValue}`);
} else if (result instanceof SimpleNormalCompletion) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This did not have to move.

output.emitReturnValue(result);
if (result instanceof PossiblyNormalCompletion || result instanceof ForkedAbruptCompletion) {
output.emitIfThenElse(result, realm);
} else if (result instanceof SimpleNormalCompletion) {
Copy link
Contributor

Choose a reason for hiding this comment

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

You did not have to reorder these.

Copy link

@facebook-github-bot facebook-github-bot left a comment

Choose a reason for hiding this comment

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

@cblappert is landing this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

Copy link

@facebook-github-bot facebook-github-bot left a comment

Choose a reason for hiding this comment

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

@cblappert is landing this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

facebook-github-bot pushed a commit that referenced this pull request Jun 20, 2018
…ate (#2134)

Summary:
Release Notes: None

Follow up on #2110, this PR makes progress towards unifying PossiblyNormalCompletion and ForkedAbruptCompletion as well as unifying completion and effects.

Introduces `updateConsequentKeepingCurrentEffects` for a common pattern of updating one of the completions for a PNC/FAC and fixing up the effects.
Closes #2134

Differential Revision: D8525738

Pulled By: cblappert

fbshipit-source-id: c415eea47cd786e39820138f84213c2cc9d5e891
@hermanventer hermanventer deleted the refactor2 branch June 25, 2018 20:05
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants