mirror of
https://github.com/facebookarchive/prepack.git
synced 2024-09-11 14:46:37 +03:00
Use isPure and isInvariant in many temporals (#2097)
Summary: Release notes: none When we create temporals that are pure, let's mark them as pure and also skip creating invariants for them too. Making these changes allows the serializer to not emit temporals that never end up getting used, reducing the output and also making it easier to debug the output (less spam of temporals). Closes https://github.com/facebook/prepack/pull/2097 Differential Revision: D8329043 Pulled By: trueadm fbshipit-source-id: f1ef4185793115dd7982b8162a7e3dc4038a15f9
This commit is contained in:
parent
5ee7ba4aa8
commit
9c11ec9a5e
@ -97,7 +97,8 @@ function createBabelHelpers(realm: Realm, global: ObjectValue | AbstractObjectVa
|
||||
[objectWithoutPropertiesValue, obj, keys],
|
||||
([methodNode, objNode, propRemoveNode]) => {
|
||||
return t.callExpression(methodNode, [objNode, propRemoveNode]);
|
||||
}
|
||||
},
|
||||
{ skipInvariant: true, isPure: true }
|
||||
);
|
||||
if (value instanceof AbstractObjectValue) {
|
||||
// as we are returning an abstract object, we mark it as simple
|
||||
@ -189,8 +190,12 @@ function createBabelHelpers(realm: Realm, global: ObjectValue | AbstractObjectVa
|
||||
function createMagicGlobalFunction(realm: Realm, global: ObjectValue | AbstractObjectValue, functionName: string) {
|
||||
global.$DefineOwnProperty(functionName, {
|
||||
value: new NativeFunctionValue(realm, functionName, functionName, 0, (context, args) => {
|
||||
let val = AbstractValue.createTemporalFromBuildFunction(realm, FunctionValue, args, _args =>
|
||||
t.callExpression(t.identifier(functionName), ((_args: any): Array<any>))
|
||||
let val = AbstractValue.createTemporalFromBuildFunction(
|
||||
realm,
|
||||
FunctionValue,
|
||||
args,
|
||||
_args => t.callExpression(t.identifier(functionName), ((_args: any): Array<any>)),
|
||||
{ skipInvariant: true, isPure: true }
|
||||
);
|
||||
invariant(val instanceof AbstractValue);
|
||||
return val;
|
||||
@ -218,11 +223,16 @@ function createBootloader(realm: Realm, global: ObjectValue | AbstractObjectValu
|
||||
|
||||
let loadModules = new NativeFunctionValue(realm, "loadModules", "loadModules", 1, (context, args) => {
|
||||
invariant(context.$Realm.generator);
|
||||
let val = AbstractValue.createTemporalFromBuildFunction(realm, FunctionValue, args, _args =>
|
||||
t.callExpression(
|
||||
t.memberExpression(t.identifier("Bootloader"), t.identifier("loadModules")),
|
||||
((_args: any): Array<any>)
|
||||
)
|
||||
let val = AbstractValue.createTemporalFromBuildFunction(
|
||||
realm,
|
||||
FunctionValue,
|
||||
args,
|
||||
_args =>
|
||||
t.callExpression(
|
||||
t.memberExpression(t.identifier("Bootloader"), t.identifier("loadModules")),
|
||||
((_args: any): Array<any>)
|
||||
),
|
||||
{ skipInvariant: true }
|
||||
);
|
||||
invariant(val instanceof AbstractValue);
|
||||
return val;
|
||||
|
30
src/intrinsics/fb-www/react-mocks.js
vendored
30
src/intrinsics/fb-www/react-mocks.js
vendored
@ -536,16 +536,19 @@ export function createMockReact(realm: Realm, reactRequireName: string): ObjectV
|
||||
realm,
|
||||
ObjectValue,
|
||||
[funcValue, defaultValue],
|
||||
([methodNode, defaultValueNode]) => {
|
||||
return t.callExpression(methodNode, [defaultValueNode]);
|
||||
}
|
||||
([methodNode, defaultValueNode]) => t.callExpression(methodNode, [defaultValueNode]),
|
||||
{ skipInvariant: true, isPure: true }
|
||||
);
|
||||
invariant(consumer instanceof AbstractObjectValue);
|
||||
consumer.values = new ValuesDomain(new Set([consumerObject]));
|
||||
|
||||
let provider = AbstractValue.createTemporalFromBuildFunction(realm, ObjectValue, [consumer], ([consumerNode]) => {
|
||||
return t.memberExpression(consumerNode, t.identifier("Provider"));
|
||||
});
|
||||
let provider = AbstractValue.createTemporalFromBuildFunction(
|
||||
realm,
|
||||
ObjectValue,
|
||||
[consumer],
|
||||
([consumerNode]) => t.memberExpression(consumerNode, t.identifier("Provider")),
|
||||
{ skipInvariant: true, isPure: true }
|
||||
);
|
||||
invariant(provider instanceof AbstractObjectValue);
|
||||
provider.values = new ValuesDomain(new Set([providerObject]));
|
||||
|
||||
@ -570,7 +573,8 @@ export function createMockReact(realm: Realm, reactRequireName: string): ObjectV
|
||||
[funcVal],
|
||||
([createRefNode]) => {
|
||||
return t.callExpression(createRefNode, []);
|
||||
}
|
||||
},
|
||||
{ skipInvariant: true, isPure: true }
|
||||
);
|
||||
invariant(createRef instanceof AbstractObjectValue);
|
||||
return createRef;
|
||||
@ -583,7 +587,8 @@ export function createMockReact(realm: Realm, reactRequireName: string): ObjectV
|
||||
[funcVal, func],
|
||||
([forwardRefNode, funcNode]) => {
|
||||
return t.callExpression(forwardRefNode, [funcNode]);
|
||||
}
|
||||
},
|
||||
{ skipInvariant: true, isPure: true }
|
||||
);
|
||||
invariant(forwardedRef instanceof AbstractObjectValue);
|
||||
realm.react.abstractHints.set(
|
||||
@ -611,7 +616,8 @@ export function createMockReactDOM(realm: Realm, reactDomRequireName: string): O
|
||||
[funcVal, ...args],
|
||||
([renderNode, ..._args]) => {
|
||||
return t.callExpression(renderNode, ((_args: any): Array<any>));
|
||||
}
|
||||
},
|
||||
{ skipInvariant: true, isPure: true }
|
||||
);
|
||||
invariant(reactDomMethod instanceof AbstractObjectValue);
|
||||
return reactDomMethod;
|
||||
@ -629,7 +635,8 @@ export function createMockReactDOM(realm: Realm, reactDomRequireName: string): O
|
||||
[funcVal, reactPortalValue, domNodeValue],
|
||||
([renderNode, ..._args]) => {
|
||||
return t.callExpression(renderNode, ((_args: any): Array<any>));
|
||||
}
|
||||
},
|
||||
{ skipInvariant: true, isPure: true }
|
||||
);
|
||||
invariant(reactDomMethod instanceof AbstractObjectValue);
|
||||
realm.react.abstractHints.set(
|
||||
@ -659,7 +666,8 @@ export function createMockReactDOMServer(realm: Realm, requireName: string): Obj
|
||||
[funcVal, ...args],
|
||||
([renderNode, ..._args]) => {
|
||||
return t.callExpression(renderNode, ((_args: any): Array<any>));
|
||||
}
|
||||
},
|
||||
{ skipInvariant: true, isPure: true }
|
||||
);
|
||||
invariant(reactDomMethod instanceof AbstractObjectValue);
|
||||
return reactDomMethod;
|
||||
|
@ -109,14 +109,20 @@ function createReactRelayContainer(
|
||||
// allowing us to reconstruct this ReactReact.createSomeContainer(...) again
|
||||
// we also pass a reactHint so the reconciler can properly deal with this
|
||||
addMockFunctionToObject(realm, reactRelay, relayRequireName, containerName, (funcValue, args) => {
|
||||
let value = AbstractValue.createTemporalFromBuildFunction(realm, FunctionValue, [reactRelay, ...args], _args => {
|
||||
let [reactRelayIdent, ...otherArgs] = _args;
|
||||
let value = AbstractValue.createTemporalFromBuildFunction(
|
||||
realm,
|
||||
FunctionValue,
|
||||
[reactRelay, ...args],
|
||||
_args => {
|
||||
let [reactRelayIdent, ...otherArgs] = _args;
|
||||
|
||||
return t.callExpression(
|
||||
t.memberExpression(reactRelayIdent, t.identifier(containerName)),
|
||||
((otherArgs: any): Array<any>)
|
||||
);
|
||||
});
|
||||
return t.callExpression(
|
||||
t.memberExpression(reactRelayIdent, t.identifier(containerName)),
|
||||
((otherArgs: any): Array<any>)
|
||||
);
|
||||
},
|
||||
{ skipInvariant: true, isPure: true }
|
||||
);
|
||||
invariant(value instanceof AbstractValue);
|
||||
let firstRenderContainerValue = Get(realm, reactRelayFirstRenderValue, containerName);
|
||||
let firstRenderValue = realm.intrinsics.undefined;
|
||||
|
@ -559,8 +559,12 @@ export function GetFromArrayWithWidenedNumericProperty(realm: Realm, arr: ArrayV
|
||||
invariant(proto instanceof ObjectValue && proto === realm.intrinsics.ArrayPrototype);
|
||||
if (typeof P === "string") {
|
||||
if (P === "length") {
|
||||
return AbstractValue.createTemporalFromBuildFunction(realm, NumberValue, [arr], ([o]) =>
|
||||
t.memberExpression(o, t.identifier("length"), false)
|
||||
return AbstractValue.createTemporalFromBuildFunction(
|
||||
realm,
|
||||
NumberValue,
|
||||
[arr],
|
||||
([o]) => t.memberExpression(o, t.identifier("length"), false),
|
||||
{ skipInvariant: true, isPure: true }
|
||||
);
|
||||
}
|
||||
let prototypeBinding = proto.properties.get(P);
|
||||
@ -573,7 +577,14 @@ export function GetFromArrayWithWidenedNumericProperty(realm: Realm, arr: ArrayV
|
||||
}
|
||||
}
|
||||
let prop = typeof P === "string" ? new StringValue(realm, P) : P;
|
||||
return AbstractValue.createTemporalFromBuildFunction(realm, Value, [arr, prop], ([o, p]) =>
|
||||
t.memberExpression(o, p, true)
|
||||
return AbstractValue.createTemporalFromBuildFunction(
|
||||
realm,
|
||||
Value,
|
||||
[arr, prop],
|
||||
([o, p]) => t.memberExpression(o, p, true),
|
||||
{
|
||||
skipInvariant: true,
|
||||
isPure: true,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -1177,8 +1177,12 @@ export class PropertiesImplementation {
|
||||
|
||||
invariant(realm.generator);
|
||||
let pname = realm.generator.getAsPropertyNameExpression(StringKey(P));
|
||||
let absVal = AbstractValue.createTemporalFromBuildFunction(realm, Value, [O._templateFor || O], ([node]) =>
|
||||
t.memberExpression(node, pname, !t.isIdentifier(pname))
|
||||
let absVal = AbstractValue.createTemporalFromBuildFunction(
|
||||
realm,
|
||||
Value,
|
||||
[O._templateFor || O],
|
||||
([node]) => t.memberExpression(node, pname, !t.isIdentifier(pname)),
|
||||
{ isPure: true }
|
||||
);
|
||||
// TODO: We can't be sure what the descriptor will be, but the value will be abstract.
|
||||
return { configurable: true, enumerable: true, value: absVal, writable: true };
|
||||
@ -1219,7 +1223,7 @@ export class PropertiesImplementation {
|
||||
([node]) => {
|
||||
return t.memberExpression(node, pname, !t.isIdentifier(pname));
|
||||
},
|
||||
{ skipInvariant: true }
|
||||
{ skipInvariant: true, isPure: true }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -372,7 +372,8 @@ export function applyGetDerivedStateFromProps(
|
||||
[objectAssign, newState, prevState, state],
|
||||
([methodNode, ..._args]) => {
|
||||
return t.callExpression(methodNode, ((_args: any): Array<any>));
|
||||
}
|
||||
},
|
||||
{ skipInvariant: true }
|
||||
);
|
||||
newState.makeSimple();
|
||||
newState.makePartial();
|
||||
@ -392,7 +393,8 @@ export function applyGetDerivedStateFromProps(
|
||||
[objectAssign, newState, prevState, state],
|
||||
([methodNode, ..._args]) => {
|
||||
return t.callExpression(methodNode, ((_args: any): Array<any>));
|
||||
}
|
||||
},
|
||||
{ skipInvariant: true }
|
||||
);
|
||||
newState.makeSimple();
|
||||
newState.makePartial();
|
||||
|
@ -880,7 +880,8 @@ export class Reconciler {
|
||||
[reactDomPortalFunc, resolvedReactPortalValue, domNodeValue],
|
||||
([renderNode, ..._args]) => {
|
||||
return t.callExpression(renderNode, ((_args: any): Array<any>));
|
||||
}
|
||||
},
|
||||
{ skipInvariant: true, isPure: true }
|
||||
);
|
||||
}
|
||||
return createPortalNode;
|
||||
|
@ -512,6 +512,7 @@ export default class AbstractObjectValue extends AbstractValue {
|
||||
},
|
||||
{
|
||||
skipInvariant: true,
|
||||
isPure: true,
|
||||
}
|
||||
);
|
||||
};
|
||||
@ -606,8 +607,12 @@ export default class AbstractObjectValue extends AbstractValue {
|
||||
if (!(P instanceof AbstractValue)) return this.$Get(P, Receiver);
|
||||
if (this.values.isTop()) {
|
||||
if (this.isSimpleObject() && this.isIntrinsic()) {
|
||||
return AbstractValue.createTemporalFromBuildFunction(this.$Realm, Value, [this, P], ([o, p]) =>
|
||||
t.memberExpression(o, p, true)
|
||||
return AbstractValue.createTemporalFromBuildFunction(
|
||||
this.$Realm,
|
||||
Value,
|
||||
[this, P],
|
||||
([o, p]) => t.memberExpression(o, p, true),
|
||||
{ skipInvariant: true, isPure: true }
|
||||
);
|
||||
}
|
||||
if (this.$Realm.isInPureScope()) {
|
||||
@ -622,8 +627,12 @@ export default class AbstractObjectValue extends AbstractValue {
|
||||
Havoc.value(this.$Realm, Receiver);
|
||||
// Coercion can only have effects on anything reachable from the key.
|
||||
Havoc.value(this.$Realm, P);
|
||||
return AbstractValue.createTemporalFromBuildFunction(this.$Realm, Value, [Receiver, P], ([o, p]) =>
|
||||
t.memberExpression(o, p, true)
|
||||
return AbstractValue.createTemporalFromBuildFunction(
|
||||
this.$Realm,
|
||||
Value,
|
||||
[Receiver, P],
|
||||
([o, p]) => t.memberExpression(o, p, true),
|
||||
{ skipInvariant: true, isPure: true }
|
||||
);
|
||||
}
|
||||
let error = new CompilerDiagnostic(
|
||||
|
@ -562,8 +562,8 @@ export default class ObjectValue extends ConcreteValue {
|
||||
let template = new ObjectValue(this.$Realm, this.$Realm.intrinsics.ObjectPrototype);
|
||||
this.copyKeys(this.$OwnPropertyKeys(), this, template);
|
||||
let result = AbstractValue.createTemporalFromBuildFunction(this.$Realm, ObjectValue, [template], ([x]) => x, {
|
||||
isPure: true,
|
||||
skipInvariant: true,
|
||||
isPure: true,
|
||||
});
|
||||
invariant(result instanceof AbstractObjectValue);
|
||||
result.values = new ValuesDomain(template);
|
||||
@ -755,8 +755,12 @@ export default class ObjectValue extends ConcreteValue {
|
||||
// this name on other parts of the prototype chain.
|
||||
// TODO #1675: A fix to 1675 needs to take this into account.
|
||||
Havoc.value(this.$Realm, Receiver);
|
||||
return AbstractValue.createTemporalFromBuildFunction(this.$Realm, Value, [Receiver, P], ([o, p]) =>
|
||||
t.memberExpression(o, p, true)
|
||||
return AbstractValue.createTemporalFromBuildFunction(
|
||||
this.$Realm,
|
||||
Value,
|
||||
[Receiver, P],
|
||||
([o, p]) => t.memberExpression(o, p, true),
|
||||
{ skipInvariant: true, isPure: true }
|
||||
);
|
||||
} else {
|
||||
let error = new CompilerDiagnostic(
|
||||
@ -779,14 +783,22 @@ export default class ObjectValue extends ConcreteValue {
|
||||
if (this.isPartialObject()) {
|
||||
if (isWidenedValue(P)) {
|
||||
// TODO #1678: Use a snapshot or havoc this object.
|
||||
return AbstractValue.createTemporalFromBuildFunction(this.$Realm, Value, [this, P], ([o, p]) =>
|
||||
t.memberExpression(o, p, true)
|
||||
return AbstractValue.createTemporalFromBuildFunction(
|
||||
this.$Realm,
|
||||
Value,
|
||||
[this, P],
|
||||
([o, p]) => t.memberExpression(o, p, true),
|
||||
{ skipInvariant: true, isPure: true }
|
||||
);
|
||||
}
|
||||
result = AbstractValue.createFromType(this.$Realm, Value, "sentinel member expression", [this, P]);
|
||||
} else {
|
||||
result = AbstractValue.createTemporalFromBuildFunction(this.$Realm, Value, [this, P], ([o, p]) =>
|
||||
t.memberExpression(o, p, true)
|
||||
result = AbstractValue.createTemporalFromBuildFunction(
|
||||
this.$Realm,
|
||||
Value,
|
||||
[this, P],
|
||||
([o, p]) => t.memberExpression(o, p, true),
|
||||
{ skipInvariant: true, isPure: true }
|
||||
);
|
||||
}
|
||||
|
||||
@ -830,9 +842,13 @@ export default class ObjectValue extends ConcreteValue {
|
||||
let pNumber = +pName;
|
||||
if (pName === pNumber + "") propName = new NumberValue(this.$Realm, pNumber);
|
||||
}
|
||||
return AbstractValue.createTemporalFromBuildFunction(this.$Realm, absVal.getType(), [ob, propName], ([o, p]) => {
|
||||
return t.memberExpression(o, p, true);
|
||||
});
|
||||
return AbstractValue.createTemporalFromBuildFunction(
|
||||
this.$Realm,
|
||||
absVal.getType(),
|
||||
[ob, propName],
|
||||
([o, p]) => t.memberExpression(o, p, true),
|
||||
{ skipInvariant: true, isPure: true }
|
||||
);
|
||||
}
|
||||
invariant(absVal.args.length === 3 && absVal.kind === "conditional");
|
||||
let generic_cond = absVal.args[0];
|
||||
@ -844,8 +860,12 @@ export default class ObjectValue extends ConcreteValue {
|
||||
if (arg2 instanceof AbstractValue) {
|
||||
if (arg2.kind === "template for prototype member expression") {
|
||||
let ob = arg2.args[0];
|
||||
arg2 = AbstractValue.createTemporalFromBuildFunction(this.$Realm, absVal.getType(), [ob, propName], ([o, p]) =>
|
||||
t.memberExpression(o, p, true)
|
||||
arg2 = AbstractValue.createTemporalFromBuildFunction(
|
||||
this.$Realm,
|
||||
absVal.getType(),
|
||||
[ob, propName],
|
||||
([o, p]) => t.memberExpression(o, p, true),
|
||||
{ skipInvariant: true, isPure: true }
|
||||
);
|
||||
} else if (arg2.args.length === 3) {
|
||||
arg2 = this.specializeJoin(arg2, propName);
|
||||
|
13
test/serializer/additional-functions/DeadCodeCheck.js
Normal file
13
test/serializer/additional-functions/DeadCodeCheck.js
Normal file
@ -0,0 +1,13 @@
|
||||
// does not contain:x.thisShouldNotAppear
|
||||
|
||||
function fn(x) {
|
||||
var a = x.thisShouldNotAppear;
|
||||
|
||||
return 10;
|
||||
}
|
||||
|
||||
global.__optimize && __optimize(fn);
|
||||
|
||||
inspect = function() {
|
||||
return fn({});
|
||||
};
|
@ -502,7 +502,7 @@ global.result = __evaluatePureFunction(() => {
|
||||
global.__optimize && __optimize(Main);
|
||||
|
||||
global.inspect = function() {
|
||||
return Main({});
|
||||
return Main({}, {});
|
||||
};
|
||||
|
||||
return Main;
|
||||
|
Loading…
Reference in New Issue
Block a user