emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Aliasing EQ to EQL (was: [RFC PATCH] Per-window face support)


From: Stefan Monnier
Subject: Aliasing EQ to EQL (was: [RFC PATCH] Per-window face support)
Date: Sun, 17 Jun 2018 18:25:00 -0400
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/27.0.50 (gnu/linux)

>> Getting rid of `eq' is just lying to programmers about object identity.
>
> I don't see how it would be lying to equate eq and eql for numbers.  An
> object's identity is not the same thing as a machine-level address, and
> whether two instances of the same number are eq is an implementation detail
> that Lisp programmers should not rely upon.
>
> This doesn't mean that we should equate eq and eql. Perhaps there are good
> efficiency reasons to continue to distinguish them. But these would be
> merely pragmatic, not philosophical.

BTW, if someone is tempted to measure the impact, here's the naive patch
I've been using recently.

It doesn't try to be clever: other than NILP, all uses of EQ are changed
to use EQL.  Clearly, we could improve on that, but I think such
improvements should be "profile-guided".

In terms of code size it added 100KB (out of a 4MB stripped binary, so
about 0.25%) which is not insignificant, but is a cost I'm willing to
live with.


        Stefan


diff --git a/src/fns.c b/src/fns.c
index de1dad3736..11709ae266 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -2108,10 +2108,7 @@ DEFUN ("eql", Feql, Seql, 2, 2, 0,
 Floating-point numbers of equal value are `eql', but they may not be `eq'.  */)
   (Lisp_Object obj1, Lisp_Object obj2)
 {
-  if (FLOATP (obj1))
-    return equal_no_quit (obj1, obj2) ? Qt : Qnil;
-  else
-    return EQ (obj1, obj2) ? Qt : Qnil;
+  return EQL (obj1, obj2) ? Qt : Qnil;
 }
 
 DEFUN ("equal", Fequal, Sequal, 2, 2, 0,
@@ -2192,7 +2189,7 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, enum 
equal_kind equal_kind,
        }
     }
 
-  if (EQ (o1, o2))
+  if (lisp_h_EQ (o1, o2))
     return true;
   if (XTYPE (o1) != XTYPE (o2))
     return false;
@@ -3684,7 +3681,7 @@ cmpfn_user_defined (struct hash_table_test *ht,
    in a Lisp integer.  */
 
 static EMACS_UINT
-hashfn_eq (struct hash_table_test *ht, Lisp_Object key)
+hashfn__eq (struct hash_table_test *ht, Lisp_Object key)
 {
   return XHASH (key) ^ XTYPE (key);
 }
@@ -3706,7 +3703,13 @@ hashfn_equal (struct hash_table_test *ht, Lisp_Object 
key)
 static EMACS_UINT
 hashfn_eql (struct hash_table_test *ht, Lisp_Object key)
 {
-  return FLOATP (key) ? hashfn_equal (ht, key) : hashfn_eq (ht, key);
+  return FLOATP (key) ? hashfn_equal (ht, key) : hashfn__eq (ht, key);
+}
+
+static EMACS_UINT
+hashfn_eq (struct hash_table_test *ht, Lisp_Object key)
+{
+  return hashfn_eql (ht, key);
 }
 
 /* Value is a hash code for KEY for use in hash table H which uses as
diff --git a/src/lisp.h b/src/lisp.h
index 56ad8b814b..e3b2cd9cf0 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -322,7 +322,7 @@ error !;
 #define lisp_h_INTEGERP(x) ((XTYPE (x) & (Lisp_Int0 | ~Lisp_Int1)) == 
Lisp_Int0)
 #define lisp_h_MARKERP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Marker)
 #define lisp_h_MISCP(x) (XTYPE (x) == Lisp_Misc)
-#define lisp_h_NILP(x) EQ (x, Qnil)
+#define lisp_h_NILP(x) lisp_h_EQ (x, Qnil)
 #define lisp_h_SET_SYMBOL_VAL(sym, v) \
    (eassert ((sym)->u.s.redirect == SYMBOL_PLAINVAL), \
     (sym)->u.s.val.value = (v))
@@ -374,7 +374,7 @@ error !;
 # define CHECK_SYMBOL(x) lisp_h_CHECK_SYMBOL (x)
 # define CHECK_TYPE(ok, predicate, x) lisp_h_CHECK_TYPE (ok, predicate, x)
 # define CONSP(x) lisp_h_CONSP (x)
-# define EQ(x, y) lisp_h_EQ (x, y)
+# define EQ(x, y) EQL (x, y)
 # define FLOATP(x) lisp_h_FLOATP (x)
 # define INTEGERP(x) lisp_h_INTEGERP (x)
 # define MARKERP(x) lisp_h_MARKERP (x)
@@ -1040,10 +1040,21 @@ make_natnum (EMACS_INT n)
 
 /* Return true if X and Y are the same object.  */
 
+extern bool equal_no_quit (Lisp_Object o1, Lisp_Object o2);
+
+INLINE bool
+EQL (Lisp_Object x, Lisp_Object y)
+{
+  if (lisp_h_FLOATP (x))
+    return equal_no_quit (x, y);
+  else
+    return lisp_h_EQ (x, y);
+}
+
 INLINE bool
 (EQ) (Lisp_Object x, Lisp_Object y)
 {
-  return lisp_h_EQ (x, y);
+  return EQL (x, y);
 }
 
 /* True if the possibly-unsigned integer I doesn't fit in a Lisp fixnum.  */
@@ -3432,7 +3443,6 @@ extern Lisp_Object merge (Lisp_Object, Lisp_Object, 
Lisp_Object);
 extern Lisp_Object do_yes_or_no_p (Lisp_Object);
 extern Lisp_Object concat2 (Lisp_Object, Lisp_Object);
 extern Lisp_Object concat3 (Lisp_Object, Lisp_Object, Lisp_Object);
-extern bool equal_no_quit (Lisp_Object, Lisp_Object);
 extern Lisp_Object nconc2 (Lisp_Object, Lisp_Object);
 extern Lisp_Object assq_no_quit (Lisp_Object, Lisp_Object);
 extern Lisp_Object assoc_no_quit (Lisp_Object, Lisp_Object);




reply via email to

[Prev in Thread] Current Thread [Next in Thread]