Created
July 23, 2016 10:34
-
-
Save forax/7d1c06df9546baf9d98e8c0c1f255e05 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package java.lang.invoke; | |
import java.lang.invoke.MethodHandles.Lookup; | |
import java.net.URI; | |
import java.net.URISyntaxException; | |
// compile with: | |
// /usr/jdk/jdk-9/bin/javac -Xmodule:java.base -d ../classes java/lang/invoke/FunPIC.java | |
// execute with: | |
// /usr/jdk/jdk-9/bin/java -Xpatch:java.base=../classes -m java.base/java.lang.invoke.FunPIC | |
public class FunPIC { | |
@jdk.internal.vm.annotation.Stable static MethodHandle[] GUARDS = new MethodHandle[2]; | |
@jdk.internal.vm.annotation.Stable static MethodHandle[] TARGETS = new MethodHandle[2]; | |
@jdk.internal.vm.annotation.ForceInline | |
private static int m(Object o) throws Throwable { | |
if (GUARDS[0] == null) { | |
return deopt(o, 0); | |
} | |
if ((boolean)GUARDS[0].invokeExact(o)) { | |
return (int)TARGETS[0].invokeExact(o); | |
} | |
if (GUARDS[1] == null) { | |
return deopt(o, 1); | |
} | |
if ((boolean)GUARDS[1].invokeExact(o)) { | |
return (int)TARGETS[1].invokeExact(o); | |
} | |
return deopt(o, -1); | |
} | |
public static int test(Object o) { | |
try { | |
return m(o); | |
} catch (Throwable e) { | |
throw new AssertionError(e); | |
} | |
} | |
public static int loop(Object o) { | |
int sum = 0; | |
for(int i = 0; i < 100_000_000; i++) { | |
sum += test(o); | |
} | |
return sum; | |
} | |
public static void main(String[] args) throws URISyntaxException { | |
Object[] array = { "hello", new URI("http://hello/") /*, 4.5*/ }; | |
int sum = 0; | |
for(Object o: array) { | |
sum += loop(o); | |
} | |
System.out.println(sum); | |
} | |
@jdk.internal.vm.annotation.DontInline | |
private static int deopt(Object receiver, int i) throws Throwable { | |
System.out.println("deopt " + i); | |
if (i == -1) { | |
throw new UnsupportedOperationException("we are morons"); | |
} | |
Class<?> receiverClass = receiver.getClass(); | |
MethodHandle guard = MethodHandles.insertArguments(TYPE_CHECK, 1, receiverClass); | |
MethodHandle target; | |
try { | |
target = LOOKUP.findStatic(FunPIC.class, "impl", MethodType.methodType(int.class, receiverClass)); | |
} catch (NoSuchMethodException | IllegalAccessException e) { | |
throw new AssertionError(e); | |
} | |
target = target.asType(MethodType.methodType(int.class, Object.class)); | |
GUARDS[i] = guard; | |
TARGETS[i] = target; | |
return (int) target.invokeExact(receiver); | |
} | |
private static final Lookup LOOKUP = MethodHandles.Lookup.IMPL_LOOKUP; | |
private static final MethodHandle TYPE_CHECK; | |
static { | |
try { | |
TYPE_CHECK = LOOKUP.findStatic(FunPIC.class, "typeCheck", MethodType.methodType(boolean.class, Object.class, Class.class)); | |
} catch (NoSuchMethodException | IllegalAccessException e) { | |
throw new AssertionError(e); | |
} | |
} | |
private static boolean typeCheck(Object o, Class<?> type) { | |
return o.getClass() == type; | |
} | |
private static int impl(String s) { | |
int sum = 0; | |
for(int c: s.toCharArray()) { | |
sum += c; | |
} | |
return sum; | |
} | |
private static int impl(URI u) { | |
int sum = 0; | |
for(int c: u.toASCIIString().toCharArray()) { | |
sum += c; | |
} | |
return sum; | |
} | |
private static int impl(Integer i) { | |
return ((Integer)i.intValue()).intValue(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment