mirror of
https://github.com/facebookarchive/prepack.git
synced 2024-09-11 14:46:37 +03:00
Ensure temporal assignments are not lost when the value does not change. (#2197)
Summary: Release note: Fix temporal assignments to intrinsics that happen inside non deterministic loops Tweak the property set logic to not short circuit when the target object is intrinsic and the RH value is the same as the current (tracked) property value. Also fix the code generator for loop bodies to not get upset when the lh side is temporal, but rh side is not widened (because it is a constant). Closes https://github.com/facebook/prepack/pull/2197 Differential Revision: D8721001 Pulled By: hermanventer fbshipit-source-id: d38565a40fa7ab8b4e30596f0e1dcfc655a4fb5e
This commit is contained in:
parent
466d19ddfd
commit
b6ce555f37
@ -731,7 +731,8 @@ export class PropertiesImplementation {
|
||||
}
|
||||
if (!identical) break;
|
||||
}
|
||||
if (identical) {
|
||||
// Only return here if the assigment is not temporal.
|
||||
if (identical && (O === realm.$GlobalObject || (O !== undefined && !O.isIntrinsic()))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
38
src/realm.js
38
src/realm.js
@ -1156,22 +1156,28 @@ export class Realm {
|
||||
let mightBeUndefined = value.mightBeUndefined();
|
||||
let keyKey = key.key;
|
||||
if (typeof keyKey === "string") {
|
||||
gen.emitStatement([key.object, tval || value, this.intrinsics.empty], ([o, v, e]) => {
|
||||
invariant(path !== undefined);
|
||||
invariant(typeof keyKey === "string");
|
||||
let lh = path.buildNode([o, t.identifier(keyKey)]);
|
||||
let r = t.expressionStatement(t.assignmentExpression("=", (lh: any), v));
|
||||
if (mightHaveBeenDeleted) {
|
||||
// If v === __empty || (v === undefined && !(key.key in o)) then delete it
|
||||
let emptyTest = t.binaryExpression("===", v, e);
|
||||
let undefinedTest = t.binaryExpression("===", v, voidExpression);
|
||||
let inTest = t.unaryExpression("!", t.binaryExpression("in", t.stringLiteral(keyKey), o));
|
||||
let guard = t.logicalExpression("||", emptyTest, t.logicalExpression("&&", undefinedTest, inTest));
|
||||
let deleteIt = t.expressionStatement(t.unaryExpression("delete", (lh: any)));
|
||||
return t.ifStatement(mightBeUndefined ? emptyTest : guard, deleteIt, r);
|
||||
}
|
||||
return r;
|
||||
});
|
||||
if (path !== undefined) {
|
||||
gen.emitStatement([key.object, tval || value, this.intrinsics.empty], ([o, v, e]) => {
|
||||
invariant(path !== undefined);
|
||||
invariant(typeof keyKey === "string");
|
||||
let lh = path.buildNode([o, t.identifier(keyKey)]);
|
||||
let r = t.expressionStatement(t.assignmentExpression("=", (lh: any), v));
|
||||
if (mightHaveBeenDeleted) {
|
||||
// If v === __empty || (v === undefined && !(key.key in o)) then delete it
|
||||
let emptyTest = t.binaryExpression("===", v, e);
|
||||
let undefinedTest = t.binaryExpression("===", v, voidExpression);
|
||||
let inTest = t.unaryExpression("!", t.binaryExpression("in", t.stringLiteral(keyKey), o));
|
||||
let guard = t.logicalExpression("||", emptyTest, t.logicalExpression("&&", undefinedTest, inTest));
|
||||
let deleteIt = t.expressionStatement(t.unaryExpression("delete", (lh: any)));
|
||||
return t.ifStatement(mightBeUndefined ? emptyTest : guard, deleteIt, r);
|
||||
}
|
||||
return r;
|
||||
});
|
||||
} else {
|
||||
// RH value was not widened, so it must have been a constant. We don't need to assign that inside the loop.
|
||||
// Note, however, that if the LH side is a property of an intrinsic object, then an assignment will
|
||||
// have been emitted to the generator.
|
||||
}
|
||||
} else {
|
||||
// TODO: What if keyKey is undefined?
|
||||
invariant(keyKey instanceof Value);
|
||||
|
8
test/serializer/abstract/DoWhile13.js
Normal file
8
test/serializer/abstract/DoWhile13.js
Normal file
@ -0,0 +1,8 @@
|
||||
let template = global.__abstract ? __abstract({x: __abstract("number")}, "({ set x(v) { console.log(v); } })") : { set x(v) { console.log(v); } };
|
||||
let n = global.__abstract ? __abstract('number', '(2)') : 2;
|
||||
let i = 0;
|
||||
do {
|
||||
template.x = 3;
|
||||
} while (++i < n);
|
||||
|
||||
inspect = function() { return template.x; }
|
Loading…
Reference in New Issue
Block a user