summaryrefslogtreecommitdiffstats
path: root/2025/talks/juicemacs.md
blob: 1a5f8c792bbc4565c849768cf63997ad84f142a4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
[[!meta title="Juicemacs: Exploring Speculative JIT Compilation for ELisp in Java"]]
[[!meta copyright="Copyright © 2025 Kana"]]
[[!inline pages="internal(2025/info/juicemacs-nav)" raw="yes"]]

<!-- Initially generated with emacsconf-publish-talk-page and then left alone for manual editing -->
<!-- You can manually edit this file to update the abstract, add links, etc. --->


# Juicemacs: Exploring Speculative JIT Compilation for ELisp in Java
Kana (they/them) - IRC: kanakana, Blog: https://kyo.iroiro.party - ActivityPub: @kana@f.iroiro.party - Bluesky: @kana.iroiro.party, <mailto:kana@iroiro.party>

[[!inline pages="internal(2025/info/juicemacs-before)" raw="yes"]]

Just-in-time (JIT) compilation helps dynamic languages run fast, and
speculative compilation makes them run faster, as has been showcased
by JVMs, LuaJIT, JavaScript engines, and many more JIT runtimes.
However, Emacs native-compilation, despite its JIT compilation
(`native-comp-jit-compilation`), does not speculate about runtime
execution, making it effectively a JIT-ish AOT (ahead-of-time)
compiler. By introducing a speculative runtime for ELisp, we could
potentially improve ELisp performance even further, with many new
optimization opportunities.

Juicemacs is my work-in-progress toy project re-implementing Emacs in
Java. At its centre sits an ELisp JIT runtime powered by Graal
Truffle, a JIT interpreter framework based on partial evaluation and
Futamura projections. This talk will cover the following along with
some demonstrations:

-   What is Juicemacs and its ambition? How compatible is it (or does
    it plan to be) with GNU Emacs and how feature-complete is it now?

-   What is speculative compilation? How is it useful for an ELisp JIT
    runtime?

-   How is the performance of Juicemacs compared to Emacs nativecomp?
    How do we interpret the benchmarks?

-   What is Truffle and partial evaluation? What is needed if we are
    to implement a speculative runtime in C without Truffle?

-   What JIT techniques and other things does Juicemacs plan to
    explore? How to get involved?

Relevant links:

-   Accompanying blog post (slides + transcript + more discussions):
    <https://kyo.iroiro.party/en/posts/juicemacs-exploring-jit-for-elisp/>
    (scheduled to become available after the talk)

-   Project repository: <https://github.com/gudzpoz/Juicemacs> or
    <https://codeberg.org/gudzpoz/Juicemacs>

-   ERT testing results: <https://emacsen.de/dev/tests/>

-   Zulip chat (devlog + discussions): <https://juice.zulipchat.com>

About the speaker:

Hello! This is Kana, an Emacs hobbyist and Java lover from China. A
few years ago I discovered the Truffle JIT compilation framework and
have since hoped to implement a JIT runtime myself. Last year I
finally started implementing one for ELisp, called Juicemacs, and
have made some progress. In this talk I will share what I've learned
during the journey, including how three interpreters out of four (or
more?) in Emacs are implemented in Juicemacs and how speculative
compilation can make some optimizations possible.

## Discussion / notes

