Skip to content

[JSC] The slow path of a run-time-length array allocation takes the butterfly from the size class of its inline path - #767

Open
robobun wants to merge 1 commit into
mainfrom
robobun/c71a9b20/array-slow-path-inline-size-class
Open

robobun wants to merge 1 commit into
mainfrom
robobun/c71a9b20/array-slow-path-inline-size-class

Conversation

@robobun

@robobun robobun commented Oct 3, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

  • DFG and FTL code calls operationNewArrayWithSize for each array with a run-time length of 0 or 1: 199,901 calls for 200,000 rest(x) arrays.
  • The inline path asks for 8 + 8 * length bytes: size class 16. The slow path (JSArray::tryCreate, dfg/DFGOperations.cpp:2882) takes 48 or 32 bytes. So it never refills the free list that the inline path reads.

Fix

  • operationNewArrayWithSizeAfterInlineAllocation is now the slow path of these inline attempts. It takes the butterfly from the size class of the inline request.
  • The inline code is unchanged. Slow calls per 200,000 arrays: 199,901 to 398 for length 0 and 1, 597 to 597 for length 2.
  • Verified: JSTests/stress/runtime-length-array-slow-path-refills-inline-allocator.js (fails on main in 4 of 4 modes). Self-reviewed: 6 concerns raised, 3 addressed.

Background

  • A butterfly is the storage of an array's elements. Each size class (a step of 16 bytes) has an allocator with a free list.
  • JIT code takes the next cell of a free list inline. Only the C++ slow path fills one, and each collection empties them.
  • Considered a minimum capacity on the inline path: a compare and a conditional move more for each allocation.

Downsides

  • A length of 0 or 1 no longer gets room for 5 or 3 elements. A push or unshift right after creation now grows the array: rest(x) then push is 411 instructions, was 237 (Node 370).
  • main has that cost already (395) when other code allocates 16-byte auxiliary cells.
  • jsc text: +1,352 bytes.
Notes

Where this comes from. No user reported it. It was measured on a socket.io echo during oven-sh/bun#44112: that change removed one Buffer.from(string) for each websocket frame, and the echo then made 16.0 calls of operationNewArrayWithSize for each message where it made 2.7. Upstream WebKit main has the same code in these functions.

For a maintainer to decide. The change makes every program behave as main does today when native code allocates a 16-byte auxiliary cell now and then (column 2 of the table below). A program in which nothing did that (column 1) had one C++ call for each short array and got room for 5 or 3 elements with it. So rest() then 5 pushes goes from 268 to 994 instructions there (Node 346). Three answers are possible:

  1. Accept it. vectorLength == length is what the inline path gives every run-time length today, and V8 does the same.
  2. Change the growth path first (JSObject::ensureLengthSlow, runtime/JSObject.cpp:3862). The first push on an empty inline array is a C++ call that only finds the one spare slot of its cell, the second one grows to 3 and the fourth to 7. That is a separate change: it also applies to length 2 and more, which has these costs on main in both states.
  3. Give a run-time length the minimum capacity on the inline path. That keeps 5 and 3, adds a compare and a conditional move to each allocation of each length, and keeps 64 and 48 bytes for an array of length 0 and 1 where this change has 32.

The cause. SpeculativeJIT::emitAllocateButterfly (dfg/DFGSpeculativeJIT.cpp) and FTL allocateJSArray(LValue publicLength, LValue vectorLength, ...) (ftl/FTLLowerDFGToB3.cpp) ask vm.auxiliarySpace() for sizeof(IndexingHeader) + 8 * length bytes and store vectorLength == publicLength. For a length of 0 or 1 that is the allocator of size class 16. JSArray::tryCreate applies Butterfly::optimalContiguousVectorLength: BASE_CONTIGUOUS_VECTOR_LEN_EMPTY (5 elements, 48 bytes) for length 0 and BASE_CONTIGUOUS_VECTOR_LEN (3 elements, 32 bytes) for length 1. LocalAllocator::allocateSlowCase is the only code that gives an allocator a free list, and it ran on the allocator of size class 48 or 32. The end of each collection empties every free list (LocalAllocator::prepareForAllocation). If no C++ code had asked for 16 auxiliary bytes at all, the allocator did not exist and the JIT read a null pointer from CompleteSubspace::m_allocatorForSizeStep. From length 2 on, both paths ask for the same size class. A length that the compiler knows was never affected: DFG turns it into NewButterflyWithSize, whose slow path takes a byte size, and FTL applies the capacity of the runtime at compile time.

