mirror of
https://github.com/facebookarchive/prepack.git
synced 2024-09-11 14:46:37 +03:00
Check invariant that path conditions no longer get mutated after being used as a base (#2538)
Summary: Release notes: None Otherwise, this could cause issues, as path conditions get captured e.g. in generators. Pull Request resolved: https://github.com/facebook/prepack/pull/2538 Reviewed By: hermanventer Differential Revision: D9762541 Pulled By: NTillmann fbshipit-source-id: 4d12681e3921d2c0f10f3c9f3f0702823a2b0d99
This commit is contained in:
parent
a973f896ac
commit
1e1c03c533
@ -377,6 +377,10 @@ export class PathConditions {
|
||||
return false;
|
||||
}
|
||||
|
||||
isReadOnly(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
getLength(): number {
|
||||
return 0;
|
||||
}
|
||||
|
@ -19,11 +19,16 @@ export class PathConditionsImplementation extends PathConditions {
|
||||
constructor(baseConditions?: void | PathConditions) {
|
||||
super();
|
||||
this._assumedConditions = new Set();
|
||||
invariant(baseConditions === undefined || baseConditions instanceof PathConditionsImplementation);
|
||||
this._baseConditions = baseConditions;
|
||||
this._readonly = false;
|
||||
if (baseConditions !== undefined) {
|
||||
invariant(baseConditions instanceof PathConditionsImplementation);
|
||||
baseConditions._readonly = true;
|
||||
this._baseConditions = baseConditions;
|
||||
}
|
||||
}
|
||||
|
||||
_assumedConditions: Set<AbstractValue>;
|
||||
_readonly: boolean;
|
||||
_baseConditions: void | PathConditionsImplementation;
|
||||
_impliedConditions: void | Set<AbstractValue>;
|
||||
_impliedNegatives: void | Set<AbstractValue>;
|
||||
@ -31,9 +36,14 @@ export class PathConditionsImplementation extends PathConditions {
|
||||
_failedNegativeImplications: void | Set<AbstractValue>;
|
||||
|
||||
add(c: AbstractValue): void {
|
||||
invariant(!this._readonly);
|
||||
this._assumedConditions.add(c);
|
||||
}
|
||||
|
||||
isReadOnly(): boolean {
|
||||
return this._readonly;
|
||||
}
|
||||
|
||||
implies(e: Value, depth: number = 0): boolean {
|
||||
if (!e.mightNotBeTrue()) return true;
|
||||
if (!e.mightNotBeFalse()) return false;
|
||||
@ -156,7 +166,11 @@ export class PathConditionsImplementation extends PathConditions {
|
||||
return this._assumedConditions;
|
||||
}
|
||||
|
||||
refineBaseConditons(realm: Realm, totalRefinements: number = 0): void {
|
||||
refineBaseConditons(
|
||||
realm: Realm,
|
||||
totalRefinements: number = 0,
|
||||
refinementTarget: PathConditionsImplementation = this
|
||||
): void {
|
||||
if (realm.abstractValueImpliesMax > 0) return;
|
||||
let total = totalRefinements;
|
||||
let refine = (condition: AbstractValue) => {
|
||||
@ -164,10 +178,11 @@ export class PathConditionsImplementation extends PathConditions {
|
||||
if (refinedCondition !== condition) {
|
||||
if (!refinedCondition.mightNotBeFalse()) throw new InfeasiblePathError();
|
||||
if (refinedCondition instanceof AbstractValue) {
|
||||
this.add(refinedCondition);
|
||||
// These might have different answers now that we're adding another path condition
|
||||
this._failedImplications = undefined;
|
||||
this._failedNegativeImplications = undefined;
|
||||
refinementTarget._failedImplications = undefined;
|
||||
refinementTarget._failedNegativeImplications = undefined;
|
||||
refinementTarget._readonly = false;
|
||||
refinementTarget.add(refinedCondition);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -184,7 +199,7 @@ export class PathConditionsImplementation extends PathConditions {
|
||||
} finally {
|
||||
this._baseConditions = savedBaseConditions;
|
||||
}
|
||||
savedBaseConditions.refineBaseConditons(realm, total);
|
||||
savedBaseConditions.refineBaseConditons(realm, total, refinementTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -276,6 +291,7 @@ export class PathImplementation {
|
||||
// A path condition is an abstract value that must be true in this particular code path, so we want to assume as much
|
||||
function pushPathCondition(condition: Value): void {
|
||||
let realm = condition.$Realm;
|
||||
if (realm.pathConditions.isReadOnly()) realm.pathConditions = new PathConditionsImplementation(realm.pathConditions);
|
||||
if (!condition.mightNotBeFalse()) {
|
||||
if (realm.impliesCounterOverflowed) throw new InfeasiblePathError();
|
||||
invariant(false, "assuming that false equals true is asking for trouble");
|
||||
@ -326,6 +342,7 @@ function pushPathCondition(condition: Value): void {
|
||||
// An inverse path condition is an abstract value that must be false in this particular code path, so we want to assume as much
|
||||
function pushInversePathCondition(condition: Value): void {
|
||||
let realm = condition.$Realm;
|
||||
if (realm.pathConditions.isReadOnly()) realm.pathConditions = new PathConditionsImplementation(realm.pathConditions);
|
||||
if (!condition.mightNotBeTrue()) {
|
||||
if (realm.impliesCounterOverflowed) throw new InfeasiblePathError();
|
||||
invariant(false, "assuming that false equals true is asking for trouble");
|
||||
|
Loading…
Reference in New Issue
Block a user