Support optimized Array.filter and make filter-map compositions correct (#2582)

Summary:
Adds optimized operator support for `Array.filter`, and makes compositions in which `Array.filter` is called on a mapped array correct. Aliasing information kept in the mapped array is exposed to the `Array.filter` call, which collects it in the resulting array.

Resolves #2580
Pull Request resolved: https://github.com/facebook/prepack/pull/2582

Differential Revision: D10204091

Pulled By: sb98052

fbshipit-source-id: a365d3d7120cbae344c64c540e5b63a889b6c699
This commit is contained in:
Sapan Bhatia 2018-10-04 14:02:03 -07:00 committed by Facebook Github Bot
parent 8ca388ab0e
commit 31697d5de0
5 changed files with 84 additions and 3 deletions

View File

@ -17,6 +17,7 @@ import {
BoundFunctionValue,
ConcreteValue,
ECMAScriptSourceFunctionValue,
NativeFunctionValue,
NullValue,
NumberValue,
ObjectValue,
@ -418,10 +419,25 @@ export default function(realm: Realm, obj: ObjectValue): void {
if (thisArg) {
args.push(thisArg);
}
let possibleNestedOptimizedFunctions;
// If callbackfn is a native function, it cannot be optimized, and cannot alias locations
// other than ones accesible via global, which leaked value analysis disregards.
if (!(callbackfn instanceof NativeFunctionValue)) {
invariant(callbackfn instanceof ECMAScriptSourceFunctionValue || callbackfn instanceof BoundFunctionValue);
possibleNestedOptimizedFunctions = [
{
func: callbackfn,
thisValue: thisArg || realm.intrinsics.undefined,
kind: "filter",
},
];
}
return ArrayValue.createTemporalWithWidenedNumericProperty(
realm,
args,
createOperationDescriptor("UNKNOWN_ARRAY_METHOD_PROPERTY_CALL")
createOperationDescriptor("UNKNOWN_ARRAY_METHOD_PROPERTY_CALL"),
possibleNestedOptimizedFunctions
);
}

View File

@ -188,8 +188,12 @@ function createArrayWithWidenedNumericProperty(
): ArrayValue {
let abstractArrayValue = new ArrayValue(realm, intrinsicName);
if (possibleNestedOptimizedFunctions !== undefined && possibleNestedOptimizedFunctions.length > 0) {
if (realm.arrayNestedOptimizedFunctionsEnabled && (!realm.react.enabled || realm.react.optimizeNestedFunctions)) {
if (
realm.arrayNestedOptimizedFunctionsEnabled &&
(!realm.react.enabled || realm.react.optimizeNestedFunctions) &&
possibleNestedOptimizedFunctions !== undefined
) {
if (possibleNestedOptimizedFunctions.length > 0) {
evaluatePossibleNestedOptimizedFunctionsAndStoreEffects(
realm,
abstractArrayValue,

View File

@ -0,0 +1,19 @@
// arrayNestedOptimizedFunctionsEnabled
// does contain: return 42
function f(c) {
var arr = Array.from(c);
let obj = { foo: 42 };
function op(x) {
return obj;
}
let mapped = arr.filter(op);
mapped[0].foo = 0;
return obj.foo;
}
global.__optimize && __optimize(f);
inspect = () => f([0]);

View File

@ -0,0 +1,24 @@
// arrayNestedOptimizedFunctionsEnabled
// does not contain: return 42
function f(c) {
var arr = Array.from(c);
let obj = { foo: 42 };
function op1(x) {
return obj;
}
function op2(x) {
return true;
}
let mapped = arr.map(op1);
let mapped2 = mapped.filter(op2);
mapped2[0].foo = 0;
return obj.foo;
}
global.__optimize && __optimize(f);
inspect = () => f([0]);

View File

@ -0,0 +1,18 @@
// arrayNestedOptimizedFunctionsEnabled
// does contain:return true
function f(c, g) {
var arr = Array.from(c);
let obj = { foo: true };
function op(x) {
return obj.foo;
}
let mapped = arr.filter(op);
return mapped;
}
global.__optimize && __optimize(f);
inspect = () => f([0], () => {});