After we identified an invariant dynamic call, the call replacement technique could be applied to the caller method. The following describes an early version of the algorithm to do so:
1. find an invocation statement to ScriptBytecodeAdapter
2. determine a number of parameters that the statement needs.
2.1 if the number of parameters = 3, this invocation has no argument.
2.2 if the number of parameters = 4, this invocation has a set of arguments.
3. statically unwrap the last parameter passed to this statement
(note that Groovy's using Object
to wrap a set of method arguments,
and we need to unwrap and pass them
to the new invocation statement)
3.1 in this step, we can also clean up unneeded the Object variable
and its assignment statements.
4. construct the new invocation statement,
using information gathered from the profiler.
(we can not infer the target class using
any information provided by the statement,
because the real call will be chosen by Groovy meta-class).
5. fix object casting, this can be done by traversing backwardly
to the statement prior to the invocation.
Then change casting type from GroovyObject
to the correct type (also get this value from the profiler)
The result so far:
$r19_2 = $r19;
$r19_2 = org.codehaus.groovy.aop.tests.Target.class$groovy$lang$GroovyObject;
$r20 = ScriptBytecodeAdapter.castToType(r0, $r19_2);
$r21 = (org.codehaus.groovy.aop.tests.Target) $r20;
$r23 = $r21.method2("test");
$r18[$i0] = $r23;
$r24 = ScriptBytecodeAdapter.invokeMethodOnCurrentN(r2, $r16, $r17, $r18);