Consolidate {Property,Computed}Call into MethodCall

Now that we model the method resolution via a PropertyLoad or ComputedLoad, we 
don't need to distinguish between PropertyCall and ComputedCall. These two call 
variants are now combined into a single MethodCall variant.
This commit is contained in:
Joe Savona
2023-03-22 14:36:48 -07:00
parent 5f1bebbeae
commit 14c03b897f
23 changed files with 76 additions and 165 deletions
+7 -17
View File
@@ -935,23 +935,13 @@ function lowerExpression(
loc: GeneratedSource,
});
const args = lowerArguments(builder, expr.get("arguments"));
if (typeof memberExpr.property === "string") {
return {
kind: "PropertyCall",
receiver: memberExpr.object,
property: { ...propertyPlace },
args,
loc: exprLoc,
};
} else {
return {
kind: "ComputedCall",
receiver: memberExpr.object,
property: { ...propertyPlace },
args,
loc: exprLoc,
};
}
return {
kind: "MethodCall",
receiver: memberExpr.object,
property: { ...propertyPlace },
args,
loc: exprLoc,
};
} else {
const callee = lowerExpressionToTemporary(builder, calleePath);
const args = lowerArguments(builder, expr.get("arguments"));
+8 -16
View File
@@ -433,24 +433,23 @@ export type Phi = {
};
/**
* Forget currently does not handle PropertyCall / ComputedCall correctly in
* Forget currently does not handle MethodCall correctly in
* all cases. Specifically, we do not bind the receiver and method property
* before calling to args. Until we add a SequenceExpression to inline all
* instructions generated when lowering args, we have a limited representation
* with some constraints.
*
* Forget currently makes these assumptions (checked in codegen):
* - {@link PropertyCall.property} is a temporary produced by a PropertyLoad on {@link PropertyCall.receiver}
* - this is always true for PropertyCall, but property.object and receiver
* may be different for ComputedCalls
* - {@link PropertyCall.property} remains an rval (i.e. never promoted to a
* - {@link MethodCall.property} is a temporary produced by a PropertyLoad or ComputedLoad
* on {@link MethodCall.receiver}
* - {@link MethodCall.property} remains an rval (i.e. never promoted to a
* named identifier). We currently rely on this for codegen.
*
* Type inference does not currently guarantee that {@link PropertyCall.property}
* Type inference does not currently guarantee that {@link MethodCall.property}
* is a FunctionType.
*/
export type PropertyCall = {
kind: "PropertyCall";
export type MethodCall = {
kind: "MethodCall";
receiver: Place;
property: Place;
args: Array<Place | SpreadPattern>;
@@ -513,14 +512,7 @@ export type InstructionValue =
args: Array<Place | SpreadPattern>;
loc: SourceLocation;
}
| PropertyCall
| {
kind: "ComputedCall";
receiver: Place;
property: Place;
args: Array<Place | SpreadPattern>;
loc: SourceLocation;
}
| MethodCall
| {
kind: "UnaryExpression";
operator: string;
+2 -8
View File
@@ -268,18 +268,12 @@ export function printInstructionValue(instrValue: ReactiveValue): string {
.join(", ")})`;
break;
}
case "PropertyCall": {
value = `PropertyCall ${printPlace(instrValue.receiver)}.${printPlace(
case "MethodCall": {
value = `MethodCall ${printPlace(instrValue.receiver)}.${printPlace(
instrValue.property
)}(${instrValue.args.map((arg) => printPattern(arg)).join(", ")})`;
break;
}
case "ComputedCall": {
value = `ComputedCall ${printPlace(instrValue.receiver)}[${printPlace(
instrValue.property
)}](${instrValue.args.map((arg) => printPattern(arg)).join(", ")})`;
break;
}
case "JSXText":
case "Primitive": {
value = JSON.stringify(instrValue.value);
+2 -14
View File
@@ -55,13 +55,7 @@ export function* eachInstructionValueOperand(
yield instrValue.right;
break;
}
case "PropertyCall": {
yield instrValue.receiver;
yield instrValue.property;
yield* eachCallArgument(instrValue.args);
break;
}
case "ComputedCall": {
case "MethodCall": {
yield instrValue.receiver;
yield instrValue.property;
yield* eachCallArgument(instrValue.args);
@@ -356,13 +350,7 @@ export function mapInstructionOperands(
instrValue.args = mapCallArguments(instrValue.args, fn);
break;
}
case "PropertyCall": {
instrValue.receiver = fn(instrValue.receiver);
instrValue.property = fn(instrValue.property);
instrValue.args = mapCallArguments(instrValue.args, fn);
break;
}
case "ComputedCall": {
case "MethodCall": {
instrValue.receiver = fn(instrValue.receiver);
instrValue.property = fn(instrValue.property);
instrValue.args = mapCallArguments(instrValue.args, fn);
@@ -16,9 +16,9 @@ import {
IdentifierId,
InstructionValue,
isObjectType,
MethodCall,
Phi,
Place,
PropertyCall,
Type,
ValueKind,
} from "../HIR/HIR";
@@ -684,7 +684,7 @@ function inferBlock(
instr.lvalue.effect = Effect.Store;
continue;
}
case "PropertyCall": {
case "MethodCall": {
invariant(
state.isDefined(instrValue.receiver),
"[InferReferenceEffects] Internal error: receiver of PropertyCall should have been defined by corresponding PropertyLoad"
@@ -724,32 +724,6 @@ function inferBlock(
instr.lvalue.effect = Effect.Mutate;
continue;
}
case "ComputedCall": {
if (!state.isDefined(instrValue.receiver)) {
// TODO @josephsavona: improve handling of globals
const value: InstructionValue = {
kind: "Primitive",
loc: instrValue.loc,
value: undefined,
};
state.initialize(value, ValueKind.Frozen);
state.define(instrValue.receiver, value);
}
state.reference(instrValue.receiver, Effect.Mutate);
state.reference(instrValue.property, Effect.Read);
for (const arg of instrValue.args) {
if (arg.kind === "Identifier") {
state.reference(arg, Effect.Mutate);
} else {
state.reference(arg.place, Effect.Mutate);
}
}
state.initialize(instrValue, ValueKind.Mutable);
state.define(instr.lvalue, instrValue);
instr.lvalue.effect = Effect.Mutate;
continue;
}
case "PropertyStore": {
const effect =
state.kind(instrValue.object) === ValueKind.Context
@@ -965,7 +939,7 @@ function getFunctionCallSignature(
* @returns Inferred effects of function arguments
*/
function getFunctionCallEffects(
fn: PropertyCall,
fn: MethodCall,
sig: FunctionSignature,
defaultEffect: Effect
): Array<[Place, Effect]> {
@@ -192,10 +192,9 @@ function pruneableValue(value: InstructionValue, state: State): boolean {
}
case "CallExpression":
case "ComputedDelete":
case "ComputedCall":
case "ComputedStore":
case "PropertyDelete":
case "PropertyCall":
case "MethodCall":
case "PropertyStore": {
// Mutating instructions are not safe to prune.
// TODO: we could be more precise and make this conditional on whether
@@ -589,44 +589,20 @@ function codegenInstructionValue(
value = createCallExpression(instrValue.loc, callee, args);
break;
}
case "PropertyCall": {
case "MethodCall": {
const memberExpr = codegenPlace(cx, instrValue.property);
invariant(
t.isMemberExpression(memberExpr) ||
t.isOptionalMemberExpression(memberExpr),
"[Codegen] Internal error: PropertyCall::property must be an unpromoted + unmemoized MemberExpression."
);
invariant(
memberExpr.computed === false,
"[Codegen] Internal error: PropertyCall::property must be a non-computed MemberExpression."
"[Codegen] Internal error: MethodCall::property must be an unpromoted + unmemoized MemberExpression."
);
invariant(
t.isNodesEquivalent(
memberExpr.object,
codegenPlace(cx, instrValue.receiver)
),
"[Codegen] Internal error: Forget should always generate PropertyCall::property " +
"as a MemberExpression of PropertyCall::receiver"
);
const args = instrValue.args.map((arg) => codegenArgument(cx, arg));
value = createCallExpression(instrValue.loc, memberExpr, args);
break;
}
case "ComputedCall": {
const memberExpr = codegenPlace(cx, instrValue.property);
invariant(
t.isMemberExpression(memberExpr) ||
t.isOptionalMemberExpression(memberExpr),
"[Codegen] Internal error: ComputedCall::property must be an unpromoted + unmemoized MemberExpression, was %s.",
memberExpr.type
);
invariant(
t.isNodesEquivalent(
memberExpr.object,
codegenPlace(cx, instrValue.receiver)
),
"[Codegen] Internal error: Forget should always generate ComputedCall::property " +
"as a MemberExpression of ComputedCall::receiver"
"[Codegen] Internal error: Forget should always generate MethodCall::property " +
"as a MemberExpression of MethodCall::receiver"
);
const args = instrValue.args.map((arg) => codegenArgument(cx, arg));
value = createCallExpression(instrValue.loc, memberExpr, args);
@@ -134,7 +134,7 @@ export function inferReactiveScopeVariables(fn: HIRFunction): void {
) {
operands.push(instr.value.value.identifier);
}
} else if (instr.value.kind === "ComputedCall") {
} else if (instr.value.kind === "MethodCall") {
for (const operand of eachInstructionOperand(instr)) {
if (
isMutable(instr, operand) &&
@@ -235,8 +235,7 @@ function mayAllocate(value: InstructionValue): boolean {
case "Primitive": {
return false;
}
case "PropertyCall":
case "ComputedCall":
case "MethodCall":
case "PropertyStore":
case "ComputedStore":
case "ArrayExpression":
@@ -514,8 +514,7 @@ function computeMemoizationInputs(
case "ArrayExpression":
case "NewExpression":
case "ObjectExpression":
case "ComputedCall":
case "PropertyCall":
case "MethodCall":
case "PropertyStore": {
// All of these instructions may produce new values which must be memoized if
// reachable from a return value. Any mutable rvalue may alias any other rvalue
@@ -195,7 +195,7 @@ function* generateInstructionTypes(
break;
}
case "PropertyCall": {
case "MethodCall": {
const returnType = makeType();
yield equation(value.property.identifier.type, {
kind: "FunctionCall",
@@ -43,24 +43,24 @@ function ArrayAtTest(props) {
}
const arr = t1;
const c_4 = $[4] !== props.y;
let t2;
if (c_4) {
t2 = bar(props.y);
$[4] = props.y;
$[5] = t2;
} else {
t2 = $[5];
}
const c_6 = $[6] !== arr;
const c_7 = $[7] !== t2;
const c_5 = $[5] !== arr;
let t3;
if (c_6 || c_7) {
if (c_4 || c_5) {
const c_7 = $[7] !== props.y;
let t2;
if (c_7) {
t2 = bar(props.y);
$[7] = props.y;
$[8] = t2;
} else {
t2 = $[8];
}
t3 = arr.at(t2);
$[6] = arr;
$[7] = t2;
$[8] = t3;
$[4] = props.y;
$[5] = arr;
$[6] = t3;
} else {
t3 = $[8];
t3 = $[6];
}
const result = t3;
return result;
@@ -35,7 +35,7 @@ bb0 (block):
[6] mutate $55:TObject<Array> = LoadLocal capture arr$53:TObject<Array>
[7] mutate $56:TFunction<<generated_0>> = PropertyLoad read $55:TObject<Array>.at
[8] mutate $57 = LoadLocal capture x$48
[9] mutate $58 = PropertyCall read $55:TObject<Array>.read $56:TFunction<<generated_0>>(read $57)
[9] mutate $58 = MethodCall read $55:TObject<Array>.read $56:TFunction<<generated_0>>(read $57)
[10] Return freeze $58
[9] store $41[9:12]:TFunction = StoreLocal Const mutate fn$40[9:12]:TFunction = capture $39[8:12]:TFunction
[10] mutate $42[10:12]:TFunction = LoadLocal capture fn$40[9:12]:TFunction
@@ -30,7 +30,7 @@ bb0 (block):
[10] mutate $30 = LoadLocal read props$19
[11] mutate $31 = PropertyLoad read $30.y
[12] mutate $32 = Call read $29:TFunction(read $31)
[13] mutate $33 = PropertyCall read $27:TObject<Array>.read $28:TFunction<<generated_0>>(read $32)
[13] mutate $33 = MethodCall read $27:TObject<Array>.read $28:TFunction<<generated_0>>(read $32)
[14] store $35 = StoreLocal Const mutate result$34 = capture $33
[15] mutate $36 = LoadLocal capture result$34
[16] Return freeze $36
@@ -26,13 +26,13 @@ bb0 (block):
[8] mutate $36[8:12]:TObject<Array> = LoadLocal capture a$34[7:12]:TObject<Array>
[9] mutate $37[9:12]:TFunction<<generated_2>> = PropertyLoad read $36[8:12]:TObject<Array>.push
[10] mutate $38:TPrimitive = 42
[11] mutate $39:TPrimitive = PropertyCall mutate $36[8:12]:TObject<Array>.read $37[9:12]:TFunction<<generated_2>>(read $38:TPrimitive)
[11] mutate $39:TPrimitive = MethodCall mutate $36[8:12]:TObject<Array>.read $37[9:12]:TFunction<<generated_2>>(read $38:TPrimitive)
[12] store $41:TPrimitive = StoreLocal Const mutate x$40:TPrimitive = capture $39:TPrimitive
[13] mutate $42:TObject<Array> = LoadLocal capture a$34[7:12]:TObject<Array>
[14] mutate $43:TFunction<<generated_0>> = PropertyLoad read $42:TObject<Array>.at
[15] mutate $44 = LoadLocal read props$27
[16] mutate $45 = PropertyLoad read $44.c
[17] mutate $46 = PropertyCall read $42:TObject<Array>.read $43:TFunction<<generated_0>>(read $45)
[17] mutate $46 = MethodCall read $42:TObject<Array>.read $43:TFunction<<generated_0>>(read $45)
[18] store $48 = StoreLocal Const mutate y$47 = capture $46
[19] mutate $49:TObject<Array> = LoadLocal capture a$34[7:12]:TObject<Array>
[20] mutate $50:TPrimitive = LoadLocal capture x$40:TPrimitive
@@ -34,12 +34,12 @@ bb0 (block):
[12] mutate $41[12:21]:TObject<Array> = LoadLocal capture arr$39[11:21]:TObject<Array>
[13] mutate $42[13:21]:TFunction<<generated_2>> = PropertyLoad read $41[12:21]:TObject<Array>.push
[14] store $43:TObject<Object> = Object { }
[15] mutate $44:TPrimitive = PropertyCall mutate $41[12:21]:TObject<Array>.read $42[13:21]:TFunction<<generated_2>>(capture $43:TObject<Object>)
[15] mutate $44:TPrimitive = MethodCall mutate $41[12:21]:TObject<Array>.read $42[13:21]:TFunction<<generated_2>>(capture $43:TObject<Object>)
[16] mutate $45[16:21]:TObject<Array> = LoadLocal capture arr$39[11:21]:TObject<Array>
[17] mutate $46[17:21]:TFunction<<generated_2>> = PropertyLoad read $45[16:21]:TObject<Array>.push
[18] mutate $47 = LoadLocal capture x$31
[19] mutate $48:TObject<Object> = LoadLocal capture y$36:TObject<Object>
[20] mutate $49:TPrimitive = PropertyCall mutate $45[16:21]:TObject<Array>.read $46[17:21]:TFunction<<generated_2>>(capture $47, capture $48:TObject<Object>)
[20] mutate $49:TPrimitive = MethodCall mutate $45[16:21]:TObject<Array>.read $46[17:21]:TFunction<<generated_2>>(capture $47, capture $48:TObject<Object>)
[21] mutate $50:TObject<Array> = LoadLocal capture arr$39[11:21]:TObject<Array>
[22] Return freeze $50:TObject<Array>
```
@@ -18,7 +18,7 @@ bb0 (block):
[2] store $12[2:6]:TObject<Array> = StoreLocal Const store x$11[2:6]:TObject<Array> = capture $10[1:6]:TObject<Array>
[3] mutate $13[3:6]:TObject<Array> = LoadLocal capture x$11[2:6]:TObject<Array>
[4] mutate $14[4:6]:TPrimitive = PropertyLoad read $13[3:6]:TObject<Array>.length
[5] mutate $15 = PropertyCall mutate $13[3:6]:TObject<Array>.read $14[4:6]:TPrimitive()
[5] mutate $15 = MethodCall mutate $13[3:6]:TObject<Array>.read $14[4:6]:TPrimitive()
[6] store $17 = StoreLocal Const mutate y$16 = capture $15
[7] mutate $18 = LoadLocal capture y$16
[8] Return freeze $18
@@ -25,7 +25,7 @@ bb0 (block):
[4] mutate $42[4:36]:TFunction<<generated_2>> = PropertyLoad read $41[3:36]:TObject<Array>.push
[5] mutate $43 = LoadLocal read props$37
[6] mutate $44 = PropertyLoad read $43.bar
[7] mutate $45:TPrimitive = PropertyCall mutate $41[3:36]:TObject<Array>.read $42[4:36]:TFunction<<generated_2>>(read $44)
[7] mutate $45:TPrimitive = MethodCall mutate $41[3:36]:TObject<Array>.read $42[4:36]:TFunction<<generated_2>>(read $44)
[8] Ternary test:bb2 fallthrough=bb1
bb2 (value):
predecessor blocks: bb0
@@ -41,7 +41,7 @@ bb3 (value):
[19] mutate $57[19:36] = PropertyLoad read $56[18:36].push
[20] mutate $58 = LoadLocal read props$37
[21] mutate $59 = PropertyLoad read $58.foo
[22] mutate $60[22:33] = PropertyCall mutate $56[18:36].read $57[19:36](read $59)
[22] mutate $60[22:33] = MethodCall mutate $56[18:36].read $57[19:36](read $59)
[23] store $62[23:33] = StoreLocal Const mutate $61[8:33] = capture $60[22:33]
[24] Goto bb1
bb4 (value):
@@ -57,7 +57,7 @@ bb1 (block):
[29] mutate $69 = Global console
[30] mutate $70 = PropertyLoad read $69.log
[31] mutate $71[31:33] = LoadLocal capture _$66[28:33]
[32] mutate $72 = PropertyCall read $69.read $70(mutate $71[31:33])
[32] mutate $72 = MethodCall read $69.read $70(mutate $71[31:33])
[33] mutate $73:TFunction = Global mut
[34] mutate $74[34:36] = LoadLocal capture x$39[2:36]
[35] mutate $76 = Call read $73:TFunction(mutate $74[34:36])
@@ -24,7 +24,7 @@ bb0 (block):
[4] mutate $39[4:8]:TFunction<<generated_2>> = PropertyLoad read $38[3:8]:TObject<Array>.push
[5] mutate $40 = LoadLocal read props$34
[6] mutate $41 = PropertyLoad read $40.bar
[7] mutate $42:TPrimitive = PropertyCall mutate $38[3:8]:TObject<Array>.read $39[4:8]:TFunction<<generated_2>>(read $41)
[7] mutate $42:TPrimitive = MethodCall mutate $38[3:8]:TObject<Array>.read $39[4:8]:TFunction<<generated_2>>(read $41)
[8] Ternary test:bb2 fallthrough=bb1
bb2 (value):
predecessor blocks: bb0
@@ -40,7 +40,7 @@ bb3 (value):
[19] mutate $54[19:23] = PropertyLoad read $53[18:23].push
[20] mutate $55 = LoadLocal read props$34
[21] mutate $56 = PropertyLoad read $55.foo
[22] mutate $57[22:33] = PropertyCall mutate $53[18:23].read $54[19:23](read $56)
[22] mutate $57[22:33] = MethodCall mutate $53[18:23].read $54[19:23](read $56)
[23] store $59[23:33] = StoreLocal Const mutate $58[8:33] = capture $57[22:33]
[24] Goto bb1
bb4 (value):
@@ -56,7 +56,7 @@ bb1 (block):
[29] mutate $66 = Global console
[30] mutate $67 = PropertyLoad read $66.log
[31] mutate $68[31:33] = LoadLocal capture _$63[28:33]
[32] mutate $69 = PropertyCall read $66.read $67(mutate $68[31:33])
[32] mutate $69 = MethodCall read $66.read $67(mutate $68[31:33])
[33] mutate $70 = LoadLocal capture x$36
[34] Return freeze $70
```
@@ -23,7 +23,7 @@ bb0 (block):
[4] mutate $40[4:34]:TFunction<<generated_2>> = PropertyLoad read $39[3:34]:TObject<Array>.push
[5] mutate $41 = LoadLocal read props$35
[6] mutate $42 = PropertyLoad read $41.bar
[7] mutate $43:TPrimitive = PropertyCall mutate $39[3:34]:TObject<Array>.read $40[4:34]:TFunction<<generated_2>>(read $42)
[7] mutate $43:TPrimitive = MethodCall mutate $39[3:34]:TObject<Array>.read $40[4:34]:TFunction<<generated_2>>(read $42)
[8] Ternary test:bb2 fallthrough=bb1
bb2 (value):
predecessor blocks: bb0
@@ -38,7 +38,7 @@ bb3 (value):
[17] mutate $53[17:34]:TFunction<<generated_2>> = PropertyLoad read $52[16:34]:TObject<Array>.push
[18] mutate $54 = LoadLocal read props$35
[19] mutate $55 = PropertyLoad read $54.foo
[20] mutate $56[20:31]:TPrimitive = PropertyCall mutate $52[16:34]:TObject<Array>.read $53[17:34]:TFunction<<generated_2>>(read $55)
[20] mutate $56[20:31]:TPrimitive = MethodCall mutate $52[16:34]:TObject<Array>.read $53[17:34]:TFunction<<generated_2>>(read $55)
[21] store $58[21:31]:TPrimitive = StoreLocal Const mutate $57[8:31]:TPrimitive = capture $56[20:31]:TPrimitive
[22] Goto bb1
bb4 (value):
@@ -54,7 +54,7 @@ bb1 (block):
[27] mutate $65 = Global console
[28] mutate $66 = PropertyLoad read $65.log
[29] mutate $67[29:31] = LoadLocal capture _$62[26:31]
[30] mutate $68 = PropertyCall read $65.read $66(mutate $67[29:31])
[30] mutate $68 = MethodCall read $65.read $66(mutate $67[29:31])
[31] mutate $69:TFunction = Global mut
[32] mutate $70[32:34] = LoadLocal capture x$37[2:34]
[33] mutate $72 = Call read $69:TFunction(mutate $70[32:34])
@@ -22,7 +22,7 @@ bb0 (block):
[4] mutate $37[4:8]:TFunction<<generated_2>> = PropertyLoad read $36[3:8]:TObject<Array>.push
[5] mutate $38 = LoadLocal read props$32
[6] mutate $39 = PropertyLoad read $38.bar
[7] mutate $40:TPrimitive = PropertyCall mutate $36[3:8]:TObject<Array>.read $37[4:8]:TFunction<<generated_2>>(read $39)
[7] mutate $40:TPrimitive = MethodCall mutate $36[3:8]:TObject<Array>.read $37[4:8]:TFunction<<generated_2>>(read $39)
[8] Ternary test:bb2 fallthrough=bb1
bb2 (value):
predecessor blocks: bb0
@@ -37,7 +37,7 @@ bb3 (value):
[17] mutate $50[17:21]:TFunction<<generated_2>> = PropertyLoad read $49[16:21]:TObject<Array>.push
[18] mutate $51 = LoadLocal read props$32
[19] mutate $52 = PropertyLoad read $51.foo
[20] mutate $53[20:31]:TPrimitive = PropertyCall mutate $49[16:21]:TObject<Array>.read $50[17:21]:TFunction<<generated_2>>(read $52)
[20] mutate $53[20:31]:TPrimitive = MethodCall mutate $49[16:21]:TObject<Array>.read $50[17:21]:TFunction<<generated_2>>(read $52)
[21] store $55[21:31]:TPrimitive = StoreLocal Const mutate $54[8:31]:TPrimitive = capture $53[20:31]:TPrimitive
[22] Goto bb1
bb4 (value):
@@ -53,7 +53,7 @@ bb1 (block):
[27] mutate $62 = Global console
[28] mutate $63 = PropertyLoad read $62.log
[29] mutate $64[29:31] = LoadLocal capture _$59[26:31]
[30] mutate $65 = PropertyCall read $62.read $63(mutate $64[29:31])
[30] mutate $65 = MethodCall read $62.read $63(mutate $64[29:31])
[31] mutate $66 = LoadLocal capture x$34
[32] Return freeze $66
```
@@ -25,7 +25,7 @@ bb0 (block):
[4] mutate $48[4:8]:TFunction<<generated_2>> = PropertyLoad read $47[3:8]:TObject<Array>.push
[5] mutate $49 = LoadLocal read props$43
[6] mutate $50 = PropertyLoad read $49.bar
[7] mutate $51:TPrimitive = PropertyCall mutate $47[3:8]:TObject<Array>.read $48[4:8]:TFunction<<generated_2>>(read $50)
[7] mutate $51:TPrimitive = MethodCall mutate $47[3:8]:TObject<Array>.read $48[4:8]:TFunction<<generated_2>>(read $50)
[8] Ternary test:bb2 fallthrough=bb1
bb2 (value):
predecessor blocks: bb0
@@ -40,7 +40,7 @@ bb3 (value):
[17] mutate $61[17:42]:TFunction<<generated_2>> = PropertyLoad read $60[16:42]:TObject<Array>.push
[18] mutate $62 = LoadLocal read props$43
[19] mutate $63 = PropertyLoad read $62.foo
[20] mutate $64[20:39]:TPrimitive = PropertyCall mutate $60[16:42]:TObject<Array>.read $61[17:42]:TFunction<<generated_2>>(read $63)
[20] mutate $64[20:39]:TPrimitive = MethodCall mutate $60[16:42]:TObject<Array>.read $61[17:42]:TFunction<<generated_2>>(read $63)
[21] store $66[21:39]:TPrimitive = StoreLocal Const mutate $65[8:39]:TPrimitive = capture $64[20:39]:TPrimitive
[22] Goto bb1
bb4 (value):
@@ -51,7 +51,7 @@ bb4 (value):
[28] mutate $74[28:42]:TFunction<<generated_2>> = PropertyLoad read $73[27:42]:TObject<Array>.push
[29] mutate $75 = LoadLocal read props$43
[30] mutate $76 = PropertyLoad read $75.bar
[31] mutate $77[31:39]:TPrimitive = PropertyCall mutate $73[27:42]:TObject<Array>.read $74[28:42]:TFunction<<generated_2>>(read $76)
[31] mutate $77[31:39]:TPrimitive = MethodCall mutate $73[27:42]:TObject<Array>.read $74[28:42]:TFunction<<generated_2>>(read $76)
[32] store $79[32:39]:TPrimitive = StoreLocal Const mutate $65[8:39]:TPrimitive = capture $77[31:39]:TPrimitive
[33] Goto bb1
bb1 (block):
@@ -62,7 +62,7 @@ bb1 (block):
[35] mutate $83 = Global console
[36] mutate $84 = PropertyLoad read $83.log
[37] mutate $85[37:39] = LoadLocal capture _$80[34:39]
[38] mutate $86 = PropertyCall read $83.read $84(mutate $85[37:39])
[38] mutate $86 = MethodCall read $83.read $84(mutate $85[37:39])
[39] mutate $87:TFunction = Global mut
[40] mutate $88[40:42] = LoadLocal capture x$45[15:42]
[41] mutate $90 = Call read $87:TFunction(mutate $88[40:42])
@@ -24,7 +24,7 @@ bb0 (block):
[4] mutate $45[4:8]:TFunction<<generated_2>> = PropertyLoad read $44[3:8]:TObject<Array>.push
[5] mutate $46 = LoadLocal read props$40
[6] mutate $47 = PropertyLoad read $46.bar
[7] mutate $48:TPrimitive = PropertyCall mutate $44[3:8]:TObject<Array>.read $45[4:8]:TFunction<<generated_2>>(read $47)
[7] mutate $48:TPrimitive = MethodCall mutate $44[3:8]:TObject<Array>.read $45[4:8]:TFunction<<generated_2>>(read $47)
[8] Ternary test:bb2 fallthrough=bb1
bb2 (value):
predecessor blocks: bb0
@@ -39,7 +39,7 @@ bb3 (value):
[17] mutate $58[17:21]:TFunction<<generated_2>> = PropertyLoad read $57[16:21]:TObject<Array>.push
[18] mutate $59 = LoadLocal read props$40
[19] mutate $60 = PropertyLoad read $59.foo
[20] mutate $61[20:39]:TPrimitive = PropertyCall mutate $57[16:21]:TObject<Array>.read $58[17:21]:TFunction<<generated_2>>(read $60)
[20] mutate $61[20:39]:TPrimitive = MethodCall mutate $57[16:21]:TObject<Array>.read $58[17:21]:TFunction<<generated_2>>(read $60)
[21] store $63[21:39]:TPrimitive = StoreLocal Const mutate $62[8:39]:TPrimitive = capture $61[20:39]:TPrimitive
[22] Goto bb1
bb4 (value):
@@ -50,7 +50,7 @@ bb4 (value):
[28] mutate $71[28:32]:TFunction<<generated_2>> = PropertyLoad read $70[27:32]:TObject<Array>.push
[29] mutate $72 = LoadLocal read props$40
[30] mutate $73 = PropertyLoad read $72.bar
[31] mutate $74[31:39]:TPrimitive = PropertyCall mutate $70[27:32]:TObject<Array>.read $71[28:32]:TFunction<<generated_2>>(read $73)
[31] mutate $74[31:39]:TPrimitive = MethodCall mutate $70[27:32]:TObject<Array>.read $71[28:32]:TFunction<<generated_2>>(read $73)
[32] store $76[32:39]:TPrimitive = StoreLocal Const mutate $62[8:39]:TPrimitive = capture $74[31:39]:TPrimitive
[33] Goto bb1
bb1 (block):
@@ -61,7 +61,7 @@ bb1 (block):
[35] mutate $80 = Global console
[36] mutate $81 = PropertyLoad read $80.log
[37] mutate $82[37:39] = LoadLocal capture _$77[34:39]
[38] mutate $83 = PropertyCall read $80.read $81(mutate $82[37:39])
[38] mutate $83 = MethodCall read $80.read $81(mutate $82[37:39])
[39] mutate $84 = LoadLocal capture x$42
[40] Return freeze $84
```
@@ -30,7 +30,7 @@ bb0 (block):
[4] mutate $39[4:8]:TFunction<<generated_2>> = PropertyLoad read $38[3:8]:TObject<Array>.push
[5] mutate $40 = LoadLocal read props$34
[6] mutate $41 = PropertyLoad read $40.bar
[7] mutate $42:TPrimitive = PropertyCall mutate $38[3:8]:TObject<Array>.read $39[4:8]:TFunction<<generated_2>>(read $41)
[7] mutate $42:TPrimitive = MethodCall mutate $38[3:8]:TObject<Array>.read $39[4:8]:TFunction<<generated_2>>(read $41)
[8] mutate $43 = LoadLocal read props$34
[9] mutate $44 = PropertyLoad read $43.cond
[10] If (read $44) then:bb2 else:bb3 fallthrough=bb1
@@ -42,7 +42,7 @@ bb2 (block):
[16] mutate $52[16:34]:TFunction<<generated_2>> = PropertyLoad read $51[15:34]:TObject<Array>.push
[17] mutate $53 = LoadLocal read props$34
[18] mutate $54 = PropertyLoad read $53.foo
[19] mutate $55:TPrimitive = PropertyCall mutate $51[15:34]:TObject<Array>.read $52[16:34]:TFunction<<generated_2>>(read $54)
[19] mutate $55:TPrimitive = MethodCall mutate $51[15:34]:TObject<Array>.read $52[16:34]:TFunction<<generated_2>>(read $54)
[20] Goto bb1
bb3 (block):
predecessor blocks: bb0
@@ -52,7 +52,7 @@ bb3 (block):
[26] mutate $63[26:34]:TFunction<<generated_2>> = PropertyLoad read $62[25:34]:TObject<Array>.push
[27] mutate $64 = LoadLocal read props$34
[28] mutate $65 = PropertyLoad read $64.bar
[29] mutate $66:TPrimitive = PropertyCall mutate $62[25:34]:TObject<Array>.read $63[26:34]:TFunction<<generated_2>>(read $65)
[29] mutate $66:TPrimitive = MethodCall mutate $62[25:34]:TObject<Array>.read $63[26:34]:TFunction<<generated_2>>(read $65)
[30] Goto bb1
bb1 (block):
predecessor blocks: bb2 bb3