History

Address more bugs found during limbo compiler testing

arr committed 9 years ago

Commit 84ac3311 parent 220aaf26 files · +52 −63Browse files

Unified · Split

6 files
  1. src/include/runtime.h +1 −1
  2. src/include/vm_memory.h +20 −15
  3. src/vm/array.cpp +5 −8
  4. src/vm/execution_table.cpp +1 −3
  5. src/vm/string.cpp +16 −30
  6. src/vm/vm_memory.cpp +9 −6
src/include/runtime.h+1−1
@@ -198,7 +198,7 @@ namespace disvm · 197 unmodified lines
198 198
199 public:199 public:
200 vm_array_t(std::shared_ptr<const type_descriptor_t> td, word_t length);200 vm_array_t(std::shared_ptr<const type_descriptor_t> td, word_t length);
201 vm_array_t(vm_array_t *original, word_t begin_index, word_t length);201 vm_array_t(vm_array_t &original, word_t begin_index, word_t length);
202 vm_array_t(const vm_string_t *s);202 vm_array_t(const vm_string_t *s);
203 ~vm_array_t();203 ~vm_array_t();
204 204
src/include/vm_memory.h+20−15
@@ -60,9 +60,12 @@ namespace disvm · 59 unmodified lines
60 // Destroy supplied memory based on the type descriptor60 // Destroy supplied memory based on the type descriptor
61 void destroy_memory(const type_descriptor_t &type_desc, void *data);61 void destroy_memory(const type_descriptor_t &type_desc, void *data);
62 62
63 // Increment the ref count of all points in the supplied memory allocation63 // Increment the ref count of all pointers in the supplied memory allocation
64 void inc_ref_count_in_memory(const type_descriptor_t &type_desc, void *data);64 void inc_ref_count_in_memory(const type_descriptor_t &type_desc, void *data);
65 65
66 // Decrement the ref count of all pointers in the supplied memory allocation
67 void dec_ref_count_in_memory(const type_descriptor_t &type_desc, void *data);
68
66 // Decrement the ref count and if 0 free the allocation69 // Decrement the ref count and if 0 free the allocation
67 void dec_ref_count_and_free(vm_alloc_t *alloc);70 void dec_ref_count_and_free(vm_alloc_t *alloc);
68 71
@@ -81,20 +84,21 @@ namespace disvm · 12 unmodified lines
81 for (auto i = word_t{ 0 }; i < type_desc.map_in_bytes; ++i, memory += 8, offset_accum += (8 * sizeof(pointer_t)))84 for (auto i = word_t{ 0 }; i < type_desc.map_in_bytes; ++i, memory += 8, offset_accum += (8 * sizeof(pointer_t)))
82 {85 {
83 const auto words8 = type_desc.pointer_map[i];86 const auto words8 = type_desc.pointer_map[i];
84 if (words8 != 0)87 assert(sizeof(words8) == 1);
85 {88 if (words8 == 0)
86 const auto flags = std::bitset<sizeof(words8) * 8>{ words8 };89 continue;
87 90
88 // Enumerating the flags in reverse order so memory access is sequential.91 const auto flags = std::bitset<sizeof(words8) * 8>{ words8 };
89 if (flags[7] && (memory[0] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[0]), offset_accum);92
90 if (flags[6] && (memory[1] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[1]), offset_accum + (1 * sizeof(pointer_t)));93 // Enumerating the flags in reverse order so memory access is sequential.
91 if (flags[5] && (memory[2] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[2]), offset_accum + (2 * sizeof(pointer_t)));94 if (flags[7] && (memory[0] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[0]), offset_accum);
92 if (flags[4] && (memory[3] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[3]), offset_accum + (3 * sizeof(pointer_t)));95 if (flags[6] && (memory[1] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[1]), offset_accum + (1 * sizeof(pointer_t)));
93 if (flags[3] && (memory[4] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[4]), offset_accum + (4 * sizeof(pointer_t)));96 if (flags[5] && (memory[2] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[2]), offset_accum + (2 * sizeof(pointer_t)));
94 if (flags[2] && (memory[5] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[5]), offset_accum + (5 * sizeof(pointer_t)));97 if (flags[4] && (memory[3] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[3]), offset_accum + (3 * sizeof(pointer_t)));
95 if (flags[1] && (memory[6] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[6]), offset_accum + (6 * sizeof(pointer_t)));98 if (flags[3] && (memory[4] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[4]), offset_accum + (4 * sizeof(pointer_t)));
96 if (flags[0] && (memory[7] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[7]), offset_accum + (7 * sizeof(pointer_t)));99 if (flags[2] && (memory[5] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[5]), offset_accum + (5 * sizeof(pointer_t)));
97 }100 if (flags[1] && (memory[6] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[6]), offset_accum + (6 * sizeof(pointer_t)));
101 if (flags[0] && (memory[7] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[7]), offset_accum + (7 * sizeof(pointer_t)));
98 }102 }
99 }103 }
100 104
@@ -112,6 +116,7 @@ namespace disvm · 11 unmodified lines
112 if (byte_offset < type_desc.map_in_bytes)116 if (byte_offset < type_desc.map_in_bytes)
113 {117 {
114 const auto words8 = type_desc.pointer_map[byte_offset];118 const auto words8 = type_desc.pointer_map[byte_offset];
119 assert(sizeof(words8) == 1);
115 if (words8 != 0)120 if (words8 != 0)
116 {121 {
117 const auto flags = std::bitset<sizeof(words8) * 8>{ words8 };122 const auto flags = std::bitset<sizeof(words8) * 8>{ words8 };
src/vm/array.cpp+5−8
@@ -43,16 +43,14 @@ vm_array_t::vm_array_t(std::shared_ptr<const type_descriptor_t> td, word_t lengt · 42 unmodified lines
43 debug::log_msg(debug::component_trace_t::memory, debug::log_level_t::debug, "end: init: elements: %d", array_len);43 debug::log_msg(debug::component_trace_t::memory, debug::log_level_t::debug, "end: init: elements: %d", array_len);
44}44}
45 45
46vm_array_t::vm_array_t(vm_array_t *original, word_t begin_index, word_t length)46vm_array_t::vm_array_t(vm_array_t &original, word_t begin_index, word_t length)
47 : vm_alloc_t(vm_array_t::type_desc())47 : vm_alloc_t(vm_array_t::type_desc())
48 , _arr{ nullptr }48 , _arr{ nullptr }
49 , _element_type{ original->get_element_type() }49 , _element_type{ original.get_element_type() }
50 , _length{ length }50 , _length{ length }
51 , _original{ original }51 , _original{ &original }
52{52{
53 assert(_original != nullptr);53 assert(0 <= begin_index && (begin_index < _original->get_length() || (begin_index == _original->get_length() && length == 0)));
54 assert(0 <= begin_index && begin_index < _original->get_length());
55 assert(_length >= 0 && (_length + begin_index) <= _original->get_length());
56 54
57 if (debug::is_component_tracing_enabled<debug::component_trace_t::memory>())55 if (debug::is_component_tracing_enabled<debug::component_trace_t::memory>())
58 debug::log_msg(debug::component_trace_t::memory, debug::log_level_t::debug, "init: vm array: slice: %d %d", begin_index, _length);56 debug::log_msg(debug::component_trace_t::memory, debug::log_level_t::debug, "init: vm array: slice: %d %d", begin_index, _length);
@@ -164,7 +162,6 @@ void vm_array_t::copy_from(const vm_array_t &source, word_t this_begin_index) · 105 unmodified lines
164 {162 {
165 // [PERF] There is a chance this copy is within the same array, therefore163 // [PERF] There is a chance this copy is within the same array, therefore
166 // a check could be made to not ref count memory that is going to be moved.164 // a check could be made to not ref count memory that is going to be moved.
167 // The Inferno implementation of slicela handles this case (libinterp/xec.c).
168 const auto &type_desc = *_element_type;165 const auto &type_desc = *_element_type;
169 auto source_array_element = source._arr;166 auto source_array_element = source._arr;
170 auto dest_array_element = dest_arr;167 auto dest_array_element = dest_arr;
@@ -173,7 +170,7 @@ void vm_array_t::copy_from(const vm_array_t &source, word_t this_begin_index) · 2 unmodified lines
173 inc_ref_count_in_memory(type_desc, source_array_element);170 inc_ref_count_in_memory(type_desc, source_array_element);
174 source_array_element += type_desc.size_in_bytes;171 source_array_element += type_desc.size_in_bytes;
175 172
176 destroy_memory(type_desc, dest_array_element);173 dec_ref_count_in_memory(type_desc, dest_array_element);
177 dest_array_element += type_desc.size_in_bytes;174 dest_array_element += type_desc.size_in_bytes;
178 }175 }
179 }176 }
src/vm/execution_table.cpp+1−3
@@ -548,8 +548,6 @@ namespace · 547 unmodified lines
548 auto type = types[type_id];548 auto type = types[type_id];
549 549
550 disvm::runtime::inc_ref_count_in_memory(*type, r.src);550 disvm::runtime::inc_ref_count_in_memory(*type, r.src);
551
552 // Decrement allocated pointers in the destination.
553 destroy_memory(*type, r.dest);551 destroy_memory(*type, r.dest);
554 552
555 assert(r.src != nullptr && r.dest != nullptr);553 assert(r.src != nullptr && r.dest != nullptr);
@@ -863,7 +861,7 @@ namespace · 307 unmodified lines
863 throw out_of_range_memory{};861 throw out_of_range_memory{};
864 }862 }
865 863
866 auto new_array = new vm_array_t(arr, begin_index, length);864 auto new_array = new vm_array_t(*arr, begin_index, length);
867 865
868 if (arr->alloc_type->map_in_bytes > 0)866 if (arr->alloc_type->map_in_bytes > 0)
869 vm.get_garbage_collector().track_allocation(new_array);867 vm.get_garbage_collector().track_allocation(new_array);
src/vm/string.cpp+16−30
@@ -301,23 +301,17 @@ vm_string_t::vm_string_t(const vm_string_t &other, word_t begin_index, word_t en · 300 unmodified lines
301 301
302vm_string_t::~vm_string_t()302vm_string_t::~vm_string_t()
303{303{
304 // Free memory and string buffer304 // Determine if local or allocated memory
305 if (_is_alloc)305 auto source = (_is_alloc) ? _mem.alloc : _mem.local;
306 {306 if (static_cast<void *>(source) != static_cast<void *>(_encoded_str))
307 if (static_cast<void *>(_mem.alloc) != static_cast<void *>(_encoded_str))307 free_memory(_encoded_str);
308 free_memory(_encoded_str);
309 308
310 free_memory(_mem.alloc);309 if (_is_alloc)
311 }310 free_memory(source);
312 else
313 {
314 if (static_cast<void *>(_mem.local) != static_cast<void *>(_encoded_str))
315 free_memory(_encoded_str);
316 }
317 311
318 debug::log_msg(debug::component_trace_t::memory, debug::log_level_t::debug, "destroy: vm string");312 debug::log_msg(debug::component_trace_t::memory, debug::log_level_t::debug, "destroy: vm string");
319 313
320 debug::assign_debug_pointer(&_mem.alloc);314 debug::assign_debug_pointer(&source);
321 debug::assign_debug_pointer(&_encoded_str);315 debug::assign_debug_pointer(&_encoded_str);
322}316}
323 317
@@ -341,14 +335,10 @@ vm_string_t &vm_string_t::append(const vm_string_t &other) · 17 unmodified lines
341 const auto local_source = (_is_alloc) ? _mem.alloc : _mem.local;335 const auto local_source = (_is_alloc) ? _mem.alloc : _mem.local;
342 336
343 // Release the encoded string for this instance.337 // Release the encoded string for this instance.
344 {338 if (_encoded_str != reinterpret_cast<char*>(local_source))
345 std::lock_guard<std::mutex> lock{ _encoded_str_lock };339 free_memory(_encoded_str);
346 if (_encoded_str != reinterpret_cast<char*>(local_source))340
347 {341 _encoded_str = nullptr;
348 free_memory(_encoded_str);
349 _encoded_str = nullptr;
350 }
351 }
352 342
353 // Define the values for the appended string343 // Define the values for the appended string
354 const auto new_length = local_length + other_length;344 const auto new_length = local_length + other_length;
@@ -427,17 +417,12 @@ void vm_string_t::set_rune(word_t index, rune_t value) · 72 unmodified lines
427 throw index_out_of_range_memory{ 0, _length, index };417 throw index_out_of_range_memory{ 0, _length, index };
428 418
429 // Determine if local or allocated memory419 // Determine if local or allocated memory
430 auto source = static_cast<uint8_t *>(_mem.local);420 auto source = (_is_alloc) ? _mem.alloc : _mem.local;
431 if (_is_alloc)
432 {
433 source = static_cast<uint8_t *>(_mem.alloc);
434 421
435 // Since we are setting a rune, the string value should be freed.422 // Release the encoded string for this instance.
436 if (_encoded_str != nullptr)423 if (_encoded_str != reinterpret_cast<char*>(source))
437 free_memory(_encoded_str);424 free_memory(_encoded_str);
438 }
439 425
440 // Reset the string so it can be regenerated.
441 _encoded_str = nullptr;426 _encoded_str = nullptr;
442 427
443 const auto new_character_size = (value > utf8::constants::max_codepoint_ascii) ? sizeof(rune_t) : sizeof(char);428 const auto new_character_size = (value > utf8::constants::max_codepoint_ascii) ? sizeof(rune_t) : sizeof(char);
@@ -513,6 +498,7 @@ const char *vm_string_t::str() const · 69 unmodified lines
513 if (_character_size == sizeof(char))498 if (_character_size == sizeof(char))
514 {499 {
515 _encoded_str = (_is_alloc) ? reinterpret_cast<char *>(_mem.alloc) : reinterpret_cast<char *>(_mem.local);500 _encoded_str = (_is_alloc) ? reinterpret_cast<char *>(_mem.alloc) : reinterpret_cast<char *>(_mem.local);
501 _encoded_str[_length] = '\0';
516 return _encoded_str;502 return _encoded_str;
517 }503 }
518 504
src/vm/vm_memory.cpp+9−6
@@ -158,19 +158,22 @@ namespace · 157 unmodified lines
158 158
159void disvm::runtime::destroy_memory(const type_descriptor_t &type_desc, void *data)159void disvm::runtime::destroy_memory(const type_descriptor_t &type_desc, void *data)
160{160{
161 enum_pointer_fields(type_desc, data, dec_ref_and_free_pointer_field);161 dec_ref_count_in_memory(type_desc, data);
162
163 debug::assign_debug_memory(data, type_desc.size_in_bytes);162 debug::assign_debug_memory(data, type_desc.size_in_bytes);
164}163}
165 164
166void disvm::runtime::inc_ref_count_in_memory(const type_descriptor_t &type_desc, void *data)165void disvm::runtime::inc_ref_count_in_memory(const type_descriptor_t &type_desc, void *data)
167{166{
168 if (data == nullptr)167 assert(data != nullptr);
169 return;
170
171 enum_pointer_fields(type_desc, data, add_ref_pointer_field);168 enum_pointer_fields(type_desc, data, add_ref_pointer_field);
172}169}
173 170
171void disvm::runtime::dec_ref_count_in_memory(const type_descriptor_t &type_desc, void *data)
172{
173 assert(data != nullptr);
174 enum_pointer_fields(type_desc, data, dec_ref_and_free_pointer_field);
175}
176
174void disvm::runtime::dec_ref_count_and_free(vm_alloc_t *alloc)177void disvm::runtime::dec_ref_count_and_free(vm_alloc_t *alloc)
175{178{
176 if (alloc == nullptr)179 if (alloc == nullptr)
@@ -460,7 +463,7 @@ std::shared_ptr<const type_descriptor_t> type_descriptor_t::create( · 283 unmodified lines
460 pointer_map_local[i] = pointer_map[i];463 pointer_map_local[i] = pointer_map[i];
461 }464 }
462 465
463 auto new_type = ::new(new_type_memory) type_descriptor_t{ size_in_bytes, pointer_map_length, pointer_map_local, finalizer, "#" };466 auto new_type = ::new(new_type_memory) type_descriptor_t{ size_in_bytes, pointer_map_length, pointer_map_local, finalizer, "?" };
464 return std::shared_ptr<type_descriptor_t>{ new_type, deleter };467 return std::shared_ptr<type_descriptor_t>{ new_type, deleter };
465}468}
466 469