History

Bugs found during limbo compiler work - Ref counting mistakes in vm_array copy_from() - document perf opportunity - Multiple bugs in addc instruction - set_rune() on vm_string was creating non-null terminated strings - Add support for '*', 'c', and 'u' flags in print formatting

arr committed 9 years ago

Commit 57e9d241 parent 3f81a2c4 files · +86 −44Browse files

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

Unified · Split

src/vm/execution_table.cpp+30−24
@@ -79,7 +79,7 @@ namespace · 78 unmodified lines
79 vt_ref<big_t>(r.dest) = vt_ref<big_t>(r.mid) >> vt_ref<big_t>(r.src);79 vt_ref<big_t>(r.dest) = vt_ref<big_t>(r.mid) >> vt_ref<big_t>(r.src);
80 // Right shifting a negative number is implementation dependent in C++.80 // Right shifting a negative number is implementation dependent in C++.
81 // Assert the current compiler defaults to arithmetic shifting, not logical.81 // Assert the current compiler defaults to arithmetic shifting, not logical.
82 assert(vt_ref<word_t>(r.mid) >= 0 || (vt_ref<word_t>(r.mid) < 0 && vt_ref<word_t>(r.dest) < 0));82 assert(vt_ref<big_t>(r.mid) >= 0 || (vt_ref<big_t>(r.mid) < 0 && vt_ref<big_t>(r.dest) < 0));
83 }83 }
84 84
85 EXEC_DECL(lsrw) { vt_ref<word_t>(r.dest) = vt_ref<uword_t>(r.mid) >> vt_ref<word_t>(r.src); }85 EXEC_DECL(lsrw) { vt_ref<word_t>(r.dest) = vt_ref<uword_t>(r.mid) >> vt_ref<word_t>(r.src); }
@@ -206,8 +206,8 @@ namespace · 120 unmodified lines
206 assert(static_cast<std::size_t>(len) <= buffer.size());206 assert(static_cast<std::size_t>(len) <= buffer.size());
207 207
208 auto new_string = new vm_string_t(len, reinterpret_cast<uint8_t *>(buffer.data()));208 auto new_string = new vm_string_t(len, reinterpret_cast<uint8_t *>(buffer.data()));
209 auto str = at_val<vm_string_t>(r.dest);209 auto prev = at_val<vm_alloc_t>(r.dest);
210 dec_ref_count_and_free(str);210 dec_ref_count_and_free(prev);
211 211
212 pt_ref(r.dest) = new_string->get_allocation();212 pt_ref(r.dest) = new_string->get_allocation();
213 }213 }
@@ -233,9 +233,10 @@ namespace · 19 unmodified lines
233 233
234 auto new_string = new vm_string_t(len, reinterpret_cast<uint8_t *>(buffer.data()));234 auto new_string = new vm_string_t(len, reinterpret_cast<uint8_t *>(buffer.data()));
235 235
236 auto str = at_val<vm_string_t>(r.dest);236 auto prev = at_val<vm_alloc_t>(r.dest);
237 dec_ref_count_and_free(prev);
238
237 pt_ref(r.dest) = new_string->get_allocation();239 pt_ref(r.dest) = new_string->get_allocation();
238 dec_ref_count_and_free(str);
239 }240 }
240 241
241 EXEC_DECL(cvtcl)242 EXEC_DECL(cvtcl)
@@ -259,9 +260,10 @@ namespace · 17 unmodified lines
259 260
260 auto new_string = new vm_string_t(len, reinterpret_cast<uint8_t *>(buffer.data()));261 auto new_string = new vm_string_t(len, reinterpret_cast<uint8_t *>(buffer.data()));
261 262
262 auto str = at_val<vm_string_t>(r.dest);263 auto prev = at_val<vm_alloc_t>(r.dest);
264 dec_ref_count_and_free(prev);
265
263 pt_ref(r.dest) = new_string->get_allocation();266 pt_ref(r.dest) = new_string->get_allocation();
264 dec_ref_count_and_free(str);
265 }267 }
266 268
267 //269 //
@@ -725,9 +727,9 @@ namespace · 457 unmodified lines
725 auto index = vt_ref<word_t>(r.mid);727 auto index = vt_ref<word_t>(r.mid);
726 auto str = at_val<vm_string_t>(r.dest);728 auto str = at_val<vm_string_t>(r.dest);
727 if (str == nullptr)729 if (str == nullptr)
728 str = new vm_string_t();730 str = new vm_string_t{};
729 else if (str->get_ref_count() > 1)731 else if (str->get_ref_count() > 1)
730 str = new vm_string_t(*str, 0, str->get_length());732 str = new vm_string_t{ *str, 0, str->get_length() };
731 733
732 // Set the rune at the supplied index.734 // Set the rune at the supplied index.
733 str->set_rune(index, rune);735 str->set_rune(index, rune);
@@ -740,7 +742,8 @@ namespace · 6 unmodified lines
740 }742 }
741 }743 }
742 744
743 vm_string_t *_addc(vm_string_t *s1, const vm_string_t *s2, /* in out */ bool &append_to_s1)745 // Returns a string instance only if it is new
746 vm_string_t *concat_string(vm_string_t *s1, const vm_string_t *s2, bool try_append_to_s1)
744 {747 {
745 if (s1 == nullptr)748 if (s1 == nullptr)
746 {749 {
@@ -750,19 +753,23 @@ namespace · 3 unmodified lines
750 return new vm_string_t{ *s2, 0, s2->get_length() };753 return new vm_string_t{ *s2, 0, s2->get_length() };
751 }754 }
752 755
753 // There are other references to this string so we will not alter it.756 // If there are other references to the string, it is immutable.
754 if (s1->get_ref_count() > 1)757 if (s1->get_ref_count() > 1)
755 append_to_s1 = false;758 try_append_to_s1 = false;
756 759
757 if (s2 == nullptr)760 if (s2 == nullptr)
758 {761 {
759 if (append_to_s1)762 if (try_append_to_s1)
760 return s1;763 return nullptr;
761 764
762 return new vm_string_t(*s1, 0, s1->get_length());765 return new vm_string_t(*s1, 0, s1->get_length());
763 }766 }
764 767
765 return (append_to_s1) ? &(s1->append(*s2)) : new vm_string_t(*s1, *s2);768 if (!try_append_to_s1)
769 return new vm_string_t(*s1, *s2);
770
771 s1->append(*s2);
772 return nullptr;
766 }773 }
767 774
768 // [SPEC] 'Concat strings' op code775 // [SPEC] 'Concat strings' op code
@@ -775,20 +782,18 @@ namespace · 6 unmodified lines
775 // dst = src2 + src1782 // dst = src2 + src1
776 EXEC_DECL(addc)783 EXEC_DECL(addc)
777 {784 {
785 const auto try_append_to_s1 = r.mid == r.dest;
778 auto s1 = at_val<vm_string_t>(r.mid);786 auto s1 = at_val<vm_string_t>(r.mid);
779 const auto s2 = at_val<vm_string_t>(r.src);787 const auto s2 = at_val<vm_string_t>(r.src);
780 auto dest_maybe = at_val<vm_string_t>(r.dest);
781 788
782 // If the source is the same as the destination and the789 // If the source is the same as the destination, try to append the string during concatenation.
783 // destination is not null, append the string. This can 790 const auto new_str_maybe = concat_string(s1, s2, try_append_to_s1);
784 // change during the concat process.791 if (new_str_maybe != nullptr)
785 auto append_to_source = dest_maybe != nullptr && s1 == dest_maybe;
786 const auto str = _addc(s1, s2, append_to_source);
787
788 if (!append_to_source)
789 {792 {
790 pt_ref(r.dest) = str->get_allocation();793 auto dest_maybe = at_val<vm_alloc_t>(r.dest);
791 dec_ref_count_and_free(dest_maybe);794 dec_ref_count_and_free(dest_maybe);
795
796 pt_ref(r.dest) = new_str_maybe->get_allocation();
792 }797 }
793 }798 }
794 799
@@ -1659,6 +1664,7 @@ namespace · 864 unmodified lines
1659 // The remainder of the type is user-defined.1664 // The remainder of the type is user-defined.
1660 auto content = e->get_allocation();1665 auto content = e->get_allocation();
1661 exception_id = at_val<vm_string_t>(content);1666 exception_id = at_val<vm_string_t>(content);
1667 assert(exception_id != nullptr);
1662 1668
1663 if (debug::is_component_tracing_enabled<debug::component_trace_t::exception>())1669 if (debug::is_component_tracing_enabled<debug::component_trace_t::exception>())
1664 debug::log_msg(debug::component_trace_t::exception, debug::log_level_t::debug, "raise: exception: >>%s<<", exception_id->str());1670 debug::log_msg(debug::component_trace_t::exception, debug::log_level_t::debug, "raise: exception: >>%s<<", exception_id->str());