View Gemfile.diff
diff --git a/Gemfile b/Gemfile
index 3db4f98f0a..75cd7943a3 100644
--- a/Gemfile
+++ b/Gemfile
@@ -3,7 +3,7 @@ source ''
#source ''
# does not install in linux ATM, so hack this for now
-gem 'bootsnap', require: false
+gem 'bootsnap', require: false, platform: :mri
View listing.txt
[] ~/projects/ruby $ ls /var/folders/y0/b32crdwx1zvb9zvq3w_ccny80000gn/T/*mjit*
View gist:5c3b25bdd1fbca47513416223e82861a
root@87006c934ea0:~/jruby# time jruby -e 1
real 0m1.469s
user 0m3.440s
sys 0m0.210s
root@87006c934ea0:~/jruby# time jruby -e 1
private static final Method nop1;
private static final MethodHandle nop2;
private static final MethodHandle nop3;
static {
Method _nop1 = null;
MethodHandle _nop2 = null;
MethodHandle _nop3 = null;
try {
_nop1 = Hello.class.getMethod("nop", long.class);
View bloop
[] ~/projects/jruby $ cat > wacky.c
#include <stdio.h>
int main() {
printf("this " "is " "a " "C " "thing" "\n");
return 0;
[] ~/projects/jruby $ gcc wacky.c ; ./a.out
this is a C thing
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
public class Hello {
private static final MethodHandles.Lookup lookup = MethodHandles.lookup();
public static void main(String[] args) throws Throwable {
System.out.println("Hello, " + args[0]);
View gist:88d7f5449049794e286aab364de9830d
[exec] 1. [1/2] Assertion for "stdout"
[exec] | <["[fcall(proc,[],&block([],[unary(!,ref(y))]))]"]> expected but was
[exec] | <["#",
[exec] | "# There is insufficient memory for the Java Runtime Environment to continue.",
[exec] | "# Native memory allocation (mmap) failed to map 262144 bytes for committing reserved memory.",
[exec] | "# An error report file with more information is saved as:",
[exec] | "# /home/travis/build/jruby/jruby/hs_err_pid14318.log"]>.


  1. A secret byte you want to read is stored at inaccessible memory location priv_mem.
  2. The sender triggers an access exception by attempting to read priv_mem.
  3. Due to CPU optimization (out-of-order execution), the load of secret from priv_mem and the use of its value in (4) and (5) below may execute before the exception is triggered.
  4. Calculate an offset into a known array probe by multiplying secret by the width of a cache line. This guarantees each of those 256 possible offsets will cache separately.
  5. Load probe[offset], which causes the CPU to cache exactly one chunk of of our array, populating one cache line.
  6. The exception finally triggers, clearing the modified registers...but cached data is not excised.
  7. Iterate over all 256 offsets into probe to find out which one loads fast. You've determined the value of secret.
View .asm
java/lang/invoke/LambdaForm$MH.identity_L [0x000000011418f040, 0x000000011418f388] 840 bytes
[Entry Point]
[Verified Entry Point]
# {method} {0x00000001306a0e98} 'identity_L' '(Ljava/lang/Object;)V' in 'java/lang/invoke/LambdaForm$MH'
# parm0: rsi:rsi = 'java/lang/Object'
# [sp+0xd0] (sp of caller)
0x000000011418f040: mov DWORD PTR [rsp-0x14000],eax
0x000000011418f047: push rbp
0x000000011418f048: sub rsp,0xc0
View blah.asm
Compiled method (c1) 18446 2640 2 java.lang.invoke.LambdaForm$MH/1430710100::identity_L (89 bytes)
total in heap [0x0000000114fad090,0x0000000114fae118] = 4232
relocation [0x0000000114fad200,0x0000000114fad2b8] = 184
main code [0x0000000114fad2c0,0x0000000114fad800] = 1344
stub code [0x0000000114fad800,0x0000000114fad8e8] = 232
oops [0x0000000114fad8e8,0x0000000114fad960] = 120
metadata [0x0000000114fad960,0x0000000114fad9d8] = 120
scopes data [0x0000000114fad9d8,0x0000000114fadd80] = 936
scopes pcs [0x0000000114fadd80,0x0000000114fae090] = 784
dependencies [0x0000000114fae090,0x0000000114fae098] = 8