invokedynamic in 45 minutes

63
invokedynamic IN 45 MINUTES!!! Wednesday, February 6, 13

Upload: charles-nutter

Post on 10-May-2015

6.304 views

Category:

Technology


0 download

DESCRIPTION

Talk on invokedynamic delivered at Jfokus 2013.

TRANSCRIPT

Page 1: Invokedynamic in 45 Minutes

invokedynamicIN 45 MINUTES!!!

Wednesday, February 6, 13

Page 2: Invokedynamic in 45 Minutes

Me

• Charles Oliver Nutter

[email protected], @headius

• blog.headius.com

• JRuby Guy at Sun, Engine Yard, Red Hat

• JVM enthusiast, educator, contributor

• Earliest adopter of invokedynamic

Wednesday, February 6, 13

Page 3: Invokedynamic in 45 Minutes

27 April, 2011

Wednesday, February 6, 13

Page 4: Invokedynamic in 45 Minutes

History

• JVM authors mentioned non-Java languages

• Language authors have targeted JVM

• Hundreds of JVM languages now

• But JVM was a mismatch for many of them

• Usually required tricks that defeated JVM optimizations

• Or required features JDK could not provide

Wednesday, February 6, 13

Page 5: Invokedynamic in 45 Minutes

• Early impls of Python (JPython), JS (Rhino) and many others

• No official backing by Sun until 2006

• JRuby team hired

• JSR-292 “invokedynamic” rebooted in 2007

• Java 7 shipped invokedynamic in 2011

JVM LanguagesThrough the Years

Wednesday, February 6, 13

Page 6: Invokedynamic in 45 Minutes

What isinvokedynamic

Wednesday, February 6, 13

Page 7: Invokedynamic in 45 Minutes

New Bytecode?

Well, yes...but what does that mean?And is that all?

Wednesday, February 6, 13

Page 8: Invokedynamic in 45 Minutes

Wednesday, February 6, 13

Page 9: Invokedynamic in 45 Minutes

New form of invocation?

That’s one use, but there are many others

Wednesday, February 6, 13

Page 10: Invokedynamic in 45 Minutes

Wednesday, February 6, 13

Page 11: Invokedynamic in 45 Minutes

Only for Dynamic Languages?

Dynamic dispatch is a common use,but there are many others

Wednesday, February 6, 13

Page 12: Invokedynamic in 45 Minutes

Wednesday, February 6, 13

Page 13: Invokedynamic in 45 Minutes

A User-definable Bytecode

You decide how the JVM implements it

Wednesday, February 6, 13

Page 14: Invokedynamic in 45 Minutes

+Method Pointers

and AdaptersFaster than reflection, with user-definedargument, flow, and exception handling

A User-definable Bytecode

You decide how the JVM implements it

Wednesday, February 6, 13

Page 15: Invokedynamic in 45 Minutes

Wednesday, February 6, 13

Page 16: Invokedynamic in 45 Minutes

invokedynamic

Wednesday, February 6, 13

Page 17: Invokedynamic in 45 Minutes

invokedynamicuser-def’d bytecode

Wednesday, February 6, 13

Page 18: Invokedynamic in 45 Minutes

invokedynamicuser-def’d bytecode method pointers

Wednesday, February 6, 13

Page 19: Invokedynamic in 45 Minutes

invokedynamicuser-def’d bytecodebytecode + bootstrap method pointersMethodHandles

Wednesday, February 6, 13

Page 20: Invokedynamic in 45 Minutes

https://github.com/headius/indy_deep_dive

Wednesday, February 6, 13

Page 21: Invokedynamic in 45 Minutes

MethodHandles

Wednesday, February 6, 13

Page 22: Invokedynamic in 45 Minutes

Method Handles

• Function/field/array pointers

• Argument manipulation

• Flow control

• Optimizable by the JVM

• This is very important

Wednesday, February 6, 13

Page 23: Invokedynamic in 45 Minutes

java.lang.invoke

• MethodHandle

• An invokable target + adaptations

• MethodType

• Representation of args + return type

• MethodHandles

• Utilities for acquiring, adapting handles

Wednesday, February 6, 13

Page 24: Invokedynamic in 45 Minutes

MethodHandles.Lookup

• Method pointers

• findStatic, findVirtual,findSpecial, findConstructor

• Field pointers

• findGetter, findSetter,findStaticGetter, findStaticSetter

Wednesday, February 6, 13

Page 25: Invokedynamic in 45 Minutes

Why Casting?

• invoke() is “signature polymorphic”

• Call-side types define signature

• At compile time

• Signature must match MethodHandle type

• Or use invokeWithArguments

value1 = (String)mh1.invoke("java.home");mh2.invoke((Object)"Hello, world");

Wednesday, February 6, 13

Page 26: Invokedynamic in 45 Minutes

