This is an automated email from the ASF dual-hosted git repository. blackdrag pushed a commit to branch feature/indy_perf in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 3475381bf51a47345753d208dffbd223f1cab022 Author: Jochen Theodorou <[email protected]> AuthorDate: Wed Jan 17 13:53:38 2024 +0100 first mrta method test --- src/test/indy/perf/IndyMetaMethodTest.java | 159 +++++++++++++++++++++++++++++ src/test/indy/perf/IndyPerfUtil.java | 2 +- 2 files changed, 160 insertions(+), 1 deletion(-) diff --git a/src/test/indy/perf/IndyMetaMethodTest.java b/src/test/indy/perf/IndyMetaMethodTest.java new file mode 100644 index 0000000000..d5a882a4b8 --- /dev/null +++ b/src/test/indy/perf/IndyMetaMethodTest.java @@ -0,0 +1,159 @@ +package indy.perf; + +import groovy.lang.GroovyObject; +import groovy.lang.GroovySystem; +import groovy.lang.MetaClass; +import groovy.lang.MetaClassRegistry; +import groovy.lang.MetaMethod; +import org.codehaus.groovy.GroovyBugError; +import org.codehaus.groovy.classgen.asm.BytecodeHelper; +import org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl; +import org.junit.FixMethodOrder; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; +import org.junit.runners.MethodSorters; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; + +import java.io.IOException; +import java.lang.invoke.CallSite; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.invoke.MutableCallSite; + +import static indy.perf.IndyPerfUtil.*; +//125467 +//630155 - 740342 +@FixMethodOrder( MethodSorters.NAME_ASCENDING ) +public class IndyMetaMethodTest { + @Rule + public final TestRule watchman = new TestWatcher() { + @Override + protected void starting(Description description) { + System.out.println(description + "\n\n\tstarted."); + } + + @Override + protected void finished(Description description) { + System.out.println(description + "\tdone."); + } + }; + + public static int foo(int i) { + return i; + } + + private final static MethodHandle MC_INVOKE, GET_MC_CALL, BASE_HANLDE_CALL, BASE_HANLDE; + static { + //Object invokeMethod(Class sender, Object receiver, String methodName, Object[] arguments, boolean isCallToSuper, boolean fromInsideClass); + try { + MC_INVOKE = LOOKUP.findVirtual(MetaClass.class, "invokeStaticMethod", MethodType.methodType(Object.class, Object.class, String.class, Object[].class)); + GET_MC_CALL = LOOKUP.findStatic(IndyMetaMethodTest.class, "getMetaClass", MethodType.methodType(MetaClass.class, MyCallSite.class, Object.class)); + + MethodType type = MethodType.methodType(int.class, Class.class, int.class); + MethodHandle invoke = MC_INVOKE.asCollector(3, Object[].class, type.parameterCount()-1); + BASE_HANLDE = invoke; + + MethodHandle invokeWithGetMc = MethodHandles.dropArguments(invoke, 1, MyCallSite.class); + invokeWithGetMc = MethodHandles.foldArguments(invokeWithGetMc, GET_MC_CALL); + BASE_HANLDE_CALL = invokeWithGetMc; + } catch (Exception e) { + throw new GroovyBugError(e); + } + } + + final static MetaClass MC; + static { + var mc = GroovySystem.getMetaClassRegistry().getMetaClass(IndyMetaMethodTest.class); + mc.initialize(); + MC = mc; + } + + private static class MyCallSite extends MutableCallSite { + public final MethodHandle tail; + public final String name; + private MyCallSite(MethodType type, String name, MethodHandle tail) { + super(type); + this.tail = tail; + this.name = name; + } + + } + + public static MetaClass getMetaClass(MyCallSite callsite, Object receiver) { + //MetaClass mc = GroovySystem.getMetaClassRegistry().getMetaClass((Class) receiver); + /*MethodHandle handle = MethodHandles.insertArguments(callsite.tail, 0, mc); + handle = MethodHandles.insertArguments(handle, 1, callsite.name); + handle = handle.asType(callsite.getTarget().type()); + callsite.setTarget(handle);*/ + //return mc; + return MC; + } + + + @SuppressWarnings("unused") + public static CallSite bootstrap(MethodHandles.Lookup caller, String name, MethodType type) { + +/* + MethodHandle invoke = MethodHandles.insertArguments(MC_INVOKE, 2, name); + invoke = invoke.asCollector(2, Object[].class, type.parameterCount()-1); + + MethodHandle invokeWithGetMc = MethodHandles.dropArguments(invoke, 1, MyCallSite.class); + invokeWithGetMc = MethodHandles.foldArguments(invokeWithGetMc, GET_MC_CALL); + + + MyCallSite callsite = new MyCallSite(type, invoke); + invokeWithGetMc = MethodHandles.insertArguments(invokeWithGetMc, 0, callsite); + MethodHandle handle = invokeWithGetMc.asType(type); + */ + + MethodHandle handle; + + MyCallSite callsite = new MyCallSite(type, name, BASE_HANLDE);/* + MethodHandle handle = MethodHandles.insertArguments(BASE_HANLDE_CALL, 0, callsite); + handle = MethodHandles.insertArguments(handle, 1, name); + handle = handle.asType(type); +*/ + try { + handle = caller.findStatic(IndyMetaMethodTest.class, name, type.dropParameterTypes(0,1)); + handle = MethodHandles.dropArguments(handle, 0, Class.class); + } catch (NoSuchMethodException | IllegalAccessException e) { + throw new RuntimeException(e); + } + + callsite.setTarget(handle); + return callsite; + } + + @Test + public void t1_indyDirectMetaMethodCall() throws ReflectiveOperationException, IOException { + execute(null); + } + + @Test + public void t2_indyDirectMetaMethodCall() throws ReflectiveOperationException, IOException { + execute("t2_indyDirectMetaMethodCall2"); + } + + public void execute(String name) throws ReflectiveOperationException, IOException { + Type thisClass = Type.getType(this.getClass()); + Class<? extends Runnable> c = writeIndyCall(getBSM(IndyMetaMethodTest.class).handle, "foo", + "(Ljava/lang/Class;I)I", + (mv -> { + mv.visitLdcInsn(thisClass); + mv.visitInsn(Opcodes.ICONST_1); + })); + Runnable r = c.getDeclaredConstructor().newInstance(); + GroovySystem.getMetaClassRegistry().getMetaClass(c).initialize(); + perf(r, name); + } + + public static void main(String[] args) { + executeTests(IndyMetaMethodTest.class); + } + +} diff --git a/src/test/indy/perf/IndyPerfUtil.java b/src/test/indy/perf/IndyPerfUtil.java index ba202d93a8..783ad876ba 100644 --- a/src/test/indy/perf/IndyPerfUtil.java +++ b/src/test/indy/perf/IndyPerfUtil.java @@ -19,7 +19,7 @@ import java.util.Comparator; import java.util.Optional; import java.util.function.Consumer; -import static org.objectweb.asm.Opcodes.ACC_PUBLIC; +import static org.objectweb.asm.Opcodes.*; public class IndyPerfUtil { private static final int WARM_UP_ITERATIONS = 100;
