Showing the changes to src/vm/execution_table.cpp (1 of 4 files). Show all
Unified · Split
| @@ -79,7 +79,7 @@ namespace · 78 unmodified lines | ||
| 79 | 79 | vt_ref<big_t>(r.dest) = vt_ref<big_t>(r.mid) >> vt_ref<big_t>(r.src); |
| 80 | 80 | // Right shifting a negative number is implementation dependent in C++. |
| 81 | 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 | 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 | 206 | assert(static_cast<std::size_t>(len) <= buffer.size()); |
| 207 | 207 | |
| 208 | 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); | |
| 210 | − dec_ref_count_and_free(str); | |
| 209 | + auto prev = at_val<vm_alloc_t>(r.dest); | |
| 210 | + dec_ref_count_and_free(prev); | |
| 211 | 211 | |
| 212 | 212 | pt_ref(r.dest) = new_string->get_allocation(); |
| 213 | 213 | } |
| @@ -233,9 +233,10 @@ namespace · 19 unmodified lines | ||
| 233 | 233 | |
| 234 | 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 | 239 | pt_ref(r.dest) = new_string->get_allocation(); |
| 238 | − dec_ref_count_and_free(str); | |
| 239 | 240 | } |
| 240 | 241 | |
| 241 | 242 | EXEC_DECL(cvtcl) |
| @@ -259,9 +260,10 @@ namespace · 17 unmodified lines | ||
| 259 | 260 | |
| 260 | 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 | 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 | 727 | auto index = vt_ref<word_t>(r.mid); |
| 726 | 728 | auto str = at_val<vm_string_t>(r.dest); |
| 727 | 729 | if (str == nullptr) |
| 728 | − str = new vm_string_t(); | |
| 730 | + str = new vm_string_t{}; | |
| 729 | 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 | 734 | // Set the rune at the supplied index. |
| 733 | 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 | 748 | if (s1 == nullptr) |
| 746 | 749 | { |
| @@ -750,19 +753,23 @@ namespace · 3 unmodified lines | ||
| 750 | 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 | 757 | if (s1->get_ref_count() > 1) |
| 755 | − append_to_s1 = false; | |
| 758 | + try_append_to_s1 = false; | |
| 756 | 759 | |
| 757 | 760 | if (s2 == nullptr) |
| 758 | 761 | { |
| 759 | − if (append_to_s1) | |
| 760 | − return s1; | |
| 762 | + if (try_append_to_s1) | |
| 763 | + return nullptr; | |
| 761 | 764 | |
| 762 | 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 | 775 | // [SPEC] 'Concat strings' op code |
| @@ -775,20 +782,18 @@ namespace · 6 unmodified lines | ||
| 775 | 782 | // dst = src2 + src1 |
| 776 | 783 | EXEC_DECL(addc) |
| 777 | 784 | { |
| 785 | + const auto try_append_to_s1 = r.mid == r.dest; | |
| 778 | 786 | auto s1 = at_val<vm_string_t>(r.mid); |
| 779 | 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 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) | |
| 789 | 792 | { |
| 790 | − pt_ref(r.dest) = str->get_allocation(); | |
| 793 | + auto dest_maybe = at_val<vm_alloc_t>(r.dest); | |
| 791 | 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 | 1664 | // The remainder of the type is user-defined. |
| 1660 | 1665 | auto content = e->get_allocation(); |
| 1661 | 1666 | exception_id = at_val<vm_string_t>(content); |
| 1667 | + assert(exception_id != nullptr); | |
| 1662 | 1668 | |
| 1663 | 1669 | if (debug::is_component_tracing_enabled<debug::component_trace_t::exception>()) |
| 1664 | 1670 | debug::log_msg(debug::component_trace_t::exception, debug::log_level_t::debug, "raise: exception: >>%s<<", exception_id->str()); |