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}