Ways to a run-time length of 0 or 1: a rest parameter, new Array(n), Array(n), a derived class of Array with a constructor that calls super(n), slice, map and the other builtins that use @newArrayWithSize, a literal with more than one spread. In Bun: EventEmitter.prototype.emit(type, ...args), process.nextTick(fn, ...args).

The change.

  • operationNewArrayWithSizeAfterInlineAllocation has the signature of operationNewArrayWithSize. With a butterfly it makes the cell. With no butterfly and an ArrayStorage structure (a length that is too large for the inline path) it calls JSArray::tryCreate as before. With no butterfly and a contiguous structure it allocates Butterfly::availableContiguousVectorLength(structure, length) elements: the size class of the inline request, with the vector length that fills the cell. For a length of 2 and more that is what JSArray::tryCreate gave.
  • CallArrayAllocatorWithVariableSizeSlowPathGenerator and CallArrayAllocatorWithVariableStructureVariableSizeSlowPathGenerator no longer take the operation as an argument. A site that uses one of them cannot pair the inline butterfly with another operation.
  • FTL allocateJSArray chooses the operation in the lazy slow path: the new one when the vector length is the run-time length, operationNewArrayWithSize when the vector length is static (it then has the capacity of the runtime already).
  • operationNewArrayWithSize, operationNewArrayWithSizeAndHint, runtime/ and heap/ are as they were. The two direct calls of operationNewArrayWithSize (a realm that is having a bad time) and the two calls with a butterfly (only the cell failed) stay.

Method. x86-64 Linux. jsc and bun-profile are release builds (RelWithDebInfo, no LTO) of the base and of this change with one toolchain, unless a table says otherwise. --useConcurrentJIT=false (BUN_JSC_useConcurrentJIT=0). A count of calls is the hit count of a gdb breakpoint with a large ignore count. Instructions are single steps (PTRACE_SINGLESTEP) of the main thread between two native marker calls around N calls of a function that is not inlined, as the difference of two window sizes. perf and valgrind are not available where this was built.

Slow path calls for 200,000 arrays, jsc (the three array operations together, the same with --useFTLJIT=false)

Shape base this change
new Array(n), n = 0 199,566 398
new Array(n), n = 1 199,566 398
new Array(n), n = 2 597 597
rest() 199,901 398
rest(x) 199,901 398
rest(x, y) 597 597
[x].slice() 199,901 398
[x, y].slice() 597 597
[x].map(f) 199,907 398
[...one, ...none] 199,901 398
[x] literal, FTL / DFG 585 / 0 585 / 0
[] literal, FTL / DFG 780 / 0 780 / 0

398 is one call for each refill of a free list (the butterflies and the cells).

In Bun (bun-profile with this WebKit, base and change)

Program base this change
new Array(n) 1,000,000 times, n = 0 / 1 / 2 999,901 / 999,901 / 2,991 1,731 / 1,524 / 2,991
rest() / rest(x) / rest(x, y), 200,000 times 145,005 / 145,138 / 598 322 / 453 / 597
[x].slice() / [x].map(f), 200,000 times 199,901 / 199,907 398 / 331
emitter.emit("msg", 1), 200,000 times 129,958 261
socket.io 4.7.1 echo in one process, 30,000 messages 82,671 2,860
tsc --noEmit on 25 files of src/js/node (1.5 MB) 43,291 1,195

For the last two rows, the calls of JSObject::ensureLengthSlow are 40 and 40 (socket.io) and 5,820 and 8,292 (tsc), and the calls of operationArrayPush are 12 and 12, and 3,055 and 5,500. operationArrayUnshift was not counted in these runs. A slow allocation that goes away is about 150 instructions, so the echo gains about 400 instructions for each message, which is about 2% of what one message costs on main. With oven-sh/bun#44112 the echo has 16 such calls for each message.

