mirror of
https://github.com/facebookarchive/prepack.git
synced 2024-08-18 02:50:34 +03:00
Unify logic for checking for intrinsic objects that have been derived (#2581)
Summary: Release notes: none This PR cleans up some of the `onArrayWithWidenedNumericProperty` logic, making it more generic for cases where we want to use concrete derived object values. Furthermore, it strengthens the validation process by checking for existence of `isScopedTemplate` on the internal object. Pull Request resolved: https://github.com/facebook/prepack/pull/2581 Differential Revision: D10141954 Pulled By: trueadm fbshipit-source-id: 8de828080b8a41357830cdbf7e49359512bc7244
This commit is contained in:
parent
ed784d6899
commit
5fc6feeeb2
@ -305,7 +305,7 @@ function InternalCloneObject(realm: Realm, val: ObjectValue): ObjectValue {
|
||||
}
|
||||
if (val.isPartialObject()) clone.makePartial();
|
||||
if (val.isSimpleObject()) clone.makeSimple();
|
||||
clone._isScopedTemplate = true; // because this object doesn't exist ahead of time, and the visitor would otherwise declare it in the common scope
|
||||
clone.isScopedTemplate = true; // because this object doesn't exist ahead of time, and the visitor would otherwise declare it in the common scope
|
||||
return clone;
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,6 @@
|
||||
|
||||
import {
|
||||
AbstractValue,
|
||||
ArrayValue,
|
||||
BoundFunctionValue,
|
||||
FunctionValue,
|
||||
ObjectValue,
|
||||
@ -38,9 +37,9 @@ type EmitterDependenciesVisitorCallbacks<T> = {
|
||||
// Callback invoked whenever a dependency is visited that is an abstract value with an identifier.
|
||||
// A return value that is not undefined indicates that the visitor should stop, and return the value as the overall result.
|
||||
onAbstractValueWithIdentifier?: AbstractValue => void | T,
|
||||
// Callback invoked whenever a dependency is visited that is an array value with a widened numeric property.
|
||||
// Callback invoked whenever a dependency is visited that is an intrinsic object that was derived
|
||||
// A return value that is not undefined indicates that the visitor should stop, and return the value as the overall result.
|
||||
onArrayWithWidenedNumericProperty?: ArrayValue => void | T,
|
||||
onIntrinsicDerivedObject?: ObjectValue => void | T,
|
||||
};
|
||||
|
||||
// The emitter keeps track of a stack of what's currently being emitted.
|
||||
@ -78,7 +77,7 @@ export class Emitter {
|
||||
this._activeValues = new Set();
|
||||
this._activeGeneratorStack = [this._mainBody];
|
||||
this._finalized = false;
|
||||
let mustWaitForValue = (val: AbstractValue | ArrayValue) => {
|
||||
let mustWaitForValue = (val: AbstractValue | ObjectValue) => {
|
||||
if (this.cannotDeclare()) return false;
|
||||
if (this.hasBeenDeclared(val)) return false;
|
||||
let activeOptimizedFunction = this.getActiveOptimizedFunction();
|
||||
@ -95,7 +94,7 @@ export class Emitter {
|
||||
},
|
||||
onAbstractValueWithIdentifier: val =>
|
||||
derivedIds.has(val.getIdentifier()) && mustWaitForValue(val) ? val : undefined,
|
||||
onArrayWithWidenedNumericProperty: val => (mustWaitForValue(val) ? val : undefined),
|
||||
onIntrinsicDerivedObject: val => (mustWaitForValue(val) ? val : undefined),
|
||||
};
|
||||
this._conditionalFeasibility = conditionalFeasibility;
|
||||
}
|
||||
@ -351,10 +350,8 @@ export class Emitter {
|
||||
result = recurse(val.$Description);
|
||||
if (result !== undefined) return result;
|
||||
}
|
||||
} else if (val instanceof ArrayValue && ArrayValue.isIntrinsicAndHasWidenedNumericProperty(val)) {
|
||||
result = callbacks.onArrayWithWidenedNumericProperty
|
||||
? callbacks.onArrayWithWidenedNumericProperty(val)
|
||||
: undefined;
|
||||
} else if (val instanceof ObjectValue && ObjectValue.isIntrinsicDerivedObject(val)) {
|
||||
result = callbacks.onIntrinsicDerivedObject ? callbacks.onIntrinsicDerivedObject(val) : undefined;
|
||||
if (result !== undefined) return result;
|
||||
} else if (val instanceof ObjectValue) {
|
||||
let kind = val.getKind();
|
||||
|
@ -940,11 +940,9 @@ export class ResidualHeapSerializer {
|
||||
// which is related to one of the scopes this value is used by.
|
||||
let notYetDoneBodies = new Set();
|
||||
this.emitter.dependenciesVisitor(val, {
|
||||
onArrayWithWidenedNumericProperty: dependency => {
|
||||
onIntrinsicDerivedObject: dependency => {
|
||||
if (trace) {
|
||||
console.log(
|
||||
` depending on array with widened numeric properties and an identifier ${dependency.intrinsicName || "?"}`
|
||||
);
|
||||
console.log(` depending on intrinsic derived object and an identifier ${dependency.intrinsicName || "?"}`);
|
||||
}
|
||||
invariant(
|
||||
optimizedFunctionRoot === undefined || !!this.emitter.getActiveOptimizedFunction(),
|
||||
|
@ -1087,7 +1087,7 @@ export class ResidualHeapVisitor {
|
||||
} else if (val.isIntrinsic()) {
|
||||
// All intrinsic values exist from the beginning of time...
|
||||
// ...except for a few that come into existence as templates for abstract objects via executable code.
|
||||
if (val instanceof ObjectValue && val._isScopedTemplate) {
|
||||
if (val instanceof ObjectValue && val.isScopedTemplate) {
|
||||
this.preProcessValue(val);
|
||||
this.postProcessValue(val);
|
||||
} else
|
||||
|
@ -1067,7 +1067,7 @@ export class Generator {
|
||||
let id = this.preludeGenerator.nameGenerator.generate("derived");
|
||||
let value = buildValue(id);
|
||||
value.intrinsicNameGenerated = true;
|
||||
value._isScopedTemplate = true; // because this object doesn't exist ahead of time, and the visitor would otherwise declare it in the common scope
|
||||
value.isScopedTemplate = true; // because this object doesn't exist ahead of time, and the visitor would otherwise declare it in the common scope
|
||||
invariant(value.intrinsicName === id);
|
||||
this._addDerivedEntry({
|
||||
isPure: optionalArgs ? optionalArgs.isPure : undefined,
|
||||
|
@ -242,7 +242,8 @@ export default class ArrayValue extends ObjectValue {
|
||||
}
|
||||
|
||||
static isIntrinsicAndHasWidenedNumericProperty(obj: Value): boolean {
|
||||
if (obj instanceof ArrayValue && obj.intrinsicName !== undefined) {
|
||||
if (obj instanceof ArrayValue && obj.intrinsicName !== undefined && obj.isScopedTemplate !== undefined) {
|
||||
invariant(ObjectValue.isIntrinsicDerivedObject(obj));
|
||||
const prop = obj.unknownProperty;
|
||||
if (prop !== undefined && prop.descriptor !== undefined) {
|
||||
const desc = prop.descriptor.throwIfNotConcrete(obj.$Realm);
|
||||
|
@ -279,7 +279,7 @@ export default class ObjectValue extends ConcreteValue {
|
||||
|
||||
// Specifies whether the object is a template that needs to be created in a scope
|
||||
// If set, this happened during object initialization and the value is never changed again, so not tracked.
|
||||
_isScopedTemplate: void | true;
|
||||
isScopedTemplate: void | true;
|
||||
|
||||
// If true, then unknown properties should return transitively simple abstract object values
|
||||
_simplicityIsTransitive: AbstractValue | BooleanValue;
|
||||
@ -718,4 +718,8 @@ export default class ObjectValue extends ConcreteValue {
|
||||
if (pb.internalSlot && typeof pb.key === "string" && pb.key[0] === "_") return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static isIntrinsicDerivedObject(obj: Value): boolean {
|
||||
return obj instanceof ObjectValue && obj.intrinsicName !== undefined && obj.isScopedTemplate !== undefined;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user