@@ -46,7 +46,7 @@ class CharString;
4646template <class T , class V >
4747class VMap ;
4848
49- SAFE_NUMERIC_TYPE_PUN_GUARANTEES (uint32_t )
49+ SAFE_NUMERIC_TYPE_PUN_GUARANTEES (uint64_t )
5050
5151// Silence a false positive warning (see GH-52119).
5252#if defined(__GNUC__) && !defined(__clang__)
@@ -64,45 +64,71 @@ class CowData {
6464 template <class TV , class VV >
6565 friend class VMap ;
6666
67+ public:
68+ typedef int64_t Size;
69+ typedef uint64_t USize;
70+ static constexpr USize MAX_INT = INT64_MAX ;
71+
6772private:
73+ // Function to find the next power of 2 to an integer.
74+ static _FORCE_INLINE_ USize next_po2 (USize x) {
75+ if (x == 0 ) {
76+ return 0 ;
77+ }
78+
79+ --x;
80+ x |= x >> 1 ;
81+ x |= x >> 2 ;
82+ x |= x >> 4 ;
83+ x |= x >> 8 ;
84+ x |= x >> 16 ;
85+ if (sizeof (USize) == 8 ) {
86+ x |= x >> 32 ;
87+ }
88+
89+ return ++x;
90+ }
91+
92+ static constexpr USize ALLOC_PAD = sizeof (USize) * 2 ; // For size and atomic refcount.
93+
6894 mutable T *_ptr = nullptr ;
6995
7096 // internal helpers
7197
72- _FORCE_INLINE_ SafeNumeric<uint32_t > *_get_refcount () const {
98+ _FORCE_INLINE_ SafeNumeric<USize > *_get_refcount () const {
7399 if (!_ptr) {
74100 return nullptr ;
75101 }
76102
77- return reinterpret_cast <SafeNumeric<uint32_t > *>(_ptr) - 2 ;
103+ return reinterpret_cast <SafeNumeric<USize > *>(_ptr) - 2 ;
78104 }
79105
80- _FORCE_INLINE_ uint32_t *_get_size () const {
106+ _FORCE_INLINE_ USize *_get_size () const {
81107 if (!_ptr) {
82108 return nullptr ;
83109 }
84110
85- return reinterpret_cast <uint32_t *>(_ptr) - 1 ;
111+ return reinterpret_cast <USize *>(_ptr) - 1 ;
86112 }
87113
88- _FORCE_INLINE_ size_t _get_alloc_size (size_t p_elements) const {
89- return next_power_of_2 (p_elements * sizeof (T));
114+ _FORCE_INLINE_ USize _get_alloc_size (USize p_elements) const {
115+ return next_po2 (p_elements * sizeof (T));
90116 }
91117
92- _FORCE_INLINE_ bool _get_alloc_size_checked (size_t p_elements, size_t *out) const {
118+ _FORCE_INLINE_ bool _get_alloc_size_checked (USize p_elements, USize *out) const {
93119 if (unlikely (p_elements == 0 )) {
94120 *out = 0 ;
95121 return true ;
96122 }
97- #if defined(__GNUC__)
98- size_t o;
99- size_t p;
123+ #if defined(__GNUC__) && defined(IS_32_BIT)
124+ USize o;
125+ USize p;
100126 if (__builtin_mul_overflow (p_elements, sizeof (T), &o)) {
101127 *out = 0 ;
102128 return false ;
103129 }
104- *out = next_power_of_2 (o);
105- if (__builtin_add_overflow (o, static_cast <size_t >(32 ), &p)) {
130+ *out = next_po2 (o);
131+ if (__builtin_add_overflow (o, static_cast <USize >(32 ), &p)) {
106132 return false ; // No longer allocated here.
107133 }
108134#else
@@ -116,7 +142,7 @@ class CowData {
116142 void _unref (void *p_data);
117143 void _ref (const CowData *p_from);
118144 void _ref (const CowData &p_from);
119- uint32_t _copy_on_write ();
145+ USize _copy_on_write ();
120146
121147public:
122148 void operator =(const CowData<T> &p_from) { _ref (p_from); }
@@ -130,8 +156,8 @@ class CowData {
130156 return _ptr;
131157 }
132158
133- _FORCE_INLINE_ int size () const {
134- uint32_t *size = (uint32_t *)_get_size ();
159+ _FORCE_INLINE_ Size size () const {
160+ USize *size = (USize *)_get_size ();
135161 if (size) {
136162 return *size;
137163 } else {
@@ -142,52 +168,52 @@ class CowData {
142168 _FORCE_INLINE_ void clear () { resize (0 ); }
143169 _FORCE_INLINE_ bool is_empty () const { return _ptr == nullptr ; }
144170
145- _FORCE_INLINE_ void set (int p_index, const T &p_elem) {
171+ _FORCE_INLINE_ void set (Size p_index, const T &p_elem) {
146172 ERR_FAIL_INDEX (p_index, size ());
147173 _copy_on_write ();
148174 _ptr[p_index] = p_elem;
149175 }
150176
151- _FORCE_INLINE_ T &get_m (int p_index) {
177+ _FORCE_INLINE_ T &get_m (Size p_index) {
152178 CRASH_BAD_INDEX (p_index, size ());
153179 _copy_on_write ();
154180 return _ptr[p_index];
155181 }
156182
157- _FORCE_INLINE_ const T &get (int p_index) const {
183+ _FORCE_INLINE_ const T &get (Size p_index) const {
158184 CRASH_BAD_INDEX (p_index, size ());
159185
160186 return _ptr[p_index];
161187 }
162188
163189 template <bool p_ensure_zero = false >
164- Error resize (int p_size);
190+ Error resize (Size p_size);
165191
166- _FORCE_INLINE_ void remove_at (int p_index) {
192+ _FORCE_INLINE_ void remove_at (Size p_index) {
167193 ERR_FAIL_INDEX (p_index, size ());
168194 T *p = ptrw ();
169- int len = size ();
170- for (int i = p_index; i < len - 1 ; i++) {
195+ Size len = size ();
196+ for (Size i = p_index; i < len - 1 ; i++) {
171197 p[i] = p[i + 1 ];
172198 }
173199
174200 resize (len - 1 );
175201 }
176202
177- Error insert (int p_pos, const T &p_val) {
203+ Error insert (Size p_pos, const T &p_val) {
178204 ERR_FAIL_INDEX_V (p_pos, size () + 1 , ERR_INVALID_PARAMETER );
179205 resize (size () + 1 );
180- for (int i = (size () - 1 ); i > p_pos; i--) {
206+ for (Size i = (size () - 1 ); i > p_pos; i--) {
181207 set (i, get (i - 1 ));
182208 }
183209 set (p_pos, p_val);
184210
185211 return OK ;
186212 }
187213
188- int find (const T &p_val, int p_from = 0 ) const ;
189- int rfind (const T &p_val, int p_from = -1 ) const ;
190- int count (const T &p_val) const ;
214+ Size find (const T &p_val, Size p_from = 0 ) const ;
215+ Size rfind (const T &p_val, Size p_from = -1 ) const ;
216+ Size count (const T &p_val) const ;
191217
192218 _FORCE_INLINE_ CowData () {}
193219 _FORCE_INLINE_ ~CowData ();
@@ -200,43 +226,44 @@ void CowData<T>::_unref(void *p_data) {
200226 return ;
201227 }
202228
203- SafeNumeric<uint32_t > *refc = _get_refcount ();
229+ SafeNumeric<USize > *refc = _get_refcount ();
204230
205231 if (refc->decrement () > 0 ) {
206232 return ; // still in use
207233 }
208234 // clean up
209235
210236 if (!std::is_trivially_destructible<T>::value) {
211- uint32_t *count = _get_size ();
237+ USize *count = _get_size ();
212238 T *data = (T *)(count + 1 );
213239
214- for (uint32_t i = 0 ; i < *count; ++i) {
240+ for (USize i = 0 ; i < *count; ++i) {
215241 // call destructors
216242 data[i].~T ();
217243 }
218244 }
219245
220246 // free mem
221- Memory::free_static ((uint8_t *)p_data, true );
247+ Memory::free_static ((( uint8_t *)p_data) - ALLOC_PAD , false );
222248}
223249
224250template <class T >
225- uint32_t CowData<T>::_copy_on_write() {
251+ typename CowData<T>::USize CowData<T>::_copy_on_write() {
226252 if (!_ptr) {
227253 return 0 ;
228254 }
229255
230- SafeNumeric<uint32_t > *refc = _get_refcount ();
256+ SafeNumeric<USize > *refc = _get_refcount ();
231257
232- uint32_t rc = refc->get ();
258+ USize rc = refc->get ();
233259 if (unlikely (rc > 1 )) {
234260 /* in use by more than me */
235- uint32_t current_size = *_get_size ();
261+ USize current_size = *_get_size ();
236262
237- uint32_t *mem_new = (uint32_t *)Memory::alloc_static (_get_alloc_size (current_size), true );
263+ USize *mem_new = (USize *)Memory::alloc_static (_get_alloc_size (current_size) + ALLOC_PAD , false );
264+ mem_new += 2 ;
238265
239- new (mem_new - 2 ) SafeNumeric<uint32_t >(1 ); // refcount
266+ new (mem_new - 2 ) SafeNumeric<USize >(1 ); // refcount
240267 *(mem_new - 1 ) = current_size; // size
241268
242269 T *_data = (T *)(mem_new);
@@ -246,7 +273,7 @@ uint32_t CowData<T>::_copy_on_write() {
246273 memcpy (mem_new, _ptr, current_size * sizeof (T));
247274
248275 } else {
249- for (uint32_t i = 0 ; i < current_size; i++) {
276+ for (USize i = 0 ; i < current_size; i++) {
250277 memnew_placement (&_data[i], T (_ptr[i]));
251278 }
252279 }
@@ -261,10 +288,10 @@ uint32_t CowData<T>::_copy_on_write() {
261288
262289template <class T >
263290template <bool p_ensure_zero>
264- Error CowData<T>::resize(int p_size) {
291+ Error CowData<T>::resize(Size p_size) {
265292 ERR_FAIL_COND_V (p_size < 0 , ERR_INVALID_PARAMETER );
266293
267- int current_size = size ();
294+ Size current_size = size ();
268295
269296 if (p_size == current_size) {
270297 return OK ;
@@ -278,27 +305,29 @@ Error CowData<T>::resize(int p_size) {
278305 }
279306
280307 // possibly changing size, copy on write
281- uint32_t rc = _copy_on_write ();
308+ USize rc = _copy_on_write ();
282309
283- size_t current_alloc_size = _get_alloc_size (current_size);
284- size_t alloc_size;
310+ USize current_alloc_size = _get_alloc_size (current_size);
311+ USize alloc_size;
285312 ERR_FAIL_COND_V (!_get_alloc_size_checked (p_size, &alloc_size), ERR_OUT_OF_MEMORY );
286313
287314 if (p_size > current_size) {
288315 if (alloc_size != current_alloc_size) {
289316 if (current_size == 0 ) {
290317 // alloc from scratch
291- uint32_t *ptr = (uint32_t *)Memory::alloc_static (alloc_size, true );
318+ USize *ptr = (USize *)Memory::alloc_static (alloc_size + ALLOC_PAD , false );
319+ ptr += 2 ;
292320 ERR_FAIL_NULL_V (ptr, ERR_OUT_OF_MEMORY );
293321 *(ptr - 1 ) = 0 ; // size, currently none
294- new (ptr - 2 ) SafeNumeric<uint32_t >(1 ); // refcount
322+ new (ptr - 2 ) SafeNumeric<USize >(1 ); // refcount
295323
296324 _ptr = (T *)ptr;
297325
298326 } else {
299- uint32_t *_ptrnew = (uint32_t *)Memory::realloc_static (_ptr, alloc_size, true );
327+ USize *_ptrnew = (USize *)Memory::realloc_static ((( uint8_t *) _ptr) - ALLOC_PAD , alloc_size + ALLOC_PAD , false );
300328 ERR_FAIL_NULL_V (_ptrnew, ERR_OUT_OF_MEMORY );
301- new (_ptrnew - 2 ) SafeNumeric<uint32_t >(rc); // refcount
329+ _ptrnew += 2 ;
330+ new (_ptrnew - 2 ) SafeNumeric<USize>(rc); // refcount
302331
303332 _ptr = (T *)(_ptrnew);
304333 }
@@ -307,7 +336,7 @@ Error CowData<T>::resize(int p_size) {
307336 // construct the newly created elements
308337
309338 if (!std::is_trivially_constructible<T>::value) {
310- for (int i = *_get_size (); i < p_size; i++) {
339+ for (Size i = *_get_size (); i < p_size; i++) {
311340 memnew_placement (&_ptr[i], T);
312341 }
313342 } else if (p_ensure_zero) {
@@ -319,16 +348,17 @@ Error CowData<T>::resize(int p_size) {
319348 } else if (p_size < current_size) {
320349 if (!std::is_trivially_destructible<T>::value) {
321350 // deinitialize no longer needed elements
322- for (uint32_t i = p_size; i < *_get_size (); i++) {
351+ for (USize i = p_size; i < *_get_size (); i++) {
323352 T *t = &_ptr[i];
324353 t->~T ();
325354 }
326355 }
327356
328357 if (alloc_size != current_alloc_size) {
329- uint32_t *_ptrnew = (uint32_t *)Memory::realloc_static (_ptr, alloc_size, true );
358+ USize *_ptrnew = (USize *)Memory::realloc_static ((( uint8_t *) _ptr) - ALLOC_PAD , alloc_size + ALLOC_PAD , false );
330359 ERR_FAIL_NULL_V (_ptrnew, ERR_OUT_OF_MEMORY );
331- new (_ptrnew - 2 ) SafeNumeric<uint32_t >(rc); // refcount
360+ _ptrnew += 2 ;
361+ new (_ptrnew - 2 ) SafeNumeric<USize>(rc); // refcount
332362
333363 _ptr = (T *)(_ptrnew);
334364 }
@@ -340,14 +370,14 @@ Error CowData<T>::resize(int p_size) {
340370}
341371
342372template <class T >
343- int CowData<T>::find(const T &p_val, int p_from) const {
344- int ret = -1 ;
373+ typename CowData<T>::Size CowData<T>:: find(const T &p_val, Size p_from) const {
374+ Size ret = -1 ;
345375
346376 if (p_from < 0 || size () == 0 ) {
347377 return ret;
348378 }
349379
350- for (int i = p_from; i < size (); i++) {
380+ for (Size i = p_from; i < size (); i++) {
351381 if (get (i) == p_val) {
352382 ret = i;
353383 break ;
@@ -358,8 +388,8 @@ int CowData<T>::find(const T &p_val, int p_from) const {
358388}
359389
360390template <class T >
361- int CowData<T>::rfind(const T &p_val, int p_from) const {
362- const int s = size ();
391+ typename CowData<T>::Size CowData<T>:: rfind(const T &p_val, Size p_from) const {
392+ const Size s = size ();
363393
364394 if (p_from < 0 ) {
365395 p_from = s + p_from;
@@ -368,7 +398,7 @@ int CowData<T>::rfind(const T &p_val, int p_from) const {
368398 p_from = s - 1 ;
369399 }
370400
371- for (int i = p_from; i >= 0 ; i--) {
401+ for (Size i = p_from; i >= 0 ; i--) {
372402 if (get (i) == p_val) {
373403 return i;
374404 }
@@ -377,9 +407,9 @@ int CowData<T>::rfind(const T &p_val, int p_from) const {
377407}
378408
379409template <class T >
380- int CowData<T>::count(const T &p_val) const {
381- int amount = 0 ;
382- for (int i = 0 ; i < size (); i++) {
410+ typename CowData<T>::Size CowData<T>::count(const T &p_val) const {
411+ Size amount = 0 ;
412+ for (Size i = 0 ; i < size (); i++) {
383413 if (get (i) == p_val) {
384414 amount++;
385415 }
0 commit comments