mirror of
https://github.com/facebookarchive/prepack.git
synced 2024-10-03 18:07:21 +03:00
Merge adjacent JOIN_GENERATORS with the same path conditions (#2623)
Summary: Release notes: Adjacent JOIN_GENERATORS with same path conditions are now merged for optimization. This pull request attempts to tackle https://github.com/facebook/prepack/issues/2565. Some assumptions were made (for lack of certainty) but commented on for further improvement. Pull Request resolved: https://github.com/facebook/prepack/pull/2623 Differential Revision: D13864274 Pulled By: NTillmann fbshipit-source-id: 50f965f4fc3e906d78af9a610b487b2854b085b2
This commit is contained in:
parent
011e69c153
commit
93d82b55a6
@ -368,6 +368,10 @@ export type PathType = {
|
||||
export class PathConditions {
|
||||
add(c: AbstractValue): void {}
|
||||
|
||||
equals(x: PathConditions): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
// this => val. A false value does not imply that !(this => val).
|
||||
implies(e: Value, depth: number = 0): boolean {
|
||||
return false;
|
||||
|
@ -1197,7 +1197,44 @@ export class Generator {
|
||||
invariant(other.effectsToApply === undefined);
|
||||
|
||||
if (other.empty()) return;
|
||||
this._entries.push(...other._entries);
|
||||
let otherEntries = other._entries;
|
||||
otherEntries.forEach(otherEntry => this._appendEntry(otherEntry));
|
||||
}
|
||||
|
||||
_appendEntry(entry: GeneratorEntry): void {
|
||||
let attemptToMergeEntry = (): boolean => {
|
||||
// It attempts to merge the `entry` argument with the last entry item
|
||||
// in `this._entries` if both are `JOIN_GENERATORS` and have the same
|
||||
// path conditions
|
||||
if (entry instanceof TemporalOperationEntry) {
|
||||
let operationDescriptor = entry.operationDescriptor;
|
||||
if (operationDescriptor.type === "JOIN_GENERATORS" && !this.empty()) {
|
||||
invariant(operationDescriptor.data.generators);
|
||||
let thisLastEntry = this._entries[this._entries.length - 1];
|
||||
if (thisLastEntry instanceof TemporalOperationEntry) {
|
||||
let thisLastEntryOperationDescriptor = thisLastEntry.operationDescriptor;
|
||||
if (thisLastEntryOperationDescriptor.type === "JOIN_GENERATORS") {
|
||||
invariant(thisLastEntryOperationDescriptor.data.generators);
|
||||
let [entryGenerator1, entryGenerator2] = operationDescriptor.data.generators;
|
||||
let [thisLastEntryGenerator1, thisLastEntryGenerator2] = thisLastEntryOperationDescriptor.data.generators;
|
||||
if (
|
||||
entryGenerator1.pathConditions.equals(thisLastEntryGenerator1.pathConditions) &&
|
||||
entryGenerator2.pathConditions.equals(thisLastEntryGenerator2.pathConditions)
|
||||
) {
|
||||
if (!entryGenerator1.empty())
|
||||
entryGenerator1._entries.forEach(e => thisLastEntryGenerator1._entries.push(e));
|
||||
if (!entryGenerator2.empty())
|
||||
entryGenerator2._entries.forEach(e => thisLastEntryGenerator2._entries.push(e));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
attemptToMergeEntry() || this._entries.push(entry);
|
||||
}
|
||||
|
||||
joinGenerators(joinCondition: AbstractValue, generator1: Generator, generator2: Generator): void {
|
||||
|
@ -41,6 +41,32 @@ export class PathConditionsImplementation extends PathConditions {
|
||||
this._failedNegativeImplications = undefined;
|
||||
}
|
||||
|
||||
// It makes the strong assumption that, in order for 2 path conditions to be equal,
|
||||
// the number of values must be the same, as well as their order.
|
||||
// This might not always be the case, yielding false negatives?!
|
||||
equals(x: PathConditions): boolean {
|
||||
invariant(x instanceof PathConditionsImplementation);
|
||||
let conditionsAreEqual = () => {
|
||||
if (this._assumedConditions.size !== x._assumedConditions.size) return false;
|
||||
let thisConditions = Array.from(this._assumedConditions);
|
||||
let xConditions = Array.from(x._assumedConditions);
|
||||
let thisLength = thisConditions.length;
|
||||
for (let i = 0; i < thisLength; i++) {
|
||||
let thisCondition = thisConditions[i];
|
||||
let xCondition = xConditions[i];
|
||||
if (!thisCondition.equals(xCondition)) return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
let baseConditionsAreEqual = () => {
|
||||
if (this._baseConditions && !x._baseConditions) return false;
|
||||
if (!this._baseConditions && x._baseConditions) return false;
|
||||
if (this._baseConditions && x._baseConditions) return this._baseConditions.equals(x._baseConditions);
|
||||
return true;
|
||||
};
|
||||
return this === x || (conditionsAreEqual() && baseConditionsAreEqual());
|
||||
}
|
||||
|
||||
isReadOnly(): boolean {
|
||||
return this._readonly;
|
||||
}
|
||||
|
19
test/serializer/optimizations/simplifyMultipleIfs1.js
Normal file
19
test/serializer/optimizations/simplifyMultipleIfs1.js
Normal file
@ -0,0 +1,19 @@
|
||||
// omit invariants
|
||||
// Copies of if \(:2
|
||||
var x = global.__abstract ? __abstract("boolean", "x") : "x";
|
||||
|
||||
if (x) {
|
||||
console.log("Hello");
|
||||
}
|
||||
|
||||
if (x) {
|
||||
console.log(" World");
|
||||
}
|
||||
|
||||
if (x) {
|
||||
console.log("!");
|
||||
}
|
||||
|
||||
if (!x) {
|
||||
console.log("Hello World!");
|
||||
}
|
16
test/serializer/optimizations/simplifyMultipleIfs2.js
Normal file
16
test/serializer/optimizations/simplifyMultipleIfs2.js
Normal file
@ -0,0 +1,16 @@
|
||||
// omit invariants
|
||||
// Copies of if \(:2
|
||||
var x = global.__abstract ? __abstract("boolean", "x") : "x";
|
||||
var y = global.__abstract ? __abstract("boolean", "y") : "y";
|
||||
|
||||
if (x) {
|
||||
console.log("Hello World!");
|
||||
}
|
||||
|
||||
if (x && y) {
|
||||
console.log("Hello");
|
||||
}
|
||||
|
||||
if (x && y) {
|
||||
console.log(" World!");
|
||||
}
|
Loading…
Reference in New Issue
Block a user