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
7979 vt_ref<big_t>(r.dest) = vt_ref<big_t>(r.mid) >> vt_ref<big_t>(r.src);
8080 // Right shifting a negative number is implementation dependent in C++.
8181 // 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));
8383 }
8484
8585 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
206206 assert(static_cast<std::size_t>(len) <= buffer.size());
207207
208208 auto new_string = new vm_string_t(len, reinterpret_cast<uint8_t *>(buffer.data()));
209− auto str = at_val<vm_string_t>(r.dest);
210− dec_ref_count_and_free(str);
209+ auto prev = at_val<vm_alloc_t>(r.dest);
210+ dec_ref_count_and_free(prev);
211211
212212 pt_ref(r.dest) = new_string->get_allocation();
213213 }
@@ -233,9 +233,10 @@ namespace · 19 unmodified lines
233233
234234 auto new_string = new vm_string_t(len, reinterpret_cast<uint8_t *>(buffer.data()));
235235
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+
237239 pt_ref(r.dest) = new_string->get_allocation();
238− dec_ref_count_and_free(str);
239240 }
240241
241242 EXEC_DECL(cvtcl)
@@ -259,9 +260,10 @@ namespace · 17 unmodified lines
259260
260261 auto new_string = new vm_string_t(len, reinterpret_cast<uint8_t *>(buffer.data()));
261262
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+
263266 pt_ref(r.dest) = new_string->get_allocation();
264− dec_ref_count_and_free(str);
265267 }
266268
267269 //
@@ -725,9 +727,9 @@ namespace · 457 unmodified lines
725727 auto index = vt_ref<word_t>(r.mid);
726728 auto str = at_val<vm_string_t>(r.dest);
727729 if (str == nullptr)
728− str = new vm_string_t();
730+ str = new vm_string_t{};
729731 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() };
731733
732734 // Set the rune at the supplied index.
733735 str->set_rune(index, rune);
@@ -740,7 +742,8 @@ namespace · 6 unmodified lines
740742 }
741743 }
742744
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)
744747 {
745748 if (s1 == nullptr)
746749 {
@@ -750,19 +753,23 @@ namespace · 3 unmodified lines
750753 return new vm_string_t{ *s2, 0, s2->get_length() };
751754 }
752755
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.
754757 if (s1->get_ref_count() > 1)
755− append_to_s1 = false;
758+ try_append_to_s1 = false;
756759
757760 if (s2 == nullptr)
758761 {
759− if (append_to_s1)
760− return s1;
762+ if (try_append_to_s1)
763+ return nullptr;
761764
762765 return new vm_string_t(*s1, 0, s1->get_length());
763766 }
764767
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;
766773 }
767774
768775 // [SPEC] 'Concat strings' op code
@@ -775,20 +782,18 @@ namespace · 6 unmodified lines
775782 // dst = src2 + src1
776783 EXEC_DECL(addc)
777784 {
785+ const auto try_append_to_s1 = r.mid == r.dest;
778786 auto s1 = at_val<vm_string_t>(r.mid);
779787 const auto s2 = at_val<vm_string_t>(r.src);
780− auto dest_maybe = at_val<vm_string_t>(r.dest);
781788
782− // If the source is the same as the destination and the
783− // destination is not null, append the string. This can
784− // change during the concat process.
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+ // If the source is the same as the destination, try to append the string during concatenation.
790+ const auto new_str_maybe = concat_string(s1, s2, try_append_to_s1);
791+ if (new_str_maybe != nullptr)
789792 {
790− pt_ref(r.dest) = str->get_allocation();
793+ auto dest_maybe = at_val<vm_alloc_t>(r.dest);
791794 dec_ref_count_and_free(dest_maybe);
795+
796+ pt_ref(r.dest) = new_str_maybe->get_allocation();
792797 }
793798 }
794799
@@ -1659,6 +1664,7 @@ namespace · 864 unmodified lines
16591664 // The remainder of the type is user-defined.
16601665 auto content = e->get_allocation();
16611666 exception_id = at_val<vm_string_t>(content);
1667+ assert(exception_id != nullptr);
16621668
16631669 if (debug::is_component_tracing_enabled<debug::component_trace_t::exception>())
16641670 debug::log_msg(debug::component_trace_t::exception, debug::log_level_t::debug, "raise: exception: >>%s<<", exception_id->str());