changeset 32326:084fc89a253b

VM Fix compound subassignment of globals (bug #64702) Also fix some other places with the same potential problem. * libinterp/parse-tree/pt-bytecode-vm.cc: Ref, deref properly * test/compile/bytecode.tst: Update tests * test/compile/bytecode_global_1.m
author Petter T.
date Fri, 22 Sep 2023 09:58:42 +0200
parents 9d758cacf7ca
children 55ea70c8d00a
files libinterp/parse-tree/pt-bytecode-vm.cc test/compile/bytecode.tst test/compile/bytecode_global_1.m
diffstat 3 files changed, 39 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/parse-tree/pt-bytecode-vm.cc	Fri Sep 22 20:28:30 2023 -0400
+++ b/libinterp/parse-tree/pt-bytecode-vm.cc	Fri Sep 22 09:58:42 2023 +0200
@@ -1160,7 +1160,10 @@
         int n_root_wanted = std::max (root_nargout, 1);
         for (j = 1; j < n_returns_callee && j < (n_root_wanted + 1); j++)
           {
-            ret.append (std::move (bsp[j].ov));
+            if (OCTAVE_UNLIKELY (bsp[j].ov.is_ref ()))
+              ret.append (bsp[j].ov.ref_rep ()->deref ());
+            else
+              ret.append (std::move (bsp[j].ov));
             bsp[j].ov.~octave_value ();
           }
         // Destroy rest of return values, if any
@@ -5035,8 +5038,13 @@
             if (cntr == 0 && ov.is_nil () && has_slot)
               {
                 // Put a function cache object in the slot and in the local ov
-                ov = bsp[slot].ov =
-                  octave_value (new octave_fcn_cache (name_data[slot]));
+                ov = octave_value (new octave_fcn_cache (name_data[slot]));
+
+                if (OCTAVE_UNLIKELY (bsp[slot].ov.is_ref ()))
+                  bsp[slot].ov.ref_rep ()->set_value (ov);
+                else
+                  bsp[slot].ov = ov;
+
               }
 
             if (cntr == 0 && ov.has_function_cache () && has_slot)
@@ -5697,12 +5705,14 @@
             // Clear it to make assigns not need a new copy.
             lhs = octave_value {};
 
-            bool is_ref = lhs_slot.is_ref ();
-
-            if (is_ref)
-              lhs_slot.ref_rep ()->ref ().make_unique ();
-
-            lhs_slot.assign (op, type, idx, rhs);
+            if (OCTAVE_UNLIKELY (lhs_slot.is_ref ()))
+              {
+                octave_value &ov_ref = lhs_slot.ref_rep ()->ref ();
+                ov_ref.make_unique ();
+                ov_ref.assign (op, type, idx, rhs);
+              }
+            else
+              lhs_slot.assign (op, type, idx, rhs);
 
             // Push a dummy octave_value. Always poped by a POP opcode. 
             PUSH_OV (octave_value {});
--- a/test/compile/bytecode.tst	Fri Sep 22 20:28:30 2023 -0400
+++ b/test/compile/bytecode.tst	Fri Sep 22 09:58:42 2023 +0200
@@ -311,7 +311,7 @@
 %!test
 %! __enable_vm_eval__ (0, "local");
 %! clear all
-%! key = "double 0 0 1 1 1 1 1 2 2 2 400 100 0 1 3 double 1 1 1 2 double 1 2 1 1 11 eclass:double 1 1 3 4 double 1 2 400 100 1 1 1 1 3 4 1 1 5 6 1 1 1 2 double 1 2 1 2 double 1 2 1 1 3 4 eclass:double 1 2 3 4 double 1 2 0 0 1 1 3 4 1 1 5 6 1 0 2 double 2 double 11 2 6 4 5 double 1 5 11 double 1 1 22 double 1 1 33 double 1 1 3 double 1 1 4 double 1 1 10 double 1 1 2 3 double 1 2 3 double 1 1 2 double 1 1 55 double 1 1 7 double 1 1 0 ";
+%! key = "double 0 0 1 1 1 1 1 2 2 2 400 100 0 1 3 double 1 1 1 2 double 1 2 1 1 11 eclass:double 1 1 3 4 double 1 2 400 100 1 1 1 1 3 4 1 1 5 6 1 1 1 2 double 1 2 1 2 double 1 2 1 1 3 4 eclass:double 1 2 3 4 double 1 2 0 0 1 1 3 4 1 1 5 6 1 0 2 double 2 double 11 2 6 4 5 double 1 5 11 double 1 1 22 double 1 1 33 double 1 1 3 double 1 1 4 double 1 1 10 double 1 1 2 3 double 1 2 3 double 1 1 2 double 1 1 55 double 1 1 7 double 1 1 0 11 12 4 11 12 4 ";
 %!
 %! __compile__ bytecode_global_1 clear;
 %! clear global a;
--- a/test/compile/bytecode_global_1.m	Fri Sep 22 20:28:30 2023 -0400
+++ b/test/compile/bytecode_global_1.m	Fri Sep 22 09:58:42 2023 +0200
@@ -123,6 +123,23 @@
   clear global c
   __printf_assert__ ("%d ", length (who ('global','c')));
 
+  % Assure some different subassignment operators are working
+  global s;
+  s = [1 2 3 4];
+  s(1) = 11;  %SUBASSIGN_ID
+  s(2) += 10; %SUBASSIGN_CHAINED
+  s(3) = [];  %SUBASSIGN_ID
+
+  __printf_assert__ ("%d ", s);
+
+  global t;
+  t.s = [1 2 3 4];
+  t.s(1) = 11;  %SUBASSIGN_CHAINED
+  t.s(2) += 10; %SUBASSIGN_CHAINED
+  t.s(3) = [];  %SUBASSIGN_CHAINED
+
+  __printf_assert__ ("%d ", t.s);
+
   clear global d
   clear global e
   clear global f
@@ -135,6 +152,8 @@
   clear global o
   clear global p
   clear global r
+  clear global s
+  clear global t
 end
 
 function [q w e] = returns3()