23 |
23 |
24 #include "precompiled.hpp" |
24 #include "precompiled.hpp" |
25 #include "gc/z/zList.inline.hpp" |
25 #include "gc/z/zList.inline.hpp" |
26 #include "gc/z/zMemory.inline.hpp" |
26 #include "gc/z/zMemory.inline.hpp" |
27 #include "memory/allocation.inline.hpp" |
27 #include "memory/allocation.inline.hpp" |
|
28 |
|
29 ZMemory* ZMemoryManager::create(uintptr_t start, size_t size) { |
|
30 ZMemory* const area = new ZMemory(start, size); |
|
31 if (_callbacks._create != NULL) { |
|
32 _callbacks._create(area); |
|
33 } |
|
34 return area; |
|
35 } |
|
36 |
|
37 void ZMemoryManager::destroy(ZMemory* area) { |
|
38 if (_callbacks._destroy != NULL) { |
|
39 _callbacks._destroy(area); |
|
40 } |
|
41 delete area; |
|
42 } |
|
43 |
|
44 void ZMemoryManager::shrink_from_front(ZMemory* area, size_t size) { |
|
45 if (_callbacks._shrink_from_front != NULL) { |
|
46 _callbacks._shrink_from_front(area, size); |
|
47 } |
|
48 area->shrink_from_front(size); |
|
49 } |
|
50 |
|
51 void ZMemoryManager::shrink_from_back(ZMemory* area, size_t size) { |
|
52 if (_callbacks._shrink_from_back != NULL) { |
|
53 _callbacks._shrink_from_back(area, size); |
|
54 } |
|
55 area->shrink_from_back(size); |
|
56 } |
|
57 |
|
58 void ZMemoryManager::grow_from_front(ZMemory* area, size_t size) { |
|
59 if (_callbacks._grow_from_front != NULL) { |
|
60 _callbacks._grow_from_front(area, size); |
|
61 } |
|
62 area->grow_from_front(size); |
|
63 } |
|
64 |
|
65 void ZMemoryManager::grow_from_back(ZMemory* area, size_t size) { |
|
66 if (_callbacks._grow_from_back != NULL) { |
|
67 _callbacks._grow_from_back(area, size); |
|
68 } |
|
69 area->grow_from_back(size); |
|
70 } |
|
71 |
|
72 ZMemoryManager::Callbacks::Callbacks() : |
|
73 _create(NULL), |
|
74 _destroy(NULL), |
|
75 _shrink_from_front(NULL), |
|
76 _shrink_from_back(NULL), |
|
77 _grow_from_front(NULL), |
|
78 _grow_from_back(NULL) {} |
|
79 |
|
80 ZMemoryManager::ZMemoryManager() : |
|
81 _freelist(), |
|
82 _callbacks() {} |
|
83 |
|
84 void ZMemoryManager::register_callbacks(const Callbacks& callbacks) { |
|
85 _callbacks = callbacks; |
|
86 } |
28 |
87 |
29 uintptr_t ZMemoryManager::alloc_from_front(size_t size) { |
88 uintptr_t ZMemoryManager::alloc_from_front(size_t size) { |
30 ZListIterator<ZMemory> iter(&_freelist); |
89 ZListIterator<ZMemory> iter(&_freelist); |
31 for (ZMemory* area; iter.next(&area);) { |
90 for (ZMemory* area; iter.next(&area);) { |
32 if (area->size() >= size) { |
91 if (area->size() >= size) { |
33 if (area->size() == size) { |
92 if (area->size() == size) { |
34 // Exact match, remove area |
93 // Exact match, remove area |
35 const uintptr_t start = area->start(); |
94 const uintptr_t start = area->start(); |
36 _freelist.remove(area); |
95 _freelist.remove(area); |
37 delete area; |
96 destroy(area); |
38 return start; |
97 return start; |
39 } else { |
98 } else { |
40 // Larger than requested, shrink area |
99 // Larger than requested, shrink area |
41 const uintptr_t start = area->start(); |
100 const uintptr_t start = area->start(); |
42 area->shrink_from_front(size); |
101 shrink_from_front(area, size); |
43 return start; |
102 return start; |
44 } |
103 } |
45 } |
104 } |
46 } |
105 } |
47 |
106 |
55 if (area->size() <= size) { |
114 if (area->size() <= size) { |
56 // Smaller than or equal to requested, remove area |
115 // Smaller than or equal to requested, remove area |
57 const uintptr_t start = area->start(); |
116 const uintptr_t start = area->start(); |
58 *allocated = area->size(); |
117 *allocated = area->size(); |
59 _freelist.remove(area); |
118 _freelist.remove(area); |
60 delete area; |
119 destroy(area); |
61 return start; |
120 return start; |
62 } else { |
121 } else { |
63 // Larger than requested, shrink area |
122 // Larger than requested, shrink area |
64 const uintptr_t start = area->start(); |
123 const uintptr_t start = area->start(); |
65 area->shrink_from_front(size); |
124 shrink_from_front(area, size); |
66 *allocated = size; |
125 *allocated = size; |
67 return start; |
126 return start; |
68 } |
127 } |
69 } |
128 } |
70 |
129 |
79 if (area->size() >= size) { |
138 if (area->size() >= size) { |
80 if (area->size() == size) { |
139 if (area->size() == size) { |
81 // Exact match, remove area |
140 // Exact match, remove area |
82 const uintptr_t start = area->start(); |
141 const uintptr_t start = area->start(); |
83 _freelist.remove(area); |
142 _freelist.remove(area); |
84 delete area; |
143 destroy(area); |
85 return start; |
144 return start; |
86 } else { |
145 } else { |
87 // Larger than requested, shrink area |
146 // Larger than requested, shrink area |
88 area->shrink_from_back(size); |
147 shrink_from_back(area, size); |
89 return area->end(); |
148 return area->end(); |
90 } |
149 } |
91 } |
150 } |
92 } |
151 } |
93 |
152 |
101 if (area->size() <= size) { |
160 if (area->size() <= size) { |
102 // Smaller than or equal to requested, remove area |
161 // Smaller than or equal to requested, remove area |
103 const uintptr_t start = area->start(); |
162 const uintptr_t start = area->start(); |
104 *allocated = area->size(); |
163 *allocated = area->size(); |
105 _freelist.remove(area); |
164 _freelist.remove(area); |
106 delete area; |
165 destroy(area); |
107 return start; |
166 return start; |
108 } else { |
167 } else { |
109 // Larger than requested, shrink area |
168 // Larger than requested, shrink area |
110 area->shrink_from_back(size); |
169 shrink_from_back(area, size); |
111 *allocated = size; |
170 *allocated = size; |
112 return area->end(); |
171 return area->end(); |
113 } |
172 } |
114 } |
173 } |
115 |
174 |
127 if (start < area->start()) { |
186 if (start < area->start()) { |
128 ZMemory* const prev = _freelist.prev(area); |
187 ZMemory* const prev = _freelist.prev(area); |
129 if (prev != NULL && start == prev->end()) { |
188 if (prev != NULL && start == prev->end()) { |
130 if (end == area->start()) { |
189 if (end == area->start()) { |
131 // Merge with prev and current area |
190 // Merge with prev and current area |
132 prev->grow_from_back(size + area->size()); |
191 grow_from_back(prev, size + area->size()); |
133 _freelist.remove(area); |
192 _freelist.remove(area); |
134 delete area; |
193 delete area; |
135 } else { |
194 } else { |
136 // Merge with prev area |
195 // Merge with prev area |
137 prev->grow_from_back(size); |
196 grow_from_back(prev, size); |
138 } |
197 } |
139 } else if (end == area->start()) { |
198 } else if (end == area->start()) { |
140 // Merge with current area |
199 // Merge with current area |
141 area->grow_from_front(size); |
200 grow_from_front(area, size); |
142 } else { |
201 } else { |
143 // Insert new area before current area |
202 // Insert new area before current area |
144 assert(end < area->start(), "Areas must not overlap"); |
203 assert(end < area->start(), "Areas must not overlap"); |
145 ZMemory* new_area = new ZMemory(start, size); |
204 ZMemory* const new_area = create(start, size); |
146 _freelist.insert_before(area, new_area); |
205 _freelist.insert_before(area, new_area); |
147 } |
206 } |
148 |
207 |
149 // Done |
208 // Done |
150 return; |
209 return; |
153 |
212 |
154 // Insert last |
213 // Insert last |
155 ZMemory* const last = _freelist.last(); |
214 ZMemory* const last = _freelist.last(); |
156 if (last != NULL && start == last->end()) { |
215 if (last != NULL && start == last->end()) { |
157 // Merge with last area |
216 // Merge with last area |
158 last->grow_from_back(size); |
217 grow_from_back(last, size); |
159 } else { |
218 } else { |
160 // Insert new area last |
219 // Insert new area last |
161 ZMemory* new_area = new ZMemory(start, size); |
220 ZMemory* const new_area = create(start, size); |
162 _freelist.insert_last(new_area); |
221 _freelist.insert_last(new_area); |
163 } |
222 } |
164 } |
223 } |