Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[compiler][ez] rewrite invariant in InferReferenceEffects #32093

Merged
merged 1 commit into from
Jan 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,16 @@ function inferOperandEffect(state: State, place: Place): null | FunctionEffect {
if (isRefOrRefValue(place.identifier)) {
break;
} else if (value.kind === ValueKind.Context) {
CompilerError.invariant(value.context.size > 0, {
reason:
"[InferFunctionEffects] Expected Context-kind value's capture list to be non-empty.",
loc: place.loc,
});
return {
kind: 'ContextMutation',
loc: place.loc,
effect: place.effect,
places: value.context.size === 0 ? new Set([place]) : value.context,
places: value.context,
};
} else if (
value.kind !== ValueKind.Mutable &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -857,17 +857,19 @@ function inferBlock(
break;
}
case 'ArrayExpression': {
const valueKind: AbstractValue = hasContextRefOperand(state, instrValue)
? {
kind: ValueKind.Context,
reason: new Set([ValueReason.Other]),
context: new Set(),
}
: {
kind: ValueKind.Mutable,
reason: new Set([ValueReason.Other]),
context: new Set(),
};
const contextRefOperands = getContextRefOperand(state, instrValue);
const valueKind: AbstractValue =
contextRefOperands.length > 0
? {
kind: ValueKind.Context,
reason: new Set([ValueReason.Other]),
context: new Set(contextRefOperands),
}
: {
kind: ValueKind.Mutable,
reason: new Set([ValueReason.Other]),
context: new Set(),
};
Comment on lines +860 to +872
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm it seems wrong to do this only for array and object expressions: there could just as easily be a function call or constructor that captures context values in the same way. I think we missed this when we originally added the context ref check — let's generalize this check

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just slightly ahead of you, see repro here #31770

+1 on generalizing this check -- although I'm curious how many changes to compilation output this would result in

continuation = {
kind: 'initialize',
valueKind,
Expand Down Expand Up @@ -918,17 +920,19 @@ function inferBlock(
break;
}
case 'ObjectExpression': {
const valueKind: AbstractValue = hasContextRefOperand(state, instrValue)
? {
kind: ValueKind.Context,
reason: new Set([ValueReason.Other]),
context: new Set(),
}
: {
kind: ValueKind.Mutable,
reason: new Set([ValueReason.Other]),
context: new Set(),
};
const contextRefOperands = getContextRefOperand(state, instrValue);
const valueKind: AbstractValue =
contextRefOperands.length > 0
? {
kind: ValueKind.Context,
reason: new Set([ValueReason.Other]),
context: new Set(contextRefOperands),
}
: {
kind: ValueKind.Mutable,
reason: new Set([ValueReason.Other]),
context: new Set(),
};

for (const property of instrValue.properties) {
switch (property.kind) {
Expand Down Expand Up @@ -1593,15 +1597,21 @@ function inferBlock(
}
case 'LoadLocal': {
const lvalue = instr.lvalue;
const effect =
state.isDefined(lvalue) &&
state.kind(lvalue).kind === ValueKind.Context
? Effect.ConditionallyMutate
: Effect.Capture;
CompilerError.invariant(
!(
state.isDefined(lvalue) &&
state.kind(lvalue).kind === ValueKind.Context
),
{
reason:
'[InferReferenceEffects] Unexpected LoadLocal with context kind',
loc: lvalue.loc,
},
);
state.referenceAndRecordEffects(
freezeActions,
instrValue.place,
effect,
Effect.Capture,
ValueReason.Other,
);
lvalue.effect = Effect.ConditionallyMutate;
Expand Down Expand Up @@ -1932,19 +1942,20 @@ function inferBlock(
);
}

function hasContextRefOperand(
function getContextRefOperand(
state: InferenceState,
instrValue: InstructionValue,
): boolean {
): Array<Place> {
const result = [];
for (const place of eachInstructionValueOperand(instrValue)) {
if (
state.isDefined(place) &&
state.kind(place).kind === ValueKind.Context
) {
return true;
result.push(place);
}
}
return false;
return result;
}

export function getFunctionCallSignature(
Expand Down
Loading