jsconf.eu 2011

dynjs

(almost) 100% invokedynamic ecmascript impl

@qmx | http://qmx.me

!SLIDE

whoami?

!SLIDE

opensource freak

opensource !SLIDE

contributor @

JRuby !SLIDE

why?

!SLIDE

geek appeal?

!SLIDE

fun \o/

!SLIDE

guess what?

Author: norris%netscape.com <norris%netscape.com>
Date:   Mon Apr 19 20:43:07 1999 +0000

    Publish Rhino as open source. !SLIDE # 1999 !SLIDE # Rhino !SLIDE # Java 2 !SLIDE # Rhino devs <br/>===<br/> miracle guys !SLIDE # thank you, Rhino! !SLIDE # Java 7 !SLIDE # cool stuff !SLIDE # dynamic language support !SLIDE # lack of tools at that time !SLIDE # pretty steep learning curve !SLIDE # the challenge !SLIDE # why not? !SLIDE ## challenge accepted ![challenge accepted](/talks/2011/jsconf.eu/img/challenge-accepted.jpg) !SLIDE # 3 premises !SLIDE # 1 !SLIDE # fun \o/ !SLIDE # 2 !SLIDE # learning something new !SLIDE # 3 !SLIDE # beautiful code !SLIDE # compilers? !SLIDE # yes, we can! !SLIDE # a friendlier compiler? !SLIDE # why not? !SLIDE # JVM !SLIDE # finely-crafted over many years !SLIDE # the one-language show !SLIDE # invocation strategies !SLIDE ## static ![invokestatic](/talks/img/invokestatic.png) !SLIDE ## virtual ![invokevirtual](/talks/img/invokevirtual.png) !SLIDE ## interface ![invokeinterface1](/talks/img/invokeinterface1.png) !SLIDE ## interface ![invokeinterface2](/talks/img/invokeinterface2.png) !SLIDE ## interface ![invokeinterface3](/talks/img/invokeinterface3.png) !SLIDE ## interface ![invokeinterface5](/talks/img/invokeinterface5.png) !SLIDE # New stuff on JDK7 !SLIDE # dynamic invocation !SLIDE ## dynamic ![invokedynamic1](/talks/img/invokedynamic1.png) !SLIDE ## dynamic ![invokedynamic2](/talks/img/invokedynamic2.png) !SLIDE ## dynamic ![invokedynamic3](/talks/img/invokedynamic3.png) !SLIDE # thats huge !SLIDE # VM-only !SLIDE ## bytecode # 0xCAFEBABE !SLIDE ## bytecode
0000000: cafe babe 0000 0033 00b7 0a00 1900 6909  .......3......i.
0000010: 006a 006b 0a00 6c00 6d0a 0023 006e 0a00  .j.k..l.m..#.n.. !SLIDE # beautiful? !SLIDE # abstraction !SLIDE # Internal DSLs !SLIDE # [jitescript](https://github.com/qmx/jitescript) !SLIDE ## javascript is readable
(function(){
    print("hello, jsconf.eu");
})(); !SLIDE ## bytecode (raw)
0000000: cafe babe 0000 0032 0018 0100 0b68 656c
0000010: 6c6f 5f77 6f72 6c64 0700 0101 0010 6a61
0000020: 7661 2f6c 616e 672f 4f62 6a65 6374 0700
0000030: 0301 000e 6865 6c6c 6f5f 776f 726c 642e
0000040: 6273 0100 046d 6169 6e01 0016 285b 4c6a
....
00000f0: 1200 130a 0011 0014 0100 0443 6f64 6501
0000100: 000a 536f 7572 6365 4669 6c65 0021 0002
0000110: 0004 0000 0000 0001 0009 0006 0007 0001
0000120: 0016 0000 0016 0002 0001 0000 000a 1209
0000130: b200 0f5f b600 15b1 0000 0000 0001 0017
0000140: 0000 0002 0005                          !SLIDE ## bytecode (disassembled)
LDC #9
GETSTATIC #15
SWAP
INVOKEVIRTUAL #21
RETURN !SLIDE # much better !SLIDE ## jitescript
CodeBlock.newCodeBlock()
    .ldc("helloWorld")
    .getstatic(p(System.class), "out", ci(PrintStream.class))
    .swap()
    .invokevirtual(p(PrintStream.class),
        "println",
        sig(void.class, Object.class))
    .voidreturn(); !SLIDE # waaay better  !SLIDE # real world !SLIDE # compiler !SLIDE # var x = 1; !SLIDE ## var x = 1; * define decimal literal '1' * retrieve current scope (function or global) * assign it to the 'x' slot on current scope !SLIDE ## defining the literal