Instructions for each call, arrays that do not grow (FTL / --useFTLJIT=false)

Shape base this change
new Array(n), n = 0 212 / 226 66 / 93
new Array(n), n = 1 216 / 233 67 / 97
new Array(n), n = 2 75 / 108 75 / 108
rest() 205 / 224 58 / 96
rest(x) 220 / 237 66 / 107
rest(x, y) 82 / 125 80 / 125
[x].slice() 244 / 255 92 / 122

The inline path is the same. DFG emits the same number of bytes for each node on both builds, before and after "(End Of Main Path)": NewArrayWithSize 289 + 181, CreateRest 338 + 77, ArraySlice 419 + 160, NewArray 228 + 161 ([x]) and 224 + 80 ([]). With the free list of the base filled by a native allocation before each window, the smallest of 16 windows of 100 calls has the same instruction count on both builds for 7 of 7 shapes in DFG. In FTL it has the same count for 5 of 7 shapes in one run. The other two (rest(x, y), [x].slice()) move by 1 or 2 instructions for each call from run to run on each build, with the addresses that the code holds, and have the same set of values on both over 6 runs. A slow call that refills a free list at length 2 takes 1,328 instructions where it took 1,335 (from the entry of the operation to its return).

Memory. Heap bytes for each array, cell and butterfly: rest() 64 to 32, rest(x) 48 to 32, rest(x, y) 48 and 48, new Array(0) 64 to 32, new Array(1) 48 to 32, new Array(2) 48 and 48. Collections for 8,000,000 arrays that die at once: rest() 15 to 7, rest(x) 11 to 7, rest(x, y) 11 and 11.

Arrays that grow right after creation. Instructions for each call. main is the released build of 4fde1587 (LTO). Column 2 is that build with new Uint8Array(buffer) once in 512 calls, which refills the free list of size class 16 (its cost is in the number). Node is 26.3.0 with inlining of the callee off.

Call main, no such allocation main, one in 512 calls this change Node
rest() 218 76 64 178
rest(x) 229 84 75 232
rest(x, y) 89 98 89 250
rest() then push 226 302 288 275
rest(x) then push 237 395 411 370
rest(x, y) then push 314 324 313 363
rest() then 5 pushes 268 947 994 346
rest(x) then 5 pushes 577 741 781 410
rest(x, y) then 5 pushes 656 665 678 403
rest() then unshift 235 493 462 723
rest(x) then unshift 251 617 600 836
rest(x, y) then unshift 559 570 540 844
f(ev, ...args) with args.unshift(ev), 0 / 1 / 2 arguments 245 / 261 / 569 503 / 627 / 580 473 / 610 / 550 725 / 838 / 846
[x].slice() 249 110 98 265
[x].slice() then push 258 420 429 409
[x, y].slice() then push 334 347 329 382

The DFG fast path of unshift for a length of 0 or 1 (compileArrayUnshift, dfg/DFGSpeculativeJIT64.cpp) needs a spare slot. An array from the inline path has none, on main too.

Size. jsc text 43,993,539 to 43,994,891 bytes (+1,352). bun-profile text +2,412 bytes. The new operation is 1,290 bytes. One more JIT operation.

