Making peephole optimization in _getPropertyAssignmentStatement aware of implied conditions (#2592)

Summary:
Release notes: None

Added regression test.
Pull Request resolved: https://github.com/facebook/prepack/pull/2592

Differential Revision: D10227678

Pulled By: NTillmann

fbshipit-source-id: abeedaa43ce688fa9cb4ea095b3d7180a545fba5
This commit is contained in:
Nikolai Tillmann 2018-10-05 17:23:15 -07:00 committed by Facebook Github Bot
parent 5828c0a666
commit b942cd9635
2 changed files with 53 additions and 24 deletions

View File

@ -1212,35 +1212,55 @@ export class ResidualHeapSerializer {
deleteIfMightHaveBeenDeleted: boolean = false
): BabelNodeStatement {
if (mightHaveBeenDeleted) {
// We always need to serialize this value in order to keep the invariants happy.
invariant(value.mightHaveBeenDeleted());
// We always need to serialize this value in order to keep the invariants happy,
// as the visitor hasn't been taught about the following peephole optimization.
let serializedValue = this.serializeValue(value);
let condition;
if (value instanceof AbstractValue && value.kind === "conditional") {
let [c, x, y] = value.args;
if (x instanceof EmptyValue) {
if (c instanceof AbstractValue && c.kind === "!") condition = this.serializeValue(c.args[0]);
else condition = t.unaryExpression("!", this.serializeValue(c));
serializedValue = this.serializeValue(y);
} else if (y instanceof EmptyValue) {
condition = this.serializeValue(c);
serializedValue = this.serializeValue(x);
// Let's find the relevant value taking into account conditions implied by path conditions
while (value instanceof AbstractValue && value.kind === "conditional") {
let cf = this.conditionalFeasibility.get(value);
invariant(cf !== undefined);
if (cf.t && cf.f) break;
if (cf.t) value = value.args[1];
else {
invariant(cf.f);
value = value.args[2];
}
}
if (condition === undefined) {
condition = t.binaryExpression("!==", this.serializeValue(value), this._serializeEmptyValue());
if (value instanceof EmptyValue) {
return t.expressionStatement(t.unaryExpression("delete", ((location: any): BabelNodeMemberExpression), true));
} else if (value.mightHaveBeenDeleted()) {
// Let's try for a little peephole optimization, if __empty is a branch of a conditional, and the other side cannot be __empty
let condition;
if (value instanceof AbstractValue && value.kind === "conditional") {
let [c, x, y] = value.args;
if (x instanceof EmptyValue && !y.mightHaveBeenDeleted()) {
if (c instanceof AbstractValue && c.kind === "!") condition = this.serializeValue(c.args[0]);
else condition = t.unaryExpression("!", this.serializeValue(c));
serializedValue = this.serializeValue(y);
} else if (y instanceof EmptyValue && !x.mightHaveBeenDeleted()) {
condition = this.serializeValue(c);
serializedValue = this.serializeValue(x);
}
}
if (condition === undefined) {
condition = t.binaryExpression("!==", serializedValue, this._serializeEmptyValue());
}
let assignment = t.expressionStatement(t.assignmentExpression("=", location, serializedValue));
let deletion = null;
if (deleteIfMightHaveBeenDeleted) {
invariant(location.type === "MemberExpression");
deletion = t.expressionStatement(
t.unaryExpression("delete", ((location: any): BabelNodeMemberExpression), true)
);
}
return t.ifStatement(condition, assignment, deletion);
}
let assignment = t.expressionStatement(t.assignmentExpression("=", location, serializedValue));
let deletion = null;
if (deleteIfMightHaveBeenDeleted) {
invariant(location.type === "MemberExpression");
deletion = t.expressionStatement(
t.unaryExpression("delete", ((location: any): BabelNodeMemberExpression), true)
);
}
return t.ifStatement(condition, assignment, deletion);
} else {
return t.expressionStatement(t.assignmentExpression("=", location, this.serializeValue(value)));
}
return t.expressionStatement(t.assignmentExpression("=", location, this.serializeValue(value)));
}
_serializeArrayIndexProperties(

View File

@ -0,0 +1,9 @@
(function() {
let b = global.__abstract ? __abstract("boolean", "(true)") : true;
let obj = {};
if (b) {
global.obj = obj;
} else {
obj.x = 42;
}
})();