History

Move some basic offset functions to header files for inlining ease Replace enum_pointer_field functions with custom implementations - GC now has custom implementation - other implementations use template<> version Fix misuse of shared_ptr<type_descriptor_t> in various built-in types Observed 5 - 8 % improvement in GC for compiler scenario.

arr committed 9 years ago

Commit cd2748b1 parent 3dd1c8210 files · +115 −160Browse files

Showing the changes to src/vm/vm_memory.cpp (1 of 10 files). Show all

Unified · Split

src/vm/vm_memory.cpp+12−107
@@ -83,16 +83,16 @@ void disvm::runtime::init_memory(const type_descriptor_t &type_desc, void *data) · 82 unmodified lines
83 83
84namespace84namespace
85{85{
86 void dec_ref_and_free_pointer_field(pointer_t pointer_field)86 void dec_ref_and_free_pointer_field(pointer_t *pointer_field)
87 {87 {
88 assert(pointer_field != nullptr);88 assert(pointer_field != nullptr && *pointer_field != nullptr);
89 dec_ref_count_and_free(vm_alloc_t::from_allocation(pointer_field));89 dec_ref_count_and_free(vm_alloc_t::from_allocation(*pointer_field));
90 }90 }
91 91
92 void add_ref_pointer_field(pointer_t pointer_field)92 void add_ref_pointer_field(pointer_t *pointer_field)
93 {93 {
94 assert(pointer_field != nullptr);94 assert(pointer_field != nullptr && *pointer_field != nullptr);
95 vm_alloc_t::from_allocation(pointer_field)->add_ref();95 vm_alloc_t::from_allocation(*pointer_field)->add_ref();
96 }96 }
97}97}
98 98
@@ -128,87 +128,6 @@ void disvm::runtime::dec_ref_count_and_free(vm_alloc_t *alloc) · 29 unmodified lines
128 delete alloc;128 delete alloc;
129}129}
130 130
131void disvm::runtime::enum_pointer_fields(const type_descriptor_t &type_desc, void *data, pointer_field_callback_t callback)
132{
133 assert(data != nullptr && callback != nullptr);
134
135 auto memory = reinterpret_cast<word_t *>(data);
136 for (auto i = word_t{ 0 }; i < type_desc.map_in_bytes; ++i, memory += 8)
137 {
138 const auto words8 = type_desc.pointer_map[i];
139 assert(sizeof(words8) == 1);
140 if (words8 == 0)
141 continue;
142
143 const auto flags = std::bitset<sizeof(words8) * 8>{ words8 };
144
145 // Enumerating the flags in reverse order so memory access is sequential.
146 if (flags[7] && (memory[0] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[0]));
147 if (flags[6] && (memory[1] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[1]));
148 if (flags[5] && (memory[2] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[2]));
149 if (flags[4] && (memory[3] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[3]));
150 if (flags[3] && (memory[4] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[4]));
151 if (flags[2] && (memory[5] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[5]));
152 if (flags[1] && (memory[6] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[6]));
153 if (flags[0] && (memory[7] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[7]));
154 }
155}
156
157void disvm::runtime::enum_pointer_fields(const type_descriptor_t &type_desc, void *data, pointer_field_callback_ext_t callback, void *cxt)
158{
159 assert(data != nullptr && callback != nullptr);
160
161 auto memory = reinterpret_cast<word_t *>(data);
162 for (auto i = word_t{ 0 }; i < type_desc.map_in_bytes; ++i, memory += 8)
163 {
164 const auto words8 = type_desc.pointer_map[i];
165 assert(sizeof(words8) == 1);
166 if (words8 == 0)
167 continue;
168
169 const auto flags = std::bitset<sizeof(words8) * 8>{ words8 };
170
171 // Enumerating the flags in reverse order so memory access is sequential.
172 if (flags[7] && (memory[0] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[0]), cxt);
173 if (flags[6] && (memory[1] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[1]), cxt);
174 if (flags[5] && (memory[2] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[2]), cxt);
175 if (flags[4] && (memory[3] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[3]), cxt);
176 if (flags[3] && (memory[4] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[4]), cxt);
177 if (flags[2] && (memory[5] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[5]), cxt);
178 if (flags[1] && (memory[6] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[6]), cxt);
179 if (flags[0] && (memory[7] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[7]), cxt);
180 }
181}
182
183void disvm::runtime::enum_pointer_fields_with_offset(const type_descriptor_t &type_desc, void *data, pointer_field_offset_callback_t callback)
184{
185 assert(data != nullptr && callback != nullptr);
186 if (type_desc.size_in_bytes == 0)
187 return;
188
189 auto offset_accum = std::size_t{ 0 };
190 auto memory = reinterpret_cast<word_t *>(data);
191 for (auto i = word_t{ 0 }; i < type_desc.map_in_bytes; ++i, memory += 8, offset_accum += (8 * sizeof(pointer_t)))
192 {
193 const auto words8 = type_desc.pointer_map[i];
194 assert(sizeof(words8) == 1);
195 if (words8 == 0)
196 continue;
197
198 const auto flags = std::bitset<sizeof(words8) * 8>{ words8 };
199
200 // Enumerating the flags in reverse order so memory access is sequential.
201 if (flags[7] && (memory[0] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[0]), offset_accum);
202 if (flags[6] && (memory[1] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[1]), offset_accum + (1 * sizeof(pointer_t)));
203 if (flags[5] && (memory[2] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[2]), offset_accum + (2 * sizeof(pointer_t)));
204 if (flags[4] && (memory[3] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[3]), offset_accum + (3 * sizeof(pointer_t)));
205 if (flags[3] && (memory[4] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[4]), offset_accum + (4 * sizeof(pointer_t)));
206 if (flags[2] && (memory[5] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[5]), offset_accum + (5 * sizeof(pointer_t)));
207 if (flags[1] && (memory[6] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[6]), offset_accum + (6 * sizeof(pointer_t)));
208 if (flags[0] && (memory[7] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[7]), offset_accum + (7 * sizeof(pointer_t)));
209 }
210}
211
212bool disvm::runtime::is_offset_pointer(const type_descriptor_t &type_desc, std::size_t offset)131bool disvm::runtime::is_offset_pointer(const type_descriptor_t &type_desc, std::size_t offset)
213{132{
214 if (type_desc.size_in_bytes == 0)133 if (type_desc.size_in_bytes == 0)
@@ -247,14 +166,15 @@ void vm_alloc_t::operator delete(void *ptr) · 32 unmodified lines
247vm_alloc_t *vm_alloc_t::allocate(std::shared_ptr<const type_descriptor_t> td)166vm_alloc_t *vm_alloc_t::allocate(std::shared_ptr<const type_descriptor_t> td)
248{167{
249 assert(td != nullptr);168 assert(td != nullptr);
250 if (td->size_in_bytes <= 0)169 const auto type_size_in_bytes = td->size_in_bytes;
170 if (type_size_in_bytes <= 0)
251 throw vm_system_exception{ "Invalid dynamic memory allocation size" };171 throw vm_system_exception{ "Invalid dynamic memory allocation size" };
252 172
253 auto mem = alloc_memory(sizeof(vm_alloc_t) + td->size_in_bytes);173 auto mem = alloc_memory(sizeof(vm_alloc_t) + type_size_in_bytes);
254 auto alloc = ::new(mem)vm_alloc_t{ td };174 auto alloc = ::new(mem)vm_alloc_t{ std::move(td) };
255 175
256 if (disvm::debug::is_component_tracing_enabled<component_trace_t::memory>())176 if (disvm::debug::is_component_tracing_enabled<component_trace_t::memory>())
257 disvm::debug::log_msg(component_trace_t::memory, log_level_t::debug, "init: vm alloc: %d", td->size_in_bytes);177 disvm::debug::log_msg(component_trace_t::memory, log_level_t::debug, "init: vm alloc: %d", type_size_in_bytes);
258 178
259 return alloc;179 return alloc;
260}180}
@@ -273,16 +193,8 @@ vm_alloc_t *vm_alloc_t::copy(const vm_alloc_t &other) · 12 unmodified lines
273 return alloc_copy;193 return alloc_copy;
274}194}
275 195
276vm_alloc_t *vm_alloc_t::from_allocation(pointer_t allocation)
277{
278 if (allocation == nullptr)
279 return nullptr;
280
281 return reinterpret_cast<vm_alloc_t *>(reinterpret_cast<uint8_t *>(allocation) - sizeof(vm_alloc_t));
282}
283
284vm_alloc_t::vm_alloc_t(std::shared_ptr<const type_descriptor_t> td)196vm_alloc_t::vm_alloc_t(std::shared_ptr<const type_descriptor_t> td)
285 : alloc_type{ td }197 : alloc_type{ std::move(td) }
286 , gc_reserved{ nullptr }198 , gc_reserved{ nullptr }
287 , _ref_count{ 1 }199 , _ref_count{ 1 }
288{200{
@@ -330,13 +242,6 @@ std::size_t vm_alloc_t::get_ref_count() const · 41 unmodified lines
330 return _ref_count;242 return _ref_count;
331}243}
332 244
333pointer_t vm_alloc_t::get_allocation() const
334{
335 // Remove const on the this pointer so the offset can be computed.
336 auto non_const_this = const_cast<vm_alloc_t *>(this);
337 return reinterpret_cast<pointer_t>(reinterpret_cast<uint8_t *>(non_const_this)+sizeof(vm_alloc_t));
338}
339
340namespace245namespace
341{246{
342 namespace hidden_type_desc247 namespace hidden_type_desc