diff options
| author | Stefan Kangas | 2025-02-28 18:28:58 +0100 |
|---|---|---|
| committer | Stefan Kangas | 2025-02-28 18:32:28 +0100 |
| commit | 8b659313b83c82cfe09af1638289fccdfc9af23d (patch) | |
| tree | ffe568825f16999e921c93920a2b5d7de8db1148 /src | |
| parent | 92a8d24e4948dd9e7fa8bdbadac48f9eed19fa49 (diff) | |
| download | emacs-8b659313b83c82cfe09af1638289fccdfc9af23d.tar.gz emacs-8b659313b83c82cfe09af1638289fccdfc9af23d.zip | |
Lift widget functions from C to Lisp
In the mid-1990s, these functions were moved from Lisp to C to
"improve performance". However, Moore's Law, and perhaps other
improvements too, has made this rationale irrelevant.
On this machine, with --native-compilation=no, I observed only a
slight ~4% performance difference. For example, displaying a buffer
full of widgets (e.g., 'M-x customize RET browse-url RET') takes 4ms
here, meaning the performance gap is under 0.1ms. Even on less
powerful machines, this difference would remain imperceptible. Given
this, let's lift these functions back to to Lisp, which offers the
usual benefits.
We already have solid test coverage, but let's add a more focused test
for 'widget-get' and 'widget-put' to be thorough.
* lisp/wid-edit.el (widget-put, widget-get, widget-apply): Move to
Lisp from...
* src/fns.c (Fwidget_put, Fwidget_get, Fwidget_apply): ...here.
(syms_of_fns): Remove defsubrs for the above functions.
* test/lisp/wid-edit-tests.el
(widget-test-editable-field-widget-get/put): New test.
Diffstat (limited to 'src')
| -rw-r--r-- | src/fns.c | 62 |
1 files changed, 1 insertions, 61 deletions
| @@ -3831,65 +3831,8 @@ FILENAME are suppressed. */) | |||
| 3831 | 3831 | ||
| 3832 | return feature; | 3832 | return feature; |
| 3833 | } | 3833 | } |
| 3834 | |||
| 3835 | /* Primitives for work of the "widget" library. | ||
| 3836 | In an ideal world, this section would not have been necessary. | ||
| 3837 | However, lisp function calls being as slow as they are, it turns | ||
| 3838 | out that some functions in the widget library (wid-edit.el) are the | ||
| 3839 | bottleneck of Widget operation. Here is their translation to C, | ||
| 3840 | for the sole reason of efficiency. */ | ||
| 3841 | |||
| 3842 | DEFUN ("widget-put", Fwidget_put, Swidget_put, 3, 3, 0, | ||
| 3843 | doc: /* In WIDGET, set PROPERTY to VALUE. | ||
| 3844 | The value can later be retrieved with `widget-get'. */) | ||
| 3845 | (Lisp_Object widget, Lisp_Object property, Lisp_Object value) | ||
| 3846 | { | ||
| 3847 | CHECK_CONS (widget); | ||
| 3848 | XSETCDR (widget, plist_put (XCDR (widget), property, value)); | ||
| 3849 | return value; | ||
| 3850 | } | ||
| 3851 | |||
| 3852 | DEFUN ("widget-get", Fwidget_get, Swidget_get, 2, 2, 0, | ||
| 3853 | doc: /* In WIDGET, get the value of PROPERTY. | ||
| 3854 | The value could either be specified when the widget was created, or | ||
| 3855 | later with `widget-put'. */) | ||
| 3856 | (Lisp_Object widget, Lisp_Object property) | ||
| 3857 | { | ||
| 3858 | Lisp_Object tmp; | ||
| 3859 | |||
| 3860 | while (1) | ||
| 3861 | { | ||
| 3862 | if (NILP (widget)) | ||
| 3863 | return Qnil; | ||
| 3864 | CHECK_CONS (widget); | ||
| 3865 | tmp = plist_member (XCDR (widget), property); | ||
| 3866 | if (CONSP (tmp)) | ||
| 3867 | { | ||
| 3868 | tmp = XCDR (tmp); | ||
| 3869 | return CAR (tmp); | ||
| 3870 | } | ||
| 3871 | tmp = XCAR (widget); | ||
| 3872 | if (NILP (tmp)) | ||
| 3873 | return Qnil; | ||
| 3874 | widget = Fget (tmp, Qwidget_type); | ||
| 3875 | } | ||
| 3876 | } | ||
| 3877 | |||
| 3878 | DEFUN ("widget-apply", Fwidget_apply, Swidget_apply, 2, MANY, 0, | ||
| 3879 | doc: /* Apply the value of WIDGET's PROPERTY to the widget itself. | ||
| 3880 | Return the result of applying the value of PROPERTY to WIDGET. | ||
| 3881 | ARGS are passed as extra arguments to the function. | ||
| 3882 | usage: (widget-apply WIDGET PROPERTY &rest ARGS) */) | ||
| 3883 | (ptrdiff_t nargs, Lisp_Object *args) | ||
| 3884 | { | ||
| 3885 | Lisp_Object widget = args[0]; | ||
| 3886 | Lisp_Object property = args[1]; | ||
| 3887 | Lisp_Object propval = Fwidget_get (widget, property); | ||
| 3888 | Lisp_Object trailing_args = Flist (nargs - 2, args + 2); | ||
| 3889 | Lisp_Object result = CALLN (Fapply, propval, widget, trailing_args); | ||
| 3890 | return result; | ||
| 3891 | } | ||
| 3892 | 3834 | ||
| 3835 | |||
| 3893 | #ifdef HAVE_LANGINFO_CODESET | 3836 | #ifdef HAVE_LANGINFO_CODESET |
| 3894 | #include <langinfo.h> | 3837 | #include <langinfo.h> |
| 3895 | #endif | 3838 | #endif |
| @@ -6903,9 +6846,6 @@ For best results this should end in a space. */); | |||
| 6903 | defsubr (&Srequire); | 6846 | defsubr (&Srequire); |
| 6904 | defsubr (&Sprovide); | 6847 | defsubr (&Sprovide); |
| 6905 | defsubr (&Splist_member); | 6848 | defsubr (&Splist_member); |
| 6906 | defsubr (&Swidget_put); | ||
| 6907 | defsubr (&Swidget_get); | ||
| 6908 | defsubr (&Swidget_apply); | ||
| 6909 | defsubr (&Sbase64_encode_region); | 6849 | defsubr (&Sbase64_encode_region); |
| 6910 | defsubr (&Sbase64_decode_region); | 6850 | defsubr (&Sbase64_decode_region); |
| 6911 | defsubr (&Sbase64_encode_string); | 6851 | defsubr (&Sbase64_encode_string); |