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"]]
|