mirror of
https://github.com/facebookarchive/prepack.git
synced 2024-10-26 23:32:02 +03:00
Back out "[prepack][PR] Support call expressions where the base might be an abstract conditional"
Summary: It caused some regressions but we're not sure why. Need to increase test coverage first. Reverting for now. Reviewed By: trueadm Differential Revision: D8205062 fbshipit-source-id: fe03f8ea9e8c3d85b3ce96912c5135019f407a56
This commit is contained in:
parent
24181252fe
commit
f55285012e
@ -13,17 +13,11 @@ import { CompilerDiagnostic, FatalError } from "../errors.js";
|
||||
import { AbruptCompletion, PossiblyNormalCompletion } from "../completions.js";
|
||||
import type { Realm } from "../realm.js";
|
||||
import { Effects } from "../realm.js";
|
||||
import { type LexicalEnvironment, type BaseValue, mightBecomeAnObject } from "../environment.js";
|
||||
import type { LexicalEnvironment } from "../environment.js";
|
||||
import { EnvironmentRecord } from "../environment.js";
|
||||
import { TypesDomain, ValuesDomain } from "../domains/index.js";
|
||||
import {
|
||||
AbstractValue,
|
||||
AbstractObjectValue,
|
||||
ConcreteValue,
|
||||
FunctionValue,
|
||||
ObjectValue,
|
||||
Value,
|
||||
} from "../values/index.js";
|
||||
import { Value } from "../values/index.js";
|
||||
import { AbstractValue, AbstractObjectValue, BooleanValue, ConcreteValue, FunctionValue } from "../values/index.js";
|
||||
import { Reference } from "../environment.js";
|
||||
import { Environment, Functions, Havoc, Join } from "../singletons.js";
|
||||
import {
|
||||
@ -53,103 +47,28 @@ export default function(
|
||||
|
||||
// 1. Let ref be the result of evaluating MemberExpression.
|
||||
let ref = env.evaluate(ast.callee, strictCode);
|
||||
|
||||
return evaluateReference(ref, ast, strictCode, env, realm);
|
||||
}
|
||||
|
||||
function evaluateReference(
|
||||
ref: Reference | Value,
|
||||
ast: BabelNodeCallExpression,
|
||||
strictCode: boolean,
|
||||
env: LexicalEnvironment,
|
||||
realm: Realm
|
||||
): Value {
|
||||
if (
|
||||
ref instanceof Reference &&
|
||||
ref.base instanceof AbstractValue &&
|
||||
ref.base.mightNotBeObject() &&
|
||||
realm.isInPureScope()
|
||||
) {
|
||||
let base = ref.base;
|
||||
if (base.kind === "conditional") {
|
||||
return evaluateConditionalReferenceBase(ref, ast, strictCode, env, realm);
|
||||
}
|
||||
let dummy = ref.base;
|
||||
// avoid explicitly converting ref.base to an object because that will create a generator entry
|
||||
// leading to two object allocations rather than one.
|
||||
return realm.evaluateWithPossibleThrowCompletion(
|
||||
() => generateRuntimeCall(ref, base, ast, strictCode, env, realm),
|
||||
() => generateRuntimeCall(ref, dummy, ast, strictCode, env, realm),
|
||||
TypesDomain.topVal,
|
||||
ValuesDomain.topVal
|
||||
);
|
||||
}
|
||||
|
||||
// 2. Let func be ? GetValue(ref).
|
||||
let func = Environment.GetValue(realm, ref);
|
||||
|
||||
return EvaluateCall(ref, func, ast, strictCode, env, realm);
|
||||
}
|
||||
|
||||
function evaluateConditionalReferenceBase(
|
||||
ref: Reference,
|
||||
ast: BabelNodeCallExpression,
|
||||
strictCode: boolean,
|
||||
env: LexicalEnvironment,
|
||||
realm: Realm
|
||||
): Value {
|
||||
let base = ref.base;
|
||||
invariant(base instanceof AbstractValue);
|
||||
invariant(base.kind === "conditional", "evaluateConditionalReferenceBase expects an abstract conditional");
|
||||
let [condValue, consequentVal, alternateVal] = base.args;
|
||||
invariant(condValue instanceof AbstractValue);
|
||||
|
||||
return realm.evaluateWithAbstractConditional(
|
||||
condValue,
|
||||
() => {
|
||||
return realm.evaluateForEffects(
|
||||
() => {
|
||||
if (
|
||||
consequentVal instanceof AbstractObjectValue ||
|
||||
consequentVal instanceof ObjectValue ||
|
||||
mightBecomeAnObject(consequentVal)
|
||||
) {
|
||||
let consequentRef = new Reference(
|
||||
((consequentVal: any): BaseValue),
|
||||
ref.referencedName,
|
||||
ref.strict,
|
||||
ref.thisValue
|
||||
);
|
||||
return evaluateReference(consequentRef, ast, strictCode, env, realm);
|
||||
}
|
||||
return consequentVal;
|
||||
},
|
||||
null,
|
||||
"evaluateConditionalReferenceBase consequent"
|
||||
);
|
||||
},
|
||||
() => {
|
||||
return realm.evaluateForEffects(
|
||||
() => {
|
||||
if (
|
||||
alternateVal instanceof AbstractObjectValue ||
|
||||
alternateVal instanceof ObjectValue ||
|
||||
mightBecomeAnObject(alternateVal)
|
||||
) {
|
||||
let alternateRef = new Reference(
|
||||
((alternateVal: any): BaseValue),
|
||||
ref.referencedName,
|
||||
ref.strict,
|
||||
ref.thisValue
|
||||
);
|
||||
return evaluateReference(alternateRef, ast, strictCode, env, realm);
|
||||
}
|
||||
return alternateVal;
|
||||
},
|
||||
null,
|
||||
"evaluateConditionalReferenceBase alternate"
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function callBothFunctionsAndJoinTheirEffects(
|
||||
args: Array<Value>,
|
||||
ast: BabelNodeCallExpression,
|
||||
@ -158,7 +77,7 @@ function callBothFunctionsAndJoinTheirEffects(
|
||||
realm: Realm
|
||||
): Value {
|
||||
let [cond, func1, func2] = args;
|
||||
invariant(cond instanceof AbstractValue);
|
||||
invariant(cond instanceof AbstractValue && cond.getType() === BooleanValue);
|
||||
invariant(Value.isTypeCompatibleWith(func1.getType(), FunctionValue));
|
||||
invariant(Value.isTypeCompatibleWith(func2.getType(), FunctionValue));
|
||||
|
||||
|
@ -11,13 +11,7 @@
|
||||
|
||||
import type { PropertyKeyValue } from "../types.js";
|
||||
import type { ECMAScriptFunctionValue } from "../values/index.js";
|
||||
import {
|
||||
EnvironmentRecord,
|
||||
GlobalEnvironmentRecord,
|
||||
LexicalEnvironment,
|
||||
mightBecomeAnObject,
|
||||
Reference,
|
||||
} from "../environment.js";
|
||||
import { LexicalEnvironment, Reference, EnvironmentRecord, GlobalEnvironmentRecord } from "../environment.js";
|
||||
import { FatalError } from "../errors.js";
|
||||
import { Realm, ExecutionContext } from "../realm.js";
|
||||
import Value from "../values/Value.js";
|
||||
@ -287,29 +281,22 @@ export function OrdinaryCallBindThis(
|
||||
return envRec.BindThisValue(thisValue);
|
||||
}
|
||||
|
||||
function callNativeFunctionValue(
|
||||
// ECMA262 9.2.1.3
|
||||
export function OrdinaryCallEvaluateBody(
|
||||
realm: Realm,
|
||||
f: NativeFunctionValue,
|
||||
f: ECMAScriptFunctionValue,
|
||||
argumentsList: Array<Value>
|
||||
): Value | AbruptCompletion {
|
||||
let env = realm.getRunningContext().lexicalEnvironment;
|
||||
let context = env.environmentRecord.GetThisBinding();
|
||||
): Reference | Value | AbruptCompletion {
|
||||
if (f instanceof NativeFunctionValue) {
|
||||
let env = realm.getRunningContext().lexicalEnvironment;
|
||||
let context = env.environmentRecord.GetThisBinding();
|
||||
|
||||
const functionCall = contextVal => {
|
||||
if (context instanceof AbstractObjectValue && context.kind === "conditional") {
|
||||
// TODO: we should handle this case and split the calls up
|
||||
// on the conditional, as it may yield better results
|
||||
}
|
||||
try {
|
||||
invariant(
|
||||
contextVal instanceof AbstractObjectValue ||
|
||||
contextVal instanceof ObjectValue ||
|
||||
contextVal instanceof NullValue ||
|
||||
contextVal instanceof UndefinedValue ||
|
||||
mightBecomeAnObject(contextVal)
|
||||
);
|
||||
return f.callCallback(
|
||||
// this is to get around Flow not understand the above invariant
|
||||
((contextVal: any): AbstractObjectValue | ObjectValue | NullValue | UndefinedValue),
|
||||
argumentsList,
|
||||
env.environmentRecord.$NewTarget
|
||||
);
|
||||
return f.callCallback(context, argumentsList, env.environmentRecord.$NewTarget);
|
||||
} catch (err) {
|
||||
if (err instanceof AbruptCompletion) {
|
||||
return err;
|
||||
@ -319,33 +306,6 @@ function callNativeFunctionValue(
|
||||
throw new FatalError(err);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (context instanceof AbstractObjectValue && context.kind === "conditional") {
|
||||
let [condValue, consequentVal, alternateVal] = context.args;
|
||||
invariant(condValue instanceof AbstractValue);
|
||||
|
||||
return realm.evaluateWithAbstractConditional(
|
||||
condValue,
|
||||
() => {
|
||||
return realm.evaluateForEffects(() => functionCall(consequentVal), null, "callNativeFunctionValue consequent");
|
||||
},
|
||||
() => {
|
||||
return realm.evaluateForEffects(() => functionCall(alternateVal), null, "callNativeFunctionValue alternate");
|
||||
}
|
||||
);
|
||||
}
|
||||
return functionCall(context);
|
||||
}
|
||||
|
||||
// ECMA262 9.2.1.3
|
||||
export function OrdinaryCallEvaluateBody(
|
||||
realm: Realm,
|
||||
f: ECMAScriptFunctionValue,
|
||||
argumentsList: Array<Value>
|
||||
): Reference | Value | AbruptCompletion {
|
||||
if (f instanceof NativeFunctionValue) {
|
||||
return callNativeFunctionValue(realm, f, argumentsList);
|
||||
} else {
|
||||
invariant(f instanceof ECMAScriptSourceFunctionValue);
|
||||
let F = f;
|
||||
|
@ -1,16 +0,0 @@
|
||||
// does contain:1-2-3
|
||||
|
||||
function fn(a) {
|
||||
var array = (a === null ? [1,2,3] : [4,5,6]);
|
||||
|
||||
return array.join("-");
|
||||
}
|
||||
|
||||
global.__optimize && __optimize(fn);
|
||||
|
||||
inspect = function() {
|
||||
return JSON.stringify({
|
||||
a: fn(null),
|
||||
b: fn(true),
|
||||
});
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
function fn(a, b) {
|
||||
var array = (a === null ? b : [4,5,6]);
|
||||
|
||||
return array.join("-");
|
||||
}
|
||||
|
||||
global.__optimize && __optimize(fn);
|
||||
|
||||
inspect = function() {
|
||||
return JSON.stringify({
|
||||
a: fn(null, [1,2,3]),
|
||||
b: fn(true, [1,2,3]),
|
||||
});
|
||||
}
|
Loading…
Reference in New Issue
Block a user