Skip to content

Commit 316aa36

Browse files
Tom910acdlite
andauthored
[Scheduler] Fix de-opt caused by out-of-bounds access (#21147)
Scheduler's heap implementation sometimes accesses indices that are out of bounds (larger than the size of the array). This causes a VM de-opt. This change fixes the de-opt by always checking the index before accessing the array. In exchange, we can remove the typecheck on the returned element. Background: https://v8.dev/blog/elements-kinds#avoid-reading-beyond-the-length-of-the-array Co-authored-by: Andrew Clark <git@andrewclark.io>
1 parent a817840 commit 316aa36

File tree

1 file changed

+16
-17
lines changed

1 file changed

+16
-17
lines changed

packages/scheduler/src/SchedulerMinHeap.js

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,30 +20,28 @@ export function push(heap: Heap, node: Node): void {
2020
}
2121

2222
export function peek(heap: Heap): Node | null {
23-
const first = heap[0];
24-
return first === undefined ? null : first;
23+
return heap.length === 0 ? null : heap[0];
2524
}
2625

2726
export function pop(heap: Heap): Node | null {
28-
const first = heap[0];
29-
if (first !== undefined) {
30-
const last = heap.pop();
31-
if (last !== first) {
32-
heap[0] = last;
33-
siftDown(heap, last, 0);
34-
}
35-
return first;
36-
} else {
27+
if (heap.length === 0) {
3728
return null;
3829
}
30+
const first = heap[0];
31+
const last = heap.pop();
32+
if (last !== first) {
33+
heap[0] = last;
34+
siftDown(heap, last, 0);
35+
}
36+
return first;
3937
}
4038

4139
function siftUp(heap, node, i) {
4240
let index = i;
43-
while (true) {
41+
while (index > 0) {
4442
const parentIndex = (index - 1) >>> 1;
4543
const parent = heap[parentIndex];
46-
if (parent !== undefined && compare(parent, node) > 0) {
44+
if (compare(parent, node) > 0) {
4745
// The parent is larger. Swap positions.
4846
heap[parentIndex] = node;
4947
heap[index] = parent;
@@ -58,15 +56,16 @@ function siftUp(heap, node, i) {
5856
function siftDown(heap, node, i) {
5957
let index = i;
6058
const length = heap.length;
61-
while (index < length) {
59+
const halfLength = length >>> 1;
60+
while (index < halfLength) {
6261
const leftIndex = (index + 1) * 2 - 1;
6362
const left = heap[leftIndex];
6463
const rightIndex = leftIndex + 1;
6564
const right = heap[rightIndex];
6665

6766
// If the left or right node is smaller, swap with the smaller of those.
68-
if (left !== undefined && compare(left, node) < 0) {
69-
if (right !== undefined && compare(right, left) < 0) {
67+
if (compare(left, node) < 0) {
68+
if (rightIndex < length && compare(right, left) < 0) {
7069
heap[index] = right;
7170
heap[rightIndex] = node;
7271
index = rightIndex;
@@ -75,7 +74,7 @@ function siftDown(heap, node, i) {
7574
heap[leftIndex] = node;
7675
index = leftIndex;
7776
}
78-
} else if (right !== undefined && compare(right, node) < 0) {
77+
} else if (rightIndex < length && compare(right, node) < 0) {
7978
heap[index] = right;
8079
heap[rightIndex] = node;
8180
index = rightIndex;

0 commit comments

Comments
 (0)