Speed up 'equal'-comparison of vectorlike objects

* src/fns.c (internal_equal_1): Switch on the vectorlike type instead of
using a sequence of type predicates.
This commit is contained in:
Mattias Engdegård 2026-02-24 12:19:22 +01:00
parent 2505af27c6
commit a84530ac2e

View file

@ -2940,12 +2940,12 @@ internal_equal_1 (Lisp_Object o1, Lisp_Object o2, enum equal_kind equal_kind,
if (ASIZE (o2) != size)
return false;
/* Compare bignums, overlays, markers, boolvectors, and
symbols with position specially, by comparing their values. */
if (BIGNUMP (o1))
return mpz_cmp (*xbignum_val (o1), *xbignum_val (o2)) == 0;
if (OVERLAYP (o1))
switch (PSEUDOVECTOR_TYPE (XVECTOR (o1)))
{
case PVEC_BIGNUM:
return mpz_cmp (*xbignum_val (o1), *xbignum_val (o2)) == 0;
case PVEC_OVERLAY:
if (OVERLAY_BUFFER (o1) != OVERLAY_BUFFER (o2)
|| OVERLAY_START (o1) != OVERLAY_START (o2)
|| OVERLAY_END (o1) != OVERLAY_END (o2))
@ -2954,53 +2954,50 @@ internal_equal_1 (Lisp_Object o1, Lisp_Object o2, enum equal_kind equal_kind,
o2 = XOVERLAY (o2)->plist;
depth++;
goto tail_recurse;
}
if (MARKERP (o1))
{
case PVEC_MARKER:
return (XMARKER (o1)->buffer == XMARKER (o2)->buffer
&& (XMARKER (o1)->buffer == 0
|| XMARKER (o1)->bytepos == XMARKER (o2)->bytepos));
}
if (BOOL_VECTOR_P (o1))
{
EMACS_INT size = bool_vector_size (o1);
return (size == bool_vector_size (o2)
&& !memcmp (bool_vector_data (o1), bool_vector_data (o2),
bool_vector_bytes (size)));
}
case PVEC_BOOL_VECTOR:
{
EMACS_INT size = bool_vector_size (o1);
return (size == bool_vector_size (o2)
&& !memcmp (bool_vector_data (o1), bool_vector_data (o2),
bool_vector_bytes (size)));
}
#ifdef HAVE_TREE_SITTER
if (TS_NODEP (o1))
return treesit_node_eq (o1, o2);
case PVEC_TS_NODE:
return treesit_node_eq (o1, o2);
#endif
if (SYMBOL_WITH_POS_P (o1))
{
case PVEC_SYMBOL_WITH_POS:
eassert (!symbols_with_pos_enabled);
return (BASE_EQ (XSYMBOL_WITH_POS_SYM (o1),
XSYMBOL_WITH_POS_SYM (o2))
&& BASE_EQ (XSYMBOL_WITH_POS_POS (o1),
XSYMBOL_WITH_POS_POS (o2)));
}
/* Aside from them, only true vectors, char-tables, compiled
functions, and fonts (font-spec, font-entity, font-object)
are sensible to compare, so eliminate the others now. */
if (size & PSEUDOVECTOR_FLAG)
{
if (((size & PVEC_TYPE_MASK) >> PSEUDOVECTOR_AREA_BITS)
< PVEC_CLOSURE)
return false;
/* Compare these element-wise. */
case PVEC_CLOSURE:
case PVEC_CHAR_TABLE:
case PVEC_SUB_CHAR_TABLE:
case PVEC_RECORD:
case PVEC_FONT:
size &= PSEUDOVECTOR_SIZE_MASK;
FALLTHROUGH;
case PVEC_NORMAL_VECTOR:
for (ptrdiff_t i = 0; i < size; i++)
if (!internal_equal_1 (AREF (o1, i), AREF (o2, i),
equal_kind, depth + 1, ht))
return false;
return true;
default:
return false;
}
for (ptrdiff_t i = 0; i < size; i++)
{
Lisp_Object v1, v2;
v1 = AREF (o1, i);
v2 = AREF (o2, i);
if (!internal_equal_1 (v1, v2, equal_kind, depth + 1, ht))
return false;
}
return true;
}
break;