-   Q: Sorry for the explain-for-CL-user question - is what juicemacs is
    doing analogous to issuing a new declamation then doing something
    like (funcall (eval (function-lambda-expression
    #'my-sbcl-function))) ?
    -   -   (Thanks I had been confused about JIT a little bit)

    -   A: I actually know very little about CL (the benchmarks come
        from an article linked in elisp-benchmarks). Personally I think
        the difference between Juicemacs and CL impl like SBCL, is that,
        most CL runtimes I know actually ahead-of-time compiles code,
        even in REPL, but Juicemacs is a JIT runtime and tries to gather
        statistics before compiling things (mostly through Truffle). For
        function calls, Juicemacs has several optimizations, like
        assuming unchanged function definitions (and recompile when it
        changes), and cache functions produced by `#'(lambda ()
        ...)` constructs.
-   Q: What's the inspiration behind the name Juicemacs?
    -   A: Since it is in Java, so I want the name to begin with 'J'.
        Since juice is humorously not solid, I chose that name :)
-   Q: Do you think the GC of Juicemacs will have similarities with the
    GC iterations of GNU Emacs (such as IGC)?
    -   A: I am very much looking forward to IGC but haven't tried it
        yet. The difference between IGC (using MPS under the hood) and
        JVM GCs is that the MPS used by Emacs is conservative (GC term)
        and not "precise" (also GC term), in that it guesses what
        machine words on the stack are actual objects, but otherwise it
        should be a very competent GC.
-   Q: Just reading the blog - your experiments with Emacs are so
    extensive :D how'd you get started? Have you experience writing
    text editors?
    -   A: Thanks! Currently, Juicemacs is mostly about an ELisp runtime
        though and has very little actual "text editor" things. (It
        has proper elisp buffers, but not display in any way - no
        GUI/TUI). And with a functional elisp runtime, an actual editor
        can (1) be fairly easy if you ignore a bunch of things mentioned
        in the blog, (2) or very very hard if you want to replicate
        Emacs. And, sadly, no, I don't have experience previously
        writing text editors, so my current plan is to delegate
        rendering to GTK (and Pango for low-level rendering to support
        overlays) (and other programmers by using a proper IPC protocol
        :-) ), and delegate editing to ELisp (which is also what Emacs
        does).
    -   For getting started, I don't know? I've already started
        experimenting with a bit more things. Basically it is all about
        replicating and learning from other implementations, like Emacs
        and GtkTextView (and GraalJs for JIT compilers) (oh! and VS
        Code, I just borrowed their intervalTree.ts for overlays): it's
        all there, written by competent people. And all you need is
        maybe read them all? ;P (Experimenting with Emacs and learning
        about it (and crashing it sometimes) is very fun, by the way.)
    -   Here is a little devlog:
        [https://juice.zulipchat.com/#narrow/channel/535506-gui/topic/Tiny.20progress.3A.20GUI.20dev.20log/with/562157361](https://juice.zulipchat.com/#narrow/channel/535506-gui/topic/Tiny.20progress.3A.20GUI.20dev.20log/with/562157361)
        , in which I am trying to get a GUI (and after that maybe an
        editor) working.
    -   (original question-asker) -> So: read read read, smash smash
        smash. Love it :D and zulip is a nice idea for organising public
        engagement with a project, looks v cool. Thanks for sharing!
-   Q: <emarsden> GraalVM is able to run C code via LLVM; I wonder
    whether it would be feasible to use some of the existing Emacs code
    in that way
    -   A: (Came across this interesting question on #emacs IRC.)
        Actually, Java has added FFI (or "Foreign Function and Memory,
        FFM) API very recently, so we can directly run (dynamically
        linked) C code without needing LLVM or GraalVM in Java. However,
        the thing I'm afraid of is that, Emacs is very complicated, and
        it seems rather impossible to just use "some" of its existing
        code without incorporating a whole GNU Emacs... (For example,
        even passing a cons list from Java to C code is very hard, since
        we need to now care about ABI compatibility. Not to mention that
        in many places Emacs just assumes it is run with its built-in
        GC.) But, speaking of FFM, I think we can make very good use of
        it to support Emacs dynamic modules (right now I'm also
        listening to the Emacs PDF reader talk, which is also a dynamic
        module). As far as I know, the API interface of Emacs dynamic
        modules is very clearly decoupled from Emacs internals (when
        reading /usr/include/emacs-module.h, which seems to make its
        `struct emacs_value` opaque, meaning that we can use any
        pointer, or even Java object references in that pointer), and we
        should be able to support any dynamic modules out there with
        FFM.
-   [https://codeberg.org/gudzpoz/Juicemacs](https://codeberg.org/gudzpoz/Juicemacs)
-   The blog article is now online:
    [https://kyo.iroiro.party/en/posts/juicemacs-exploring-jit-for-elisp/](https://kyo.iroiro.party/en/posts/juicemacs-exploring-jit-for-elisp/)
-   Wonderful explanations!  Thank you for taking the time to share your
    wisdom.
-   A very impressive project! Thanks for presenting it
-   [https://juice.zulipchat.com](https://juice.zulipchat.com)
-   Very exciting project!

- yet another exciting emacs clone lets goo!!
- I really want to end up with a formal specification of emacs lisp one day
- juicemacs elisp is suprisingly far along
- your jit compiled elisp is impressive
- Thanks, I know a little more about JIT now !
- Kana here! Thanks! Please feel free to ask any question. I'm also trying out a Zulip chat server for maybe lengthier discussions: https://juice.zulipchat.com .

[[!inline pages="internal(2025/info/juicemacs-after)" raw="yes"]]

[[!inline pages="internal(2025/info/juicemacs-nav)" raw="yes"]]