26
1

Javaforum indy

  • Upload
    squeed

  • View
    752

  • Download
    4

Embed Size (px)

DESCRIPTION

Vilka problem har man historiskt sett haft med att kompilera dynamiska språk till Java bytekod? Vad fanns för work-arounds? Vilka andra roliga saker kan man göra själv med Invokedynamic?Även om du bara har en vag bild på vad en bytekod överhuvudtaget är och varför du skall bry dig om en ny sådan så är det här en presentation som kommer att fördjupa din förståelse av Java på riktigt låg nivå.

Citation preview

Page 1: Javaforum indy

1

Page 2: Javaforum indy

2

The following is intended to outline our general

product direction. It is intended for information

purposes only, and may not be incorporated into

any contract. It is not a commitment to deliver any

material, code, or functionality, and should not

be relied upon in making purchasing decisions.

The development, release, and timing of any

features or functionality described for Oracle’s

products remains at the sole discretion of Oracle.

Page 3: Javaforum indy

<Insert Picture Here>

invokedynamic på 20 minuter

Joel Borggrén-Franck <[email protected]>

Java Platform Group

Page 4: Javaforum indy

4

<Insert Picture Here>

Intro till JSR-292: invokedynamic,

MethodHandle och dynamiskt typade

språk på JVM:en

• Varför JSR-292/invokedynamic?

• Vad erbjuder JSR-292?

• Dynamiskt typade exempel och jämförelser med vad

JVM:en kan göra av Java

Page 5: Javaforum indy

5

Warning!

The following slides may contain traces of:

- x86 assembler

- Ruby, and

- Common Lisp

Page 6: Javaforum indy

6

• Det finns en mängd intressanta programmeringsspråk

• JVM:en är långt mycket mer avancerad än andra

VM:ar/runtimes

• Java är inte allas favoritspråk

• Naturligvis vill man köra alla nya spännande språk på

JVM:en

Page 7: Javaforum indy

7

• Dynamiskt typade språk:

– Modifierar klasser vid körtid

– Alternativt, saknar klasser och lägger till properties i körtid

class ExampleClass

def exampleMethod

5

end

end

exampleObject.class.send(:define_method,

"aNewMethod") do

10

end

Page 8: Javaforum indy

8

• Motsvarigheten i Java finns egentligen inte

– Den naiva implementationen blir istället en Map<String,

TargetMethodObject>

• Mer eller mindre avancerade sätt att optimera

ovanstående

– JRuby har sina fält i en Object[] och en Map<String, Integer>

där du slår upp vilket index du ska använda in i arrayen

Page 9: Javaforum indy

9

• Dynamiskt typade språk:

– har ofta inkompatibla sätt att definera/anropa metoder

(defun foo

(var...

&optional (var initform svar)...

&rest var

&key ((keyword var) initform svar)...

&aux (var initform)...))

Page 10: Javaforum indy

10

• Man kan arbeta runt problemen

• Ett av de få verktyg man har är

klassladdning/klassurladdning

– leder till permgen-problem på HotSpot

• Det tar tid att implementera

– om man vill få det att gå fort

Page 11: Javaforum indy

11

Invokedynamic, en språkimplementatörs räddare i

nöden

• Invokedynamic är en brygga mellan

språkimplementatören och JVM:en

• Invokedynamic består av 3 delar

– en ny bytekod som markerar ett dynamiskt CallSite

– ett protokoll/API för livscykeln av dynamiska CallSites

– MethodHandle

• funktionspekare på sterodier

Page 12: Javaforum indy

12

• Första gången JVM:en exekverar en invokedynamic

bytekod kommer den:

– Hitta och köra den bootstrapmetod som skaparen av

klassfilen angett

• resulterar i ett CallSite-objekt som har ett MethodHandle

som target

– Länka CallSite-objektet

• Ovanstående görs bara en gång

• Efterföljande körningar av samma invokedynamic

kommer helt skippa bootstrap och länkning

• == Snabbt!!

Page 13: Javaforum indy

13

aload 0x25

dup

invokedynamic 0x22 0x23

getfield 0xba 0xdd

Bootstrap methodCallSite object

target MethodHandle

