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
198198
199199 public:
200200 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);
202202 vm_array_t(const vm_string_t *s);
203203 ~vm_array_t();
204204
src/include/vm_memory.h+20−15
@@ -60,9 +60,12 @@ namespace disvm · 59 unmodified lines
6060 // Destroy supplied memory based on the type descriptor
6161 void destroy_memory(const type_descriptor_t &type_desc, void *data);
6262
63− // Increment the ref count of all points in the supplied memory allocation
63+ // Increment the ref count of all pointers in the supplied memory allocation
6464 void inc_ref_count_in_memory(const type_descriptor_t &type_desc, void *data);
6565
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+
6669 // Decrement the ref count and if 0 free the allocation
6770 void dec_ref_count_and_free(vm_alloc_t *alloc);
6871
@@ -81,20 +84,21 @@ namespace disvm · 12 unmodified lines
8184 for (auto i = word_t{ 0 }; i < type_desc.map_in_bytes; ++i, memory += 8, offset_accum += (8 * sizeof(pointer_t)))
8285 {
8386 const auto words8 = type_desc.pointer_map[i];
84− if (words8 != 0)
85− {
86− const auto flags = std::bitset<sizeof(words8) * 8>{ words8 };
87−
88− // Enumerating the flags in reverse order so memory access is sequential.
89− if (flags[7] && (memory[0] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[0]), offset_accum);
90− if (flags[6] && (memory[1] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[1]), offset_accum + (1 * sizeof(pointer_t)));
91− if (flags[5] && (memory[2] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[2]), offset_accum + (2 * sizeof(pointer_t)));
92− if (flags[4] && (memory[3] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[3]), offset_accum + (3 * 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)));
94− if (flags[2] && (memory[5] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[5]), offset_accum + (5 * 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)));
96− if (flags[0] && (memory[7] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[7]), offset_accum + (7 * sizeof(pointer_t)));
97− }
87+ assert(sizeof(words8) == 1);
88+ if (words8 == 0)
89+ continue;
90+
91+ const auto flags = std::bitset<sizeof(words8) * 8>{ words8 };
92+
93+ // Enumerating the flags in reverse order so memory access is sequential.
94+ if (flags[7] && (memory[0] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[0]), offset_accum);
95+ if (flags[6] && (memory[1] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[1]), offset_accum + (1 * 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)));
97+ if (flags[4] && (memory[3] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[3]), offset_accum + (3 * 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)));
99+ if (flags[2] && (memory[5] != runtime_constants::nil)) callback(reinterpret_cast<pointer_t>(memory[5]), offset_accum + (5 * sizeof(pointer_t)));
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)));
98102 }
99103 }
100104
@@ -112,6 +116,7 @@ namespace disvm · 11 unmodified lines
112116 if (byte_offset < type_desc.map_in_bytes)
113117 {
114118 const auto words8 = type_desc.pointer_map[byte_offset];
119+ assert(sizeof(words8) == 1);
115120 if (words8 != 0)
116121 {
117122 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
4343 debug::log_msg(debug::component_trace_t::memory, debug::log_level_t::debug, "end: init: elements: %d", array_len);
4444 }
4545
46−vm_array_t::vm_array_t(vm_array_t *original, word_t begin_index, word_t length)
46+vm_array_t::vm_array_t(vm_array_t &original, word_t begin_index, word_t length)
4747 : vm_alloc_t(vm_array_t::type_desc())
4848 , _arr{ nullptr }
49− , _element_type{ original->get_element_type() }
49+ , _element_type{ original.get_element_type() }
5050 , _length{ length }
51− , _original{ original }
51+ , _original{ &original }
5252 {
53− assert(_original != nullptr);
54− assert(0 <= begin_index && begin_index < _original->get_length());
55− assert(_length >= 0 && (_length + begin_index) <= _original->get_length());
53+ assert(0 <= begin_index && (begin_index < _original->get_length() || (begin_index == _original->get_length() && length == 0)));
5654
5755 if (debug::is_component_tracing_enabled<debug::component_trace_t::memory>())
5856 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
164162 {
165163 // [PERF] There is a chance this copy is within the same array, therefore
166164 // 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).
168165 const auto &type_desc = *_element_type;
169166 auto source_array_element = source._arr;
170167 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
173170 inc_ref_count_in_memory(type_desc, source_array_element);
174171 source_array_element += type_desc.size_in_bytes;
175172
176− destroy_memory(type_desc, dest_array_element);
173+ dec_ref_count_in_memory(type_desc, dest_array_element);
177174 dest_array_element += type_desc.size_in_bytes;
178175 }
179176 }
src/vm/execution_table.cpp+1−3
@@ -548,8 +548,6 @@ namespace · 547 unmodified lines
548548 auto type = types[type_id];
549549
550550 disvm::runtime::inc_ref_count_in_memory(*type, r.src);
551−
552− // Decrement allocated pointers in the destination.
553551 destroy_memory(*type, r.dest);
554552
555553 assert(r.src != nullptr && r.dest != nullptr);
@@ -863,7 +861,7 @@ namespace · 307 unmodified lines
863861 throw out_of_range_memory{};
864862 }
865863
866− auto new_array = new vm_array_t(arr, begin_index, length);
864+ auto new_array = new vm_array_t(*arr, begin_index, length);
867865
868866 if (arr->alloc_type->map_in_bytes > 0)
869867 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
301301
302302 vm_string_t::~vm_string_t()
303303 {
304− // Free memory and string buffer
305− if (_is_alloc)
306− {
307− if (static_cast<void *>(_mem.alloc) != static_cast<void *>(_encoded_str))
308− free_memory(_encoded_str);
304+ // Determine if local or allocated memory
305+ auto source = (_is_alloc) ? _mem.alloc : _mem.local;
306+ if (static_cast<void *>(source) != static_cast<void *>(_encoded_str))
307+ free_memory(_encoded_str);
309308
310− free_memory(_mem.alloc);
311− }
312− else
313− {
314− if (static_cast<void *>(_mem.local) != static_cast<void *>(_encoded_str))
315− free_memory(_encoded_str);
316− }
309+ if (_is_alloc)
310+ free_memory(source);
317311
318312 debug::log_msg(debug::component_trace_t::memory, debug::log_level_t::debug, "destroy: vm string");
319313
320− debug::assign_debug_pointer(&_mem.alloc);
314+ debug::assign_debug_pointer(&source);
321315 debug::assign_debug_pointer(&_encoded_str);
322316 }
323317
@@ -341,14 +335,10 @@ vm_string_t &vm_string_t::append(const vm_string_t &other) · 17 unmodified lines
341335 const auto local_source = (_is_alloc) ? _mem.alloc : _mem.local;
342336
343337 // Release the encoded string for this instance.
344− {
345− std::lock_guard<std::mutex> lock{ _encoded_str_lock };
346− if (_encoded_str != reinterpret_cast<char*>(local_source))
347− {
348− free_memory(_encoded_str);
349− _encoded_str = nullptr;
350− }
351− }
338+ if (_encoded_str != reinterpret_cast<char*>(local_source))
339+ free_memory(_encoded_str);
340+
341+ _encoded_str = nullptr;
352342
353343 // Define the values for the appended string
354344 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
427417 throw index_out_of_range_memory{ 0, _length, index };
428418
429419 // Determine if local or allocated memory
430− auto source = static_cast<uint8_t *>(_mem.local);
431− if (_is_alloc)
432− {
433− source = static_cast<uint8_t *>(_mem.alloc);
420+ auto source = (_is_alloc) ? _mem.alloc : _mem.local;
434421
435− // Since we are setting a rune, the string value should be freed.
436− if (_encoded_str != nullptr)
437− free_memory(_encoded_str);
438− }
422+ // Release the encoded string for this instance.
423+ if (_encoded_str != reinterpret_cast<char*>(source))
424+ free_memory(_encoded_str);
439425
440− // Reset the string so it can be regenerated.
441426 _encoded_str = nullptr;
442427
443428 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
513498 if (_character_size == sizeof(char))
514499 {
515500 _encoded_str = (_is_alloc) ? reinterpret_cast<char *>(_mem.alloc) : reinterpret_cast<char *>(_mem.local);
501+ _encoded_str[_length] = '\0';
516502 return _encoded_str;
517503 }
518504
src/vm/vm_memory.cpp+9−6
@@ -158,19 +158,22 @@ namespace · 157 unmodified lines
158158
159159 void disvm::runtime::destroy_memory(const type_descriptor_t &type_desc, void *data)
160160 {
161− enum_pointer_fields(type_desc, data, dec_ref_and_free_pointer_field);
162−
161+ dec_ref_count_in_memory(type_desc, data);
163162 debug::assign_debug_memory(data, type_desc.size_in_bytes);
164163 }
165164
166165 void disvm::runtime::inc_ref_count_in_memory(const type_descriptor_t &type_desc, void *data)
167166 {
168− if (data == nullptr)
169− return;
170−
167+ assert(data != nullptr);
171168 enum_pointer_fields(type_desc, data, add_ref_pointer_field);
172169 }
173170
171+void 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+
174177 void disvm::runtime::dec_ref_count_and_free(vm_alloc_t *alloc)
175178 {
176179 if (alloc == nullptr)
@@ -460,7 +463,7 @@ std::shared_ptr<const type_descriptor_t> type_descriptor_t::create( · 283 unmodified lines
460463 pointer_map_local[i] = pointer_map[i];
461464 }
462465
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, "?" };
464467 return std::shared_ptr<type_descriptor_t>{ new_type, deleter };
465468 }
466469