77#include "misc.h"
88#include "mpconfig.h"
99#include "obj.h"
10+ #include "map.h"
1011#include "runtime.h"
1112#include "bc.h"
1213
@@ -129,9 +130,10 @@ mp_obj_t rt_make_function_var_between(int n_args_min, int n_args_max, mp_fun_var
129130
130131typedef struct _mp_obj_fun_bc_t {
131132 mp_obj_base_t base ;
132- int n_args ;
133- uint n_state ;
134- const byte * code ;
133+ mp_map_t * globals ; // the context within which this function was defined
134+ int n_args ; // number of arguments this function takes
135+ uint n_state ; // total state size for the executing function (incl args, locals, stack)
136+ const byte * bytecode ; // bytecode for the function
135137} mp_obj_fun_bc_t ;
136138
137139// args are in reverse order in the array
@@ -142,15 +144,17 @@ mp_obj_t fun_bc_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
142144 nlr_jump (mp_obj_new_exception_msg_2_args (rt_q_TypeError , "function takes %d positional arguments but %d were given" , (const char * )(machine_int_t )self -> n_args , (const char * )(machine_int_t )n_args ));
143145 }
144146
145- return mp_execute_byte_code (self -> code , args , n_args , self -> n_state );
146- }
147-
148- void mp_obj_fun_bc_get (mp_obj_t self_in , int * n_args , uint * n_state , const byte * * code ) {
149- assert (MP_OBJ_IS_TYPE (self_in , & fun_bc_type ));
150- mp_obj_fun_bc_t * self = self_in ;
151- * n_args = self -> n_args ;
152- * n_state = self -> n_state ;
153- * code = self -> code ;
147+ // optimisation: allow the compiler to optimise this tail call for
148+ // the common case when the globals don't need to be changed
149+ mp_map_t * old_globals = rt_globals_get ();
150+ if (self -> globals == old_globals ) {
151+ return mp_execute_byte_code (self -> bytecode , args , n_args , self -> n_state );
152+ } else {
153+ rt_globals_set (self -> globals );
154+ mp_obj_t result = mp_execute_byte_code (self -> bytecode , args , n_args , self -> n_state );
155+ rt_globals_set (old_globals );
156+ return result ;
157+ }
154158}
155159
156160const mp_obj_type_t fun_bc_type = {
@@ -170,12 +174,21 @@ const mp_obj_type_t fun_bc_type = {
170174mp_obj_t mp_obj_new_fun_bc (int n_args , uint n_state , const byte * code ) {
171175 mp_obj_fun_bc_t * o = m_new_obj (mp_obj_fun_bc_t );
172176 o -> base .type = & fun_bc_type ;
177+ o -> globals = rt_globals_get ();
173178 o -> n_args = n_args ;
174179 o -> n_state = n_state ;
175- o -> code = code ;
180+ o -> bytecode = code ;
176181 return o ;
177182}
178183
184+ void mp_obj_fun_bc_get (mp_obj_t self_in , int * n_args , uint * n_state , const byte * * code ) {
185+ assert (MP_OBJ_IS_TYPE (self_in , & fun_bc_type ));
186+ mp_obj_fun_bc_t * self = self_in ;
187+ * n_args = self -> n_args ;
188+ * n_state = self -> n_state ;
189+ * code = self -> bytecode ;
190+ }
191+
179192/******************************************************************************/
180193/* inline assembler functions */
181194
0 commit comments