comparison src/vim9execute.c @ 19532:b8f778dda1a1 v8.2.0323

patch 8.2.0323: Vim9: calling a function that is defined later is slow Commit: https://github.com/vim/vim/commit/7eeefd4a395fe3d7c7a2a0879467cf7ed4c29fe6 Author: Bram Moolenaar <Bram@vim.org> Date: Wed Feb 26 21:24:23 2020 +0100 patch 8.2.0323: Vim9: calling a function that is defined later is slow Problem: Vim9: calling a function that is defined later is slow. Solution: Once the function is found update the instruction so it can be called directly.
author Bram Moolenaar <Bram@vim.org>
date Wed, 26 Feb 2020 21:30:04 +0100
parents 3b026343f398
children 7df9c8df26f1
comparison
equal deleted inserted replaced
19531:d984a63f23df 19532:b8f778dda1a1
265 return OK; 265 return OK;
266 } 266 }
267 267
268 /* 268 /*
269 * Execute a user defined function. 269 * Execute a user defined function.
270 * "iptr" can be used to replace the instruction with a more efficient one.
270 */ 271 */
271 static int 272 static int
272 call_ufunc(ufunc_T *ufunc, int argcount, ectx_T *ectx) 273 call_ufunc(ufunc_T *ufunc, int argcount, ectx_T *ectx, isn_T *iptr)
273 { 274 {
274 typval_T argvars[MAX_FUNC_ARGS]; 275 typval_T argvars[MAX_FUNC_ARGS];
275 funcexe_T funcexe; 276 funcexe_T funcexe;
276 int error; 277 int error;
277 int idx; 278 int idx;
278 279
279 if (ufunc->uf_dfunc_idx >= 0) 280 if (ufunc->uf_dfunc_idx >= 0)
280 // The function has been compiled, can call it quickly. 281 {
282 // The function has been compiled, can call it quickly. For a function
283 // that was defined later: we can call it directly next time.
284 if (iptr != NULL)
285 {
286 iptr->isn_type = ISN_DCALL;
287 iptr->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
288 iptr->isn_arg.dfunc.cdf_argcount = argcount;
289 }
281 return call_dfunc(ufunc->uf_dfunc_idx, argcount, ectx); 290 return call_dfunc(ufunc->uf_dfunc_idx, argcount, ectx);
291 }
282 292
283 if (call_prepare(argcount, argvars, ectx) == FAIL) 293 if (call_prepare(argcount, argvars, ectx) == FAIL)
284 return FAIL; 294 return FAIL;
285 vim_memset(&funcexe, 0, sizeof(funcexe)); 295 vim_memset(&funcexe, 0, sizeof(funcexe));
286 funcexe.evaluate = TRUE; 296 funcexe.evaluate = TRUE;
303 } 313 }
304 314
305 /* 315 /*
306 * Execute a function by "name". 316 * Execute a function by "name".
307 * This can be a builtin function or a user function. 317 * This can be a builtin function or a user function.
318 * "iptr" can be used to replace the instruction with a more efficient one.
308 * Returns FAIL if not found without an error message. 319 * Returns FAIL if not found without an error message.
309 */ 320 */
310 static int 321 static int
311 call_by_name(char_u *name, int argcount, ectx_T *ectx) 322 call_by_name(char_u *name, int argcount, ectx_T *ectx, isn_T *iptr)
312 { 323 {
313 ufunc_T *ufunc; 324 ufunc_T *ufunc;
314 325
315 if (builtin_function(name, -1)) 326 if (builtin_function(name, -1))
316 { 327 {
323 return call_bfunc(func_idx, argcount, ectx); 334 return call_bfunc(func_idx, argcount, ectx);
324 } 335 }
325 336
326 ufunc = find_func(name, NULL); 337 ufunc = find_func(name, NULL);
327 if (ufunc != NULL) 338 if (ufunc != NULL)
328 return call_ufunc(ufunc, argcount, ectx); 339 return call_ufunc(ufunc, argcount, ectx, iptr);
329 340
330 return FAIL; 341 return FAIL;
331 } 342 }
332 343
333 static int 344 static int
339 if (tv->v_type == VAR_PARTIAL) 350 if (tv->v_type == VAR_PARTIAL)
340 { 351 {
341 partial_T *pt = tv->vval.v_partial; 352 partial_T *pt = tv->vval.v_partial;
342 353
343 if (pt->pt_func != NULL) 354 if (pt->pt_func != NULL)
344 return call_ufunc(pt->pt_func, argcount, ectx); 355 return call_ufunc(pt->pt_func, argcount, ectx, NULL);
345 name = pt->pt_name; 356 name = pt->pt_name;
346 } 357 }
347 else 358 else
348 name = tv->vval.v_string; 359 name = tv->vval.v_string;
349 if (call_by_name(name, argcount, ectx) == FAIL) 360 if (call_by_name(name, argcount, ectx, NULL) == FAIL)
350 { 361 {
351 if (called_emsg == called_emsg_before) 362 if (called_emsg == called_emsg_before)
352 semsg(_(e_unknownfunc), name); 363 semsg(_(e_unknownfunc), name);
353 return FAIL; 364 return FAIL;
354 } 365 }
370 } 381 }
371 382
372 /* 383 /*
373 * Execute a function by "name". 384 * Execute a function by "name".
374 * This can be a builtin function, user function or a funcref. 385 * This can be a builtin function, user function or a funcref.
386 * "iptr" can be used to replace the instruction with a more efficient one.
375 */ 387 */
376 static int 388 static int
377 call_eval_func(char_u *name, int argcount, ectx_T *ectx) 389 call_eval_func(char_u *name, int argcount, ectx_T *ectx, isn_T *iptr)
378 { 390 {
379 int called_emsg_before = called_emsg; 391 int called_emsg_before = called_emsg;
380 392
381 if (call_by_name(name, argcount, ectx) == FAIL 393 if (call_by_name(name, argcount, ectx, iptr) == FAIL
382 && called_emsg == called_emsg_before) 394 && called_emsg == called_emsg_before)
383 { 395 {
384 // "name" may be a variable that is a funcref or partial 396 // "name" may be a variable that is a funcref or partial
385 // if find variable 397 // if find variable
386 // call_partial() 398 // call_partial()
981 { 993 {
982 cufunc_T *cufunc = &iptr->isn_arg.ufunc; 994 cufunc_T *cufunc = &iptr->isn_arg.ufunc;
983 995
984 SOURCING_LNUM = iptr->isn_lnum; 996 SOURCING_LNUM = iptr->isn_lnum;
985 if (call_eval_func(cufunc->cuf_name, 997 if (call_eval_func(cufunc->cuf_name,
986 cufunc->cuf_argcount, &ectx) == FAIL) 998 cufunc->cuf_argcount, &ectx, iptr) == FAIL)
987 goto failed; 999 goto failed;
988 } 1000 }
989 break; 1001 break;
990 1002
991 // return from a :def function call 1003 // return from a :def function call
1556 { 1568 {
1557 int error = FALSE; 1569 int error = FALSE;
1558 1570
1559 tv = STACK_TV_BOT(-1); 1571 tv = STACK_TV_BOT(-1);
1560 if (check_not_string(tv) == FAIL) 1572 if (check_not_string(tv) == FAIL)
1561 { 1573 goto failed;
1562 --ectx.ec_stack.ga_len;
1563 goto failed;
1564 }
1565 (void)tv_get_number_chk(tv, &error); 1574 (void)tv_get_number_chk(tv, &error);
1566 if (error) 1575 if (error)
1567 goto failed; 1576 goto failed;
1568 } 1577 }
1569 break; 1578 break;
1625 *rettv = *tv; 1634 *rettv = *tv;
1626 tv->v_type = VAR_UNKNOWN; 1635 tv->v_type = VAR_UNKNOWN;
1627 ret = OK; 1636 ret = OK;
1628 1637
1629 failed: 1638 failed:
1639 // When failed need to unwind the call stack.
1640 while (ectx.ec_frame != initial_frame_ptr)
1641 func_return(&ectx);
1642
1630 for (idx = 0; idx < ectx.ec_stack.ga_len; ++idx) 1643 for (idx = 0; idx < ectx.ec_stack.ga_len; ++idx)
1631 clear_tv(STACK_TV(idx)); 1644 clear_tv(STACK_TV(idx));
1632 vim_free(ectx.ec_stack.ga_data); 1645 vim_free(ectx.ec_stack.ga_data);
1633 return ret; 1646 return ret;
1634 } 1647 }