changeset 33246:877dddec681f v9.0.1895

patch 9.0.1895: Vim9: finding object method/member is inefficient Commit: https://github.com/vim/vim/commit/4d00b835c49ffc5c416b65ca466d6ad695cbd3d2 Author: Ernie Rael <errael@raelity.com> Date: Mon Sep 11 19:54:42 2023 +0200 patch 9.0.1895: Vim9: finding object method/member is inefficient Problem: Vim9: finding method/member is inefficient Solution: Use lookups closes: #13073 Signed-off-by: Christian Brabandt <cb@256bit.org> Co-authored-by: Ernie Rael <errael@raelity.com>
author Christian Brabandt <cb@256bit.org>
date Mon, 11 Sep 2023 20:00:03 +0200
parents 485561aa8f1e
children 3ba31a65248f
files src/version.c src/vim9class.c src/vim9expr.c src/vim9instr.c
diffstat 4 files changed, 103 insertions(+), 65 deletions(-) [+]
line wrap: on
line diff
--- a/src/version.c
+++ b/src/version.c
@@ -700,6 +700,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1895,
+/**/
     1894,
 /**/
     1893,
--- a/src/vim9class.c
+++ b/src/vim9class.c
@@ -1883,9 +1883,8 @@ class_object_index(
     if (*name_end == '(')
     {
 	ufunc_T *fp;
-	int	m_idx;
 
-	fp = method_lookup(cl, rettv->v_type, name, len, &m_idx);
+	fp = method_lookup(cl, rettv->v_type, name, len, NULL);
 	if (fp == NULL)
 	{
 	    semsg(_(e_method_not_found_on_class_str_str), cl->class_name,
@@ -2022,8 +2021,7 @@ find_class_func(char_u **arg)
 	goto fail_after_eval;
     len = fname_end - fname;
 
-    int m_idx;
-    fp = method_lookup(cl, tv.v_type, fname, len, &m_idx);
+    fp = method_lookup(cl, tv.v_type, fname, len, NULL);
 
 fail_after_eval:
     clear_tv(&tv);
@@ -2038,20 +2036,9 @@ fail_after_eval:
     int
 class_member_idx(class_T *cl, char_u *name, size_t namelen)
 {
-    for (int i = 0; i < cl->class_class_member_count; ++i)
-    {
-	ocmember_T *m = &cl->class_class_members[i];
-	if (namelen)
-	{
-	    if (STRNCMP(name, m->ocm_name, namelen) == 0
-		    && m->ocm_name[namelen] == NUL)
-		return i;
-	}
-	else if (STRCMP(name, m->ocm_name) == 0)
-	    return i;
-    }
-
-    return -1;
+    int idx;
+    class_member_lookup(cl, name, namelen, &idx);
+    return idx;
 }
 
 /*
@@ -2062,8 +2049,31 @@ class_member_idx(class_T *cl, char_u *na
     ocmember_T *
 class_member_lookup(class_T *cl, char_u *name, size_t namelen, int *idx)
 {
-    *idx = class_member_idx(cl, name, namelen);
-    return *idx >= 0 ? &cl->class_class_members[*idx] : NULL;
+    ocmember_T	*ret_m = NULL;
+    int		ret_idx = -1;
+    for (int i = 0; i < cl->class_class_member_count; ++i)
+    {
+	ocmember_T *m = &cl->class_class_members[i];
+	if (namelen)
+	{
+	    if (STRNCMP(name, m->ocm_name, namelen) == 0
+		    && m->ocm_name[namelen] == NUL)
+	    {
+		ret_m = m;
+		ret_idx = i;
+		break;
+	    }
+	}
+	else if (STRCMP(name, m->ocm_name) == 0)
+	{
+	    ret_m = m;
+	    ret_idx = i;
+            break;
+	}
+    }
+    if (idx != NULL)
+	*idx = ret_idx;
+    return ret_m;
 }
 
 /*
@@ -2073,15 +2083,9 @@ class_member_lookup(class_T *cl, char_u 
     int
 class_method_idx(class_T *cl, char_u *name, size_t namelen)
 {
-    for (int i = 0; i < cl->class_class_function_count; ++i)
-    {
-	ufunc_T *fp = cl->class_class_functions[i];
-	char_u *ufname = (char_u *)fp->uf_name;
-	if (STRNCMP(name, ufname, namelen) == 0 && ufname[namelen] == NUL)
-	    return i;
-    }
-
-    return -1;
+    int idx;
+    class_method_lookup(cl, name, namelen, &idx);
+    return idx;
 }
 
 /*
@@ -2092,8 +2096,22 @@ class_method_idx(class_T *cl, char_u *na
     ufunc_T *
 class_method_lookup(class_T *cl, char_u *name, size_t namelen, int *idx)
 {
-    *idx = class_method_idx(cl, name, namelen);
-    return *idx >= 0 ? cl->class_class_functions[*idx] : NULL;
+    ufunc_T	*ret_fp = NULL;
+    int		ret_idx = -1;
+    for (int i = 0; i < cl->class_class_function_count; ++i)
+    {
+	ufunc_T *fp = cl->class_class_functions[i];
+	char_u *ufname = (char_u *)fp->uf_name;
+	if (STRNCMP(name, ufname, namelen) == 0 && ufname[namelen] == NUL)
+	{
+	    ret_fp = fp;
+	    ret_idx = i;
+	    break;
+	}
+    }
+    if (idx != NULL)
+	*idx = ret_idx;
+    return ret_fp;
 }
 
 /*
@@ -2104,20 +2122,9 @@ class_method_lookup(class_T *cl, char_u 
     int
 object_member_idx(class_T *cl, char_u *name, size_t namelen)
 {
-    for (int i = 0; i < cl->class_obj_member_count; ++i)
-    {
-	ocmember_T *m = &cl->class_obj_members[i];
-	if (namelen)
-	{
-	    if (STRNCMP(name, m->ocm_name, namelen) == 0
-		    && m->ocm_name[namelen] == NUL)
-	    return i;
-	}
-	else if (STRCMP(name, m->ocm_name) == 0)
-	    return i;
-    }
-
-    return -1;
+    int idx;
+    object_member_lookup(cl, name, namelen, &idx);
+    return idx;
 }
 
 /*
@@ -2128,8 +2135,31 @@ object_member_idx(class_T *cl, char_u *n
     ocmember_T *
 object_member_lookup(class_T *cl, char_u *name, size_t namelen, int *idx)
 {
-    *idx = object_member_idx(cl, name, namelen);
-    return *idx >= 0 ? &cl->class_obj_members[*idx] : NULL;
+    ocmember_T	*ret_m = NULL;
+    int		ret_idx = -1;
+    for (int i = 0; i < cl->class_obj_member_count; ++i)
+    {
+	ocmember_T  *m = &cl->class_obj_members[i];
+	if (namelen)
+	{
+	    if (STRNCMP(name, m->ocm_name, namelen) == 0
+		    && m->ocm_name[namelen] == NUL)
+	    {
+		ret_m = m;
+		ret_idx = i;
+		break;
+	    }
+	}
+	else if (STRCMP(name, m->ocm_name) == 0)
+        {
+	    ret_m = m;
+	    ret_idx = i;
+            break;
+        }
+    }
+    if (idx != NULL)
+	*idx = ret_idx;
+    return ret_m;
 }
 
 /*
@@ -2139,17 +2169,9 @@ object_member_lookup(class_T *cl, char_u
     int
 object_method_idx(class_T *cl, char_u *name, size_t namelen)
 {
-    for (int i = 0; i < cl->class_obj_method_count; ++i)
-    {
-	ufunc_T *fp = cl->class_obj_methods[i];
-	// Use a separate pointer to avoid that ASAN complains about
-	// uf_name[] only being 4 characters.
-	char_u *ufname = (char_u *)fp->uf_name;
-	if (STRNCMP(name, ufname, namelen) == 0 && ufname[namelen] == NUL)
-	    return i;
-    }
-
-    return -1;
+    int idx;
+    object_method_lookup(cl, name, namelen, &idx);
+    return idx;
 }
 
 /*
@@ -2160,8 +2182,24 @@ object_method_idx(class_T *cl, char_u *n
     ufunc_T *
 object_method_lookup(class_T *cl, char_u *name, size_t namelen, int *idx)
 {
-    *idx = object_method_idx(cl, name, namelen);
-    return *idx >= 0 ? cl->class_obj_methods[*idx] : NULL;
+    ufunc_T	*ret_fp = NULL;
+    int		ret_idx = -1;
+    for (int i = 0; i < cl->class_obj_method_count; ++i)
+    {
+	ufunc_T *fp = cl->class_obj_methods[i];
+	// Use a separate pointer to avoid that ASAN complains about
+	// uf_name[] only being 4 characters.
+	char_u *ufname = (char_u *)fp->uf_name;
+	if (STRNCMP(name, ufname, namelen) == 0 && ufname[namelen] == NUL)
+	{
+	    ret_fp = fp;
+	    ret_idx = i;
+	    break;
+	}
+    }
+    if (idx != NULL)
+	*idx = ret_idx;
+    return ret_fp;
 }
 
 /*
--- a/src/vim9expr.c
+++ b/src/vim9expr.c
@@ -394,10 +394,10 @@ compile_class_object_index(cctx_T *cctx,
 
     if (type->tt_type == VAR_OBJECT)
     {
-	int m_idx = object_member_idx(cl, name, len);
+        int m_idx;
+        ocmember_T *m = object_member_lookup(cl, name, len, &m_idx);
 	if (m_idx >= 0)
 	{
-	    ocmember_T *m = &cl->class_obj_members[m_idx];
 	    if (*name == '_' && !inside_class(cctx, cl))
 	    {
 		semsg(_(e_cannot_access_private_member_str), m->ocm_name);
--- a/src/vim9instr.c
+++ b/src/vim9instr.c
@@ -1838,9 +1838,7 @@ generate_CALL(
 		{
 		    class_T *clp = mtype->tt_class;
 		    char_u  *aname = ((char_u **)ufunc->uf_args.ga_data)[i];
-		    int	    m_idx;
-		    ocmember_T *m = object_member_lookup(clp, aname, 0,
-									&m_idx);
+		    ocmember_T *m = object_member_lookup(clp, aname, 0, NULL);
 		    if (m != NULL)
 			expected = m->ocm_type;
 		}