diff --git a/libinterp/corefcn/interpreter.cc b/libinterp/corefcn/interpreter.cc --- a/libinterp/corefcn/interpreter.cc +++ b/libinterp/corefcn/interpreter.cc @@ -1044,6 +1044,8 @@ namespace octave // is unloaded. // // OCTAVE_SAFE_CALL (singleton_cleanup_list::cleanup, ()); + + display_octave_value_counts (); } tree_evaluator& interpreter::get_evaluator (void) diff --git a/libinterp/octave-value/ov-base-diag.cc b/libinterp/octave-value/ov-base-diag.cc --- a/libinterp/octave-value/ov-base-diag.cc +++ b/libinterp/octave-value/ov-base-diag.cc @@ -189,7 +189,7 @@ octave_base_diag::subsasgn (con { matrix.dgelem (i0(0)) = val; retval = this; - this->count++; + this->increment_count (); // invalidate cache dense_cache = octave_value (); } @@ -217,7 +217,7 @@ octave_base_diag::subsasgn (con { matrix.dgelem (i0(0)) = val; retval = this; - this->count++; + this->increment_count (); // invalidate cache dense_cache = octave_value (); } diff --git a/libinterp/octave-value/ov-base.cc b/libinterp/octave-value/ov-base.cc --- a/libinterp/octave-value/ov-base.cc +++ b/libinterp/octave-value/ov-base.cc @@ -1202,7 +1202,7 @@ octave_base_value::numeric_assign (const if (done) { - count++; + increment_count (); retval = octave_value (this); } else @@ -1265,7 +1265,7 @@ octave_base_value::numeric_assign (const else tmp_rhs = rhs; - count++; + increment_count (); octave_value tmp_lhs = octave_value (this); if (cf_this) diff --git a/libinterp/octave-value/ov-base.h b/libinterp/octave-value/ov-base.h --- a/libinterp/octave-value/ov-base.h +++ b/libinterp/octave-value/ov-base.h @@ -159,28 +159,45 @@ DEF_CLASS_TO_BTYP (char, btyp_char); DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA2 (OCTAVE_EMPTY_CPP_ARG) #define DECLARE_OV_BASE_TYPEID_FUNCTIONS_AND_DATA \ - DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA2(virtual) + DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA2(virtual) \ #define DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA2(VIRTUAL) \ public: \ VIRTUAL int type_id (void) const { return t_id; } \ VIRTUAL std::string type_name (void) const { return t_name; } \ VIRTUAL std::string class_name (void) const { return c_name; } \ + VIRTUAL octave_idx_type total_use_count (void) \ + { \ + return s_total_use_count; \ + } \ + VIRTUAL octave_idx_type increment_total_use_count (void) \ + { \ + return ++s_total_use_count; \ + } \ + VIRTUAL octave_idx_type decrement_total_use_count (void) \ + { \ + return --s_total_use_count; \ + } \ static int static_type_id (void) { return t_id; } \ static std::string static_type_name (void) { return t_name; } \ static std::string static_class_name (void) { return c_name; } \ + static octave_idx_type static_total_use_count (void) \ + { \ + return s_total_use_count; \ + } \ static void register_type (void); \ static void register_type (octave::type_info&); \ - \ private: \ static int t_id; \ static const std::string t_name; \ - static const std::string c_name; + static const std::string c_name; \ + static octave::refcount s_total_use_count; #define DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA(t, n, c) \ int t::t_id (-1); \ const std::string t::t_name (n); \ const std::string t::c_name (c); \ + octave::refcount t::s_total_use_count (0); \ void t::register_type (void) \ { \ octave::type_info& type_info \ @@ -227,9 +244,21 @@ public: friend class octave_value; - octave_base_value (void) : count (1) { } + octave_base_value (void) + : m_count (1) + { + // THIS DOES NOT WORK: virtual functions are not virtual when + // called from constructors. + increment_total_use_count (); + } - octave_base_value (const octave_base_value&) : count (1) { } + octave_base_value (const octave_base_value&) + : m_count (1) + { + // THIS DOES NOT WORK: virtual functions are not virtual when + // called from constructors. + increment_total_use_count (); + } virtual ~octave_base_value (void) = default; @@ -818,17 +847,34 @@ public: void grab (void) { - ++count; + increment_count (); } // Release the reference count. For use by jit. void release (void) { - if (--count == 0) + if (decrement_count () == 0) delete this; } + octave_idx_type count (void) const + { + return m_count; + } + + octave_idx_type increment_count (void) + { + increment_total_use_count (); + return ++m_count; + } + + octave_idx_type decrement_count (void) + { + decrement_total_use_count (); + return --m_count; + } + protected: // This should only be called for derived types. @@ -855,12 +901,6 @@ protected: void reset (void) const; - // A reference count. - // NOTE: the declaration is octave_idx_type because with 64-bit indexing, - // it is well possible to have more than MAX_INT copies of a single value - // (think of an empty cell array with >2G elements). - octave::refcount count; - static const char * get_umap_name (unary_mapper_t); void warn_load (const char *type) const; @@ -868,6 +908,12 @@ protected: private: + // A reference count. + // NOTE: the declaration is octave_idx_type because with 64-bit indexing, + // it is well possible to have more than MAX_INT copies of a single value + // (think of an empty cell array with >2G elements). + octave::refcount m_count; + void wrong_type_arg_error (void) const; static int curr_print_indent_level; diff --git a/libinterp/octave-value/ov-cell.cc b/libinterp/octave-value/ov-cell.cc --- a/libinterp/octave-value/ov-cell.cc +++ b/libinterp/octave-value/ov-cell.cc @@ -353,7 +353,7 @@ octave_cell::subsasgn (const std::string else octave_base_matrix::assign (i, Cell (t_rhs)); - count++; + increment_count (); retval = octave_value (this); } break; @@ -385,7 +385,7 @@ octave_cell::subsasgn (const std::string else err_nonbraced_cs_list_assignment (); - count++; + increment_count (); retval = octave_value (this); } break; diff --git a/libinterp/octave-value/ov-class.cc b/libinterp/octave-value/ov-class.cc --- a/libinterp/octave-value/ov-class.cc +++ b/libinterp/octave-value/ov-class.cc @@ -64,6 +64,8 @@ int octave_class::t_id (-1); const std::string octave_class::t_name ("class"); +octave::refcount octave_class::s_total_use_count (0); + void octave_class::register_type (octave::type_info& ti) { @@ -206,16 +208,16 @@ octave_class::octave_class (const octave octave_base_value * octave_class::unique_clone (void) { - if (count == obsolete_copies) + if (count () == obsolete_copies) { // All remaining copies are obsolete. We don't actually need to clone. - count++; + increment_count (); return this; } else { // In theory, this shouldn't be happening, but it's here just in case. - if (count < obsolete_copies) + if (count () < obsolete_copies) obsolete_copies = 0; return clone (); @@ -306,7 +308,7 @@ octave_class::size (void) if (meth.is_defined ()) { - count++; + increment_count (); octave_value_list args (1, octave_value (this)); octave_value_list lv = octave::feval (meth.function_value (), args, 1); @@ -349,7 +351,7 @@ octave_class::numel (const octave_value_ { octave_value_list args (idx.length () + 1, octave_value ()); - count++; + increment_count (); args(0) = octave_value (this); for (octave_idx_type i = 0; i < idx.length (); i++) @@ -447,7 +449,7 @@ octave_class::subsref (const std::string args(1) = make_idx_args (type, idx, "subsref"); - count++; + increment_count (); args(0) = octave_value (this); // FIXME: for Matlab compatibility, let us attempt to set up a proper @@ -511,7 +513,7 @@ octave_class::subsasgn (const std::strin const std::list& idx, const octave_value& rhs) { - count++; + increment_count (); return subsasgn_common (octave_value (this), type, idx, rhs); } @@ -614,7 +616,7 @@ octave_class::subsasgn_common (const oct obvp->subsasgn (type, idx, rhs); - count++; + increment_count (); retval = octave_value (this); return retval; @@ -740,7 +742,7 @@ octave_class::subsasgn_common (const oct map.assign (idx.front (), key, t_rhs); - count++; + increment_count (); retval = octave_value (this); } else @@ -751,7 +753,7 @@ octave_class::subsasgn_common (const oct map.assign (idx.front (), rhs_map); - count++; + increment_count (); retval = octave_value (this); } else @@ -761,7 +763,7 @@ octave_class::subsasgn_common (const oct map.delete_elements (idx.front ()); - count++; + increment_count (); retval = octave_value (this); } } @@ -796,7 +798,7 @@ octave_class::subsasgn_common (const oct map.setfield (key, tmp_cell); } - count++; + increment_count (); retval = octave_value (this); } break; diff --git a/libinterp/octave-value/ov-class.h b/libinterp/octave-value/ov-class.h --- a/libinterp/octave-value/ov-class.h +++ b/libinterp/octave-value/ov-class.h @@ -218,6 +218,26 @@ private: static const std::string t_name; std::string c_name; + +public: + octave_idx_type total_use_count (void) const + { + return s_total_use_count; + } + + octave_idx_type increment_total_use_count (void) + { + return ++s_total_use_count; + } + + octave_idx_type decrement_total_use_count (void) + { + return --s_total_use_count; + } + +private: + static octave::refcount s_total_use_count; + std::list parent_list; bool in_class_method (void); diff --git a/libinterp/octave-value/ov-classdef.cc b/libinterp/octave-value/ov-classdef.cc --- a/libinterp/octave-value/ov-classdef.cc +++ b/libinterp/octave-value/ov-classdef.cc @@ -875,7 +875,7 @@ octave_classdef::subsref (const std::str args(1) = make_idx_args (type, idx, "subsref"); - count++; + increment_count (); args(0) = octave_value (this); retval = meth.execute (args, nargout, true, "subsref"); @@ -934,7 +934,7 @@ octave_classdef::subsasgn (const std::st args(1) = make_idx_args (type, idx, "subsasgn"); - count++; + increment_count (); args(0) = octave_value (this); args(2) = rhs; @@ -987,7 +987,7 @@ octave_classdef::numel (const octave_val { octave_value_list args (idx.length () + 1, octave_value ()); - count++; + increment_count (); args(0) = octave_value (this); for (octave_idx_type i = 0; i < idx.length (); i++) diff --git a/libinterp/octave-value/ov-java.cc b/libinterp/octave-value/ov-java.cc --- a/libinterp/octave-value/ov-java.cc +++ b/libinterp/octave-value/ov-java.cc @@ -2070,6 +2070,8 @@ int octave_java::t_id (-1); const std::string octave_java::t_name ("octave_java"); +octave::refcount octave_java::s_total_use_count (0); + void octave_java::register_type (octave::type_info& ti) { @@ -2124,7 +2126,7 @@ octave_java::subsref (const std::string& if (type.length () > 1 && type[1] == '(') { octave_value_list ovl; - count++; + increment_count (); ovl(1) = octave_value (this); ovl(0) = (idx.front ())(0); auto it = idx.begin (); @@ -2135,7 +2137,7 @@ octave_java::subsref (const std::string& else { octave_value_list ovl; - count++; + increment_count (); ovl(0) = octave_value (this); ovl(1) = (idx.front ())(0); retval = F__java_get__ (ovl, 1); @@ -2190,13 +2192,13 @@ octave_java::subsasgn (const std::string { // field assignment octave_value_list ovl; - count++; + increment_count (); ovl(0) = octave_value (this); ovl(1) = (idx.front ())(0); ovl(2) = rhs; F__java_set__ (ovl); - count++; + increment_count (); retval = octave_value (this); } else if (type.length () > 2 && type[1] == '(') @@ -2212,7 +2214,7 @@ octave_java::subsasgn (const std::string next_idx.erase (next_idx.begin ()); u(0).subsasgn (type.substr (2), next_idx, rhs); - count++; + increment_count (); retval = octave_value (this); } else if (type[1] == '.') @@ -2223,7 +2225,7 @@ octave_java::subsasgn (const std::string next_idx.erase (next_idx.begin ()); u(0).subsasgn (type.substr (1), next_idx, rhs); - count++; + increment_count (); retval = octave_value (this); } else @@ -2236,7 +2238,7 @@ octave_java::subsasgn (const std::string set_array_elements (current_env, TO_JOBJECT (to_java ()), idx.front (), rhs); - count++; + increment_count (); retval = octave_value (this); } break; diff --git a/libinterp/octave-value/ov-java.h b/libinterp/octave-value/ov-java.h --- a/libinterp/octave-value/ov-java.h +++ b/libinterp/octave-value/ov-java.h @@ -184,6 +184,27 @@ private: static int t_id; static const std::string t_name; + +public: + + octave_idx_type total_use_count (void) const + { + return s_total_use_count; + } + + octave_idx_type increment_total_use_count (void) + { + return ++s_total_use_count; + } + + octave_idx_type decrement_total_use_count (void) + { + return --s_total_use_count; + } + +private: + + static octave::refcount s_total_use_count; }; extern OCTINTERP_API bool Vjava_matrix_autoconversion; diff --git a/libinterp/octave-value/ov-perm.cc b/libinterp/octave-value/ov-perm.cc --- a/libinterp/octave-value/ov-perm.cc +++ b/libinterp/octave-value/ov-perm.cc @@ -115,7 +115,7 @@ octave_perm_matrix::do_index_op (const o else { retval = this; - this->count++; + this->increment_count (); } } } diff --git a/libinterp/octave-value/ov-re-diag.cc b/libinterp/octave-value/ov-re-diag.cc --- a/libinterp/octave-value/ov-re-diag.cc +++ b/libinterp/octave-value/ov-re-diag.cc @@ -115,7 +115,7 @@ octave_diag_matrix::do_index_op (const o else { retval = this; - this->count++; + this->increment_count (); } } } diff --git a/libinterp/octave-value/ov-struct.cc b/libinterp/octave-value/ov-struct.cc --- a/libinterp/octave-value/ov-struct.cc +++ b/libinterp/octave-value/ov-struct.cc @@ -441,7 +441,7 @@ octave_struct::subsasgn (const std::stri map.assign (idxf, key, tmp_cell); - count++; + increment_count (); retval = octave_value (this); } else @@ -455,7 +455,7 @@ octave_struct::subsasgn (const std::stri map.assign (idxf, key, Cell (t_rhs.storable_value ())); - count++; + increment_count (); retval = octave_value (this); } else @@ -470,7 +470,7 @@ octave_struct::subsasgn (const std::stri map.assign (idx.front (), rhs_map); - count++; + increment_count (); retval = octave_value (this); } else @@ -480,7 +480,7 @@ octave_struct::subsasgn (const std::stri map.delete_elements (idx.front ()); - count++; + increment_count (); retval = octave_value (this); } } @@ -517,7 +517,7 @@ octave_struct::subsasgn (const std::stri map.setfield (key, tmp_cell); } - count++; + increment_count (); retval = octave_value (this); } break; @@ -1238,7 +1238,7 @@ octave_scalar_struct::subsasgn (const st map.setfield (key, t_rhs.storable_value ()); - count++; + increment_count (); retval = this; } else diff --git a/libinterp/octave-value/ov.cc b/libinterp/octave-value/ov.cc --- a/libinterp/octave-value/ov.cc +++ b/libinterp/octave-value/ov.cc @@ -25,6 +25,8 @@ along with Octave; see the file COPYING. # include "config.h" #endif +#include + #include "data-conv.h" #include "quit.h" #include "str-vec.h" @@ -1122,7 +1124,7 @@ octave_value::octave_value (octave_base_ : rep (new_rep) { if (borrow) - rep->count++; + rep->increment_count (); } octave_base_value * @@ -1138,7 +1140,7 @@ octave_value::maybe_mutate (void) if (tmp && tmp != rep) { - if (--rep->count == 0) + if (rep->decrement_count () == 0) delete rep; rep = tmp; @@ -1525,7 +1527,7 @@ octave_value::assign (assign_op op, cons octave::type_info::assign_op_fcn f = nullptr; // Only attempt to operate in-place if this variable is unshared. - if (rep->count == 1) + if (rep->count () == 1) { int tthis = this->type_id (); int trhs = rhs.type_id (); @@ -2145,7 +2147,7 @@ octave_value::make_storable_value (void) if (isnull ()) { octave_base_value *rc = rep->empty_clone (); - if (--rep->count == 0) + if (rep->decrement_count () == 0) delete rep; rep = rc; } @@ -2752,14 +2754,14 @@ octave_value::do_non_const_unary_op (una { f (*rep); - if (old_rep && --old_rep->count == 0) + if (old_rep && old_rep->decrement_count () == 0) delete old_rep; } else { if (old_rep) { - if (--rep->count == 0) + if (rep->decrement_count () == 0) delete rep; rep = old_rep; @@ -2778,7 +2780,7 @@ octave_value::do_non_const_unary_op (una octave::type_info::non_const_unary_op_fcn f = nullptr; // Only attempt to operate in-place if this variable is unshared. - if (rep->count == 1) + if (rep->count () == 1) { octave::type_info& ti = octave::__get_type_info__ ("do_non_const_unary_op"); @@ -2968,6 +2970,73 @@ install_types (octave::type_info& ti) octave_lazy_index::register_type (ti); octave_oncleanup::register_type (ti); octave_java::register_type (ti); + + display_octave_value_counts (); +} + +template +void display_count (void) +{ + std::cerr << T::static_type_name () << ": " + << T::static_total_use_count () << std::endl; +} + +void display_octave_value_counts (void) +{ + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); + display_count (); } DEFUN (sizeof, args, , diff --git a/libinterp/octave-value/ov.h b/libinterp/octave-value/ov.h --- a/libinterp/octave-value/ov.h +++ b/libinterp/octave-value/ov.h @@ -174,7 +174,7 @@ public: octave_value (void) : rep (nil_rep ()) { - rep->count++; + rep->increment_count (); } octave_value (short int i); @@ -307,7 +307,7 @@ public: octave_value (const octave_value& a) { rep = a.rep; - rep->count++; + rep->increment_count (); } // This should only be called for derived types. @@ -321,17 +321,17 @@ public: ~octave_value (void) { - if (--rep->count == 0) + if (rep->decrement_count () == 0) delete rep; } void make_unique (void) { - if (rep->count > 1) + if (rep->count () > 1) { octave_base_value *r = rep->unique_clone (); - if (--rep->count == 0) + if (rep->decrement_count () == 0) delete rep; rep = r; @@ -343,11 +343,11 @@ public: // know a certain copy, typically within a cell array, to be obsolete. void make_unique (int obsolete_copies) { - if (rep->count > obsolete_copies + 1) + if (rep->count () > obsolete_copies + 1) { octave_base_value *r = rep->unique_clone (); - if (--rep->count == 0) + if (rep->decrement_count () == 0) delete rep; rep = r; @@ -360,17 +360,17 @@ public: { if (rep != a.rep) { - if (--rep->count == 0) + if (rep->decrement_count () == 0) delete rep; rep = a.rep; - rep->count++; + rep->increment_count (); } return *this; } - octave_idx_type get_count (void) const { return rep->count; } + octave_idx_type get_count (void) const { return rep->count (); } octave_base_value::type_conv_info numeric_conversion_function (void) const { return rep->numeric_conversion_function (); } @@ -1639,6 +1639,8 @@ OV_COMP_BINOP_FN (op_mul_herm) extern OCTINTERP_API void install_types (octave::type_info&); +extern void display_octave_value_counts (void); + // Templated value extractors. template inline Value octave_value_extract (const octave_value&)