comparison src/vim9execute.c @ 23976:03819ebd3e6d v8.2.2530

patch 8.2.2530: Vim9: not enough testing for profiling Commit: https://github.com/vim/vim/commit/12d265315fac9e4f3436c38a87f6d9a23b9e7e2b Author: Bram Moolenaar <Bram@vim.org> Date: Fri Feb 19 19:13:21 2021 +0100 patch 8.2.2530: Vim9: not enough testing for profiling Problem: Vim9: not enough testing for profiling. Solution: Add a test with nested functions and a lambda. Fix profiling for calling a compiled function.
author Bram Moolenaar <Bram@vim.org>
date Fri, 19 Feb 2021 19:15:03 +0100
parents f9a4ede76237
children 9fcd71d0db89
comparison
equal deleted inserted replaced
23975:a1b074b83f39 23976:03819ebd3e6d
69 isn_T *ec_instr; // array with instructions 69 isn_T *ec_instr; // array with instructions
70 int ec_iidx; // index in ec_instr: instruction to execute 70 int ec_iidx; // index in ec_instr: instruction to execute
71 71
72 garray_T ec_funcrefs; // partials that might be a closure 72 garray_T ec_funcrefs; // partials that might be a closure
73 }; 73 };
74
75 #ifdef FEAT_PROFILE
76 // stack of profinfo_T used when profiling.
77 static garray_T profile_info_ga = {0, 0, sizeof(profinfo_T), 20, NULL};
78 #endif
74 79
75 // Get pointer to item relative to the bottom of the stack, -1 is the last one. 80 // Get pointer to item relative to the bottom of the stack, -1 is the last one.
76 #define STACK_TV_BOT(idx) (((typval_T *)ectx->ec_stack.ga_data) + ectx->ec_stack.ga_len + (idx)) 81 #define STACK_TV_BOT(idx) (((typval_T *)ectx->ec_stack.ga_data) + ectx->ec_stack.ga_len + (idx))
77 82
78 void 83 void
182 dfunc->df_name == NULL ? (char_u *)"unknown" : dfunc->df_name); 187 dfunc->df_name == NULL ? (char_u *)"unknown" : dfunc->df_name);
183 return FAIL; 188 return FAIL;
184 } 189 }
185 190
186 #ifdef FEAT_PROFILE 191 #ifdef FEAT_PROFILE
187 // Profiling might be enabled/disabled along the way. This should not 192 if (do_profiling == PROF_YES)
188 // fail, since the function was compiled before and toggling profiling 193 {
189 // doesn't change any errors. 194 if (ga_grow(&profile_info_ga, 1) == OK)
190 if (func_needs_compiling(ufunc, PROFILING(ufunc)) 195 {
191 && compile_def_function(ufunc, FALSE, PROFILING(ufunc), NULL) 196 profinfo_T *info = ((profinfo_T *)profile_info_ga.ga_data)
197 + profile_info_ga.ga_len;
198 ++profile_info_ga.ga_len;
199 CLEAR_POINTER(info);
200 profile_may_start_func(info, ufunc,
201 (((dfunc_T *)def_functions.ga_data)
202 + ectx->ec_dfunc_idx)->df_ufunc);
203 }
204
205 // Profiling might be enabled/disabled along the way. This should not
206 // fail, since the function was compiled before and toggling profiling
207 // doesn't change any errors.
208 if (func_needs_compiling(ufunc, PROFILING(ufunc))
209 && compile_def_function(ufunc, FALSE, PROFILING(ufunc), NULL)
192 == FAIL) 210 == FAIL)
193 return FAIL; 211 return FAIL;
212 }
194 #endif 213 #endif
195 214
196 if (ufunc->uf_va_name != NULL) 215 if (ufunc->uf_va_name != NULL)
197 { 216 {
198 // Need to make a list out of the vararg arguments. 217 // Need to make a list out of the vararg arguments.
515 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) 534 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
516 + ectx->ec_dfunc_idx; 535 + ectx->ec_dfunc_idx;
517 int argcount = ufunc_argcount(dfunc->df_ufunc); 536 int argcount = ufunc_argcount(dfunc->df_ufunc);
518 int top = ectx->ec_frame_idx - argcount; 537 int top = ectx->ec_frame_idx - argcount;
519 estack_T *entry; 538 estack_T *entry;
520 539 int prev_dfunc_idx = STACK_TV(ectx->ec_frame_idx
540 + STACK_FRAME_FUNC_OFF)->vval.v_number;
541 dfunc_T *prev_dfunc = ((dfunc_T *)def_functions.ga_data)
542 + prev_dfunc_idx;
543
544 #ifdef FEAT_PROFILE
545 if (do_profiling == PROF_YES)
546 {
547 ufunc_T *caller = prev_dfunc->df_ufunc;
548
549 if (dfunc->df_ufunc->uf_profiling
550 || (caller != NULL && caller->uf_profiling))
551 {
552 profile_may_end_func(((profinfo_T *)profile_info_ga.ga_data)
553 + profile_info_ga.ga_len - 1, dfunc->df_ufunc, caller);
554 --profile_info_ga.ga_len;
555 }
556 }
557 #endif
521 // execution context goes one level up 558 // execution context goes one level up
522 entry = estack_pop(); 559 entry = estack_pop();
523 if (entry != NULL) 560 if (entry != NULL)
524 current_sctx.sc_sid = entry->es_save_sid; 561 current_sctx.sc_sid = entry->es_save_sid;
525 562
542 ret_idx = 0; 579 ret_idx = 0;
543 580
544 vim_free(ectx->ec_outer); 581 vim_free(ectx->ec_outer);
545 582
546 // Restore the previous frame. 583 // Restore the previous frame.
547 ectx->ec_dfunc_idx = STACK_TV(ectx->ec_frame_idx 584 ectx->ec_dfunc_idx = prev_dfunc_idx;
548 + STACK_FRAME_FUNC_OFF)->vval.v_number;
549 ectx->ec_iidx = STACK_TV(ectx->ec_frame_idx 585 ectx->ec_iidx = STACK_TV(ectx->ec_frame_idx
550 + STACK_FRAME_IIDX_OFF)->vval.v_number; 586 + STACK_FRAME_IIDX_OFF)->vval.v_number;
551 ectx->ec_outer = (void *)STACK_TV(ectx->ec_frame_idx 587 ectx->ec_outer = (void *)STACK_TV(ectx->ec_frame_idx
552 + STACK_FRAME_OUTER_OFF)->vval.v_string; 588 + STACK_FRAME_OUTER_OFF)->vval.v_string;
553 // restoring ec_frame_idx must be last 589 // restoring ec_frame_idx must be last
554 ectx->ec_frame_idx = STACK_TV(ectx->ec_frame_idx 590 ectx->ec_frame_idx = STACK_TV(ectx->ec_frame_idx
555 + STACK_FRAME_IDX_OFF)->vval.v_number; 591 + STACK_FRAME_IDX_OFF)->vval.v_number;
556 dfunc = ((dfunc_T *)def_functions.ga_data) + ectx->ec_dfunc_idx; 592 ectx->ec_instr = INSTRUCTIONS(prev_dfunc);
557 ectx->ec_instr = INSTRUCTIONS(dfunc);
558 593
559 if (ret_idx > 0) 594 if (ret_idx > 0)
560 { 595 {
561 // Reset the stack to the position before the call, with a spot for the 596 // Reset the stack to the position before the call, with a spot for the
562 // return value, moved there from above the frame. 597 // return value, moved there from above the frame.