Tests.

  • JSTests/stress/runtime-length-array-slow-path-refills-inline-allocator.js reads $vm.deltaBetweenButterflies of arrays that one function makes one after the other. The most frequent distance is the cell size of the size class. It expects 16 for 11 ways to a run-time length of 0 or 1, 32 for 3 ways to a run-time length of 2, 32 for [x] and 48 for [], for the arrays that DFG code made and for those that FTL code made. Two of its four modes add --forceGCSlowPaths=true, which sends each allocation to the slow path. On the base, 22 of 32 checks fail with FTL and 11 of 16 without (new Array(0) in DFG: expected 16 but got 48). The released build of 4fde1587 fails the same way. Each mode runs in 16 to 59 ms.
  • JSTests/microbenchmarks/runtime-length-small-array-then-grow.js has the never-grown, one push, five pushes and unshift forms at lengths 0, 1 and 2.
  • CI on this head: Test bun-webkit-linux-amd64-lto and Test bun-webkit-linux-arm64-lto run run-javascriptcore-tests (JSTests, LayoutTests/js, the PerformanceTests collections) against the jsc of this change, and both pass.
  • Local runs: the new test in its 4 modes, on the base and on the change. Then 187 files of JSTests/stress whose names have to do with arrays (new-array, rest-parameter, create-rest, array-slice, spread, array-species, vector-length, auxiliary-evacuation, having-a-bad-time, array-push, array-unshift) in every mode of run-jsc-stress-tests: 2,737 of 2,754 runs pass. The 17 that fail are the modes of intl-having-a-bad-time.js. The local build has no ICU data, so new Intl.DateTimeFormat("en") alone fails on it.

Self-review. 6 concerns.

  1. Calls that grow a short array right after creation get slower against main in the state where nothing else allocates 16-byte auxiliary cells, and two push rows end behind Node. Not addressed in code. It is the first Downsides bullet and the decision above.
  2. The unshift form was in no table and not in the microbenchmark. Addressed: both have it.
  3. The numbers compared against one state of main. Addressed: the table has both.
  4. The gain for a whole program was not stated. Addressed: about 2% of a socket.io echo message on main.
  5. A third operationNewArrayWithSize* operation, paired with the inline path by convention. Not taken. A slow path for the butterfly alone that takes the byte size (what allocateButterfly has) makes the pairing structural, and adds a second slow path to each site. The two generator classes and one FTL function now hold the pairing.
  6. The FIXME on FTL allocateJSArray asks to build it from allocateButterfly and allocateJSArray(IndexingType, ...). Not taken here: it is the same larger change as 5.

Not in this change.

  • x + "" with an empty operand that is known only at run time calls operationMakeRope2 each time: 199,901 calls for 200,000, and 398 with a non-empty operand. The inline path of MakeRope does not take an empty string. No open PR has it.
  • operationNewArrayWithSizeAndHint applies the capacity of the runtime to its hint. FTL passes it static vector lengths only, which have that capacity already.

…utterfly from the size class of its inline path

DFG and FTL allocate the butterfly of an array with a run-time length inline
(SpeculativeJIT::emitAllocateButterfly, FTL allocateJSArray). They ask
vm.auxiliarySpace() for sizeof(IndexingHeader) + 8 * length bytes. For a length
of 0 or 1 that is size class 16.

Their slow path, operationNewArrayWithSize, called JSArray::tryCreate. That
applies the minimum capacity of the runtime: 5 elements (48 bytes) for length 0
and 3 elements (32 bytes) for length 1. So the slow path never ran
LocalAllocator::allocateSlowCase on the allocator whose free list the inline
path reads. Each collection empties that free list. After that, each allocation
of such an array called the slow path again, until other code allocated a
16-byte auxiliary cell. Rest parameters with 0 or 1 arguments, new Array(n),
slice and map of short arrays are on this path.

operationNewArrayWithSizeAfterInlineAllocation is now the slow path of these
inline attempts. With no butterfly and a contiguous structure, it takes the
butterfly from the size class that the inline path asked for. Lengths of 2 and
more get the same butterfly as before.

The two DFG slow path generators for a run-time length call the operation by
name. FTL allocateJSArray calls it when the vector length is not static. A
static vector length already has the capacity of the runtime, so that arm keeps
operationNewArrayWithSize. The inline code does not change.

* JSTests/stress/runtime-length-array-slow-path-refills-inline-allocator.js: Added.
* JSTests/microbenchmarks/runtime-length-small-array-then-grow.js: Added.
* Source/JavaScriptCore/dfg/DFGCallArrayAllocatorSlowPathGenerator.h:
* Source/JavaScriptCore/dfg/DFGOperations.cpp:
* Source/JavaScriptCore/dfg/DFGOperations.h:
* Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp:
* Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp:
@robobun

robobun commented Oct 3, 2026

