# HG changeset patch # User Petter T. # Date 1698423579 -7200 # Fri Oct 27 18:19:39 2023 +0200 # Node ID 9a9e04e3f249d68211db64bfdf68466588018d54 # Parent 6e770b6fca8f3b8c6f6fb3d3fa4098fd7d6bfba0 Lookup function cache with arguments on the bytecode vm stack Avoids allocating container for bytecode to bytecode calls by using pointers to the vm stack as parameters to function cache querries. * ov-base.h: New function get_cached_fcn(void*,void*) * ov-fcn-handle.cc: get_cached_fcn(void*,void*) * ov-fcn-handle.h: get_cached_fcn(void*,void*) * ov-fcn.h: New functions get_cached_fcn_if_fresh, has_cached_function, get_cached_fcn(void*,void*) * ov-fcn.cc: Defs * ov.h: New function get_cached_fcn(void*,void*) diff -r 6e770b6fca8f -r 9a9e04e3f249 libinterp/octave-value/ov-base.h --- a/libinterp/octave-value/ov-base.h Fri Oct 27 18:19:32 2023 +0200 +++ b/libinterp/octave-value/ov-base.h Fri Oct 27 18:19:39 2023 +0200 @@ -551,6 +551,8 @@ virtual octave_function * get_cached_fcn (const octave_value_list&) { return nullptr; } + virtual octave_function * get_cached_fcn (void*, void*) { return nullptr; } + virtual octave_fcn_cache * fcn_cache_value (void) { return nullptr; } virtual void erase_subfunctions () { } diff -r 6e770b6fca8f -r 9a9e04e3f249 libinterp/octave-value/ov-fcn-handle.cc --- a/libinterp/octave-value/ov-fcn-handle.cc Fri Oct 27 18:19:32 2023 +0200 +++ b/libinterp/octave-value/ov-fcn-handle.cc Fri Oct 27 18:19:39 2023 +0200 @@ -233,6 +233,9 @@ octave_function * get_cached_fcn (const octave_value_list &args); + octave_function * + get_cached_fcn (void *beg, void *end); + bool has_function_cache (void) const; private: @@ -311,6 +314,15 @@ friend bool is_equal_to (const scoped_fcn_handle& fh1, const scoped_fcn_handle& fh2); + octave_function * + get_cached_fcn (void *, void *) { return m_fcn.function_value (); } + + octave_function * + get_cached_fcn (const octave_value_list&) { return m_fcn.function_value (); } + + bool + has_function_cache (void) const { return true; } + protected: void find_function (); @@ -697,6 +709,10 @@ octave_function * get_cached_fcn (const octave_value_list&) { return m_fcn.function_value (); } + + octave_function * + get_cached_fcn (void *, void *) { return m_fcn.function_value (); } + // TODO: This is a hack to get uncompiled anonymous functions to be subsrefed in the VM bool has_function_cache (void) const { @@ -977,6 +993,7 @@ // FIXME: Find a way to avoid duplication of code in // simple_fcn_handle::call + octave_function * simple_fcn_handle:: get_cached_fcn (const octave_value_list &args) @@ -1033,6 +1050,23 @@ } } +octave_function * +simple_fcn_handle:: +get_cached_fcn (void *pbeg, void *pend) +{ + if (m_cache.has_cached_function (pbeg, pend)) + return m_cache.get_cached_fcn (); + + octave::stack_element *beg = static_cast (pbeg); + octave::stack_element *end = static_cast (pend); + + octave_value_list args; + while (beg != end) + args.append ((beg++)->ov); + + return get_cached_fcn (args); // TODO: Avoid extra call to has_cached_function() +} + // FIXME: Find a way to avoid duplication of code in // simple_fcn_handle::call // Like call(), but instead returns true if the call() would end diff -r 6e770b6fca8f -r 9a9e04e3f249 libinterp/octave-value/ov-fcn-handle.h --- a/libinterp/octave-value/ov-fcn-handle.h Fri Oct 27 18:19:32 2023 +0200 +++ b/libinterp/octave-value/ov-fcn-handle.h Fri Oct 27 18:19:39 2023 +0200 @@ -155,7 +155,11 @@ } virtual octave_function * + get_cached_fcn (void *, void *) { return nullptr; } + + virtual octave_function * get_cached_fcn (const octave_value_list&) { return nullptr; } + virtual bool has_function_cache (void) const { return false; } @@ -374,7 +378,11 @@ is_equal_to (const octave_fcn_handle& fh1, const octave_fcn_handle& fh2); octave_function * + get_cached_fcn (void *beg, void *end) { return m_rep->get_cached_fcn (beg, end); } + + octave_function * get_cached_fcn (const octave_value_list& args) { return m_rep->get_cached_fcn (args); } + bool has_function_cache (void) const { return m_rep->has_function_cache (); } vm_call_dispatch_type vm_dispatch_call (void) diff -r 6e770b6fca8f -r 9a9e04e3f249 libinterp/octave-value/ov-fcn.cc --- a/libinterp/octave-value/ov-fcn.cc Fri Oct 27 18:19:32 2023 +0200 +++ b/libinterp/octave-value/ov-fcn.cc Fri Oct 27 18:19:39 2023 +0200 @@ -69,6 +69,29 @@ return execute (tw, nargout, args); } +bool +octave_fcn_cache::has_cached_function (void *pbeg, void *pend) const +{ + octave::stack_element *beg = static_cast (pbeg); + octave::stack_element *end = static_cast (pend); + + if (m_n_updated == 0) + return false; + + unsigned vec_n = m_cached_args.size (); + + unsigned n_args = end - beg; + if (n_args != vec_n) + return false; + + for (unsigned i = 0; i < n_args; i++) + { + if (beg[i].ov.type_id () != m_cached_args [i]) + return false; + } + + return true; +} void octave_fcn_cache::set_cached_function (octave_value ov, @@ -79,6 +102,9 @@ if (!ov.is_defined ()) return; + // Arbitrary limit on how many args we keep track of in caches. + if (args.length () > 32) + return; // We need to keep a reference to the metaobject for as long as the function is alive if (ov.is_classdef_meta ()) @@ -105,12 +131,12 @@ octave_value octave_fcn_cache:: -get_cached_obj (const octave_value_list& args) +get_cached_obj () { octave_function *fcn = nullptr; octave_idx_type current_n_updated = octave::load_path::get_weak_n_updated (); - if (has_cached_function (args)) + if (has_cached_function (nullptr, nullptr)) { if (m_n_updated == current_n_updated) return m_cached_function; @@ -124,12 +150,12 @@ octave::__get_interpreter__ (); octave::symbol_table& symtab = interp.get_symbol_table (); - octave_value val = symtab.find_function (m_fcn_name, args); + octave_value val = symtab.find_function (m_fcn_name, octave_value_list {}); if (val.is_function ()) { fcn = val.function_value (true); - set_cached_function (val, args, current_n_updated); + set_cached_function (val, octave_value_list {}, current_n_updated); return val; } @@ -176,6 +202,16 @@ octave_function * octave_fcn_cache:: +get_cached_fcn_if_fresh () +{ + octave_idx_type current_n_updated = octave::load_path::get_weak_n_updated (); + if (m_n_updated == current_n_updated) + return get_cached_fcn (); + return nullptr; +} + +octave_function * +octave_fcn_cache:: get_cached_fcn (const octave_value_list& args) { octave_idx_type current_n_updated = octave::load_path::get_weak_n_updated (); @@ -186,6 +222,30 @@ return get_cached_fcn_internal (args); } +octave_function * +octave_fcn_cache:: +get_cached_fcn (void *pbeg, void *pend) +{ + octave_idx_type current_n_updated = octave::load_path::get_weak_n_updated (); + if (OCTAVE_LIKELY (has_cached_function (pbeg, pend))) + if (OCTAVE_LIKELY (m_n_updated == current_n_updated)) + return m_cached_function.function_value (true); + + octave::stack_element *beg = static_cast (pbeg); + octave::stack_element *end = static_cast (pend); + + octave_value_list args; + for (; beg != end; beg++) + { + if (OCTAVE_UNLIKELY (beg->ov.is_cs_list ())) + args.append (beg->ov.list_value ()); + else + args.append (beg->ov); + } + + return get_cached_fcn_internal (args); +} + octave_value_list octave_fcn_cache:: call (octave::tree_evaluator& tw, diff -r 6e770b6fca8f -r 9a9e04e3f249 libinterp/octave-value/ov-fcn.h --- a/libinterp/octave-value/ov-fcn.h Fri Oct 27 18:19:32 2023 +0200 +++ b/libinterp/octave-value/ov-fcn.h Fri Oct 27 18:19:39 2023 +0200 @@ -71,10 +71,13 @@ get_cached_fcn (const octave_value_list& args); octave_function * + get_cached_fcn (void *beg, void *end); + + octave_function * get_cached_fcn () { return m_cached_function.function_value (); } octave_value - get_cached_obj (const octave_value_list& args); + get_cached_obj (); octave_fcn_cache * fcn_cache_value (void) { @@ -109,6 +112,10 @@ return true; } + bool has_cached_function (void *beg, void *end) const; + + octave_function * get_cached_fcn_if_fresh (); + private: octave_function * get_cached_fcn_internal (const octave_value_list& args); @@ -318,6 +325,15 @@ const octave_value_list& args = octave_value_list ()) = 0; vm_call_dispatch_type vm_dispatch_call (void) { return vm_call_dispatch_type::CALL; } + + octave_function * + get_cached_fcn (void *, void *) { return function_value (); } + + octave_function * + get_cached_fcn (const octave_value_list&) { return function_value (); } + + bool has_function_cache (void) const { return true; } + protected: octave_function (const std::string& nm, diff -r 6e770b6fca8f -r 9a9e04e3f249 libinterp/octave-value/ov.h --- a/libinterp/octave-value/ov.h Fri Oct 27 18:19:32 2023 +0200 +++ b/libinterp/octave-value/ov.h Fri Oct 27 18:19:39 2023 +0200 @@ -1572,6 +1572,11 @@ octave_function * get_cached_fcn (const octave_value_list& args) { return m_rep->get_cached_fcn (args); } + // Arguments need to be pointing to union stack_element:s. + // Using void* to avoid polluting namespace. + octave_function * get_cached_fcn (void *beg, void *end) + { return m_rep->get_cached_fcn (beg, end); } + // Returns true if the octave_value is either undefined or // or a function. bool is_maybe_function (void) const