Skip to content

Instantly share code, notes, and snippets.

Created July 26, 2011 22:47
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save anonymous/1108283 to your computer and use it in GitHub Desktop.
Save anonymous/1108283 to your computer and use it in GitHub Desktop.
package com.headius.indy.examples;
import java.lang.invoke.MethodHandle;
import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
import java.lang.invoke.MutableCallSite;
public class IndyLoop {
public static void main(String[] args) throws Throwable {
// method handle loop adds up numbers from 1 to args[0].to_i
int max = args.length == 0 ? 10000 : Integer.parseInt(args[0]);
MethodHandle loop = makeLoop();
System.out.println((int)loop.invokeExact(max));
System.out.println(addAll(max, 0));
}
private static int addAll(int max, int accum) {
if (max > 0) {
return addAll(dec(max), add(accum, max));
} else {
return accum;
}
}
private static MethodHandle makeLoop() throws Exception {
Lookup lookup = lookup();
// backward branch
MutableCallSite bottom = new MutableCallSite(methodType(int.class, int.class, int.class));
MethodHandle mh = bottom.dynamicInvoker();
// drop previous iteration's values
mh = dropArguments(mh, 2, int.class, int.class);
// decrement max
MethodHandle dec = lookup.findStatic(IndyLoop.class, "dec", methodType(int.class, int.class));
dec = permuteArguments(dec, methodType(int.class, int.class, int.class, int.class), new int[]{1});
mh = foldArguments(mh, dec);
// add both arguments
MethodHandle add = lookup.findStatic(IndyLoop.class, "add", methodType(int.class, int.class, int.class));
mh = foldArguments(mh, add);
// compare to zero
MethodHandle test = lookup.findStatic(IndyLoop.class, "gtZero", methodType(boolean.class, int.class));
test = dropArguments(test, 1, int.class);
// return accumulator
MethodHandle fallback = dropArguments(identity(int.class), 0, int.class);
mh = guardWithTest(test, mh, fallback);
// rebind callsite
bottom.setTarget(mh);
// insert initial accum value
return insertArguments(mh, 1, 0);
}
private static boolean gtZero(int a) {
return a > 0;
}
private static int add(int a, int b) {
return a + b;
}
private static int dec(int a) {
return a - 1;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment