1 /*************************************************************************/
2 /* memory.cpp */
3 /*************************************************************************/
4 /* This file is part of: */
5 /* GODOT ENGINE */
6 /* https://godotengine.org */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
9 /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
10 /* */
11 /* Permission is hereby granted, free of charge, to any person obtaining */
12 /* a copy of this software and associated documentation files (the */
13 /* "Software"), to deal in the Software without restriction, including */
14 /* without limitation the rights to use, copy, modify, merge, publish, */
15 /* distribute, sublicense, and/or sell copies of the Software, and to */
16 /* permit persons to whom the Software is furnished to do so, subject to */
17 /* the following conditions: */
18 /* */
19 /* The above copyright notice and this permission notice shall be */
20 /* included in all copies or substantial portions of the Software. */
21 /* */
22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29 /*************************************************************************/
30
31 #include "memory.h"
32
33 #include "core/error_macros.h"
34 #include "core/os/copymem.h"
35 #include "core/safe_refcount.h"
36
37 #include <stdio.h>
38 #include <stdlib.h>
39
operator new(size_t p_size,const char * p_description)40 void *operator new(size_t p_size, const char *p_description) {
41
42 return Memory::alloc_static(p_size, false);
43 }
44
operator new(size_t p_size,void * (* p_allocfunc)(size_t p_size))45 void *operator new(size_t p_size, void *(*p_allocfunc)(size_t p_size)) {
46
47 return p_allocfunc(p_size);
48 }
49
50 #ifdef _MSC_VER
operator delete(void * p_mem,const char * p_description)51 void operator delete(void *p_mem, const char *p_description) {
52
53 CRASH_NOW_MSG("Call to placement delete should not happen.");
54 }
55
operator delete(void * p_mem,void * (* p_allocfunc)(size_t p_size))56 void operator delete(void *p_mem, void *(*p_allocfunc)(size_t p_size)) {
57
58 CRASH_NOW_MSG("Call to placement delete should not happen.");
59 }
60
operator delete(void * p_mem,void * p_pointer,size_t check,const char * p_description)61 void operator delete(void *p_mem, void *p_pointer, size_t check, const char *p_description) {
62
63 CRASH_NOW_MSG("Call to placement delete should not happen.");
64 }
65 #endif
66
67 #ifdef DEBUG_ENABLED
68 uint64_t Memory::mem_usage = 0;
69 uint64_t Memory::max_usage = 0;
70 #endif
71
72 uint64_t Memory::alloc_count = 0;
73
alloc_static(size_t p_bytes,bool p_pad_align)74 void *Memory::alloc_static(size_t p_bytes, bool p_pad_align) {
75
76 #ifdef DEBUG_ENABLED
77 bool prepad = true;
78 #else
79 bool prepad = p_pad_align;
80 #endif
81
82 void *mem = malloc(p_bytes + (prepad ? PAD_ALIGN : 0));
83
84 ERR_FAIL_COND_V(!mem, NULL);
85
86 atomic_increment(&alloc_count);
87
88 if (prepad) {
89 uint64_t *s = (uint64_t *)mem;
90 *s = p_bytes;
91
92 uint8_t *s8 = (uint8_t *)mem;
93
94 #ifdef DEBUG_ENABLED
95 atomic_add(&mem_usage, p_bytes);
96 atomic_exchange_if_greater(&max_usage, mem_usage);
97 #endif
98 return s8 + PAD_ALIGN;
99 } else {
100 return mem;
101 }
102 }
103
realloc_static(void * p_memory,size_t p_bytes,bool p_pad_align)104 void *Memory::realloc_static(void *p_memory, size_t p_bytes, bool p_pad_align) {
105
106 if (p_memory == NULL) {
107 return alloc_static(p_bytes, p_pad_align);
108 }
109
110 uint8_t *mem = (uint8_t *)p_memory;
111
112 #ifdef DEBUG_ENABLED
113 bool prepad = true;
114 #else
115 bool prepad = p_pad_align;
116 #endif
117
118 if (prepad) {
119 mem -= PAD_ALIGN;
120 uint64_t *s = (uint64_t *)mem;
121
122 #ifdef DEBUG_ENABLED
123 if (p_bytes > *s) {
124 atomic_add(&mem_usage, p_bytes - *s);
125 atomic_exchange_if_greater(&max_usage, mem_usage);
126 } else {
127 atomic_sub(&mem_usage, *s - p_bytes);
128 }
129 #endif
130
131 if (p_bytes == 0) {
132 free(mem);
133 return NULL;
134 } else {
135 *s = p_bytes;
136
137 mem = (uint8_t *)realloc(mem, p_bytes + PAD_ALIGN);
138 ERR_FAIL_COND_V(!mem, NULL);
139
140 s = (uint64_t *)mem;
141
142 *s = p_bytes;
143
144 return mem + PAD_ALIGN;
145 }
146 } else {
147
148 mem = (uint8_t *)realloc(mem, p_bytes);
149
150 ERR_FAIL_COND_V(mem == NULL && p_bytes > 0, NULL);
151
152 return mem;
153 }
154 }
155
free_static(void * p_ptr,bool p_pad_align)156 void Memory::free_static(void *p_ptr, bool p_pad_align) {
157
158 ERR_FAIL_COND(p_ptr == NULL);
159
160 uint8_t *mem = (uint8_t *)p_ptr;
161
162 #ifdef DEBUG_ENABLED
163 bool prepad = true;
164 #else
165 bool prepad = p_pad_align;
166 #endif
167
168 atomic_decrement(&alloc_count);
169
170 if (prepad) {
171 mem -= PAD_ALIGN;
172
173 #ifdef DEBUG_ENABLED
174 uint64_t *s = (uint64_t *)mem;
175 atomic_sub(&mem_usage, *s);
176 #endif
177
178 free(mem);
179 } else {
180
181 free(mem);
182 }
183 }
184
get_mem_available()185 uint64_t Memory::get_mem_available() {
186
187 return -1; // 0xFFFF...
188 }
189
get_mem_usage()190 uint64_t Memory::get_mem_usage() {
191 #ifdef DEBUG_ENABLED
192 return mem_usage;
193 #else
194 return 0;
195 #endif
196 }
197
get_mem_max_usage()198 uint64_t Memory::get_mem_max_usage() {
199 #ifdef DEBUG_ENABLED
200 return max_usage;
201 #else
202 return 0;
203 #endif
204 }
205
_GlobalNil()206 _GlobalNil::_GlobalNil() {
207
208 color = 1;
209 left = this;
210 right = this;
211 parent = this;
212 }
213
214 _GlobalNil _GlobalNilClass::_nil;
215