mirror of
https://github.com/facebookarchive/prepack.git
synced 2024-08-17 10:30:32 +03:00
Deduplicate object creation code in a non-branched setting (#2302)
Summary: This pull request breaks out the first part of #2185, which deduplicates object creation when leaking is unconditional to begin with. No changes are made to how leaking works. Only to how leak information is used by the serializer and visitor. Pull Request resolved: https://github.com/facebook/prepack/pull/2302 Differential Revision: D8997109 Pulled By: sb98052 fbshipit-source-id: e0ea2e7ea574a9f2be71b70be289831c7f797d9d
This commit is contained in:
parent
b0fe89e863
commit
3bcd3fb4ee
@ -324,11 +324,20 @@ export class ResidualHeapSerializer {
|
||||
);
|
||||
}
|
||||
|
||||
// TODO #2259: Make deduplication in the face of leaking work for custom accessors
|
||||
let isCertainlyLeaked = !obj.mightNotBeHavocedObject();
|
||||
let shouldDropAsAssignedProp = (descriptor: Descriptor | void) =>
|
||||
isCertainlyLeaked && (descriptor !== undefined && (descriptor.get === undefined && descriptor.set === undefined));
|
||||
|
||||
// inject properties
|
||||
for (let [key, propertyBinding] of properties) {
|
||||
invariant(propertyBinding);
|
||||
|
||||
if (propertyBinding.pathNode !== undefined) continue; // Property is assigned to inside loop
|
||||
let desc = propertyBinding.descriptor;
|
||||
|
||||
if (shouldDropAsAssignedProp(desc)) continue;
|
||||
|
||||
if (desc === undefined) continue; //deleted
|
||||
if (this.residualHeapInspector.canIgnoreProperty(obj, key)) continue;
|
||||
invariant(desc !== undefined);
|
||||
@ -1694,13 +1703,25 @@ export class ResidualHeapSerializer {
|
||||
let remainingProperties = new Map(val.properties);
|
||||
const dummyProperties = new Set();
|
||||
let props = [];
|
||||
let isCertainlyLeaked = !val.mightNotBeHavocedObject();
|
||||
|
||||
// TODO #2259: Make deduplication in the face of leaking work for custom accessors
|
||||
let shouldDropAsAssignedProp = (descriptor: Descriptor | void) =>
|
||||
isCertainlyLeaked && (descriptor !== undefined && (descriptor.get === undefined && descriptor.set === undefined));
|
||||
|
||||
if (val.temporalAlias !== undefined) {
|
||||
return t.objectExpression(props);
|
||||
} else {
|
||||
for (let [key, propertyBinding] of val.properties) {
|
||||
if (propertyBinding.descriptor !== undefined && shouldDropAsAssignedProp(propertyBinding.descriptor)) {
|
||||
remainingProperties.delete(key);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (propertyBinding.pathNode !== undefined) continue; // written to inside loop
|
||||
let descriptor = propertyBinding.descriptor;
|
||||
if (descriptor === undefined || descriptor.value === undefined) continue; // deleted
|
||||
|
||||
let serializedKey = getAsPropertyNameExpression(key);
|
||||
if (this._canEmbedProperty(val, key, descriptor)) {
|
||||
let propValue = descriptor.value;
|
||||
@ -1727,6 +1748,7 @@ export class ResidualHeapSerializer {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this._emitObjectProperties(
|
||||
val,
|
||||
remainingProperties,
|
||||
@ -1734,6 +1756,7 @@ export class ResidualHeapSerializer {
|
||||
dummyProperties,
|
||||
skipPrototype
|
||||
);
|
||||
|
||||
return t.objectExpression(props);
|
||||
}
|
||||
|
||||
|
@ -287,6 +287,7 @@ export class ResidualHeapVisitor {
|
||||
}
|
||||
|
||||
visitObjectProperties(obj: ObjectValue, kind?: ObjectKind): void {
|
||||
// In non-instant render mode, properties of leaked objects are generated via assignments
|
||||
let { skipPrototype, constructor } = getObjectPrototypeMetadata(this.realm, obj);
|
||||
if (obj.temporalAlias !== undefined) return;
|
||||
|
||||
@ -313,6 +314,15 @@ export class ResidualHeapVisitor {
|
||||
continue;
|
||||
}
|
||||
if (propertyBindingValue.pathNode !== undefined) continue; // property is written to inside a loop
|
||||
|
||||
// Leaked object. Properties are set via assignments
|
||||
// TODO #2259: Make deduplication in the face of leaking work for custom accessors
|
||||
if (
|
||||
!obj.mightNotBeHavocedObject() &&
|
||||
(descriptor !== undefined && (descriptor.get === undefined && descriptor.set === undefined))
|
||||
)
|
||||
continue;
|
||||
|
||||
invariant(propertyBindingValue);
|
||||
this.visitObjectProperty(propertyBindingValue);
|
||||
}
|
||||
|
@ -0,0 +1,22 @@
|
||||
(function() {
|
||||
function f(c, g) {
|
||||
let x = 23;
|
||||
let y = 0;
|
||||
if (c) {
|
||||
x = Date.now();
|
||||
function h() {
|
||||
y = x;
|
||||
x++;
|
||||
}
|
||||
g(h);
|
||||
return x - y;
|
||||
} else {
|
||||
x = Date.now();
|
||||
return x - y;
|
||||
}
|
||||
}
|
||||
global.__optimize && __optimize(f);
|
||||
global.inspect = function() {
|
||||
return f(true, g => g());
|
||||
};
|
||||
})();
|
@ -0,0 +1,17 @@
|
||||
(function() {
|
||||
function f(g, c) {
|
||||
let o = { foo: 42 };
|
||||
if (c) {
|
||||
g(o);
|
||||
} else {
|
||||
o.foo = 2;
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
global.__optimize && __optimize(f);
|
||||
inspect = function() {
|
||||
return JSON.stringify(f(o => o, false));
|
||||
};
|
||||
})();
|
@ -0,0 +1,17 @@
|
||||
(function() {
|
||||
function f(g, c) {
|
||||
let o = { foo: 42 };
|
||||
if (c) {
|
||||
g(o);
|
||||
} else {
|
||||
o.x = 1;
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
global.__optimize && __optimize(f);
|
||||
inspect = function() {
|
||||
return JSON.stringify(f(o => o, false));
|
||||
};
|
||||
})();
|
17
test/serializer/optimized-functions/LeakObjectWithSetter.js
Normal file
17
test/serializer/optimized-functions/LeakObjectWithSetter.js
Normal file
@ -0,0 +1,17 @@
|
||||
(function() {
|
||||
function f(g) {
|
||||
let o = {
|
||||
foo: 1,
|
||||
set x(v) {
|
||||
this.foo += 1;
|
||||
},
|
||||
};
|
||||
g(o);
|
||||
return o;
|
||||
}
|
||||
|
||||
global.__optimize && __optimize(f);
|
||||
inspect = () => {
|
||||
JSON.stringify(f(o => o));
|
||||
};
|
||||
})();
|
@ -0,0 +1,17 @@
|
||||
function f(g, c) {
|
||||
let o = { foo: {} };
|
||||
o.__proto__ = {};
|
||||
|
||||
if (c) {
|
||||
g(o);
|
||||
} else {
|
||||
o.foo = { bar: 5 };
|
||||
g(o);
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
global.__optimize && __optimize(f);
|
||||
inspect = function() {
|
||||
return f(o => o);
|
||||
};
|
@ -0,0 +1,12 @@
|
||||
// Copies of 42:1
|
||||
function f(g) {
|
||||
var o = {};
|
||||
o.foo = 42;
|
||||
g(o);
|
||||
return o;
|
||||
}
|
||||
|
||||
global.__optimize && __optimize(f);
|
||||
inspect = function() {
|
||||
return f(o => o);
|
||||
};
|
Loading…
Reference in New Issue
Block a user