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