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 | 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 code | 775 | // [SPEC] 'Concat strings' op code |
| @@ -775,20 +782,18 @@ namespace · 6 unmodified lines | |||
| 775 | // dst = src2 + src1 | 782 | // 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 the | 789 | // 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()); |