Copy link
Copy Markdown
Collaborator Author

Status

How this was reproduced, with plain JavaScript in jsc and in Bun, no websocket code:

function rest(...values) { return values; }
noInline(rest);
const keep = new Array(200000);
for (let i = 0; i < 200000; ++i)
    keep[i] = rest(i);
  • jsc --useConcurrentJIT=false under gdb, with a breakpoint that has a large ignore count on the array slow path operations: 199,901 calls on main, 398 calls with this change. With two arguments: 597 and 597.
  • JSTests/stress/runtime-length-array-slow-path-refills-inline-allocator.js fails on main in its 4 modes with new Array(0) in DFG: expected 16 but got 48, and passes with this change.

One decision is open for a maintainer. It is in the Notes of the description ("For a maintainer to decide").

@github-actions

github-actions Bot commented Oct 3, 2026

Copy link
Copy Markdown

Preview build of d184a84: autobuild-preview-pr-767-d184a84b

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Beyond the inline findings, I also checked two things in tryCreateArrayInSizeClassOfInlineAllocation and ruled them out: the raw butterfly held across JSArray::createWithButterfly is a conservative stack root, the same pattern JSArray::tryCreate already uses; and the length > MAX_STORAGE_VECTOR_LENGTH nullptr return is unreachable from the DFG/FTL callers with a contiguous structure, since they switch to the ArrayStorage structure at MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH before taking this slow path.

Extended reasoning...

The change adds a new DFG/FTL slow-path JIT operation in Source/JavaScriptCore/dfg/DFGOperations.cpp and rewires the two DFG slow-path generators and the FTL lazy slow path to it, plus a stress test and a microbenchmark; it touches allocator/GC-adjacent code but no auth, injection, or data-exposure surface. Verified findings on the test and on the capacity trade-off are posted inline, so a human review is already signalled; this note only records the two additional concerns that were examined and ruled out.

Findings marked 🟡 are optional suggestions and need no follow-up push.

