Skip to content

Instantly share code, notes, and snippets.

@melix
Created May 21, 2014 14:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save melix/49c0dd8e601aad423e1e to your computer and use it in GitHub Desktop.
Save melix/49c0dd8e601aad423e1e to your computer and use it in GitHub Desktop.
Caching with invokedynamic
import groovy.transform.CompileStatic
import java.lang.invoke.CallSite
import java.lang.invoke.ConstantCallSite
import java.lang.invoke.MethodHandle
import java.lang.invoke.MethodHandles
import java.lang.invoke.MethodType
import java.lang.invoke.SwitchPoint
import static groovyjarjarasm.asm.Opcodes.*
@CompileStatic
class Helper {
public static CallSite bootstrap(MethodHandles.Lookup lookup, String callType, MethodType type, String methodName) {
println 'in bootstrap'
def mh = cacheValue(lookup, type, methodName)
new ConstantCallSite(mh)
}
static MethodHandle cacheValue(MethodHandles.Lookup lookup, MethodType type, String methodName) {
def sp = new SwitchPoint()
def uncached = lookup.findStatic(Helper, methodName, type)
def cached = lookup.findStatic(Helper, "getCached${methodName.capitalize()}", type)
def invalidator = lookup.findStatic(Helper, 'invalidator', MethodType.methodType(Object, MethodHandle, SwitchPoint))
invalidator = MethodHandles.insertArguments(invalidator, 0, uncached, sp).asType(type)
sp.guardWithTest(invalidator, cached)
}
static Object invalidator(MethodHandle uncached, SwitchPoint sp) {
SwitchPoint.invalidateAll([sp] as SwitchPoint[])
uncached.invokeWithArguments()
}
static int cachedFoo
static int foo() {
println 'in foo'
cachedFoo = 666
cachedFoo
}
}
@groovyx.ast.bytecode.Bytecode
int testConstant() {
invokedynamic 'experiment', '()I', [H_INVOKESTATIC, 'Helper', 'bootstrap', [CallSite, MethodHandles.Lookup, String, MethodType, String]], 'foo'
ireturn
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment