Mercurial > octave
changeset 32371:ff0859c6f361
VM Freshen up auxilliary dev functions
Add support for handles, script. Fix broken "vm is executing" function.
libinterp/corefcn/compile.cc: Changed
author | Petter T. <petter.vilhelm@gmail.com> |
---|---|
date | Wed, 20 Sep 2023 22:00:45 +0200 |
parents | 9155a67023bc |
children | 2c0dc2ac3d3b |
files | libinterp/corefcn/compile.cc |
diffstat | 1 files changed, 179 insertions(+), 37 deletions(-) [+] |
line wrap: on
line diff
--- a/libinterp/corefcn/compile.cc Fri Sep 22 15:46:36 2023 +0200 +++ b/libinterp/corefcn/compile.cc Wed Sep 20 22:00:45 2023 +0200 @@ -146,7 +146,15 @@ @end deftypefn */) { - bool bytecode_running = interp.get_evaluator ().get_current_stack_frame ()->is_bytecode_fcn_frame (); + auto frame = interp.get_evaluator ().get_current_stack_frame (); + if (!frame) + error ("Invalid current frame"); + + auto caller_frame = frame->static_link (); + if (!caller_frame) + error ("Invalid caller frame"); + + bool bytecode_running = caller_frame->is_bytecode_fcn_frame (); return octave_value {bytecode_running}; } @@ -264,13 +272,14 @@ return octave_value {true}; } -DEFMETHOD (__print_bytecode__, interp, args, , +DEFMETHOD (__vm_print_bytecode__, interp, args, , doc: /* -*- texinfo -*- -@deftypefn {} {@var{success} =} __print_bytecode__ (@var{fn_name})) +@deftypefn {} {@var{success} =} __vm_print_bytecode__ (@var{fn_name})) +@deftypefnx {} {@var{success} =} __vm_print_bytecode__ (@var{fn_handle})) Internal function. -Prints the bytecode of a function, if any. +Prints the bytecode of a function name or function handle, if any. @end deftypefn */) { @@ -296,7 +305,19 @@ else ov = args (0); - octave_user_function *ufn = ov.user_function_value (); + octave_user_code *ufn = nullptr; + octave_fcn_handle *h = nullptr; + + if (ov.is_function_handle ()) + { + h = ov.fcn_handle_value (); + if (!h) + error ("Invalid function handle"); + ufn = h->user_function_value (); + } + else + ufn = ov.user_code_value (); + std::string fn_name = ufn->name (); if (!ufn || (!ufn->is_user_function () && !ufn->is_user_script ())) @@ -304,8 +325,15 @@ error ("Function not a user function or script: %s", fn_name.c_str ()); } - if (!ufn->is_compiled () && V__vm_enable__ && !ov.is_anonymous_function ()) - compile_user_function (*ufn, 0); + // Nested functions need to be compiled via their parent + bool is_nested = ufn->is_nested_function (); + + bool try_compile = !ufn->is_compiled () && V__vm_enable__ && !is_nested; + + if (try_compile && h && h->is_anonymous ()) + h->compile (); + else if (try_compile) + vm::maybe_compile_or_compiled (ufn, 0); else if (!ufn->is_compiled ()) error ("Function not compiled: %s", fn_name.c_str ()); @@ -319,12 +347,78 @@ return octave_value {true}; } +DEFMETHOD (__vm_is_compiled__, interp, args, , + doc: /* -*- texinfo -*- +@deftypefn {} {@var{is_compiled} =} __vm_is_compiled__ (@var{fn_name}) +@deftypefnx {} {@var{is_compiled} =} __vm_is_compiled__ (@var{fn_handle}) + +Internal function. + +Returns true if the specified function name or function handle is compiled. + +False otherwise. + +@end deftypefn */) +{ + int nargin = args.length (); + + if (nargin != 1) + print_usage (); + + std::string fcn_to_compile; + octave_fcn_handle *handle_to_compile = nullptr; + + bool do_handle = false; + + if (args (0).is_string ()) + fcn_to_compile = args (0).string_value (); + else if (args (0).is_function_handle ()) + { + handle_to_compile = args (0).fcn_handle_value (); + do_handle = true; + } + else + error ("First argument need to be a function name or function handle."); + + try + { + if (do_handle) + { + octave_user_function *ufn = handle_to_compile->user_function_value (); + if (!ufn) + return octave_value {false}; + return octave_value {ufn->is_compiled ()}; + } + else + { + std::string name = fcn_to_compile; + symbol_table& symtab = interp.get_symbol_table (); + octave_value ov = symtab.find_function (name); + + if (!ov.is_defined ()) + return octave_value {false}; + + octave_user_code *ufn = ov.user_code_value (); + if (!ufn) + return octave_value {false}; + + return octave_value {ufn->is_compiled ()}; + } + } + catch (execution_exception &) + { + return octave_value {false}; + } +} + DEFMETHOD (__vm_compile__, interp, args, , doc: /* -*- texinfo -*- @deftypefn {} {@var{success} =} __vm_compile__ (@var{fn_name}) @deftypefnx {} {@var{success} =} __vm_compile__ (@var{fn_name}, "clear") @deftypefnx {} {@var{success} =} __vm_compile__ (@var{fn_name}, "print") +Internal function. + Compile the specified function to bytecode. The compiled function and its subfunctions will be executed @@ -332,6 +426,8 @@ Returns true on success, otherwise false. +Don't recompile or clear the bytecode of a running function with __vm_compile__. + The @qcode{"print"} option prints the bytecode after compilation. The @qcode{"clear"} option removes the bytecode from the function instead. @@ -344,10 +440,19 @@ print_usage (); std::string fcn_to_compile; + octave_fcn_handle *handle_to_compile = nullptr; + bool do_clear = false; bool do_print = false; - for (int i = 0; i < nargin; i++) + if (args (0).is_string ()) + fcn_to_compile = args (0).string_value (); + else if (args (0).is_function_handle ()) + handle_to_compile = args (0).fcn_handle_value (); + else + error ("First argument need to be a function name or function handle."); + + for (int i = 1; i < nargin; i++) { auto arg = args(i); @@ -356,12 +461,6 @@ std::string arg_s = arg.string_value (); - if (i == 0) - { - fcn_to_compile = arg_s; - continue; - } - if (arg_s == "clear") do_clear = true; @@ -369,7 +468,17 @@ do_print = true; } - if (do_clear) + if (do_clear && handle_to_compile) + { + octave_user_function *ufn = handle_to_compile->user_function_value (); + if (!ufn) + error ("Invalid function handle"); + + ufn->clear_bytecode (); + + return octave_value {true}; + } + else if (do_clear) { std::string name = fcn_to_compile; symbol_table& symtab = interp.get_symbol_table (); @@ -382,9 +491,9 @@ octave_user_code *ufn = ov.user_code_value (); - if (!ufn || !ufn->is_user_function ()) + if (!ufn || (!ufn->is_user_function () && !ufn->is_user_script ())) { - error ("Function not a user function: %s", name.c_str ()); + error ("Function not an user function or script: %s", name.c_str ()); } ufn->clear_bytecode (); @@ -392,32 +501,65 @@ return octave_value {true}; } + if (handle_to_compile) + { + octave_user_function *ufn = handle_to_compile->user_function_value (); + if (!ufn) + error ("Invalid function handle"); - { - std::string name = fcn_to_compile; - symbol_table& symtab = interp.get_symbol_table (); - octave_value ov = symtab.find_function (name); + if (ufn->is_nested_function ()) + error ("Nested functions need to be compiled via their parent"); - if (!ov.is_defined ()) - { - error ("Function not defined: %s", name.c_str ()); - } + // Anonymous functions need to be compiled via their handle + // to get the locals. + if (handle_to_compile->is_anonymous ()) + { + handle_to_compile->compile (); + if (do_print && ufn->is_compiled ()) + { + auto bc = ufn->get_bytecode (); + print_bytecode (bc); + } + + return octave_value {true}; + } + else + { + // Throws on errors + compile_user_function (*ufn, do_print); - if (!ov.is_user_function () && !ov.is_user_script ()) - { - error ("Function is not a user function or script: %s", name.c_str ()); - } + return octave_value {true}; + } + } + else + { + std::string name = fcn_to_compile; + symbol_table& symtab = interp.get_symbol_table (); + octave_value ov = symtab.find_function (name); - octave_user_code *ufn = ov.user_code_value (); + if (!ov.is_defined ()) + { + error ("Function not defined: %s", name.c_str ()); + } - if (!ufn || (!ufn->is_user_function () && !ufn->is_user_script ())) - { - error ("Function is not really user function or script: %s", name.c_str ()); - } + if (!ov.is_user_function () && !ov.is_user_script ()) + { + error ("Function is not a user function or script: %s", name.c_str ()); + } + + octave_user_code *ufn = ov.user_code_value (); - // Throws on errors - compile_user_function (*ufn, do_print); - } + if (!ufn || (!ufn->is_user_function () && !ufn->is_user_script ())) + { + error ("Function is not really user function or script: %s", name.c_str ()); + } + + if (ufn->is_nested_function ()) + error ("Nested functions need to be compiled via their parent"); + + // Throws on errors + compile_user_function (*ufn, do_print); + } return octave_value {true}; }