Comment on lines +2896 to +2902
static ALWAYS_INLINE JSArray* tryCreateArrayInSizeClassOfInlineAllocation(VM& vm, Structure* structure, unsigned length)
{
ASSERT(!hasAnyArrayStorage(structure->indexingType()));
if (length > MAX_STORAGE_VECTOR_LENGTH) [[unlikely]]
return nullptr;

unsigned vectorLength = Butterfly::availableContiguousVectorLength(structure, length);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 (optional) Programs that grow a rest-parameter or new Array(n) array right after creating it now pay a reallocation on every call, where the base often gave spare room. tryCreateArrayInSizeClassOfInlineAllocation at DFGOperations.cpp:2902 sizes a run-time length of 0 or 1 to one element, and the inline path it now keeps fed stores vectorLength == length, so the first push or unshift goes through JSObject::ensureLengthSlow. Fix: keep the slow path in the inline size class but give a run-time length of 0 or 1 the runtime minimum capacity on the inline path as well (one compare and conditional move in emitAllocateButterfly and FTL allocateJSArray), or state in the PR that the growth cost is accepted for Bun workloads.

Why this was flagged

A DFG or FTL compiled function with a rest parameter, new Array(n), Array(n), slice or map whose length is 0 or 1 at run time, followed by push or unshift. On the base branch the inline path in SpeculativeJIT::emitAllocateButterfly (DFGSpeculativeJIT.cpp:14315) finds its size-16 free list empty almost every time, so JSArray::tryCreate at DFGOperations.cpp:2882 served the array with vectorLength 5 (length 0) or 3 (length 1) via Butterfly::optimalContiguousVectorLength. After the change tryCreateArrayInSizeClassOfInlineAllocation (DFGOperations.cpp:2896-2910) uses Butterfly::availableContiguousVectorLength, giving vectorLength 1, and the refilled free list makes the inline path, which stores vectorLength == publicLength (DFGSpeculativeJIT.cpp:14330, FTLLowerDFGToB3.cpp:24295), serve the rest. Every later push or unshift beyond that one slot calls JSObject::ensureLengthSlow (JSObject.cpp:4119) and allocates a second butterfly. No guard limits this: the growth path is unchanged and nothing on the inline path applies BASE_CONTIGUOUS_VECTOR_LEN.

Verification: New helper at DFGOperations.cpp:2902 sizes the butterfly with Butterfly::availableContiguousVectorLength; for length 0 or 1 that is totalSize = 8 (+8) bytes -> MarkedSpace::optimalSizeFor -> 16-byte cell -> vectorLength = (16-8)/8 = 1 (ButterflyInlines.h:46-52). Base JSArray::tryCreate (JSArrayInlines.h:56) used optimalContiguousVectorLength.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

This is the decision that the description leaves to a maintainer (Downsides, and "For a maintainer to decide" in the Notes). The table there has both states of main: the growth cost is what main has today in a program where other code allocates 16-byte auxiliary cells, and it is new only where nothing does.

The minimum capacity on the inline path is option 3 there. It keeps 5 and 3 elements, adds the compare and the conditional move to each run-time-length allocation of each length, and keeps 64 and 48 bytes for an array of length 0 and 1 where this change has 32. I did not build it. I can do that as a follow-up if a maintainer picks it.

@coderabbitai

coderabbitai Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: ASSERTIVE
  • Plan: Essentials
  • Run ID: dc04e935-eb91-4354-9b1d-3ec345f3e162
📥 Commits

Reviewing files that changed from the base of the PR and between 1600131 and d184a84.

📒 Files selected for processing (7)
  • JSTests/microbenchmarks/runtime-length-small-array-then-grow.js
  • JSTests/stress/runtime-length-array-slow-path-refills-inline-allocator.js
  • Source/JavaScriptCore/dfg/DFGCallArrayAllocatorSlowPathGenerator.h
  • Source/JavaScriptCore/dfg/DFGOperations.cpp
  • Source/JavaScriptCore/dfg/DFGOperations.h
  • Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
  • Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

Included review availability: This review used your included allowance. Your plan provides up to 5 included reviews per hour; 1 remain after this review.


Walkthrough

JavaScriptCore adds a dedicated operation for array allocation after inline allocation and routes DFG and FTL slow paths through it. New stress-test and microbenchmark cases cover small arrays and storage distances.

Changes

Runtime-length array allocation

Layer / File(s) Summary
Post-inline allocation operation
Source/JavaScriptCore/dfg/DFGOperations.h, Source/JavaScriptCore/dfg/DFGOperations.cpp
A new JIT operation handles allocation after inline allocation. It rejects negative sizes, uses a supplied butterfly when available, and otherwise allocates based on the array structure.
DFG and FTL slow-path wiring
Source/JavaScriptCore/dfg/DFGCallArrayAllocatorSlowPathGenerator.h, Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp, Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
DFG slow-path generators call the new operation, and DFG allocation sites use those generators. FTL selects the operation based on whether the vector length is static.
Small-array allocation tests
JSTests/stress/runtime-length-array-slow-path-refills-inline-allocator.js, JSTests/microbenchmarks/runtime-length-small-array-then-grow.js
The stress test checks storage distances for array allocation expressions. The microbenchmark compares rest-parameter arrays and new Array arrays at lengths zero through two.

Priority: ➖ Normal

Merge Risk: ⚪ Minimal · up to d184a

The change makes the slow path for small run-time-length arrays refill the free list used by inline allocation. No concrete merge-blocking problem was found. The author documents a trade-off of reduced initial capacity for length 0 and 1 arrays, and maintainers should decide whether to accept it.

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly identifies the main change: matching the runtime-length array slow path to the inline path’s butterfly size class. It is longer than ideal but remains specific and relevant.
Description check ✅ Passed The description is detailed and explains the problem, fix, trade-offs, and tests. It does not include a Bugzilla bug link or the template’s “Reviewed by” line, so those required details are missing.
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Warning

Git: CodeRabbit could not clone the repository, so clone-backed analysis was skipped and this review may be incomplete. Verify repository clone access, such as SSH credentials, before requesting another full review. If clone access is intentionally unavailable, use path_filters to narrow the review scope.


Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant