Skip to content
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 @@ -5403,25 +5403,27 @@ private static bool TryAppendComputedMemberCallTargetPreparation(
}
}

var keyIndex = callTargetIndexInProgram - 1;
var keyStartIndex = FindComputedCallKeyStart(expressionProgram, callTargetIndexInProgram);
if (!TryAppendNamedReceiverOperations(
expressionProgram,
activationSlots,
unified,
Comment on lines +5406 to 5410
stringConstants,
keyIndex,
keyStartIndex,
allowDeepChain: false,
out reason))
{
return false;
}

if (!TryAppendComputedPropertyKeyLoad(
expressionProgram.GetOperation(keyIndex),
if (!TryAppendComputedPropertyKeySpan(
expressionProgram,
activationSlots,
unified,
literalConstants,
stringConstants,
startInclusive: keyStartIndex,
endExclusive: callTargetIndexInProgram,
out reason))
{
return false;
Expand All @@ -5445,6 +5447,31 @@ private static bool TryAppendComputedMemberCallTargetPreparation(
out reason);
}

private static int FindComputedCallKeyStart(
ExpressionProgram expressionProgram,
int callTargetIndexInProgram)
{
var stringConstants = expressionProgram.StringConstants.AsSpan();
var keyStartIndex = 1;
while (keyStartIndex < callTargetIndexInProgram &&
IsPlainNamedPropertyRead(expressionProgram.GetOperation(keyStartIndex), stringConstants))
{
keyStartIndex++;
}

return keyStartIndex;
}

private static bool IsPlainNamedPropertyRead(
PackedExpressionOp operation,
ReadOnlySpan<string> stringConstants)
{
return operation.Kind == ExpressionOpKind.GetNamedProperty &&
!operation.IsOptional &&
!operation.ShortCircuitOnNullishTarget &&
!operation.GetString(stringConstants).IsPrivateName();
}

private static bool TryAppendNamedSuperCallTargetPreparation(
ExpressionProgram expressionProgram,
UnifiedBytecodeSlotLayout slotLayout,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2730,18 +2730,20 @@ private static bool TryIsFirstBoundaryCallTargetPreparationCandidate(
if (computedCallTargetIndex >= 2)
{
var computedCallTarget = program.GetOperation(computedCallTargetIndex);
var keyIndex = computedCallTargetIndex - 1;
var keyStartIndex = FindComputedCallKeyStart(program, computedCallTargetIndex, stringConstants);
return !computedCallTarget.IsOptional &&
!computedCallTarget.ShortCircuitOnNullishTarget &&
IsSupportedNamedReceiverChain(
Comment on lines 2732 to 2736
program,
identifierConstants,
stringConstants,
activationSlots,
keyIndex,
keyStartIndex,
allowDeepChain: false) &&
IsSimpleComputedPropertyKey(
program.GetOperation(keyIndex),
IsSupportedComputedPropertyKeySpan(
program,
startInclusive: keyStartIndex,
endExclusive: computedCallTargetIndex,
identifierConstants,
activationSlots) &&
HasSimpleCallArguments(
Expand All @@ -2755,6 +2757,21 @@ private static bool TryIsFirstBoundaryCallTargetPreparationCandidate(
return false;
}

private static int FindComputedCallKeyStart(
ExpressionProgram program,
int computedCallTargetIndex,
ReadOnlySpan<string> stringConstants)
{
var keyStartIndex = 1;
while (keyStartIndex < computedCallTargetIndex &&
IsPlainNamedPropertyRead(program.GetOperation(keyStartIndex), stringConstants))
{
keyStartIndex++;
}

return keyStartIndex;
}

private static bool IsFirstBoundaryDirectEvalCallCandidate(
ExpressionProgram program,
ReadOnlySpan<IdentifierOperand> identifierConstants,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2446,7 +2446,7 @@ function invokeComputedExpressionKey(box, left, right) {
}
""",
"invokeComputedExpressionKey",
(int)UnifiedBytecodeProductionDeclineCode.CallDependency)]
(int)UnifiedBytecodeProductionDeclineCode.None)]
[InlineData(
"""
function invokeDeepComputedCallee(root, key, value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1994,6 +1994,32 @@ static record => record.Message.Contains(
StringComparison.Ordinal));
}

[Fact(Timeout = 5000)]
public async Task ComputedMemberCallWithExpressionKey_UsesUnifiedBytecodeProductionFastPathAndPreservesThis()
{
await using var engine = CreateEngine();
var result = await engine.Evaluate("""
var box = {
offset: 1,
read(value) {
return value + this.offset;
}
};

function invoke(box, left, right, value) {
return box[left + right](value);
}

invoke(box, "re", "ad", 41);
""");

Assert.Equal(42d, result);
Assert.Contains(CurrentLogger!.Collector.Snapshot(),
static record => record.Message.Contains(
"unified-bytecode-production-fast-path func=invoke argc=4",
StringComparison.Ordinal));
}

[Fact(Timeout = 5000)]
public async Task ComputedMemberCall_NullishReceiverThrowsBeforeKeyCoercion()
{
Expand Down