state of java.lang.invoke implementation in...

Post on 03-Oct-2020

1 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

1 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

State of java.lang.invoke Implementation in OpenJDK

Vladimir Ivanov HotSpot JVM Compile r Oracle Corp. JVM Language Summit 2015

2 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Safe Harbor Statement

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.

3 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

2005

JSR 292 Support for Dynamically Typed Languages in the JVM

Method Handle API (Early Draft Review)

Java 7 Release

JSR 292 Expert Group

formed

Initial design sketch Expert Group reboot

API refinement (e.g., CONSTANT_MethodHandle)

API refinement (e.g., BootstrapMethods)

2006 2007 2008 2009 2010 2011

4 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Method Handles in JDK 7 GA § Good

–  Flexible and powerful. –  MH graphs are aggressively inlined and optimized.

§ Not-so-good –  “Performance cliff” when inlining does not occur –  MH.invoke() is slow –  NoClassDefFoundError in large applications

§ Ugly –  No general fast path for compiled code –  JVM is entangled in MH operations

5 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Quest for a Better IR

§ Root problem: MH chains are wrong IR for the JVM

§ Lambda Forms for the rescue –  Mostly-native moves into Java –  Decouple representation decisions from the JVM –  Meshes better with the JVM execution engine

§  translates to bytecode §  Interprets and/or compiles

–  Erases types, avoiding NCDFE issues

2012: Lambda Forms in 7u40

6 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

MHs vs LFs

MH

LF

n:1 .form

public

internal “ [A lambda form is a] … symbolic, non-executable form of a method handle's invocation semantics.”

“A method handle is a typed, directly executable reference to an underlying method, constructor, field, or similar low-level operation, with optional transformations of arguments or return values.”

javadoc

7 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

The Grand Plan MH

CS MT

public n:1

.type

.target

MH = MethodHandle MT = MethodType CS = CallSite

n:1

JDK

8 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

The Grand Plan MH

CS

LF

MN

MT

MTF

DMH

n:1 .form

n:1 .vmentry

public

internal

n:1

.type

.target

MH = MethodHandle MT = MethodType CS = CallSite LF = LambdaForm DMH = DirectMethodHandle BMH = BoundMethodHandle MN = MemberName MTF = MethodTypeForm

n:1

n:1

VM anon classes

BMH extends

JDK

9 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

The Grand Plan MH

CS

LF

MN

JVM

MT

MTF

DMH

n:1 .form

n:1 .vmentry

n:1 .vmtarget

public

internal

n:1

.type

.target

MH = MethodHandle MT = MethodType CS = CallSite LF = LambdaForm DMH = DirectMethodHandle BMH = BoundMethodHandle MN = MemberName MTF = MethodTypeForm MHN = MethodHandleNative

n:1

n:1

JVM_Method

MH::linkTo* MH::invokeBasic

native stubs linkCallSite linkMethod

etc

Upcalls

MH::init/resolve setCallSiteTarget*

etc

VM calls

MHN

resolved_references[]

appendix

VM anon classes

BMH extends

methodHandles*.cpp

JDK

10 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Lambda Form

putObjectFieldCast_000=Lambda(a0:L,a1:L,a2:L)=>{ t3:J=DMH.fieldOffset (a0:L); t4:L=DMH.checkBase (a1:L); t5:L=DMH.checkCast (a0:L,a2:L); t6:V=Unsafe.putObject((Unsafe@...),t4:L,t3:J,t5:L);void}

Example: putfield / Lookup.findSetter

11 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Lambda Form

putObjectFieldCast_000=Lambda(a0:L,a1:L,a2:L)=>{ t3:J=DMH.fieldOffset (a0:L); t4:L=DMH.checkBase (a1:L); t5:L=DMH.checkCast (a0:L,a2:L); t6:V=Unsafe.putObject((Unsafe@...),t4:L,t3:J,t5:L);void} § Basic value type is one of { ref, int, long, float, double } + void

–  represented as signature letters "LIJFD” + “V”

Example: putfield / Lookup.findSetter

12 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Lambda Form

putObjectFieldCast_000=Lambda(a0:L,a1:L,a2:L)=>{ t3:J=DMH.fieldOffset (a0:L); t4:L=DMH.checkBase (a1:L); t5:L=DMH.checkCast (a0:L,a2:L); t6:V=Unsafe.putObject((Unsafe@...),t4:L,t3:J,t5:L);void}

