Skip to content

Commit 19d9b04

Browse files
authored
Merge pull request godotengine#86730 from reduz/64-bit-cowdata
Promote CowData to 64 bits
2 parents 2fd387b + 45b3b16 commit 19d9b04

10 files changed

Lines changed: 145 additions & 114 deletions

File tree

core/io/packet_peer.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -318,9 +318,9 @@ int PacketPeerStream::get_output_buffer_max_size() const {
318318
}
319319

320320
PacketPeerStream::PacketPeerStream() {
321-
int rbsize = GLOBAL_GET("network/limits/packet_peer_stream/max_buffer_po2");
321+
int64_t rbsize = GLOBAL_GET("network/limits/packet_peer_stream/max_buffer_po2");
322322

323323
ring_buffer.resize(rbsize);
324-
input_buffer.resize(1 << rbsize);
325-
output_buffer.resize(1 << rbsize);
324+
input_buffer.resize(int64_t(1) << rbsize);
325+
output_buffer.resize(int64_t(1) << rbsize);
326326
}

core/templates/cowdata.h

Lines changed: 91 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class CharString;
4646
template <class T, class V>
4747
class 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+
6772
private:
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

121147
public:
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

224250
template <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

262289
template <class T>
263290
template <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

342372
template <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

360390
template <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

379409
template <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
}

core/templates/ring_buffer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ class RingBuffer {
197197
int old_size = size();
198198
int new_size = 1 << p_power;
199199
int mask = new_size - 1;
200-
data.resize(1 << p_power);
200+
data.resize(int64_t(1) << int64_t(p_power));
201201
if (old_size < new_size && read_pos > write_pos) {
202202
for (int i = 0; i < write_pos; i++) {
203203
data.write[(old_size + i) & mask] = data[i];

0 commit comments

Comments
 (0)