jsconf.eu 2011
jsconf.eu 2011
(almost) 100% invokedynamic ecmascript impl
@qmx | http://qmx.me
!SLIDE
whoami?
!SLIDE
opensource freak
!SLIDE
contributor @
!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  !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  !SLIDE ## virtual  !SLIDE ## interface  !SLIDE ## interface  !SLIDE ## interface  !SLIDE ## interface  !SLIDE # New stuff on JDK7 !SLIDE # dynamic invocation !SLIDE ## dynamic  !SLIDE ## dynamic  !SLIDE ## dynamic  !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  !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  !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? [](http://dynjs.org) ### [http://dynjs.org](http://dynjs.org) !SLIDE # thank you