Skip to main content

luaur_common/methods/
vec_deque_grow.rs

1use crate::macros::luau_assert::LUAU_ASSERT;
2use crate::records::vec_deque::VecDeque;
3use core::cmp;
4use core::ptr;
5
6impl<T> VecDeque<T> {
7    #[allow(dead_code)]
8    pub(crate) fn vec_deque_grow_impl(&mut self) {
9        let old_capacity = self.capacity();
10
11        // we use a growth factor of 1.5x (plus a constant) here in order to enable the
12        // previous memory to be reused after a certain number of calls to grow.
13        // see: https://github.com/facebook/folly/blob/main/folly/docs/FBVector.md#memory-handling
14        let new_capacity = if old_capacity > 0 {
15            old_capacity * 3 / 2 + 1
16        } else {
17            4
18        };
19
20        // check that it's a legal allocation
21        if new_capacity > self.max_size() {
22            panic!("bad_array_new_length");
23        }
24
25        // allocate a new backing buffer
26        let new_buffer = self.allocate(new_capacity);
27
28        // we should not be growing if the capacity is not the current size
29        LUAU_ASSERT!(old_capacity == self.queue_size);
30
31        // how many elements are in the head portion (i.e. from the head to the end of the buffer)
32        let head_size = cmp::min(self.queue_size, old_capacity - self.head);
33        // how many elements are in the tail portion (i.e. any portion that wrapped to the front)
34        let tail_size = self.queue_size - head_size;
35
36        if let Some(old_ptr) = self.buffer {
37            unsafe {
38                // move the head into the new buffer
39                if head_size != 0 {
40                    ptr::copy_nonoverlapping(
41                        old_ptr.as_ptr().add(self.head),
42                        new_buffer.as_ptr(),
43                        head_size,
44                    );
45                }
46
47                // move the tail into the new buffer immediately after
48                if tail_size != 0 {
49                    ptr::copy_nonoverlapping(
50                        old_ptr.as_ptr(),
51                        new_buffer.as_ptr().add(head_size),
52                        tail_size,
53                    );
54                }
55            }
56        }
57
58        // destroy the old elements
59        self.destroyElements();
60
61        // deallocate the old buffer
62        self.deallocate(self.buffer, old_capacity);
63
64        // set up the queue to be backed by the new buffer
65        self.buffer = Some(new_buffer);
66        self.buffer_capacity = new_capacity;
67        self.head = 0;
68    }
69}
70
71impl<T> VecDeque<T> {
72    // The record file already contains a stub for grow() that calls vec_deque_grow_impl.
73    // To avoid E0592 (duplicate definitions), we do not redefine grow() here.
74}