Ensure Object.assign merge optimization properly accounts for prefix args (#2261)

Summary:
Release notes: none

When we check to do the temporal `Object.assign` merge optimization, we should properly account for any "prefix" args that occur before "to" and the "suffix" args. Test case added that came up in testing.
Pull Request resolved: https://github.com/facebook/prepack/pull/2261

Differential Revision: D8874714

Pulled By: trueadm

fbshipit-source-id: 59869f556c1300424c5a1b59d3df1fdd139b41fe
This commit is contained in:
Dominic Gannaway 2018-07-17 06:13:07 -07:00 committed by Facebook Github Bot
parent 2dc8607269
commit 5f626ebdbf
3 changed files with 62 additions and 9 deletions

View File

@ -1361,7 +1361,7 @@ export function attemptToMergeEquivalentObjectAssigns(
}
let otherArgs = otherTemporalBuildNodeEntry.args;
// Object.assign has at least 1 arg
if (otherArgs.length < 2) {
if (otherArgs.length < 1) {
continue;
}
let otherArgsToUse = [];
@ -1404,15 +1404,12 @@ export function attemptToMergeEquivalentObjectAssigns(
// If we cannot omit the "to" value that means it's being used, so we shall not try to
// optimize this Object.assign.
if (!callbacks.canOmit(to)) {
let newArgs = [to, ...otherArgsToUse];
// our merged Object.assign, shoud look like:
// Object.assign(to, ...prefixArgs, ...otherArgsToUse, ...suffixArgs)
let prefixArgs = args.slice(1, i - 1); // We start at 1, as 0 is the index of "to" a
let suffixArgs = args.slice(i + 1);
let newArgs = [to, ...prefixArgs, ...otherArgsToUse, ...suffixArgs];
for (let x = 2; x < args.length; x++) {
let arg = args[x];
// We don't want to add the "to" that we're merging with!
if (arg !== possibleOtherObjectAssignTo) {
newArgs.push(arg);
}
}
// We now create a new TemporalObjectAssignEntry, without mutating the existing
// entry at this point. This new entry is essentially a TemporalObjectAssignEntry
// that contains two Object.assign call TemporalObjectAssignEntry entries that have

View File

@ -0,0 +1,28 @@
// Copies of _\$C\(:1
// Copies of var _\$C = _\$B.assign;:1
// inline expressions
// _$C is the variable for Object.assign. See DeadObjectAssign4.js for
// a larger explanation.
function fn(obj, x) {
var a = Object.assign({}, x, { a: 1 });
var b = Object.assign({}, x, { b: 1 });
if (obj.cond) {
var c = Object.assign({}, a, b);
return c.a + c.b;
}
}
this.__optimize && __optimize(fn);
inspect = function() {
return fn(
{
cond: true,
},
{ a: 0, b: 0 }
);
};

View File

@ -0,0 +1,28 @@
// Copies of _\$D\(:1
// Copies of var _\$D = _\$C.assign;:1
// inline expressions
// _$C is the variable for Object.assign. See DeadObjectAssign4.js for
// a larger explanation.
function fn(obj, x) {
var a = Object.assign({}, x, { a: 1 });
var b = Object.assign({}, x, { b: 1 });
if (obj.cond) {
var c = Object.assign({}, a, b, a);
return c.a + c.b;
}
}
this.__optimize && __optimize(fn);
inspect = function() {
return fn(
{
cond: true,
},
{ a: 0, b: 0 }
);
};