Example: putfield / Lookup.findSetter LF.names[7]

Name.function Name.arguments[]

Name.type Name.index

LF.debugName

LF.result = -1

LF.arity = 3

13 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Lambda Form

putObjectFieldCast_000=Lambda(a0:L,a1:L,a2:L)=>{ t3:J=DMH.fieldOffset (a0:L); t4:L=DMH.checkBase (a1:L); t5:L=DMH.checkCast (a0:L,a2:L); t6:V=Unsafe.putObject((Unsafe@...),t4:L,t3:J,t5:L);void}

Execution

14 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Lambda Form

Entry point: LambdaForm::vmentry Can point to:

–  LambdaForm Interpreter –  compiled bytecode

Execution

.form

MH

LF

MN

JVM_Method

.vmentry

.vmtarget

.from_interpreted .from_compiled

interpreter compiled code

MH

LF

class (VM anon)

?

15 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Lambda Form Interpreter

16 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Lambda Form Compiled Form static void putObjectFieldCast_000( Object, Object, Object ); 0: aload_0 1: invokestatic #16 // DMH.fieldOffset:... 4: lstore_3 5: aload_1 6: invokestatic #20 // DMH.checkBase:... 9: astore 5 11: aload_0 12: aload_2 13: invokestatic #24 // DMH.checkCast:... 16: astore 6 18: ldc #26 // <<sun.misc.Unsafe@3830f1c0>> 20: checkcast #28 // class sun/misc/Unsafe 23: aload 5 25: lload_3 26: aload 6 28: invokevirtual #32 // Unsafe.putObject:(Object;Object;)V 31: return

RuntimeVisibleAnnotations:

LambdaForm$Hidden, LambdaForm$Compiled, ForceInline

t3:J

t4:L

t5:L

t6:V

a0:L a1:L a2:L putObjectFieldCast_000=Lambda(a0:L,a1:L,a2:L)=>{

t3:J=DMH.fieldOffset (a0:L);

t4:L=DMH.checkBase (a1:L);

t5:L=DMH.checkCast (a0:L,a2:L);

t6:V=Unsafe.putObject((Unsafe@...),t4:L,t3:J,t5:L);void}

17 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

VM Anonymous Classes Constant Pool Patching static void putObjectFieldCast_000(…); ... 18: ldc #26

// String “CONSTANT_PLACEHOLDER_0“ 20: checkcast #28

// class sun/misc/Unsafe 23: aload 5 25: lload_3 26: aload 6 28: invokevirtual #32 // Unsafe.putObject(...) 31: return

t6:V

putObjectFieldCast_000=Lambda(a0:L,a1:L,a2:L)=>{

t3:J=DMH.fieldOffset (a0:L);

t4:L=DMH.checkBase (a1:L);

t5:L=DMH.checkCast (a0:L,a2:L);

t6:V=Unsafe.putObject((Unsafe@...),t4:L,t3:J,t5:L);void}

ConstantPool

#26 = Utf8 “...”

...

resolved_references[] { ..., unsafeObj , ...}

Unsafe.defineAnonymousClass( LambdaForm.class, byte[] {…}, Object[] { …, unsafeObj, …})

#26

18 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

MHs vs LFs

§ Shared Lambda Form –  many method handles share a

single LF instance

§ Customized Lambda Form –  LF instance is customized for

some particular method handle

Sharing vs Customization

LF

LF

MH

MH

19 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

MHs vs LFs

putObjectFieldCast_000=Lambda(a0:L,a1:L,a2:L)=>{

t3:J=DMH.fieldOffset (a0:L);

t4:L=DMH.checkBase (a1:L);

t5:L=DMH.checkCast (a0:L,a2:L);

t6:V=Unsafe.putObject((Unsafe@...),t4:L,t3:J,t5:L);void}

Example: putfield / Lookup.findSetter

LF

MH

.form