Page 14: Javaforum indy

14

• En invokedynamic kommer alltid att motsvaras av

samma CallSite

• Ett CallSite kan ändra target till att peka på en ny

MethodHandle

• Om du kan uttrycka ditt språks semantik som CallSite

+ en utbytbar MethodHandle kommer det gå fort!

Page 15: Javaforum indy

15

MethodHandles is the kitchen sink of the JVM

- Dan Heidinga, JVM Lang 2010

• MethodHandle är i grund och botten en

funktionspekare

• Pekas normalt ut som target i en CallSite

• Kan också köras genom ett Java-API

• Hjälpklassen ”MethodHandles” har metoder för att

– Wrappa MethodHandle i andra MethodHandle

– Transformera argumenten på ett MethodHandle

– Köra kod runt en MethodHandle

Page 16: Javaforum indy

16

• MethodHandle kan också peka ut fält

• Användbart för lat initialisering av en gigantisk array

– Wrappa arrayaccessen i ett MethodHandle som transparent

initialiserar den

– Generera bytecode som kör MethodHandlet för den

wrappade arrayen istället för den vanliga ”aref”-bytekoden

Page 17: Javaforum indy

17

• MethodHandle kan också transformera argument

– asCollector(…)

– asFixedArity(…)

– asSpreader(…)

– …

• Och byta returtyp

– asType(newType)

Page 18: Javaforum indy

18

• MethodHandles.Lookup har också stöd för att

reflektera över typer

• Användbart för det mesta man vill göra med reflection

• Fast snabbt

Page 19: Javaforum indy

19

• JVM:en vet hur den skall optimera MethodHandle

• Igen: Kan du bara uttrycka ditt språks semantik som

CallSite + en utbytbar MethodHandle kommer det gå

fort!

Page 20: Javaforum indy

20

• Ett call i Java kommer kompileras till:

– Slå upp objektets vtable (en del av klassen)

– Kör koden som pekas ut på en vid just-in-time-kompilering

känd plats i vtablen

• 2 instruktioner + ev. några cachemissar

• == Snabbt!

moveq r12, [rdi + 0x128] ;get vtable for ”this”

callq [r12+0x12] ;call 3:rd method

Exempel: ett vanligt metodanrop i Java

Page 21: Javaforum indy

21

• Motsvarande logik för ett dynamiskt typat språk utan

invokedynamic:

String methodName;

CallTarget t;

for(RubyClazz clz : o.getClzAndSuperClzs()) {

if ((t = clz.hasMethod(methodName)) != null)

break;

}

if (t == null) throw new NoSuchRubyMethod();

Exempel: ett metodanrop i fiktiv Ruby på JVM:en

Page 22: Javaforum indy

22

• Låt bootstrapmetoden returnera ett MethodHandle:MethodHandle lastCalled;

int rubyClzId;

if (receiver.currentRubyClzId == rubyClzId) {

return lastCalled.invoke(args …);

} else {

missCount++;

MethodHandle t = doFulLookup(mName, args…);

if (missCount > MISS_LIMIT) {

relinkThisCallSite(t);

}

return t.invoke();

}

Exempel: med invokedynamic …

Page 23: Javaforum indy

23

• Bootstrapmetoden får leta reda på den

implementerande ruby-metoden

• Wrappa i ett MethodHandle som

– Testar om det är samma implementerande ruby-klass

– Testar om det är samma version av ruby-klassen

• Så länge det är samma implementerande klass

kommer JVM:en kunna kompilera till en handfull

instruktioner

• Det är nästan alltid samma implementerande klass!

• Om det inte är samma klass kan din ruby-VM begära

omlänkning via CallSite-objektet!

Exempel: med invokedynamic …

Page 24: Javaforum indy

24

• == Snabbt!!

Page 25: Javaforum indy

25

• Invokedynamic hjälper dig som språkimplementatör:

– Kommunicera ditt språks speciella semantik till VM:en

– Återanvända VM:ens maskineri för

• Optimeringar

• Deoptimeringar

– Hjälper dig att transformera semantiken i ditt språks

objektsystem till något som JVM:en kan använda

Page 26: Javaforum indy

26