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
8383
8484 namespace
8585 {
86− void dec_ref_and_free_pointer_field(pointer_t pointer_field)
86+ void dec_ref_and_free_pointer_field(pointer_t *pointer_field)
8787 {
88− assert(pointer_field != nullptr);
89− dec_ref_count_and_free(vm_alloc_t::from_allocation(pointer_field));
88+ assert(pointer_field != nullptr && *pointer_field != nullptr);
89+ dec_ref_count_and_free(vm_alloc_t::from_allocation(*pointer_field));
9090 }
9191
92− void add_ref_pointer_field(pointer_t pointer_field)
92+ void add_ref_pointer_field(pointer_t *pointer_field)
9393 {
94− assert(pointer_field != nullptr);
95− vm_alloc_t::from_allocation(pointer_field)->add_ref();
94+ assert(pointer_field != nullptr && *pointer_field != nullptr);
95+ vm_alloc_t::from_allocation(*pointer_field)->add_ref();
9696 }
9797 }
9898
@@ -128,87 +128,6 @@ void disvm::runtime::dec_ref_count_and_free(vm_alloc_t *alloc) · 29 unmodified lines
128128 delete alloc;
129129 }
130130
131−void 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−
157−void 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−
183−void 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−
212131 bool disvm::runtime::is_offset_pointer(const type_descriptor_t &type_desc, std::size_t offset)
213132 {
214133 if (type_desc.size_in_bytes == 0)
@@ -247,14 +166,15 @@ void vm_alloc_t::operator delete(void *ptr) · 32 unmodified lines
247166 vm_alloc_t *vm_alloc_t::allocate(std::shared_ptr<const type_descriptor_t> td)
248167 {
249168 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)
251171 throw vm_system_exception{ "Invalid dynamic memory allocation size" };
252172
253− auto mem = alloc_memory(sizeof(vm_alloc_t) + td->size_in_bytes);
254− auto alloc = ::new(mem)vm_alloc_t{ td };
173+ auto mem = alloc_memory(sizeof(vm_alloc_t) + type_size_in_bytes);
174+ auto alloc = ::new(mem)vm_alloc_t{ std::move(td) };
255175
256176 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);
258178
259179 return alloc;
260180 }
@@ -273,16 +193,8 @@ vm_alloc_t *vm_alloc_t::copy(const vm_alloc_t &other) · 12 unmodified lines
273193 return alloc_copy;
274194 }
275195
276−vm_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−
284196 vm_alloc_t::vm_alloc_t(std::shared_ptr<const type_descriptor_t> td)
285− : alloc_type{ td }
197+ : alloc_type{ std::move(td) }
286198 , gc_reserved{ nullptr }
287199 , _ref_count{ 1 }
288200 {
@@ -330,13 +242,6 @@ std::size_t vm_alloc_t::get_ref_count() const · 41 unmodified lines
330242 return _ref_count;
331243 }
332244
333−pointer_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−
340245 namespace
341246 {
342247 namespace hidden_type_desc