Adapters

• Methods on j.l.i.MethodHandles

• Argument manipulation, modification

• Flow control and exception handling

• Similar to writing your own command-pattern utility objects

Wednesday, February 6, 13

Page 27: Invokedynamic in 45 Minutes

Argument Juggling

• insert, drop, permute

• filter, fold, cast

• splat (varargs), spread (unbox varargs)

Wednesday, February 6, 13

Page 28: Invokedynamic in 45 Minutes

Flow Control

• guardWithTest: boolean branch

• condition, true path, false path

• Combination of three handles

• SwitchPoint: on/off branch

• true and false paths

• Once off, always off

Wednesday, February 6, 13

Page 29: Invokedynamic in 45 Minutes

Exception Handling

• catchException

• body, exception type, handler

• throwException

• Throws Throwable in argument 0

Wednesday, February 6, 13

Page 30: Invokedynamic in 45 Minutes

bytecode

Wednesday, February 6, 13

Page 31: Invokedynamic in 45 Minutes

Goals of JSR 292

• A user-definable bytecode

• Full freedom to define VM behavior

• Fast method pointers + adapters

• Optimizable like normal Java code

• Avoid future modifications

Wednesday, February 6, 13

Page 32: Invokedynamic in 45 Minutes

JVM 101

Wednesday, February 6, 13

Page 33: Invokedynamic in 45 Minutes

JVM 101200 opcodes

Wednesday, February 6, 13

Page 34: Invokedynamic in 45 Minutes

JVM 101200 opcodes

Ten (or 16) “endpoints”

Wednesday, February 6, 13

Page 35: Invokedynamic in 45 Minutes

JVM 101200 opcodes

Invocationinvokevirtual

invokeinterfaceinvokestaticinvokespecial

Ten (or 16) “endpoints”

Wednesday, February 6, 13

Page 36: Invokedynamic in 45 Minutes

JVM 101200 opcodes

Invocationinvokevirtual

invokeinterfaceinvokestaticinvokespecial

Field Accessgetfieldsetfieldgetstaticsetstatic

Ten (or 16) “endpoints”

Wednesday, February 6, 13

Page 37: Invokedynamic in 45 Minutes

JVM 101200 opcodes

Invocationinvokevirtual

invokeinterfaceinvokestaticinvokespecial

Field Accessgetfieldsetfieldgetstaticsetstatic

Array Access*aload*astore

b,s,c,i,l,d,f,a

Ten (or 16) “endpoints”

Wednesday, February 6, 13

Page 38: Invokedynamic in 45 Minutes

JVM 101200 opcodes

Invocationinvokevirtual

invokeinterfaceinvokestaticinvokespecial

Field Accessgetfieldsetfieldgetstaticsetstatic

Array Access*aload*astore

b,s,c,i,l,d,f,a

Ten (or 16) “endpoints”

All Java code revolves around these endpoints

Remaining ops are stack, local vars, flow control,allocation, and math/boolean/bit operations

Wednesday, February 6, 13

Page 39: Invokedynamic in 45 Minutes

The Problem

• JVM spec (pre-7) defined 200 opcodes

• All bytecode lives within these 200

• What if your use case does not fit?

• Dynamic language/dispatch

• Lazy initialization

• Non-Java features

Wednesday, February 6, 13

Page 40: Invokedynamic in 45 Minutes

// StaticSystem.currentTimeMillis()Math.log(1.0) // Virtual"hello".toUpperCase()System.out.println() // InterfacemyList.add("happy happy")myRunnable.run() // Specialnew ArrayList()super.equals(other)

Wednesday, February 6, 13

Page 41: Invokedynamic in 45 Minutes

// Staticinvokestatic java/lang/System.currentTimeMillis:()Jinvokestatic java/lang/Math.log:(D)D

// Virtualinvokevirtual java/lang/String.toUpperCase:()Ljava/lang/String;invokevirtual java/io/PrintStream.println:()V

// Interfaceinvokeinterface java/util/List.add:(Ljava/lang/Object;)Zinvokeinterface java/lang/Runnable.add:()V

// Specialinvokespecial java/util/ArrayList.<init>:()Vinvokespecial java/lang/Object.equals:(java/lang/Object)Z

invokestatic

invokevirtual

invokeinterface

invokespecial

Wednesday, February 6, 13

Page 42: Invokedynamic in 45 Minutes

invokestatic

invokevirtual

invokeinterface

invokespecial

Wednesday, February 6, 13

Page 43: Invokedynamic in 45 Minutes

invokestatic1. Confirm arguments are of correct type2. Look up method on Java class3. Cache method4. Invoke method

invokevirtual1. Confirm object is of correct type2. Confirm arguments are of correct type3. Look up method on Java class4. Cache method5. Invoke method

invokeinterface1. Confirm object’s type implements interface2. Confirm arguments are of correct type3. Look up method on Java class4. Cache method5. Invoke method

invokespecial1. Confirm object is of correct type2. Confirm arguments are of correct type3. Confirm target method is visible4. Look up method on Java class5. Cache method6. Invoke method

invokestaticinvokevirtual

invokeinterface invokespecial

Wednesday, February 6, 13

Page 44: Invokedynamic in 45 Minutes

invokestatic1. Confirm arguments are of correct type2. Look up method on Java class3. Cache method4. Invoke method

invokevirtual1. Confirm object is of correct type2. Confirm arguments are of correct type3. Look up method on Java class4. Cache method5. Invoke method

invokeinterface1. Confirm object’s type implements interface2. Confirm arguments are of correct type3. Look up method on Java class4. Cache method5. Invoke method

invokespecial1. Confirm object is of correct type2. Confirm arguments are of correct type3. Confirm target method is visible4. Look up method on Java class5. Cache method6. Invoke method

invokestaticinvokevirtual

invokeinterface invokespecial

invokedynamic1. Call bootstrap handle (your code)2. Bootstrap prepares CallSite + MethodHandle3. MethodHandle invoked now and future (until CallSite changes)

Wednesday, February 6, 13

Page 45: Invokedynamic in 45 Minutes

Wednesday, February 6, 13

Page 46: Invokedynamic in 45 Minutes

invokedynamic bytecode

Wednesday, February 6, 13

Page 47: Invokedynamic in 45 Minutes

invokedynamic bytecode

bootstrap method

Wednesday, February 6, 13

Page 48: Invokedynamic in 45 Minutes

method handles

invokedynamic bytecode

bootstrap method

Wednesday, February 6, 13

Page 49: Invokedynamic in 45 Minutes

method handles

invokedynamic bytecode

bootstrap method

target method

Wednesday, February 6, 13

Page 50: Invokedynamic in 45 Minutes

method handles

invokedynamic bytecode

bootstrap method

target method

Wednesday, February 6, 13

Page 51: Invokedynamic in 45 Minutes

method handles

invokedynamic bytecode

bootstrap method

target method

Wednesday, February 6, 13

Page 52: Invokedynamic in 45 Minutes

All Together Now...

Wednesday, February 6, 13

Page 53: Invokedynamic in 45 Minutes

Tools

• ObjectWeb's ASM library

• De facto standard bytecode library

• Jitescript

• DSL/fluent wrapper around ASM

• InvokeBinder

• DSL/fluent API for building MH chains

Wednesday, February 6, 13

Page 54: Invokedynamic in 45 Minutes

#1: Trivial Binding

• Simple binding of a method

• j.l.i.ConstantCallSite

• Method returns String

• Print out String

Wednesday, February 6, 13

Page 55: Invokedynamic in 45 Minutes

#2: Modifying the Site

• Toggle between two targets each call

• j.l.i.MutableCallSite

• Call site sent into methods

• ...so they can modify it

• Trivial example of late binding

• InvokeBinder usage

Wednesday, February 6, 13

Page 56: Invokedynamic in 45 Minutes

#3: Dynamic Dispatch

• Target method not known at compile time

• Dynamically look up after bootstrap

• Rebind call site to proper method

Wednesday, February 6, 13

Page 57: Invokedynamic in 45 Minutes

StupidScript

• push <string>: push string on stack

• send <number>: call function with n args

• One arg call: ["print", "Hello, world"]

• def <name> '\n' <op1> [ '\n' <op2> ...] '\n' end

• define function with given ops

• One builtin: print (System.out.println)

Wednesday, February 6, 13

Page 58: Invokedynamic in 45 Minutes

StupidScript

• push <string>: push string on stack

• send <number>: call function with n args

• def <name> '\n' <op1> [ '\n' <op2> ...] '\n' end

• One builtin: print (System.out.println)

Wednesday, February 6, 13

Page 59: Invokedynamic in 45 Minutes

Implementation

• Simple parser generates AST

• Compiler walks AST, emits .class

• Top level code goes into run() method

• defs create additional methods

Wednesday, February 6, 13

Page 60: Invokedynamic in 45 Minutes

Hello, world!

push Hello, world!push printsend 1

Wednesday, February 6, 13

Page 61: Invokedynamic in 45 Minutes

Define Function

def hellopush printpush Hello, world!send 1end

Wednesday, February 6, 13

Page 62: Invokedynamic in 45 Minutes

Call Function

push hellosend 0

Wednesday, February 6, 13

Page 63: Invokedynamic in 45 Minutes

More Information

• My blog: http://blog.headius.com

• Follow me: @headius

• Code on Github

• https://github.com/headius/indy_deep_dive

• Slides posted online

Wednesday, February 6, 13