.aload(1)
.ldc(value)
.invokevirtual(p(DynThreadContext.class), "defineOctalLiteral", sig(DynPrimitiveNumber.class, String.class)); !SLIDE ## retrieving current scope
.aload(0)
.aload(2)
.invokedynamic("dynjs:scope:lookup", sig(Scope.class, Object.class, Scope.class), RT.BOOTSTRAP, RT.BOOTSTRAP_ARGS) !SLIDE ## storing the primitive on scope
.ldc(id)
.aload(3)
.invokedynamic("dynjs:scope:define", sig(void.class, Scope.class, String.class, DynAtom.class), RT.BOOTSTRAP, RT.BOOTSTRAP_ARGS); !SLIDE # thank you! !SLIDE # not yet :) !SLIDE # where do this calls go? !SLIDE # dynalink !SLIDE # dynamic linking framework !SLIDE ## provides the ? on the picture ![invokedynamic2](/talks/img/invokedynamic2.png) !SLIDE # Bootstrap Method (BSM) !SLIDE # built-in type conversion !SLIDE # I have a primitive String !SLIDE # I want a String object !SLIDE # autoboxing / unboxing !SLIDE ## type promotion / conversion
convertToType(Class<?> sourceType, Class<?> targetType) {
    // compare classes and use converter methods
    ...
} !SLIDE # monomorphic inliner !SLIDE # WTF? !SLIDE # js is dynamic !SLIDE ## let's remember how to find C ![invokedynamic3](/talks/img/invokedynamic3.png) !SLIDE ## we issue a dynamic instruction
.invokedynamic("dynjs:scope:define",
    sig(void.class, String.class, DynAtom.class),
    RT.BOOTSTRAP, RT.BOOTSTRAP_ARGS); !SLIDE ## and receive the call at the linker
String instruction = callSiteDescriptor.getName();
if (name.startsWith("dynjs:scope")) {
    // delegate to scope handling code
    ... !SLIDE # give "pointers" to the JVM !SLIDE ## remember?
int (*func)(int a, float b); !SLIDE # MethodHandles !SLIDE # find the target !SLIDE ## our target
Scope#define(name, anything); !SLIDE ## get the "pointer"
MethodHandles.lookup().findVirtual(Scope.class,
    "define",
    MethodHandles.methodType(void.class, String.class, DynAtom.class)); !SLIDE # pass the "pointer" !SLIDE # let JVM do the hard work for us !SLIDE # Meta Object Protocol !SLIDE # interactions between jvm languages !SLIDE # potentially inlinable !SLIDE # when? !SLIDE # releasing now! ### (when the talk ends) !SLIDE # opensource, as it should be (ASL2) !SLIDE # current status !SLIDE ## current status * ES3 grammar (waiting ES6 to settle) * partial AOT compiler * autoboxing/unboxing primitives * prototype chain !SLIDE # closing !SLIDE # \o/ !SLIDE # learn something new !SLIDE # use good abstractions !SLIDE # KISS !SLIDE # and why not, beautiful too? !SLIDE # one more thing... !SLIDE # demo !SLIDE # that's all folks !SLIDE ## questions? [![dynjs](/talks/2011/jsconf.eu/img/dynjs.png)](http://dynjs.org) ### [http://dynjs.org](http://dynjs.org) !SLIDE # thank you