Fix join of SimpleNormal with PossiblyNormal completions. (#2250)

Summary:
Release note: none

When joining a SimpleNormalCompletion with a PossiblyNormalCompletion, do not move the join condition to a leaf position.
Pull Request resolved: https://github.com/facebook/prepack/pull/2250

Differential Revision: D8838821

Pulled By: hermanventer

fbshipit-source-id: 6e102307af31e2ff2f3fbc7ec7f5ad516df5f7a5
This commit is contained in:
Herman Venter 2018-07-13 11:21:34 -07:00 committed by Facebook Github Bot
parent 912384679b
commit cd1b752e92
4 changed files with 22 additions and 111 deletions

View File

@ -88,6 +88,9 @@ export class BreakCompletion extends AbruptCompletion {
export class ReturnCompletion extends AbruptCompletion {
constructor(value: Value, precedingEffects: void | Effects, location: ?BabelNodeSourceLocation) {
super(value, precedingEffects, location);
if (value instanceof EmptyValue) {
this.value = value.$Realm.intrinsics.undefined;
}
}
}

View File

@ -334,87 +334,11 @@ export class JoinImplementation {
}
}
updatePossiblyNormalCompletionWithConditionalSimpleNormalCompletion(
joinNormalCompletions(
realm: Realm,
joinCondition: AbstractValue,
pnc: PossiblyNormalCompletion,
nc: SimpleNormalCompletion
): void {
let v = nc.value;
if (pnc.consequent instanceof AbruptCompletion) {
if (pnc.alternate instanceof SimpleNormalCompletion) {
nc.value = AbstractValue.createFromConditionalOp(realm, joinCondition, pnc.alternate.value, v);
pnc.alternateEffects.result = nc;
nc.effects = pnc.alternateEffects;
pnc.alternate = nc;
} else {
invariant(pnc.alternate instanceof PossiblyNormalCompletion);
this.updatePossiblyNormalCompletionWithConditionalSimpleNormalCompletion(
realm,
joinCondition,
pnc.alternate,
nc
);
}
} else {
if (pnc.consequent instanceof SimpleNormalCompletion) {
nc.value = AbstractValue.createFromConditionalOp(realm, joinCondition, pnc.consequent.value, v);
pnc.consequentEffects.result = nc;
nc.effects = pnc.consequentEffects;
pnc.consequent = nc;
} else {
invariant(pnc.consequent instanceof PossiblyNormalCompletion);
this.updatePossiblyNormalCompletionWithConditionalSimpleNormalCompletion(
realm,
joinCondition,
pnc.consequent,
nc
);
}
}
}
updatePossiblyNormalCompletionWithInverseConditionalSimpleNormalCompletion(
realm: Realm,
joinCondition: AbstractValue,
pnc: PossiblyNormalCompletion,
nc: SimpleNormalCompletion
): void {
let v = nc.value;
if (pnc.consequent instanceof AbruptCompletion) {
if (pnc.alternate instanceof SimpleNormalCompletion) {
nc.value = AbstractValue.createFromConditionalOp(realm, joinCondition, v, pnc.alternate.value);
pnc = pnc.updateAlternateKeepingCurrentEffects(nc);
} else {
invariant(pnc.alternate instanceof PossiblyNormalCompletion);
this.updatePossiblyNormalCompletionWithInverseConditionalSimpleNormalCompletion(
realm,
joinCondition,
pnc.alternate,
nc
);
}
} else {
if (pnc.consequent instanceof SimpleNormalCompletion) {
nc.value = AbstractValue.createFromConditionalOp(realm, joinCondition, v, pnc.consequent.value);
pnc = pnc.updateConsequentKeepingCurrentEffects(nc);
} else {
invariant(pnc.consequent instanceof PossiblyNormalCompletion);
this.updatePossiblyNormalCompletionWithInverseConditionalSimpleNormalCompletion(
realm,
joinCondition,
pnc.consequent,
nc
);
}
}
}
joinPossiblyNormalCompletions(
realm: Realm,
joinCondition: AbstractValue,
c: PossiblyNormalCompletion,
a: PossiblyNormalCompletion
c: NormalCompletion,
a: NormalCompletion
): PossiblyNormalCompletion {
let getAbstractValue = (v1: void | Value, v2: void | Value): Value => {
if (v1 instanceof EmptyValue) return v2 || realm.intrinsics.undefined;
@ -633,8 +557,8 @@ export class JoinImplementation {
if (result1 instanceof AbruptCompletion && result2 instanceof AbruptCompletion) {
return new ForkedAbruptCompletion(realm, joinCondition, result1, e1, result2, e2);
}
if (result1 instanceof PossiblyNormalCompletion && result2 instanceof PossiblyNormalCompletion) {
return this.joinPossiblyNormalCompletions(realm, joinCondition, result1, result2);
if (result1 instanceof NormalCompletion && result2 instanceof NormalCompletion) {
return this.joinNormalCompletions(realm, joinCondition, result1, result2);
}
if (result1 instanceof AbruptCompletion) {
let completion = result2;
@ -678,21 +602,6 @@ export class JoinImplementation {
savedEffects
);
}
if (result1 instanceof PossiblyNormalCompletion) {
invariant(result2 instanceof SimpleNormalCompletion);
this.updatePossiblyNormalCompletionWithConditionalSimpleNormalCompletion(realm, joinCondition, result1, result2);
return result1;
}
if (result2 instanceof PossiblyNormalCompletion) {
invariant(result1 instanceof SimpleNormalCompletion);
this.updatePossiblyNormalCompletionWithInverseConditionalSimpleNormalCompletion(
realm,
joinCondition,
result2,
result1
);
return result2;
}
invariant(false);
}

View File

@ -32,7 +32,6 @@ import {
AbruptCompletion,
Completion,
ForkedAbruptCompletion,
SimpleNormalCompletion,
PossiblyNormalCompletion,
NormalCompletion,
} from "./completions.js";
@ -741,20 +740,6 @@ export type JoinType = {
e: Effects
): ForkedAbruptCompletion,
updatePossiblyNormalCompletionWithConditionalSimpleNormalCompletion(
realm: Realm,
joinCondition: AbstractValue,
pnc: PossiblyNormalCompletion,
nc: SimpleNormalCompletion
): void,
updatePossiblyNormalCompletionWithInverseConditionalSimpleNormalCompletion(
realm: Realm,
joinCondition: AbstractValue,
pnc: PossiblyNormalCompletion,
nc: SimpleNormalCompletion
): void,
extractAndJoinCompletionsOfType(CompletionType: typeof AbruptCompletion, realm: Realm, c: AbruptCompletion): Effects,
joinForkOrChoose(realm: Realm, joinCondition: Value, e1: Effects, e2: Effects): Effects,

View File

@ -0,0 +1,14 @@
let c1 = global.__abstract ? __abstract("boolean", "true") : true;
let c2 = global.__abstract ? __abstract("boolean", "false") : false;
function foo(cond) {
if (cond) throw "I am an error too!";
}
if (c2) {
foo(c1);
}
inspect = function() {
return "success";
};