LOOKUP.findSetter( MyClass1.class, “f1", Field1.class);

MT Field2.class

offset2

(MyClass2,Field2)void (MyClass1,Field1)void

Field1.class offset1

LOOKUP.findSetter( MyClass2.class, “f2", Field2.class);

… constructs …

(L,L,L)void .form LF

MH

20 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

MHs vs LFs

putIntField_000=Lambda(a0:L,a1:L,a2:I)=>{

t3:J=DMH.fieldOffset (a0:L);

t4:L=DMH.checkBase (a1:L);

t5:V=Unsafe.putInt((Unsafe@...),t4:L,t3:J,a2:I);void}

Example: putfield / Lookup.findSetter

LF

MH

.form

LOOKUP.findSetter( MyClass1.class, “i1", int.class);

MT long.class

offset2

(MyClass2,long)void (MyClass1,int)void

int.class offset1

LOOKUP.findSetter( MyClass2.class, “l2", long.class);

… constructs …

(L,L,I)void .form LF

MH

putLongField_000=Lambda(a0:L,a1:L,a2:J)=>{

t3:J=DMH.fieldOffset (a0:L);

t4:L=DMH.checkBase (a1:L);

t5:V=Unsafe.putLong((Unsafe@...),t4:L,t3:J,a2:J);void}

(L,L,J)void

21 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

7 GA 8 GA 7u40 8u20 8u40

Lambda Forms j.l.i enhancements Type speculation in C2 Math.exact*() intrinsics

Nashorn Project Lambda

JSR 292 Released Lambda Form Sharing

22 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

23 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Lambda Form Caching 8u40: JEP 210

LF

MH

LF

MH ~106

~106 ~103

~104 ~103

classes classes

24 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Sharing vs Customization Example: MHs.guardWithTest()

T guard(A... a, B... b) { if (test(a...)) return target(a..., b...); else return fallback(a..., b...); }

guard=Lambda(a0:L, a…, b…) => { t1:I =<<test>>(a…); t2:L=MHI.selectAlternative( t1:I, <<target>>, <<fallback>>); t3:?=MH.invokeBasic(t2:L, a…, b…);t3}

25 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Sharing vs Customization Example: Customized version

guard_000=Lambda(a0:L)=>{ t1:I =(MH()boolean@...); t2:L=MHI.selectAlternative( t1:I,(MH()void@...),(MH()void@...)); t3:V=MH.invokeBasic(t2:L);void}

static void guard_000(Object); ldc ... // <<MethodHandle()boolean>> checkcast ... // class MethodHandle invokevirtual ... // MethodHandle.invokeBasic:()I … if_icmpne … ldc ... // <<MethodHandle()void>> checkcast ... // class MethodHandle astore_2 aload_2 invokevirtual ... // MethodHandle.invokeBasic:()V goto … ldc ... // <<MethodHandle()void>> checkcast ... // class MethodHandle astore_2 aload_2 invokevirtual ... // MethodHandle.invokeBasic:()V return

t1:I

test: MethodHandle target: MethodHandle fallback: MethodHandle

t2:L +

t3:V

26 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Sharing vs Customization Example: Shareable version

guard_000=Lambda(a0:L)=>{ t3:L=BMH$Species_L3.argL0(a0:L); // test t4:L=BMH$Species_L3.argL1(a0:L); // target t5:L=BMH$Species_L3.argL2(a0:L); // fallback t6:I =MethodHandle.invokeBasic(t3:L); t7:L=MethodHandleImpl.selectAlternative(t6:I,t4:L,t5:L); t8:V=MethodHandle.invokeBasic(t7:L);void}

27 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Lambda Form Sharing

§ Smaller dynamic footprint –  # of loaded classes, Metaspace size

§ Faster startup/warmup –  less LFs to instantiate, less classes to load, less code to compile

§ Enables new optimizations –  Lambda Form precompilation –  Improves worst case stack consumption

Pros

28 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Lambda Form Sharing Dynamic Footprint

1

2

4

8

16

metaspace

classes

Measurements by Sergey Kuksenko 8u40: b05 vs b21, Nashorn

ratio

Octane

higher/better

29 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Lambda Form Sharing Startup / Warmup

-80

-30

20

70

120

8u40: b05 vs b21, Nashorn

354%

%

1st iteration duration higher/better

30 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Lambda Form Precompilation

§ Before: –  first 30 invocations go through LF interpreter –  then compiled to bytecode

§ After: –  Lambda Form is precompiled during creation –  completely bypasses LF interpreter

31 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Stack Consumption

jdk.nashorn.internal.scripts.Script$Recompilation$2$test.f1(test.js:1) j.l.i.LambdaForm$DMH/804581391.invokeStatic_LL_L

j.l.i.LambdaForm$DMH/1854778591.invokeSpecial_L3_L

j.l.i.LambdaForm$NamedFunction.invoke_LLL_L

j.l.i.LambdaForm$DMH/804581391.invokeStatic_LL_L

j.l.i.LambdaForm$NamedFunction.invokeWithArguments

j.l.i.LambdaForm.interpretName

j.l.i.LambdaForm.interpretWithArguments

j.l.i.LambdaForm.interpret_L

j.l.i.LambdaForm$DMH/1854778591.invokeSpecial_L3_L

j.l.i.LambdaForm$NamedFunction.invoke_LLL_L

j.l.i.LambdaForm$DMH/804581391.invokeStatic_LL_L

j.l.i.LambdaForm$NamedFunction.invokeWithArguments

j.l.i.LambdaForm.interpretName

j.l.i.LambdaForm.interpretWithArguments

j.l.i.LambdaForm.interpret_L

j.l.i.LambdaForm$MH/2142080121.linkToCallSite

jdk.nashorn.internal.scripts.Script$Recompilation$1$test.:program(test.js:2)

Lambda Form Interpreter

reinvoke

exactInvoker

test.js: 1: function f1() {} 2: f1()

32 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Stack Consumption

jdk.nashorn.internal.scripts.Script$Recompilation$2$test.f1(test.js:1) j.l.i.LambdaForm$DMH/804581391.invokeStatic_LL_L j.l.i.LambdaForm$BMH/921760190.reinvoke j.l.i.LambdaForm$MH/1690254271.exactInvoker j.l.i.LambdaForm$MH/206835546.linkToCallSite

jdk.nashorn.internal.scripts.Script$Recompilation$1$test.:program(test.js:9)

Compiled Form

33 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Lambda Form Sharing Peak Performance

-20

-10

0

10

20

30

40

Measurements by Sergey Kuksenko 8u40: b05 vs b21, Nashorn

125%

%

higher/better

34 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Lambda Form Sharing

§ Profile pollution –  peak performance suffers

§ Non-constant MH calls became slower –  JIT can’t inline through them –  less optimized machine code

Problems in 8u40

35 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Profile Pollution

Customization vs Sharing

36 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Profile Pollution Customized version

static void guard_000(Object); ldc ... // <<test>> checkcast ... // class MethodHandle invokevirtual ... // MethodHandle.invokeBasic:()I … if_icmpne … ldc ... // <<target>> checkcast ... // class MethodHandle astore_2 aload_2 invokevirtual ... // MH.invokeBasic:()V goto … ldc ... // <<fallback>> checkcast ... // class MethodHandle astore_2 aload_2 invokevirtual ... // MethodHandle.invokeBasic:()V return

t1:I

t2:L +

t3:V guard_000=Lambda(a0:L)=>{ t1:I =<<test>>(); t2:L=MethodHandleImpl.selectAlternative( t1:I,<<target>>,<<fallback>>); t3:V=MethodHandle.invokeBasic(t2:L);void}

37 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Profile Pollution Customized version

static void guard_000(Object); ldc ... // <<alwaysTrue>> checkcast ... // class MethodHandle invokevirtual ... // MH.invokeBasic:()I … if_icmpne … ldc ... // <<target>> checkcast ... // class MethodHandle astore_2 aload_2 invokevirtual ... // MH.invokeBasic:()V goto … ldc ... // <<fallback>> checkcast ... // class MethodHandle astore_2 aload_2 invokevirtual ... // MH.invokeBasic:()V return

t1:I

t2:L +

t3:V

0%

guard_000=Lambda(a0:L)=>{ t1:I =<<alwaysTrue>>(); t2:L=MethodHandleImpl.selectAlternative( t1:I,<<target>>,<<fallback>>); t3:V=MethodHandle.invokeBasic(t2:L);void}

38 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Profile Pollution Customized version

static void guard_001(Object); ldc ... // <<alwaysFalse>> checkcast ... // class MethodHandle invokevirtual ... // MH.invokeBasic:()I … if_icmpne … ldc ... // <<target>> checkcast ... // class MethodHandle astore_2 aload_2 invokevirtual ... // MH.invokeBasic:()V goto … ldc ... // <<fallback>> checkcast ... // class MethodHandle astore_2 aload_2 invokevirtual ... // MH.invokeBasic:()V return

t1:I

t2:L +

t3:V

100%

guard_001=Lambda(a0:L)=>{ t1:I =<<alwaysFalse>>; t2:L=MethodHandleImpl.selectAlternative( t1:I,<<target>>,<<fallback>>); t3:V=MethodHandle.invokeBasic(t2:L);void}

39 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Profile Pollution Shared version

static void guard_000(Object); aload_0 checkcast … // BMH$Species_L3 getfield ... // BMH$Species_L3.argL0:Object invokevirtual ... // MH.invokeBasic:()I … if_icmpne … aload_2 checkcast ... // class MethodHandle astore_5 aload_5 invokevirtual ... // MH.invokeBasic:()V goto … aload_3 checkcast ... // class MethodHandle astore_5 aload_5 invokevirtual ... // MH.invokeBasic:()V return

???%

40 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Profile Pollution How to fix

static void guard_000(Object); aload_0 checkcast … // BMH$Species_L3 getfield ... // BMH$Species_L3.argL0:Object invokevirtual ... // MH.invokeBasic:()I … if_icmpne … aload_2 checkcast ... // class MethodHandle astore_5 aload_5 invokevirtual ... // MH.invokeBasic:()V goto … aload_3 checkcast ... // class MethodHandle astore_5 aload_5 invokevirtual ... // MH.invokeBasic:()V return

?%

§  Idea: customized profiling –  collect per-MethodHandle profile

during warm-up –  inject profile into the JVM when

warm-up is over

41 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Profile Pollution Custom Branch Profiling

guard_000=Lambda(a0:L)=>{ t1:L=BMH$Species_L4.argL0(a0:L); // test t2:L=BMH$Species_L4.argL1(a0:L); // target t3:L=BMH$Species_L4.argL2(a0:L); // fallback t4:L=BMH$Species_L4.argL3(a0:L); // counts (int[2]) t5:I =MethodHandle.invokeBasic(t1:L); t6:I =MethodHandleImpl.profileBoolean(t5:I,t4:L); t7:L=MethodHandleImpl.selectAlternative(t6:I,t2:L,t3:L); t8:V=MethodHandle.invokeBasic(t7:L);void}

42 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Profile Pollution Custom Branch Profiling Logic

§ profiling / warm-up –  interpreter / C1 –  C2 when counts array is unknown

§  per-LambdaForm compiled method

§ optimized –  C2 intrinsic –  injects per-MH counts into IR

43 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Profile Pollution Custom Branch Profiling Logic

§ profiling / warm-up –  interpreter / C1 –  C2 when counts array is unknown

§  per-LambdaForm compiled method

§ optimized –  C2 intrinsic –  injects per-MH counts into IR

44 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Profile Pollution

§ Type profile –  not a problem –  Type speculation (by Roland Westrelin in 8u20)

§  -XX:+UseTypeProfile -XX:TypeProfileLevel=[012]{3}

§ Deoptimization counts –  no generic solution yet –  fixed some manifestations of the problem

§  JDK-8074551: GWT can be marked non-compilable due to deopt count pollution

Other cases

45 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Non-Constant Method Handle

Invocation

MH.invokeExact() et al

46 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Non-Constant Method Handle Invocation Non-constant method handle

@ 105 jsr292.GWT::run1 (7 bytes) inline (hot) @ 3 java.lang.invoke.LambdaForm$MH/789451787::invokeExact_MT (13 bytes) inline (hot) @ 2 java.lang.invoke.Invokers::checkExactType (30 bytes) inline (hot) @ 11 java.lang.invoke.MethodHandle::type (5 bytes) accessor @ 9 java.lang.invoke.MethodHandle::invokeBasic()V (0 bytes) receiver not constant

47 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Non-Constant Method Handle Invocation Customized version java.lang.invoke.LambdaForm$MH/1510467688::guard (56 bytes)

@ 5 java.lang.invoke.LambdaForm$DMH/1581781576::invokeStatic__I (13 bytes) inline (hot) @ 1 java.lang.invoke.DirectMethodHandle::internalMemberName (8 bytes) inline (hot) @ 9 jsr292.GWT::test1 (12 bytes) inline (hot) @ 31 java.lang.invoke.LambdaForm$DMH/1581781576::invokeStatic__V (13 bytes) inline (hot) @ 1 java.lang.invoke.DirectMethodHandle::internalMemberName (8 bytes) inline (hot) @ 9 jsr292.GWT::f1 (2 bytes) inline (hot) @ 52 java.lang.invoke.LambdaForm$DMH/1581781576::invokeStatic__V (13 bytes) inline (hot) @ 1 java.lang.invoke.DirectMethodHandle::internalMemberName (8 bytes) inline (hot) @ 9 jsr292.GWT::f2 (2 bytes) inline (hot)

48 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Non-Constant Method Handle Invocation Shared version java.lang.invoke.LambdaForm$MH/1252585652::guard (68 bytes)

@ 24 java.lang.invoke.MethodHandle::invokeBasic()I (0 bytes) receiver not constant @ 47 java.lang.invoke.MethodHandle::invokeBasic()V (0 bytes) receiver not constant @ 64 java.lang.invoke.MethodHandle::invokeBasic()V (0 bytes) receiver not constant

49 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

§ Customized Lambda Form –  single compiled method per

MH chain / root LF

§ Shared Lambda Form –  compiled method per MH/LF

Non-Constant Method Handle Invocation

nmethod

50 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Non-Constant Method Handle Invocation

nmethod Solution: Optional Customization §  Original (shared) guard_000=Lambda(a0:L)=>{ t1:L=BMH$Species_L4.argL0(a0:L); … §  Customized (a0 is overridden by t1:L) guard_000=Lambda(a0:L)=>{ t1:L=<<MethodHandle …>> t2:L=BMH$Species_L4.argL0(t1:L); …

51 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

7 GA 8 GA 9+

Timeline

7u40 8u20 8u40

λ-form sharing

Performance fixes

(e.g. per-MH profiling, LF customization)

λ-forms catchException λ-form sharing

type speculation Math.exact*() intrinsics

Now

8u60

Nashorn Project Lambda

Aug, 2015

52 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Future work

•  Ultimate Sharing •  MH.asType() Optimization •  Reduce Stack Consumption •  Lightweight Code Loading •  Profile Pollution

53 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Ultimate Sharing

[ I , J , L , … , F ]

[ I , J , L , … , F ]

[ I , J , L , … , F ]

[ I , J , L , … , F ]

...

Currently: Lambda Form instance per erased signature

Goal: Single Lambda Form instance per unit of behavior

call site

LF

LF

target

54 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Ultimate Sharing

[ I , J , L , … , F ]

[ I , J , L , … , F ]

[ L , L , L , … , L ]

[ L , L , L , … , L ]

...

[ I , J , L , … , F ]

[ I , J , L , … , F ]

[ I , J , L , … , F ]

[ I , J , L , … , F ]

...

call site

LF

LF

target

No conversions Boxing

55 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Ultimate Sharing

[ I , J , L , … , F ]

[ I , J , L , … , F ]

[ L , L , L , … , L ]

[ L , L , L , … , L ]

...

[ I , J , L , … , F ]

[ I , J , L , … , F ]

[ I , J , L , … , F ]

[ I , J , L , … , F ]

...

[ I , J , L , … , F ]

[ I , J , L , … , F ]

[ L ]

[ L ]

call site

LF

LF

target

No conversions Boxing Boxing + VarArgs

56 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Ultimate Sharing

[ I , J , L , … , F ]

[ I , J , L , … , F ]

[ ]

[ ]

§  JVM support is needed –  reliable box/unbox elimination –  array explosion

[ I , J , L , … , F ]

[ I , J , L , … , F ]

[ L ]

[ L ]

57 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

MethodHandle.asType()

§  Improve caching/sharing of MH.asType() transformations –  type adaptations are expensive to construct

§ Single-element per-MH cache –  subject to profile pollution

§ MH.invoke() on shared MH doesn’t work well –  (w.r.t. peak performance)

Better Caching / Sharing

58 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Reduce stack consumption

jdk.nashorn.internal.scripts.Script$Recompilation$2$test.f1(test.js:1) j.l.i.LambdaForm$DMH/804581391.invokeStatic_LL_L j.l.i.LambdaForm$BMH/921760190.reinvoke j.l.i.LambdaForm$MH/1690254271.exactInvoker j.l.i.LambdaForm$MH/206835546.linkToCallSite

jdk.nashorn.internal.scripts.Script$Recompilation$1$test.:program(test.js:9)

Precompiled Lambda Forms

59 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Reduce stack consumption

jdk.nashorn.internal.scripts.Script$Recompilation$2$test.f1(test.js:1) j.l.i.LambdaForm$DMH/804581391.invokeStatic_LL_L j.l.i.LambdaForm$BMH/921760190.reinvoke j.l.i.LF$MH/….customized j.l.i.LambdaForm$MH/1690254271.exactInvoker j.l.i.LambdaForm$MH/206835546.linkToCallSite

jdk.nashorn.internal.scripts.Script$Recompilation$1$test.:program(test.js:9)

(1) Lambda Form Inlining

60 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Reduce stack consumption

jdk.nashorn.internal.scripts.Script$Recompilation$2$test.f1(test.js:1) j.l.i.LambdaForm$MH/483294845.customized j.l.i.LambdaForm$MH/206835546.linkToCallSite

jdk.nashorn.internal.scripts.Script$Recompilation$1$test.:program(test.js:9)

(1) Lambda Form Inlining

61 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Reduce stack consumption

§ Pros –  easy to implement –  doesn’t require any JVM extensions

§ Cons –  defeats Lambda Form sharing

§  too many indy call sites to specialize for §  VM anonymous classes are too heavyweight

(1) Lambda Form Inlining

62 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Reduce stack consumption

jdk.nashorn.internal.scripts.Script$Recompilation$2$test.f1(test.js:1) (*)

jdk.nashorn.internal.scripts.Script$Recompilation$1$test.:program(test.js:9) (*) during invocation: linkToCallSite =tail-call=> reinvoke =tail-call=> exactInvoker =tail-call=> invokeStatic_LL_L =tail-call=> …$test.f1

(2) Tail Calls

63 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Lightweight Code Loading VM Anonymous Classes

Class<?>  Unsafe.defineAnonymousClass(                  Class<?>  hostClass,                    byte[]      code,                    Object[]  cpPatches)  

64 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Lightweight Code Loading VM Anonymous Classes

Class<?>  Unsafe.defineAnonymousClass(                  Class<?>  hostClass,                    byte[]      code,                    Object[]  cpPatches)  

65 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Lightweight Code Loading

MethodHandle  Lookup.loadCode(                /*Class<?>  hostClass,*/                    byte[]      code,                    Object[]  cpPatches)  

66 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Profile Pollution

LF

MH

class

67 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Future Extensions

•  Variable Handles •  Small API Enhancements •  Native Calls

68 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

JEP 193: Variable Handles

§ Safe, performant, enhanced atomics –  access to fields and array elements

§ VarHandles are like method handles for data –  Abstracts over location – static fields, instance fields, arrays, off heap –  Supports explicit fences and atomic operation

§ Safer than Unsafe, as fast as MethodHandles

JEP-193 “Variable Handles” by Doug Lea, Paul Sandoz http://openjdk.java.net/jeps/193

69 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

API Enhancements

§ Candidates –  MHs.tryFinally() –  MHs.*Loop() –  Lookup.lookupClass()/findSuperConstructor() –  Additional combinators for argument handling

§  e.g. MHs.spreadArguments(MH target, int pos, int count)

mlvm-dev@ojdk.net discussion http://mail.openjdk.java.net/pipermail/mlvm-dev/2015-February/006288.html

70 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Native Calls Project Panama: FFI

Java Native

Construction Lookup.findVirtual() et al Lookup.findNative()

Reference (typed) DirectMethodHandle NativeMethodHandle

Reference (direct) MemberName NativeEntryPoint

Linker MH.linkToVirtual() et al MH.linkToNative()

Invocation indy, MH.invoke(), MH.invokeExact()

“Making native calls from the JVM” by John Rose http://cr.openjdk.java.net/~jrose/panama/native-call-primitive.html

71 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Thank you!

@iwan0www

72 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Materials

§  Implementation Notes:–  http://cr.openjdk.java.net/~vlivanov/talks/2015-Indy_Deep_Dive.pdf

§  https://wiki.openjdk.java.net/display/HotSpot/Method+handles+and+invokedynamic §  https://wiki.openjdk.java.net/display/HotSpot/Bound+method+handles §  https://wiki.openjdk.java.net/display/HotSpot/Direct+method+handles §  https://wiki.openjdk.java.net/display/HotSpot/Method+handle+invocation §  "Deconstructing MethodHandles” by Paul Sandoz

–  https://wiki.openjdk.java.net/display/HotSpot/Deconstructing+MethodHandles §  "Lambda Forms” by John Rose, JVMLS'12

–  http://cr.openjdk.java.net/~jrose/pres/201207-LF-Tutorial.pdf

§  “J9's MethodHandle Compilation Pipeline” by Dan Heidinga, Jfocus VM Summit’15 –  http://www.jfokus.se/jfokus15/preso/J9%20MethodHandle%20Compilation%20Pipeline.pdf

73 Copyright © 2015, Oracle and/or its affiliates. All rights reserved

Graphic Section Divider

top related